From bb711c26ac6ecfa621a58c9ff712fe1db39143d8 Mon Sep 17 00:00:00 2001 From: Cadence Ember Date: Mon, 12 May 2025 14:30:49 +1200 Subject: [PATCH] API endpoint for message info --- src/matrix/api.js | 9 ++++++ src/web/routes/info.js | 60 +++++++++++++++++++++++++++++++++++++ src/web/routes/info.test.js | 19 ++++++++++++ src/web/server.js | 1 + test/test.js | 1 + 5 files changed, 90 insertions(+) create mode 100644 src/web/routes/info.js create mode 100644 src/web/routes/info.test.js diff --git a/src/matrix/api.js b/src/matrix/api.js index 170802d..eb534c0 100644 --- a/src/matrix/api.js +++ b/src/matrix/api.js @@ -419,6 +419,14 @@ async function setPresence(data, mxid) { await mreq.mreq("PUT", path(`/client/v3/presence/${mxid}/status`, mxid), data) } +/** + * @param {string} mxid + * @returns {Promise<{displayname?: string, avatar_url?: string}>} + */ +function getProfile(mxid) { + return mreq.mreq("GET", `/client/v3/profile/${mxid}`) +} + module.exports.path = path module.exports.register = register module.exports.createRoom = createRoom @@ -452,3 +460,4 @@ module.exports.getAlias = getAlias module.exports.getAccountData = getAccountData module.exports.setAccountData = setAccountData module.exports.setPresence = setPresence +module.exports.getProfile = getProfile diff --git a/src/web/routes/info.js b/src/web/routes/info.js new file mode 100644 index 0000000..1ed615b --- /dev/null +++ b/src/web/routes/info.js @@ -0,0 +1,60 @@ +// @ts-check + +const {z} = require("zod") +const {defineEventHandler, getValidatedQuery, H3Event} = require("h3") +const {as, from, sync, select} = require("../../passthrough") + +/** + * @param {H3Event} event + * @returns {import("../../matrix/api")} + */ +function getAPI(event) { + /* c8 ignore next */ + return event.context.api || sync.require("../../matrix/api") +} + +const schema = { + message: z.object({ + message_id: z.string().regex(/^[0-9]+$/) + }) +} + +as.router.get("/api/message", defineEventHandler(async event => { + const api = getAPI(event) + + const {message_id} = await getValidatedQuery(event, schema.message.parse) + const metadatas = from("event_message").join("message_channel", "message_id").join("channel_room", "channel_id").where({message_id}) + .select("event_id", "event_type", "event_subtype", "part", "reaction_part", "room_id", "source").and("ORDER BY part ASC, reaction_part DESC").all() + + if (metadatas.length === 0) { + return new Response("Message not found", {status: 404, statusText: "Not Found"}) + } + + const events = await Promise.all(metadatas.map(metadata => + api.getEvent(metadata.room_id, metadata.event_id).then(raw => ({ + metadata: Object.assign({sender: raw.sender}, metadata), + raw + })) + )) + + const primary = events.find(e => e.metadata.part === 0) || events[0] + const mxid = primary.metadata.sender + const source = primary.metadata.source === 0 ? "matrix" : "discord" + + let matrix_author = undefined + if (source === "matrix") { + matrix_author = select("member_cache", ["displayname", "avatar_url", "mxid"], {room_id: primary.metadata.room_id, mxid}).get() + if (!matrix_author) { + try { + matrix_author = await api.getProfile(mxid) + } catch (e) { + matrix_author = {} + } + } + if (!matrix_author.displayname) matrix_author.displayname = mxid + if (!matrix_author.avatar_url) matrix_author.avatar_url = null + matrix_author["mxid"] = mxid + } + + return {source, matrix_author, events} +})) diff --git a/src/web/routes/info.test.js b/src/web/routes/info.test.js new file mode 100644 index 0000000..5188198 --- /dev/null +++ b/src/web/routes/info.test.js @@ -0,0 +1,19 @@ +// @ts-check + +const assert = require("assert/strict") +const tryToCatch = require("try-to-catch") +const {router, test} = require("../../../test/web") + +test("web info: 404 when message does not exist", async t => { + const res = await router.test("get", "/api/message?message_id=1", { + api: { + async getEvent(roomID, eventID) { + } + } + }) + t.fail("test not written") +}) + +test("web info: returns data when message exists", async t => { + t.fail("test not written") +}) diff --git a/src/web/server.js b/src/web/server.js index 565f29a..7c8ed3e 100644 --- a/src/web/server.js +++ b/src/web/server.js @@ -29,6 +29,7 @@ sync.require("./routes/download-matrix") sync.require("./routes/download-discord") sync.require("./routes/guild-settings") sync.require("./routes/guild") +sync.require("./routes/info") sync.require("./routes/link") sync.require("./routes/log-in-with-matrix") sync.require("./routes/oauth") diff --git a/test/test.js b/test/test.js index 2d02cbb..3695a84 100644 --- a/test/test.js +++ b/test/test.js @@ -133,6 +133,7 @@ file._actuallyUploadDiscordFileToMxc = function(url, res) { throw new Error(`Not require("../src/web/routes/download-matrix.test") require("../src/web/routes/guild.test") require("../src/web/routes/guild-settings.test") + require("../src/web/routes/info.test") require("../src/web/routes/link.test") require("../src/web/routes/log-in-with-matrix.test") require("../src/discord/utils.test")