diff --git a/src/d2m/converters/find-mentions.js b/src/d2m/converters/find-mentions.js index 8107459..5135d17 100644 --- a/src/d2m/converters/find-mentions.js +++ b/src/d2m/converters/find-mentions.js @@ -107,7 +107,6 @@ function tokenise(name) { * @returns {ProcessedJoined} */ function processJoined(joined) { - joined = joined.filter(j => !userRegex.some(rx => j.mxid.match(rx))) return { mxids: joined.map(j => { const localpart = j.mxid.match(/@([^:]*)/) @@ -141,8 +140,14 @@ function findMention(pjr, maximumWrittenSection, baseOffset, prefix, content) { /** @type {{mxid: string, scored: {score: number, matchedInputTokens: Token[]}}[]} */ let allItems = pjr.mxids.map(mxid => ({...mxid, scored: scoreLocalpart(mxid.localpart, maximumWrittenSection, mxid.displayname)})) allItems = allItems.concat(pjr.names.map(name => ({...name, scored: scoreName(name.displaynameTokens, maximumWrittenSectionTokens)}))) - const best = allItems.sort((a, b) => b.scored.score - a.scored.score)[0] - if (best.scored.score > 4) { // requires in smallest case perfect match of 2 characters, or in largest case a partial middle match of 5+ characters in a row + // Tiebreaker bonus for Matrix users + for (const item of allItems) { + if (!userRegex.some(rx => item.mxid.match(rx))) item.scored.score += 1 + } + const [best, secondBest] = allItems.sort((a, b) => b.scored.score - a.scored.score) + if (userRegex.some(rx => best.mxid.match(rx))) return // Discord user was best match, so it was just a written non-pinging @ for a Discord user. Don't highlight a Matrix user. + if (secondBest && secondBest.scored.score === best.scored.score) return // all tied up + if (best.scored.score > 5) { // requires in smallest case Matrix user tiebreaker + perfect match of 2 characters, or in largest case a partial middle match of 5+ characters in a row // Highlight the relevant part of the message const start = baseOffset + best.scored.matchedInputTokens[0].index const end = baseOffset + prefix.length + best.scored.matchedInputTokens.slice(-1)[0].end diff --git a/src/d2m/converters/find-mentions.test.js b/src/d2m/converters/find-mentions.test.js index 8f2be09..d0a3de9 100644 --- a/src/d2m/converters/find-mentions.test.js +++ b/src/d2m/converters/find-mentions.test.js @@ -117,6 +117,47 @@ test("score name: finds match location", t => { t.equal(message.slice(startLocation, endLocation), "evil lillith") }) +test("score name: matches the correct jan", t => { + const names = [ + "jan Kanoli", + "jan Mijawi", + "jan Mukin" + ] + t.deepEqual(names.map(n => scoreName(tokenise(n), tokenise("jan Mijawi")).score), [ + 6, + 18.4, + 6 + ]) +}) + +test("find mention: highlights nothing if a Discord user scored highest", t => { + const found = findMention(processJoined([{ + mxid: "@jankanoli:matrix.org", + displayname: "jan Kanoli" + }, { + mxid: "@_ooye_jan_mijawi:cadence.moe", + displayname: "jan Mijawi" + }, { + mxid: "@_ooye_jan_mukin:cadence.moe", + displayname: "jan Mukin" + }]), "jan Mijawi, run this\n.def", 0, "@", "jan Mijawi, run this\n.def") + t.equal(found, undefined) +}) + +test("find mention: highlights nothing if all tied", t => { + const found = findMention(processJoined([{ + mxid: "@jankanoli:matrix.org", + displayname: "jan Kanoli" + }, { + mxid: "@_ooye_jan_mijawi:cadence.moe", + displayname: "jan Mijawi" + }, { + mxid: "@_ooye_jan_mukin:cadence.moe", + displayname: "jan Mukin" + }]), "jan Misali, run this\n.def", 0, "@", "jan Misali, run this\n.def") + t.equal(found, undefined) +}) + test("find mention: test various tiebreakers", t => { const found = findMention(processJoined([{ mxid: "@emma:conduit.rory.gay",