From a52c50198e591c1d53f8255b7fd3774bfddfac25 Mon Sep 17 00:00:00 2001 From: Kibi Kelburton Date: Tue, 27 Jan 2026 14:48:02 +0100 Subject: [PATCH] adding @mention functionality --- public/s/js/f0ck.js | 1 + src/inc/routes/comments.mjs | 71 ++++++++++++++++++++++++------------- 2 files changed, 47 insertions(+), 25 deletions(-) diff --git a/public/s/js/f0ck.js b/public/s/js/f0ck.js index e7e7811..5821c4b 100644 --- a/public/s/js/f0ck.js +++ b/public/s/js/f0ck.js @@ -1208,6 +1208,7 @@ class NotificationSystem { let typeText = 'Start'; if (n.type === 'comment_reply') typeText = 'replied to you'; else if (n.type === 'subscription') typeText = 'commented in a thread you follow'; + else if (n.type === 'mention') typeText = 'highlighted you'; const cid = n.comment_id || n.reference_id; const link = `/${n.item_id}#c${cid}`; diff --git a/src/inc/routes/comments.mjs b/src/inc/routes/comments.mjs index 6a1d837..9012414 100644 --- a/src/inc/routes/comments.mjs +++ b/src/inc/routes/comments.mjs @@ -191,51 +191,72 @@ export default (router, tpl) => { const commentId = parseInt(newComment[0].id, 10); // Notify Subscribers (excluding the author) - // 1. Get subscribers of the item - // 2. If it's a reply, notify parent author? (Optional, complex logic. Let's stick to item subscription for now + Parent author) - - // Logic: Notify users who subscribed to this item OR are the parent author. - // Exclude current user. - - // 1. Get subscribers + // 1. Get subscribers (existing code) const subscribers = await db`SELECT user_id FROM comment_subscriptions WHERE item_id = ${item_id}`; + // Mentions Logic: Parse content for @username + // Allow alphanumeric, underscore, dash. + const mentionRegex = /@([a-zA-Z0-9_\-]+)/g; + const matches = [...content.matchAll(mentionRegex)]; + const mentionedNames = [...new Set(matches.map(m => m[1]))]; + const lowerNames = mentionedNames.map(n => n.toLowerCase()); + + console.log("DEBUG: Mentions found:", mentionedNames); + + let mentionedUsers = []; + if (lowerNames.length > 0) { + // Fetch IDs via login column (lowercase) + mentionedUsers = await db`SELECT id, user FROM "user" WHERE login IN ${db(lowerNames)}`; + console.log("DEBUG: Users resolved:", mentionedUsers); + } + // 2. Get parent author let parentAuthor = []; if (parent_id) { parentAuthor = await db`SELECT user_id FROM comments WHERE id = ${parent_id}`; } - // 3. Prepare notifications - const notificationsToAdd = []; + // 3. Prepare notifications with priority: Mention > Reply > Subscription + // Use a Map to ensure one notification per user + const notificationsMap = new Map(); // UserId -> { type, ... } - // Parent author gets 'comment_reply' + // A. Mentions + mentionedUsers.forEach(u => { + if (u.id !== req.session.id) { + notificationsMap.set(u.id, 'mention'); + } + }); + + // B. Reply (Parent Author) if (parentAuthor.length > 0) { const pid = parentAuthor[0].user_id; - if (pid !== req.session.id) { - notificationsToAdd.push({ - user_id: pid, - type: 'comment_reply', - item_id: item_id, - reference_id: commentId - }); + // Only if not already mentioned + if (pid !== req.session.id && !notificationsMap.has(pid)) { + notificationsMap.set(pid, 'comment_reply'); } } - // Subscribers get 'subscription' (unless they already got comment_reply) + // C. Subscribers const parentUserId = parentAuthor.length > 0 ? parentAuthor[0].user_id : -1; subscribers.forEach(s => { - if (s.user_id !== req.session.id && s.user_id !== parentUserId) { - notificationsToAdd.push({ - user_id: s.user_id, - type: 'subscription', - item_id: item_id, - reference_id: commentId - }); + // If not self, and not already notified (as mention or reply) + if (s.user_id !== req.session.id && !notificationsMap.has(s.user_id)) { + notificationsMap.set(s.user_id, 'subscription'); } }); + // Build insert array + const notificationsToAdd = []; + for (const [uid, type] of notificationsMap.entries()) { + notificationsToAdd.push({ + user_id: uid, + type: type, + item_id: item_id, + reference_id: commentId + }); + } + // 4. Batch insert if (notificationsToAdd.length > 0) { await db`INSERT INTO notifications ${db(notificationsToAdd)}`;