mirror of
https://github.com/Drop-OSS/drop.git
synced 2026-01-31 15:37:09 +01:00
Switch to nuxt assets for emojis (#311)
* switch to nuxt assets for emojis * add auth to emoji endpoint * fix cache control header * fix type error
This commit is contained in:
@@ -10,6 +10,6 @@ const props = defineProps<{
|
||||
}>();
|
||||
|
||||
const url = computed(() => {
|
||||
return `/twemoji/${twemoji.convert.toCodePoint(props.emoji)}.svg`;
|
||||
return `/api/v1/emoji/${twemoji.convert.toCodePoint(props.emoji)}`;
|
||||
});
|
||||
</script>
|
||||
|
||||
@@ -1,9 +1,8 @@
|
||||
import tailwindcss from "@tailwindcss/vite";
|
||||
import { execSync } from "node:child_process";
|
||||
import { cpSync, readFileSync, existsSync } from "node:fs";
|
||||
import { readFileSync, existsSync } from "node:fs";
|
||||
import path from "node:path";
|
||||
import { findPackageJSON } from "node:module";
|
||||
import { viteStaticCopy } from "vite-plugin-static-copy";
|
||||
import module from "module";
|
||||
import { type } from "arktype";
|
||||
|
||||
const packageJsonSchema = type({
|
||||
@@ -11,6 +10,14 @@ const packageJsonSchema = type({
|
||||
version: "string",
|
||||
});
|
||||
|
||||
const twemojiJson = module.findPackageJSON(
|
||||
"@discordapp/twemoji",
|
||||
import.meta.url,
|
||||
);
|
||||
if (!twemojiJson) {
|
||||
throw new Error("Could not find @discordapp/twemoji package.");
|
||||
}
|
||||
|
||||
// get drop version
|
||||
const dropVersion = getDropVersion();
|
||||
|
||||
@@ -56,7 +63,7 @@ export default defineNuxtConfig({
|
||||
|
||||
experimental: {
|
||||
buildCache: true,
|
||||
viewTransition: false,
|
||||
viewTransition: true,
|
||||
componentIslands: true,
|
||||
},
|
||||
|
||||
@@ -68,39 +75,9 @@ export default defineNuxtConfig({
|
||||
plugins: [
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
tailwindcss() as any,
|
||||
// only used in dev server, not build because nitro sucks
|
||||
// see build hook below
|
||||
viteStaticCopy({
|
||||
targets: [
|
||||
{
|
||||
src: "node_modules/@discordapp/twemoji/dist/svg/*",
|
||||
dest: "twemoji",
|
||||
},
|
||||
],
|
||||
// eslint-disable-next-line @typescript-eslint/no-explicit-any
|
||||
}) as any,
|
||||
],
|
||||
},
|
||||
|
||||
hooks: {
|
||||
"nitro:build:public-assets": (nitro) => {
|
||||
const twemojiJson = findPackageJSON(
|
||||
"@discordapp/twemoji",
|
||||
import.meta.url,
|
||||
);
|
||||
if (!twemojiJson) {
|
||||
throw new Error("Could not find @discordapp/twemoji package.");
|
||||
}
|
||||
// this is only run during build, not dev server
|
||||
// https://github.com/nuxt/nuxt/issues/18918#issuecomment-1925774964
|
||||
// copy emojis to .output/public/twemoji
|
||||
const targetDir = path.join(nitro.options.output.publicDir, "twemoji");
|
||||
cpSync(path.join(path.dirname(twemojiJson), "dist", "svg"), targetDir, {
|
||||
recursive: true,
|
||||
});
|
||||
},
|
||||
},
|
||||
|
||||
runtimeConfig: {
|
||||
gitRef: commitHash,
|
||||
dropVersion: dropVersion,
|
||||
@@ -139,6 +116,7 @@ export default defineNuxtConfig({
|
||||
|
||||
scheduledTasks: {
|
||||
"0 * * * *": ["dailyTasks"],
|
||||
"*/30 * * * *": ["downloadCleanup"],
|
||||
},
|
||||
|
||||
storage: {
|
||||
@@ -154,6 +132,14 @@ export default defineNuxtConfig({
|
||||
base: "./.data/appCache",
|
||||
},
|
||||
},
|
||||
|
||||
serverAssets: [
|
||||
{
|
||||
baseName: "twemoji",
|
||||
// get path to twemoji svg assets
|
||||
dir: path.join(path.dirname(twemojiJson), "dist", "svg"),
|
||||
},
|
||||
],
|
||||
},
|
||||
|
||||
typescript: {
|
||||
|
||||
@@ -59,7 +59,6 @@
|
||||
"stream-mime-type": "^2.0.0",
|
||||
"turndown": "^7.2.0",
|
||||
"unstorage": "^1.15.0",
|
||||
"vite-plugin-static-copy": "^3.1.2",
|
||||
"vue": "latest",
|
||||
"vue-router": "latest",
|
||||
"vue3-carousel": "^0.16.0",
|
||||
|
||||
81
pnpm-lock.yaml
generated
81
pnpm-lock.yaml
generated
@@ -128,9 +128,6 @@ importers:
|
||||
unstorage:
|
||||
specifier: ^1.15.0
|
||||
version: 1.16.1(@netlify/blobs@9.1.2)(db0@0.3.4)(ioredis@5.8.2)
|
||||
vite-plugin-static-copy:
|
||||
specifier: ^3.1.2
|
||||
version: 3.1.2(vite@7.2.2(@types/node@22.16.5)(jiti@2.6.1)(lightningcss@1.30.1)(sass@1.89.2)(terser@5.43.1)(yaml@2.8.1))
|
||||
vue:
|
||||
specifier: latest
|
||||
version: 3.5.26(typescript@5.8.3)
|
||||
@@ -3058,10 +3055,6 @@ packages:
|
||||
resolution: {integrity: sha512-k38b3XOZKv60C4E2hVsXTolJWfkGRMbILBIe2IBITXciy5bOsTKot5kDrf3ZfufQtQOUN5mXceUEpU1rTl9Uog==}
|
||||
hasBin: true
|
||||
|
||||
binary-extensions@2.3.0:
|
||||
resolution: {integrity: sha512-Ceh+7ox5qe7LJuLHoY0feh3pHuUDHAcRUeyL2VYghZwfpkNIy/+8Ocg0a3UuSoYzavmylwuLWQOf3hl0jjMMIw==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
bindings@1.5.0:
|
||||
resolution: {integrity: sha512-p2q/t/mhvuOj/UeLlV6566GD/guowlr0hHxClI0W9m7MWYkL1F0hLo+0Aexs9HSPCtR1SXQ0TD3MMKrXZajbiQ==}
|
||||
|
||||
@@ -3203,10 +3196,6 @@ packages:
|
||||
resolution: {integrity: sha512-IkxPpb5rS/d1IiLbHMgfPuS0FgiWTtFIm/Nj+2woXDLTZ7fOT2eqzgYbdMlLweqlHbsZjxEChoVK+7iph7jyQg==}
|
||||
engines: {node: '>=20.18.1'}
|
||||
|
||||
chokidar@3.6.0:
|
||||
resolution: {integrity: sha512-7VT13fmjotKpGipCW9JEQAusEPE+Ei8nl6/g4FBAmIm0GOOLMua9NDDo/DWp0ZAxCr3cPq5ZpBqmPAQgDda2Pw==}
|
||||
engines: {node: '>= 8.10.0'}
|
||||
|
||||
chokidar@4.0.3:
|
||||
resolution: {integrity: sha512-Qgzu8kfBvo+cA4962jnP1KkS6Dop5NS6g7R5LFYJr4b8Ub94PPQXUksCw9PvXoeXPRRddRNC5C1JQUR2SMGtnA==}
|
||||
engines: {node: '>= 14.16.0'}
|
||||
@@ -4094,10 +4083,6 @@ packages:
|
||||
fs-constants@1.0.0:
|
||||
resolution: {integrity: sha512-y6OAwoSIf7FyjMIv94u+b5rdheZEjzR63GTyZJm5qh4Bi+2YgwLCcI/fPFZkL5PSixOt6ZNKm+w+Hfp/Bciwow==}
|
||||
|
||||
fs-extra@11.3.0:
|
||||
resolution: {integrity: sha512-Z4XaCL6dUDHfP/jT25jJKMmtxvuwbkrD1vNSMFlo9lNLY2c5FHYSQgHPRZUjAB26TpDEoW9HCOgplrdbaPV/ew==}
|
||||
engines: {node: '>=14.14'}
|
||||
|
||||
fs-extra@8.1.0:
|
||||
resolution: {integrity: sha512-yhlQgA6mnOJUKOsRUFsgJdQCvkKhcz8tlZG5HBQfReYZy46OwLcY+Zia0mtdHsOo9y/hP+CxMN0TU9QxoOtG4g==}
|
||||
engines: {node: '>=6 <7 || >=8'}
|
||||
@@ -4344,10 +4329,6 @@ packages:
|
||||
is-arrayish@0.3.2:
|
||||
resolution: {integrity: sha512-eVRqCvVlZbuw3GrM63ovNSNAeA1K16kaR/LRY/92w0zxQ5/1YzwblUX652i4Xs9RwAGjW9d9y6X88t8OaAJfWQ==}
|
||||
|
||||
is-binary-path@2.1.0:
|
||||
resolution: {integrity: sha512-ZMERYes6pDydyuGidse7OsHxtbI7WVeUEozgR/g7rd0xUimYNlvZRE/K2MgZTjWy725IfelLeVcEM97mmtRGXw==}
|
||||
engines: {node: '>=8'}
|
||||
|
||||
is-builtin-module@3.2.1:
|
||||
resolution: {integrity: sha512-BSLE3HnV2syZ0FK0iMA/yUGplUeMmNz4AW5fnTunbCIqZi4vG3WjJT9FHMy5D69xmAYBHXQhJdALdpwVxV501A==}
|
||||
engines: {node: '>=6'}
|
||||
@@ -4541,9 +4522,6 @@ packages:
|
||||
jsonfile@5.0.0:
|
||||
resolution: {integrity: sha512-NQRZ5CRo74MhMMC3/3r5g2k4fjodJ/wh8MxjFbCViWKFjxrnudWSY5vomh+23ZaXzAS7J3fBZIR2dV6WbmfM0w==}
|
||||
|
||||
jsonfile@6.1.0:
|
||||
resolution: {integrity: sha512-5dgndWOriYSm5cnYaJNhalLNDKOqFwyDB/rr1E9ZsGciGvKPs8R2xYGCacuf3z6K1YKDz182fd+fY3cn3pMqXQ==}
|
||||
|
||||
junk@4.0.1:
|
||||
resolution: {integrity: sha512-Qush0uP+G8ZScpGMZvHUiRfI0YBWuB3gVBYlI0v0vvOJt5FLicco+IkP0a50LqTTQhmts/m6tP5SWE+USyIvcQ==}
|
||||
engines: {node: '>=12.20'}
|
||||
@@ -5702,10 +5680,6 @@ packages:
|
||||
readdir-glob@1.1.3:
|
||||
resolution: {integrity: sha512-v05I2k7xN8zXvPD9N+z/uhXPaj0sUFCe2rcWZIpBsqxfP7xXFQ0tipAd/wjj1YxWyWtUS5IDJpOG82JKt2EAVA==}
|
||||
|
||||
readdirp@3.6.0:
|
||||
resolution: {integrity: sha512-hOS089on8RduqdbhvQ5Z37A0ESjsqz6qnRcffsMU3495FuTdqSm+7bhJ29JvIOsBDEEnan5DPu9t3To9VRlMzA==}
|
||||
engines: {node: '>=8.10.0'}
|
||||
|
||||
readdirp@4.1.2:
|
||||
resolution: {integrity: sha512-GDhwkLfywWL2s6vEjyhri+eXmfH6j1L7JE27WhqLeYzoh/A3DBaYGEj2H/HFZCn/kMfim73FXxEJTw06WtxQwg==}
|
||||
engines: {node: '>= 14.18.0'}
|
||||
@@ -6341,10 +6315,6 @@ packages:
|
||||
resolution: {integrity: sha512-rBJeI5CXAlmy1pV+617WB9J63U6XcazHHF2f2dbJix4XzpUF0RS3Zbj0FGIOCAva5P/d/GBOYaACQ1w+0azUkg==}
|
||||
engines: {node: '>= 4.0.0'}
|
||||
|
||||
universalify@2.0.1:
|
||||
resolution: {integrity: sha512-gptHNQghINnc/vTGIk0SOFGFNXw7JVrlRUtConJRlvaw6DuX0wO5Jeko9sWrMBhh+PsYAZ7oXAiOnf/UKogyiw==}
|
||||
engines: {node: '>= 10.0.0'}
|
||||
|
||||
unixify@1.0.0:
|
||||
resolution: {integrity: sha512-6bc58dPYhCMHHuwxldQxO3RRNZ4eCogZ/st++0+fcC1nr0jiGUtAdBJ2qzmLQWSxbtz42pWt4QQMiZ9HvZf5cg==}
|
||||
engines: {node: '>=0.10.0'}
|
||||
@@ -6626,12 +6596,6 @@ packages:
|
||||
'@nuxt/kit':
|
||||
optional: true
|
||||
|
||||
vite-plugin-static-copy@3.1.2:
|
||||
resolution: {integrity: sha512-aVmYOzptLVOI2b1jL+cmkF7O6uhRv1u5fvOkQgbohWZp2CbR22kn9ZqkCUIt9umKF7UhdbsEpshn1rf4720QFg==}
|
||||
engines: {node: ^18.0.0 || >=20.0.0}
|
||||
peerDependencies:
|
||||
vite: ^5.0.0 || ^6.0.0 || ^7.0.0
|
||||
|
||||
vite-plugin-vue-tracer@1.1.3:
|
||||
resolution: {integrity: sha512-fM7hfHELZvbPnSn8EKZwHfzxm5EfYFQIclz8rwcNXfodNbRkwNvh0AGMtaBfMxQ9HC5KVa3KitwHnmE4ezDemw==}
|
||||
peerDependencies:
|
||||
@@ -10047,8 +10011,6 @@ snapshots:
|
||||
|
||||
bcryptjs@3.0.2: {}
|
||||
|
||||
binary-extensions@2.3.0: {}
|
||||
|
||||
bindings@1.5.0:
|
||||
dependencies:
|
||||
file-uri-to-path: 1.0.0
|
||||
@@ -10248,18 +10210,6 @@ snapshots:
|
||||
undici: 7.13.0
|
||||
whatwg-mimetype: 4.0.0
|
||||
|
||||
chokidar@3.6.0:
|
||||
dependencies:
|
||||
anymatch: 3.1.3
|
||||
braces: 3.0.3
|
||||
glob-parent: 5.1.2
|
||||
is-binary-path: 2.1.0
|
||||
is-glob: 4.0.3
|
||||
normalize-path: 3.0.0
|
||||
readdirp: 3.6.0
|
||||
optionalDependencies:
|
||||
fsevents: 2.3.3
|
||||
|
||||
chokidar@4.0.3:
|
||||
dependencies:
|
||||
readdirp: 4.1.2
|
||||
@@ -11214,12 +11164,6 @@ snapshots:
|
||||
fs-constants@1.0.0:
|
||||
optional: true
|
||||
|
||||
fs-extra@11.3.0:
|
||||
dependencies:
|
||||
graceful-fs: 4.2.11
|
||||
jsonfile: 6.1.0
|
||||
universalify: 2.0.1
|
||||
|
||||
fs-extra@8.1.0:
|
||||
dependencies:
|
||||
graceful-fs: 4.2.11
|
||||
@@ -11543,10 +11487,6 @@ snapshots:
|
||||
|
||||
is-arrayish@0.3.2: {}
|
||||
|
||||
is-binary-path@2.1.0:
|
||||
dependencies:
|
||||
binary-extensions: 2.3.0
|
||||
|
||||
is-builtin-module@3.2.1:
|
||||
dependencies:
|
||||
builtin-modules: 3.3.0
|
||||
@@ -11696,12 +11636,6 @@ snapshots:
|
||||
optionalDependencies:
|
||||
graceful-fs: 4.2.11
|
||||
|
||||
jsonfile@6.1.0:
|
||||
dependencies:
|
||||
universalify: 2.0.1
|
||||
optionalDependencies:
|
||||
graceful-fs: 4.2.11
|
||||
|
||||
junk@4.0.1: {}
|
||||
|
||||
jwt-decode@4.0.0: {}
|
||||
@@ -13262,10 +13196,6 @@ snapshots:
|
||||
dependencies:
|
||||
minimatch: 5.1.6
|
||||
|
||||
readdirp@3.6.0:
|
||||
dependencies:
|
||||
picomatch: 2.3.1
|
||||
|
||||
readdirp@4.1.2: {}
|
||||
|
||||
real-require@0.2.0: {}
|
||||
@@ -13987,8 +13917,6 @@ snapshots:
|
||||
|
||||
universalify@0.1.2: {}
|
||||
|
||||
universalify@2.0.1: {}
|
||||
|
||||
unixify@1.0.0:
|
||||
dependencies:
|
||||
normalize-path: 2.1.1
|
||||
@@ -14281,15 +14209,6 @@ snapshots:
|
||||
transitivePeerDependencies:
|
||||
- supports-color
|
||||
|
||||
vite-plugin-static-copy@3.1.2(vite@7.2.2(@types/node@22.16.5)(jiti@2.6.1)(lightningcss@1.30.1)(sass@1.89.2)(terser@5.43.1)(yaml@2.8.1)):
|
||||
dependencies:
|
||||
chokidar: 3.6.0
|
||||
fs-extra: 11.3.0
|
||||
p-map: 7.0.3
|
||||
picocolors: 1.1.1
|
||||
tinyglobby: 0.2.14
|
||||
vite: 7.2.2(@types/node@22.16.5)(jiti@2.6.1)(lightningcss@1.30.1)(sass@1.89.2)(terser@5.43.1)(yaml@2.8.1)
|
||||
|
||||
vite-plugin-vue-tracer@1.1.3(vite@7.2.2(@types/node@22.16.5)(jiti@2.6.1)(lightningcss@1.30.1)(sass@1.89.2)(terser@5.43.1)(yaml@2.8.1))(vue@3.5.26(typescript@5.8.3)):
|
||||
dependencies:
|
||||
estree-walker: 3.0.3
|
||||
|
||||
39
server/api/v1/emoji/[codepoint]/index.get.ts
Normal file
39
server/api/v1/emoji/[codepoint]/index.get.ts
Normal file
@@ -0,0 +1,39 @@
|
||||
import aclManager from "~/server/internal/acls";
|
||||
|
||||
export default defineEventHandler(async (h3) => {
|
||||
const allowed = await aclManager.hasACL(h3, [
|
||||
"system:setup",
|
||||
"user:emoji:read",
|
||||
]);
|
||||
if (!allowed)
|
||||
throw createError({
|
||||
statusCode: 403,
|
||||
statusMessage: "Requires authentication",
|
||||
});
|
||||
|
||||
const codepoint = getRouterParam(h3, "codepoint");
|
||||
if (!codepoint) {
|
||||
throw createError({
|
||||
statusCode: 400,
|
||||
statusMessage: "Missing codepoint parameter",
|
||||
});
|
||||
}
|
||||
|
||||
// Get the emoji SVG from server assets
|
||||
const asset = await useStorage("assets:twemoji").getItemRaw(
|
||||
`${codepoint}.svg`,
|
||||
);
|
||||
|
||||
if (!asset) {
|
||||
throw createError({
|
||||
statusCode: 404,
|
||||
statusMessage: "Emoji not found",
|
||||
});
|
||||
}
|
||||
|
||||
// Set proper content type for SVG
|
||||
setResponseHeader(h3, "Content-Type", "image/svg+xml");
|
||||
setResponseHeader(h3, "Cache-Control", "private, max-age=31536000");
|
||||
|
||||
return asset;
|
||||
});
|
||||
@@ -40,6 +40,8 @@ export const userACLDescriptions: ObjectFromList<typeof userACLs> = {
|
||||
|
||||
"news:read": "Read the server's news articles.",
|
||||
|
||||
"emoji:read": "Read built in emojis",
|
||||
|
||||
"settings:read": "Read system settings.",
|
||||
};
|
||||
|
||||
|
||||
@@ -32,6 +32,8 @@ export const userACLs = [
|
||||
"clients:read",
|
||||
"clients:revoke",
|
||||
|
||||
"emoji:read",
|
||||
|
||||
"news:read",
|
||||
|
||||
"settings:read",
|
||||
@@ -220,7 +222,7 @@ class ACLManager {
|
||||
return false;
|
||||
}
|
||||
|
||||
async hasACL(request: MinimumRequestObject | undefined, acls: string[]) {
|
||||
async hasACL(request: MinimumRequestObject | undefined, acls: GlobalACL[]) {
|
||||
for (const acl of acls) {
|
||||
if (acl.startsWith(userACLPrefix)) {
|
||||
const rawACL = acl.substring(userACLPrefix.length);
|
||||
|
||||
@@ -284,7 +284,8 @@ class TaskHandler {
|
||||
return;
|
||||
}
|
||||
|
||||
const allowed = await aclManager.hasACL(request, task.acls);
|
||||
// cast acls due to prisma types being less strict
|
||||
const allowed = await aclManager.hasACL(request, task.acls as GlobalACL[]);
|
||||
if (!allowed) {
|
||||
// logger.warn("user does not have necessary ACLs");
|
||||
peer.send(
|
||||
|
||||
Reference in New Issue
Block a user