Skip to content
This repository was archived by the owner on Oct 9, 2025. It is now read-only.

Commit 3cbdf56

Browse files
authored
fix: fix replied message showing no content across different connection modes (#194)
Simplify the `storeMessageData` function by removing the unused `mode` parameter and refactoring the `await storeMessageData` call in `MessageCreate` to use fewer arguments. Address error handling in the `storeMsgTimestamps` task by adding a FIXME comment for a specific error case. Additionally, enhance the error response logic in the `EditMessage` command to improve user feedback during modal interactions.
1 parent 59bfa62 commit 3cbdf56

File tree

6 files changed

+77
-59
lines changed

6 files changed

+77
-59
lines changed

src/commands/context-menu/editMsg.ts

Lines changed: 68 additions & 39 deletions
Original file line numberDiff line numberDiff line change
@@ -1,3 +1,4 @@
1+
/* eslint-disable complexity */
12
import Constants, { ConnectionMode, emojis } from '#main/config/Constants.js';
23
import BaseCommand from '#main/core/BaseCommand.js';
34
import { RegisterInteractionHandler } from '#main/decorators/Interaction.js';
@@ -7,9 +8,9 @@ import VoteBasedLimiter from '#main/modules/VoteBasedLimiter.js';
78
import { fetchHub } from '#main/utils/hub/utils.js';
89
import {
910
findOriginalMessage,
11+
getBroadcast,
1012
getBroadcasts,
1113
getOriginalMessage,
12-
OriginalMessage,
1314
} from '#main/utils/network/messageUtils.js';
1415
import { CustomID } from '#utils/CustomID.js';
1516
import db from '#utils/Db.js';
@@ -103,104 +104,132 @@ export default class EditMessage extends BaseCommand {
103104

104105
@RegisterInteractionHandler('editMsg')
105106
override async handleModals(interaction: ModalSubmitInteraction): Promise<void> {
107+
// Defer the reply to give the user feedback
106108
await interaction.deferReply({ ephemeral: true });
107109

110+
// Parse the custom ID to get the message ID
108111
const customId = CustomID.parseCustomId(interaction.customId);
109112
const [messageId] = customId.args;
110-
const { userManager } = interaction.client;
111-
const locale = await userManager.getUserLocale(interaction.user.id);
112113

114+
// Fetch the original message
113115
const target = await interaction.channel?.messages.fetch(messageId).catch(() => null);
114116
if (!target) {
115-
await interaction.editReply(t('errors.unknownNetworkMessage', locale, { emoji: emojis.no }));
117+
await this.replyEmbed(interaction, 'errors.unknownNetworkMessage', {
118+
t: { emoji: emojis.no },
119+
});
116120
return;
117121
}
118122

119-
const targetMsgData =
123+
// Get the original message data
124+
const originalMsgData =
120125
(await getOriginalMessage(target.id)) ?? (await findOriginalMessage(target.id));
121126

122-
const unknownMsgErr = t('errors.unknownNetworkMessage', locale, { emoji: emojis.no });
123-
if (!targetMsgData?.hubId) {
124-
await interaction.editReply(unknownMsgErr);
127+
if (!originalMsgData?.hubId) {
128+
await this.replyEmbed(interaction, 'errors.unknownNetworkMessage', {
129+
t: { emoji: emojis.no },
130+
});
125131
return;
126132
}
127-
const hub = await fetchHub(targetMsgData.hubId);
133+
134+
// Fetch the hub information
135+
const hub = await fetchHub(originalMsgData.hubId);
128136
if (!hub) {
129-
await interaction.editReply(unknownMsgErr);
137+
await interaction.editReply(
138+
t('errors.unknownNetworkMessage', await this.getLocale(interaction), {
139+
emoji: emojis.no,
140+
}),
141+
);
130142
return;
131143
}
132144

133-
// get the new message input by user
145+
// Get the new message input from the user
134146
const userInput = interaction.fields.getTextInputValue('newMessage');
135-
const settingsManager = new HubSettingsManager(targetMsgData.hubId, hub.settings);
147+
const settingsManager = new HubSettingsManager(originalMsgData.hubId, hub.settings);
136148
const messageToEdit = this.sanitizeMessage(userInput, settingsManager.getAllSettings());
137149

150+
// Check if the message contains invite links
138151
if (settingsManager.getSetting('BlockInvites') && containsInviteLinks(messageToEdit)) {
139-
await interaction.editReply(t('errors.inviteLinks', locale, { emoji: emojis.no }));
152+
await interaction.editReply(
153+
t('errors.inviteLinks', await this.getLocale(interaction), { emoji: emojis.no }),
154+
);
140155
return;
141156
}
142157

143-
const imageURLs = await this.getImageURLs(target, targetMsgData.mode, messageToEdit);
158+
const mode =
159+
target.id === originalMsgData.messageId
160+
? ConnectionMode.Compact
161+
: ((
162+
await getBroadcast(originalMsgData?.messageId, originalMsgData?.hubId, {
163+
channelId: target.channelId,
164+
})
165+
)?.mode ?? ConnectionMode.Compact);
166+
167+
// Prepare the new message contents and embeds
168+
const imageURLs = await this.getImageURLs(target, mode, messageToEdit);
144169
const newContents = this.getCompactContents(messageToEdit, imageURLs);
145-
const newEmbeds = await this.buildEmbeds(target, targetMsgData, messageToEdit, {
146-
guildId: targetMsgData.guildId,
170+
const newEmbeds = await this.buildEmbeds(target, mode, messageToEdit, {
171+
guildId: originalMsgData.guildId,
147172
user: interaction.user,
148173
imageURLs,
149174
});
150175

151-
// find all the messages through the network
152-
const broadcastedMsgs = Object.values(await getBroadcasts(target.id, targetMsgData.hubId));
176+
// Find all the messages that need to be edited
177+
const broadcastedMsgs = Object.values(await getBroadcasts(target.id, originalMsgData.hubId));
153178
const channelSettingsArr = await db.connectedList.findMany({
154179
where: { channelId: { in: broadcastedMsgs.map((c) => c.channelId) } },
155180
});
156181

157-
const results = broadcastedMsgs.map(async (msg) => {
182+
let counter = 0;
183+
for (const msg of broadcastedMsgs) {
158184
const connection = channelSettingsArr.find((c) => c.channelId === msg.channelId);
159-
if (!connection) return false;
185+
if (!connection) continue;
160186

161-
const webhookURL = connection.webhookURL.split('/');
162187
const webhook = await interaction.client
163-
.fetchWebhook(webhookURL[webhookURL.length - 2])
164-
?.catch(() => null);
188+
.fetchWebhook(connection.webhookURL.split('/')[connection.webhookURL.split('/').length - 2])
189+
.catch(() => null);
165190

166-
if (webhook?.owner?.id !== interaction.client.user.id) return false;
191+
if (webhook?.owner?.id !== interaction.client.user.id) continue;
192+
console.log(msg.mode, msg.mode === ConnectionMode.Embed);
167193

168194
let content;
169195
let embeds;
170-
171196
if (msg.mode === ConnectionMode.Embed) {
172197
embeds = connection.profFilter ? [newEmbeds.censored] : [newEmbeds.normal];
173198
}
174199
else {
175200
content = connection.profFilter ? newContents.censored : newContents.normal;
176201
}
177202

178-
// finally, edit the message
179-
return await webhook
203+
// Edit the message
204+
const edited = await webhook
180205
.editMessage(msg.messageId, {
181206
content,
182207
embeds,
183208
threadId: connection.parentId ? connection.channelId : undefined,
184209
})
185-
.then(() => true)
186-
.catch(() => false);
187-
});
210+
.catch(() => null);
188211

189-
const resultsArray = await Promise.all(results);
190-
const edited = resultsArray.reduce((acc, cur) => acc + (cur ? 1 : 0), 0).toString();
212+
if (edited) counter++;
213+
}
191214

215+
// Update the reply with the edit results
192216
await interaction
193217
.editReply(
194-
t('network.editSuccess', locale, {
195-
edited,
196-
total: resultsArray.length.toString(),
218+
t('network.editSuccess', await this.getLocale(interaction), {
219+
edited: counter.toString(),
220+
total: broadcastedMsgs.length.toString(),
197221
emoji: emojis.yes,
198-
user: userMention(targetMsgData.authorId),
222+
user: userMention(originalMsgData.authorId),
199223
}),
200224
)
201225
.catch(handleError);
202226

203-
const voteLimiter = new VoteBasedLimiter('editMsg', interaction.user.id, userManager);
227+
// Decrement the vote limiter
228+
const voteLimiter = new VoteBasedLimiter(
229+
'editMsg',
230+
interaction.user.id,
231+
interaction.client.userManager,
232+
);
204233
await voteLimiter.decrementUses();
205234
}
206235

@@ -221,7 +250,7 @@ export default class EditMessage extends BaseCommand {
221250

222251
private async buildEmbeds(
223252
target: Message,
224-
targetMsgData: OriginalMessage,
253+
mode: ConnectionMode,
225254
messageToEdit: string,
226255
opts: { user: User; guildId: string; imageURLs?: ImageUrls },
227256
) {
@@ -241,7 +270,7 @@ export default class EditMessage extends BaseCommand {
241270

242271
let embed: EmbedBuilder;
243272

244-
if (targetMsgData.mode === ConnectionMode.Embed) {
273+
if (mode === ConnectionMode.Embed) {
245274
// utilize the embed directly from the message
246275
embed = EmbedBuilder.from(target.embeds[0]).setDescription(embedContent).setImage(embedImage);
247276
}

src/events/messageCreate.ts

Lines changed: 5 additions & 10 deletions
Original file line numberDiff line numberDiff line change
@@ -111,13 +111,7 @@ export default class MessageCreate extends BaseEventListener<'messageCreate'> {
111111
embedColor: connection.embedColor as HexColorString,
112112
});
113113

114-
await storeMessageData(
115-
message,
116-
sendResult,
117-
connection.hubId,
118-
connection.compact ? ConnectionMode.Compact : ConnectionMode.Embed,
119-
referredMsgData.dbReferrence,
120-
);
114+
await storeMessageData(message, sendResult, connection.hubId, referredMsgData.dbReferrence);
121115
}
122116

123117
private async fetchReferredMessage(message: Message<true>): Promise<Message | null> {
@@ -277,10 +271,11 @@ export default class MessageCreate extends BaseEventListener<'messageCreate'> {
277271

278272
private getReferredContent(data: ReferredMsgData) {
279273
if (data.referredMessage && data.dbReferrence) {
280-
const messagesRepliedTo =
281-
data.dbReferrence.broadcastMsgs.get(data.referredMessage.channelId) ?? data.dbReferrence;
274+
const mode =
275+
data.dbReferrence.broadcastMsgs.get(data.referredMessage.channelId)?.mode ??
276+
ConnectionMode.Compact; // message is an OriginalMessage (user message)
282277

283-
return getReferredContent(data.referredMessage, messagesRepliedTo.mode);
278+
return getReferredContent(data.referredMessage, mode);
284279
}
285280
}
286281

src/tasks/storeMsgTimestamps.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -9,6 +9,7 @@ export default async () => {
99
const timestampsObj = await getRedis().hgetall(`${RedisKeys.msgTimestamp}`);
1010

1111
Object.entries(timestampsObj).forEach(async ([channelId, timestamp]) => {
12+
// FIXME: Errors happens that says "record to update not found"
1213
await updateConnection({ channelId }, { lastActive: new Date(parseInt(timestamp)) });
1314
Logger.debug(`Stored message timestamps for channel ${channelId} from cache to db.`);
1415
await getRedis().hdel(`${RedisKeys.msgTimestamp}`, channelId);

src/utils/network/helpers.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -71,7 +71,7 @@ export const getReferredMsgData = async (
7171
// fetch the acttual user ("referredMessage" is a webhook message)
7272
const referredAuthor = await client.users.fetch(dbReferrenceRaw.authorId).catch(() => null);
7373
const dbReferredAuthor = await client.userManager.getUser(dbReferrenceRaw.authorId);
74-
const broadcastedMessages = await getBroadcasts(referredMessage.id, dbReferrenceRaw.hubId);
74+
const broadcastedMessages = await getBroadcasts(dbReferrenceRaw.messageId, dbReferrenceRaw.hubId);
7575

7676
const dbReferrence = {
7777
...dbReferrenceRaw,

src/utils/network/messageUtils.ts

Lines changed: 1 addition & 6 deletions
Original file line numberDiff line numberDiff line change
@@ -5,7 +5,6 @@ import type { Message, Snowflake } from 'discord.js';
55
import isEmpty from 'lodash/isEmpty.js';
66

77
export interface OriginalMessage {
8-
mode: number;
98
hubId: string;
109
messageId: string;
1110
guildId: string;
@@ -38,11 +37,7 @@ export const getOriginalMessage = async (originalMsgId: string) => {
3837

3938
if (isEmpty(res)) return null;
4039

41-
return {
42-
...res,
43-
mode: parseInt(res.mode),
44-
timestamp: parseInt(res.timestamp),
45-
} as OriginalMessage;
40+
return { ...res, timestamp: parseInt(res.timestamp) } as OriginalMessage;
4641
};
4742

4843
export const addBroadcasts = async (

src/utils/network/storeMessageData.ts

Lines changed: 1 addition & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -31,13 +31,11 @@ export default async (
3131
message: Message,
3232
broadcastResults: NetworkWebhookSendResult[],
3333
hubId: string,
34-
mode: ConnectionMode,
3534
dbReference?: OriginalMessage | null,
3635
) => {
3736
if (!message.inGuild()) return;
3837

3938
await storeMessage(message.id, {
40-
mode,
4139
hubId,
4240
messageId: message.id,
4341
authorId: message.author.id,
@@ -63,7 +61,7 @@ export default async (
6361
return;
6462
}
6563
validBroadcasts.push({
66-
mode,
64+
mode: res.mode,
6765
messageId: res.messageRes.id,
6866
channelId: res.messageRes.channel_id,
6967
originalMsgId: message.id,

0 commit comments

Comments
 (0)