Skip to content

Commit 8f6b5e7

Browse files
dsshimelclaude
andcommitted
fix edited Discord messages not updating in database
logMessage now upserts content on conflict instead of INSERT OR IGNORE, so backfill picks up edited messages. Added messageUpdate event handler to capture edits in real-time. This fixes student stats showing 0 PRs when students edit their EOD messages to add PR links. Co-Authored-By: Claude Opus 4.6 <noreply@anthropic.com>
1 parent 7cbf40d commit 8f6b5e7

File tree

3 files changed

+58
-1
lines changed

3 files changed

+58
-1
lines changed

attendabot/backend/src/services/db.ts

Lines changed: 3 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -290,8 +290,10 @@ export function logMessage(message: MessageRecord): void {
290290
upsertUser(message.author_id, message.display_name, message.username);
291291

292292
const stmt = db.prepare(`
293-
INSERT OR IGNORE INTO messages (discord_message_id, channel_id, author_id, content, created_at)
293+
INSERT INTO messages (discord_message_id, channel_id, author_id, content, created_at)
294294
VALUES (?, ?, ?, ?, ?)
295+
ON CONFLICT(discord_message_id) DO UPDATE SET
296+
content = excluded.content
295297
`);
296298
stmt.run(
297299
message.discord_message_id,

attendabot/backend/src/services/discord.ts

Lines changed: 25 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -186,6 +186,31 @@ export async function initializeDiscord(): Promise<Client> {
186186
}
187187
});
188188

189+
// Register messageUpdate listener to capture edited messages
190+
discordClient.on("messageUpdate", async (_oldMessage, newMessage) => {
191+
if (!MONITORED_CHANNEL_IDS.includes(newMessage.channelId)) return;
192+
if (newMessage.author?.bot) return;
193+
194+
try {
195+
// Fetch full message if partial (not in cache)
196+
const message = newMessage.partial ? await newMessage.fetch() : newMessage;
197+
const channel = message.channel as TextChannel;
198+
logMessage({
199+
discord_message_id: message.id,
200+
channel_id: message.channelId,
201+
channel_name: channel.name,
202+
author_id: message.author.id,
203+
display_name: message.member?.displayName || null,
204+
username: message.author.username,
205+
content: message.content,
206+
created_at: message.createdAt.toISOString(),
207+
});
208+
console.log(`Updated edited message from ${message.author.username} in #${channel.name}`);
209+
} catch (error) {
210+
console.error("Failed to update edited message:", error);
211+
}
212+
});
213+
189214
// Run backfill after ready
190215
backfillMonitoredChannels(discordClient).catch((error) => {
191216
console.error("Failed to backfill monitored channels", error);

attendabot/backend/src/test/services/db.test.ts

Lines changed: 30 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -134,6 +134,36 @@ describe("Database Service - Direct Tests", () => {
134134
expect(result.count).toBe(1);
135135
});
136136

137+
it("updates content on duplicate discord_message_id via upsert", () => {
138+
const channel = createTestChannel(db);
139+
const user = createTestUser(db);
140+
141+
createTestMessage(db, {
142+
discordMessageId: "msg-1",
143+
channelId: channel.channel_id,
144+
authorId: user.author_id,
145+
content: "Original content",
146+
});
147+
148+
// Re-insert with updated content (simulates logMessage upsert after edit)
149+
const stmt = db.prepare(`
150+
INSERT INTO messages (discord_message_id, channel_id, author_id, content, created_at)
151+
VALUES (?, ?, ?, ?, ?)
152+
ON CONFLICT(discord_message_id) DO UPDATE SET
153+
content = excluded.content
154+
`);
155+
stmt.run("msg-1", channel.channel_id, user.author_id, "Edited with PRs", new Date().toISOString());
156+
157+
const row = db.prepare("SELECT content FROM messages WHERE discord_message_id = ?")
158+
.get("msg-1") as { content: string };
159+
160+
expect(row.content).toBe("Edited with PRs");
161+
162+
const countResult = db.prepare("SELECT COUNT(*) as count FROM messages")
163+
.get() as { count: number };
164+
expect(countResult.count).toBe(1);
165+
});
166+
137167
it("retrieves messages ordered by newest first", () => {
138168
const channel = createTestChannel(db);
139169
const user = createTestUser(db);

0 commit comments

Comments
 (0)