From e98af2b2a78463bd64393936dbe223127552bff5 Mon Sep 17 00:00:00 2001 From: Nanaka Hiira Date: Sat, 23 Dec 2023 05:04:54 +0900 Subject: [PATCH] feat: add /api/emojis endpoint --- README.md | 1 + packages/backend/src/server/api/endpoints.ts | 2 + .../src/server/api/endpoints/emojis.ts | 50 +++++++++++++++++++ packages/backend/src/server/web/index.ts | 38 ++++++++++++++ 4 files changed, 91 insertions(+) create mode 100644 packages/backend/src/server/api/endpoints/emojis.ts diff --git a/README.md b/README.md index 6257805a7..0939c3712 100644 --- a/README.md +++ b/README.md @@ -38,6 +38,7 @@ ## 細かい変更点 +- `emojis` の API エンドポイント(Misskey v13- 互換)を追加([firefish-mkdir](https://git.mkdir.uk/hiira/firefish-mkdir) から取り込み) - Docker のベースイメージに Node v21 を使用 - HTML のコードに入るコメントアートを削除 - 全ページにこんなの入れなくても…… diff --git a/packages/backend/src/server/api/endpoints.ts b/packages/backend/src/server/api/endpoints.ts index a3d4e0784..0821d8a27 100644 --- a/packages/backend/src/server/api/endpoints.ts +++ b/packages/backend/src/server/api/endpoints.ts @@ -139,6 +139,7 @@ import * as ep___drive_folders_update from "./endpoints/drive/folders/update.js" import * as ep___drive_stream from "./endpoints/drive/stream.js"; import * as ep___emailAddress_available from "./endpoints/email-address/available.js"; import * as ep___emoji from "./endpoints/emoji.js"; +import * as ep___emojis from "./endpoints/emojis.js"; import * as ep___endpoint from "./endpoints/endpoint.js"; import * as ep___endpoints from "./endpoints/endpoints.js"; import * as ep___exportCustomEmojis from "./endpoints/export-custom-emojis.js"; @@ -496,6 +497,7 @@ const eps = [ ["drive/stream", ep___drive_stream], ["email-address/available", ep___emailAddress_available], ["emoji", ep___emoji], + ["emojis", ep___emojis], ["endpoint", ep___endpoint], ["endpoints", ep___endpoints], ["export-custom-emojis", ep___exportCustomEmojis], diff --git a/packages/backend/src/server/api/endpoints/emojis.ts b/packages/backend/src/server/api/endpoints/emojis.ts new file mode 100644 index 000000000..21de8e358 --- /dev/null +++ b/packages/backend/src/server/api/endpoints/emojis.ts @@ -0,0 +1,50 @@ +import { Emojis } from "@/models/index.js"; +import define from "@/server/api/define.js"; +import { IsNull } from "typeorm"; + +export const meta = { + tags: ["meta"], + + requireCredential: false, + cacheSec: 3600, + + res: { + type: "object", + optional: false, + nullable: false, + properties: { + emojis: { + type: "array", + optional: false, + nullable: false, + items: { + type: "object", + optional: false, + nullable: false, + ref: "Emoji", + }, + }, + }, + }, +} as const; + +export const paramDef = { + type: "object", + properties: {}, + required: [], +} as const; + +export default define(meta, paramDef, async (ps, me) => { + const emojis = await Emojis.find({ + where: { + host: IsNull(), + }, + order: { + category: "ASC", + name: "ASC", + }, + }); + return { + emojis: await Emojis.packMany(emojis), + }; +}); diff --git a/packages/backend/src/server/web/index.ts b/packages/backend/src/server/web/index.ts index 90e40eec7..de7386861 100644 --- a/packages/backend/src/server/web/index.ts +++ b/packages/backend/src/server/web/index.ts @@ -25,6 +25,7 @@ import { Pages, Channels, Clips, + Emojis, GalleryPosts, } from "@/models/index.js"; import * as Acct from "@/misc/acct.js"; @@ -111,6 +112,43 @@ app.use(async (ctx, next) => { // Init router const router = new Router(); +router.get<{ Params: { path: string } }>("/emoji/:path(.*)", async (ctx) => { + const path = ctx.params.path; + + ctx.set("Cache-Control", "public, max-age=86400"); + + if (!path.match(/^[a-zA-Z0-9\-_@\.]+?\.webp$/)) { + ctx.throw(400, "Bad Request"); + return; + } + + const name = path.split("@")[0].replace(/\.webp$/i, ""); + const host = path.split("@")[1]?.replace(/\.webp$/i, ""); + + const emoji = await Emojis.findOneBy({ + host: host == null || host === "." ? IsNull() : host, + name: name, + }); + + ctx.set( + "Content-Security-Policy", + "default-src 'none'; style-src 'unsafe-inline'", + ); + + if (emoji == null) { + ctx.throw(404, "Emoji not found"); + return; + } + + let url = new URL(`${config.mediaProxy || config.url + "/proxy"}/emoji.webp`); + // || emoji.originalUrl してるのは後方互換性のため + url.searchParams.append("url", emoji.publicUrl || emoji.originalUrl); + url.searchParams.append("emoji", "1"); + if ("static" in ctx.query) url.searchParams.append("static", "1"); + + return ctx.redirect(url.toString()); +}); + //#region static assets router.get("/static-assets/(.*)", async (ctx) => {