diff --git a/scripts/setup.js b/scripts/setup.js index 69b62a2..4e6de0a 100644 --- a/scripts/setup.js +++ b/scripts/setup.js @@ -1,7 +1,6 @@ #!/usr/bin/env node // @ts-check -const Ty = require("../src/types") const assert = require("assert").strict const fs = require("fs") const sqlite = require("better-sqlite3") @@ -286,8 +285,8 @@ function defineEchoHandler() { console.log() // Done with user prompts, reg is now guaranteed to be valid - const mreq = require("../src/matrix/mreq") const api = require("../src/matrix/api") + const file = require("../src/matrix/file") const DiscordClient = require("../src/d2m/discord-client") const discord = new DiscordClient(reg.ooye.discord_token, "no") passthrough.discord = discord @@ -344,13 +343,7 @@ function defineEchoHandler() { await api.register(reg.sender_localpart) // upload initial images... - const avatarBuffer = await fs.promises.readFile(join(__dirname, "..", "docs", "img", "icon.png"), null) - /** @type {Ty.R.FileUploaded} */ - const root = await mreq.mreq("POST", "/media/v3/upload", avatarBuffer, { - headers: {"Content-Type": "image/png"} - }) - const avatarUrl = root.content_uri - assert(avatarUrl) + const avatarUrl = await file.uploadDiscordFileToMxc("https://cadence.moe/friends/out_of_your_element.png") console.log("✅ Matrix appservice login works...") @@ -359,7 +352,8 @@ function defineEchoHandler() { console.log("✅ Emojis are ready...") // set profile data on discord... - await discord.snow.user.updateSelf({avatar: "data:image/png;base64," + avatarBuffer.toString("base64")}) + const avatarImageBuffer = await fetch("https://cadence.moe/friends/out_of_your_element.png").then(res => res.arrayBuffer()) + await discord.snow.user.updateSelf({avatar: "data:image/png;base64," + Buffer.from(avatarImageBuffer).toString("base64")}) console.log("✅ Discord profile updated...") // set profile data on homeserver... diff --git a/src/m2d/actions/sticker.js b/src/m2d/actions/sticker.js deleted file mode 100644 index 341d8b0..0000000 --- a/src/m2d/actions/sticker.js +++ /dev/null @@ -1,40 +0,0 @@ -// @ts-check - -const {Readable} = require("stream") -const {ReadableStream} = require("stream/web") - -const {sync} = require("../../passthrough") -const sharp = require("sharp") -/** @type {import("../../matrix/api")} */ -const api = sync.require("../../matrix/api") -/** @type {import("../../matrix/mreq")} */ -const mreq = sync.require("../../matrix/mreq") -const streamMimeType = require("stream-mime-type") - -const WIDTH = 160 -const HEIGHT = 160 -/** - * Downloads the sticker from the web and converts to webp data. - * @param {string} mxc a single mxc:// URL - * @returns {Promise} sticker webp data, or undefined if the downloaded sticker is not valid - */ -async function getAndResizeSticker(mxc) { - const res = await api.getMedia(mxc) - if (res.status !== 200) { - const root = await res.json() - throw new mreq.MatrixServerError(root, {mxc}) - } - - const streamIn = Readable.fromWeb(res.body) - const { stream, mime } = await streamMimeType.getMimeType(streamIn) - const animated = ["image/gif", "image/webp"].includes(mime) - - const transformer = sharp({animated: animated}) - .resize(WIDTH, HEIGHT, {fit: "inside", background: {r: 0, g: 0, b: 0, alpha: 0}}) - .webp() - stream.pipe(transformer) - return Readable.toWeb(transformer) -} - - -module.exports.getAndResizeSticker = getAndResizeSticker diff --git a/src/m2d/converters/event-to-message.js b/src/m2d/converters/event-to-message.js index f4e3ba4..7eee659 100644 --- a/src/m2d/converters/event-to-message.js +++ b/src/m2d/converters/event-to-message.js @@ -633,10 +633,23 @@ async function eventToMessage(event, guild, channel, di) { } if (event.type === "m.sticker") { - const withoutMxc = mxUtils.makeMxcPublic(event.content.url) - assert(withoutMxc) - const url = `${reg.ooye.bridge_origin}/download/sticker/${withoutMxc}/_.webp` - content = `[${event.content.body || "\u2800"}](${url})` + content = "" + let filename = event.content.body + if (event.type === "m.sticker") { + let mimetype + if (event.content.info?.mimetype?.includes("/")) { + mimetype = event.content.info.mimetype + } else { + const res = await di.api.getMedia(event.content.url, {method: "HEAD"}) + if (res.status === 200) { + mimetype = res.headers.get("content-type") + } + if (!mimetype) throw new Error(`Server error ${res.status} or missing content-type while detecting sticker mimetype`) + } + filename += "." + mimetype.split("/")[1] + } + attachments.push({id: "0", filename}) + pendingFiles.push({name: filename, mxc: event.content.url}) } else if (event.type === "org.matrix.msc3381.poll.start") { const pollContent = event.content["org.matrix.msc3381.poll.start"] // just for convenience diff --git a/src/web/routes/download-matrix.js b/src/web/routes/download-matrix.js index 82e2f7e..bb6b850 100644 --- a/src/web/routes/download-matrix.js +++ b/src/web/routes/download-matrix.js @@ -16,9 +16,6 @@ const emojiSheet = sync.require("../../m2d/actions/emoji-sheet") /** @type {import("../../m2d/converters/emoji-sheet")} */ const emojiSheetConverter = sync.require("../../m2d/converters/emoji-sheet") -/** @type {import("../../m2d/actions/sticker")} */ -const sticker = sync.require("../../m2d/actions/sticker") - const schema = { params: z.object({ server_name: z.string(), @@ -26,10 +23,6 @@ const schema = { }), sheet: z.object({ e: z.array(z.string()).or(z.string()) - }), - sticker: z.object({ - server_name: z.string().regex(/^[^/]+$/), - media_id: z.string().regex(/^[A-Za-z0-9_-]+$/) }) } @@ -97,14 +90,3 @@ as.router.get(`/download/sheet`, defineEventHandler(async event => { setResponseHeader(event, "Content-Type", "image/png") return buffer })) - -as.router.get(`/download/sticker/:server_name/:media_id/_.webp`, defineEventHandler(async event => { - const {server_name, media_id} = await getValidatedRouterParams(event, schema.sticker.parse) - /** remember that this has no mxc:// protocol in the string */ - const mxc = server_name + "/" + media_id - verifyMediaHash(mxc) - - const stream = await sticker.getAndResizeSticker(`mxc://${mxc}`) - setResponseHeader(event, "Content-Type", "image/webp") - return stream -}))