From 5a3c1a3f537082a377ca69bab71d2aad5957ab7a Mon Sep 17 00:00:00 2001 From: Rory& Date: Wed, 17 Dec 2025 09:25:41 +0100 Subject: [PATCH] Prettier u9 --- .../#connection_id/access-token.ts | 33 +----- .../#connection_name/#connection_id/index.ts | 82 ++++++-------- src/api/util/handlers/route.ts | 52 ++------- src/api/util/utility/EmbedHandlers.ts | 106 ++++-------------- src/api/util/utility/passwordStrength.ts | 12 +- src/cdn/routes/avatars.ts | 58 ++++------ src/cdn/routes/embed.ts | 20 +--- src/cdn/routes/guild-profiles.ts | 22 +--- src/cdn/routes/role-icons.ts | 69 ++++-------- 9 files changed, 124 insertions(+), 330 deletions(-) diff --git a/src/api/routes/users/@me/connections/#connection_name/#connection_id/access-token.ts b/src/api/routes/users/@me/connections/#connection_name/#connection_id/access-token.ts index a422050ff..fcab43219 100644 --- a/src/api/routes/users/@me/connections/#connection_name/#connection_id/access-token.ts +++ b/src/api/routes/users/@me/connections/#connection_name/#connection_id/access-token.ts @@ -17,14 +17,7 @@ */ import { route } from "@spacebar/api"; -import { - ApiError, - ConnectedAccount, - ConnectionStore, - DiscordApiErrors, - FieldErrors, - RefreshableConnection, -} from "@spacebar/util"; +import { ApiError, ConnectedAccount, ConnectionStore, DiscordApiErrors, FieldErrors, RefreshableConnection } from "@spacebar/util"; import { Request, Response, Router } from "express"; const router = Router({ mergeParams: true }); @@ -62,33 +55,17 @@ router.get("/", route({}), async (req: Request, res: Response) => { external_id: connection_id, user_id: req.user_id, }, - select: [ - "external_id", - "type", - "name", - "verified", - "visibility", - "show_activity", - "revoked", - "token_data", - "friend_sync", - "integrations", - ], + select: ["external_id", "type", "name", "verified", "visibility", "show_activity", "revoked", "token_data", "friend_sync", "integrations"], }); if (!connectedAccount) throw DiscordApiErrors.UNKNOWN_CONNECTION; if (connectedAccount.revoked) throw DiscordApiErrors.CONNECTION_REVOKED; - if (!connectedAccount.token_data) - throw new ApiError("No token data", 0, 400); + if (!connectedAccount.token_data) throw new ApiError("No token data", 0, 400); let access_token = connectedAccount.token_data.access_token; const { expires_at, expires_in, fetched_at } = connectedAccount.token_data; - if ( - (expires_at && expires_at < Date.now()) || - (expires_in && fetched_at + expires_in * 1000 < Date.now()) - ) { - if (!(connection instanceof RefreshableConnection)) - throw new ApiError("Access token expired", 0, 400); + if ((expires_at && expires_at < Date.now()) || (expires_in && fetched_at + expires_in * 1000 < Date.now())) { + if (!(connection instanceof RefreshableConnection)) throw new ApiError("Access token expired", 0, 400); const tokenData = await connection.refresh(connectedAccount); access_token = tokenData.access_token; } diff --git a/src/api/routes/users/@me/connections/#connection_name/#connection_id/index.ts b/src/api/routes/users/@me/connections/#connection_name/#connection_id/index.ts index f4b6ab14d..37deee389 100644 --- a/src/api/routes/users/@me/connections/#connection_name/#connection_id/index.ts +++ b/src/api/routes/users/@me/connections/#connection_name/#connection_id/index.ts @@ -19,62 +19,48 @@ import { route } from "@spacebar/api"; import { ConnectedAccount, DiscordApiErrors, emitEvent } from "@spacebar/util"; import { Request, Response, Router } from "express"; -import { ConnectionUpdateSchema } from "@spacebar/schemas" +import { ConnectionUpdateSchema } from "@spacebar/schemas"; const router = Router({ mergeParams: true }); // TODO: connection update schema -router.patch( - "/", - route({ requestBody: "ConnectionUpdateSchema" }), - async (req: Request, res: Response) => { - const { connection_name, connection_id } = req.params; - const body = req.body as ConnectionUpdateSchema; +router.patch("/", route({ requestBody: "ConnectionUpdateSchema" }), async (req: Request, res: Response) => { + const { connection_name, connection_id } = req.params; + const body = req.body as ConnectionUpdateSchema; - const connection = await ConnectedAccount.findOne({ - where: { - user_id: req.user_id, - external_id: connection_id, - type: connection_name, - }, - select: [ - "external_id", - "type", - "name", - "verified", - "visibility", - "show_activity", - "revoked", - "friend_sync", - "integrations", - ], - }); + const connection = await ConnectedAccount.findOne({ + where: { + user_id: req.user_id, + external_id: connection_id, + type: connection_name, + }, + select: ["external_id", "type", "name", "verified", "visibility", "show_activity", "revoked", "friend_sync", "integrations"], + }); - if (!connection) return DiscordApiErrors.UNKNOWN_CONNECTION; - // TODO: do we need to do anything if the connection is revoked? + if (!connection) return DiscordApiErrors.UNKNOWN_CONNECTION; + // TODO: do we need to do anything if the connection is revoked? - if (typeof body.visibility === "boolean") - //@ts-expect-error For some reason the client sends this as a boolean, even tho docs say its a number? - body.visibility = body.visibility ? 1 : 0; - if (typeof body.show_activity === "boolean") - //@ts-expect-error For some reason the client sends this as a boolean, even tho docs say its a number? - body.show_activity = body.show_activity ? 1 : 0; - if (typeof body.metadata_visibility === "boolean") - //@ts-expect-error For some reason the client sends this as a boolean, even tho docs say its a number? - body.metadata_visibility = body.metadata_visibility ? 1 : 0; + if (typeof body.visibility === "boolean") + //@ts-expect-error For some reason the client sends this as a boolean, even tho docs say its a number? + body.visibility = body.visibility ? 1 : 0; + if (typeof body.show_activity === "boolean") + //@ts-expect-error For some reason the client sends this as a boolean, even tho docs say its a number? + body.show_activity = body.show_activity ? 1 : 0; + if (typeof body.metadata_visibility === "boolean") + //@ts-expect-error For some reason the client sends this as a boolean, even tho docs say its a number? + body.metadata_visibility = body.metadata_visibility ? 1 : 0; - connection.assign(req.body); + connection.assign(req.body); - await ConnectedAccount.update( - { - user_id: req.user_id, - external_id: connection_id, - type: connection_name, - }, - connection, - ); - res.json(connection.toJSON()); - }, -); + await ConnectedAccount.update( + { + user_id: req.user_id, + external_id: connection_id, + type: connection_name, + }, + connection, + ); + res.json(connection.toJSON()); +}); router.delete("/", route({}), async (req: Request, res: Response) => { const { connection_name, connection_id } = req.params; diff --git a/src/api/util/handlers/route.ts b/src/api/util/handlers/route.ts index 15cc0a196..bb38c5303 100644 --- a/src/api/util/handlers/route.ts +++ b/src/api/util/handlers/route.ts @@ -16,26 +16,15 @@ along with this program. If not, see . */ -import { - DiscordApiErrors, - EVENT, - FieldErrors, - PermissionResolvable, - Permissions, - RightResolvable, - Rights, - SpacebarApiErrors, - getPermission, - getRights, -} from "@spacebar/util"; +import { DiscordApiErrors, EVENT, FieldErrors, PermissionResolvable, Permissions, RightResolvable, Rights, SpacebarApiErrors, getPermission, getRights } from "@spacebar/util"; import { AnyValidateFunction } from "ajv/dist/core"; import { NextFunction, Request, Response } from "express"; -import { ajv } from "@spacebar/schemas" +import { ajv } from "@spacebar/schemas"; const ignoredRequestSchemas = [ // skip validation for settings proto JSON updates - TODO: figure out if this even possible to fix? - "SettingsProtoUpdateJsonSchema" -] + "SettingsProtoUpdateJsonSchema", +]; declare global { // TODO: fix this @@ -94,27 +83,18 @@ export function route(opts: RouteOptions) { throw e; } - if (!validate) - throw new Error(`Body schema ${opts.requestBody} not found`); + if (!validate) throw new Error(`Body schema ${opts.requestBody} not found`); } return async (req: Request, res: Response, next: NextFunction) => { if (opts.permission) { - req.permission = await getPermission( - req.user_id, - req.params.guild_id, - req.params.channel_id, - ); + req.permission = await getPermission(req.user_id, req.params.guild_id, req.params.channel_id); - const requiredPerms = Array.isArray(opts.permission) - ? opts.permission - : [opts.permission]; + const requiredPerms = Array.isArray(opts.permission) ? opts.permission : [opts.permission]; requiredPerms.forEach((perm) => { // bitfield comparison: check if user lacks certain permission if (!req.permission!.has(new Permissions(perm))) { - throw DiscordApiErrors.MISSING_PERMISSIONS.withParams( - perm as string, - ); + throw DiscordApiErrors.MISSING_PERMISSIONS.withParams(perm as string); } }); } @@ -124,20 +104,14 @@ export function route(opts: RouteOptions) { req.rights = await getRights(req.user_id); if (!req.rights || !req.rights.has(required)) { - throw SpacebarApiErrors.MISSING_RIGHTS.withParams( - opts.right as string, - ); + throw SpacebarApiErrors.MISSING_RIGHTS.withParams(opts.right as string); } } - if (validate && !ignoredRequestSchemas.includes(opts.requestBody!)) { const valid = validate(req.body); if (!valid) { - const fields: Record< - string, - { code?: string; message: string } - > = {}; + const fields: Record = {}; validate.errors?.forEach( (x) => (fields[x.instancePath.slice(1)] = { @@ -145,11 +119,7 @@ export function route(opts: RouteOptions) { message: x.message || "", }), ); - if (process.env.LOG_VALIDATION_ERRORS) - console.log( - `[VALIDATION ERROR] ${req.method} ${req.originalUrl} - SCHEMA='${opts.requestBody}' -`, - validate?.errors, - ); + if (process.env.LOG_VALIDATION_ERRORS) console.log(`[VALIDATION ERROR] ${req.method} ${req.originalUrl} - SCHEMA='${opts.requestBody}' -`, validate?.errors); throw FieldErrors(fields, validate.errors!); } } diff --git a/src/api/util/utility/EmbedHandlers.ts b/src/api/util/utility/EmbedHandlers.ts index 96fbe1c95..8bbd62834 100644 --- a/src/api/util/utility/EmbedHandlers.ts +++ b/src/api/util/utility/EmbedHandlers.ts @@ -16,7 +16,7 @@ along with this program. If not, see . */ -import { Config }from "@spacebar/util"; +import { Config } from "@spacebar/util"; import { Embed, EmbedImage, EmbedType } from "@spacebar/schemas"; import * as cheerio from "cheerio"; import crypto from "crypto"; @@ -26,18 +26,13 @@ import probe from "probe-image-size"; export const DEFAULT_FETCH_OPTIONS: RequestInit = { redirect: "follow", headers: { - "user-agent": - "Mozilla/5.0 (compatible; Spacebar/1.0; +https://github.com/spacebarchat/server)", + "user-agent": "Mozilla/5.0 (compatible; Spacebar/1.0; +https://github.com/spacebarchat/server)", }, // size: 1024 * 1024 * 5, // grabbed from config later method: "GET", }; -const makeEmbedImage = ( - url: string | undefined, - width: number | undefined, - height: number | undefined, -): Required | undefined => { +const makeEmbedImage = (url: string | undefined, width: number | undefined, height: number | undefined): Required | undefined => { if (!url || !width || !height) return undefined; return { url, @@ -49,13 +44,8 @@ const makeEmbedImage = ( let hasWarnedAboutImagor = false; -export const getProxyUrl = ( - url: URL, - width: number, - height: number, -): string => { - const { resizeWidthMax, resizeHeightMax, imagorServerUrl } = - Config.get().cdn; +export const getProxyUrl = (url: URL, width: number, height: number): string => { + const { resizeWidthMax, resizeHeightMax, imagorServerUrl } = Config.get().cdn; const secret = Config.get().security.requestSignature; width = Math.min(width || 500, resizeWidthMax || width); height = Math.min(height || 500, resizeHeightMax || width); @@ -64,24 +54,14 @@ export const getProxyUrl = ( if (imagorServerUrl) { const path = `${width}x${height}/${url.host}${url.pathname}`; - const hash = crypto - .createHmac("sha1", secret) - .update(path) - .digest("base64") - .replace(/\+/g, "-") - .replace(/\//g, "_"); + const hash = crypto.createHmac("sha1", secret).update(path).digest("base64").replace(/\+/g, "-").replace(/\//g, "_"); return `${imagorServerUrl}/${hash}/${path}`; } if (!hasWarnedAboutImagor) { hasWarnedAboutImagor = true; - console.log( - "[Embeds]", - yellow( - "Imagor has not been set up correctly. https://docs.spacebar.chat/setup/server/configuration/imagor/", - ), - ); + console.log("[Embeds]", yellow("Imagor has not been set up correctly. https://docs.spacebar.chat/setup/server/configuration/imagor/")); } return url.toString(); @@ -161,11 +141,7 @@ const genericImageHandler = async (url: URL): Promise => { const response = await doFetch(url); if (!response) return null; const metas = getMetaDescriptions(await response.text()); - image = makeEmbedImage( - metas.image || metas.image_fallback, - metas.width, - metas.height, - ); + image = makeEmbedImage(metas.image || metas.image_fallback, metas.width, metas.height); } if (!image) return null; @@ -186,8 +162,7 @@ export const EmbedHandlers: { ...DEFAULT_FETCH_OPTIONS, method: "HEAD", }); - if (type.headers.get("content-type")?.indexOf("image") !== -1) - return await genericImageHandler(url); + if (type.headers.get("content-type")?.indexOf("image") !== -1) return await genericImageHandler(url); const response = await doFetch(url); if (!response) return null; @@ -300,9 +275,7 @@ export const EmbedHandlers: { const text = json.data.text; const created_at = new Date(json.data.created_at); const metrics = json.data.public_metrics; - const media = json.includes.media?.filter( - (x: { type: string }) => x.type == "photo", - ); + const media = json.includes.media?.filter((x: { type: string }) => x.type == "photo"); const embed: Embed = { type: EmbedType.rich, @@ -311,11 +284,7 @@ export const EmbedHandlers: { author: { url: `https://twitter.com/${author.username}`, name: `${author.name} (@${author.username})`, - proxy_icon_url: getProxyUrl( - new URL(author.profile_image_url), - 400, - 400, - ), + proxy_icon_url: getProxyUrl(new URL(author.profile_image_url), 400, 400), icon_url: author.profile_image_url, }, timestamp: created_at, @@ -334,15 +303,8 @@ export const EmbedHandlers: { color: 1942002, footer: { text: "Twitter", - proxy_icon_url: getProxyUrl( - new URL( - "https://abs.twimg.com/icons/apple-touch-icon-192x192.png", - ), - 192, - 192, - ), - icon_url: - "https://abs.twimg.com/icons/apple-touch-icon-192x192.png", + proxy_icon_url: getProxyUrl(new URL("https://abs.twimg.com/icons/apple-touch-icon-192x192.png"), 192, 192), + icon_url: "https://abs.twimg.com/icons/apple-touch-icon-192x192.png", }, // Discord doesn't send this? // provider: { @@ -356,11 +318,7 @@ export const EmbedHandlers: { width: media[0].width, height: media[0].height, url: media[0].url, - proxy_url: getProxyUrl( - new URL(media[0].url), - media[0].width, - media[0].height, - ), + proxy_url: getProxyUrl(new URL(media[0].url), media[0].width, media[0].height), }; media.shift(); } @@ -413,11 +371,7 @@ export const EmbedHandlers: { type: EmbedType.image, title: metas.title, description: metas.description, - image: makeEmbedImage( - metas.image || metas.image_fallback, - metas.width, - metas.height, - ), + image: makeEmbedImage(metas.image || metas.image_fallback, metas.width, metas.height), provider: { url: "https://pixiv.net", name: "Pixiv", @@ -429,17 +383,9 @@ export const EmbedHandlers: { const response = await doFetch(url); if (!response) return null; const metas = getMetaDescriptions(await response.text()); - const numReviews = metas.$("#review_summary_num_reviews").val() as - | string - | undefined; - const price = metas - .$(".game_purchase_price.price") - .data("price-final") as number | undefined; - const releaseDate = metas - .$(".release_date") - .find("div.date") - .text() - .trim(); + const numReviews = metas.$("#review_summary_num_reviews").val() as string | undefined; + const price = metas.$(".game_purchase_price.price").data("price-final") as number | undefined; + const releaseDate = metas.$(".release_date").find("div.date").text().trim(); const isReleased = new Date(releaseDate) < new Date(); const fields: Embed["fields"] = []; @@ -477,9 +423,7 @@ export const EmbedHandlers: { width: 460, height: 215, url: metas.image, - proxy_url: metas.image - ? getProxyUrl(new URL(metas.image), 460, 215) - : undefined, + proxy_url: metas.image ? getProxyUrl(new URL(metas.image), 460, 215) : undefined, }, provider: { url: "https://store.steampowered.com", @@ -510,19 +454,11 @@ export const EmbedHandlers: { const metas = getMetaDescriptions(await response.text()); return { - video: makeEmbedImage( - metas.youtube_embed, - metas.width, - metas.height, - ), + video: makeEmbedImage(metas.youtube_embed, metas.width, metas.height), url: url.href, type: metas.youtube_embed ? EmbedType.video : EmbedType.link, title: metas.title, - thumbnail: makeEmbedImage( - metas.image || metas.image_fallback, - metas.width, - metas.height, - ), + thumbnail: makeEmbedImage(metas.image || metas.image_fallback, metas.width, metas.height), provider: { url: "https://www.youtube.com", name: "YouTube", diff --git a/src/api/util/utility/passwordStrength.ts b/src/api/util/utility/passwordStrength.ts index f48b8022d..beb277b01 100644 --- a/src/api/util/utility/passwordStrength.ts +++ b/src/api/util/utility/passwordStrength.ts @@ -35,8 +35,7 @@ const reSYMBOLS = /[A-Za-z0-9]/g; * Returns: 0 > pw > 1 */ export function checkPassword(password: string): number { - const { minLength, minNumbers, minUpperCase, minSymbols } = - Config.get().register.password; + const { minLength, minNumbers, minUpperCase, minSymbols } = Config.get().register.password; let strength = 0; // checks for total password len @@ -60,10 +59,7 @@ export function checkPassword(password: string): number { } // checks if password only consists of numbers or only consists of chars - if ( - password.length == password.match(reNUMBER)?.length || - password.length === password.match(reUPPERCASELETTER)?.length - ) { + if (password.length == password.match(reNUMBER)?.length || password.length === password.match(reUPPERCASELETTER)?.length) { strength = 0; } @@ -76,8 +72,6 @@ export function checkPassword(password: string): number { const entropies = Object.values(entropyMap); entropies.map((x) => x / entropyMap.length); - strength += - entropies.reduceRight((a: number, x: number) => a - x * Math.log2(x)) / - Math.log2(password.length); + strength += entropies.reduceRight((a: number, x: number) => a - x * Math.log2(x)) / Math.log2(password.length); return strength; } diff --git a/src/cdn/routes/avatars.ts b/src/cdn/routes/avatars.ts index d5212f0c3..8866bef99 100644 --- a/src/cdn/routes/avatars.ts +++ b/src/cdn/routes/avatars.ts @@ -30,50 +30,35 @@ import { multer } from "../util/multer"; // TODO: delete old icons const ANIMATED_MIME_TYPES = ["image/apng", "image/gif", "image/gifv"]; -const STATIC_MIME_TYPES = [ - "image/png", - "image/jpeg", - "image/webp", - "image/svg+xml", - "image/svg", -]; +const STATIC_MIME_TYPES = ["image/png", "image/jpeg", "image/webp", "image/svg+xml", "image/svg"]; const ALLOWED_MIME_TYPES = [...ANIMATED_MIME_TYPES, ...STATIC_MIME_TYPES]; const router = Router({ mergeParams: true }); -router.post( - "/:user_id", - multer.single("file"), - async (req: Request, res: Response) => { - if (req.headers.signature !== Config.get().security.requestSignature) - throw new HTTPError("Invalid request signature"); - if (!req.file) throw new HTTPError("Missing file"); - const { buffer, size } = req.file; - const { user_id } = req.params; +router.post("/:user_id", multer.single("file"), async (req: Request, res: Response) => { + if (req.headers.signature !== Config.get().security.requestSignature) throw new HTTPError("Invalid request signature"); + if (!req.file) throw new HTTPError("Missing file"); + const { buffer, size } = req.file; + const { user_id } = req.params; - let hash = crypto - .createHash("md5") - .update(Snowflake.generate()) - .digest("hex"); + let hash = crypto.createHash("md5").update(Snowflake.generate()).digest("hex"); - const type = await fileTypeFromBuffer(buffer); - if (!type || !ALLOWED_MIME_TYPES.includes(type.mime)) - throw new HTTPError("Invalid file type"); - if (ANIMATED_MIME_TYPES.includes(type.mime)) hash = `a_${hash}`; // animated icons have a_ infront of the hash + const type = await fileTypeFromBuffer(buffer); + if (!type || !ALLOWED_MIME_TYPES.includes(type.mime)) throw new HTTPError("Invalid file type"); + if (ANIMATED_MIME_TYPES.includes(type.mime)) hash = `a_${hash}`; // animated icons have a_ infront of the hash - const path = `avatars/${user_id}/${hash}`; - const endpoint = Config.get().cdn.endpointPublic; + const path = `avatars/${user_id}/${hash}`; + const endpoint = Config.get().cdn.endpointPublic; - await storage.set(path, buffer); + await storage.set(path, buffer); - return res.json({ - id: hash, - content_type: type.mime, - size, - url: `${endpoint}${req.baseUrl}/${user_id}/${hash}`, - }); - }, -); + return res.json({ + id: hash, + content_type: type.mime, + size, + url: `${endpoint}${req.baseUrl}/${user_id}/${hash}`, + }); +}); router.get("/:user_id", async (req: Request, res: Response) => { let { user_id } = req.params; @@ -109,8 +94,7 @@ export const getAvatar = async (req: Request, res: Response) => { router.get("/:user_id/:hash", getAvatar); router.delete("/:user_id/:id", async (req: Request, res: Response) => { - if (req.headers.signature !== Config.get().security.requestSignature) - throw new HTTPError("Invalid request signature"); + if (req.headers.signature !== Config.get().security.requestSignature) throw new HTTPError("Invalid request signature"); const { user_id, id } = req.params; const path = `avatars/${user_id}/${id}`; diff --git a/src/cdn/routes/embed.ts b/src/cdn/routes/embed.ts index 5f3801a29..4964efd8a 100644 --- a/src/cdn/routes/embed.ts +++ b/src/cdn/routes/embed.ts @@ -63,15 +63,7 @@ router.get("/avatars/:id", async (req: Request, res: Response) => { id = id.split(".")[0]; // remove .file extension const hash = defaultAvatarHashMap.get(id); if (!hash) throw new HTTPError("not found", 404); - const path = join( - __dirname, - "..", - "..", - "..", - "assets", - "public", - `${hash}.png`, - ); + const path = join(__dirname, "..", "..", "..", "assets", "public", `${hash}.png`); const file = await getFile(path); if (!file) throw new HTTPError("not found", 404); @@ -88,15 +80,7 @@ router.get("/group-avatars/:id", async (req: Request, res: Response) => { id = id.split(".")[0]; // remove .file extension const hash = defaultGroupDMAvatarHashMap.get(id); if (!hash) throw new HTTPError("not found", 404); - const path = join( - __dirname, - "..", - "..", - "..", - "assets", - "public", - `${hash}.png`, - ); + const path = join(__dirname, "..", "..", "..", "assets", "public", `${hash}.png`); const file = await getFile(path); if (!file) throw new HTTPError("not found", 404); diff --git a/src/cdn/routes/guild-profiles.ts b/src/cdn/routes/guild-profiles.ts index 018a4b2b6..9f2173d76 100644 --- a/src/cdn/routes/guild-profiles.ts +++ b/src/cdn/routes/guild-profiles.ts @@ -30,32 +30,21 @@ import { fileTypeFromBuffer } from "file-type"; // TODO: delete old icons const ANIMATED_MIME_TYPES = ["image/apng", "image/gif", "image/gifv"]; -const STATIC_MIME_TYPES = [ - "image/png", - "image/jpeg", - "image/webp", - "image/svg+xml", - "image/svg", -]; +const STATIC_MIME_TYPES = ["image/png", "image/jpeg", "image/webp", "image/svg+xml", "image/svg"]; const ALLOWED_MIME_TYPES = [...ANIMATED_MIME_TYPES, ...STATIC_MIME_TYPES]; const router = Router({ mergeParams: true }); router.post("/", multer.single("file"), async (req: Request, res: Response) => { - if (req.headers.signature !== Config.get().security.requestSignature) - throw new HTTPError("Invalid request signature"); + if (req.headers.signature !== Config.get().security.requestSignature) throw new HTTPError("Invalid request signature"); if (!req.file) throw new HTTPError("Missing file"); const { buffer, size } = req.file; const { guild_id, user_id } = req.params; - let hash = crypto - .createHash("md5") - .update(Snowflake.generate()) - .digest("hex"); + let hash = crypto.createHash("md5").update(Snowflake.generate()).digest("hex"); const type = await fileTypeFromBuffer(buffer); - if (!type || !ALLOWED_MIME_TYPES.includes(type.mime)) - throw new HTTPError("Invalid file type"); + if (!type || !ALLOWED_MIME_TYPES.includes(type.mime)) throw new HTTPError("Invalid file type"); if (ANIMATED_MIME_TYPES.includes(type.mime)) hash = `a_${hash}`; // animated icons have a_ infront of the hash const path = `guilds/${guild_id}/users/${user_id}/avatars/${hash}`; @@ -104,8 +93,7 @@ router.get("/:hash", async (req: Request, res: Response) => { }); router.delete("/:id", async (req: Request, res: Response) => { - if (req.headers.signature !== Config.get().security.requestSignature) - throw new HTTPError("Invalid request signature"); + if (req.headers.signature !== Config.get().security.requestSignature) throw new HTTPError("Invalid request signature"); const { guild_id, user_id, id } = req.params; const path = `guilds/${guild_id}/users/${user_id}/avatars/${id}`; diff --git a/src/cdn/routes/role-icons.ts b/src/cdn/routes/role-icons.ts index 859be2af9..b88f80acf 100644 --- a/src/cdn/routes/role-icons.ts +++ b/src/cdn/routes/role-icons.ts @@ -30,49 +30,34 @@ import { multer } from "../util/multer"; // TODO: generate different sizes of icon // TODO: generate different image types of icon -const STATIC_MIME_TYPES = [ - "image/png", - "image/jpeg", - "image/webp", - "image/svg+xml", - "image/svg", -]; +const STATIC_MIME_TYPES = ["image/png", "image/jpeg", "image/webp", "image/svg+xml", "image/svg"]; const ALLOWED_MIME_TYPES = [...STATIC_MIME_TYPES]; const router = Router({ mergeParams: true }); -router.post( - "/:role_id", - multer.single("file"), - async (req: Request, res: Response) => { - if (req.headers.signature !== Config.get().security.requestSignature) - throw new HTTPError("Invalid request signature"); - if (!req.file) throw new HTTPError("Missing file"); - const { buffer, size } = req.file; - const { role_id } = req.params; +router.post("/:role_id", multer.single("file"), async (req: Request, res: Response) => { + if (req.headers.signature !== Config.get().security.requestSignature) throw new HTTPError("Invalid request signature"); + if (!req.file) throw new HTTPError("Missing file"); + const { buffer, size } = req.file; + const { role_id } = req.params; - const hash = crypto - .createHash("md5") - .update(Snowflake.generate()) - .digest("hex"); + const hash = crypto.createHash("md5").update(Snowflake.generate()).digest("hex"); - const type = await fileTypeFromBuffer(buffer); - if (!type || !ALLOWED_MIME_TYPES.includes(type.mime)) - throw new HTTPError("Invalid file type"); + const type = await fileTypeFromBuffer(buffer); + if (!type || !ALLOWED_MIME_TYPES.includes(type.mime)) throw new HTTPError("Invalid file type"); - const path = `role-icons/${role_id}/${hash}.png`; - const endpoint = Config.get().cdn.endpointPublic; + const path = `role-icons/${role_id}/${hash}.png`; + const endpoint = Config.get().cdn.endpointPublic; - await storage.set(path, buffer); + await storage.set(path, buffer); - return res.json({ - id: hash, - content_type: type.mime, - size, - url: `${endpoint}${req.baseUrl}/${role_id}/${hash}`, - }); - }, -); + return res.json({ + id: hash, + content_type: type.mime, + size, + url: `${endpoint}${req.baseUrl}/${role_id}/${hash}`, + }); +}); router.get("/:role_id", async (req: Request, res: Response) => { const { role_id } = req.params; @@ -96,19 +81,10 @@ router.get("/:role_id/:hash", async (req: Request, res: Response) => { const role_icon_hash = hash.split(".")[0]; let file: Buffer | null = null; - const extensions_to_try = [ - requested_extension, - "png", - "jpg", - "jpeg", - "webp", - "svg", - ]; + const extensions_to_try = [requested_extension, "png", "jpg", "jpeg", "webp", "svg"]; for (let i = 0; i < extensions_to_try.length; i++) { - file = await storage.get( - `role-icons/${role_id}/${role_icon_hash}.${extensions_to_try[i]}`, - ); + file = await storage.get(`role-icons/${role_id}/${role_icon_hash}.${extensions_to_try[i]}`); if (file) break; } @@ -122,8 +98,7 @@ router.get("/:role_id/:hash", async (req: Request, res: Response) => { }); router.delete("/:role_id/:id", async (req: Request, res: Response) => { - if (req.headers.signature !== Config.get().security.requestSignature) - throw new HTTPError("Invalid request signature"); + if (req.headers.signature !== Config.get().security.requestSignature) throw new HTTPError("Invalid request signature"); const { role_id, id } = req.params; const path = `role-icons/${role_id}/${id}`;