2023-06-28 12:06:56 +00:00
const assert = require ( "assert" ) . strict
2023-08-17 13:22:14 +00:00
const util = require ( "util" )
2023-07-03 12:39:42 +00:00
const { sync , db } = require ( "../passthrough" )
2023-05-04 20:25:00 +00:00
/** @type {import("./actions/send-message")}) */
const sendMessage = sync . require ( "./actions/send-message" )
2023-08-17 04:41:28 +00:00
/** @type {import("./actions/edit-message")}) */
const editMessage = sync . require ( "./actions/edit-message" )
2023-08-17 13:22:14 +00:00
/** @type {import("./actions/delete-message")}) */
const deleteMessage = sync . require ( "./actions/delete-message" )
2023-05-09 05:13:59 +00:00
/** @type {import("./actions/add-reaction")}) */
const addReaction = sync . require ( "./actions/add-reaction" )
2023-08-17 13:22:14 +00:00
/** @type {import("../matrix/api")}) */
const api = sync . require ( "../matrix/api" )
let lastReportedEvent = 0
2023-05-04 20:25:00 +00:00
// Grab Discord events we care about for the bridge, check them, and pass them on
2023-04-30 12:57:30 +00:00
2023-04-25 20:06:08 +00:00
module . exports = {
2023-08-17 13:22:14 +00:00
/ * *
* @ 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: ` )
2023-08-18 04:58:46 +00:00
console . dir ( gatewayMessage . d , { depth : null } )
2023-08-17 13:22:14 +00:00
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" ]
}
} )
}
}
} ,
2023-04-25 20:06:08 +00:00
/ * *
* @ param { import ( "./discord-client" ) } client
* @ param { import ( "discord-api-types/v10" ) . GatewayMessageCreateDispatchData } message
* /
2023-08-18 04:58:46 +00:00
async onMessageCreate ( client , message ) {
2023-07-03 12:39:42 +00:00
if ( message . webhook _id ) {
const row = db . prepare ( "SELECT webhook_id FROM webhook WHERE webhook_id = ?" ) . pluck ( ) . get ( message . webhook _id )
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
}
}
2023-07-04 20:41:15 +00:00
/** @type {import("discord-api-types/v10").APIGuildChannel} */
const channel = client . channels . get ( message . channel _id )
if ( ! channel . guild _id ) return // Nothing we can do in direct messages.
const guild = client . guilds . get ( channel . guild _id )
if ( message . guild _id !== "112760669178241024" && message . guild _id !== "497159726455455754" ) return // TODO: activate on other servers (requires the space creation flow to be done first)
2023-08-18 04:58:46 +00:00
await sendMessage . sendMessage ( message , guild )
2023-04-25 20:06:08 +00:00
} ,
2023-08-17 04:41:28 +00:00
/ * *
* @ param { import ( "./discord-client" ) } client
* @ param { import ( "discord-api-types/v10" ) . GatewayMessageUpdateDispatchData } message
* /
2023-08-18 04:58:46 +00:00
async onMessageUpdate ( client , data ) {
2023-08-17 07:03:09 +00:00
if ( data . webhook _id ) {
2023-08-17 13:22:14 +00:00
const row = db . prepare ( "SELECT webhook_id FROM webhook WHERE webhook_id = ?" ) . pluck ( ) . get ( data . webhook _id )
2023-08-17 07:03:09 +00:00
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
}
}
2023-08-17 04:41:28 +00:00
// Based on looking at data they've sent me over the gateway, this is the best way to check for meaningful changes.
// If the message content is a string then it includes all interesting fields and is meaningful.
if ( typeof data . content === "string" ) {
/** @type {import("discord-api-types/v10").GatewayMessageCreateDispatchData} */
const message = data
/** @type {import("discord-api-types/v10").APIGuildChannel} */
const channel = client . channels . get ( message . channel _id )
if ( ! channel . guild _id ) return // Nothing we can do in direct messages.
const guild = client . guilds . get ( channel . guild _id )
if ( message . guild _id !== "112760669178241024" && message . guild _id !== "497159726455455754" ) return // TODO: activate on other servers (requires the space creation flow to be done first)
2023-08-18 04:58:46 +00:00
await editMessage . editMessage ( message , guild )
2023-08-17 04:41:28 +00:00
}
} ,
2023-04-25 20:06:08 +00:00
/ * *
* @ param { import ( "./discord-client" ) } client
* @ param { import ( "discord-api-types/v10" ) . GatewayMessageReactionAddDispatchData } data
* /
2023-08-18 04:58:46 +00:00
async onReactionAdd ( client , data ) {
2023-07-04 20:41:15 +00:00
if ( data . user _id === client . user . id ) return // m2d reactions are added by the discord bot user - do not reflect them back to matrix.
2023-06-28 11:38:58 +00:00
if ( data . emoji . id !== null ) return // TODO: image emoji reactions
2023-04-25 20:06:08 +00:00
console . log ( data )
2023-08-18 04:58:46 +00:00
await addReaction . addReaction ( data )
2023-08-17 13:22:14 +00:00
} ,
/ * *
* @ param { import ( "./discord-client" ) } client
* @ param { import ( "discord-api-types/v10" ) . GatewayMessageDeleteDispatchData } data
* /
2023-08-18 04:58:46 +00:00
async onMessageDelete ( client , data ) {
2023-08-17 13:22:14 +00:00
console . log ( data )
2023-08-18 04:58:46 +00:00
await deleteMessage . deleteMessage ( data )
2023-04-25 20:06:08 +00:00
}
}