diff --git a/db/data-for-test.sql b/db/data-for-test.sql index 8c564df..7148b19 100644 --- a/db/data-for-test.sql +++ b/db/data-for-test.sql @@ -47,13 +47,6 @@ CREATE TABLE IF NOT EXISTS "event_message" ( "source" INTEGER NOT NULL, PRIMARY KEY("event_id","message_id") ); -CREATE TABLE IF NOT EXISTS "member_cache" ( - "room_id" TEXT NOT NULL, - "mxid" TEXT NOT NULL, - "displayname" TEXT, - "avatar_url" TEXT, - PRIMARY KEY("room_id", "mxid") -); COMMIT; @@ -74,8 +67,7 @@ INSERT INTO sim (discord_id, sim_name, localpart, mxid) VALUES ('820865262526005258', 'crunch_god', '_ooye_crunch_god', '@_ooye_crunch_god:cadence.moe'), ('771520384671416320', 'bojack_horseman', '_ooye_bojack_horseman', '@_ooye_bojack_horseman:cadence.moe'), ('112890272819507200', '.wing.', '_ooye_.wing.', '@_ooye_.wing.:cadence.moe'), -('114147806469554185', 'extremity', '_ooye_extremity', '@_ooye_extremity:cadence.moe'), -('111604486476181504', 'kyuugryphon', '_ooye_kyuugryphon', '@_ooye_kyuugryphon:cadence.moe');; +('114147806469554185', 'extremity', '_ooye_extremity', '@_ooye_extremity:cadence.moe'); INSERT INTO sim_member (mxid, room_id, profile_event_content_hash) VALUES ('@_ooye_bojack_horseman:cadence.moe', '!uCtjHhfGlYbVnPVlkG:cadence.moe', NULL); @@ -94,8 +86,7 @@ INSERT INTO event_message (event_id, event_type, event_subtype, message_id, chan ('$FchUVylsOfmmbj-VwEs5Z9kY49_dt2zd0vWfylzy5Yo', 'm.room.message', 'm.text', '1143121514925928541', '1100319550446252084', 0, 1), ('$lnAF9IosAECTnlv9p2e18FG8rHn-JgYKHEHIh5qdFv4', 'm.room.message', 'm.text', '1106366167788044450', '122155380120748034', 0, 1), ('$Ijf1MFCD39ktrNHxrA-i2aKoRWNYdAV2ZXYQeiZIgEU', 'm.room.message', 'm.image', '1106366167788044450', '122155380120748034', 0, 0), -('$f9cjKiacXI9qPF_nUAckzbiKnJEi0LM399kOkhdd8f8', 'm.sticker', NULL, '1106366167788044450', '122155380120748034', 0, 0), -('$Fxy8SMoJuTduwReVkHZ1uHif9EuvNx36Hg79cltiA04', 'm.room.message', 'm.text', '1144865310588014633', '687028734322147344', 0, 1); +('$f9cjKiacXI9qPF_nUAckzbiKnJEi0LM399kOkhdd8f8', 'm.sticker', NULL, '1106366167788044450', '122155380120748034', 0, 0); INSERT INTO file (discord_url, mxc_url) VALUES ('https://cdn.discordapp.com/attachments/497161332244742154/1124628646431297546/image.png', 'mxc://cadence.moe/qXoZktDqNtEGuOCZEADAMvhM'), @@ -108,9 +99,4 @@ INSERT INTO file (discord_url, mxc_url) VALUES ('https://cdn.discordapp.com/icons/112760669178241024/a_f83622e09ead74f0c5c527fe241f8f8c.png?size=1024', 'mxc://cadence.moe/zKXGZhmImMHuGQZWJEFKJbsF'), ('https://cdn.discordapp.com/avatars/113340068197859328/b48302623a12bc7c59a71328f72ccb39.png?size=1024', 'mxc://cadence.moe/UpAeIqeclhKfeiZNdIWNcXXL'); -INSERT INTO member_cache (room_id, mxid, displayname, avatar_url) VALUES -('!kLRqKKUQXcibIMtOpl:cadence.moe', '@cadence:cadence.moe', 'cadence [they]', NULL), -('!BpMdOUkWWhFxmTrENV:cadence.moe', '@cadence:cadence.moe', 'cadence [they]', NULL), -('!fGgIymcYWOqjbSRUdV:cadence.moe', '@cadence:cadence.moe', 'cadence [they]', 'mxc://cadence.moe/azCAhThKTojXSZJRoWwZmhvU'); - COMMIT; diff --git a/m2d/actions/add-reaction.js b/m2d/actions/add-reaction.js index 49aa845..68828dd 100644 --- a/m2d/actions/add-reaction.js +++ b/m2d/actions/add-reaction.js @@ -21,20 +21,9 @@ async function addReaction(event) { let encoded = encodeURIComponent(emoji) let encodedTrimmed = encoded.replace(/%EF%B8%8F/g, "") - // https://github.com/discord/discord-api-docs/issues/2723#issuecomment-807022205 ???????????? + console.log("add reaction from matrix:", emoji, encoded, encodedTrimmed) - const forceTrimmedList = [ - "%E2%AD%90" // ⭐ - ] - - let discordPreferredEncoding = - ( forceTrimmedList.includes(encodedTrimmed) ? encodedTrimmed - : encodedTrimmed !== encoded && [...emoji].length === 2 ? encoded - : encodedTrimmed) - - console.log("add reaction from matrix:", emoji, encoded, encodedTrimmed, "chosen:", discordPreferredEncoding) - - return discord.snow.channel.createReaction(channelID, messageID, discordPreferredEncoding) + return discord.snow.channel.createReaction(channelID, messageID, encoded) } module.exports.addReaction = addReaction diff --git a/m2d/actions/send-event.js b/m2d/actions/send-event.js index 016768e..39eed22 100644 --- a/m2d/actions/send-event.js +++ b/m2d/actions/send-event.js @@ -9,8 +9,6 @@ const {sync, discord, db} = passthrough const channelWebhook = sync.require("./channel-webhook") /** @type {import("../converters/event-to-message")} */ const eventToMessage = sync.require("../converters/event-to-message") -/** @type {import("../../matrix/api")}) */ -const api = sync.require("../../matrix/api") /** @param {import("../../types").Event.Outer} event */ async function sendEvent(event) { @@ -22,14 +20,10 @@ async function sendEvent(event) { threadID = channelID channelID = row.thread_parent // it's the thread's parent... get with the times... } - // @ts-ignore - const guildID = discord.channels.get(channelID).guild_id - const guild = discord.guilds.get(guildID) - assert(guild) // no need to sync the matrix member to the other side. but if I did need to, this is where I'd do it - const messages = await eventToMessage.eventToMessage(event, guild, {api}) + const messages = eventToMessage.eventToMessage(event) assert(Array.isArray(messages)) // sanity /** @type {DiscordTypes.APIMessage[]} */ diff --git a/m2d/converters/event-to-message.js b/m2d/converters/event-to-message.js index f5d3c90..7893799 100644 --- a/m2d/converters/event-to-message.js +++ b/m2d/converters/event-to-message.js @@ -9,8 +9,6 @@ const passthrough = require("../../passthrough") const { sync, db, discord } = passthrough /** @type {import("../../matrix/file")} */ const file = sync.require("../../matrix/file") -/** @type {import("../converters/utils")} */ -const utils = sync.require("../converters/utils") const BLOCK_ELEMENTS = [ "ADDRESS", "ARTICLE", "ASIDE", "AUDIO", "BLOCKQUOTE", "BODY", "CANVAS", @@ -28,8 +26,6 @@ const turndownService = new TurndownService({ codeBlockStyle: "fenced" }) -turndownService.remove("mx-reply") - turndownService.addRule("strikethrough", { filter: ["del", "s", "strike"], replacement: function (content) { @@ -37,75 +33,20 @@ turndownService.addRule("strikethrough", { } }) -turndownService.addRule("blockquote", { - filter: "blockquote", - replacement: function (content) { - content = content.replace(/^\n+|\n+$/g, "") - content = content.replace(/^/gm, "> ") - return content - } -}) - -turndownService.addRule("fencedCodeBlock", { - filter: function (node, options) { - return ( - options.codeBlockStyle === "fenced" && - node.nodeName === "PRE" && - node.firstChild && - node.firstChild.nodeName === "CODE" - ) - }, - replacement: function (content, node, options) { - const className = node.firstChild.getAttribute("class") || "" - const language = (className.match(/language-(\S+)/) || [null, ""])[1] - const code = node.firstChild - const visibleCode = code.childNodes.map(c => c.nodeName === "BR" ? "\n" : c.textContent).join("").replace(/\n*$/g, "") - - var fence = "```" - - return ( - fence + language + "\n" + - visibleCode + - "\n" + fence - ) - } -}) - -/** - * @param {string} roomID - * @param {string} mxid - * @returns {Promise<{displayname?: string?, avatar_url?: string?}>} - */ -async function getMemberFromCacheOrHomeserver(roomID, mxid, api) { - const row = db.prepare("SELECT displayname, avatar_url FROM member_cache WHERE room_id = ? AND mxid = ?").get(roomID, mxid) - if (row) return row - return api.getStateEvent(roomID, "m.room.member", mxid).then(event => { - db.prepare("REPLACE INTO member_cache (room_id, mxid, displayname, avatar_url) VALUES (?, ?, ?, ?)").run(roomID, mxid, event?.displayname || null, event?.avatar_url || null) - return event - }).catch(() => { - return {displayname: null, avatar_url: null} - }) -} - /** * @param {Ty.Event.Outer} event - * @param {import("discord-api-types/v10").APIGuild} guild - * @param {{api: import("../../matrix/api")}} di simple-as-nails dependency injection for the matrix API */ -async function eventToMessage(event, guild, di) { +function eventToMessage(event) { /** @type {(DiscordTypes.RESTPostAPIWebhookWithTokenJSONBody & {files?: {name: string, file: Buffer}[]})[]} */ let messages = [] let displayName = event.sender let avatarURL = undefined - let replyLine = "" - // Extract a basic display name from the sender const match = event.sender.match(/^@(.*?):/) - if (match) displayName = match[1] - // Try to extract an accurate display name and avatar URL from the member event - const member = await getMemberFromCacheOrHomeserver(event.room_id, event.sender, di?.api) - if (member.displayname) displayName = member.displayname - if (member.avatar_url) avatarURL = utils.getPublicUrlForMxc(member.avatar_url) + if (match) { + displayName = match[1] + // TODO: get the media repo domain and the avatar url from the matrix member event + } // Convert content depending on what the message is let content = event.content.body // ultimate fallback @@ -120,39 +61,9 @@ async function eventToMessage(event, guild, di) { // input = input.replace(/ /g, " ") // There is also a corresponding test to uncomment, named "event2message: whitespace is retained" - // Handling replies. We'll look up the data of the replied-to event from the Matrix homeserver. - await (async () => { - const repliedToEventId = event.content["m.relates_to"]?.["m.in_reply_to"].event_id - if (!repliedToEventId) return - const repliedToEvent = await di.api.getEvent(event.room_id, repliedToEventId) - if (!repliedToEvent) return - const row = db.prepare("SELECT channel_id, message_id FROM event_message WHERE event_id = ? ORDER BY part").get(repliedToEventId) - if (row) { - replyLine = `<:L1:1144820033948762203><:L2:1144820084079087647>https://discord.com/channels/${guild.id}/${row.channel_id}/${row.message_id} ` - } else { - replyLine = `<:L1:1144820033948762203><:L2:1144820084079087647>` - } - const sender = repliedToEvent.sender - const senderName = sender.match(/@([^:]*)/)?.[1] || sender - const authorID = db.prepare("SELECT discord_id FROM sim WHERE mxid = ?").pluck().get(repliedToEvent.sender) - if (authorID) { - replyLine += `<@${authorID}>: ` - } else { - replyLine += `Ⓜ️**${senderName}**: ` - } - const repliedToContent = repliedToEvent.content.formatted_body || repliedToEvent.content.body - const contentPreviewChunks = chunk(repliedToContent.replace(/.*<\/mx-reply>/, "").replace(/(?:\n|
)+/g, " ").replace(/<[^>]+>/g, ""), 24) - const contentPreview = contentPreviewChunks.length > 1 ? contentPreviewChunks[0] + "..." : contentPreviewChunks[0] - replyLine += contentPreview + "\n" - })() - - // Element adds a bunch of
before but doesn't render them. I can't figure out how this even works in the browser, so let's just delete those. - input = input.replace(/(?:\n|
\s*)*<\/blockquote>/g, "") - // The matrix spec hasn't decided whether \n counts as a newline or not, but I'm going to count it, because if it's in the data it's there for a reason. // But I should not count it if it's between block elements. input = input.replace(/(<\/?([^ >]+)[^>]*>)?\n(<\/?([^ >]+)[^>]*>)?/g, (whole, beforeContext, beforeTag, afterContext, afterTag) => { - // console.error(beforeContext, beforeTag, afterContext, afterTag) if (typeof beforeTag !== "string" && typeof afterTag !== "string") { return "
" } @@ -178,8 +89,6 @@ async function eventToMessage(event, guild, di) { content = content.replace(/([*_~`#])/g, `\\$1`) } - content = replyLine + content - // Split into 2000 character chunks const chunks = chunk(content, 2000) messages = messages.concat(chunks.map(content => ({ diff --git a/m2d/converters/event-to-message.test.js b/m2d/converters/event-to-message.test.js index b595be8..7aefdb1 100644 --- a/m2d/converters/event-to-message.test.js +++ b/m2d/converters/event-to-message.test.js @@ -1,42 +1,18 @@ +// @ts-check + const {test} = require("supertape") const {eventToMessage} = require("./event-to-message") const data = require("../../test/data") -/** - * @param {string} roomID - * @param {string} eventID - * @returns {(roomID: string, eventID: string) => Promise>} - */ -function mockGetEvent(t, roomID_in, eventID_in, outer) { - return async function(roomID, eventID) { - t.equal(roomID, roomID_in) - t.equal(eventID, eventID_in) - return new Promise(resolve => { - setTimeout(() => { - resolve({ - event_id: eventID_in, - room_id: roomID_in, - origin_server_ts: 1680000000000, - unsigned: { - age: 2245, - transaction_id: "$local.whatever" - }, - ...outer - }) - }) - }) - } -} - function sameFirstContentAndWhitespace(t, a, b) { const a2 = JSON.stringify(a[0].content) const b2 = JSON.stringify(b[0].content) t.equal(a2, b2) } -test("event2message: body is used when there is no formatted_body", async t => { +test("event2message: body is used when there is no formatted_body", t => { t.deepEqual( - await eventToMessage({ + eventToMessage({ content: { body: "testing plaintext", msgtype: "m.text" @@ -51,16 +27,16 @@ test("event2message: body is used when there is no formatted_body", async t => { } }), [{ - username: "cadence [they]", + username: "cadence", content: "testing plaintext", avatar_url: undefined }] ) }) -test("event2message: any markdown in body is escaped", async t => { +test("event2message: any markdown in body is escaped", t => { t.deepEqual( - await eventToMessage({ + eventToMessage({ content: { body: "testing **special** ~~things~~ which _should_ *not* `trigger` @any ", msgtype: "m.text" @@ -75,16 +51,16 @@ test("event2message: any markdown in body is escaped", async t => { } }), [{ - username: "cadence [they]", + username: "cadence", content: "testing \\*\\*special\\*\\* \\~\\~things\\~\\~ which \\_should\\_ \\*not\\* \\`trigger\\` @any ", avatar_url: undefined }] ) }) -test("event2message: basic html is converted to markdown", async t => { +test("event2message: basic html is converted to markdown", t => { t.deepEqual( - await eventToMessage({ + eventToMessage({ content: { msgtype: "m.text", body: "wrong body", @@ -101,16 +77,16 @@ test("event2message: basic html is converted to markdown", async t => { } }), [{ - username: "cadence [they]", + username: "cadence", content: "this **is** a **_test_** of ~~formatting~~", avatar_url: undefined }] ) }) -test("event2message: markdown syntax is escaped", async t => { +test("event2message: markdown syntax is escaped", t => { t.deepEqual( - await eventToMessage({ + eventToMessage({ content: { msgtype: "m.text", body: "wrong body", @@ -127,16 +103,16 @@ test("event2message: markdown syntax is escaped", async t => { } }), [{ - username: "cadence [they]", + username: "cadence", content: "this \\*\\*is\\*\\* an **_extreme_** \\\\\\*test\\\\\\* of", avatar_url: undefined }] ) }) -test("event2message: html lines are bridged correctly", async t => { +test("event2message: html lines are bridged correctly", t => { t.deepEqual( - await eventToMessage({ + eventToMessage({ content: { msgtype: "m.text", body: "wrong body", @@ -153,16 +129,16 @@ test("event2message: html lines are bridged correctly", async t => { } }), [{ - username: "cadence [they]", + username: "cadence", content: "paragraph one\nline _two_\nline three\n\nparagraph two\nline _two_\nline three\n\nparagraph three\n\nparagraph four\nline two\nline three\nline four\n\nparagraph five", avatar_url: undefined }] ) }) -/*test("event2message: whitespace is retained", async t => { +/*test("event2message: whitespace is retained", t => { t.deepEqual( - await eventToMessage({ + eventToMessage({ content: { msgtype: "m.text", body: "wrong body", @@ -179,17 +155,17 @@ test("event2message: html lines are bridged correctly", async t => { } }), [{ - username: "cadence [they]", + username: "cadence", content: "line one: test test\nline two: **test** **test**\nline three: **test test**\nline four: test test\n line five", avatar_url: undefined }] ) })*/ -test("event2message: whitespace is collapsed", async t => { +test("event2message: whitespace is collapsed", t => { sameFirstContentAndWhitespace( t, - await eventToMessage({ + eventToMessage({ content: { msgtype: "m.text", body: "wrong body", @@ -206,17 +182,17 @@ test("event2message: whitespace is collapsed", async t => { } }), [{ - username: "cadence [they]", + username: "cadence", content: "line one: test test\nline two: **test** **test**\nline three: **test test**\nline four: test test\nline five", avatar_url: undefined }] ) }) -test("event2message: lists are bridged correctly", async t => { +test("event2message: lists are bridged correctly", t => { sameFirstContentAndWhitespace( t, - await eventToMessage({ + eventToMessage({ "type": "m.room.message", "sender": "@cadence:cadence.moe", "content": { @@ -234,16 +210,16 @@ test("event2message: lists are bridged correctly", async t => { "room_id": "!BpMdOUkWWhFxmTrENV:cadence.moe" }), [{ - username: "cadence [they]", + username: "cadence", content: "* line one\n* line two\n* line three\n * nested one\n * nested two\n* line four", avatar_url: undefined }] ) }) -test("event2message: long messages are split", async t => { +test("event2message: long messages are split", t => { t.deepEqual( - await eventToMessage({ + eventToMessage({ content: { body: ("a".repeat(130) + " ").repeat(19), msgtype: "m.text" @@ -258,20 +234,20 @@ test("event2message: long messages are split", async t => { } }), [{ - username: "cadence [they]", + username: "cadence", content: (("a".repeat(130) + " ").repeat(15)).slice(0, -1), avatar_url: undefined }, { - username: "cadence [they]", + username: "cadence", content: (("a".repeat(130) + " ").repeat(4)).slice(0, -1), avatar_url: undefined }] ) }) -test("event2message: code blocks work", async t => { +test("event2message: code blocks work", t => { t.deepEqual( - await eventToMessage({ + eventToMessage({ content: { msgtype: "m.text", body: "wrong body", @@ -288,69 +264,17 @@ test("event2message: code blocks work", async t => { } }), [{ - username: "cadence [they]", + username: "cadence", content: "preceding\n\n```\ncode block\n```\n\nfollowing `code` is inline", avatar_url: undefined }] ) }) -test("event2message: code block contents are formatted correctly and not escaped", async t => { - t.deepEqual( - await eventToMessage({ - "type": "m.room.message", - "sender": "@cadence:cadence.moe", - "content": { - "msgtype": "m.text", - "body": "wrong body", - "format": "org.matrix.custom.html", - "formatted_body": "
input = input.replace(/(<\\/?([^ >]+)[^>]*>)?\\n(<\\/?([^ >]+)[^>]*>)?/g,\n_input_ = input = input.replace(/(<\\/?([^ >]+)[^>]*>)?\\n(<\\/?([^ >]+)[^>]*>)?/g,\n
\n

input = input.replace(/(<\\/?([^ >]+)[^>]*>)?\\n(<\\/?([^ >]+)[^>]*>)?/g,

\n" - }, - "origin_server_ts": 1693031482275, - "unsigned": { - "age": 99, - "transaction_id": "m1693031482146.511" - }, - "event_id": "$pGkWQuGVmrPNByrFELxhzI6MCBgJecr5I2J3z88Gc2s", - "room_id": "!BpMdOUkWWhFxmTrENV:cadence.moe" - }), - [{ - username: "cadence [they]", - content: "```\ninput = input.replace(/(<\\/?([^ >]+)[^>]*>)?\\n(<\\/?([^ >]+)[^>]*>)?/g,\n_input_ = input = input.replace(/(<\\/?([^ >]+)[^>]*>)?\\n(<\\/?([^ >]+)[^>]*>)?/g,\n```\n\n`input = input.replace(/(<\\/?([^ >]+)[^>]*>)?\\n(<\\/?([^ >]+)[^>]*>)?/g,`", - avatar_url: undefined - }] - ) -}) -test("event2message: quotes have an appropriate amount of whitespace", async t => { +test("event2message: m.emote markdown syntax is escaped", t => { t.deepEqual( - await eventToMessage({ - content: { - msgtype: "m.text", - body: "wrong body", - format: "org.matrix.custom.html", - formatted_body: "
Chancellor of Germany Angela Merkel, on March 17, 2017: they did not shake hands



🤨" - }, - event_id: "$g07oYSZFWBkxohNEfywldwgcWj1hbhDzQ1sBAKvqOOU", - origin_server_ts: 1688301929913, - room_id: "!kLRqKKUQXcibIMtOpl:cadence.moe", - sender: "@cadence:cadence.moe", - type: "m.room.message", - unsigned: { - age: 405299 - } - }), - [{ - username: "cadence [they]", - content: "> Chancellor of Germany Angela Merkel, on March 17, 2017: they did not shake hands\n🤨", - avatar_url: undefined - }] - ) -}) - -test("event2message: m.emote markdown syntax is escaped", async t => { - t.deepEqual( - await eventToMessage({ + eventToMessage({ content: { msgtype: "m.emote", body: "wrong body", @@ -367,142 +291,9 @@ test("event2message: m.emote markdown syntax is escaped", async t => { } }), [{ - username: "cadence [they]", - content: "\\* cadence \\[they\\] shows you \\*\\*her\\*\\* **_extreme_** \\\\\\*test\\\\\\* of", + username: "cadence", + content: "\\* cadence shows you \\*\\*her\\*\\* **_extreme_** \\\\\\*test\\\\\\* of", avatar_url: undefined }] ) }) - -test("event2message: rich reply to a sim user", async t => { - t.deepEqual( - await eventToMessage({ - "type": "m.room.message", - "sender": "@cadence:cadence.moe", - "content": { - "msgtype": "m.text", - "body": "> <@_ooye_kyuugryphon:cadence.moe> Slow news day.\n\nTesting this reply, ignore", - "format": "org.matrix.custom.html", - "formatted_body": "
In reply to @_ooye_kyuugryphon:cadence.moe
Slow news day.
Testing this reply, ignore", - "m.relates_to": { - "m.in_reply_to": { - "event_id": "$Fxy8SMoJuTduwReVkHZ1uHif9EuvNx36Hg79cltiA04" - } - } - }, - "origin_server_ts": 1693029683016, - "unsigned": { - "age": 91, - "transaction_id": "m1693029682894.510" - }, - "event_id": "$v_Gtr-bzv9IVlSLBO5DstzwmiDd-GSFaNfHX66IupV8", - "room_id": "!fGgIymcYWOqjbSRUdV:cadence.moe" - }, data.guild.general, { - api: { - getEvent: mockGetEvent(t, "!fGgIymcYWOqjbSRUdV:cadence.moe", "$Fxy8SMoJuTduwReVkHZ1uHif9EuvNx36Hg79cltiA04", { - type: "m.room.message", - content: { - msgtype: "m.text", - body: "Slow news day." - }, - sender: "@_ooye_kyuugryphon:cadence.moe" - }) - } - }), - [{ - username: "cadence [they]", - content: "<:L1:1144820033948762203><:L2:1144820084079087647>https://discord.com/channels/112760669178241024/687028734322147344/1144865310588014633 <@111604486476181504>: Slow news day.\nTesting this reply, ignore", - avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU" - }] - ) -}) - -test("event2message: rich reply to a matrix user's long message with formatting", async t => { - t.deepEqual( - await eventToMessage({ - "type": "m.room.message", - "sender": "@cadence:cadence.moe", - "content": { - "msgtype": "m.text", - "body": "> <@cadence:cadence.moe> ```\n> i should have a little happy test\n> ```\n> * list **bold** _em_ ~~strike~~\n> # heading 1\n> ## heading 2\n> ### heading 3\n> https://cadence.moe\n> [legit website](https://cadence.moe)\n\nno you can't!!!", - "format": "org.matrix.custom.html", - "formatted_body": "
In reply to @cadence:cadence.moe
i should have a little happy test\n
\n
    \n
  • list bold em ~~strike~~
  • \n
\n

heading 1

\n

heading 2

\n

heading 3

\n

https://cadence.moe
legit website

\n
no you can't!!!", - "m.relates_to": { - "m.in_reply_to": { - "event_id": "$Fxy8SMoJuTduwReVkHZ1uHif9EuvNx36Hg79cltiA04" - } - } - }, - "origin_server_ts": 1693037401693, - "unsigned": { - "age": 381, - "transaction_id": "m1693037401592.521" - }, - "event_id": "$v_Gtr-bzv9IVlSLBO5DstzwmiDd-GSFaNfHX66IupV8", - "room_id": "!fGgIymcYWOqjbSRUdV:cadence.moe" - }, data.guild.general, { - api: { - getEvent: mockGetEvent(t, "!fGgIymcYWOqjbSRUdV:cadence.moe", "$Fxy8SMoJuTduwReVkHZ1uHif9EuvNx36Hg79cltiA04", { - "type": "m.room.message", - "sender": "@cadence:cadence.moe", - "content": { - "msgtype": "m.text", - "body": "```\ni should have a little happy test\n```\n* list **bold** _em_ ~~strike~~\n# heading 1\n## heading 2\n### heading 3\nhttps://cadence.moe\n[legit website](https://cadence.moe)", - "format": "org.matrix.custom.html", - "formatted_body": "
i should have a little happy test\n
\n
    \n
  • list bold em ~~strike~~
  • \n
\n

heading 1

\n

heading 2

\n

heading 3

\n

https://cadence.moe
legit website

\n" - } - }) - } - }), - [{ - username: "cadence [they]", - content: "<:L1:1144820033948762203><:L2:1144820084079087647>https://discord.com/channels/112760669178241024/687028734322147344/1144865310588014633 Ⓜ️**cadence**: i should have a little...\n**no you can't!!!**", - avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU" - }] - ) -}) - -test("event2message: with layered rich replies, the preview should only be the real text", async t => { - t.deepEqual( - await eventToMessage({ - type: "m.room.message", - sender: "@cadence:cadence.moe", - content: { - msgtype: "m.text", - body: "> <@cadence:cadence.moe> two\n\nthree", - format: "org.matrix.custom.html", - formatted_body: "
In reply to @cadence:cadence.moe
two
three", - "m.relates_to": { - "m.in_reply_to": { - event_id: "$Fxy8SMoJuTduwReVkHZ1uHif9EuvNx36Hg79cltiA04" - } - } - }, - event_id: "$v_Gtr-bzv9IVlSLBO5DstzwmiDd-GSFaNfHX66IupV8", - room_id: "!fGgIymcYWOqjbSRUdV:cadence.moe" - }, data.guild.general, { - api: { - getEvent: mockGetEvent(t, "!fGgIymcYWOqjbSRUdV:cadence.moe", "$Fxy8SMoJuTduwReVkHZ1uHif9EuvNx36Hg79cltiA04", { - "type": "m.room.message", - "sender": "@cadence:cadence.moe", - "content": { - "msgtype": "m.text", - "body": "> <@cadence:cadence.moe> one\n\ntwo", - "format": "org.matrix.custom.html", - "formatted_body": "
In reply to @cadence:cadence.moe
one
two", - "m.relates_to": { - "m.in_reply_to": { - "event_id": "$5UtboIC30EFlAYD_Oh0pSYVW8JqOp6GsDIJZHtT0Wls" - } - } - } - }) - } - }), - [{ - username: "cadence [they]", - content: "<:L1:1144820033948762203><:L2:1144820084079087647>https://discord.com/channels/112760669178241024/687028734322147344/1144865310588014633 Ⓜ️**cadence**: two\nthree", - avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU" - }] - ) -}) diff --git a/m2d/converters/utils.js b/m2d/converters/utils.js index 02ec147..7b9c504 100644 --- a/m2d/converters/utils.js +++ b/m2d/converters/utils.js @@ -19,15 +19,4 @@ function eventSenderIsFromDiscord(sender) { return false } -/** - * @param {string} mxc - * @returns {string?} - */ -function getPublicUrlForMxc(mxc) { - const avatarURLParts = mxc?.match(/^mxc:\/\/([^/]+)\/(\w+)$/) - if (avatarURLParts) return `https://matrix.cadence.moe/_matrix/media/r0/download/${avatarURLParts[1]}/${avatarURLParts[2]}` - else return null -} - module.exports.eventSenderIsFromDiscord = eventSenderIsFromDiscord -module.exports.getPublicUrlForMxc = getPublicUrlForMxc diff --git a/m2d/event-dispatcher.js b/m2d/event-dispatcher.js index 9a575fc..c62d805 100644 --- a/m2d/event-dispatcher.js +++ b/m2d/event-dispatcher.js @@ -80,24 +80,3 @@ async event => { const url = event.content.url || null db.prepare("UPDATE channel_room SET custom_avatar = ? WHERE room_id = ?").run(url, event.room_id) })) - -sync.addTemporaryListener(as, "type:m.room.name", guard("m.room.name", -/** - * @param {Ty.Event.StateOuter} event - */ -async event => { - if (event.state_key !== "") return - if (utils.eventSenderIsFromDiscord(event.sender)) return - const name = event.content.name || null - db.prepare("UPDATE channel_room SET nick = ? WHERE room_id = ?").run(name, event.room_id) -})) - -sync.addTemporaryListener(as, "type:m.room.member", guard("m.room.member", -/** - * @param {Ty.Event.StateOuter} event - */ -async event => { - if (event.state_key[0] !== "@") return - if (utils.eventSenderIsFromDiscord(event.sender)) return - db.prepare("REPLACE INTO member_cache (room_id, mxid, displayname, avatar_url) VALUES (?, ?, ?, ?)").run(event.room_id, event.sender, event.content.displayname || null, event.content.avatar_url || null) -})) diff --git a/types.d.ts b/types.d.ts index 5475904..badbbab 100644 --- a/types.d.ts +++ b/types.d.ts @@ -70,17 +70,12 @@ export namespace Event { msgtype: "m.text" | "m.emote" body: string format?: "org.matrix.custom.html" - formatted_body?: string, - "m.relates_to"?: { - "m.in_reply_to": { - event_id: string - } - } + formatted_body?: string } export type M_Room_Member = { membership: string - displayname?: string + display_name?: string avatar_url?: string } @@ -89,10 +84,6 @@ export namespace Event { url?: string } - export type M_Room_Name = { - name?: string - } - export type M_Reaction = { "m.relates_to": { rel_type: "m.annotation"