support written @mentions (scenario 3)

This commit is contained in:
Cadence Ember 2023-07-11 17:27:40 +12:00
parent 328ae74b61
commit 437f04682c
3 changed files with 94 additions and 1 deletions

View file

@ -8,6 +8,9 @@ const passthrough = require("../../passthrough")
const { sync, db, discord } = passthrough
/** @type {import("../../matrix/file")} */
const file = sync.require("../../matrix/file")
const reg = require("../../matrix/read-registration")
const userRegex = reg.namespaces.users.map(u => new RegExp(u.regex))
function getDiscordParseCallbacks(message, useHTML) {
return {
@ -69,7 +72,7 @@ async function messageToEvent(message, guild, api) {
function addMention(mxid) {
if (!mentions.user_ids) mentions.user_ids = []
mentions.user_ids.push(mxid)
if (!mentions.user_ids.includes(mxid)) mentions.user_ids.push(mxid)
}
// Mentions scenarios 1 and 2, part A. i.e. translate relevant message.mentions to m.mentions
@ -106,12 +109,28 @@ async function messageToEvent(message, guild, api) {
discordCallback: getDiscordParseCallbacks(message, true)
}, null, null)
// TODO: add a string return type to my discord-markdown library
let body = markdown.toHTML(content, {
discordCallback: getDiscordParseCallbacks(message, false),
discordOnly: true,
escapeHTML: false,
}, null, null)
// Mentions scenario 3: scan the message content for written @mentions of matrix users
const matches = [...content.matchAll(/@([a-z0-9._]+)\b/gi)]
if (matches.length && matches.some(m => m[1].match(/[a-z]/i))) {
const writtenMentionsText = matches.map(m => m[1].toLowerCase())
const roomID = db.prepare("SELECT room_id FROM channel_room WHERE channel_id = ?").pluck().get(message.channel_id)
const {joined} = await api.getJoinedMembers(roomID)
for (const [mxid, member] of Object.entries(joined)) {
if (!userRegex.some(rx => mxid.match(rx))) {
const localpart = mxid.match(/@([^:]*)/)
assert(localpart)
if (writtenMentionsText.includes(localpart[1].toLowerCase()) || writtenMentionsText.includes(member.display_name.toLowerCase())) addMention(mxid)
}
}
}
// Fallback body/formatted_body for replies
if (repliedToEventId) {
let repliedToDisplayName

View file

@ -215,4 +215,47 @@ test("message2event: simple reply to matrix user", async t => {
}])
})
test("message2event: simple written @mention for matrix user", async t => {
const events = await messageToEvent(data.message.simple_written_at_mention_for_matrix, data.guild.general, {
async getJoinedMembers(roomID) {
t.equal(roomID, "!kLRqKKUQXcibIMtOpl:cadence.moe")
return new Promise(resolve => {
setTimeout(() => {
resolve({
joined: {
"@cadence:cadence.moe": {
display_name: "cadence [they]",
avatar_url: "whatever"
},
"@huckleton:cadence.moe": {
display_name: "huck",
avatar_url: "whatever"
},
"@_ooye_botrac4r:cadence.moe": {
display_name: "botrac4r",
avatar_url: "whatever"
},
"@_ooye_bot:cadence.moe": {
display_name: "Out Of Your Element",
avatar_url: "whatever"
}
}
})
})
})
}
})
t.deepEqual(events, [{
$type: "m.room.message",
"m.mentions": {
user_ids: [
"@cadence:cadence.moe",
"@huckleton:cadence.moe"
]
},
msgtype: "m.text",
body: "@Cadence, tell me about @Phil, the creator of the Chin Trick, who has become ever more powerful under the mentorship of @botrac4r and @huck"
}])
})
// TODO: read "edits of replies" in the spec