Add new WHERE feature to my funny orm
This commit is contained in:
parent
28abdac5b6
commit
475cd5b724
30 changed files with 149 additions and 105 deletions
|
@ -21,7 +21,7 @@ async function addReaction(data) {
|
||||||
const user = data.member?.user
|
const user = data.member?.user
|
||||||
assert.ok(user && user.username)
|
assert.ok(user && user.username)
|
||||||
|
|
||||||
const parentID = select("event_message", "event_id", "WHERE message_id = ? AND part = 0").pluck().get(data.message_id) // 0 = primary
|
const parentID = select("event_message", "event_id", {message_id: data.message_id, part: 0}).pluck().get() // 0 = primary
|
||||||
if (!parentID) return // Nothing can be done if the parent message was never bridged.
|
if (!parentID) return // Nothing can be done if the parent message was never bridged.
|
||||||
assert.equal(typeof parentID, "string")
|
assert.equal(typeof parentID, "string")
|
||||||
|
|
||||||
|
|
|
@ -15,7 +15,7 @@ const api = sync.require("../../matrix/api")
|
||||||
* @param {import("discord-api-types/v10").APIThreadChannel} thread
|
* @param {import("discord-api-types/v10").APIThreadChannel} thread
|
||||||
*/
|
*/
|
||||||
async function announceThread(parentRoomID, threadRoomID, thread) {
|
async function announceThread(parentRoomID, threadRoomID, thread) {
|
||||||
const creatorMxid = select("sim", "mxid", "WHERE user_id = ?").pluck().get(thread.owner_id)
|
const creatorMxid = select("sim", "mxid", {user_id: thread.owner_id}).pluck().get()
|
||||||
|
|
||||||
const content = await threadToAnnouncement.threadToAnnouncement(parentRoomID, threadRoomID, creatorMxid, thread, {api})
|
const content = await threadToAnnouncement.threadToAnnouncement(parentRoomID, threadRoomID, creatorMxid, thread, {api})
|
||||||
|
|
||||||
|
|
|
@ -71,7 +71,7 @@ async function channelToKState(channel, guild) {
|
||||||
const spaceID = await createSpace.ensureSpace(guild)
|
const spaceID = await createSpace.ensureSpace(guild)
|
||||||
assert.ok(typeof spaceID === "string")
|
assert.ok(typeof spaceID === "string")
|
||||||
|
|
||||||
const row = select("channel_room", ["nick", "custom_avatar"], "WHERE channel_id = ?").get(channel.id)
|
const row = select("channel_room", ["nick", "custom_avatar"], {channel_id: channel.id}).get()
|
||||||
const customName = row?.nick
|
const customName = row?.nick
|
||||||
const customAvatar = row?.custom_avatar
|
const customAvatar = row?.custom_avatar
|
||||||
const [convertedName, convertedTopic] = convertNameAndTopic(channel, guild, customName)
|
const [convertedName, convertedTopic] = convertNameAndTopic(channel, guild, customName)
|
||||||
|
@ -248,7 +248,7 @@ async function _syncRoom(channelID, shouldActuallySync) {
|
||||||
await inflightRoomCreate.get(channelID) // just waiting, and then doing a new db query afterwards, is the simplest way of doing it
|
await inflightRoomCreate.get(channelID) // just waiting, and then doing a new db query afterwards, is the simplest way of doing it
|
||||||
}
|
}
|
||||||
|
|
||||||
const existing = select("channel_room", ["room_id", "thread_parent"], "WHERE channel_id = ?").get(channelID)
|
const existing = select("channel_room", ["room_id", "thread_parent"], {channel_id: channelID}).get()
|
||||||
|
|
||||||
if (!existing) {
|
if (!existing) {
|
||||||
const creation = (async () => {
|
const creation = (async () => {
|
||||||
|
@ -308,9 +308,9 @@ async function _unbridgeRoom(channelID) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function unbridgeDeletedChannel(channelID, guildID) {
|
async function unbridgeDeletedChannel(channelID, guildID) {
|
||||||
const roomID = select("channel_room", "room_id", "WHERE channel_id = ?").pluck().get(channelID)
|
const roomID = select("channel_room", "room_id", {channel_id: channelID}).pluck().get()
|
||||||
assert.ok(roomID)
|
assert.ok(roomID)
|
||||||
const spaceID = select("guild_space", "space_id", "WHERE guild_id = ?").pluck().get(guildID)
|
const spaceID = select("guild_space", "space_id", {guild_id: guildID}).pluck().get()
|
||||||
assert.ok(spaceID)
|
assert.ok(spaceID)
|
||||||
|
|
||||||
// remove room from being a space member
|
// remove room from being a space member
|
||||||
|
|
|
@ -86,7 +86,7 @@ async function _syncSpace(guild, shouldActuallySync) {
|
||||||
await inflightSpaceCreate.get(guild.id) // just waiting, and then doing a new db query afterwards, is the simplest way of doing it
|
await inflightSpaceCreate.get(guild.id) // just waiting, and then doing a new db query afterwards, is the simplest way of doing it
|
||||||
}
|
}
|
||||||
|
|
||||||
const spaceID = select("guild_space", "space_id", "WHERE guild_id = ?").pluck().get(guild.id)
|
const spaceID = select("guild_space", "space_id", {guild_id: guild.id}).pluck().get()
|
||||||
|
|
||||||
if (!spaceID) {
|
if (!spaceID) {
|
||||||
const creation = (async () => {
|
const creation = (async () => {
|
||||||
|
@ -117,7 +117,7 @@ async function _syncSpace(guild, shouldActuallySync) {
|
||||||
const newAvatarState = spaceDiff["m.room.avatar/"]
|
const newAvatarState = spaceDiff["m.room.avatar/"]
|
||||||
if (guild.icon && newAvatarState?.url) {
|
if (guild.icon && newAvatarState?.url) {
|
||||||
// don't try to update rooms with custom avatars though
|
// don't try to update rooms with custom avatars though
|
||||||
const roomsWithCustomAvatars = select("channel_room", "room_id", "WHERE custom_avatar IS NOT NULL").pluck().all()
|
const roomsWithCustomAvatars = select("channel_room", "room_id", {}, "WHERE custom_avatar IS NOT NULL").pluck().all()
|
||||||
|
|
||||||
const childRooms = ks.kstateToState(spaceKState).filter(({type, state_key, content}) => {
|
const childRooms = ks.kstateToState(spaceKState).filter(({type, state_key, content}) => {
|
||||||
return type === "m.space.child" && "via" in content && !roomsWithCustomAvatars.includes(state_key)
|
return type === "m.space.child" && "via" in content && !roomsWithCustomAvatars.includes(state_key)
|
||||||
|
@ -159,7 +159,7 @@ async function syncSpaceFully(guildID) {
|
||||||
const guild = discord.guilds.get(guildID)
|
const guild = discord.guilds.get(guildID)
|
||||||
assert.ok(guild)
|
assert.ok(guild)
|
||||||
|
|
||||||
const spaceID = select("guild_space", "space_id", "WHERE guild_id = ?").pluck().get(guildID)
|
const spaceID = select("guild_space", "space_id", {guild_id: guildID}).pluck().get()
|
||||||
|
|
||||||
const guildKState = await guildToKState(guild)
|
const guildKState = await guildToKState(guild)
|
||||||
|
|
||||||
|
@ -180,7 +180,7 @@ async function syncSpaceFully(guildID) {
|
||||||
}).map(({state_key}) => state_key)
|
}).map(({state_key}) => state_key)
|
||||||
|
|
||||||
for (const roomID of childRooms) {
|
for (const roomID of childRooms) {
|
||||||
const channelID = select("channel_room", "channel_id", "WHERE room_id = ?").pluck().get(roomID)
|
const channelID = select("channel_room", "channel_id", {room_id: roomID}).pluck().get()
|
||||||
if (!channelID) continue
|
if (!channelID) continue
|
||||||
if (discord.channels.has(channelID)) {
|
if (discord.channels.has(channelID)) {
|
||||||
await createRoom.syncRoom(channelID)
|
await createRoom.syncRoom(channelID)
|
||||||
|
@ -198,7 +198,7 @@ async function syncSpaceFully(guildID) {
|
||||||
async function syncSpaceExpressions(data) {
|
async function syncSpaceExpressions(data) {
|
||||||
// No need for kstate here. Each of these maps to a single state event, which will always overwrite what was there before. I can just send the state event.
|
// No need for kstate here. Each of these maps to a single state event, which will always overwrite what was there before. I can just send the state event.
|
||||||
|
|
||||||
const spaceID = select("guild_space", "space_id", "WHERE guild_id = ?").pluck().get(data.guild_id)
|
const spaceID = select("guild_space", "space_id", {guild_id: data.guild_id}).pluck().get()
|
||||||
if (!spaceID) return
|
if (!spaceID) return
|
||||||
|
|
||||||
if ("emojis" in data && data.emojis.length) {
|
if ("emojis" in data && data.emojis.length) {
|
||||||
|
|
|
@ -9,10 +9,10 @@ const api = sync.require("../../matrix/api")
|
||||||
* @param {import("discord-api-types/v10").GatewayMessageDeleteDispatchData} data
|
* @param {import("discord-api-types/v10").GatewayMessageDeleteDispatchData} data
|
||||||
*/
|
*/
|
||||||
async function deleteMessage(data) {
|
async function deleteMessage(data) {
|
||||||
const roomID = select("channel_room", "room_id", "WHERE channel_id = ?").pluck().get(data.channel_id)
|
const roomID = select("channel_room", "room_id", {channel_id: data.channel_id}).pluck().get()
|
||||||
if (!roomID) return
|
if (!roomID) return
|
||||||
|
|
||||||
const eventsToRedact = select("event_message", "event_id", "WHERE message_id = ?").pluck().all(data.id)
|
const eventsToRedact = select("event_message", "event_id", {message_id: data.id}).pluck().all()
|
||||||
for (const eventID of eventsToRedact) {
|
for (const eventID of eventsToRedact) {
|
||||||
// Unfortunately, we can't specify a sender to do the redaction as, unless we find out that info via the audit logs
|
// Unfortunately, we can't specify a sender to do the redaction as, unless we find out that info via the audit logs
|
||||||
await api.redactEvent(roomID, eventID)
|
await api.redactEvent(roomID, eventID)
|
||||||
|
|
|
@ -51,7 +51,7 @@ async function createSim(user) {
|
||||||
*/
|
*/
|
||||||
async function ensureSim(user) {
|
async function ensureSim(user) {
|
||||||
let mxid = null
|
let mxid = null
|
||||||
const existing = select("sim", "mxid", "WHERE user_id = ?").pluck().get(user.id)
|
const existing = select("sim", "mxid", {user_id: user.id}).pluck().get()
|
||||||
if (existing) {
|
if (existing) {
|
||||||
mxid = existing
|
mxid = existing
|
||||||
} else {
|
} else {
|
||||||
|
@ -74,7 +74,7 @@ async function ensureSimJoined(user, roomID) {
|
||||||
const mxid = await ensureSim(user)
|
const mxid = await ensureSim(user)
|
||||||
|
|
||||||
// Ensure joined
|
// Ensure joined
|
||||||
const existing = select("sim_member", "mxid", "WHERE room_id = ? AND mxid = ?").pluck().get(roomID, mxid)
|
const existing = select("sim_member", "mxid", {room_id: roomID, mxid}).pluck().get()
|
||||||
if (!existing) {
|
if (!existing) {
|
||||||
try {
|
try {
|
||||||
await api.inviteToRoom(roomID, mxid)
|
await api.inviteToRoom(roomID, mxid)
|
||||||
|
@ -143,7 +143,7 @@ async function syncUser(user, member, guildID, roomID) {
|
||||||
const mxid = await ensureSimJoined(user, roomID)
|
const mxid = await ensureSimJoined(user, roomID)
|
||||||
const content = await memberToStateContent(user, member, guildID)
|
const content = await memberToStateContent(user, member, guildID)
|
||||||
const currentHash = hashProfileContent(content)
|
const currentHash = hashProfileContent(content)
|
||||||
const existingHash = select("sim_member", "hashed_profile_content", "WHERE room_id = ? AND mxid = ?").safeIntegers().pluck().get(roomID, mxid)
|
const existingHash = select("sim_member", "hashed_profile_content", {room_id: roomID, mxid}).safeIntegers().pluck().get()
|
||||||
// only do the actual sync if the hash has changed since we last looked
|
// only do the actual sync if the hash has changed since we last looked
|
||||||
if (existingHash !== currentHash) {
|
if (existingHash !== currentHash) {
|
||||||
await api.sendState(roomID, "m.room.member", mxid, content, mxid)
|
await api.sendState(roomID, "m.room.member", mxid, content, mxid)
|
||||||
|
@ -153,9 +153,9 @@ async function syncUser(user, member, guildID, roomID) {
|
||||||
}
|
}
|
||||||
|
|
||||||
async function syncAllUsersInRoom(roomID) {
|
async function syncAllUsersInRoom(roomID) {
|
||||||
const mxids = select("sim_member", "mxid", "WHERE room_id = ?").pluck().all(roomID)
|
const mxids = select("sim_member", "mxid", {room_id: roomID}).pluck().all()
|
||||||
|
|
||||||
const channelID = select("channel_room", "channel_id", "WHERE room_id = ?").pluck().get(roomID)
|
const channelID = select("channel_room", "channel_id", {room_id: roomID}).pluck().get()
|
||||||
assert.ok(typeof channelID === "string")
|
assert.ok(typeof channelID === "string")
|
||||||
|
|
||||||
/** @ts-ignore @type {import("discord-api-types/v10").APIGuildChannel} */
|
/** @ts-ignore @type {import("discord-api-types/v10").APIGuildChannel} */
|
||||||
|
@ -164,7 +164,7 @@ async function syncAllUsersInRoom(roomID) {
|
||||||
assert.ok(typeof guildID === "string")
|
assert.ok(typeof guildID === "string")
|
||||||
|
|
||||||
for (const mxid of mxids) {
|
for (const mxid of mxids) {
|
||||||
const userID = select("sim", "user_id", "WHERE mxid = ?").pluck().get(mxid)
|
const userID = select("sim", "user_id", {mxid}).pluck().get()
|
||||||
assert.ok(typeof userID === "string")
|
assert.ok(typeof userID === "string")
|
||||||
|
|
||||||
/** @ts-ignore @type {Required<import("discord-api-types/v10").APIGuildMember>} */
|
/** @ts-ignore @type {Required<import("discord-api-types/v10").APIGuildMember>} */
|
||||||
|
|
|
@ -18,9 +18,9 @@ const emoji = sync.require("../../m2d/converters/emoji")
|
||||||
* @param {import("discord-api-types/v10").GatewayMessageReactionRemoveDispatchData} data
|
* @param {import("discord-api-types/v10").GatewayMessageReactionRemoveDispatchData} data
|
||||||
*/
|
*/
|
||||||
async function removeReaction(data) {
|
async function removeReaction(data) {
|
||||||
const roomID = select("channel_room", "room_id", "WHERE channel_id = ?").pluck().get(data.channel_id)
|
const roomID = select("channel_room", "room_id", {channel_id: data.channel_id}).pluck().get()
|
||||||
if (!roomID) return
|
if (!roomID) return
|
||||||
const eventIDForMessage = select("event_message", "event_id", "WHERE message_id = ? AND part = 0").pluck().get(data.message_id)
|
const eventIDForMessage = select("event_message", "event_id", {message_id: data.message_id, part: 0}).pluck().get()
|
||||||
if (!eventIDForMessage) return
|
if (!eventIDForMessage) return
|
||||||
|
|
||||||
/** @type {Ty.Pagination<Ty.Event.Outer<Ty.Event.M_Reaction>>} */
|
/** @type {Ty.Pagination<Ty.Event.Outer<Ty.Event.M_Reaction>>} */
|
||||||
|
@ -42,7 +42,7 @@ async function removeReaction(data) {
|
||||||
}
|
}
|
||||||
if (!lookingAtMatrixReaction && !wantToRemoveMatrixReaction) {
|
if (!lookingAtMatrixReaction && !wantToRemoveMatrixReaction) {
|
||||||
// We are removing a Discord user's reaction, so we just make the sim user remove it.
|
// We are removing a Discord user's reaction, so we just make the sim user remove it.
|
||||||
const mxid = select("sim", "mxid", "WHERE user_id = ?").pluck().get(data.user_id)
|
const mxid = select("sim", "mxid", {user_id: data.user_id}).pluck().get()
|
||||||
if (mxid === event.sender) {
|
if (mxid === event.sender) {
|
||||||
await api.redactEvent(roomID, event.event_id, mxid)
|
await api.redactEvent(roomID, event.event_id, mxid)
|
||||||
}
|
}
|
||||||
|
@ -55,9 +55,9 @@ async function removeReaction(data) {
|
||||||
* @param {import("discord-api-types/v10").GatewayMessageReactionRemoveEmojiDispatchData} data
|
* @param {import("discord-api-types/v10").GatewayMessageReactionRemoveEmojiDispatchData} data
|
||||||
*/
|
*/
|
||||||
async function removeEmojiReaction(data) {
|
async function removeEmojiReaction(data) {
|
||||||
const roomID = select("channel_room", "room_id", "WHERE channel_id = ?").pluck().get(data.channel_id)
|
const roomID = select("channel_room", "room_id", {channel_id: data.channel_id}).pluck().get()
|
||||||
if (!roomID) return
|
if (!roomID) return
|
||||||
const eventIDForMessage = select("event_message", "event_id", "WHERE message_id = ? AND part = 0").pluck().get(data.message_id)
|
const eventIDForMessage = select("event_message", "event_id", {message_id: data.message_id, part: 0}).pluck().get()
|
||||||
if (!eventIDForMessage) return
|
if (!eventIDForMessage) return
|
||||||
|
|
||||||
/** @type {Ty.Pagination<Ty.Event.Outer<Ty.Event.M_Reaction>>} */
|
/** @type {Ty.Pagination<Ty.Event.Outer<Ty.Event.M_Reaction>>} */
|
||||||
|
@ -79,9 +79,9 @@ async function removeEmojiReaction(data) {
|
||||||
* @param {import("discord-api-types/v10").GatewayMessageReactionRemoveAllDispatchData} data
|
* @param {import("discord-api-types/v10").GatewayMessageReactionRemoveAllDispatchData} data
|
||||||
*/
|
*/
|
||||||
async function removeAllReactions(data) {
|
async function removeAllReactions(data) {
|
||||||
const roomID = select("channel_room", "room_id", "WHERE channel_id = ?").pluck().get(data.channel_id)
|
const roomID = select("channel_room", "room_id", {channel_id: data.channel_id}).pluck().get()
|
||||||
if (!roomID) return
|
if (!roomID) return
|
||||||
const eventIDForMessage = select("event_message", "event_id", "WHERE message_id = ? AND part = 0").pluck().get(data.message_id)
|
const eventIDForMessage = select("event_message", "event_id", {message_id: data.message_id, part: 0}).pluck().get()
|
||||||
if (!eventIDForMessage) return
|
if (!eventIDForMessage) return
|
||||||
|
|
||||||
/** @type {Ty.Pagination<Ty.Event.Outer<Ty.Event.M_Reaction>>} */
|
/** @type {Ty.Pagination<Ty.Event.Outer<Ty.Event.M_Reaction>>} */
|
||||||
|
|
|
@ -1,9 +1,9 @@
|
||||||
// @ts-check
|
// @ts-check
|
||||||
|
|
||||||
const assert = require("assert")
|
const assert = require("assert").strict
|
||||||
|
|
||||||
const passthrough = require("../../passthrough")
|
const passthrough = require("../../passthrough")
|
||||||
const {discord, sync, db, select} = passthrough
|
const {discord, sync, db, select, from} = passthrough
|
||||||
/** @type {import("./message-to-event")} */
|
/** @type {import("./message-to-event")} */
|
||||||
const messageToEvent = sync.require("../converters/message-to-event")
|
const messageToEvent = sync.require("../converters/message-to-event")
|
||||||
/** @type {import("../actions/register-user")} */
|
/** @type {import("../actions/register-user")} */
|
||||||
|
@ -21,15 +21,12 @@ const createRoom = sync.require("../actions/create-room")
|
||||||
async function editToChanges(message, guild, api) {
|
async function editToChanges(message, guild, api) {
|
||||||
// Figure out what events we will be replacing
|
// Figure out what events we will be replacing
|
||||||
|
|
||||||
const roomID = select("channel_room", "room_id", "WHERE channel_id = ?").pluck().get(message.channel_id)
|
const roomID = select("channel_room", "room_id", {channel_id: message.channel_id}).pluck().get()
|
||||||
let senderMxid = select("sim", "mxid", "WHERE user_id = ?").pluck().get(message.author.id) || null
|
assert(roomID)
|
||||||
if (senderMxid) {
|
/** @type {string?} Null if we don't have a sender in the room, which will happen if it's a webhook's message. The bridge bot will do the edit instead. */
|
||||||
const senderIsInRoom = select("sim_member", "mxid", "WHERE room_id = ? AND mxid = ?").get(roomID, senderMxid)
|
const senderMxid = from("sim").join("sim_member", "mxid").where({user_id: message.author.id}).pluck("mxid").get() || null
|
||||||
if (!senderIsInRoom) {
|
|
||||||
senderMxid = null // just send as ooye bot
|
const oldEventRows = select("event_message", ["event_id", "event_type", "event_subtype", "part"], {message_id: message.id}).all()
|
||||||
}
|
|
||||||
}
|
|
||||||
const oldEventRows = select("event_message", ["event_id", "event_type", "event_subtype", "part"], "WHERE message_id = ?").all(message.id)
|
|
||||||
|
|
||||||
// Figure out what we will be replacing them with
|
// Figure out what we will be replacing them with
|
||||||
|
|
||||||
|
|
|
@ -14,7 +14,7 @@ async function emojiToKey(emoji) {
|
||||||
let key
|
let key
|
||||||
if (emoji.id) {
|
if (emoji.id) {
|
||||||
// Custom emoji
|
// Custom emoji
|
||||||
const mxc = select("emoji", "mxc_url", "WHERE id = ?").pluck().get(emoji.id)
|
const mxc = select("emoji", "mxc_url", {emoji_id: emoji.id}).pluck().get(emoji.id)
|
||||||
if (mxc) {
|
if (mxc) {
|
||||||
// The custom emoji is registered and we should send it
|
// The custom emoji is registered and we should send it
|
||||||
key = mxc
|
key = mxc
|
||||||
|
|
|
@ -38,7 +38,7 @@ const Rlottie = (async () => {
|
||||||
* @returns {Promise<{mxc_url: string, info: typeof INFO}>}
|
* @returns {Promise<{mxc_url: string, info: typeof INFO}>}
|
||||||
*/
|
*/
|
||||||
async function convert(stickerItem) {
|
async function convert(stickerItem) {
|
||||||
const existingMxc = select("lottie", "mxc_url", "WHERE sticker_id = ?").pluck().get(stickerItem.id)
|
const existingMxc = select("lottie", "mxc_url", {sticker_id: stickerItem.id}).pluck().get()
|
||||||
if (existingMxc) return {mxc_url: existingMxc, info: INFO}
|
if (existingMxc) return {mxc_url: existingMxc, info: INFO}
|
||||||
const r = await Rlottie
|
const r = await Rlottie
|
||||||
const res = await fetch(file.DISCORD_IMAGES_BASE + file.sticker(stickerItem))
|
const res = await fetch(file.DISCORD_IMAGES_BASE + file.sticker(stickerItem))
|
||||||
|
|
|
@ -19,7 +19,7 @@ function getDiscordParseCallbacks(message, useHTML) {
|
||||||
return {
|
return {
|
||||||
/** @param {{id: string, type: "discordUser"}} node */
|
/** @param {{id: string, type: "discordUser"}} node */
|
||||||
user: node => {
|
user: node => {
|
||||||
const mxid = select("sim", "mxid", "WHERE user_id = ?").pluck().get(node.id)
|
const mxid = select("sim", "mxid", {user_id: node.id}).pluck().get()
|
||||||
const username = message.mentions.find(ment => ment.id === node.id)?.username || node.id
|
const username = message.mentions.find(ment => ment.id === node.id)?.username || node.id
|
||||||
if (mxid && useHTML) {
|
if (mxid && useHTML) {
|
||||||
return `<a href="https://matrix.to/#/${mxid}">@${username}</a>`
|
return `<a href="https://matrix.to/#/${mxid}">@${username}</a>`
|
||||||
|
@ -29,7 +29,7 @@ function getDiscordParseCallbacks(message, useHTML) {
|
||||||
},
|
},
|
||||||
/** @param {{id: string, type: "discordChannel"}} node */
|
/** @param {{id: string, type: "discordChannel"}} node */
|
||||||
channel: node => {
|
channel: node => {
|
||||||
const row = select("channel_room", ["room_id", "name", "nick"], "WHERE channel_id = ?").get(node.id)
|
const row = select("channel_room", ["room_id", "name", "nick"], {channel_id: node.id}).get()
|
||||||
if (!row) {
|
if (!row) {
|
||||||
return `<#${node.id}>` // fallback for when this channel is not bridged
|
return `<#${node.id}>` // fallback for when this channel is not bridged
|
||||||
} else if (useHTML) {
|
} else if (useHTML) {
|
||||||
|
@ -41,7 +41,7 @@ function getDiscordParseCallbacks(message, useHTML) {
|
||||||
/** @param {{animated: boolean, name: string, id: string, type: "discordEmoji"}} node */
|
/** @param {{animated: boolean, name: string, id: string, type: "discordEmoji"}} node */
|
||||||
emoji: node => {
|
emoji: node => {
|
||||||
if (useHTML) {
|
if (useHTML) {
|
||||||
const mxc = select("emoji", "mxc_url", "WHERE id = ?").pluck().get(node.id)
|
const mxc = select("emoji", "mxc_url", {emoji_id: node.id}).pluck().get()
|
||||||
if (mxc) {
|
if (mxc) {
|
||||||
return `<img data-mx-emoticon height="32" src="${mxc}" title=":${node.name}:" alt=":${node.name}:">`
|
return `<img data-mx-emoticon height="32" src="${mxc}" title=":${node.name}:" alt=":${node.name}:">`
|
||||||
} else { // We shouldn't get here since all emojis should have been added ahead of time in the messageToEvent function.
|
} else { // We shouldn't get here since all emojis should have been added ahead of time in the messageToEvent function.
|
||||||
|
@ -85,8 +85,8 @@ async function messageToEvent(message, guild, options = {}, di) {
|
||||||
const ref = message.message_reference
|
const ref = message.message_reference
|
||||||
assert(ref)
|
assert(ref)
|
||||||
assert(ref.message_id)
|
assert(ref.message_id)
|
||||||
const eventID = select("event_message", "event_id", "WHERE message_id = ?").pluck().get(ref.message_id)
|
const eventID = select("event_message", "event_id", {message_id: ref.message_id}).pluck().get()
|
||||||
const roomID = select("channel_room", "room_id", "WHERE channel_id = ?").pluck().get(ref.channel_id)
|
const roomID = select("channel_room", "room_id", {channel_id: ref.channel_id}).pluck().get()
|
||||||
if (!eventID || !roomID) return []
|
if (!eventID || !roomID) return []
|
||||||
const event = await di.api.getEvent(roomID, eventID)
|
const event = await di.api.getEvent(roomID, eventID)
|
||||||
return [{
|
return [{
|
||||||
|
@ -138,8 +138,8 @@ async function messageToEvent(message, guild, options = {}, di) {
|
||||||
|
|
||||||
async function addTextEvent(content, msgtype, {scanMentions}) {
|
async function addTextEvent(content, msgtype, {scanMentions}) {
|
||||||
content = content.replace(/https:\/\/(?:ptb\.|canary\.|www\.)?discord(?:app)?\.com\/channels\/([0-9]+)\/([0-9]+)\/([0-9]+)/, (whole, guildID, channelID, messageID) => {
|
content = content.replace(/https:\/\/(?:ptb\.|canary\.|www\.)?discord(?:app)?\.com\/channels\/([0-9]+)\/([0-9]+)\/([0-9]+)/, (whole, guildID, channelID, messageID) => {
|
||||||
const eventID = select("event_message", "event_id", "WHERE message_id = ?").pluck().get(messageID)
|
const eventID = select("event_message", "event_id", {message_id: messageID}).pluck().get()
|
||||||
const roomID = select("channel_room", "room_id", "WHERE channel_id = ?").pluck().get(channelID)
|
const roomID = select("channel_room", "room_id", {channel_id: channelID}).pluck().get()
|
||||||
if (eventID && roomID) {
|
if (eventID && roomID) {
|
||||||
return `https://matrix.to/#/${roomID}/${eventID}`
|
return `https://matrix.to/#/${roomID}/${eventID}`
|
||||||
} else {
|
} else {
|
||||||
|
@ -155,8 +155,8 @@ async function messageToEvent(message, guild, options = {}, di) {
|
||||||
const id = match[3]
|
const id = match[3]
|
||||||
const name = match[2]
|
const name = match[2]
|
||||||
const animated = +!!match[1]
|
const animated = +!!match[1]
|
||||||
const row = select("emoji", "id", "WHERE id = ?").pluck().get(id)
|
const exists = select("emoji", "emoji_id", {emoji_id: id}).pluck().get()
|
||||||
if (!row) {
|
if (!exists) {
|
||||||
// The custom emoji is not registered. We will register it and then add it.
|
// The custom emoji is not registered. We will register it and then add it.
|
||||||
emojiDownloads.push(
|
emojiDownloads.push(
|
||||||
file.uploadDiscordFileToMxc(file.emoji(id, animated)).then(mxc => {
|
file.uploadDiscordFileToMxc(file.emoji(id, animated)).then(mxc => {
|
||||||
|
@ -182,7 +182,7 @@ async function messageToEvent(message, guild, options = {}, di) {
|
||||||
const matches = [...content.matchAll(/@ ?([a-z0-9._]+)\b/gi)]
|
const matches = [...content.matchAll(/@ ?([a-z0-9._]+)\b/gi)]
|
||||||
if (matches.length && matches.some(m => m[1].match(/[a-z]/i))) {
|
if (matches.length && matches.some(m => m[1].match(/[a-z]/i))) {
|
||||||
const writtenMentionsText = matches.map(m => m[1].toLowerCase())
|
const writtenMentionsText = matches.map(m => m[1].toLowerCase())
|
||||||
const roomID = select("channel_room", "room_id", "WHERE channel_id = ?").pluck().get(message.channel_id)
|
const roomID = select("channel_room", "room_id", {channel_id: message.channel_id}).pluck().get()
|
||||||
assert(roomID)
|
assert(roomID)
|
||||||
const {joined} = await di.api.getJoinedMembers(roomID)
|
const {joined} = await di.api.getJoinedMembers(roomID)
|
||||||
for (const [mxid, member] of Object.entries(joined)) {
|
for (const [mxid, member] of Object.entries(joined)) {
|
||||||
|
|
|
@ -17,7 +17,7 @@ const userRegex = reg.namespaces.users.map(u => new RegExp(u.regex))
|
||||||
* @param {{api: import("../../matrix/api")}} di simple-as-nails dependency injection for the matrix API
|
* @param {{api: import("../../matrix/api")}} di simple-as-nails dependency injection for the matrix API
|
||||||
*/
|
*/
|
||||||
async function threadToAnnouncement(parentRoomID, threadRoomID, creatorMxid, thread, di) {
|
async function threadToAnnouncement(parentRoomID, threadRoomID, creatorMxid, thread, di) {
|
||||||
const branchedFromEventID = select("event_message", "event_id", "WHERE message_id = ?").pluck().get(thread.id)
|
const branchedFromEventID = select("event_message", "event_id", {message_id: thread.id}).pluck().get()
|
||||||
/** @type {{"m.mentions"?: any, "m.in_reply_to"?: any}} */
|
/** @type {{"m.mentions"?: any, "m.in_reply_to"?: any}} */
|
||||||
const context = {}
|
const context = {}
|
||||||
if (branchedFromEventID) {
|
if (branchedFromEventID) {
|
||||||
|
|
|
@ -53,7 +53,7 @@ function userToSimName(user) {
|
||||||
assert.notEqual(user.discriminator, "0000", "cannot create user for a webhook")
|
assert.notEqual(user.discriminator, "0000", "cannot create user for a webhook")
|
||||||
|
|
||||||
// 1. Is sim user already registered?
|
// 1. Is sim user already registered?
|
||||||
const existing = select("sim", "sim_name", "WHERE user_id = ?").pluck().get(user.id)
|
const existing = select("sim", "sim_name", {user_id: user.id}).pluck().get()
|
||||||
if (existing) return existing
|
if (existing) return existing
|
||||||
|
|
||||||
// 2. Register based on username (could be new or old format)
|
// 2. Register based on username (could be new or old format)
|
||||||
|
@ -64,7 +64,7 @@ function userToSimName(user) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Check for conflicts with already registered sims
|
// Check for conflicts with already registered sims
|
||||||
const matches = select("sim", "sim_name", "WHERE sim_name LIKE ? ESCAPE '@'").pluck().all(downcased + "%")
|
const matches = select("sim", "sim_name", {}, "WHERE sim_name LIKE ? ESCAPE '@'").pluck().all(downcased + "%")
|
||||||
// Keep generating until we get a suggestion that doesn't conflict
|
// Keep generating until we get a suggestion that doesn't conflict
|
||||||
for (const suggestion of generateLocalpartAlternatives(preferences)) {
|
for (const suggestion of generateLocalpartAlternatives(preferences)) {
|
||||||
if (!matches.includes(suggestion)) return suggestion
|
if (!matches.includes(suggestion)) return suggestion
|
||||||
|
|
|
@ -46,7 +46,7 @@ module.exports = {
|
||||||
|
|
||||||
const channelID = gatewayMessage.d.channel_id
|
const channelID = gatewayMessage.d.channel_id
|
||||||
if (!channelID) return
|
if (!channelID) return
|
||||||
const roomID = select("channel_room", "room_id", "WHERE channel_id = ?").pluck().get(channelID)
|
const roomID = select("channel_room", "room_id", {channel_id: channelID}).pluck().get()
|
||||||
if (!roomID) return
|
if (!roomID) return
|
||||||
|
|
||||||
let stackLines = e.stack.split("\n")
|
let stackLines = e.stack.split("\n")
|
||||||
|
@ -85,7 +85,7 @@ module.exports = {
|
||||||
async checkMissedMessages(client, guild) {
|
async checkMissedMessages(client, guild) {
|
||||||
if (guild.unavailable) return
|
if (guild.unavailable) return
|
||||||
const bridgedChannels = select("channel_room", "channel_id").pluck().all()
|
const bridgedChannels = select("channel_room", "channel_id").pluck().all()
|
||||||
const prepared = select("event_message", "event_id", "WHERE message_id = ?").pluck()
|
const prepared = select("event_message", "event_id", {}, "WHERE message_id = ?").pluck()
|
||||||
for (const channel of guild.channels.concat(guild.threads)) {
|
for (const channel of guild.channels.concat(guild.threads)) {
|
||||||
if (!bridgedChannels.includes(channel.id)) continue
|
if (!bridgedChannels.includes(channel.id)) continue
|
||||||
if (!channel.last_message_id) continue
|
if (!channel.last_message_id) continue
|
||||||
|
@ -129,7 +129,7 @@ module.exports = {
|
||||||
* @param {import("discord-api-types/v10").APIThreadChannel} thread
|
* @param {import("discord-api-types/v10").APIThreadChannel} thread
|
||||||
*/
|
*/
|
||||||
async onThreadCreate(client, thread) {
|
async onThreadCreate(client, thread) {
|
||||||
const parentRoomID = select("channel_room", "room_id", "WHERE channel_id = ?").pluck().get(thread.parent_id)
|
const parentRoomID = select("channel_room", "room_id", {channel_id: thread.parent_id}).pluck().get()
|
||||||
if (!parentRoomID) return // Not interested in a thread if we aren't interested in its wider channel
|
if (!parentRoomID) return // Not interested in a thread if we aren't interested in its wider channel
|
||||||
const threadRoomID = await createRoom.syncRoom(thread.id) // Create room (will share the same inflight as the initial message to the thread)
|
const threadRoomID = await createRoom.syncRoom(thread.id) // Create room (will share the same inflight as the initial message to the thread)
|
||||||
await announceThread.announceThread(parentRoomID, threadRoomID, thread)
|
await announceThread.announceThread(parentRoomID, threadRoomID, thread)
|
||||||
|
@ -140,7 +140,7 @@ module.exports = {
|
||||||
* @param {import("discord-api-types/v10").GatewayGuildUpdateDispatchData} guild
|
* @param {import("discord-api-types/v10").GatewayGuildUpdateDispatchData} guild
|
||||||
*/
|
*/
|
||||||
async onGuildUpdate(client, guild) {
|
async onGuildUpdate(client, guild) {
|
||||||
const spaceID = select("guild_space", "space_id", "WHERE guild_id = ?").pluck().get(guild.id)
|
const spaceID = select("guild_space", "space_id", {guild_id: guild.id}).pluck().get()
|
||||||
if (!spaceID) return
|
if (!spaceID) return
|
||||||
await createSpace.syncSpace(guild)
|
await createSpace.syncSpace(guild)
|
||||||
},
|
},
|
||||||
|
@ -151,7 +151,7 @@ module.exports = {
|
||||||
* @param {boolean} isThread
|
* @param {boolean} isThread
|
||||||
*/
|
*/
|
||||||
async onChannelOrThreadUpdate(client, channelOrThread, isThread) {
|
async onChannelOrThreadUpdate(client, channelOrThread, isThread) {
|
||||||
const roomID = select("channel_room", "room_id", "WHERE channel_id = ?").pluck().get(channelOrThread.id)
|
const roomID = select("channel_room", "room_id", {channel_id: channelOrThread.id}).pluck().get()
|
||||||
if (!roomID) return // No target room to update the data on
|
if (!roomID) return // No target room to update the data on
|
||||||
await createRoom.syncRoom(channelOrThread.id)
|
await createRoom.syncRoom(channelOrThread.id)
|
||||||
},
|
},
|
||||||
|
@ -162,7 +162,7 @@ module.exports = {
|
||||||
*/
|
*/
|
||||||
async onMessageCreate(client, message) {
|
async onMessageCreate(client, message) {
|
||||||
if (message.webhook_id) {
|
if (message.webhook_id) {
|
||||||
const row = select("webhook", "webhook_id", "WHERE webhook_id = ?").pluck().get(message.webhook_id)
|
const row = select("webhook", "webhook_id", {webhook_id: message.webhook_id}).pluck().get()
|
||||||
if (row) {
|
if (row) {
|
||||||
// The message was sent by the bridge's own webhook on discord. We don't want to reflect this back, so just drop it.
|
// The message was sent by the bridge's own webhook on discord. We don't want to reflect this back, so just drop it.
|
||||||
return
|
return
|
||||||
|
@ -183,7 +183,7 @@ module.exports = {
|
||||||
*/
|
*/
|
||||||
async onMessageUpdate(client, data) {
|
async onMessageUpdate(client, data) {
|
||||||
if (data.webhook_id) {
|
if (data.webhook_id) {
|
||||||
const row = select("webhook", "webhook_id", "WHERE webhook_id = ?").pluck().get(data.webhook_id)
|
const row = select("webhook", "webhook_id", {webhook_id: data.webhook_id}).pluck().get()
|
||||||
if (row) {
|
if (row) {
|
||||||
// The update was sent by the bridge's own webhook on discord. We don't want to reflect this back, so just drop it.
|
// The update was sent by the bridge's own webhook on discord. We don't want to reflect this back, so just drop it.
|
||||||
return
|
return
|
||||||
|
@ -249,9 +249,9 @@ module.exports = {
|
||||||
* @param {import("discord-api-types/v10").GatewayTypingStartDispatchData} data
|
* @param {import("discord-api-types/v10").GatewayTypingStartDispatchData} data
|
||||||
*/
|
*/
|
||||||
async onTypingStart(client, data) {
|
async onTypingStart(client, data) {
|
||||||
const roomID = select("channel_room", "room_id", "WHERE channel_id = ?").pluck().get(data.channel_id)
|
const roomID = select("channel_room", "room_id", {channel_id: data.channel_id}).pluck().get()
|
||||||
if (!roomID) return
|
if (!roomID) return
|
||||||
const mxid = from("sim").join("sim_member", "mxid").and("WHERE user_id = ? AND room_id = ?").pluck("mxid").get(data.user_id, roomID)
|
const mxid = from("sim").join("sim_member", "mxid").where({user_id: data.user_id, room_id: roomID}).pluck("mxid").get()
|
||||||
if (!mxid) return
|
if (!mxid) return
|
||||||
// Each Discord user triggers the notification every 8 seconds as long as they remain typing.
|
// Each Discord user triggers the notification every 8 seconds as long as they remain typing.
|
||||||
// Discord does not send typing stopped events, so typing only stops if the timeout is reached or if the user sends their message.
|
// Discord does not send typing stopped events, so typing only stops if the timeout is reached or if the user sends their message.
|
||||||
|
|
|
@ -12,4 +12,8 @@ ALTER TABLE lottie RENAME COLUMN id TO sticker_id;
|
||||||
|
|
||||||
ALTER TABLE sim RENAME COLUMN discord_id TO user_id;
|
ALTER TABLE sim RENAME COLUMN discord_id TO user_id;
|
||||||
|
|
||||||
|
-- Rename id to emoji_id so joins make sense in the future
|
||||||
|
|
||||||
|
ALTER TABLE emoji RENAME COLUMN id TO emoji_id;
|
||||||
|
|
||||||
COMMIT;
|
COMMIT;
|
||||||
|
|
2
db/orm-utils.d.ts → db/orm-defs.d.ts
vendored
2
db/orm-utils.d.ts → db/orm-defs.d.ts
vendored
|
@ -64,7 +64,7 @@ export type Models = {
|
||||||
}
|
}
|
||||||
|
|
||||||
emoji: {
|
emoji: {
|
||||||
id: string
|
emoji_id: string
|
||||||
name: string
|
name: string
|
||||||
animated: number
|
animated: number
|
||||||
mxc_url: string
|
mxc_url: string
|
42
db/orm.js
42
db/orm.js
|
@ -1,19 +1,28 @@
|
||||||
// @ts-check
|
// @ts-check
|
||||||
|
|
||||||
const {db} = require("../passthrough")
|
const {db} = require("../passthrough")
|
||||||
const U = require("./orm-utils")
|
const U = require("./orm-defs")
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @template {keyof U.Models} Table
|
* @template {keyof U.Models} Table
|
||||||
* @template {keyof U.Models[Table]} Col
|
* @template {keyof U.Models[Table]} Col
|
||||||
* @param {Table} table
|
* @param {Table} table
|
||||||
* @param {Col[] | Col} cols
|
* @param {Col[] | Col} cols
|
||||||
|
* @param {Partial<U.Models[Table]>} where
|
||||||
* @param {string} [e]
|
* @param {string} [e]
|
||||||
*/
|
*/
|
||||||
function select(table, cols, e = "") {
|
function select(table, cols, where = {}, e = "") {
|
||||||
if (!Array.isArray(cols)) cols = [cols]
|
if (!Array.isArray(cols)) cols = [cols]
|
||||||
|
const parameters = []
|
||||||
|
const wheres = Object.entries(where).map(([col, value]) => {
|
||||||
|
parameters.push(value)
|
||||||
|
return `"${col}" = ?`
|
||||||
|
})
|
||||||
|
const whereString = wheres.length ? " WHERE " + wheres.join(" AND ") : ""
|
||||||
/** @type {U.Prepared<Pick<U.Models[Table], Col>>} */
|
/** @type {U.Prepared<Pick<U.Models[Table], Col>>} */
|
||||||
const prepared = db.prepare(`SELECT ${cols.map(k => `"${String(k)}"`).join(", ")} FROM ${table} ${e}`)
|
const prepared = db.prepare(`SELECT ${cols.map(k => `"${String(k)}"`).join(", ")} FROM ${table} ${whereString} ${e}`)
|
||||||
|
prepared.get = prepared.get.bind(prepared, ...parameters)
|
||||||
|
prepared.all = prepared.all.bind(prepared, ...parameters)
|
||||||
return prepared
|
return prepared
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -26,13 +35,18 @@ class From {
|
||||||
* @param {Table} table
|
* @param {Table} table
|
||||||
*/
|
*/
|
||||||
constructor(table) {
|
constructor(table) {
|
||||||
/** @type {Table[]} */
|
/** @private @type {Table[]} */
|
||||||
this.tables = [table]
|
this.tables = [table]
|
||||||
|
/** @private */
|
||||||
this.sql = ""
|
this.sql = ""
|
||||||
|
/** @private */
|
||||||
this.cols = []
|
this.cols = []
|
||||||
|
/** @private */
|
||||||
this.using = []
|
this.using = []
|
||||||
|
/** @private */
|
||||||
this.isPluck = false
|
this.isPluck = false
|
||||||
|
/** @private */
|
||||||
|
this.parameters = []
|
||||||
}
|
}
|
||||||
|
|
||||||
/**
|
/**
|
||||||
|
@ -78,7 +92,19 @@ class From {
|
||||||
* @param {string} sql
|
* @param {string} sql
|
||||||
*/
|
*/
|
||||||
and(sql) {
|
and(sql) {
|
||||||
this.sql = sql
|
this.sql += " " + sql
|
||||||
|
return this
|
||||||
|
}
|
||||||
|
|
||||||
|
/**
|
||||||
|
* @param {Partial<U.Models[Table]>} conditions
|
||||||
|
*/
|
||||||
|
where(conditions) {
|
||||||
|
const wheres = Object.entries(conditions).map(([col, value]) => {
|
||||||
|
this.parameters.push(value)
|
||||||
|
return `"${col}" = ?`
|
||||||
|
})
|
||||||
|
this.sql += " WHERE " + wheres.join(" AND ")
|
||||||
return this
|
return this
|
||||||
}
|
}
|
||||||
|
|
||||||
|
@ -98,12 +124,12 @@ class From {
|
||||||
|
|
||||||
get(..._) {
|
get(..._) {
|
||||||
const prepared = this.prepare()
|
const prepared = this.prepare()
|
||||||
return prepared.get(..._)
|
return prepared.get(...this.parameters, ..._)
|
||||||
}
|
}
|
||||||
|
|
||||||
all(..._) {
|
all(..._) {
|
||||||
const prepared = this.prepare()
|
const prepared = this.prepare()
|
||||||
return prepared.all(..._)
|
return prepared.all(...this.parameters, ..._)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -6,7 +6,7 @@ const data = require("../test/data")
|
||||||
const {db, select, from} = require("../passthrough")
|
const {db, select, from} = require("../passthrough")
|
||||||
|
|
||||||
test("orm: select: get works", t => {
|
test("orm: select: get works", t => {
|
||||||
const row = select("guild_space", "guild_id", "WHERE space_id = ?").get("!jjWAGMeQdNrVZSSfvz:cadence.moe")
|
const row = select("guild_space", "guild_id", {}, "WHERE space_id = ?").get("!jjWAGMeQdNrVZSSfvz:cadence.moe")
|
||||||
t.equal(row?.guild_id, data.guild.general.id)
|
t.equal(row?.guild_id, data.guild.general.id)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -16,10 +16,20 @@ test("orm: from: get works", t => {
|
||||||
})
|
})
|
||||||
|
|
||||||
test("orm: select: get pluck works", t => {
|
test("orm: select: get pluck works", t => {
|
||||||
const guildID = select("guild_space", "guild_id", "WHERE space_id = ?").pluck().get("!jjWAGMeQdNrVZSSfvz:cadence.moe")
|
const guildID = select("guild_space", "guild_id", {}, "WHERE space_id = ?").pluck().get("!jjWAGMeQdNrVZSSfvz:cadence.moe")
|
||||||
t.equal(guildID, data.guild.general.id)
|
t.equal(guildID, data.guild.general.id)
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test("orm: select: get, where and pluck works", t => {
|
||||||
|
const channelID = select("message_channel", "channel_id", {message_id: "1128118177155526666"}).pluck().get()
|
||||||
|
t.equal(channelID, "112760669178241024")
|
||||||
|
})
|
||||||
|
|
||||||
|
test("orm: select: all, where and pluck works on multiple columns", t => {
|
||||||
|
const names = select("member_cache", "displayname", {room_id: "!kLRqKKUQXcibIMtOpl:cadence.moe", mxid: "@cadence:cadence.moe"}).pluck().all()
|
||||||
|
t.deepEqual(names, ["cadence [they]"])
|
||||||
|
})
|
||||||
|
|
||||||
test("orm: from: get pluck works", t => {
|
test("orm: from: get pluck works", t => {
|
||||||
const guildID = from("guild_space").pluck("guild_id").and("WHERE space_id = ?").get("!jjWAGMeQdNrVZSSfvz:cadence.moe")
|
const guildID = from("guild_space").pluck("guild_id").and("WHERE space_id = ?").get("!jjWAGMeQdNrVZSSfvz:cadence.moe")
|
||||||
t.equal(guildID, data.guild.general.id)
|
t.equal(guildID, data.guild.general.id)
|
||||||
|
@ -29,3 +39,8 @@ test("orm: from: join and pluck works", t => {
|
||||||
const mxid = from("sim").join("sim_member", "mxid").and("WHERE user_id = ? AND room_id = ?").pluck("mxid").get("771520384671416320", "!hYnGGlPHlbujVVfktC:cadence.moe")
|
const mxid = from("sim").join("sim_member", "mxid").and("WHERE user_id = ? AND room_id = ?").pluck("mxid").get("771520384671416320", "!hYnGGlPHlbujVVfktC:cadence.moe")
|
||||||
t.equal(mxid, "@_ooye_bojack_horseman:cadence.moe")
|
t.equal(mxid, "@_ooye_bojack_horseman:cadence.moe")
|
||||||
})
|
})
|
||||||
|
|
||||||
|
test("orm: from: where and pluck works", t => {
|
||||||
|
const subtypes = from("event_message").where({message_id: "1141501302736695316"}).pluck("event_subtype").all()
|
||||||
|
t.deepEqual(subtypes.sort(), ["m.image", "m.text"])
|
||||||
|
})
|
||||||
|
|
|
@ -81,7 +81,7 @@ const commands = [{
|
||||||
execute: replyctx(
|
execute: replyctx(
|
||||||
async (message, channel, guild, ctx) => {
|
async (message, channel, guild, ctx) => {
|
||||||
// Guard
|
// Guard
|
||||||
const roomID = select("channel_room", "room_id", "WHERE channel_id = ?").pluck().get(channel.id)
|
const roomID = select("channel_room", "room_id", {channel_id: channel.id}).pluck().get()
|
||||||
if (!roomID) return discord.snow.channel.createMessage(channel.id, {
|
if (!roomID) return discord.snow.channel.createMessage(channel.id, {
|
||||||
...ctx,
|
...ctx,
|
||||||
content: "This channel isn't bridged to the other side."
|
content: "This channel isn't bridged to the other side."
|
||||||
|
@ -125,8 +125,8 @@ const commands = [{
|
||||||
execute: replyctx(
|
execute: replyctx(
|
||||||
async (message, channel, guild, ctx) => {
|
async (message, channel, guild, ctx) => {
|
||||||
// Check guild is bridged
|
// Check guild is bridged
|
||||||
const spaceID = select("guild_space", "space_id", "WHERE guild_id = ?").pluck().get(guild.id)
|
const spaceID = select("guild_space", "space_id", {guild_id: guild.id}).pluck().get()
|
||||||
const roomID = select("channel_room", "room_id", "WHERE channel_id = ?").pluck().get(channel.id)
|
const roomID = select("channel_room", "room_id", {channel_id: channel.id}).pluck().get()
|
||||||
if (!spaceID || !roomID) return discord.snow.channel.createMessage(channel.id, {
|
if (!spaceID || !roomID) return discord.snow.channel.createMessage(channel.id, {
|
||||||
...ctx,
|
...ctx,
|
||||||
content: "This server isn't bridged to Matrix, so you can't invite Matrix users."
|
content: "This server isn't bridged to Matrix, so you can't invite Matrix users."
|
||||||
|
|
|
@ -14,9 +14,9 @@ const emoji = sync.require("../converters/emoji")
|
||||||
* @param {Ty.Event.Outer<Ty.Event.M_Reaction>} event
|
* @param {Ty.Event.Outer<Ty.Event.M_Reaction>} event
|
||||||
*/
|
*/
|
||||||
async function addReaction(event) {
|
async function addReaction(event) {
|
||||||
const channelID = select("channel_room", "channel_id", "WHERE room_id = ?").pluck().get(event.room_id)
|
const channelID = select("channel_room", "channel_id", {room_id: event.room_id}).pluck().get()
|
||||||
if (!channelID) return // We just assume the bridge has already been created
|
if (!channelID) return // We just assume the bridge has already been created
|
||||||
const messageID = select("event_message", "message_id", "WHERE event_id = ? AND part = 0").pluck().get(event.content["m.relates_to"].event_id) // 0 = primary
|
const messageID = select("event_message", "message_id", {event_id: event.content["m.relates_to"].event_id, part: 0}).pluck().get() // 0 = primary
|
||||||
if (!messageID) return // Nothing can be done if the parent message was never bridged.
|
if (!messageID) return // Nothing can be done if the parent message was never bridged.
|
||||||
|
|
||||||
const key = event.content["m.relates_to"].key // TODO: handle custom text or emoji reactions
|
const key = event.content["m.relates_to"].key // TODO: handle custom text or emoji reactions
|
||||||
|
|
|
@ -14,7 +14,7 @@ const {discord, db, select} = passthrough
|
||||||
*/
|
*/
|
||||||
async function ensureWebhook(channelID, forceCreate = false) {
|
async function ensureWebhook(channelID, forceCreate = false) {
|
||||||
if (!forceCreate) {
|
if (!forceCreate) {
|
||||||
const row = select("webhook", ["webhook_id", "webhook_token"], "WHERE channel_id = ?").get(channelID)
|
const row = select("webhook", ["webhook_id", "webhook_token"], {channel_id: channelID}).get()
|
||||||
if (row) {
|
if (row) {
|
||||||
return {
|
return {
|
||||||
id: row.webhook_id,
|
id: row.webhook_id,
|
||||||
|
|
|
@ -12,7 +12,7 @@ const utils = sync.require("../converters/utils")
|
||||||
* @param {Ty.Event.Outer_M_Room_Redaction} event
|
* @param {Ty.Event.Outer_M_Room_Redaction} event
|
||||||
*/
|
*/
|
||||||
async function deleteMessage(event) {
|
async function deleteMessage(event) {
|
||||||
const rows = from("event_message").join("message_channel", "message_id").select("channel_id", "message_id").and("WHERE event_id = ?").all(event.redacts)
|
const rows = from("event_message").join("message_channel", "message_id").select("channel_id", "message_id").where({event_id: event.redacts}).all()
|
||||||
for (const row of rows) {
|
for (const row of rows) {
|
||||||
discord.snow.channel.deleteMessage(row.channel_id, row.message_id, event.content.reason)
|
discord.snow.channel.deleteMessage(row.channel_id, row.message_id, event.content.reason)
|
||||||
}
|
}
|
||||||
|
@ -23,7 +23,8 @@ async function deleteMessage(event) {
|
||||||
*/
|
*/
|
||||||
async function removeReaction(event) {
|
async function removeReaction(event) {
|
||||||
const hash = utils.getEventIDHash(event.redacts)
|
const hash = utils.getEventIDHash(event.redacts)
|
||||||
const row = from("reaction").join("message_channel", "message_id").select("channel_id", "message_id", "encoded_emoji").and("WHERE hashed_event_id = ?").get(hash)
|
// TODO: this works but fix the type
|
||||||
|
const row = from("reaction").join("message_channel", "message_id").select("channel_id", "message_id", "encoded_emoji").where({hashed_event_id: hash}).get()
|
||||||
if (!row) return
|
if (!row) return
|
||||||
await discord.snow.channel.deleteReactionSelf(row.channel_id, row.message_id, row.encoded_emoji)
|
await discord.snow.channel.deleteReactionSelf(row.channel_id, row.message_id, row.encoded_emoji)
|
||||||
db.prepare("DELETE FROM reaction WHERE hashed_event_id = ?").run(hash)
|
db.prepare("DELETE FROM reaction WHERE hashed_event_id = ?").run(hash)
|
||||||
|
|
|
@ -58,7 +58,7 @@ async function resolvePendingFiles(message) {
|
||||||
|
|
||||||
/** @param {Ty.Event.Outer_M_Room_Message | Ty.Event.Outer_M_Room_Message_File | Ty.Event.Outer_M_Sticker} event */
|
/** @param {Ty.Event.Outer_M_Room_Message | Ty.Event.Outer_M_Room_Message_File | Ty.Event.Outer_M_Sticker} event */
|
||||||
async function sendEvent(event) {
|
async function sendEvent(event) {
|
||||||
const row = select("channel_room", ["channel_id", "thread_parent"], "WHERE room_id = ?").get(event.room_id)
|
const row = select("channel_room", ["channel_id", "thread_parent"], {room_id: event.room_id}).get()
|
||||||
if (!row) return // allow the bot to exist in unbridged rooms, just don't do anything with it
|
if (!row) return // allow the bot to exist in unbridged rooms, just don't do anything with it
|
||||||
let channelID = row.channel_id
|
let channelID = row.channel_id
|
||||||
let threadID = undefined
|
let threadID = undefined
|
||||||
|
|
|
@ -7,19 +7,19 @@ const passthrough = require("../../passthrough")
|
||||||
const {sync, select} = passthrough
|
const {sync, select} = passthrough
|
||||||
|
|
||||||
/**
|
/**
|
||||||
* @param {string} emoji
|
* @param {string} input
|
||||||
* @param {string | null | undefined} shortcode
|
* @param {string | null | undefined} shortcode
|
||||||
* @returns {string?}
|
* @returns {string?}
|
||||||
*/
|
*/
|
||||||
function encodeEmoji(emoji, shortcode) {
|
function encodeEmoji(input, shortcode) {
|
||||||
let discordPreferredEncoding
|
let discordPreferredEncoding
|
||||||
if (emoji.startsWith("mxc://")) {
|
if (input.startsWith("mxc://")) {
|
||||||
// Custom emoji
|
// Custom emoji
|
||||||
let row = select("emoji", ["id", "name"], "WHERE mxc_url = ?").get(emoji)
|
let row = select("emoji", ["emoji_id", "name"], {mxc_url: input}).get()
|
||||||
if (!row && shortcode) {
|
if (!row && shortcode) {
|
||||||
// Use the name to try to find a known emoji with the same name.
|
// Use the name to try to find a known emoji with the same name.
|
||||||
const name = shortcode.replace(/^:|:$/g, "")
|
const name = shortcode.replace(/^:|:$/g, "")
|
||||||
row = select("emoji", ["id", "name"], "WHERE name = ?").get(name)
|
row = select("emoji", ["emoji_id", "name"], {name: name}).get()
|
||||||
}
|
}
|
||||||
if (!row) {
|
if (!row) {
|
||||||
// We don't have this emoji and there's no realistic way to just-in-time upload a new emoji somewhere.
|
// We don't have this emoji and there's no realistic way to just-in-time upload a new emoji somewhere.
|
||||||
|
@ -27,11 +27,11 @@ function encodeEmoji(emoji, shortcode) {
|
||||||
return null
|
return null
|
||||||
}
|
}
|
||||||
// Cool, we got an exact or a candidate emoji.
|
// Cool, we got an exact or a candidate emoji.
|
||||||
discordPreferredEncoding = encodeURIComponent(`${row.name}:${row.id}`)
|
discordPreferredEncoding = encodeURIComponent(`${row.name}:${row.emoji_id}`)
|
||||||
} else {
|
} else {
|
||||||
// Default emoji
|
// Default emoji
|
||||||
// https://github.com/discord/discord-api-docs/issues/2723#issuecomment-807022205 ????????????
|
// https://github.com/discord/discord-api-docs/issues/2723#issuecomment-807022205 ????????????
|
||||||
const encoded = encodeURIComponent(emoji)
|
const encoded = encodeURIComponent(input)
|
||||||
const encodedTrimmed = encoded.replace(/%EF%B8%8F/g, "")
|
const encodedTrimmed = encoded.replace(/%EF%B8%8F/g, "")
|
||||||
|
|
||||||
const forceTrimmedList = [
|
const forceTrimmedList = [
|
||||||
|
@ -42,10 +42,10 @@ function encodeEmoji(emoji, shortcode) {
|
||||||
|
|
||||||
discordPreferredEncoding =
|
discordPreferredEncoding =
|
||||||
( forceTrimmedList.includes(encodedTrimmed) ? encodedTrimmed
|
( forceTrimmedList.includes(encodedTrimmed) ? encodedTrimmed
|
||||||
: encodedTrimmed !== encoded && [...emoji].length === 2 ? encoded
|
: encodedTrimmed !== encoded && [...input].length === 2 ? encoded
|
||||||
: encodedTrimmed)
|
: encodedTrimmed)
|
||||||
|
|
||||||
console.log("add reaction from matrix:", emoji, encoded, encodedTrimmed, "chosen:", discordPreferredEncoding)
|
console.log("add reaction from matrix:", input, encoded, encodedTrimmed, "chosen:", discordPreferredEncoding)
|
||||||
}
|
}
|
||||||
return discordPreferredEncoding
|
return discordPreferredEncoding
|
||||||
}
|
}
|
||||||
|
|
|
@ -121,7 +121,7 @@ turndownService.addRule("emoji", {
|
||||||
replacement: function (content, node) {
|
replacement: function (content, node) {
|
||||||
const mxcUrl = node.getAttribute("src")
|
const mxcUrl = node.getAttribute("src")
|
||||||
// Get the known emoji from the database. (We may not be able to actually use this if it was from another server.)
|
// Get the known emoji from the database. (We may not be able to actually use this if it was from another server.)
|
||||||
const row = select("emoji", ["id", "name", "animated"], "WHERE mxc_url = ?").get(mxcUrl)
|
const row = select("emoji", ["emoji_id", "name", "animated"], {mxc_url: mxcUrl}).get()
|
||||||
// Also guess a suitable emoji based on the ID (if available) or name
|
// Also guess a suitable emoji based on the ID (if available) or name
|
||||||
let guess = null
|
let guess = null
|
||||||
const guessedName = node.getAttribute("title").replace(/^:|:$/g, "")
|
const guessedName = node.getAttribute("title").replace(/^:|:$/g, "")
|
||||||
|
@ -129,7 +129,7 @@ turndownService.addRule("emoji", {
|
||||||
/** @type {{name: string, id: string, animated: number}[]} */
|
/** @type {{name: string, id: string, animated: number}[]} */
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
const emojis = guild.emojis
|
const emojis = guild.emojis
|
||||||
const match = emojis.find(e => e.id === row?.id) || emojis.find(e => e.name === guessedName) || emojis.find(e => e.name?.toLowerCase() === guessedName.toLowerCase())
|
const match = emojis.find(e => e.id === row?.emoji_id) || emojis.find(e => e.name === guessedName) || emojis.find(e => e.name?.toLowerCase() === guessedName.toLowerCase())
|
||||||
if (match) {
|
if (match) {
|
||||||
guess = match
|
guess = match
|
||||||
break
|
break
|
||||||
|
@ -180,7 +180,7 @@ turndownService.addRule("fencedCodeBlock", {
|
||||||
* @returns {Promise<{displayname?: string?, avatar_url?: string?}>}
|
* @returns {Promise<{displayname?: string?, avatar_url?: string?}>}
|
||||||
*/
|
*/
|
||||||
async function getMemberFromCacheOrHomeserver(roomID, mxid, api) {
|
async function getMemberFromCacheOrHomeserver(roomID, mxid, api) {
|
||||||
const row = select("member_cache", ["displayname", "avatar_url"], "WHERE room_id = ? AND mxid = ?").get(roomID, mxid)
|
const row = select("member_cache", ["displayname", "avatar_url"], {room_id: roomID, mxid}).get()
|
||||||
if (row) return row
|
if (row) return row
|
||||||
return api.getStateEvent(roomID, "m.room.member", mxid).then(event => {
|
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)
|
db.prepare("REPLACE INTO member_cache (room_id, mxid, displayname, avatar_url) VALUES (?, ?, ?, ?)").run(roomID, mxid, event?.displayname || null, event?.avatar_url || null)
|
||||||
|
@ -285,7 +285,7 @@ async function eventToMessage(event, guild, di) {
|
||||||
if (relType !== "m.replace") return
|
if (relType !== "m.replace") return
|
||||||
const originalEventId = relatesTo.event_id
|
const originalEventId = relatesTo.event_id
|
||||||
if (!originalEventId) return
|
if (!originalEventId) return
|
||||||
messageIDsToEdit = select("event_message", "message_id", "WHERE event_id = ? ORDER BY part").pluck().all(originalEventId)
|
messageIDsToEdit = select("event_message", "message_id", {event_id: originalEventId}, "ORDER BY part").pluck().all()
|
||||||
if (!messageIDsToEdit.length) return
|
if (!messageIDsToEdit.length) return
|
||||||
|
|
||||||
// Ok, it's an edit.
|
// Ok, it's an edit.
|
||||||
|
@ -316,7 +316,7 @@ async function eventToMessage(event, guild, di) {
|
||||||
if (!repliedToEventId) return
|
if (!repliedToEventId) return
|
||||||
let repliedToEvent = await di.api.getEvent(event.room_id, repliedToEventId)
|
let repliedToEvent = await di.api.getEvent(event.room_id, repliedToEventId)
|
||||||
if (!repliedToEvent) return
|
if (!repliedToEvent) return
|
||||||
const row = from("event_message").join("message_channel", "message_id").select("channel_id", "message_id").and("WHERE event_id = ? ORDER BY part").get(repliedToEventId)
|
const row = from("event_message").join("message_channel", "message_id").select("channel_id", "message_id").where({event_id: repliedToEventId}).and("ORDER BY part").get()
|
||||||
if (row) {
|
if (row) {
|
||||||
replyLine = `<:L1:1144820033948762203><:L2:1144820084079087647>https://discord.com/channels/${guild.id}/${row.channel_id}/${row.message_id} `
|
replyLine = `<:L1:1144820033948762203><:L2:1144820084079087647>https://discord.com/channels/${guild.id}/${row.channel_id}/${row.message_id} `
|
||||||
} else {
|
} else {
|
||||||
|
@ -324,7 +324,7 @@ async function eventToMessage(event, guild, di) {
|
||||||
}
|
}
|
||||||
const sender = repliedToEvent.sender
|
const sender = repliedToEvent.sender
|
||||||
const senderName = sender.match(/@([^:]*)/)?.[1] || sender
|
const senderName = sender.match(/@([^:]*)/)?.[1] || sender
|
||||||
const authorID = select("sim", "user_id", "WHERE mxid = ?").pluck().get(repliedToEvent.sender)
|
const authorID = select("sim", "user_id", {mxid: repliedToEvent.sender}).pluck().get()
|
||||||
if (authorID) {
|
if (authorID) {
|
||||||
replyLine += `<@${authorID}>`
|
replyLine += `<@${authorID}>`
|
||||||
} else {
|
} else {
|
||||||
|
@ -367,14 +367,14 @@ async function eventToMessage(event, guild, di) {
|
||||||
// Handling mentions of Discord users
|
// Handling mentions of Discord users
|
||||||
input = input.replace(/("https:\/\/matrix.to\/#\/(@[^"]+)")>/g, (whole, attributeValue, mxid) => {
|
input = input.replace(/("https:\/\/matrix.to\/#\/(@[^"]+)")>/g, (whole, attributeValue, mxid) => {
|
||||||
if (!utils.eventSenderIsFromDiscord(mxid)) return whole
|
if (!utils.eventSenderIsFromDiscord(mxid)) return whole
|
||||||
const userID = select("sim", "user_id", "WHERE mxid = ?").pluck().get(mxid)
|
const userID = select("sim", "user_id", {mxid: mxid}).pluck().get()
|
||||||
if (!userID) return whole
|
if (!userID) return whole
|
||||||
return `${attributeValue} data-user-id="${userID}">`
|
return `${attributeValue} data-user-id="${userID}">`
|
||||||
})
|
})
|
||||||
|
|
||||||
// Handling mentions of Discord rooms
|
// Handling mentions of Discord rooms
|
||||||
input = input.replace(/("https:\/\/matrix.to\/#\/(![^"]+)")>/g, (whole, attributeValue, roomID) => {
|
input = input.replace(/("https:\/\/matrix.to\/#\/(![^"]+)")>/g, (whole, attributeValue, roomID) => {
|
||||||
const channelID = select("channel_room", "channel_id", "WHERE room_id = ?").pluck().get(roomID)
|
const channelID = select("channel_room", "channel_id", {room_id: roomID}).pluck().get()
|
||||||
if (!channelID) return whole
|
if (!channelID) return whole
|
||||||
return `${attributeValue} data-channel-id="${channelID}">`
|
return `${attributeValue} data-channel-id="${channelID}">`
|
||||||
})
|
})
|
||||||
|
|
|
@ -1508,7 +1508,7 @@ test("event2message: caches the member if the member is not known", async t => {
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
|
|
||||||
t.deepEqual(select("member_cache", ["avatar_url", "displayname", "mxid"], "WHERE room_id = '!should_be_newly_cached:cadence.moe'").all(), [
|
t.deepEqual(select("member_cache", ["avatar_url", "displayname", "mxid"], {room_id: "!should_be_newly_cached:cadence.moe"}).all(), [
|
||||||
{avatar_url: "mxc://cadence.moe/this_is_the_avatar", displayname: null, mxid: "@should_be_newly_cached:cadence.moe"}
|
{avatar_url: "mxc://cadence.moe/this_is_the_avatar", displayname: null, mxid: "@should_be_newly_cached:cadence.moe"}
|
||||||
])
|
])
|
||||||
t.equal(called, 1, "getStateEvent should be called once")
|
t.equal(called, 1, "getStateEvent should be called once")
|
||||||
|
@ -1551,7 +1551,7 @@ test("event2message: skips caching the member if the member does not exist, some
|
||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
t.deepEqual(select("member_cache", ["avatar_url", "displayname", "mxid"], "WHERE room_id = '!not_real:cadence.moe'").all(), [])
|
t.deepEqual(select("member_cache", ["avatar_url", "displayname", "mxid"], {room_id: "!not_real:cadence.moe"}).all(), [])
|
||||||
t.equal(called, 1, "getStateEvent should be called once")
|
t.equal(called, 1, "getStateEvent should be called once")
|
||||||
})
|
})
|
||||||
|
|
||||||
|
@ -1594,7 +1594,7 @@ test("event2message: overly long usernames are shifted into the message content"
|
||||||
}]
|
}]
|
||||||
}
|
}
|
||||||
)
|
)
|
||||||
t.deepEqual(select("member_cache", ["avatar_url", "displayname", "mxid"], "WHERE room_id = '!should_be_newly_cached_2:cadence.moe'").all(), [
|
t.deepEqual(select("member_cache", ["avatar_url", "displayname", "mxid"], {room_id: "!should_be_newly_cached_2:cadence.moe"}).all(), [
|
||||||
{avatar_url: null, displayname: "I am BLACK I am WHITE I am SHORT I am LONG I am EVERYTHING YOU THINK IS IMPORTANT and I DON'T MATTER", mxid: "@should_be_newly_cached_2:cadence.moe"}
|
{avatar_url: null, displayname: "I am BLACK I am WHITE I am SHORT I am LONG I am EVERYTHING YOU THINK IS IMPORTANT and I DON'T MATTER", mxid: "@should_be_newly_cached_2:cadence.moe"}
|
||||||
])
|
])
|
||||||
t.equal(called, 1, "getStateEvent should be called once")
|
t.equal(called, 1, "getStateEvent should be called once")
|
||||||
|
|
|
@ -43,7 +43,7 @@ async function uploadDiscordFileToMxc(path) {
|
||||||
}
|
}
|
||||||
|
|
||||||
// Has this file already been uploaded in the past? Grab the existing copy from the database.
|
// Has this file already been uploaded in the past? Grab the existing copy from the database.
|
||||||
const existingFromDb = select("file", "mxc_url", "WHERE discord_url = ?").pluck().get(urlNoExpiry)
|
const existingFromDb = select("file", "mxc_url", {discord_url: urlNoExpiry}).pluck().get()
|
||||||
if (typeof existingFromDb === "string") {
|
if (typeof existingFromDb === "string") {
|
||||||
return existingFromDb
|
return existingFromDb
|
||||||
}
|
}
|
||||||
|
|
|
@ -151,7 +151,7 @@ const commands = [{
|
||||||
async (event, realBody, ctx) => {
|
async (event, realBody, ctx) => {
|
||||||
// Guard
|
// Guard
|
||||||
/** @type {string} */ // @ts-ignore
|
/** @type {string} */ // @ts-ignore
|
||||||
const channelID = select("channel_room", "channel_id", "WHERE room_id = ?").pluck().get(event.room_id)
|
const channelID = select("channel_room", "channel_id", {room_id: event.room_id}).pluck().get()
|
||||||
const guildID = discord.channels.get(channelID)?.["guild_id"]
|
const guildID = discord.channels.get(channelID)?.["guild_id"]
|
||||||
let matrixOnlyReason = null
|
let matrixOnlyReason = null
|
||||||
const matrixOnlyConclusion = "So the emoji will be uploaded on Matrix-side only. It will still be usable over the bridge, but may have degraded functionality."
|
const matrixOnlyConclusion = "So the emoji will be uploaded on Matrix-side only. It will still be usable over the bridge, but may have degraded functionality."
|
||||||
|
|
|
@ -8,7 +8,8 @@ INSERT INTO channel_room (channel_id, room_id, name, nick, thread_parent, custom
|
||||||
('497161350934560778', '!CzvdIdUQXgUjDVKxeU:cadence.moe', 'amanda-spam', NULL, NULL, NULL),
|
('497161350934560778', '!CzvdIdUQXgUjDVKxeU:cadence.moe', 'amanda-spam', NULL, NULL, NULL),
|
||||||
('160197704226439168', '!hYnGGlPHlbujVVfktC:cadence.moe', 'the-stanley-parable-channel', 'bots', NULL, NULL),
|
('160197704226439168', '!hYnGGlPHlbujVVfktC:cadence.moe', 'the-stanley-parable-channel', 'bots', NULL, NULL),
|
||||||
('1100319550446252084', '!BnKuBPCvyfOkhcUjEu:cadence.moe', 'worm-farm', NULL, NULL, NULL),
|
('1100319550446252084', '!BnKuBPCvyfOkhcUjEu:cadence.moe', 'worm-farm', NULL, NULL, NULL),
|
||||||
('297272183716052993', '!rEOspnYqdOalaIFniV:cadence.moe', 'general', NULL, NULL, NULL);
|
('297272183716052993', '!rEOspnYqdOalaIFniV:cadence.moe', 'general', NULL, NULL, NULL),
|
||||||
|
('122155380120748034', '!cqeGDbPiMFAhLsqqqq:cadence.moe', 'cadences-mind', 'coding', NULL, NULL);
|
||||||
|
|
||||||
INSERT INTO sim (user_id, sim_name, localpart, mxid) VALUES
|
INSERT INTO sim (user_id, sim_name, localpart, mxid) VALUES
|
||||||
('0', 'bot', '_ooye_bot', '@_ooye_bot:cadence.moe'),
|
('0', 'bot', '_ooye_bot', '@_ooye_bot:cadence.moe'),
|
||||||
|
@ -72,7 +73,7 @@ INSERT INTO file (discord_url, mxc_url) VALUES
|
||||||
('https://cdn.discordapp.com/emojis/393635038903926784.gif', 'mxc://cadence.moe/WbYqNlACRuicynBfdnPYtmvc'),
|
('https://cdn.discordapp.com/emojis/393635038903926784.gif', 'mxc://cadence.moe/WbYqNlACRuicynBfdnPYtmvc'),
|
||||||
('https://cdn.discordapp.com/attachments/176333891320283136/1157854643037163610/Screenshot_20231001_034036.jpg', 'mxc://cadence.moe/zAXdQriaJuLZohDDmacwWWDR');
|
('https://cdn.discordapp.com/attachments/176333891320283136/1157854643037163610/Screenshot_20231001_034036.jpg', 'mxc://cadence.moe/zAXdQriaJuLZohDDmacwWWDR');
|
||||||
|
|
||||||
INSERT INTO emoji (id, name, animated, mxc_url) VALUES
|
INSERT INTO emoji (emoji_id, name, animated, mxc_url) VALUES
|
||||||
('230201364309868544', 'hippo', 0, 'mxc://cadence.moe/qWmbXeRspZRLPcjseyLmeyXC'),
|
('230201364309868544', 'hippo', 0, 'mxc://cadence.moe/qWmbXeRspZRLPcjseyLmeyXC'),
|
||||||
('393635038903926784', 'hipposcope', 1, 'mxc://cadence.moe/WbYqNlACRuicynBfdnPYtmvc'),
|
('393635038903926784', 'hipposcope', 1, 'mxc://cadence.moe/WbYqNlACRuicynBfdnPYtmvc'),
|
||||||
('362741439211503616', 'bn_re', 0, 'mxc://cadence.moe/OIpqpfxTnHKokcsYqDusxkBT'),
|
('362741439211503616', 'bn_re', 0, 'mxc://cadence.moe/OIpqpfxTnHKokcsYqDusxkBT'),
|
||||||
|
|
Loading…
Reference in a new issue