diff --git a/d2m/actions/register-user.js b/d2m/actions/register-user.js index ca8fb8e..62e0fb6 100644 --- a/d2m/actions/register-user.js +++ b/d2m/actions/register-user.js @@ -134,7 +134,7 @@ function hashProfileContent(content) { * 1. Join the sim to the room if needed * 2. Make an object of what the new room member state content would be, including uploading the profile picture if it hasn't been done before * 3. Compare against the previously known state content, which is helpfully stored in the database - * 4. If the state content has changes, send it to Matrix and update it in the database for next time + * 4. If the state content has changed, send it to Matrix and update it in the database for next time * @param {import("discord-api-types/v10").APIUser} user * @param {Omit} member * @returns {Promise} mxid of the updated sim diff --git a/d2m/converters/edit-to-changes.test.js b/d2m/converters/edit-to-changes.test.js index c0762c7..8c67f6a 100644 --- a/d2m/converters/edit-to-changes.test.js +++ b/d2m/converters/edit-to-changes.test.js @@ -97,6 +97,22 @@ test("edit2changes: remove caption from image", async t => { t.equal(promoteNextEvent, false) }) +test("edit2changes: change file type", async t => { + const {eventsToRedact, eventsToReplace, eventsToSend, promoteEvent, promoteNextEvent} = await editToChanges(data.message_update.changed_file_type, data.guild.general, {}) + t.deepEqual(eventsToRedact, ["$51f4yqHinwnSbPEQ9dCgoyy4qiIJSX0QYYVUnvwyTCJ"]) + t.deepEqual(eventsToSend, [{ + $type: "m.room.message", + body: "📝 Uploaded file: https://cdn.discordapp.com/attachments/112760669178241024/1141501302497615912/gaze_into_my_dark_mind.txt (20 MB)", + format: "org.matrix.custom.html", + formatted_body: "📝 Uploaded file: gaze_into_my_dark_mind.txt (20 MB)", + "m.mentions": {}, + msgtype: "m.text" + }]) + t.deepEqual(eventsToReplace, []) + t.equal(promoteEvent, null) + t.equal(promoteNextEvent, true) +}) + test("edit2changes: add caption back to that image", async t => { const {eventsToRedact, eventsToReplace, eventsToSend, promoteEvent, promoteNextEvent} = await editToChanges(data.message_update.added_caption_to_image, data.guild.general, {}) t.deepEqual(eventsToRedact, []) @@ -136,7 +152,6 @@ test("edit2changes: stickers and attachments are not changed, only the content c }]) }) - test("edit2changes: edit of reply to skull webp attachment with content", async t => { const {eventsToRedact, eventsToReplace, eventsToSend} = await editToChanges(data.message_update.edit_of_reply_to_skull_webp_attachment_with_content, data.guild.general, {}) t.deepEqual(eventsToRedact, []) diff --git a/m2d/converters/emoji-sheet.js b/m2d/converters/emoji-sheet.js index c271567..c05f45d 100644 --- a/m2d/converters/emoji-sheet.js +++ b/m2d/converters/emoji-sheet.js @@ -40,6 +40,7 @@ async function compositeMatrixEmojis(mxcs) { .resize(SIZE, SIZE, {fit: "contain", background: {r: 0, g: 0, b: 0, alpha: 0}}) .png({compressionLevel: 0}) .toBuffer((err, buffer, info) => { + /* c8 ignore next */ if (err) return reject(err) resolve({info, buffer}) }) @@ -73,6 +74,7 @@ async function compositeMatrixEmojis(mxcs) { } })) + // Calculate the size of the final composited image const totalWidth = Math.min(buffers.length, IMAGES_ACROSS) * SIZE const imagesDown = Math.ceil(buffers.length / IMAGES_ACROSS) const totalHeight = imagesDown * SIZE @@ -80,8 +82,15 @@ async function compositeMatrixEmojis(mxcs) { let left = 0, top = 0 for (const buffer of buffers) { if (Buffer.isBuffer(buffer)) { + // Composite the current buffer into the sprite sheet comp.push({left, top, input: buffer}) - ;(left += SIZE) + SIZE > RESULT_WIDTH && (left = 0, top += SIZE) + // The next buffer should be placed one slot to the right + left += SIZE + // If we're out of space to fit the entire next buffer there, wrap to the next line + if (left + SIZE > RESULT_WIDTH) { + left = 0 + top += SIZE + } } } diff --git a/m2d/converters/event-to-message.js b/m2d/converters/event-to-message.js index bd9c37a..8a68656 100644 --- a/m2d/converters/event-to-message.js +++ b/m2d/converters/event-to-message.js @@ -125,7 +125,7 @@ turndownService.addRule("emoji", { // Also guess a suitable emoji based on the ID (if available) or name let guess = null const guessedName = node.getAttribute("title").replace(/^:|:$/g, "") - for (const guild of discord?.guilds.values() || []) { + for (const guild of discord.guilds.values()) { /** @type {{name: string, id: string, animated: number}[]} */ // @ts-ignore const emojis = guild.emojis diff --git a/m2d/converters/event-to-message.test.js b/m2d/converters/event-to-message.test.js index ef7f65d..87a4b12 100644 --- a/m2d/converters/event-to-message.test.js +++ b/m2d/converters/event-to-message.test.js @@ -1,9 +1,11 @@ +const assert = require("assert").strict const {test} = require("supertape") const {eventToMessage} = require("./event-to-message") const data = require("../../test/data") const {MatrixServerError} = require("../../matrix/mreq") const {db, select} = require("../../passthrough") +/* c8 ignore next 7 */ function slow() { if (process.argv.includes("--slow")) { return test @@ -843,6 +845,7 @@ test("event2message: editing a rich reply to a sim user", async t => { }, data.guild.general, { api: { getEvent: (roomID, eventID) => { + assert.ok(eventID === "$Fxy8SMoJuTduwReVkHZ1uHif9EuvNx36Hg79cltiA04" || eventID === "$v_Gtr-bzv9IVlSLBO5DstzwmiDd-GSFaNfHX66IupV8") if (eventID === "$Fxy8SMoJuTduwReVkHZ1uHif9EuvNx36Hg79cltiA04") { eventsFetched.push("past") return mockGetEvent(t, "!fGgIymcYWOqjbSRUdV:cadence.moe", "$Fxy8SMoJuTduwReVkHZ1uHif9EuvNx36Hg79cltiA04", { @@ -870,8 +873,6 @@ test("event2message: editing a rich reply to a sim user", async t => { } } })(roomID, eventID) - } else { - throw new Error(`This test wasn't meant to fetch event ID: ${eventID}`) } } } @@ -1920,9 +1921,9 @@ slow()("event2message: all unknown chess emojis are reuploaded as a sprite sheet sender: "@cadence:cadence.moe", content: { msgtype: "m.text", - body: "testing :chess_good_move::chess_incorrect::chess_blund::chess_brilliant_move::chess_blundest::chess_draw_black:", + body: "testing :chess_good_move::chess_incorrect::chess_blund::chess_brilliant_move::chess_blundest::chess_draw_black::chess_good_move::chess_incorrect::chess_blund::chess_brilliant_move::chess_blundest::chess_draw_black:", format: "org.matrix.custom.html", - formatted_body: "testing \":chess_good_move:\"\":chess_incorrect:\"\":chess_blund:\"\":chess_brilliant_move:\"\":chess_blundest:\"\":chess_draw_black:\"" + formatted_body: "testing \":chess_good_move:\"\":chess_incorrect:\"\":chess_blund:\"\":chess_brilliant_move:\"\":chess_blundest:\"\":chess_draw_black:\"\":chess_good_move:\"\":chess_incorrect:\"\":chess_blund:\"\":chess_brilliant_move:\"\":chess_blundest:\"\":chess_draw_black:\"" }, event_id: "$Me6iE8C8CZyrDEOYYrXKSYRuuh_25Jj9kZaNrf7LKr4", room_id: "!maggESguZBqGBZtSnr:cadence.moe" diff --git a/m2d/converters/utils.test.js b/m2d/converters/utils.test.js index ae3159e..9d039fe 100644 --- a/m2d/converters/utils.test.js +++ b/m2d/converters/utils.test.js @@ -1,7 +1,7 @@ // @ts-check const {test} = require("supertape") -const {eventSenderIsFromDiscord} = require("./utils") +const {eventSenderIsFromDiscord, getEventIDHash} = require("./utils") test("sender type: matrix user", t => { t.notOk(eventSenderIsFromDiscord("@cadence:cadence.moe")) @@ -14,3 +14,12 @@ test("sender type: ooye bot", t => { test("sender type: ooye puppet", t => { t.ok(eventSenderIsFromDiscord("@_ooye_sheep:cadence.moe")) }) + +test("event hash: hash is the same each time", t => { + const eventID = "$example" + t.equal(getEventIDHash(eventID), getEventIDHash(eventID)) +}) + +test("event hash: hash is different for different inputs", t => { + t.notEqual(getEventIDHash("$Ij3qo7NxMA4VPexlAiIx2CB9JbsiGhJeyt-2OvkAUe1"), getEventIDHash("$Ij3qo7NxMA4VPexlAiIx2CB9JbsiGhJeyt-2OvkAUe2")) +}) diff --git a/package.json b/package.json index e9a42e2..e40e82c 100644 --- a/package.json +++ b/package.json @@ -48,6 +48,6 @@ "addbot": "node addbot.js", "test": "cross-env FORCE_COLOR=true supertape --no-check-assertions-count --format tap test/test.js | tap-dot", "test-slow": "cross-env FORCE_COLOR=true supertape --no-check-assertions-count --format tap test/test.js -- --slow | tap-dot", - "cover": "c8 --skip-full -r html -r text supertape --no-check-assertions-count --format fail test/test.js" + "cover": "c8 --skip-full -x db/migrations -x matrix/file.js -x matrix/api.js -x matrix/mreq.js -r html -r text supertape --no-check-assertions-count --format fail test/test.js -- --slow" } } diff --git a/test/data.js b/test/data.js index bcaf9c4..d6abc9d 100644 --- a/test/data.js +++ b/test/data.js @@ -1665,6 +1665,80 @@ module.exports = { tts: false, type: 0 }, + changed_file_type: { + attachments: [ + { + content_type: "text/plain", + filename: "gaze_into_my_dark_mind.txt", + size: 20102199, + url: "https://cdn.discordapp.com/attachments/112760669178241024/1141501302497615912/gaze_into_my_dark_mind.txt", + } + ], + author: { + avatar: "47db1be7ab77e1d812a4573177af0692", + avatar_decoration: null, + discriminator: "0", + global_name: "wing", + id: "112890272819507200", + public_flags: 0, + username: ".wing." + }, + channel_id: "112760669178241024", + components: [], + content: "", + edited_timestamp: "2023-08-17T00:13:18.620975+00:00", + embeds: [], + flags: 0, + guild_id: "112760669178241024", + id: "1141501302736695317", + member: { + avatar: null, + communication_disabled_until: null, + deaf: false, + flags: 0, + joined_at: "2015-11-08T12:25:38.461000+00:00", + mute: false, + nick: "windfucker", + pending: false, + premium_since: null, + roles: [ + "204427286542417920", + "118924814567211009", + "222168467627835392", + "265239342648131584", + "303273332248412160", + "303319030163439616", + "305775031223320577", + "318243902521868288", + "349185088157777920", + "378402925128712193", + "391076926573510656", + "230462991751970827", + "392141548932038658", + "397533096012152832", + "454567553738473472", + "482658335536185357", + "482860581670486028", + "495384759074160642", + "638988388740890635", + "764071315388629012", + "373336013109461013", + "872274377150980116", + "1034022405275910164", + "790724320824655873", + "1040735082610167858", + "1123730787653660742", + "1070177137367208036" + ] + }, + mention_everyone: false, + mention_roles: [], + mentions: [], + pinned: false, + timestamp: "2023-08-16T22:38:38.641000+00:00", + tts: false, + type: 0 + }, edited_content_with_sticker_and_attachments: { id: "1106366167788044450", type: 0,