diff --git a/package-lock.json b/package-lock.json
index ed438d0..eb07b4d 100644
--- a/package-lock.json
+++ b/package-lock.json
@@ -1,12 +1,12 @@
{
"name": "out-of-your-element",
- "version": "3.6.0",
+ "version": "3.5.1",
"lockfileVersion": 3,
"requires": true,
"packages": {
"": {
"name": "out-of-your-element",
- "version": "3.6.0",
+ "version": "3.5.1",
"license": "AGPL-3.0-or-later",
"dependencies": {
"@chriscdn/promise-semaphore": "^3.0.1",
diff --git a/package.json b/package.json
index 73fd43d..9dfd2a8 100644
--- a/package.json
+++ b/package.json
@@ -1,6 +1,6 @@
{
"name": "out-of-your-element",
- "version": "3.6.0",
+ "version": "3.5.1",
"description": "A bridge between Matrix and Discord",
"main": "index.js",
"repository": {
diff --git a/src/d2m/actions/send-message.js b/src/d2m/actions/send-message.js
index 5b3b4f3..8550d43 100644
--- a/src/d2m/actions/send-message.js
+++ b/src/d2m/actions/send-message.js
@@ -60,7 +60,8 @@ async function sendMessage(message, channel, guild, row) {
const detailedResultsMessage = await pollEnd.endPoll(message)
if (detailedResultsMessage) {
const threadParent = select("channel_room", "thread_parent", {channel_id: message.channel_id}).pluck().get()
- const {channelID, threadID} = dUtils.swapThreadID(message.channel_id, threadParent)
+ const channelID = threadParent ? threadParent : message.channel_id
+ const threadID = threadParent ? message.channel_id : undefined
sentResultsMessage = await channelWebhook.sendMessageWithWebhook(channelID, detailedResultsMessage, threadID)
}
}
diff --git a/src/d2m/actions/speedbump.js b/src/d2m/actions/speedbump.js
index 42e3a35..218f046 100644
--- a/src/d2m/actions/speedbump.js
+++ b/src/d2m/actions/speedbump.js
@@ -1,5 +1,6 @@
// @ts-check
+const DiscordTypes = require("discord-api-types/v10")
const passthrough = require("../../passthrough")
const {discord, select, db} = passthrough
@@ -69,18 +70,12 @@ async function doSpeedbump(messageID) {
* Check whether to slow down a message, and do it. After it passes the speedbump, return whether it's okay or if it's been deleted.
* @param {string} channelID
* @param {string} messageID
- * @param {string} [userID] if provided, only slow down the message when the user has used PK before
* @returns whether it was deleted, and data about the channel's (not thread's) speedbump
*/
-async function maybeDoSpeedbump(channelID, messageID, userID) {
- let row = select("channel_room", ["room_id", "thread_parent", "speedbump_id", "speedbump_webhook_id"], {channel_id: channelID}).get()
- if (row?.thread_parent) row = select("channel_room", ["room_id", "thread_parent", "speedbump_id", "speedbump_webhook_id"], {channel_id: row.thread_parent}).get() // webhooks belong to the channel, not the thread
- if (!row?.speedbump_webhook_id) return {affected: false, row: null} // channel not affected, no speedbump
- if (userID) {
- if (row.speedbump_webhook_id === userID) return {affected: false, row} // shortcut
- const userHasProxy = select("sim_proxy", "user_id", {proxy_owner_id: userID}).pluck().get()
- if (!userHasProxy) return {affected: false, row} // user has not used PK before, no speedbump
- }
+async function maybeDoSpeedbump(channelID, messageID) {
+ let row = select("channel_room", ["thread_parent", "speedbump_id", "speedbump_webhook_id"], {channel_id: channelID}).get()
+ if (row?.thread_parent) row = select("channel_room", ["thread_parent", "speedbump_id", "speedbump_webhook_id"], {channel_id: row.thread_parent}).get() // webhooks belong to the channel, not the thread
+ if (!row?.speedbump_webhook_id) return {affected: false, row: null} // not affected, no speedbump
const affected = await doSpeedbump(messageID)
return {affected, row} // maybe affected, and there is a speedbump
}
diff --git a/src/d2m/converters/message-to-event.js b/src/d2m/converters/message-to-event.js
index aeda572..7229d3d 100644
--- a/src/d2m/converters/message-to-event.js
+++ b/src/d2m/converters/message-to-event.js
@@ -265,9 +265,8 @@ function getFormattedInteraction(interaction, isThinkingInteraction) {
* @param {any} newEvents merge into events
* @param {any} events will be modified
* @param {boolean} forceSameMsgtype whether m.text may only be combined with m.text, etc
- * @param {boolean} [forceMerge] if true, must merge event, will error if it had to append
*/
-function mergeTextEvents(newEvents, events, forceSameMsgtype, forceMerge = false) {
+function mergeTextEvents(newEvents, events, forceSameMsgtype) {
let prev = events.at(-1)
for (const ne of newEvents) {
const isAllText = prev?.body && prev?.formatted_body && ["m.text", "m.notice"].includes(ne.msgtype) && ["m.text", "m.notice"].includes(prev?.msgtype)
@@ -279,8 +278,6 @@ function mergeTextEvents(newEvents, events, forceSameMsgtype, forceMerge = false
rep.addLine(ne.body, ne.formatted_body)
prev.body = rep.body
prev.formatted_body = rep.formattedBody
- } else if (forceMerge) {
- throw new Error("Unable to merge events")
} else {
events.push(ne)
}
@@ -557,7 +554,7 @@ async function messageToEvent(message, guild, options = {}, di) {
// Handling emojis that we don't know about. The emoji has to be present in the DB for it to be picked up in the emoji markdown converter.
// So we scan the message ahead of time for all its emojis and ensure they are in the DB.
- const emojiMatches = [...content.matchAll(/<(a?):([^:>]+):([0-9]+)>/g)]
+ const emojiMatches = [...content.matchAll(/<(a?):([^:>]{1,64}):([0-9]+)>/g)]
await Promise.all(emojiMatches.map(match => {
const id = match[3]
const name = match[2]
@@ -970,8 +967,7 @@ async function messageToEvent(message, guild, options = {}, di) {
// May only be a section accessory or in an action row (up to 5)
if (component.style === DiscordTypes.ButtonStyle.Link) {
assert(component.label) // required for Discord to validate link buttons
- const link = await transformContentMessageLinks(component.url)
- stack.msb.add(`[${component.label} ${link}] `, tag`${component.label} `)
+ stack.msb.add(`[${component.label} ${component.url}] `, tag`${component.label} `)
}
}
@@ -984,19 +980,7 @@ async function messageToEvent(message, guild, options = {}, di) {
const {body, formatted_body} = stack.msb.get()
if (body.trim().length) {
- // Create new message if Components V2 (cannot have regular content)
- if ((message.flags ?? 0) & DiscordTypes.MessageFlags.IsComponentsV2) {
- await addTextEvent(body, formatted_body, "m.text")
- }
- // Add to existing message if legacy components https://docs.discord.com/developers/components/reference#legacy-message-component-behavior
- else {
- mergeTextEvents([{
- msgtype: "m.text",
- body,
- format: "org.matrix.custom.html",
- formatted_body
- }], events, false, true)
- }
+ await addTextEvent(body, formatted_body, "m.text")
}
}
diff --git a/src/d2m/converters/message-to-event.test.components.js b/src/d2m/converters/message-to-event.test.components.js
index 1ef83c3..137b63b 100644
--- a/src/d2m/converters/message-to-event.test.components.js
+++ b/src/d2m/converters/message-to-event.test.components.js
@@ -1,7 +1,6 @@
const {test} = require("supertape")
const {messageToEvent} = require("./message-to-event")
const data = require("../../../test/data")
-const {mockGetEffectivePower} = require("../../matrix/utils.test")
test("message2event components: pk question mark output", async t => {
const events = await messageToEvent(data.message_with_components.pk_question_mark_response, data.guild.general, {})
@@ -78,24 +77,3 @@ test("message2event components: pk question mark output", async t => {
msgtype: "m.text",
}])
})
-
-test("message2event components: pk ping message legacy components", async t => {
- const events = await messageToEvent(data.message_with_components.pk_ping_components_v1, data.guild.general, {}, {
- api: {
- async getJoinedMembers() {
- return {joined: {}}
- },
- getEffectivePower: mockGetEffectivePower()
- }
- })
- t.deepEqual(events, [{
- $type: "m.room.message",
- msgtype: "m.text",
- body: "โญ cadence used `/๐ Ping author`"
- + "\nPsst, **Red** (@cadence.worm:), you have been pinged by @cadence.worm:."
- + "\n[Jump https://matrix.to/#/!TqlyQmifxGUggEmdBN:cadence.moe/$l9FMmsEbh9K0NUReeEpWOMZYGRlUOE8yLcm6P-TYHSM?via=cadence.moe] ",
- format: "org.matrix.custom.html",
- formatted_body: "
โญ cadence used /๐ Ping author
Psst, Red (@cadence.worm), you have been pinged by @cadence.worm.
Jump ",
- "m.mentions": {}
- }])
-})
diff --git a/src/d2m/event-dispatcher.js b/src/d2m/event-dispatcher.js
index 03ca72b..8101a03 100644
--- a/src/d2m/event-dispatcher.js
+++ b/src/d2m/event-dispatcher.js
@@ -313,7 +313,7 @@ module.exports = {
if (!createRoom.existsOrAutocreatable(channel, guild.id)) return // Check that the sending-to room exists or is autocreatable
- const {affected, row} = await speedbump.maybeDoSpeedbump(message.channel_id, message.id, message.author.id)
+ const {affected, row} = await speedbump.maybeDoSpeedbump(message.channel_id, message.id)
if (affected) return
// @ts-ignore
@@ -335,11 +335,13 @@ module.exports = {
if (dUtils.isEphemeralMessage(data)) return // Ephemeral messages are for the eyes of the receiver only!
// Edits need to go through the speedbump as well. If the message is delayed but the edit isn't, we don't have anything to edit from.
- const {affected, row} = await speedbump.maybeDoSpeedbump(data.channel_id, data.id, data.author.id)
+ const {affected, row} = await speedbump.maybeDoSpeedbump(data.channel_id, data.id)
if (affected) return
- // Check that the sending-to room exists, and deal with Eventual Consistency(TM)
- if (!await retrigger.waitForMessage(data.id)) return
+ if (!row) {
+ // Check that the sending-to room exists, and deal with Eventual Consistency(TM)
+ if (!await retrigger.waitForMessage(data.id)) return
+ }
/** @type {DiscordTypes.GatewayMessageCreateDispatchData} */
// @ts-ignore
diff --git a/src/discord/register-interactions.js b/src/discord/register-interactions.js
index 66012b4..e3d58c4 100644
--- a/src/discord/register-interactions.js
+++ b/src/discord/register-interactions.js
@@ -91,32 +91,40 @@ function registerInteractions() {
async function dispatchInteraction(interaction) {
const interactionId = interaction.data?.["custom_id"] || interaction.data?.["name"]
try {
- if (interactionId === "Matrix info") {
- await matrixInfo.interact(interaction)
- } else if (interactionId === "invite") {
- await invite.interact(interaction)
- } else if (interactionId === "invite_channel") {
- await invite.interactButton(interaction)
- } else if (interactionId === "Permissions") {
- await permissions.interact(interaction)
- } else if (interactionId === "permissions_edit") {
- await permissions.interactEdit(interaction)
- } else if (interactionId === "Responses") {
- /** @type {DiscordTypes.APIMessageApplicationCommandGuildInteraction} */ // @ts-ignore
- const messageInteraction = interaction
- if (select("poll", "message_id", {message_id: messageInteraction.data.target_id}).get()) {
- await pollResponses.interact(messageInteraction)
+ if (interaction.type === DiscordTypes.InteractionType.MessageComponent || interaction.type === DiscordTypes.InteractionType.ModalSubmit) {
+ // All we get is custom_id, don't know which context the button was clicked in.
+ // So we namespace these ourselves in the custom_id. Currently the only existing namespace is POLL_.
+ if (interaction.data.custom_id.startsWith("POLL_")) {
+ await poll.interact(interaction)
} else {
- await reactions.interact(messageInteraction)
+ throw new Error(`Unknown message component ${interaction.data.custom_id}`)
}
- } else if (interactionId === "ping") {
- await ping.interact(interaction)
- } else if (interactionId === "privacy") {
- await privacy.interact(interaction)
- } else if (interactionId.startsWith("POLL_")) {
- await poll.interact(interaction)
} else {
- throw new Error(`Unknown interaction ${interactionId}`)
+ if (interactionId === "Matrix info") {
+ await matrixInfo.interact(interaction)
+ } else if (interactionId === "invite") {
+ await invite.interact(interaction)
+ } else if (interactionId === "invite_channel") {
+ await invite.interactButton(interaction)
+ } else if (interactionId === "Permissions") {
+ await permissions.interact(interaction)
+ } else if (interactionId === "permissions_edit") {
+ await permissions.interactEdit(interaction)
+ } else if (interactionId === "Responses") {
+ /** @type {DiscordTypes.APIMessageApplicationCommandGuildInteraction} */ // @ts-ignore
+ const messageInteraction = interaction
+ if (select("poll", "message_id", {message_id: messageInteraction.data.target_id}).get()) {
+ await pollResponses.interact(messageInteraction)
+ } else {
+ await reactions.interact(messageInteraction)
+ }
+ } else if (interactionId === "ping") {
+ await ping.interact(interaction)
+ } else if (interactionId === "privacy") {
+ await privacy.interact(interaction)
+ } else {
+ throw new Error(`Unknown interaction ${interactionId}`)
+ }
}
} catch (e) {
let stackLines = null
diff --git a/src/discord/utils.js b/src/discord/utils.js
index 6fb0b43..0d400f1 100644
--- a/src/discord/utils.js
+++ b/src/discord/utils.js
@@ -182,18 +182,6 @@ function filterTo(xs, fn) {
return filtered
}
-/**
- * The parameters correspond to the columns of the channel_room table.
- * @param {string} rowChannelID thread ID, OR channel ID if there is no thread
- * @param {string | null | undefined} rowThreadParent channel ID if there is a thread
- */
-function swapThreadID(rowChannelID, rowThreadParent) {
- return {
- channelID: rowThreadParent ? rowThreadParent : rowChannelID,
- threadID: rowThreadParent ? rowChannelID : undefined
- }
-}
-
const supportedPlaintextPreviewExtensions = new Set([
"4d",
"abnf",
@@ -594,5 +582,4 @@ module.exports.timestampToSnowflakeInexact = timestampToSnowflakeInexact
module.exports.getPublicUrlForCdn = getPublicUrlForCdn
module.exports.howOldUnbridgedMessage = howOldUnbridgedMessage
module.exports.filterTo = filterTo
-module.exports.swapThreadID = swapThreadID
module.exports.supportedPlaintextPreviewExtensions = supportedPlaintextPreviewExtensions
diff --git a/src/m2d/actions/vote.js b/src/m2d/actions/vote.js
index 84f8cc7..926b957 100644
--- a/src/m2d/actions/vote.js
+++ b/src/m2d/actions/vote.js
@@ -1,12 +1,18 @@
// @ts-check
const Ty = require("../../types")
+const DiscordTypes = require("discord-api-types/v10")
+const {Readable} = require("stream")
const assert = require("assert").strict
+const crypto = require("crypto")
const passthrough = require("../../passthrough")
-const {sync, db, select} = passthrough
+const {sync, discord, db, select} = passthrough
-/** @type {import("../../discord/utils")} */
-const dUtils = sync.require("../../discord/utils")
+const {reg} = require("../../matrix/read-registration")
+/** @type {import("../../matrix/api")} */
+const api = sync.require("../../matrix/api")
+/** @type {import("../../matrix/utils")} */
+const utils = sync.require("../../matrix/utils")
/** @type {import("../converters/poll-components")} */
const pollComponents = sync.require("../converters/poll-components")
/** @type {import("./channel-webhook")} */
@@ -27,11 +33,10 @@ async function updateVote(event) {
// If poll was started on Matrix, the Discord version is using components, so we can update that to the current status
if (messageRow.source === 0) {
- const row = select("channel_room", ["channel_id", "thread_parent"], {room_id: event.room_id}).get()
- assert(row)
- const {channelID, threadID} = dUtils.swapThreadID(row.channel_id, row.thread_parent)
- await webhook.editMessageWithWebhook(channelID, messageID, pollComponents.getPollComponentsFromDatabase(messageID), threadID)
+ const channelID = select("channel_room", "channel_id", {room_id: event.room_id}).pluck().get()
+ assert(channelID)
+ await webhook.editMessageWithWebhook(channelID, messageID, pollComponents.getPollComponentsFromDatabase(messageID))
}
}
-module.exports.updateVote = updateVote
+module.exports.updateVote = updateVote
\ No newline at end of file
diff --git a/src/web/pug/guild.pug b/src/web/pug/guild.pug
index 7411a1e..9791ae3 100644
--- a/src/web/pug/guild.pug
+++ b/src/web/pug/guild.pug
@@ -122,7 +122,7 @@ block body
#role-add.s-popover(popover style="display: revert").ws2.px0.py4.bs-lg.overflow-visible
.s-popover--arrow.s-popover--arrow__tc
+add-roles-menu(guild, guild_id)
- p.fc-light.mb0.mt8 Matrix users will start with these roles. If your main channels are gated by a role, use this to let Matrix users skip the gate.
+ p.fc-medium.mb0.mt8 Matrix users will start with these roles. If your main channels are gated by a role, use this to let Matrix users skip the gate.
h3.mt32.fs-category Features
.s-card.d-grid.px0.g16
@@ -191,14 +191,14 @@ block body
label.s-btn.s-btn__muted.ta-left.truncate(for=channel.id)
+discord(channel, true, "Announcement")
else
- .s-empty-state.p8 No Discord channels available.
+ .s-empty-state.p8 All Discord channels are linked.
.fl-grow1.s-btn-group.fd-column.w30
each room in unlinkedRooms
input.s-btn--radio(type="radio" name="matrix" required id=room.room_id value=room.room_id)
label.s-btn.s-btn__muted.ta-left.truncate(for=room.room_id)
+matrix(room, true)
else
- .s-empty-state.p8 No Matrix rooms available.
+ .s-empty-state.p8 All Matrix rooms are linked.
input(type="hidden" name="guild_id" value=guild_id)
div
button.s-btn.s-btn__icon.s-btn__filled#link-button
diff --git a/test/data.js b/test/data.js
index eab9a63..f3092bc 100644
--- a/test/data.js
+++ b/test/data.js
@@ -5473,189 +5473,6 @@ module.exports = {
content: '-# Original Message ID: 1466556003645657118 ยท '
}
]
- },
- pk_ping_components_v1: {
- type: 23,
- content: "Psst, **Red** (<@772659086046658620>), you have been pinged by <@772659086046658620>.",
- mentions: [
- {
- id: "772659086046658620",
- username: "cadence.worm",
- avatar: "466df0c98b1af1e1388f595b4c1ad1b9",
- discriminator: "0",
- public_flags: 0,
- flags: 0,
- banner: null,
- accent_color: null,
- global_name: "cadence",
- avatar_decoration_data: null,
- collectibles: null,
- display_name_styles: null,
- banner_color: null,
- clan: {
- identity_guild_id: "532245108070809601",
- identity_enabled: true,
- tag: "doll",
- badge: "dba08126b4e810a0e096cc7cd5bc37f0"
- },
- primary_guild: {
- identity_guild_id: "532245108070809601",
- identity_enabled: true,
- tag: "doll",
- badge: "dba08126b4e810a0e096cc7cd5bc37f0"
- }
- }
- ],
- mention_roles: [],
- attachments: [],
- embeds: [],
- timestamp: "2026-03-25T07:07:02.626000+00:00",
- edited_timestamp: null,
- flags: 0,
- components: [
- {
- type: 1,
- id: 1,
- components: [
- {
- type: 2,
- id: 2,
- style: 5,
- label: "Jump",
- url: "https://discord.com/channels/1160893336324931584/1160894080998461480/1440549403667468320"
- }
- ]
- }
- ],
- id: "1486260105908457653",
- channel_id: "1160894080998461480",
- author: {
- id: "466378653216014359",
- username: "PluralKit",
- avatar: "b78ef67a081737a830b60aa47d9ebcd9",
- discriminator: "4020",
- public_flags: 65536,
- flags: 65536,
- bot: true,
- banner: null,
- accent_color: null,
- global_name: null,
- avatar_decoration_data: null,
- collectibles: null,
- display_name_styles: null,
- banner_color: null,
- clan: null,
- primary_guild: null
- },
- pinned: false,
- mention_everyone: false,
- tts: false,
- application_id: "466378653216014359",
- interaction: {
- id: "1486260103928614932",
- type: 2,
- name: "๐ Ping author",
- user: {
- id: "772659086046658620",
- username: "cadence.worm",
- avatar: "466df0c98b1af1e1388f595b4c1ad1b9",
- discriminator: "0",
- public_flags: 0,
- flags: 0,
- banner: null,
- accent_color: null,
- global_name: "cadence",
- avatar_decoration_data: null,
- collectibles: null,
- display_name_styles: null,
- banner_color: null,
- clan: {
- identity_guild_id: "532245108070809601",
- identity_enabled: true,
- tag: "doll",
- badge: "dba08126b4e810a0e096cc7cd5bc37f0"
- },
- primary_guild: {
- identity_guild_id: "532245108070809601",
- identity_enabled: true,
- tag: "doll",
- badge: "dba08126b4e810a0e096cc7cd5bc37f0"
- }
- }
- },
- webhook_id: "466378653216014359",
- message_reference: {
- type: 0,
- channel_id: "1160894080998461480",
- message_id: "1440549403667468320",
- guild_id: "1160893336324931584"
- },
- interaction_metadata: {
- id: "1486260103928614932",
- type: 2,
- user: {
- id: "772659086046658620",
- username: "cadence.worm",
- avatar: "466df0c98b1af1e1388f595b4c1ad1b9",
- discriminator: "0",
- public_flags: 0,
- flags: 0,
- banner: null,
- accent_color: null,
- global_name: "cadence",
- avatar_decoration_data: null,
- collectibles: null,
- display_name_styles: null,
- banner_color: null,
- clan: {
- identity_guild_id: "532245108070809601",
- identity_enabled: true,
- tag: "doll",
- badge: "dba08126b4e810a0e096cc7cd5bc37f0"
- },
- primary_guild: {
- identity_guild_id: "532245108070809601",
- identity_enabled: true,
- tag: "doll",
- badge: "dba08126b4e810a0e096cc7cd5bc37f0"
- }
- },
- authorizing_integration_owners: { "0": "1160893336324931584" },
- name: "๐ Ping author",
- command_type: 3,
- target_message_id: "1440549403667468320"
- },
- referenced_message: {
- type: 0,
- content: "test",
- mentions: [],
- mention_roles: [],
- attachments: [],
- embeds: [],
- timestamp: "2025-11-19T03:49:01.948000+00:00",
- edited_timestamp: null,
- flags: 0,
- components: [],
- id: "1440549403667468320",
- channel_id: "1160894080998461480",
- author: {
- id: "1195662438662680720",
- username: "special name",
- avatar: "a82347890f2739e5880cd82b8c1a708e",
- discriminator: "0000",
- public_flags: 0,
- flags: 0,
- bot: true,
- global_name: null,
- clan: null,
- primary_guild: null
- },
- pinned: false,
- mention_everyone: false,
- tts: false,
- application_id: "466378653216014359",
- webhook_id: "1195662438662680720"
- }
}
},
message_update: {
diff --git a/test/ooye-test-data.sql b/test/ooye-test-data.sql
index 1662320..8dd71cd 100644
--- a/test/ooye-test-data.sql
+++ b/test/ooye-test-data.sql
@@ -95,8 +95,7 @@ WITH a (message_id, channel_id) AS (VALUES
('1381212840957972480', '112760669178241024'),
('1401760355339862066', '112760669178241024'),
('1439351590262800565', '1438284564815548418'),
-('1404133238414376971', '112760669178241024'),
-('1440549403667468320', '1160894080998461480'))
+('1404133238414376971', '112760669178241024'))
SELECT message_id, max(historical_room_index) as historical_room_index FROM a INNER JOIN historical_channel_room ON historical_channel_room.reference_channel_id = a.channel_id GROUP BY message_id;
INSERT INTO event_message (event_id, event_type, event_subtype, message_id, part, reaction_part, source) VALUES
@@ -144,8 +143,7 @@ INSERT INTO event_message (event_id, event_type, event_subtype, message_id, part
('$7P2O_VTQNHvavX5zNJ35DV-dbJB1Ag80tGQP_JzGdhk', 'm.room.message', 'm.text', '1401760355339862066', 0, 0, 0),
('$ielAnR6geu0P1Tl5UXfrbxlIf-SV9jrNprxrGXP3v7M', 'm.room.message', 'm.image', '1439351590262800565', 0, 0, 0),
('$uUKLcTQvik5tgtTGDKuzn0Ci4zcCvSoUcYn2X7mXm9I', 'm.room.message', 'm.text', '1404133238414376971', 0, 1, 1),
-('$LhmoWWvYyn5_AHkfb6FaXmLI6ZOC1kloql5P40YDmIk', 'm.room.message', 'm.notice', '1404133238414376971', 1, 0, 1),
-('$l9FMmsEbh9K0NUReeEpWOMZYGRlUOE8yLcm6P-TYHSM', 'm.room.message', 'm.text', '1440549403667468320', 0, 0, 1);
+('$LhmoWWvYyn5_AHkfb6FaXmLI6ZOC1kloql5P40YDmIk', 'm.room.message', 'm.notice', '1404133238414376971', 1, 0, 1);
INSERT INTO file (discord_url, mxc_url) VALUES
('https://cdn.discordapp.com/attachments/497161332244742154/1124628646431297546/image.png', 'mxc://cadence.moe/qXoZktDqNtEGuOCZEADAMvhM'),