summary refs log tree commit diff
path: root/src/api/util
diff options
context:
space:
mode:
Diffstat (limited to 'src/api/util')
-rw-r--r--src/api/util/handlers/route.ts52
-rw-r--r--src/api/util/utility/EmbedHandlers.ts106
-rw-r--r--src/api/util/utility/passwordStrength.ts12
3 files changed, 35 insertions, 135 deletions
diff --git a/src/api/util/handlers/route.ts b/src/api/util/handlers/route.ts

index 15cc0a19..bb38c530 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 <https://www.gnu.org/licenses/>. */ -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<string, { code?: string; message: string }> = {}; 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 96fbe1c9..8bbd6283 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 <https://www.gnu.org/licenses/>. */ -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<EmbedImage> | undefined => { +const makeEmbedImage = (url: string | undefined, width: number | undefined, height: number | undefined): Required<EmbedImage> | 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<Embed | null> => { 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 f48b8022..beb277b0 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; }