From 83c4d21811e565d33950e1a6b4cce8548bd0382f Mon Sep 17 00:00:00 2001 From: Cadence Ember Date: Fri, 7 Jul 2023 19:28:23 +1200 Subject: [PATCH 1/2] update discord-markdown to fix tests --- d2m/actions/register-user.test.js | 34 ++++---- d2m/converters/message-to-event.test.js | 110 ++++++++++++------------ package-lock.json | 18 ++-- package.json | 2 +- 4 files changed, 82 insertions(+), 82 deletions(-) diff --git a/d2m/actions/register-user.test.js b/d2m/actions/register-user.test.js index 7e23450..0afce50 100644 --- a/d2m/actions/register-user.test.js +++ b/d2m/actions/register-user.test.js @@ -4,21 +4,21 @@ const {test} = require("supertape") const testData = require("../../test/data") test("member2state: general", async t => { - t.deepEqual( - await _memberToStateContent(testData.member.sheep.user, testData.member.sheep, testData.guild.general.id), - { - avatar_url: "mxc://cadence.moe/rfemHmAtcprjLEiPiEuzPhpl", - displayname: "The Expert's Submarine | aprilsong", - membership: "join", - "moe.cadence.ooye.member": { - avatar: "/guilds/112760669178241024/users/134826546694193153/avatars/38dd359aa12bcd52dd3164126c587f8c.png?size=1024" - }, - "uk.half-shot.discord.member": { - bot: false, - displayColor: null, - id: "134826546694193153", - username: "@aprilsong" - } - } - ) + t.deepEqual( + await _memberToStateContent(testData.member.sheep.user, testData.member.sheep, testData.guild.general.id), + { + avatar_url: "mxc://cadence.moe/rfemHmAtcprjLEiPiEuzPhpl", + displayname: "The Expert's Submarine | aprilsong", + membership: "join", + "moe.cadence.ooye.member": { + avatar: "/guilds/112760669178241024/users/134826546694193153/avatars/38dd359aa12bcd52dd3164126c587f8c.png?size=1024" + }, + "uk.half-shot.discord.member": { + bot: false, + displayColor: null, + id: "134826546694193153", + username: "@aprilsong" + } + } + ) }) diff --git a/d2m/converters/message-to-event.test.js b/d2m/converters/message-to-event.test.js index 1f3a844..6e673f1 100644 --- a/d2m/converters/message-to-event.test.js +++ b/d2m/converters/message-to-event.test.js @@ -3,68 +3,68 @@ const {messageToEvent} = require("./message-to-event") const data = require("../../test/data") test("message2event: simple plaintext", async t => { - const events = await messageToEvent(data.message.simple_plaintext, data.guild.general) - t.deepEqual(events, [{ - $type: "m.room.message", - msgtype: "m.text", - body: "ayy lmao" - }]) + const events = await messageToEvent(data.message.simple_plaintext, data.guild.general) + t.deepEqual(events, [{ + $type: "m.room.message", + msgtype: "m.text", + body: "ayy lmao" + }]) }) test("message2event: simple user mention", async t => { - const events = await messageToEvent(data.message.simple_user_mention, data.guild.general) - t.deepEqual(events, [{ - $type: "m.room.message", - msgtype: "m.text", - body: "@crunch god: Tell me about Phil, renowned martial arts master and creator of the Chin Trick", - format: "org.matrix.custom.html", - formatted_body: '@crunch god Tell me about Phil, renowned martial arts master and creator of the Chin Trick' - }]) + const events = await messageToEvent(data.message.simple_user_mention, data.guild.general) + t.deepEqual(events, [{ + $type: "m.room.message", + msgtype: "m.text", + body: "@crunch god: Tell me about Phil, renowned martial arts master and creator of the Chin Trick", + format: "org.matrix.custom.html", + formatted_body: '@crunch god Tell me about Phil, renowned martial arts master and creator of the Chin Trick' + }]) }) test("message2event: attachment with no content", async t => { - const events = await messageToEvent(data.message.attachment_no_content, data.guild.general) - t.deepEqual(events, [{ - $type: "m.room.message", - msgtype: "m.image", - url: "mxc://cadence.moe/qXoZktDqNtEGuOCZEADAMvhM", - body: "image.png", - external_url: "https://cdn.discordapp.com/attachments/497161332244742154/1124628646431297546/image.png", - info: { - mimetype: "image/png", - w: 466, - h: 85, - size: 12919, - }, - }]) + const events = await messageToEvent(data.message.attachment_no_content, data.guild.general) + t.deepEqual(events, [{ + $type: "m.room.message", + msgtype: "m.image", + url: "mxc://cadence.moe/qXoZktDqNtEGuOCZEADAMvhM", + body: "image.png", + external_url: "https://cdn.discordapp.com/attachments/497161332244742154/1124628646431297546/image.png", + info: { + mimetype: "image/png", + w: 466, + h: 85, + size: 12919, + }, + }]) }) test("message2event: stickers", async t => { - const events = await messageToEvent(data.message.sticker, data.guild.general) - t.deepEqual(events, [{ - $type: "m.room.message", - msgtype: "m.text", - body: "can have attachments too" - }, { - $type: "m.room.message", - msgtype: "m.image", - url: "mxc://cadence.moe/ZDCNYnkPszxGKgObUIFmvjus", - body: "image.png", - external_url: "https://cdn.discordapp.com/attachments/122155380120748034/1106366167486038016/image.png", - info: { - mimetype: "image/png", - w: 333, - h: 287, - size: 127373, - }, - }, { - $type: "m.sticker", - body: "pomu puff - damn that tiny lil bitch really chuffing. puffing that fat ass dart", - info: { - mimetype: "image/png" - // thumbnail_url - // thumbnail_info - }, - url: "mxc://cadence.moe/UuUaLwXhkxFRwwWCXipDlBHn" - }]) + const events = await messageToEvent(data.message.sticker, data.guild.general) + t.deepEqual(events, [{ + $type: "m.room.message", + msgtype: "m.text", + body: "can have attachments too" + }, { + $type: "m.room.message", + msgtype: "m.image", + url: "mxc://cadence.moe/ZDCNYnkPszxGKgObUIFmvjus", + body: "image.png", + external_url: "https://cdn.discordapp.com/attachments/122155380120748034/1106366167486038016/image.png", + info: { + mimetype: "image/png", + w: 333, + h: 287, + size: 127373, + }, + }, { + $type: "m.sticker", + body: "pomu puff - damn that tiny lil bitch really chuffing. puffing that fat ass dart", + info: { + mimetype: "image/png" + // thumbnail_url + // thumbnail_info + }, + url: "mxc://cadence.moe/UuUaLwXhkxFRwwWCXipDlBHn" + }]) }) diff --git a/package-lock.json b/package-lock.json index 4908aa6..7dcde49 100644 --- a/package-lock.json +++ b/package-lock.json @@ -11,7 +11,7 @@ "dependencies": { "better-sqlite3": "^8.3.0", "cloudstorm": "^0.8.0", - "discord-markdown": "git+https://git.sr.ht/~cadence/nodejs-discord-markdown#24508e701e91d5a00fa5e773ced874d9ee8c889b", + "discord-markdown": "git+https://git.sr.ht/~cadence/nodejs-discord-markdown#df495b152fdc48fb22284ecda9a988e6df61bf99", "heatsync": "^2.4.1", "js-yaml": "^4.1.0", "matrix-appservice": "^2.0.0", @@ -685,11 +685,11 @@ } }, "node_modules/cloudstorm": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/cloudstorm/-/cloudstorm-0.8.2.tgz", - "integrity": "sha512-G/P6/+LwXjiS6AmheRG+07DmmsrpHpt21JFMhe+rW8VagFOOKemC2Bcru+Qncl/5jdjZC2gzjKpjfdTjfUm+iw==", + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/cloudstorm/-/cloudstorm-0.8.3.tgz", + "integrity": "sha512-4c2rqFFvzM4P3pcnjnGUlYuyBjx/xnMew6imB0sFwmNLITLCTLYa3qGkrnhI1g/tM0fqg+Gr+EmDHiDZfEr9LQ==", "dependencies": { - "snowtransfer": "^0.8.2" + "snowtransfer": "^0.8.3" }, "engines": { "node": ">=12.0.0" @@ -929,7 +929,7 @@ }, "node_modules/discord-markdown": { "version": "2.4.1", - "resolved": "git+https://git.sr.ht/~cadence/nodejs-discord-markdown#24508e701e91d5a00fa5e773ced874d9ee8c889b", + "resolved": "git+https://git.sr.ht/~cadence/nodejs-discord-markdown#df495b152fdc48fb22284ecda9a988e6df61bf99", "license": "MIT", "dependencies": { "simple-markdown": "^0.7.2" @@ -2464,9 +2464,9 @@ } }, "node_modules/snowtransfer": { - "version": "0.8.2", - "resolved": "https://registry.npmjs.org/snowtransfer/-/snowtransfer-0.8.2.tgz", - "integrity": "sha512-fAmaJSpFZqGwAvbrhT3XOWwhbiuHOgxN8pGeKnDDW0f8zdkPmSQT9aekXhFr1WukB94NIALYGcyIXe902p8S4A==", + "version": "0.8.3", + "resolved": "https://registry.npmjs.org/snowtransfer/-/snowtransfer-0.8.3.tgz", + "integrity": "sha512-0X6NLFBUKppYT5VH/mVQNGX+ufv0AndunZC84MqGAR/3rfTIGQblgGJlHlDQbeCytlXdMpgRHIGQnBFlE094NQ==", "dependencies": { "discord-api-types": "^0.37.47", "form-data": "^4.0.0", diff --git a/package.json b/package.json index b3e19eb..7fb8cc6 100644 --- a/package.json +++ b/package.json @@ -17,7 +17,7 @@ "dependencies": { "better-sqlite3": "^8.3.0", "cloudstorm": "^0.8.0", - "discord-markdown": "git+https://git.sr.ht/~cadence/nodejs-discord-markdown#24508e701e91d5a00fa5e773ced874d9ee8c889b", + "discord-markdown": "git+https://git.sr.ht/~cadence/nodejs-discord-markdown#df495b152fdc48fb22284ecda9a988e6df61bf99", "heatsync": "^2.4.1", "js-yaml": "^4.1.0", "matrix-appservice": "^2.0.0", From 30d28f92c72865319759575e56e04b1bd62eef23 Mon Sep 17 00:00:00 2001 From: Cadence Ember Date: Tue, 11 Jul 2023 08:01:11 +1200 Subject: [PATCH 2/2] store the channel_id on event_message --- d2m/actions/send-message.js | 2 +- d2m/converters/message-to-event.js | 16 +++- d2m/converters/message-to-event.test.js | 22 +++++ db/ooye.db | Bin 258048 -> 303104 bytes m2d/actions/send-event.js | 2 +- test/data.js | 113 ++++++++++++++++++++++++ 6 files changed, 150 insertions(+), 5 deletions(-) diff --git a/d2m/actions/send-message.js b/d2m/actions/send-message.js index 4f111b0..f5fe5ef 100644 --- a/d2m/actions/send-message.js +++ b/d2m/actions/send-message.js @@ -37,7 +37,7 @@ async function sendMessage(message, guild) { delete eventWithoutType.$type const eventID = await api.sendEvent(roomID, eventType, event, senderMxid) - db.prepare("INSERT INTO event_message (event_id, message_id, part, source) VALUES (?, ?, ?, 1)").run(eventID, message.id, eventPart) // source 1 = discord + db.prepare("INSERT INTO event_message (event_id, message_id, channel_id, part, source) VALUES (?, ?, ?, ?, 1)").run(eventID, message.id, message.channel_id, eventPart) // source 1 = discord eventPart = 1 // TODO: use more intelligent algorithm to determine whether primary or supporting eventIDs.push(eventID) diff --git a/d2m/converters/message-to-event.js b/d2m/converters/message-to-event.js index 90023ee..fc76bf2 100644 --- a/d2m/converters/message-to-event.js +++ b/d2m/converters/message-to-event.js @@ -45,12 +45,22 @@ async function messageToEvent(message, guild) { // Text content appears first if (message.content) { - const html = markdown.toHTML(message.content, { + let content = message.content + content = content.replace(/https:\/\/(?:ptb\.|canary\.|www\.)?discord(?:app)?\.com\/channels\/([0-9]+)\/([0-9]+)\/([0-9]+)/, (whole, guildID, channelID, messageID) => { + const row = db.prepare("SELECT room_id, event_id FROM event_message INNER JOIN channel_room USING (channel_id) WHERE channel_id = ? AND message_id = ? AND part = 0").get(channelID, messageID) + if (row) { + return `https://matrix.to/#/${row.room_id}/${row.event_id}` + } else { + return `${whole} [event not found]` + } + }) + + const html = markdown.toHTML(content, { discordCallback: getDiscordParseCallbacks(message, true) }, null, null) - const body = markdown.toHTML(message.content, { - discordCallback: getDiscordParseCallbacks(message, false), //TODO: library bug!! + const body = markdown.toHTML(content, { + discordCallback: getDiscordParseCallbacks(message, false), discordOnly: true, escapeHTML: false, }, null, null) diff --git a/d2m/converters/message-to-event.test.js b/d2m/converters/message-to-event.test.js index 6e673f1..a456a94 100644 --- a/d2m/converters/message-to-event.test.js +++ b/d2m/converters/message-to-event.test.js @@ -22,6 +22,28 @@ test("message2event: simple user mention", async t => { }]) }) +test("message2event: simple room mention", async t => { + const events = await messageToEvent(data.message.simple_room_mention, data.guild.general) + t.deepEqual(events, [{ + $type: "m.room.message", + msgtype: "m.text", + body: "@crunch god: Tell me about Phil, renowned martial arts master and creator of the Chin Trick", + format: "org.matrix.custom.html", + formatted_body: '@crunch god Tell me about Phil, renowned martial arts master and creator of the Chin Trick' + }]) +}) + +test("message2event: simple message link", async t => { + const events = await messageToEvent(data.message.simple_message_link, data.guild.general) + t.deepEqual(events, [{ + $type: "m.room.message", + msgtype: "m.text", + body: "https://matrix.to/#/!kLRqKKUQXcibIMtOpl:cadence.moe/$X16nfVks1wsrhq4E9SSLiqrf2N8KD0erD0scZG7U5xg", + format: "org.matrix.custom.html", + formatted_body: 'https://matrix.to/#/!kLRqKKUQXcibIMtOpl:cadence.moe/$X16nfVks1wsrhq4E9SSLiqrf2N8KD0erD0scZG7U5xg' + }]) +}) + test("message2event: attachment with no content", async t => { const events = await messageToEvent(data.message.attachment_no_content, data.guild.general) t.deepEqual(events, [{ diff --git a/db/ooye.db b/db/ooye.db index 7df165b729fcd153b82c31b6108e205ba746d49b..b87572013e78f96e7b0fa036a7f964b33b2fad7c 100644 GIT binary patch delta 13060 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 delta 6665 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", + channel_id: "112760669178241024", + author: { + id: "116718249567059974", + username: "rnl", + avatar: "67e70f6424eead669e076b44474164c3", + discriminator: "0", + public_flags: 768, + flags: 768, + banner: null, + accent_color: null, + global_name: "▲", + avatar_decoration: null, + display_name: "▲", + banner_color: null + }, + attachments: [], + embeds: [], + mentions: [ + { + id: "113340068197859328", + username: "kumaccino", + avatar: "b48302623a12bc7c59a71328f72ccb39", + discriminator: "0", + public_flags: 128, + flags: 128, + banner: null, + accent_color: null, + global_name: "kumaccino", + avatar_decoration: null, + display_name: "kumaccino", + banner_color: null + } + ], + mention_roles: [], + pinned: false, + mention_everyone: false, + tts: false, + timestamp: "2023-07-06T20:05:32.496000+00:00", + edited_timestamp: null, + flags: 0, + components: [], + message_reference: { + channel_id: "112760669178241024", + message_id: "1126577139723026564", + guild_id: "112760669178241024" + }, + referenced_message: { + id: "1126577139723026564", + type: 0, + content: "this message was replied to", + channel_id: "112760669178241024", + author: { + id: "113340068197859328", + username: "kumaccino", + avatar: "b48302623a12bc7c59a71328f72ccb39", + discriminator: "0", + public_flags: 128, + flags: 128, + banner: null, + accent_color: null, + global_name: "kumaccino", + avatar_decoration: null, + display_name: "kumaccino", + banner_color: null + }, + attachments: [], + embeds: [], + mentions: [], + mention_roles: [], + pinned: false, + mention_everyone: false, + tts: false, + timestamp: "2023-07-06T18:15:20.901000+00:00", + edited_timestamp: null, + flags: 0, + components: [] + } + }, attachment_no_content: { id: "1124628646670389348", type: 0,