Fix mention notification with a remote account
authorChocobozzz <me@florianbigard.com>
Thu, 14 Feb 2019 10:04:50 +0000 (11:04 +0100)
committerChocobozzz <me@florianbigard.com>
Thu, 14 Feb 2019 10:04:50 +0000 (11:04 +0100)
server/lib/notifier.ts
server/models/video/video-comment.ts
server/tests/api/users/user-notifications.ts

index d1b3313467ccb61e8f0d630826afa3c36b20707e..2fa320cd7527906ea36a879da967462fd18b9b6c 100644 (file)
@@ -148,6 +148,8 @@ class Notifier {
 
   private async notifyOfCommentMention (comment: VideoCommentModel) {
     const usernames = comment.extractMentions()
+    logger.debug('Extracted %d username from comment %s.', usernames.length, comment.url, { usernames, text: comment.text })
+
     let users = await UserModel.listByUsernames(usernames)
 
     if (comment.Video.isOwned()) {
index cf6278da77399a423f18040cee265f25b294ffb3..1163f9a0eb1d3f073cdd69ee8367b8d1e8587d6f 100644 (file)
@@ -466,31 +466,41 @@ export class VideoCommentModel extends Model<VideoCommentModel> {
   }
 
   extractMentions () {
-    if (!this.text) return []
+    let result: string[] = []
 
     const localMention = `@(${actorNameAlphabet}+)`
     const remoteMention = `${localMention}@${CONFIG.WEBSERVER.HOST}`
 
+    const mentionRegex = this.isOwned()
+      ? '(?:(?:' + remoteMention + ')|(?:' + localMention + '))' // Include local mentions?
+      : '(?:' + remoteMention + ')'
+
+    const firstMentionRegex = new RegExp(`^${mentionRegex} `, 'g')
+    const endMentionRegex = new RegExp(` ${mentionRegex}$`, 'g')
     const remoteMentionsRegex = new RegExp(' ' + remoteMention + ' ', 'g')
-    const localMentionsRegex = new RegExp(' ' + localMention + ' ', 'g')
-    const firstMentionRegex = new RegExp('^(?:(?:' + remoteMention + ')|(?:' + localMention + ')) ', 'g')
-    const endMentionRegex = new RegExp(' (?:(?:' + remoteMention + ')|(?:' + localMention + '))$', 'g')
 
-    return uniq(
-      [].concat(
-        regexpCapture(this.text, remoteMentionsRegex)
-          .map(([ , username ]) => username),
+    result = result.concat(
+      regexpCapture(this.text, firstMentionRegex)
+        .map(([ , username1, username2 ]) => username1 || username2),
 
-        regexpCapture(this.text, localMentionsRegex)
-          .map(([ , username ]) => username),
+      regexpCapture(this.text, endMentionRegex)
+        .map(([ , username1, username2 ]) => username1 || username2),
+
+      regexpCapture(this.text, remoteMentionsRegex)
+        .map(([ , username ]) => username)
+    )
 
-        regexpCapture(this.text, firstMentionRegex)
-          .map(([ , username1, username2 ]) => username1 || username2),
+    // Include local mentions
+    if (this.isOwned()) {
+      const localMentionsRegex = new RegExp(' ' + localMention + ' ', 'g')
 
-        regexpCapture(this.text, endMentionRegex)
-          .map(([ , username1, username2 ]) => username1 || username2)
+      result = result.concat(
+        regexpCapture(this.text, localMentionsRegex)
+          .map(([ , username ]) => username)
       )
-    )
+    }
+
+    return uniq(result)
   }
 
   toFormattedJSON () {
index 5260d64cc163e5a057fca5b036a0e462a1d5e9c9..72b6a0aa225f15794d6460531cbe514957de5471 100644 (file)
@@ -506,6 +506,20 @@ describe('Test users notifications', function () {
       await removeAccountFromAccountBlocklist(servers[ 0 ].url, userAccessToken, 'root')
     })
 
+    it('Should not send a new mention notification if the remote account mention a local account', async function () {
+      this.timeout(20000)
+
+      const resVideo = await uploadVideo(servers[0].url, servers[0].accessToken, { name: 'super video' })
+      const uuid = resVideo.body.video.uuid
+
+      await waitJobs(servers)
+      const resThread = await addVideoCommentThread(servers[1].url, servers[1].accessToken, uuid, '@user_1 hello')
+      const threadId = resThread.body.comment.id
+
+      await waitJobs(servers)
+      await checkCommentMention(baseParams, uuid, threadId, threadId, 'super root 2 name', 'absence')
+    })
+
     it('Should send a new mention notification after local comments', async function () {
       this.timeout(10000)