finally got the thread's early messages working
This commit is contained in:
		
							parent
							
								
									180708b60e
								
							
						
					
					
						commit
						6d1635539b
					
				
					 11 changed files with 321 additions and 32 deletions
				
			
		| 
						 | 
				
			
			@ -65,6 +65,29 @@ function getDiscordParseCallbacks(message, useHTML) {
 | 
			
		|||
async function messageToEvent(message, guild, options = {}, di) {
 | 
			
		||||
	const events = []
 | 
			
		||||
 | 
			
		||||
	if (message.type === DiscordTypes.MessageType.ThreadCreated) {
 | 
			
		||||
		// This is the kind of message that appears when somebody makes a thread which isn't close enough to the message it's based off.
 | 
			
		||||
		// It lacks the lines and the pill, so it looks kind of like a member join message, and it says:
 | 
			
		||||
		// [#] NICKNAME started a thread: __THREAD NAME__. __See all threads__
 | 
			
		||||
		// We're already bridging the THREAD_CREATED gateway event to make a comparable message, so drop this one.
 | 
			
		||||
		return []
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	if (message.type === DiscordTypes.MessageType.ThreadStarterMessage) {
 | 
			
		||||
		// This is the message that appears at the top of a thread when the thread was based off an existing message.
 | 
			
		||||
		// It's just a message reference, no content.
 | 
			
		||||
		const ref = message.message_reference
 | 
			
		||||
		assert(ref)
 | 
			
		||||
		assert(ref.message_id)
 | 
			
		||||
		const row = db.prepare("SELECT room_id, event_id FROM event_message INNER JOIN channel_room USING (channel_id) WHERE channel_id = ? AND message_id = ?").get(ref.channel_id, ref.message_id)
 | 
			
		||||
		if (!row) return []
 | 
			
		||||
		const event = await di.api.getEvent(row.room_id, row.event_id)
 | 
			
		||||
		return [{
 | 
			
		||||
			...event.content,
 | 
			
		||||
			$type: event.type
 | 
			
		||||
		}]
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	/**
 | 
			
		||||
	   @type {{room?: boolean, user_ids?: string[]}}
 | 
			
		||||
		We should consider the following scenarios for mentions:
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -341,3 +341,25 @@ test("message2event: type 4 channel name change", async t => {
 | 
			
		|||
		formatted_body: "changed the channel name to <strong>worming</strong>"
 | 
			
		||||
	}])
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
test("message2event: thread start message reference", async t => {
 | 
			
		||||
	const events = await messageToEvent(data.special_message.thread_start_context, data.guild.general, {}, {
 | 
			
		||||
		api: {
 | 
			
		||||
			getEvent: mockGetEvent(t, "!PnyBKvUBOhjuCucEfk:cadence.moe", "$FchUVylsOfmmbj-VwEs5Z9kY49_dt2zd0vWfylzy5Yo", {
 | 
			
		||||
				"type": "m.room.message",
 | 
			
		||||
				"sender": "@_ooye_cadence:cadence.moe",
 | 
			
		||||
				"content": {
 | 
			
		||||
					"m.mentions": {},
 | 
			
		||||
					"msgtype": "m.text",
 | 
			
		||||
					"body": "layer 4"
 | 
			
		||||
				}
 | 
			
		||||
			})
 | 
			
		||||
		}
 | 
			
		||||
	})
 | 
			
		||||
	t.deepEqual(events, [{
 | 
			
		||||
		$type: "m.room.message",
 | 
			
		||||
		msgtype: "m.text",
 | 
			
		||||
		body: "layer 4",
 | 
			
		||||
		"m.mentions": {}
 | 
			
		||||
	}])
 | 
			
		||||
})
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
							
								
								
									
										46
									
								
								d2m/converters/thread-to-announcement.js
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										46
									
								
								d2m/converters/thread-to-announcement.js
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,46 @@
 | 
			
		|||
// @ts-check
 | 
			
		||||
 | 
			
		||||
const assert = require("assert")
 | 
			
		||||
 | 
			
		||||
const passthrough = require("../../passthrough")
 | 
			
		||||
const { discord, sync, db } = passthrough
 | 
			
		||||
/** @type {import("../../matrix/read-registration")} */
 | 
			
		||||
const reg = sync.require("../../matrix/read-registration.js")
 | 
			
		||||
 | 
			
		||||
const userRegex = reg.namespaces.users.map(u => new RegExp(u.regex))
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @param {string} parentRoomID
 | 
			
		||||
 * @param {string} threadRoomID
 | 
			
		||||
 * @param {string?} creatorMxid
 | 
			
		||||
 * @param {import("discord-api-types/v10").APIThreadChannel} thread
 | 
			
		||||
 * @param {{api: import("../../matrix/api")}} di simple-as-nails dependency injection for the matrix API
 | 
			
		||||
 */
 | 
			
		||||
async function threadToAnnouncement(parentRoomID, threadRoomID, creatorMxid, thread, di) {
 | 
			
		||||
	/** @type {string?} */
 | 
			
		||||
	const branchedFromEventID = db.prepare("SELECT event_id FROM event_message WHERE message_id = ?").pluck().get(thread.id)
 | 
			
		||||
	/** @type {{"m.mentions"?: any, "m.in_reply_to"?: any}} */
 | 
			
		||||
	const context = {}
 | 
			
		||||
	if (branchedFromEventID) {
 | 
			
		||||
		// Need to figure out who sent that event...
 | 
			
		||||
		const event = await di.api.getEvent(parentRoomID, branchedFromEventID)
 | 
			
		||||
		context["m.relates_to"] = {"m.in_reply_to": {event_id: event.event_id}}
 | 
			
		||||
		if (event.sender && !userRegex.some(rx => event.sender.match(rx))) context["m.mentions"] = {user_ids: [event.sender]}
 | 
			
		||||
	}
 | 
			
		||||
 | 
			
		||||
	const msgtype = creatorMxid ? "m.emote" : "m.text"
 | 
			
		||||
	const template = creatorMxid ? "started a thread:" : "Thread started:"
 | 
			
		||||
	let body = `${template} ${thread.name} https://matrix.to/#/${threadRoomID}`
 | 
			
		||||
	let html = `${template} <a href="https://matrix.to/#/${threadRoomID}">${thread.name}</a>`
 | 
			
		||||
 | 
			
		||||
	return {
 | 
			
		||||
		msgtype,
 | 
			
		||||
		body,
 | 
			
		||||
		format: "org.matrix.custom.html",
 | 
			
		||||
		formatted_body: html,
 | 
			
		||||
		"m.mentions": {},
 | 
			
		||||
		...context
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports.threadToAnnouncement = threadToAnnouncement
 | 
			
		||||
							
								
								
									
										150
									
								
								d2m/converters/thread-to-announcement.test.js
									
										
									
									
									
										Normal file
									
								
							
							
						
						
									
										150
									
								
								d2m/converters/thread-to-announcement.test.js
									
										
									
									
									
										Normal file
									
								
							| 
						 | 
				
			
			@ -0,0 +1,150 @@
 | 
			
		|||
const {test} = require("supertape")
 | 
			
		||||
const {threadToAnnouncement} = require("./thread-to-announcement")
 | 
			
		||||
const data = require("../../test/data")
 | 
			
		||||
const Ty = require("../../types")
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @param {string} roomID
 | 
			
		||||
 * @param {string} eventID
 | 
			
		||||
 * @returns {(roomID: string, eventID: string) => Promise<Ty.Event.Outer<Ty.Event.M_Room_Message>>}
 | 
			
		||||
 */
 | 
			
		||||
function mockGetEvent(t, roomID_in, eventID_in, outer) {
 | 
			
		||||
	return async function(roomID, eventID) {
 | 
			
		||||
		t.equal(roomID, roomID_in)
 | 
			
		||||
		t.equal(eventID, eventID_in)
 | 
			
		||||
		return new Promise(resolve => {
 | 
			
		||||
			setTimeout(() => {
 | 
			
		||||
				resolve({
 | 
			
		||||
					event_id: eventID_in,
 | 
			
		||||
					room_id: roomID_in,
 | 
			
		||||
					origin_server_ts: 1680000000000,
 | 
			
		||||
					unsigned: {
 | 
			
		||||
						age: 2245,
 | 
			
		||||
						transaction_id: "$local.whatever"
 | 
			
		||||
					},
 | 
			
		||||
					...outer
 | 
			
		||||
				})
 | 
			
		||||
			})
 | 
			
		||||
		})
 | 
			
		||||
	}
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
test("thread2announcement: no known creator, no branched from event", async t => {
 | 
			
		||||
	const content = await threadToAnnouncement("!parent", "!thread", null, {
 | 
			
		||||
		name: "test thread",
 | 
			
		||||
		id: "-1"
 | 
			
		||||
	})
 | 
			
		||||
	t.deepEqual(content, {
 | 
			
		||||
		msgtype: "m.text",
 | 
			
		||||
		body: "Thread started: test thread https://matrix.to/#/!thread",
 | 
			
		||||
		format: "org.matrix.custom.html",
 | 
			
		||||
		formatted_body: `Thread started: <a href="https://matrix.to/#/!thread">test thread</a>`,
 | 
			
		||||
		"m.mentions": {}
 | 
			
		||||
	})
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
test("thread2announcement: known creator, no branched from event", async t => {
 | 
			
		||||
	const content = await threadToAnnouncement("!parent", "!thread", "@_ooye_crunch_god:cadence.moe", {
 | 
			
		||||
		name: "test thread",
 | 
			
		||||
		id: "-1"
 | 
			
		||||
	})
 | 
			
		||||
	t.deepEqual(content, {
 | 
			
		||||
		msgtype: "m.emote",
 | 
			
		||||
		body: "started a thread: test thread https://matrix.to/#/!thread",
 | 
			
		||||
		format: "org.matrix.custom.html",
 | 
			
		||||
		formatted_body: `started a thread: <a href="https://matrix.to/#/!thread">test thread</a>`,
 | 
			
		||||
		"m.mentions": {}
 | 
			
		||||
	})
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
test("thread2announcement: no known creator, branched from discord event", async t => {
 | 
			
		||||
	const content = await threadToAnnouncement("!kLRqKKUQXcibIMtOpl:cadence.moe", "!thread", null, {
 | 
			
		||||
		name: "test thread",
 | 
			
		||||
		id: "1126786462646550579"
 | 
			
		||||
	}, {
 | 
			
		||||
		api: {
 | 
			
		||||
			getEvent: mockGetEvent(t, "!kLRqKKUQXcibIMtOpl:cadence.moe", "$X16nfVks1wsrhq4E9SSLiqrf2N8KD0erD0scZG7U5xg", {
 | 
			
		||||
				type: 'm.room.message',
 | 
			
		||||
				sender: '@_ooye_bot:cadence.moe',
 | 
			
		||||
				content: {
 | 
			
		||||
					msgtype: 'm.text',
 | 
			
		||||
					body: 'testing testing testing'
 | 
			
		||||
				}
 | 
			
		||||
			})
 | 
			
		||||
		}
 | 
			
		||||
	})
 | 
			
		||||
	t.deepEqual(content, {
 | 
			
		||||
		msgtype: "m.text",
 | 
			
		||||
		body: "Thread started: test thread https://matrix.to/#/!thread",
 | 
			
		||||
		format: "org.matrix.custom.html",
 | 
			
		||||
		formatted_body: `Thread started: <a href="https://matrix.to/#/!thread">test thread</a>`,
 | 
			
		||||
		"m.mentions": {},
 | 
			
		||||
		"m.relates_to": {
 | 
			
		||||
			"m.in_reply_to": {
 | 
			
		||||
				event_id: "$X16nfVks1wsrhq4E9SSLiqrf2N8KD0erD0scZG7U5xg"
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	})
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
test("thread2announcement: known creator, branched from discord event", async t => {
 | 
			
		||||
	const content = await threadToAnnouncement("!kLRqKKUQXcibIMtOpl:cadence.moe", "!thread", "@_ooye_crunch_god:cadence.moe", {
 | 
			
		||||
		name: "test thread",
 | 
			
		||||
		id: "1126786462646550579"
 | 
			
		||||
	}, {
 | 
			
		||||
		api: {
 | 
			
		||||
			getEvent: mockGetEvent(t, "!kLRqKKUQXcibIMtOpl:cadence.moe", "$X16nfVks1wsrhq4E9SSLiqrf2N8KD0erD0scZG7U5xg", {
 | 
			
		||||
				type: 'm.room.message',
 | 
			
		||||
				sender: '@_ooye_bot:cadence.moe',
 | 
			
		||||
				content: {
 | 
			
		||||
					msgtype: 'm.text',
 | 
			
		||||
					body: 'testing testing testing'
 | 
			
		||||
				}
 | 
			
		||||
			})
 | 
			
		||||
		}
 | 
			
		||||
	})
 | 
			
		||||
	t.deepEqual(content, {
 | 
			
		||||
		msgtype: "m.emote",
 | 
			
		||||
		body: "started a thread: test thread https://matrix.to/#/!thread",
 | 
			
		||||
		format: "org.matrix.custom.html",
 | 
			
		||||
		formatted_body: `started a thread: <a href="https://matrix.to/#/!thread">test thread</a>`,
 | 
			
		||||
		"m.mentions": {},
 | 
			
		||||
		"m.relates_to": {
 | 
			
		||||
			"m.in_reply_to": {
 | 
			
		||||
				event_id: "$X16nfVks1wsrhq4E9SSLiqrf2N8KD0erD0scZG7U5xg"
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	})
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
test("thread2announcement: no known creator, branched from matrix event", async t => {
 | 
			
		||||
	const content = await threadToAnnouncement("!kLRqKKUQXcibIMtOpl:cadence.moe", "!thread", null, {
 | 
			
		||||
		name: "test thread",
 | 
			
		||||
		id: "1128118177155526666"
 | 
			
		||||
	}, {
 | 
			
		||||
		api: {
 | 
			
		||||
			getEvent: mockGetEvent(t, "!kLRqKKUQXcibIMtOpl:cadence.moe", "$Ij3qo7NxMA4VPexlAiIx2CB9JbsiGhJeyt-2OvkAUe4", {
 | 
			
		||||
				type: "m.room.message",
 | 
			
		||||
				content: {
 | 
			
		||||
					msgtype: "m.text",
 | 
			
		||||
					body: "so can you reply to my webhook uwu"
 | 
			
		||||
				},
 | 
			
		||||
				sender: "@cadence:cadence.moe"
 | 
			
		||||
			})
 | 
			
		||||
		}
 | 
			
		||||
	})
 | 
			
		||||
	t.deepEqual(content, {
 | 
			
		||||
		msgtype: "m.text",
 | 
			
		||||
		body: "Thread started: test thread https://matrix.to/#/!thread",
 | 
			
		||||
		format: "org.matrix.custom.html",
 | 
			
		||||
		formatted_body: `Thread started: <a href="https://matrix.to/#/!thread">test thread</a>`,
 | 
			
		||||
		"m.mentions": {
 | 
			
		||||
			user_ids: ["@cadence:cadence.moe"]
 | 
			
		||||
		},
 | 
			
		||||
		"m.relates_to": {
 | 
			
		||||
			"m.in_reply_to": {
 | 
			
		||||
				event_id: "$Ij3qo7NxMA4VPexlAiIx2CB9JbsiGhJeyt-2OvkAUe4"
 | 
			
		||||
			}
 | 
			
		||||
		}
 | 
			
		||||
	})
 | 
			
		||||
})
 | 
			
		||||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue