1
0
Fork 0

show member details on discord from cache

This commit is contained in:
Cadence Ember 2023-08-26 22:22:54 +12:00
parent 0ea2b4efc9
commit 3ebfa8e3a7
4 changed files with 68 additions and 25 deletions

View file

@ -47,6 +47,13 @@ CREATE TABLE IF NOT EXISTS "event_message" (
"source" INTEGER NOT NULL, "source" INTEGER NOT NULL,
PRIMARY KEY("event_id","message_id") 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; 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/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'); ('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; COMMIT;

View file

@ -9,6 +9,8 @@ const passthrough = require("../../passthrough")
const { sync, db, discord } = passthrough const { sync, db, discord } = passthrough
/** @type {import("../../matrix/file")} */ /** @type {import("../../matrix/file")} */
const file = sync.require("../../matrix/file") const file = sync.require("../../matrix/file")
/** @type {import("../converters/utils")} */
const utils = sync.require("../converters/utils")
const BLOCK_ELEMENTS = [ const BLOCK_ELEMENTS = [
"ADDRESS", "ARTICLE", "ASIDE", "AUDIO", "BLOCKQUOTE", "BODY", "CANVAS", "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 {Ty.Event.Outer<Ty.Event.M_Room_Message>} event
* @param {import("discord-api-types/v10").APIGuild} guild * @param {import("discord-api-types/v10").APIGuild} guild
@ -81,11 +99,13 @@ async function eventToMessage(event, guild, di) {
let displayName = event.sender let displayName = event.sender
let avatarURL = undefined let avatarURL = undefined
let replyLine = "" let replyLine = ""
// Extract a basic display name from the sender
const match = event.sender.match(/^@(.*?):/) const match = event.sender.match(/^@(.*?):/)
if (match) { if (match) displayName = match[1]
displayName = match[1] // Try to extract an accurate display name and avatar URL from the member event
// TODO: get the media repo domain and the avatar url from the matrix 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 // Convert content depending on what the message is
let content = event.content.body // ultimate fallback let content = event.content.body // ultimate fallback

View file

@ -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", content: "testing plaintext",
avatar_url: undefined 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>", content: "testing \\*\\*special\\*\\* \\~\\~things\\~\\~ which \\_should\\_ \\*not\\* \\`trigger\\` @any <effects>",
avatar_url: undefined 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~~", content: "this **is** a **_test_** of ~~formatting~~",
avatar_url: undefined 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", content: "this \\*\\*is\\*\\* an **_extreme_** \\\\\\*test\\\\\\* of",
avatar_url: undefined 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", 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 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", content: "line one: test test\nline two: **test** **test**\nline three: **test test**\nline four: test test\n line five",
avatar_url: undefined 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", content: "line one: test test\nline two: **test** **test**\nline three: **test test**\nline four: test test\nline five",
avatar_url: undefined avatar_url: undefined
}] }]
@ -234,7 +234,7 @@ test("event2message: lists are bridged correctly", async t => {
"room_id": "!BpMdOUkWWhFxmTrENV:cadence.moe" "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", content: "* line one\n* line two\n* line three\n * nested one\n * nested two\n* line four",
avatar_url: undefined 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), content: (("a".repeat(130) + " ").repeat(15)).slice(0, -1),
avatar_url: undefined avatar_url: undefined
}, { }, {
username: "cadence", username: "cadence [they]",
content: (("a".repeat(130) + " ").repeat(4)).slice(0, -1), content: (("a".repeat(130) + " ").repeat(4)).slice(0, -1),
avatar_url: undefined 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", content: "preceding\n\n```\ncode block\n```\n\nfollowing `code` is inline",
avatar_url: undefined avatar_url: undefined
}] }]
@ -315,7 +315,7 @@ test("event2message: code block contents are formatted correctly and not escaped
"room_id": "!BpMdOUkWWhFxmTrENV:cadence.moe" "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,`", content: "```\ninput = input.replace(/(<\\/?([^ >]+)[^>]*>)?\\n(<\\/?([^ >]+)[^>]*>)?/g,\n_input_ = input = input.replace(/(<\\/?([^ >]+)[^>]*>)?\\n(<\\/?([^ >]+)[^>]*>)?/g,\n```\n\n`input = input.replace(/(<\\/?([^ >]+)[^>]*>)?\\n(<\\/?([^ >]+)[^>]*>)?/g,`",
avatar_url: undefined 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🤨", content: "> Chancellor of Germany Angela Merkel, on March 17, 2017: they did not shake hands\n🤨",
avatar_url: undefined avatar_url: undefined
}] }]
@ -367,8 +367,8 @@ test("event2message: m.emote markdown syntax is escaped", async t => {
} }
}), }),
[{ [{
username: "cadence", username: "cadence [they]",
content: "\\* cadence shows you \\*\\*her\\*\\* **_extreme_** \\\\\\*test\\\\\\* of", content: "\\* cadence \\[they\\] shows you \\*\\*her\\*\\* **_extreme_** \\\\\\*test\\\\\\* of",
avatar_url: undefined 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", 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!!!**", 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", 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"
}] }]
) )
}) })

View file

@ -19,4 +19,15 @@ function eventSenderIsFromDiscord(sender) {
return false 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.eventSenderIsFromDiscord = eventSenderIsFromDiscord
module.exports.getPublicUrlForMxc = getPublicUrlForMxc