diff options
author | Madeline <46743919+MaddyUnderStars@users.noreply.github.com> | 2022-09-26 22:29:30 +1000 |
---|---|---|
committer | Madeline <46743919+MaddyUnderStars@users.noreply.github.com> | 2022-09-26 22:41:21 +1000 |
commit | dbaf39237ae3a41b6b1ac6a6cd3486129599b815 (patch) | |
tree | 350cca4889d0804445eddbd8467d274b27307776 /src/api/util/handlers | |
parent | Remove the cdn storage location log (diff) | |
download | server-dbaf39237ae3a41b6b1ac6a6cd3486129599b815.tar.xz |
Prettier
Diffstat (limited to 'src/api/util/handlers')
-rw-r--r-- | src/api/util/handlers/Message.ts | 186 | ||||
-rw-r--r-- | src/api/util/handlers/Voice.ts | 11 | ||||
-rw-r--r-- | src/api/util/handlers/route.ts | 35 |
3 files changed, 168 insertions, 64 deletions
diff --git a/src/api/util/handlers/Message.ts b/src/api/util/handlers/Message.ts index 0d29c2e6..d44b368f 100644 --- a/src/api/util/handlers/Message.ts +++ b/src/api/util/handlers/Message.ts @@ -32,24 +32,32 @@ const allow_empty = false; // TODO: check webhook, application, system author, stickers // TODO: embed gifs/videos/images -const LINK_REGEX = /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/g; +const LINK_REGEX = + /https?:\/\/(www\.)?[-a-zA-Z0-9@:%._\+~#=]{1,256}\.[a-zA-Z0-9()]{1,6}\b([-a-zA-Z0-9()@:%_\+.~#?&//=]*)/g; const DEFAULT_FETCH_OPTIONS: any = { redirect: "follow", follow: 1, headers: { - "user-agent": "Mozilla/5.0 (compatible; Fosscord/1.0; +https://github.com/fosscord/fosscord)" + "user-agent": + "Mozilla/5.0 (compatible; Fosscord/1.0; +https://github.com/fosscord/fosscord)", }, // size: 1024 * 1024 * 5, // grabbed from config later compress: true, - method: "GET" + method: "GET", }; export async function handleMessage(opts: MessageOptions): Promise<Message> { - const channel = await Channel.findOneOrFail({ where: { id: opts.channel_id }, relations: ["recipients"] }); - if (!channel || !opts.channel_id) throw new HTTPError("Channel not found", 404); + const channel = await Channel.findOneOrFail({ + where: { id: opts.channel_id }, + relations: ["recipients"], + }); + if (!channel || !opts.channel_id) + throw new HTTPError("Channel not found", 404); - const stickers = opts.sticker_ids ? await Sticker.find({ where: { id: In(opts.sticker_ids) } }) : undefined; + const stickers = opts.sticker_ids + ? await Sticker.find({ where: { id: In(opts.sticker_ids) } }) + : undefined; const message = Message.create({ ...opts, id: Snowflake.generate(), @@ -58,11 +66,14 @@ export async function handleMessage(opts: MessageOptions): Promise<Message> { channel_id: opts.channel_id, attachments: opts.attachments || [], embeds: opts.embeds || [], - reactions: /*opts.reactions ||*/[], + reactions: /*opts.reactions ||*/ [], type: opts.type ?? 0, }); - if (message.content && message.content.length > Config.get().limits.message.maxCharacters) { + if ( + message.content && + message.content.length > Config.get().limits.message.maxCharacters + ) { throw new HTTPError("Content length over max character limit"); } @@ -72,13 +83,21 @@ export async function handleMessage(opts: MessageOptions): Promise<Message> { rights.hasThrow("SEND_MESSAGES"); } if (opts.application_id) { - message.application = await Application.findOneOrFail({ where: { id: opts.application_id } }); + message.application = await Application.findOneOrFail({ + where: { id: opts.application_id }, + }); } if (opts.webhook_id) { - message.webhook = await Webhook.findOneOrFail({ where: { id: opts.webhook_id } }); + message.webhook = await Webhook.findOneOrFail({ + where: { id: opts.webhook_id }, + }); } - const permission = await getPermission(opts.author_id, channel.guild_id, opts.channel_id); + const permission = await getPermission( + opts.author_id, + channel.guild_id, + opts.channel_id, + ); permission.hasThrow("SEND_MESSAGES"); if (permission.cache.member) { message.member = permission.cache.member; @@ -89,10 +108,18 @@ export async function handleMessage(opts: MessageOptions): Promise<Message> { permission.hasThrow("READ_MESSAGE_HISTORY"); // code below has to be redone when we add custom message routing if (message.guild_id !== null) { - const guild = await Guild.findOneOrFail({ where: { id: channel.guild_id } }); + const guild = await Guild.findOneOrFail({ + where: { id: channel.guild_id }, + }); if (!guild.features.includes("CROSS_CHANNEL_REPLIES")) { - if (opts.message_reference.guild_id !== channel.guild_id) throw new HTTPError("You can only reference messages from this guild"); - if (opts.message_reference.channel_id !== opts.channel_id) throw new HTTPError("You can only reference messages from this channel"); + if (opts.message_reference.guild_id !== channel.guild_id) + throw new HTTPError( + "You can only reference messages from this guild", + ); + if (opts.message_reference.channel_id !== opts.channel_id) + throw new HTTPError( + "You can only reference messages from this channel", + ); } } /** Q: should be checked if the referenced message exists? ANSWER: NO @@ -102,7 +129,13 @@ export async function handleMessage(opts: MessageOptions): Promise<Message> { } // TODO: stickers/activity - if (!allow_empty && (!opts.content && !opts.embeds?.length && !opts.attachments?.length && !opts.sticker_ids?.length)) { + if ( + !allow_empty && + !opts.content && + !opts.embeds?.length && + !opts.attachments?.length && + !opts.sticker_ids?.length + ) { throw new HTTPError("Empty messages are not allowed", 50006); } @@ -112,31 +145,42 @@ export async function handleMessage(opts: MessageOptions): Promise<Message> { var mention_user_ids = [] as string[]; var mention_everyone = false; - if (content) { // TODO: explicit-only mentions + if (content) { + // TODO: explicit-only mentions message.content = content.trim(); for (const [_, mention] of content.matchAll(CHANNEL_MENTION)) { - if (!mention_channel_ids.includes(mention)) mention_channel_ids.push(mention); + if (!mention_channel_ids.includes(mention)) + mention_channel_ids.push(mention); } for (const [_, mention] of content.matchAll(USER_MENTION)) { - if (!mention_user_ids.includes(mention)) mention_user_ids.push(mention); + if (!mention_user_ids.includes(mention)) + mention_user_ids.push(mention); } await Promise.all( - Array.from(content.matchAll(ROLE_MENTION)).map(async ([_, mention]) => { - const role = await Role.findOneOrFail({ where: { id: mention, guild_id: channel.guild_id } }); - if (role.mentionable || permission.has("MANAGE_ROLES")) { - mention_role_ids.push(mention); - } - }) + Array.from(content.matchAll(ROLE_MENTION)).map( + async ([_, mention]) => { + const role = await Role.findOneOrFail({ + where: { id: mention, guild_id: channel.guild_id }, + }); + if (role.mentionable || permission.has("MANAGE_ROLES")) { + mention_role_ids.push(mention); + } + }, + ), ); if (permission.has("MENTION_EVERYONE")) { - mention_everyone = !!content.match(EVERYONE_MENTION) || !!content.match(HERE_MENTION); + mention_everyone = + !!content.match(EVERYONE_MENTION) || + !!content.match(HERE_MENTION); } } - message.mention_channels = mention_channel_ids.map((x) => Channel.create({ id: x })); + message.mention_channels = mention_channel_ids.map((x) => + Channel.create({ id: x }), + ); message.mention_roles = mention_role_ids.map((x) => Role.create({ id: x })); message.mentions = mention_user_ids.map((x) => User.create({ id: x })); message.mention_everyone = mention_everyone; @@ -156,7 +200,8 @@ export async function postHandleMessage(message: Message) { links = links.slice(0, 20) as RegExpMatchArray; // embed max 20 links — TODO: make this configurable with instance policies - const { endpointPublic, resizeWidthMax, resizeHeightMax } = Config.get().cdn; + const { endpointPublic, resizeWidthMax, resizeHeightMax } = + Config.get().cdn; for (const link of links) { try { @@ -176,45 +221,64 @@ export async function postHandleMessage(message: Message) { }, image: { // can't be bothered rn - proxy_url: `${endpointPublic}/external/resize/${encodeURIComponent(link)}?width=500&height=400`, + proxy_url: `${endpointPublic}/external/resize/${encodeURIComponent( + link, + )}?width=500&height=400`, url: link, width: 500, - height: 400 - } + height: 400, + }, }; data.embeds.push(embed); - } - else { + } else { const text = await request.text(); const $ = cheerio.load(text); const title = $('meta[property="og:title"]').attr("content"); const provider_name = $('meta[property="og:site_name"]').text(); - const author_name = $('meta[property="article:author"]').attr("content"); - const description = $('meta[property="og:description"]').attr("content") || $('meta[property="description"]').attr("content"); + const author_name = $('meta[property="article:author"]').attr( + "content", + ); + const description = + $('meta[property="og:description"]').attr("content") || + $('meta[property="description"]').attr("content"); const image = $('meta[property="og:image"]').attr("content"); - const width = parseInt($('meta[property="og:image:width"]').attr("content") || "") || undefined; - const height = parseInt($('meta[property="og:image:height"]').attr("content") || "") || undefined; + const width = + parseInt( + $('meta[property="og:image:width"]').attr("content") || + "", + ) || undefined; + const height = + parseInt( + $('meta[property="og:image:height"]').attr("content") || + "", + ) || undefined; const url = $('meta[property="og:url"]').attr("content"); // TODO: color embed = { provider: { url: link, - name: provider_name - } + name: provider_name, + }, }; const resizeWidth = Math.min(resizeWidthMax ?? 1, width ?? 100); - const resizeHeight = Math.min(resizeHeightMax ?? 1, height ?? 100); + const resizeHeight = Math.min( + resizeHeightMax ?? 1, + height ?? 100, + ); if (author_name) embed.author = { name: author_name }; - if (image) embed.thumbnail = { - proxy_url: `${endpointPublic}/external/resize/${encodeURIComponent(image)}?width=${resizeWidth}&height=${resizeHeight}`, - url: image, - width: width, - height: height - }; + if (image) + embed.thumbnail = { + proxy_url: `${endpointPublic}/external/resize/${encodeURIComponent( + image, + )}?width=${resizeWidth}&height=${resizeHeight}`, + url: image, + width: width, + height: height, + }; if (title) embed.title = title; if (url) embed.url = url; if (description) embed.description = description; @@ -227,18 +291,25 @@ export async function postHandleMessage(message: Message) { // very bad code below // don't care lol - if (embed?.thumbnail?.url && approvedProviders.indexOf(new URL(embed.thumbnail.url).hostname) !== -1) { + if ( + embed?.thumbnail?.url && + approvedProviders.indexOf( + new URL(embed.thumbnail.url).hostname, + ) !== -1 + ) { embed = { provider: { url: link, name: new URL(link).hostname, }, image: { - proxy_url: `${endpointPublic}/external/resize/${encodeURIComponent(image!)}?width=${resizeWidth}&height=${resizeHeight}`, + proxy_url: `${endpointPublic}/external/resize/${encodeURIComponent( + image!, + )}?width=${resizeWidth}&height=${resizeHeight}`, url: image, width: width, - height: height - } + height: height, + }, }; } @@ -246,16 +317,19 @@ export async function postHandleMessage(message: Message) { data.embeds.push(embed); } } - } catch (error) { } + } catch (error) {} } await Promise.all([ emitEvent({ event: "MESSAGE_UPDATE", channel_id: message.channel_id, - data + data, } as MessageUpdateEvent), - Message.update({ id: message.id, channel_id: message.channel_id }, { embeds: data.embeds }) + Message.update( + { id: message.id, channel_id: message.channel_id }, + { embeds: data.embeds }, + ), ]); } @@ -264,10 +338,14 @@ export async function sendMessage(opts: MessageOptions) { await Promise.all([ Message.insert(message), - emitEvent({ event: "MESSAGE_CREATE", channel_id: opts.channel_id, data: message.toJSON() } as MessageCreateEvent) + emitEvent({ + event: "MESSAGE_CREATE", + channel_id: opts.channel_id, + data: message.toJSON(), + } as MessageCreateEvent), ]); - postHandleMessage(message).catch((e) => { }); // no await as it should catch error non-blockingly + postHandleMessage(message).catch((e) => {}); // no await as it should catch error non-blockingly return message; } diff --git a/src/api/util/handlers/Voice.ts b/src/api/util/handlers/Voice.ts index 4d60eb91..88e266a1 100644 --- a/src/api/util/handlers/Voice.ts +++ b/src/api/util/handlers/Voice.ts @@ -3,7 +3,9 @@ import { distanceBetweenLocations, IPAnalysis } from "../utility/ipAddress"; export async function getVoiceRegions(ipAddress: string, vip: boolean) { const regions = Config.get().regions; - const availableRegions = regions.available.filter((ar) => (vip ? true : !ar.vip)); + const availableRegions = regions.available.filter((ar) => + vip ? true : !ar.vip, + ); let optimalId = regions.default; if (!regions.useDefaultAsOptimal) { @@ -13,7 +15,10 @@ export async function getVoiceRegions(ipAddress: string, vip: boolean) { for (let ar of availableRegions) { //TODO the endpoint location should be saved in the database if not already present to prevent IPAnalysis call - const dist = distanceBetweenLocations(clientIpAnalysis, ar.location || (await IPAnalysis(ar.endpoint))); + const dist = distanceBetweenLocations( + clientIpAnalysis, + ar.location || (await IPAnalysis(ar.endpoint)), + ); if (dist < min) { min = dist; @@ -27,6 +32,6 @@ export async function getVoiceRegions(ipAddress: string, vip: boolean) { name: ar.name, custom: ar.custom, deprecated: ar.deprecated, - optimal: ar.id === optimalId + optimal: ar.id === optimalId, })); } diff --git a/src/api/util/handlers/route.ts b/src/api/util/handlers/route.ts index c245b411..5dcae953 100644 --- a/src/api/util/handlers/route.ts +++ b/src/api/util/handlers/route.ts @@ -10,7 +10,7 @@ import { PermissionResolvable, Permissions, RightResolvable, - Rights + Rights, } from "@fosscord/util"; import { NextFunction, Request, Response } from "express"; import { AnyValidateFunction } from "ajv/dist/core"; @@ -23,7 +23,11 @@ declare global { } } -export type RouteResponse = { status?: number; body?: `${string}Response`; headers?: Record<string, string> }; +export type RouteResponse = { + status?: number; + body?: `${string}Response`; + headers?: Record<string, string>; +}; export interface RouteOptions { permission?: PermissionResolvable; @@ -48,11 +52,17 @@ export function route(opts: RouteOptions) { return async (req: Request, res: Response, next: NextFunction) => { if (opts.permission) { const required = new Permissions(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, + ); // bitfield comparison: check if user lacks certain permission if (!req.permission.has(required)) { - throw DiscordApiErrors.MISSING_PERMISSIONS.withParams(opts.permission as string); + throw DiscordApiErrors.MISSING_PERMISSIONS.withParams( + opts.permission as string, + ); } } @@ -61,15 +71,26 @@ export function route(opts: RouteOptions) { req.rights = await getRights(req.user_id); if (!req.rights || !req.rights.has(required)) { - throw FosscordApiErrors.MISSING_RIGHTS.withParams(opts.right as string); + throw FosscordApiErrors.MISSING_RIGHTS.withParams( + opts.right as string, + ); } } if (validate) { const valid = validate(normalizeBody(req.body)); if (!valid) { - const fields: Record<string, { code?: string; message: string }> = {}; - validate.errors?.forEach((x) => (fields[x.instancePath.slice(1)] = { code: x.keyword, message: x.message || "" })); + const fields: Record< + string, + { code?: string; message: string } + > = {}; + validate.errors?.forEach( + (x) => + (fields[x.instancePath.slice(1)] = { + code: x.keyword, + message: x.message || "", + }), + ); throw FieldErrors(fields); } } |