add error handler and message deleter
This commit is contained in:
		
							parent
							
								
									e3737997ec
								
							
						
					
					
						commit
						6de13338a8
					
				
					 3 changed files with 100 additions and 8 deletions
				
			
		
							
								
								
									
										29
									
								
								d2m/actions/delete-message.js
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										29
									
								
								d2m/actions/delete-message.js
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,29 @@
 | 
			
		|||
// @ts-check
 | 
			
		||||
 | 
			
		||||
const passthrough = require("../../passthrough")
 | 
			
		||||
const { sync, db } = passthrough
 | 
			
		||||
/** @type {import("../converters/edit-to-changes")} */
 | 
			
		||||
const editToChanges = sync.require("../converters/edit-to-changes")
 | 
			
		||||
/** @type {import("../../matrix/api")} */
 | 
			
		||||
const api = sync.require("../../matrix/api")
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @param {import("discord-api-types/v10").GatewayMessageDeleteDispatchData} data
 | 
			
		||||
 */
 | 
			
		||||
async function deleteMessage(data) {
 | 
			
		||||
	/** @type {string?} */
 | 
			
		||||
	const roomID = db.prepare("SELECT channel_id FROM channel_room WHERE channel_id = ?").pluck().get(data.channel_id)
 | 
			
		||||
	if (!roomID) return
 | 
			
		||||
 | 
			
		||||
	/** @type {string[]} */
 | 
			
		||||
	const eventsToRedact = db.prepare("SELECT event_id FROM event_message WHERE message_id = ?").pluck().all(data.id)
 | 
			
		||||
 | 
			
		||||
	for (const eventID of eventsToRedact) {
 | 
			
		||||
		// Unfortuately, 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)
 | 
			
		||||
		db.prepare("DELETE from event_message WHERE event_id = ?").run(eventID)
 | 
			
		||||
		// TODO: Consider whether this code could be reused between edited messages and deleted messages.
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports.deleteMessage = deleteMessage
 | 
			
		||||
| 
						 | 
				
			
			@ -16,6 +16,7 @@ const utils = {
 | 
			
		|||
		/** @type {typeof import("./event-dispatcher")} */
 | 
			
		||||
		const eventDispatcher = sync.require("./event-dispatcher")
 | 
			
		||||
 | 
			
		||||
		// Client internals, keep track of the state we need
 | 
			
		||||
		if (message.t === "READY") {
 | 
			
		||||
			if (client.ready) return
 | 
			
		||||
			client.ready = true
 | 
			
		||||
| 
						 | 
				
			
			@ -62,17 +63,26 @@ const utils = {
 | 
			
		|||
					}
 | 
			
		||||
				}
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
		} else if (message.t === "MESSAGE_CREATE") {
 | 
			
		||||
		// Event dispatcher for OOYE bridge operations
 | 
			
		||||
		try {
 | 
			
		||||
			if (message.t === "MESSAGE_CREATE") {
 | 
			
		||||
				eventDispatcher.onMessageCreate(client, message.d)
 | 
			
		||||
 | 
			
		||||
			} else if (message.t === "MESSAGE_UPDATE") {
 | 
			
		||||
				eventDispatcher.onMessageUpdate(client, message.d)
 | 
			
		||||
 | 
			
		||||
			} else if (message.t === "MESSAGE_DELETE") {
 | 
			
		||||
				eventDispatcher.onMessageDelete(client, message.d)
 | 
			
		||||
 | 
			
		||||
			} else if (message.t === "MESSAGE_REACTION_ADD") {
 | 
			
		||||
				eventDispatcher.onReactionAdd(client, message.d)
 | 
			
		||||
			}
 | 
			
		||||
		} catch (e) {
 | 
			
		||||
			// Let OOYE try to handle errors too
 | 
			
		||||
			eventDispatcher.onError(client, e, message)
 | 
			
		||||
		}
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -1,17 +1,61 @@
 | 
			
		|||
const assert = require("assert").strict
 | 
			
		||||
const util = require("util")
 | 
			
		||||
const {sync, db} = require("../passthrough")
 | 
			
		||||
 | 
			
		||||
/** @type {import("./actions/send-message")}) */
 | 
			
		||||
const sendMessage = sync.require("./actions/send-message")
 | 
			
		||||
/** @type {import("./actions/edit-message")}) */
 | 
			
		||||
const editMessage = sync.require("./actions/edit-message")
 | 
			
		||||
 | 
			
		||||
/** @type {import("./actions/delete-message")}) */
 | 
			
		||||
const deleteMessage = sync.require("./actions/delete-message")
 | 
			
		||||
/** @type {import("./actions/add-reaction")}) */
 | 
			
		||||
const addReaction = sync.require("./actions/add-reaction")
 | 
			
		||||
/** @type {import("../matrix/api")}) */
 | 
			
		||||
const api = sync.require("../matrix/api")
 | 
			
		||||
 | 
			
		||||
let lastReportedEvent = 0
 | 
			
		||||
 | 
			
		||||
// Grab Discord events we care about for the bridge, check them, and pass them on
 | 
			
		||||
 | 
			
		||||
module.exports = {
 | 
			
		||||
	/**
 | 
			
		||||
	 * @param {import("./discord-client")} client
 | 
			
		||||
	 * @param {Error} e
 | 
			
		||||
	 * @param {import("cloudstorm").IGatewayMessage} gatewayMessage
 | 
			
		||||
	 */
 | 
			
		||||
	onError(client, e, gatewayMessage) {
 | 
			
		||||
		console.error("hit event-dispatcher's error handler with this exception:")
 | 
			
		||||
		console.error(e) // TODO: also log errors into a file or into the database, maybe use a library for this? or just wing it? definitely need to be able to store the formatted event body to load back in later
 | 
			
		||||
		console.error(`while handling this ${gatewayMessage.t} gateway event:`)
 | 
			
		||||
		console.dir(gatewayMessage.d)
 | 
			
		||||
 | 
			
		||||
		if (Date.now() - lastReportedEvent > 5000) {
 | 
			
		||||
			lastReportedEvent = Date.now()
 | 
			
		||||
			const channelID = gatewayMessage.d.channel_id
 | 
			
		||||
			if (channelID) {
 | 
			
		||||
				const roomID = db.prepare("SELECT room_id FROM channel_room WHERE channel_id = ?").pluck().get(channelID)
 | 
			
		||||
				let stackLines = e.stack.split("\n")
 | 
			
		||||
				let cloudstormLine = stackLines.findIndex(l => l.includes("/node_modules/cloudstorm/"))
 | 
			
		||||
				if (cloudstormLine !== -1) {
 | 
			
		||||
					stackLines = stackLines.slice(0, cloudstormLine - 2)
 | 
			
		||||
				}
 | 
			
		||||
				api.sendEvent(roomID, "m.room.message", {
 | 
			
		||||
					msgtype: "m.text",
 | 
			
		||||
					body: "\u26a0 Bridged event from Discord not delivered. See formatted content for full details.",
 | 
			
		||||
					format: "org.matrix.custom.html",
 | 
			
		||||
					formatted_body: "\u26a0 <strong>Bridged event from Discord not delivered</strong>"
 | 
			
		||||
						+ `<br>Gateway event: ${gatewayMessage.t}`
 | 
			
		||||
						+ `<pre>${stackLines.join("\n")}</pre>`
 | 
			
		||||
						+ `<details><summary>Original payload</summary>`
 | 
			
		||||
						+ `<pre>${util.inspect(gatewayMessage.d, false, 4, false)}</pre></details>`,
 | 
			
		||||
					"m.mentions": {
 | 
			
		||||
						user_ids: ["@cadence:cadence.moe"]
 | 
			
		||||
					}
 | 
			
		||||
				})
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	},
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * @param {import("./discord-client")} client
 | 
			
		||||
	 * @param {import("discord-api-types/v10").GatewayMessageCreateDispatchData} message
 | 
			
		||||
| 
						 | 
				
			
			@ -38,7 +82,7 @@ module.exports = {
 | 
			
		|||
	 */
 | 
			
		||||
	onMessageUpdate(client, data) {
 | 
			
		||||
		if (data.webhook_id) {
 | 
			
		||||
			const row = db.prepare("SELECT webhook_id FROM webhook WHERE webhook_id = ?").pluck().get(message.webhook_id)
 | 
			
		||||
			const row = db.prepare("SELECT webhook_id FROM webhook WHERE webhook_id = ?").pluck().get(data.webhook_id)
 | 
			
		||||
			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
 | 
			
		||||
| 
						 | 
				
			
			@ -67,5 +111,14 @@ module.exports = {
 | 
			
		|||
		if (data.emoji.id !== null) return // TODO: image emoji reactions
 | 
			
		||||
		console.log(data)
 | 
			
		||||
		addReaction.addReaction(data)
 | 
			
		||||
	},
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	 * @param {import("./discord-client")} client
 | 
			
		||||
	 * @param {import("discord-api-types/v10").GatewayMessageDeleteDispatchData} data
 | 
			
		||||
	 */
 | 
			
		||||
	onMessageDelete(client, data) {
 | 
			
		||||
		console.log(data)
 | 
			
		||||
		deleteMessage.deleteMessage(data)
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue