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
 | 
			
		||||
	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.
 | 
			
		||||
	assert.equal(typeof parentID, "string")
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -15,7 +15,7 @@ const api = sync.require("../../matrix/api")
 | 
			
		|||
 * @param {import("discord-api-types/v10").APIThreadChannel} 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})
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -71,7 +71,7 @@ async function channelToKState(channel, guild) {
 | 
			
		|||
	const spaceID = await createSpace.ensureSpace(guild)
 | 
			
		||||
	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 customAvatar = row?.custom_avatar
 | 
			
		||||
	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
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	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) {
 | 
			
		||||
		const creation = (async () => {
 | 
			
		||||
| 
						 | 
				
			
			@ -308,9 +308,9 @@ async function _unbridgeRoom(channelID) {
 | 
			
		|||
}
 | 
			
		||||
 | 
			
		||||
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)
 | 
			
		||||
	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)
 | 
			
		||||
 | 
			
		||||
	// 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
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	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) {
 | 
			
		||||
		const creation = (async () => {
 | 
			
		||||
| 
						 | 
				
			
			@ -117,7 +117,7 @@ async function _syncSpace(guild, shouldActuallySync) {
 | 
			
		|||
	const newAvatarState = spaceDiff["m.room.avatar/"]
 | 
			
		||||
	if (guild.icon && newAvatarState?.url) {
 | 
			
		||||
		// 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}) => {
 | 
			
		||||
			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)
 | 
			
		||||
	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)
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -180,7 +180,7 @@ async function syncSpaceFully(guildID) {
 | 
			
		|||
	}).map(({state_key}) => state_key)
 | 
			
		||||
 | 
			
		||||
	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 (discord.channels.has(channelID)) {
 | 
			
		||||
			await createRoom.syncRoom(channelID)
 | 
			
		||||
| 
						 | 
				
			
			@ -198,7 +198,7 @@ async function syncSpaceFully(guildID) {
 | 
			
		|||
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.
 | 
			
		||||
 | 
			
		||||
	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 ("emojis" in data && data.emojis.length) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,10 +9,10 @@ const api = sync.require("../../matrix/api")
 | 
			
		|||
 * @param {import("discord-api-types/v10").GatewayMessageDeleteDispatchData} 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
 | 
			
		||||
 | 
			
		||||
	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) {
 | 
			
		||||
		// 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)
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -51,7 +51,7 @@ async function createSim(user) {
 | 
			
		|||
 */
 | 
			
		||||
async function ensureSim(user) {
 | 
			
		||||
	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) {
 | 
			
		||||
		mxid = existing
 | 
			
		||||
	} else {
 | 
			
		||||
| 
						 | 
				
			
			@ -74,7 +74,7 @@ async function ensureSimJoined(user, roomID) {
 | 
			
		|||
	const mxid = await ensureSim(user)
 | 
			
		||||
 | 
			
		||||
	// 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) {
 | 
			
		||||
		try {
 | 
			
		||||
			await api.inviteToRoom(roomID, mxid)
 | 
			
		||||
| 
						 | 
				
			
			@ -143,7 +143,7 @@ async function syncUser(user, member, guildID, roomID) {
 | 
			
		|||
	const mxid = await ensureSimJoined(user, roomID)
 | 
			
		||||
	const content = await memberToStateContent(user, member, guildID)
 | 
			
		||||
	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
 | 
			
		||||
	if (existingHash !== currentHash) {
 | 
			
		||||
		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) {
 | 
			
		||||
	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")
 | 
			
		||||
 | 
			
		||||
	/** @ts-ignore @type {import("discord-api-types/v10").APIGuildChannel} */
 | 
			
		||||
| 
						 | 
				
			
			@ -164,7 +164,7 @@ async function syncAllUsersInRoom(roomID) {
 | 
			
		|||
	assert.ok(typeof guildID === "string")
 | 
			
		||||
 | 
			
		||||
	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")
 | 
			
		||||
 | 
			
		||||
		/** @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
 | 
			
		||||
 */
 | 
			
		||||
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
 | 
			
		||||
	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
 | 
			
		||||
 | 
			
		||||
	/** @type {Ty.Pagination<Ty.Event.Outer<Ty.Event.M_Reaction>>} */
 | 
			
		||||
| 
						 | 
				
			
			@ -42,7 +42,7 @@ async function removeReaction(data) {
 | 
			
		|||
			}
 | 
			
		||||
			if (!lookingAtMatrixReaction && !wantToRemoveMatrixReaction) {
 | 
			
		||||
				// 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) {
 | 
			
		||||
					await api.redactEvent(roomID, event.event_id, mxid)
 | 
			
		||||
				}
 | 
			
		||||
| 
						 | 
				
			
			@ -55,9 +55,9 @@ async function removeReaction(data) {
 | 
			
		|||
 * @param {import("discord-api-types/v10").GatewayMessageReactionRemoveEmojiDispatchData} 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
 | 
			
		||||
	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
 | 
			
		||||
 | 
			
		||||
	/** @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
 | 
			
		||||
 */
 | 
			
		||||
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
 | 
			
		||||
	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
 | 
			
		||||
 | 
			
		||||
	/** @type {Ty.Pagination<Ty.Event.Outer<Ty.Event.M_Reaction>>} */
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,9 +1,9 @@
 | 
			
		|||
// @ts-check
 | 
			
		||||
 | 
			
		||||
const assert = require("assert")
 | 
			
		||||
const assert = require("assert").strict
 | 
			
		||||
 | 
			
		||||
const passthrough = require("../../passthrough")
 | 
			
		||||
const {discord, sync, db, select} = passthrough
 | 
			
		||||
const {discord, sync, db, select, from} = passthrough
 | 
			
		||||
/** @type {import("./message-to-event")} */
 | 
			
		||||
const messageToEvent = sync.require("../converters/message-to-event")
 | 
			
		||||
/** @type {import("../actions/register-user")} */
 | 
			
		||||
| 
						 | 
				
			
			@ -21,15 +21,12 @@ const createRoom = sync.require("../actions/create-room")
 | 
			
		|||
async function editToChanges(message, guild, api) {
 | 
			
		||||
	// Figure out what events we will be replacing
 | 
			
		||||
 | 
			
		||||
	const roomID = select("channel_room", "room_id", "WHERE channel_id = ?").pluck().get(message.channel_id)
 | 
			
		||||
	let senderMxid = select("sim", "mxid", "WHERE user_id = ?").pluck().get(message.author.id) || null
 | 
			
		||||
	if (senderMxid) {
 | 
			
		||||
		const senderIsInRoom = select("sim_member", "mxid", "WHERE room_id = ? AND mxid = ?").get(roomID, senderMxid)
 | 
			
		||||
		if (!senderIsInRoom) {
 | 
			
		||||
			senderMxid = null // just send as ooye bot
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
	const oldEventRows = select("event_message", ["event_id", "event_type", "event_subtype", "part"], "WHERE message_id = ?").all(message.id)
 | 
			
		||||
	const roomID = select("channel_room", "room_id", {channel_id: message.channel_id}).pluck().get()
 | 
			
		||||
	assert(roomID)
 | 
			
		||||
	/** @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 senderMxid = from("sim").join("sim_member", "mxid").where({user_id: message.author.id}).pluck("mxid").get() || null
 | 
			
		||||
 | 
			
		||||
	const oldEventRows = select("event_message", ["event_id", "event_type", "event_subtype", "part"], {message_id: message.id}).all()
 | 
			
		||||
 | 
			
		||||
	// Figure out what we will be replacing them with
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -14,7 +14,7 @@ async function emojiToKey(emoji) {
 | 
			
		|||
	let key
 | 
			
		||||
	if (emoji.id) {
 | 
			
		||||
		// 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) {
 | 
			
		||||
			// The custom emoji is registered and we should send it
 | 
			
		||||
			key = mxc
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -38,7 +38,7 @@ const Rlottie = (async () => {
 | 
			
		|||
 * @returns {Promise<{mxc_url: string, info: typeof INFO}>}
 | 
			
		||||
 */
 | 
			
		||||
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}
 | 
			
		||||
	const r = await Rlottie
 | 
			
		||||
	const res = await fetch(file.DISCORD_IMAGES_BASE + file.sticker(stickerItem))
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,7 +19,7 @@ function getDiscordParseCallbacks(message, useHTML) {
 | 
			
		|||
	return {
 | 
			
		||||
		/** @param {{id: string, type: "discordUser"}} 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
 | 
			
		||||
			if (mxid && useHTML) {
 | 
			
		||||
				return `<a href="https://matrix.to/#/${mxid}">@${username}</a>`
 | 
			
		||||
| 
						 | 
				
			
			@ -29,7 +29,7 @@ function getDiscordParseCallbacks(message, useHTML) {
 | 
			
		|||
		},
 | 
			
		||||
		/** @param {{id: string, type: "discordChannel"}} 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) {
 | 
			
		||||
				return `<#${node.id}>` // fallback for when this channel is not bridged
 | 
			
		||||
			} else if (useHTML) {
 | 
			
		||||
| 
						 | 
				
			
			@ -41,7 +41,7 @@ function getDiscordParseCallbacks(message, useHTML) {
 | 
			
		|||
		/** @param {{animated: boolean, name: string, id: string, type: "discordEmoji"}} node */
 | 
			
		||||
		emoji: node => {
 | 
			
		||||
			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) {
 | 
			
		||||
					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.
 | 
			
		||||
| 
						 | 
				
			
			@ -85,8 +85,8 @@ async function messageToEvent(message, guild, options = {}, di) {
 | 
			
		|||
		const ref = message.message_reference
 | 
			
		||||
		assert(ref)
 | 
			
		||||
		assert(ref.message_id)
 | 
			
		||||
		const eventID = select("event_message", "event_id", "WHERE message_id = ?").pluck().get(ref.message_id)
 | 
			
		||||
		const roomID = select("channel_room", "room_id", "WHERE channel_id = ?").pluck().get(ref.channel_id)
 | 
			
		||||
		const eventID = select("event_message", "event_id", {message_id: ref.message_id}).pluck().get()
 | 
			
		||||
		const roomID = select("channel_room", "room_id", {channel_id: ref.channel_id}).pluck().get()
 | 
			
		||||
		if (!eventID || !roomID) return []
 | 
			
		||||
		const event = await di.api.getEvent(roomID, eventID)
 | 
			
		||||
		return [{
 | 
			
		||||
| 
						 | 
				
			
			@ -138,8 +138,8 @@ async function messageToEvent(message, guild, options = {}, di) {
 | 
			
		|||
 | 
			
		||||
	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) => {
 | 
			
		||||
			const eventID = select("event_message", "event_id", "WHERE message_id = ?").pluck().get(messageID)
 | 
			
		||||
			const roomID = select("channel_room", "room_id", "WHERE channel_id = ?").pluck().get(channelID)
 | 
			
		||||
			const eventID = select("event_message", "event_id", {message_id: messageID}).pluck().get()
 | 
			
		||||
			const roomID = select("channel_room", "room_id", {channel_id: channelID}).pluck().get()
 | 
			
		||||
			if (eventID && roomID) {
 | 
			
		||||
				return `https://matrix.to/#/${roomID}/${eventID}`
 | 
			
		||||
			} else {
 | 
			
		||||
| 
						 | 
				
			
			@ -155,8 +155,8 @@ async function messageToEvent(message, guild, options = {}, di) {
 | 
			
		|||
			const id = match[3]
 | 
			
		||||
			const name = match[2]
 | 
			
		||||
			const animated = +!!match[1]
 | 
			
		||||
			const row = select("emoji", "id", "WHERE id = ?").pluck().get(id)
 | 
			
		||||
			if (!row) {
 | 
			
		||||
			const exists = select("emoji", "emoji_id", {emoji_id: id}).pluck().get()
 | 
			
		||||
			if (!exists) {
 | 
			
		||||
				// The custom emoji is not registered. We will register it and then add it.
 | 
			
		||||
				emojiDownloads.push(
 | 
			
		||||
					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)]
 | 
			
		||||
			if (matches.length && matches.some(m => m[1].match(/[a-z]/i))) {
 | 
			
		||||
				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)
 | 
			
		||||
				const {joined} = await di.api.getJoinedMembers(roomID)
 | 
			
		||||
				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
 | 
			
		||||
 */
 | 
			
		||||
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}} */
 | 
			
		||||
	const context = {}
 | 
			
		||||
	if (branchedFromEventID) {
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -53,7 +53,7 @@ function userToSimName(user) {
 | 
			
		|||
	assert.notEqual(user.discriminator, "0000", "cannot create user for a webhook")
 | 
			
		||||
 | 
			
		||||
	// 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
 | 
			
		||||
 | 
			
		||||
	// 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
 | 
			
		||||
	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
 | 
			
		||||
	for (const suggestion of generateLocalpartAlternatives(preferences)) {
 | 
			
		||||
		if (!matches.includes(suggestion)) return suggestion
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -46,7 +46,7 @@ module.exports = {
 | 
			
		|||
 | 
			
		||||
		const channelID = gatewayMessage.d.channel_id
 | 
			
		||||
		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
 | 
			
		||||
 | 
			
		||||
		let stackLines = e.stack.split("\n")
 | 
			
		||||
| 
						 | 
				
			
			@ -85,7 +85,7 @@ module.exports = {
 | 
			
		|||
	async checkMissedMessages(client, guild) {
 | 
			
		||||
		if (guild.unavailable) return
 | 
			
		||||
		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)) {
 | 
			
		||||
			if (!bridgedChannels.includes(channel.id)) continue
 | 
			
		||||
			if (!channel.last_message_id) continue
 | 
			
		||||
| 
						 | 
				
			
			@ -129,7 +129,7 @@ module.exports = {
 | 
			
		|||
	 * @param {import("discord-api-types/v10").APIThreadChannel} 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
 | 
			
		||||
		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)
 | 
			
		||||
| 
						 | 
				
			
			@ -140,7 +140,7 @@ module.exports = {
 | 
			
		|||
	 * @param {import("discord-api-types/v10").GatewayGuildUpdateDispatchData} 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
 | 
			
		||||
		await createSpace.syncSpace(guild)
 | 
			
		||||
	},
 | 
			
		||||
| 
						 | 
				
			
			@ -151,7 +151,7 @@ module.exports = {
 | 
			
		|||
	 * @param {boolean} 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
 | 
			
		||||
		await createRoom.syncRoom(channelOrThread.id)
 | 
			
		||||
	},
 | 
			
		||||
| 
						 | 
				
			
			@ -162,7 +162,7 @@ module.exports = {
 | 
			
		|||
	 */
 | 
			
		||||
	async onMessageCreate(client, message) {
 | 
			
		||||
		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) {
 | 
			
		||||
				// 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
 | 
			
		||||
| 
						 | 
				
			
			@ -183,7 +183,7 @@ module.exports = {
 | 
			
		|||
	 */
 | 
			
		||||
	async onMessageUpdate(client, data) {
 | 
			
		||||
		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) {
 | 
			
		||||
				// 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
 | 
			
		||||
| 
						 | 
				
			
			@ -249,9 +249,9 @@ module.exports = {
 | 
			
		|||
	 * @param {import("discord-api-types/v10").GatewayTypingStartDispatchData} 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
 | 
			
		||||
		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
 | 
			
		||||
		// 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.
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue