show member details on discord from cache
This commit is contained in:
		
							parent
							
								
									0ea2b4efc9
								
							
						
					
					
						commit
						3ebfa8e3a7
					
				
					 4 changed files with 68 additions and 25 deletions
				
			
		| 
						 | 
				
			
			@ -47,6 +47,13 @@ CREATE TABLE IF NOT EXISTS "event_message" (
 | 
			
		|||
	"source"	INTEGER NOT NULL,
 | 
			
		||||
	PRIMARY KEY("event_id","message_id")
 | 
			
		||||
);
 | 
			
		||||
CREATE TABLE IF NOT EXISTS "member_cache" (
 | 
			
		||||
	"room_id"	TEXT NOT NULL,
 | 
			
		||||
	"mxid"	TEXT NOT NULL,
 | 
			
		||||
	"displayname"	TEXT,
 | 
			
		||||
	"avatar_url"	TEXT,
 | 
			
		||||
	PRIMARY KEY("room_id", "mxid")
 | 
			
		||||
);
 | 
			
		||||
COMMIT;
 | 
			
		||||
 | 
			
		||||
 | 
			
		||||
| 
						 | 
				
			
			@ -101,4 +108,9 @@ INSERT INTO file (discord_url, mxc_url) VALUES
 | 
			
		|||
('https://cdn.discordapp.com/icons/112760669178241024/a_f83622e09ead74f0c5c527fe241f8f8c.png?size=1024', 'mxc://cadence.moe/zKXGZhmImMHuGQZWJEFKJbsF'),
 | 
			
		||||
('https://cdn.discordapp.com/avatars/113340068197859328/b48302623a12bc7c59a71328f72ccb39.png?size=1024', 'mxc://cadence.moe/UpAeIqeclhKfeiZNdIWNcXXL');
 | 
			
		||||
 | 
			
		||||
INSERT INTO member_cache (room_id, mxid, displayname, avatar_url) VALUES
 | 
			
		||||
('!kLRqKKUQXcibIMtOpl:cadence.moe', '@cadence:cadence.moe', 'cadence [they]', NULL),
 | 
			
		||||
('!BpMdOUkWWhFxmTrENV:cadence.moe', '@cadence:cadence.moe', 'cadence [they]', NULL),
 | 
			
		||||
('!fGgIymcYWOqjbSRUdV:cadence.moe', '@cadence:cadence.moe', 'cadence [they]', 'mxc://cadence.moe/azCAhThKTojXSZJRoWwZmhvU');
 | 
			
		||||
 | 
			
		||||
COMMIT;
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -9,6 +9,8 @@ const passthrough = require("../../passthrough")
 | 
			
		|||
const { sync, db, discord } = passthrough
 | 
			
		||||
/** @type {import("../../matrix/file")} */
 | 
			
		||||
const file = sync.require("../../matrix/file")
 | 
			
		||||
/** @type {import("../converters/utils")} */
 | 
			
		||||
const utils = sync.require("../converters/utils")
 | 
			
		||||
 | 
			
		||||
const BLOCK_ELEMENTS = [
 | 
			
		||||
	"ADDRESS", "ARTICLE", "ASIDE", "AUDIO", "BLOCKQUOTE", "BODY", "CANVAS",
 | 
			
		||||
| 
						 | 
				
			
			@ -69,6 +71,22 @@ turndownService.addRule("fencedCodeBlock", {
 | 
			
		|||
	}
 | 
			
		||||
})
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @param {string} roomID
 | 
			
		||||
 * @param {string} mxid
 | 
			
		||||
 * @returns {Promise<{displayname?: string?, avatar_url?: string?}>}
 | 
			
		||||
 */
 | 
			
		||||
async function getMemberFromCacheOrHomeserver(roomID, mxid, api) {
 | 
			
		||||
	const row = db.prepare("SELECT displayname, avatar_url FROM member_cache WHERE room_id = ? AND mxid = ?").get(roomID, mxid)
 | 
			
		||||
	if (row) return row
 | 
			
		||||
	return api.getStateEvent(roomID, "m.room.member", mxid).then(event => {
 | 
			
		||||
		db.prepare("INSERT INTO member_cache (room_id, mxid, displayname, avatar_url) VALUES (?, ?, ?, ?)").run(roomID, mxid, event?.displayname || null, event?.avatar_url || null)
 | 
			
		||||
		return event
 | 
			
		||||
	}).catch(() => {
 | 
			
		||||
		return {displayname: null, avatar_url: null}
 | 
			
		||||
	})
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @param {Ty.Event.Outer<Ty.Event.M_Room_Message>} event
 | 
			
		||||
 * @param {import("discord-api-types/v10").APIGuild} guild
 | 
			
		||||
| 
						 | 
				
			
			@ -81,11 +99,13 @@ async function eventToMessage(event, guild, di) {
 | 
			
		|||
	let displayName = event.sender
 | 
			
		||||
	let avatarURL = undefined
 | 
			
		||||
	let replyLine = ""
 | 
			
		||||
	// Extract a basic display name from the sender
 | 
			
		||||
	const match = event.sender.match(/^@(.*?):/)
 | 
			
		||||
	if (match) {
 | 
			
		||||
		displayName = match[1]
 | 
			
		||||
		// TODO: get the media repo domain and the avatar url from the matrix member event
 | 
			
		||||
	}
 | 
			
		||||
	if (match) displayName = match[1]
 | 
			
		||||
	// Try to extract an accurate display name and avatar URL from the member event
 | 
			
		||||
	const member = await getMemberFromCacheOrHomeserver(event.room_id, event.sender, di?.api)
 | 
			
		||||
	if (member.displayname) displayName = member.displayname
 | 
			
		||||
	if (member.avatar_url) avatarURL = utils.getPublicUrlForMxc(member.avatar_url)
 | 
			
		||||
 | 
			
		||||
	// Convert content depending on what the message is
 | 
			
		||||
	let content = event.content.body // ultimate fallback
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -51,7 +51,7 @@ test("event2message: body is used when there is no formatted_body", async t => {
 | 
			
		|||
			}
 | 
			
		||||
		}),
 | 
			
		||||
		[{
 | 
			
		||||
			username: "cadence",
 | 
			
		||||
			username: "cadence [they]",
 | 
			
		||||
			content: "testing plaintext",
 | 
			
		||||
			avatar_url: undefined
 | 
			
		||||
		}]
 | 
			
		||||
| 
						 | 
				
			
			@ -75,7 +75,7 @@ test("event2message: any markdown in body is escaped", async t => {
 | 
			
		|||
			}
 | 
			
		||||
		}),
 | 
			
		||||
		[{
 | 
			
		||||
			username: "cadence",
 | 
			
		||||
			username: "cadence [they]",
 | 
			
		||||
			content: "testing \\*\\*special\\*\\* \\~\\~things\\~\\~ which \\_should\\_ \\*not\\* \\`trigger\\` @any <effects>",
 | 
			
		||||
			avatar_url: undefined
 | 
			
		||||
		}]
 | 
			
		||||
| 
						 | 
				
			
			@ -101,7 +101,7 @@ test("event2message: basic html is converted to markdown", async t => {
 | 
			
		|||
			}
 | 
			
		||||
		}),
 | 
			
		||||
		[{
 | 
			
		||||
			username: "cadence",
 | 
			
		||||
			username: "cadence [they]",
 | 
			
		||||
			content: "this **is** a **_test_** of ~~formatting~~",
 | 
			
		||||
			avatar_url: undefined
 | 
			
		||||
		}]
 | 
			
		||||
| 
						 | 
				
			
			@ -127,7 +127,7 @@ test("event2message: markdown syntax is escaped", async t => {
 | 
			
		|||
			}
 | 
			
		||||
		}),
 | 
			
		||||
		[{
 | 
			
		||||
			username: "cadence",
 | 
			
		||||
			username: "cadence [they]",
 | 
			
		||||
			content: "this \\*\\*is\\*\\* an **_extreme_** \\\\\\*test\\\\\\* of",
 | 
			
		||||
			avatar_url: undefined
 | 
			
		||||
		}]
 | 
			
		||||
| 
						 | 
				
			
			@ -153,7 +153,7 @@ test("event2message: html lines are bridged correctly", async t => {
 | 
			
		|||
			}
 | 
			
		||||
		}),
 | 
			
		||||
		[{
 | 
			
		||||
			username: "cadence",
 | 
			
		||||
			username: "cadence [they]",
 | 
			
		||||
			content: "paragraph one\nline _two_\nline three\n\nparagraph two\nline _two_\nline three\n\nparagraph three\n\nparagraph four\nline two\nline three\nline four\n\nparagraph five",
 | 
			
		||||
			avatar_url: undefined
 | 
			
		||||
		}]
 | 
			
		||||
| 
						 | 
				
			
			@ -179,7 +179,7 @@ test("event2message: html lines are bridged correctly", async t => {
 | 
			
		|||
			}
 | 
			
		||||
		}),
 | 
			
		||||
		[{
 | 
			
		||||
			username: "cadence",
 | 
			
		||||
			username: "cadence [they]",
 | 
			
		||||
			content: "line one: test       test\nline two: **test**       **test**\nline three: **test       test**\nline four: test       test\n       line five",
 | 
			
		||||
			avatar_url: undefined
 | 
			
		||||
		}]
 | 
			
		||||
| 
						 | 
				
			
			@ -206,7 +206,7 @@ test("event2message: whitespace is collapsed", async t => {
 | 
			
		|||
			}
 | 
			
		||||
		}),
 | 
			
		||||
		[{
 | 
			
		||||
			username: "cadence",
 | 
			
		||||
			username: "cadence [they]",
 | 
			
		||||
			content: "line one: test test\nline two: **test** **test**\nline three: **test test**\nline four: test test\nline five",
 | 
			
		||||
			avatar_url: undefined
 | 
			
		||||
		}]
 | 
			
		||||
| 
						 | 
				
			
			@ -234,7 +234,7 @@ test("event2message: lists are bridged correctly", async t => {
 | 
			
		|||
			"room_id": "!BpMdOUkWWhFxmTrENV:cadence.moe"
 | 
			
		||||
		}),
 | 
			
		||||
		[{
 | 
			
		||||
			username: "cadence",
 | 
			
		||||
			username: "cadence [they]",
 | 
			
		||||
			content: "*   line one\n*   line two\n*   line three\n    *   nested one\n    *   nested two\n*   line four",
 | 
			
		||||
			avatar_url: undefined
 | 
			
		||||
		}]
 | 
			
		||||
| 
						 | 
				
			
			@ -258,11 +258,11 @@ test("event2message: long messages are split", async t => {
 | 
			
		|||
			}
 | 
			
		||||
		}),
 | 
			
		||||
		[{
 | 
			
		||||
			username: "cadence",
 | 
			
		||||
			username: "cadence [they]",
 | 
			
		||||
			content: (("a".repeat(130) + " ").repeat(15)).slice(0, -1),
 | 
			
		||||
			avatar_url: undefined
 | 
			
		||||
		}, {
 | 
			
		||||
			username: "cadence",
 | 
			
		||||
			username: "cadence [they]",
 | 
			
		||||
			content: (("a".repeat(130) + " ").repeat(4)).slice(0, -1),
 | 
			
		||||
			avatar_url: undefined
 | 
			
		||||
		}]
 | 
			
		||||
| 
						 | 
				
			
			@ -288,7 +288,7 @@ test("event2message: code blocks work", async t => {
 | 
			
		|||
			}
 | 
			
		||||
		}),
 | 
			
		||||
		[{
 | 
			
		||||
			username: "cadence",
 | 
			
		||||
			username: "cadence [they]",
 | 
			
		||||
			content: "preceding\n\n```\ncode block\n```\n\nfollowing `code` is inline",
 | 
			
		||||
			avatar_url: undefined
 | 
			
		||||
		}]
 | 
			
		||||
| 
						 | 
				
			
			@ -315,7 +315,7 @@ test("event2message: code block contents are formatted correctly and not escaped
 | 
			
		|||
			"room_id": "!BpMdOUkWWhFxmTrENV:cadence.moe"
 | 
			
		||||
		}),
 | 
			
		||||
		[{
 | 
			
		||||
			username: "cadence",
 | 
			
		||||
			username: "cadence [they]",
 | 
			
		||||
			content: "```\ninput = input.replace(/(<\\/?([^ >]+)[^>]*>)?\\n(<\\/?([^ >]+)[^>]*>)?/g,\n_input_ = input = input.replace(/(<\\/?([^ >]+)[^>]*>)?\\n(<\\/?([^ >]+)[^>]*>)?/g,\n```\n\n`input = input.replace(/(<\\/?([^ >]+)[^>]*>)?\\n(<\\/?([^ >]+)[^>]*>)?/g,`",
 | 
			
		||||
			avatar_url: undefined
 | 
			
		||||
		}]
 | 
			
		||||
| 
						 | 
				
			
			@ -341,7 +341,7 @@ test("event2message: quotes have an appropriate amount of whitespace", async t =
 | 
			
		|||
			}
 | 
			
		||||
		}),
 | 
			
		||||
		[{
 | 
			
		||||
			username: "cadence",
 | 
			
		||||
			username: "cadence [they]",
 | 
			
		||||
			content: "> Chancellor of Germany Angela Merkel, on March 17, 2017: they did not shake hands\n🤨",
 | 
			
		||||
			avatar_url: undefined
 | 
			
		||||
		}]
 | 
			
		||||
| 
						 | 
				
			
			@ -367,8 +367,8 @@ test("event2message: m.emote markdown syntax is escaped", async t => {
 | 
			
		|||
			}
 | 
			
		||||
		}),
 | 
			
		||||
		[{
 | 
			
		||||
			username: "cadence",
 | 
			
		||||
			content: "\\* cadence shows you \\*\\*her\\*\\* **_extreme_** \\\\\\*test\\\\\\* of",
 | 
			
		||||
			username: "cadence [they]",
 | 
			
		||||
			content: "\\* cadence \\[they\\] shows you \\*\\*her\\*\\* **_extreme_** \\\\\\*test\\\\\\* of",
 | 
			
		||||
			avatar_url: undefined
 | 
			
		||||
		}]
 | 
			
		||||
	)
 | 
			
		||||
| 
						 | 
				
			
			@ -410,9 +410,9 @@ test("event2message: rich reply to a sim user", async t => {
 | 
			
		|||
			}
 | 
			
		||||
		}),
 | 
			
		||||
		[{
 | 
			
		||||
			username: "cadence",
 | 
			
		||||
			username: "cadence [they]",
 | 
			
		||||
			content: "<:L1:1144820033948762203><:L2:1144820084079087647>https://discord.com/channels/112760669178241024/687028734322147344/1144865310588014633 <@111604486476181504>: Slow news day.\nTesting this reply, ignore",
 | 
			
		||||
			avatar_url: undefined
 | 
			
		||||
			avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU"
 | 
			
		||||
		}]
 | 
			
		||||
	)
 | 
			
		||||
})
 | 
			
		||||
| 
						 | 
				
			
			@ -455,9 +455,9 @@ test("event2message: rich reply to a matrix user's long message with formatting"
 | 
			
		|||
			}
 | 
			
		||||
		}),
 | 
			
		||||
		[{
 | 
			
		||||
			username: "cadence",
 | 
			
		||||
			username: "cadence [they]",
 | 
			
		||||
			content: "<:L1:1144820033948762203><:L2:1144820084079087647>https://discord.com/channels/112760669178241024/687028734322147344/1144865310588014633 Ⓜ️**cadence**: i should have a little...\n**no you can't!!!**",
 | 
			
		||||
			avatar_url: undefined
 | 
			
		||||
			avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU"
 | 
			
		||||
		}]
 | 
			
		||||
	)
 | 
			
		||||
})
 | 
			
		||||
| 
						 | 
				
			
			@ -500,9 +500,9 @@ test("event2message: with layered rich replies, the preview should only be the r
 | 
			
		|||
			}
 | 
			
		||||
		}),
 | 
			
		||||
		[{
 | 
			
		||||
			username: "cadence",
 | 
			
		||||
			username: "cadence [they]",
 | 
			
		||||
			content: "<:L1:1144820033948762203><:L2:1144820084079087647>https://discord.com/channels/112760669178241024/687028734322147344/1144865310588014633 Ⓜ️**cadence**: two\nthree",
 | 
			
		||||
			avatar_url: undefined
 | 
			
		||||
			avatar_url: "https://matrix.cadence.moe/_matrix/media/r0/download/cadence.moe/azCAhThKTojXSZJRoWwZmhvU"
 | 
			
		||||
		}]
 | 
			
		||||
	)
 | 
			
		||||
})
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
| 
						 | 
				
			
			@ -19,4 +19,15 @@ function eventSenderIsFromDiscord(sender) {
 | 
			
		|||
	return false
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
/**
 | 
			
		||||
 * @param {string} mxc
 | 
			
		||||
 * @returns {string?}
 | 
			
		||||
 */
 | 
			
		||||
function getPublicUrlForMxc(mxc) {
 | 
			
		||||
	const avatarURLParts = mxc?.match(/^mxc:\/\/([^/]+)\/(\w+)$/)
 | 
			
		||||
	if (avatarURLParts) return `https://matrix.cadence.moe/_matrix/media/r0/download/${avatarURLParts[1]}/${avatarURLParts[2]}`
 | 
			
		||||
	else return null
 | 
			
		||||
}
 | 
			
		||||
 | 
			
		||||
module.exports.eventSenderIsFromDiscord = eventSenderIsFromDiscord
 | 
			
		||||
module.exports.getPublicUrlForMxc = getPublicUrlForMxc
 | 
			
		||||
| 
						 | 
				
			
			
 | 
			
		|||
		Loading…
	
	Add table
		Add a link
		
	
		Reference in a new issue