Sync my branches, again #3

Merged
Guzio merged 4 commits from main into fuckery 2026-02-25 09:33:46 +00:00
3 changed files with 23 additions and 43 deletions
Showing only changes of commit d1aa8f01e7 - Show all commits

View file

@ -1,7 +1,7 @@
// @ts-check // @ts-check
const streamr = require("stream") const {Readable} = require("stream")
const {pipeline} = require("stream").promises const {ReadableStream} = require("stream/web")
const {sync} = require("../../passthrough") const {sync} = require("../../passthrough")
const sharp = require("sharp") const sharp = require("sharp")
@ -16,7 +16,7 @@ const HEIGHT = 160
/** /**
* Downloads the sticker from the web and converts to webp data. * Downloads the sticker from the web and converts to webp data.
* @param {string} mxc a single mxc:// URL * @param {string} mxc a single mxc:// URL
* @returns {Promise<Buffer | undefined>} sticker webp data, or undefined if the downloaded sticker is not valid * @returns {Promise<ReadableStream>} sticker webp data, or undefined if the downloaded sticker is not valid
*/ */
async function getAndResizeSticker(mxc) { async function getAndResizeSticker(mxc) {
const res = await api.getMedia(mxc) const res = await api.getMedia(mxc)
@ -24,29 +24,16 @@ async function getAndResizeSticker(mxc) {
const root = await res.json() const root = await res.json()
throw new mreq.MatrixServerError(root, {mxc}) throw new mreq.MatrixServerError(root, {mxc})
} }
const streamIn = streamr.Readable.fromWeb(res.body)
const streamIn = Readable.fromWeb(res.body)
const { stream, mime } = await streamMimeType.getMimeType(streamIn) const { stream, mime } = await streamMimeType.getMimeType(streamIn)
let animated = false const animated = ["image/gif", "image/webp"].includes(mime)
if (mime === "image/gif" || mime === "image/webp") {
animated = true
}
const result = await new Promise((resolve, reject) => { const transformer = sharp({animated: animated})
const transformer = sharp({animated: animated}) .resize(WIDTH, HEIGHT, {fit: "inside", background: {r: 0, g: 0, b: 0, alpha: 0}})
.resize(WIDTH, HEIGHT, {fit: "inside", background: {r: 0, g: 0, b: 0, alpha: 0}}) .webp()
.webp() stream.pipe(transformer)
.toBuffer((err, buffer, info) => { return Readable.toWeb(transformer)
/* c8 ignore next */
if (err) return reject(err)
resolve({info, buffer})
})
pipeline(
stream,
transformer
)
})
return result.buffer
} }

View file

@ -631,17 +631,11 @@ async function eventToMessage(event, guild, channel, di) {
} }
if (event.type === "m.sticker") { if (event.type === "m.sticker") {
content = ""
content += `[${event.content.body}](` // sticker title for fallback if the url preview fails
const afterLink = ")"
// Make sticker URL params
const params = new URLSearchParams()
const withoutMxc = mxUtils.makeMxcPublic(event.content.url) const withoutMxc = mxUtils.makeMxcPublic(event.content.url)
assert(withoutMxc) assert(withoutMxc)
params.append("mxc", withoutMxc) const url = `${reg.ooye.bridge_origin}/download/sticker/${withoutMxc}/_.webp`
const url = `${reg.ooye.bridge_origin}/download/sticker.webp?${params.toString()}` content = `[${event.content.body || "\u2800"}](${url})`
content += url + afterLink
} else if (event.type === "org.matrix.msc3381.poll.start") { } else if (event.type === "org.matrix.msc3381.poll.start") {
const pollContent = event.content["org.matrix.msc3381.poll.start"] // just for convenience const pollContent = event.content["org.matrix.msc3381.poll.start"] // just for convenience
const isClosed = false; const isClosed = false;

View file

@ -28,7 +28,8 @@ const schema = {
e: z.array(z.string()).or(z.string()) e: z.array(z.string()).or(z.string())
}), }),
sticker: z.object({ sticker: z.object({
mxc: z.string() server_name: z.string().regex(/^[^/]+$/),
media_id: z.string().regex(/^[A-Za-z0-9_-]+$/)
}) })
} }
@ -97,15 +98,13 @@ as.router.get(`/download/sheet`, defineEventHandler(async event => {
return buffer return buffer
})) }))
as.router.get(`/download/sticker.webp`, defineEventHandler(async event => { as.router.get(`/download/sticker/:server_name/:media_id/_.webp`, defineEventHandler(async event => {
const query = await getValidatedQuery(event, schema.sticker.parse) 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)
/** remember that these have no mxc:// protocol in the string */ const stream = await sticker.getAndResizeSticker(`mxc://${mxc}`)
verifyMediaHash(query.mxc) setResponseHeader(event, "Content-Type", "image/webp")
const mxc = `mxc://${query.mxc}` return stream
setResponseHeader(event, "Content-Type", 'image/webp')
const buffer = await sticker.getAndResizeSticker(mxc)
return buffer
})) }))