diff options
author | Madeline <46743919+MaddyUnderStars@users.noreply.github.com> | 2023-01-05 17:12:21 +1100 |
---|---|---|
committer | Madeline <46743919+MaddyUnderStars@users.noreply.github.com> | 2023-01-05 17:16:55 +1100 |
commit | df449169bde6c0576757700f68f2d406139cc846 (patch) | |
tree | f8bcbaf30ed3ed007d392a51614a134e543e3c17 /src | |
parent | channel flags whoops (diff) | |
download | server-df449169bde6c0576757700f68f2d406139cc846.tar.xz |
Prettier
Diffstat (limited to 'src')
115 files changed, 1255 insertions, 901 deletions
diff --git a/src/api/Server.ts b/src/api/Server.ts index b8d1f9f6..fff94936 100644 --- a/src/api/Server.ts +++ b/src/api/Server.ts @@ -14,7 +14,7 @@ import { initInstance } from "./util/handlers/Instance"; import { registerRoutes } from "@fosscord/util"; import { red } from "picocolors"; -export interface FosscordServerOptions extends ServerOptions { } +export interface FosscordServerOptions extends ServerOptions {} declare global { namespace Express { @@ -76,15 +76,12 @@ export class FosscordServer extends Server { // 404 is not an error in express, so this should not be an error middleware // this is a fine place to put the 404 handler because its after we register the routes // and since its not an error middleware, our error handler below still works. - api.use( - "*", - (req: Request, res: Response, next: NextFunction) => { - res.status(404).json({ - message: "404 endpoint not found", - code: 0, - }); - }, - ); + api.use("*", (req: Request, res: Response, next: NextFunction) => { + res.status(404).json({ + message: "404 endpoint not found", + code: 0, + }); + }); this.app = app; diff --git a/src/api/routes/applications/#id/bot/index.ts b/src/api/routes/applications/#id/bot/index.ts index c21e19ca..c4cfccd8 100644 --- a/src/api/routes/applications/#id/bot/index.ts +++ b/src/api/routes/applications/#id/bot/index.ts @@ -1,13 +1,23 @@ import { Request, Response, Router } from "express"; import { route } from "@fosscord/api"; -import { Application, generateToken, User, BotModifySchema, handleFile, DiscordApiErrors } from "@fosscord/util"; +import { + Application, + generateToken, + User, + BotModifySchema, + handleFile, + DiscordApiErrors, +} from "@fosscord/util"; import { HTTPError } from "lambert-server"; import { verifyToken } from "node-2fa"; const router: Router = Router(); router.post("/", route({}), async (req: Request, res: Response) => { - const app = await Application.findOneOrFail({ where: { id: req.params.id }, relations: ["owner"] }); + const app = await Application.findOneOrFail({ + where: { id: req.params.id }, + relations: ["owner"], + }); if (app.owner.id != req.user_id) throw DiscordApiErrors.ACTION_NOT_AUTHORIZED_ON_APPLICATION; @@ -31,7 +41,7 @@ router.post("/", route({}), async (req: Request, res: Response) => { await app.save(); res.send({ - token: await generateToken(user.id) + token: await generateToken(user.id), }).status(204); }); @@ -42,7 +52,10 @@ router.post("/reset", route({}), async (req: Request, res: Response) => { if (owner.id != req.user_id) throw DiscordApiErrors.ACTION_NOT_AUTHORIZED_ON_APPLICATION; - if (owner.totp_secret && (!req.body.code || verifyToken(owner.totp_secret, req.body.code))) + if ( + owner.totp_secret && + (!req.body.code || verifyToken(owner.totp_secret, req.body.code)) + ) throw new HTTPError(req.t("auth:login.INVALID_TOTP_CODE"), 60008); bot.data = { hash: undefined, valid_tokens_since: new Date() }; @@ -54,30 +67,36 @@ router.post("/reset", route({}), async (req: Request, res: Response) => { res.json({ token }).status(200); }); -router.patch("/", route({ body: "BotModifySchema" }), async (req: Request, res: Response) => { - const body = req.body as BotModifySchema; - if (!body.avatar?.trim()) delete body.avatar; +router.patch( + "/", + route({ body: "BotModifySchema" }), + async (req: Request, res: Response) => { + const body = req.body as BotModifySchema; + if (!body.avatar?.trim()) delete body.avatar; - const app = await Application.findOneOrFail({ where: { id: req.params.id }, relations: ["bot", "owner"] }); + const app = await Application.findOneOrFail({ + where: { id: req.params.id }, + relations: ["bot", "owner"], + }); - if (!app.bot) - throw DiscordApiErrors.BOT_ONLY_ENDPOINT; + if (!app.bot) throw DiscordApiErrors.BOT_ONLY_ENDPOINT; - if (app.owner.id != req.user_id) - throw DiscordApiErrors.ACTION_NOT_AUTHORIZED_ON_APPLICATION; + if (app.owner.id != req.user_id) + throw DiscordApiErrors.ACTION_NOT_AUTHORIZED_ON_APPLICATION; - if (body.avatar) - body.avatar = await handleFile( - `/avatars/${app.id}`, - body.avatar as string, - ); + if (body.avatar) + body.avatar = await handleFile( + `/avatars/${app.id}`, + body.avatar as string, + ); - app.bot.assign(body); + app.bot.assign(body); - app.bot.save(); + app.bot.save(); - await app.save(); - res.json(app).status(200); -}); + await app.save(); + res.json(app).status(200); + }, +); -export default router; \ No newline at end of file +export default router; diff --git a/src/api/routes/applications/#id/index.ts b/src/api/routes/applications/#id/index.ts index 79df256a..11cd5a56 100644 --- a/src/api/routes/applications/#id/index.ts +++ b/src/api/routes/applications/#id/index.ts @@ -1,57 +1,81 @@ import { Request, Response, Router } from "express"; import { route } from "@fosscord/api"; -import { Application, OrmUtils, DiscordApiErrors, ApplicationModifySchema, User } from "@fosscord/util"; +import { + Application, + OrmUtils, + DiscordApiErrors, + ApplicationModifySchema, + User, +} from "@fosscord/util"; import { verifyToken } from "node-2fa"; import { HTTPError } from "lambert-server"; const router: Router = Router(); router.get("/", route({}), async (req: Request, res: Response) => { - const app = await Application.findOneOrFail({ where: { id: req.params.id }, relations: ["owner", "bot"] }); + const app = await Application.findOneOrFail({ + where: { id: req.params.id }, + relations: ["owner", "bot"], + }); if (app.owner.id != req.user_id) throw DiscordApiErrors.ACTION_NOT_AUTHORIZED_ON_APPLICATION; return res.json(app); }); -router.patch("/", route({ body: "ApplicationModifySchema" }), async (req: Request, res: Response) => { - const body = req.body as ApplicationModifySchema; +router.patch( + "/", + route({ body: "ApplicationModifySchema" }), + async (req: Request, res: Response) => { + const body = req.body as ApplicationModifySchema; - const app = await Application.findOneOrFail({ where: { id: req.params.id }, relations: ["owner", "bot"] }); + const app = await Application.findOneOrFail({ + where: { id: req.params.id }, + relations: ["owner", "bot"], + }); - if (app.owner.id != req.user_id) - throw DiscordApiErrors.ACTION_NOT_AUTHORIZED_ON_APPLICATION; + if (app.owner.id != req.user_id) + throw DiscordApiErrors.ACTION_NOT_AUTHORIZED_ON_APPLICATION; - if (app.owner.totp_secret && (!req.body.code || verifyToken(app.owner.totp_secret, req.body.code))) - throw new HTTPError(req.t("auth:login.INVALID_TOTP_CODE"), 60008); + if ( + app.owner.totp_secret && + (!req.body.code || + verifyToken(app.owner.totp_secret, req.body.code)) + ) + throw new HTTPError(req.t("auth:login.INVALID_TOTP_CODE"), 60008); - if (app.bot) { - app.bot.assign({ bio: body.description }); - await app.bot.save(); - } + if (app.bot) { + app.bot.assign({ bio: body.description }); + await app.bot.save(); + } - app.assign(body); + app.assign(body); - await app.save(); + await app.save(); - return res.json(app); -}); + return res.json(app); + }, +); router.post("/delete", route({}), async (req: Request, res: Response) => { - const app = await Application.findOneOrFail({ where: { id: req.params.id }, relations: ["bot", "owner"] }); + const app = await Application.findOneOrFail({ + where: { id: req.params.id }, + relations: ["bot", "owner"], + }); if (app.owner.id != req.user_id) throw DiscordApiErrors.ACTION_NOT_AUTHORIZED_ON_APPLICATION; - if (app.owner.totp_secret && (!req.body.code || verifyToken(app.owner.totp_secret, req.body.code))) + if ( + app.owner.totp_secret && + (!req.body.code || verifyToken(app.owner.totp_secret, req.body.code)) + ) throw new HTTPError(req.t("auth:login.INVALID_TOTP_CODE"), 60008); - if (app.bot) - await User.delete({ id: app.bot.id }); + if (app.bot) await User.delete({ id: app.bot.id }); await Application.delete({ id: app.id }); res.send().status(200); }); - -export default router; \ No newline at end of file +export default router; diff --git a/src/api/routes/applications/#id/skus.ts b/src/api/routes/applications/#id/skus.ts index 5b667f36..2383e6f7 100644 --- a/src/api/routes/applications/#id/skus.ts +++ b/src/api/routes/applications/#id/skus.ts @@ -8,4 +8,4 @@ router.get("/", route({}), async (req: Request, res: Response) => { res.json([]).status(200); }); -export default router; \ No newline at end of file +export default router; diff --git a/src/api/routes/applications/index.ts b/src/api/routes/applications/index.ts index 94cfa5c5..a6b35bfa 100644 --- a/src/api/routes/applications/index.ts +++ b/src/api/routes/applications/index.ts @@ -1,30 +1,42 @@ import { Request, Response, Router } from "express"; import { route } from "@fosscord/api"; -import { Application, ApplicationCreateSchema, trimSpecial, User } from "@fosscord/util"; +import { + Application, + ApplicationCreateSchema, + trimSpecial, + User, +} from "@fosscord/util"; const router: Router = Router(); router.get("/", route({}), async (req: Request, res: Response) => { - let results = await Application.find({ where: { owner: { id: req.user_id } }, relations: ["owner", "bot"] }); + let results = await Application.find({ + where: { owner: { id: req.user_id } }, + relations: ["owner", "bot"], + }); res.json(results).status(200); }); -router.post("/", route({ body: "ApplicationCreateSchema" }), async (req: Request, res: Response) => { - const body = req.body as ApplicationCreateSchema; - const user = await User.findOneOrFail({ where: { id: req.user_id } }); +router.post( + "/", + route({ body: "ApplicationCreateSchema" }), + async (req: Request, res: Response) => { + const body = req.body as ApplicationCreateSchema; + const user = await User.findOneOrFail({ where: { id: req.user_id } }); - const app = Application.create({ - name: trimSpecial(body.name), - description: "", - bot_public: true, - owner: user, - verify_key: "IMPLEMENTME", - flags: 0, - }); + const app = Application.create({ + name: trimSpecial(body.name), + description: "", + bot_public: true, + owner: user, + verify_key: "IMPLEMENTME", + flags: 0, + }); - await app.save(); + await app.save(); - res.json(app); -}); + res.json(app); + }, +); -export default router; \ No newline at end of file +export default router; diff --git a/src/api/routes/auth/generate-registration-tokens.ts b/src/api/routes/auth/generate-registration-tokens.ts index e328fe5e..0d4cf067 100644 --- a/src/api/routes/auth/generate-registration-tokens.ts +++ b/src/api/routes/auth/generate-registration-tokens.ts @@ -5,24 +5,37 @@ import { Request, Response, Router } from "express"; const router: Router = Router(); export default router; -router.get("/", route({ right: "OPERATOR" }), async (req: Request, res: Response) => { - const count = req.query.count ? parseInt(req.query.count as string) : 1; - const length = req.query.length ? parseInt(req.query.length as string) : 255; +router.get( + "/", + route({ right: "OPERATOR" }), + async (req: Request, res: Response) => { + const count = req.query.count ? parseInt(req.query.count as string) : 1; + const length = req.query.length + ? parseInt(req.query.length as string) + : 255; - let tokens: ValidRegistrationToken[] = []; + let tokens: ValidRegistrationToken[] = []; - for (let i = 0; i < count; i++) { - const token = ValidRegistrationToken.create({ - token: random(length), - expires_at: Date.now() + Config.get().security.defaultRegistrationTokenExpiration - }); - tokens.push(token); - } + for (let i = 0; i < count; i++) { + const token = ValidRegistrationToken.create({ + token: random(length), + expires_at: + Date.now() + + Config.get().security.defaultRegistrationTokenExpiration, + }); + tokens.push(token); + } - // Why are these options used, exactly? - await ValidRegistrationToken.save(tokens, { chunk: 1000, reload: false, transaction: false }); + // Why are these options used, exactly? + await ValidRegistrationToken.save(tokens, { + chunk: 1000, + reload: false, + transaction: false, + }); - if (req.query.plain) return res.send(tokens.map(x => x.token).join("\n")); + if (req.query.plain) + return res.send(tokens.map((x) => x.token).join("\n")); - return res.json({ tokens: tokens.map(x => x.token) }); -}); \ No newline at end of file + return res.json({ tokens: tokens.map((x) => x.token) }); + }, +); diff --git a/src/api/routes/auth/register.ts b/src/api/routes/auth/register.ts index c8c515e7..3d968114 100644 --- a/src/api/routes/auth/register.ts +++ b/src/api/routes/auth/register.ts @@ -33,16 +33,22 @@ router.post( // Reg tokens // They're a one time use token that bypasses registration limits ( rates, disabled reg, etc ) let regTokenUsed = false; - if (req.get("Referrer") && req.get("Referrer")?.includes("token=")) { // eg theyre on https://staging.fosscord.com/register?token=whatever + if (req.get("Referrer") && req.get("Referrer")?.includes("token=")) { + // eg theyre on https://staging.fosscord.com/register?token=whatever const token = req.get("Referrer")!.split("token=")[1].split("&")[0]; if (token) { - const regToken = await ValidRegistrationToken.findOne({ where: { token, expires_at: MoreThan(new Date()), } }); + const regToken = await ValidRegistrationToken.findOne({ + where: { token, expires_at: MoreThan(new Date()) }, + }); await ValidRegistrationToken.delete({ token }); regTokenUsed = true; - console.log(`[REGISTER] Registration token ${token} used for registration!`); - } - else { - console.log(`[REGISTER] Invalid registration token ${token} used for registration by ${ip}!`); + console.log( + `[REGISTER] Registration token ${token} used for registration!`, + ); + } else { + console.log( + `[REGISTER] Invalid registration token ${token} used for registration by ${ip}!`, + ); } } @@ -78,7 +84,11 @@ router.post( }); } - if (!regTokenUsed && register.requireCaptcha && security.captcha.enabled) { + if ( + !regTokenUsed && + register.requireCaptcha && + security.captcha.enabled + ) { const { sitekey, service } = security.captcha; if (!body.captcha_key) { return res?.status(400).json({ @@ -220,14 +230,26 @@ router.post( if ( !regTokenUsed && limits.absoluteRate.register.enabled && - (await User.count({ where: { created_at: MoreThan(new Date(Date.now() - limits.absoluteRate.register.window)) } })) - >= limits.absoluteRate.register.limit + (await User.count({ + where: { + created_at: MoreThan( + new Date( + Date.now() - limits.absoluteRate.register.window, + ), + ), + }, + })) >= limits.absoluteRate.register.limit ) { console.log( - `Global register ratelimit exceeded for ${getIpAdress(req)}, ${req.body.username}, ${req.body.invite || "No invite given"}` + `Global register ratelimit exceeded for ${getIpAdress(req)}, ${ + req.body.username + }, ${req.body.invite || "No invite given"}`, ); throw FieldErrors({ - email: { code: "TOO_MANY_REGISTRATIONS", message: req.t("auth:register.TOO_MANY_REGISTRATIONS") } + email: { + code: "TOO_MANY_REGISTRATIONS", + message: req.t("auth:register.TOO_MANY_REGISTRATIONS"), + }, }); } diff --git a/src/api/routes/channels/#channel_id/messages/#message_id/index.ts b/src/api/routes/channels/#channel_id/messages/#message_id/index.ts index cd9da184..d57d9a1b 100644 --- a/src/api/routes/channels/#channel_id/messages/#message_id/index.ts +++ b/src/api/routes/channels/#channel_id/messages/#message_id/index.ts @@ -179,7 +179,7 @@ router.put( channel.save(), ]); - postHandleMessage(message).catch((e) => { }); // no await as it shouldnt block the message send function and silently catch error + postHandleMessage(message).catch((e) => {}); // no await as it shouldnt block the message send function and silently catch error return res.json(message); }, diff --git a/src/api/routes/channels/#channel_id/messages/index.ts b/src/api/routes/channels/#channel_id/messages/index.ts index 523b0cf8..2968437d 100644 --- a/src/api/routes/channels/#channel_id/messages/index.ts +++ b/src/api/routes/channels/#channel_id/messages/index.ts @@ -21,7 +21,12 @@ import { Rights, } from "@fosscord/util"; import { HTTPError } from "lambert-server"; -import { handleMessage, postHandleMessage, route, getIpAdress } from "@fosscord/api"; +import { + handleMessage, + postHandleMessage, + route, + getIpAdress, +} from "@fosscord/api"; import multer from "multer"; import { yellow } from "picocolors"; import { FindManyOptions, LessThan, MoreThan } from "typeorm"; @@ -80,7 +85,7 @@ router.get("/", async (req: Request, res: Response) => { permissions.hasThrow("VIEW_CHANNEL"); if (!permissions.has("READ_MESSAGE_HISTORY")) return res.json([]); - var query: FindManyOptions<Message> & { where: { id?: any; }; } = { + var query: FindManyOptions<Message> & { where: { id?: any } } = { order: { timestamp: "DESC" }, take: limit, where: { channel_id }, @@ -138,8 +143,9 @@ router.get("/", async (req: Request, res: Response) => { const uri = y.proxy_url.startsWith("http") ? y.proxy_url : `https://example.org${y.proxy_url}`; - y.proxy_url = `${endpoint == null ? "" : endpoint}${new URL(uri).pathname - }`; + y.proxy_url = `${endpoint == null ? "" : endpoint}${ + new URL(uri).pathname + }`; }); /** @@ -211,8 +217,8 @@ router.post( where: { nonce: body.nonce, channel_id: channel.id, - author_id: req.user_id - } + author_id: req.user_id, + }, }); if (existing) { return res.json(existing); @@ -225,13 +231,21 @@ router.post( const count = await Message.count({ where: { channel_id, - timestamp: MoreThan(new Date(Date.now() - limits.absoluteRate.sendMessage.window)) - } + timestamp: MoreThan( + new Date( + Date.now() - + limits.absoluteRate.sendMessage.window, + ), + ), + }, }); if (count >= limits.absoluteRate.sendMessage.limit) throw FieldErrors({ - channel_id: { code: "TOO_MANY_MESSAGES", message: req.t("common:toomany.MESSAGE") } + channel_id: { + code: "TOO_MANY_MESSAGES", + message: req.t("common:toomany.MESSAGE"), + }, }); } } @@ -247,7 +261,7 @@ router.post( Attachment.create({ ...file, proxy_url: file.url }), ); } catch (error) { - return res.status(400).json({ message: error!.toString() }) + return res.status(400).json({ message: error!.toString() }); } } @@ -296,19 +310,18 @@ router.post( if (!message.member) { message.member = await Member.findOneOrFail({ where: { id: req.user_id, guild_id: message.guild_id }, - relations: ["roles"] + relations: ["roles"], }); } //@ts-ignore - message.member.roles = - message.member.roles. - filter(x => x.id != x.guild_id) - .map(x => x.id); + message.member.roles = message.member.roles + .filter((x) => x.id != x.guild_id) + .map((x) => x.id); } let read_state = await ReadState.findOne({ - where: { user_id: req.user_id, channel_id } + where: { user_id: req.user_id, channel_id }, }); if (!read_state) read_state = ReadState.create({ user_id: req.user_id, channel_id }); @@ -324,14 +337,14 @@ router.post( } as MessageCreateEvent), message.guild_id ? Member.update( - { id: req.user_id, guild_id: message.guild_id }, - { last_message_id: message.id }, - ) + { id: req.user_id, guild_id: message.guild_id }, + { last_message_id: message.id }, + ) : null, channel.save(), ]); - postHandleMessage(message).catch((e) => { }); // no await as it shouldnt block the message send function and silently catch error + postHandleMessage(message).catch((e) => {}); // no await as it shouldnt block the message send function and silently catch error return res.json(message); }, diff --git a/src/api/routes/channels/#channel_id/permissions.ts b/src/api/routes/channels/#channel_id/permissions.ts index 0a816223..b08cd0c8 100644 --- a/src/api/routes/channels/#channel_id/permissions.ts +++ b/src/api/routes/channels/#channel_id/permissions.ts @@ -5,7 +5,7 @@ import { emitEvent, Member, Role, - ChannelPermissionOverwriteSchema + ChannelPermissionOverwriteSchema, } from "@fosscord/util"; import { Router, Response, Request } from "express"; import { HTTPError } from "lambert-server"; diff --git a/src/api/routes/channels/#channel_id/webhooks.ts b/src/api/routes/channels/#channel_id/webhooks.ts index 13f421f1..f303ef80 100644 --- a/src/api/routes/channels/#channel_id/webhooks.ts +++ b/src/api/routes/channels/#channel_id/webhooks.ts @@ -1,6 +1,15 @@ import { Router, Response, Request } from "express"; import { route } from "@fosscord/api"; -import { Channel, Config, handleFile, trimSpecial, User, Webhook, WebhookCreateSchema, WebhookType } from "@fosscord/util"; +import { + Channel, + Config, + handleFile, + trimSpecial, + User, + Webhook, + WebhookCreateSchema, + WebhookType, +} from "@fosscord/util"; import { HTTPError } from "lambert-server"; import { isTextChannel } from "./messages/index"; import { DiscordApiErrors } from "@fosscord/util"; @@ -38,8 +47,7 @@ router.post( if (name === "clyde") throw new HTTPError("Invalid name", 400); if (name === "Fosscord Ghost") throw new HTTPError("Invalid name", 400); - if (avatar) - avatar = await handleFile(`/avatars/${channel_id}`, avatar); + if (avatar) avatar = await handleFile(`/avatars/${channel_id}`, avatar); const hook = Webhook.create({ type: WebhookType.Incoming, diff --git a/src/api/routes/download/index.ts b/src/api/routes/download/index.ts index 371c0fd7..1c135f25 100644 --- a/src/api/routes/download/index.ts +++ b/src/api/routes/download/index.ts @@ -12,19 +12,20 @@ const router = Router(); router.get("/", route({}), async (req: Request, res: Response) => { const { platform } = req.query; - if (!platform) throw FieldErrors({ - platform: { - code: "BASE_TYPE_REQUIRED", - message: req.t("common:field.BASE_TYPE_REQUIRED"), - } - }); + if (!platform) + throw FieldErrors({ + platform: { + code: "BASE_TYPE_REQUIRED", + message: req.t("common:field.BASE_TYPE_REQUIRED"), + }, + }); const release = await Release.findOneOrFail({ where: { enabled: true, platform: platform as string, }, - order: { pub_date: "DESC" } + order: { pub_date: "DESC" }, }); res.redirect(release.url); diff --git a/src/api/routes/guild-recommendations.ts b/src/api/routes/guild-recommendations.ts index 302bbb9c..8bf1e508 100644 --- a/src/api/routes/guild-recommendations.ts +++ b/src/api/routes/guild-recommendations.ts @@ -9,7 +9,7 @@ const router = Router(); router.get("/", route({}), async (req: Request, res: Response) => { const { limit, personalization_disabled } = req.query; var showAllGuilds = Config.get().guild.discovery.showAllGuilds; - + const genLoadId = (size: Number) => [...Array(size)] .map(() => Math.floor(Math.random() * 16).toString(16)) diff --git a/src/api/routes/guilds/#guild_id/index.ts b/src/api/routes/guilds/#guild_id/index.ts index 1e976293..79c20678 100644 --- a/src/api/routes/guilds/#guild_id/index.ts +++ b/src/api/routes/guilds/#guild_id/index.ts @@ -69,15 +69,21 @@ router.patch( body.splash, ); - if (body.discovery_splash && body.discovery_splash !== guild.discovery_splash) + if ( + body.discovery_splash && + body.discovery_splash !== guild.discovery_splash + ) body.discovery_splash = await handleFile( `/discovery-splashes/${guild_id}`, body.discovery_splash, ); if (body.features) { - const diff = guild.features.filter(x => !body.features?.includes(x)) - .concat(body.features.filter(x => !guild.features.includes(x))); + const diff = guild.features + .filter((x) => !body.features?.includes(x)) + .concat( + body.features.filter((x) => !guild.features.includes(x)), + ); // TODO move these const MUTABLE_FEATURES = [ @@ -89,7 +95,9 @@ router.patch( for (var feature of diff) { if (MUTABLE_FEATURES.includes(feature)) continue; - throw FosscordApiErrors.FEATURE_IS_IMMUTABLE.withParams(feature); + throw FosscordApiErrors.FEATURE_IS_IMMUTABLE.withParams( + feature, + ); } // for some reason, they don't update in the assign. diff --git a/src/api/routes/guilds/#guild_id/members/#member_id/index.ts b/src/api/routes/guilds/#guild_id/members/#member_id/index.ts index f1d343d9..0fcdd57c 100644 --- a/src/api/routes/guilds/#guild_id/members/#member_id/index.ts +++ b/src/api/routes/guilds/#guild_id/members/#member_id/index.ts @@ -27,42 +27,56 @@ router.get("/", route({}), async (req: Request, res: Response) => { return res.json(member); }); -router.patch("/", route({ body: "MemberChangeSchema" }), async (req: Request, res: Response) => { - let { guild_id, member_id } = req.params; - if (member_id === "@me") member_id = req.user_id; - const body = req.body as MemberChangeSchema; - - let member = await Member.findOneOrFail({ where: { id: member_id, guild_id }, relations: ["roles", "user"] }); - const permission = await getPermission(req.user_id, guild_id); - const everyone = await Role.findOneOrFail({ where: { guild_id: guild_id, name: "@everyone", position: 0 } }); - - if (body.avatar) body.avatar = await handleFile(`/guilds/${guild_id}/users/${member_id}/avatars`, body.avatar as string); - - member.assign(body); - - if ('roles' in body) { - permission.hasThrow("MANAGE_ROLES"); - - body.roles = body.roles || []; - body.roles.filter(x => !!x); - - if (body.roles.indexOf(everyone.id) === -1) body.roles.push(everyone.id); - member.roles = body.roles.map((x) => Role.create({ id: x })); // foreign key constraint will fail if role doesn't exist - } - - await member.save(); - - member.roles = member.roles.filter((x) => x.id !== everyone.id); - - // do not use promise.all as we have to first write to db before emitting the event to catch errors - await emitEvent({ - event: "GUILD_MEMBER_UPDATE", - guild_id, - data: { ...member, roles: member.roles.map((x) => x.id) } - } as GuildMemberUpdateEvent); - - res.json(member); -}); +router.patch( + "/", + route({ body: "MemberChangeSchema" }), + async (req: Request, res: Response) => { + let { guild_id, member_id } = req.params; + if (member_id === "@me") member_id = req.user_id; + const body = req.body as MemberChangeSchema; + + let member = await Member.findOneOrFail({ + where: { id: member_id, guild_id }, + relations: ["roles", "user"], + }); + const permission = await getPermission(req.user_id, guild_id); + const everyone = await Role.findOneOrFail({ + where: { guild_id: guild_id, name: "@everyone", position: 0 }, + }); + + if (body.avatar) + body.avatar = await handleFile( + `/guilds/${guild_id}/users/${member_id}/avatars`, + body.avatar as string, + ); + + member.assign(body); + + if ("roles" in body) { + permission.hasThrow("MANAGE_ROLES"); + + body.roles = body.roles || []; + body.roles.filter((x) => !!x); + + if (body.roles.indexOf(everyone.id) === -1) + body.roles.push(everyone.id); + member.roles = body.roles.map((x) => Role.create({ id: x })); // foreign key constraint will fail if role doesn't exist + } + + await member.save(); + + member.roles = member.roles.filter((x) => x.id !== everyone.id); + + // do not use promise.all as we have to first write to db before emitting the event to catch errors + await emitEvent({ + event: "GUILD_MEMBER_UPDATE", + guild_id, + data: { ...member, roles: member.roles.map((x) => x.id) }, + } as GuildMemberUpdateEvent); + + res.json(member); + }, +); router.put("/", route({}), async (req: Request, res: Response) => { // TODO: Lurker mode diff --git a/src/api/routes/guilds/#guild_id/messages/search.ts b/src/api/routes/guilds/#guild_id/messages/search.ts index ccee59f7..88488871 100644 --- a/src/api/routes/guilds/#guild_id/messages/search.ts +++ b/src/api/routes/guilds/#guild_id/messages/search.ts @@ -72,12 +72,20 @@ router.get("/", route({}), async (req: Request, res: Response) => { if (channel_id) query.where!.channel = { id: channel_id }; else { // get all channel IDs that this user can access - const channels = await Channel.find({ where: { guild_id: req.params.guild_id }, select: ["id"] }); + const channels = await Channel.find({ + where: { guild_id: req.params.guild_id }, + select: ["id"], + }); const ids = []; for (var channel of channels) { - const perm = await getPermission(req.user_id, req.params.guild_id, channel.id); - if (!perm.has("VIEW_CHANNEL") || !perm.has("READ_MESSAGE_HISTORY")) continue; + const perm = await getPermission( + req.user_id, + req.params.guild_id, + channel.id, + ); + if (!perm.has("VIEW_CHANNEL") || !perm.has("READ_MESSAGE_HISTORY")) + continue; ids.push(channel.id); } diff --git a/src/api/routes/guilds/#guild_id/profile/index.ts b/src/api/routes/guilds/#guild_id/profile/index.ts index ddc30943..20a7fa95 100644 --- a/src/api/routes/guilds/#guild_id/profile/index.ts +++ b/src/api/routes/guilds/#guild_id/profile/index.ts @@ -1,30 +1,48 @@ import { route } from "@fosscord/api"; -import { emitEvent, GuildMemberUpdateEvent, handleFile, Member, MemberChangeProfileSchema, OrmUtils } from "@fosscord/util"; +import { + emitEvent, + GuildMemberUpdateEvent, + handleFile, + Member, + MemberChangeProfileSchema, + OrmUtils, +} from "@fosscord/util"; import { Request, Response, Router } from "express"; const router = Router(); -router.patch("/:member_id", route({ body: "MemberChangeProfileSchema" }), async (req: Request, res: Response) => { - let { guild_id, member_id } = req.params; - if (member_id === "@me") member_id = req.user_id; - const body = req.body as MemberChangeProfileSchema; - - let member = await Member.findOneOrFail({ where: { id: req.user_id, guild_id }, relations: ["roles", "user"] }); - - if (body.banner) body.banner = await handleFile(`/guilds/${guild_id}/users/${req.user_id}/avatars`, body.banner as string); - - member = await OrmUtils.mergeDeep(member, body); - - await member.save(); - - // do not use promise.all as we have to first write to db before emitting the event to catch errors - await emitEvent({ - event: "GUILD_MEMBER_UPDATE", - guild_id, - data: { ...member, roles: member.roles.map((x) => x.id) } - } as GuildMemberUpdateEvent); - - res.json(member); -}); +router.patch( + "/:member_id", + route({ body: "MemberChangeProfileSchema" }), + async (req: Request, res: Response) => { + let { guild_id, member_id } = req.params; + if (member_id === "@me") member_id = req.user_id; + const body = req.body as MemberChangeProfileSchema; + + let member = await Member.findOneOrFail({ + where: { id: req.user_id, guild_id }, + relations: ["roles", "user"], + }); + + if (body.banner) + body.banner = await handleFile( + `/guilds/${guild_id}/users/${req.user_id}/avatars`, + body.banner as string, + ); + + member = await OrmUtils.mergeDeep(member, body); + + await member.save(); + + // do not use promise.all as we have to first write to db before emitting the event to catch errors + await emitEvent({ + event: "GUILD_MEMBER_UPDATE", + guild_id, + data: { ...member, roles: member.roles.map((x) => x.id) }, + } as GuildMemberUpdateEvent); + + res.json(member); + }, +); export default router; diff --git a/src/api/routes/guilds/#guild_id/roles/#role_id/index.ts b/src/api/routes/guilds/#guild_id/roles/#role_id/index.ts index cd5959ff..84648703 100644 --- a/src/api/routes/guilds/#guild_id/roles/#role_id/index.ts +++ b/src/api/routes/guilds/#guild_id/roles/#role_id/index.ts @@ -63,12 +63,14 @@ router.patch( ); else body.icon = undefined; - const role = await Role.findOneOrFail({ where: { id: role_id, guild: { id: guild_id } } }); + const role = await Role.findOneOrFail({ + where: { id: role_id, guild: { id: guild_id } }, + }); role.assign({ ...body, permissions: String( - req.permission!.bitfield & BigInt(body.permissions || "0") - ) + req.permission!.bitfield & BigInt(body.permissions || "0"), + ), }); await Promise.all([ diff --git a/src/api/routes/guilds/#guild_id/roles/index.ts b/src/api/routes/guilds/#guild_id/roles/index.ts index 534a5967..4cd47cf3 100644 --- a/src/api/routes/guilds/#guild_id/roles/index.ts +++ b/src/api/routes/guilds/#guild_id/roles/index.ts @@ -61,9 +61,13 @@ router.post( await Promise.all([ role.save(), // Move all existing roles up one position, to accommodate the new role - Role.createQueryBuilder('roles') - .where({ guild: { id: guild_id }, name: Not("@everyone"), id: Not(role.id) }) - .update({ position: () => 'position + 1' }) + Role.createQueryBuilder("roles") + .where({ + guild: { id: guild_id }, + name: Not("@everyone"), + id: Not(role.id), + }) + .update({ position: () => "position + 1" }) .execute(), emitEvent({ event: "GUILD_ROLE_CREATE", diff --git a/src/api/routes/oauth2/authorize.ts b/src/api/routes/oauth2/authorize.ts index e4c2e986..6374972e 100644 --- a/src/api/routes/oauth2/authorize.ts +++ b/src/api/routes/oauth2/authorize.ts @@ -1,17 +1,24 @@ import { Router, Request, Response } from "express"; import { route } from "@fosscord/api"; -import { ApiError, Application, ApplicationAuthorizeSchema, getPermission, DiscordApiErrors, Member, Permissions, User, getRights, Rights, MemberPrivateProjection } from "@fosscord/util"; +import { + ApiError, + Application, + ApplicationAuthorizeSchema, + getPermission, + DiscordApiErrors, + Member, + Permissions, + User, + getRights, + Rights, + MemberPrivateProjection, +} from "@fosscord/util"; const router = Router(); // TODO: scopes, other oauth types router.get("/", route({}), async (req: Request, res: Response) => { - const { - client_id, - scope, - response_type, - redirect_url, - } = req.query; + const { client_id, scope, response_type, redirect_url } = req.query; const app = await Application.findOne({ where: { @@ -33,7 +40,7 @@ router.get("/", route({}), async (req: Request, res: Response) => { id: req.user_id, bot: false, }, - select: ["id", "username", "avatar", "discriminator", "public_flags"] + select: ["id", "username", "avatar", "discriminator", "public_flags"], }); const guilds = await Member.find({ @@ -44,21 +51,23 @@ router.get("/", route({}), async (req: Request, res: Response) => { }, relations: ["guild", "roles"], //@ts-ignore - select: ["guild.id", "guild.name", "guild.icon", "guild.mfa_level", "guild.owner_id", "roles.id"] + // prettier-ignore + select: ["guild.id", "guild.name", "guild.icon", "guild.mfa_level", "guild.owner_id", "roles.id"], }); - const guildsWithPermissions = guilds.map(x => { - const perms = x.guild.owner_id === user.id - ? new Permissions(Permissions.FLAGS.ADMINISTRATOR) - : Permissions.finalPermission({ - user: { - id: user.id, - roles: x.roles?.map(x => x.id) || [], - }, - guild: { - roles: x?.roles || [], - } - }); + const guildsWithPermissions = guilds.map((x) => { + const perms = + x.guild.owner_id === user.id + ? new Permissions(Permissions.FLAGS.ADMINISTRATOR) + : Permissions.finalPermission({ + user: { + id: user.id, + roles: x.roles?.map((x) => x.id) || [], + }, + guild: { + roles: x?.roles || [], + }, + }); return { id: x.guild.id, @@ -75,7 +84,7 @@ router.get("/", route({}), async (req: Request, res: Response) => { id: user.id, username: user.username, avatar: user.avatar, - avatar_decoration: null, // TODO + avatar_decoration: null, // TODO discriminator: user.discriminator, public_flags: user.public_flags, }, @@ -87,7 +96,7 @@ router.get("/", route({}), async (req: Request, res: Response) => { summary: app.summary, type: app.type, hook: app.hook, - guild_id: null, // TODO support guilds + guild_id: null, // TODO support guilds bot_public: app.bot_public, bot_require_code_grant: app.bot_require_code_grant, verify_key: app.verify_key, @@ -97,50 +106,63 @@ router.get("/", route({}), async (req: Request, res: Response) => { id: bot.id, username: bot.username, avatar: bot.avatar, - avatar_decoration: null, // TODO + avatar_decoration: null, // TODO discriminator: bot.discriminator, public_flags: bot.public_flags, bot: true, - approximated_guild_count: 0, // TODO + approximated_guild_count: 0, // TODO }, authorized: false, }); }); -router.post("/", route({ body: "ApplicationAuthorizeSchema" }), async (req: Request, res: Response) => { - const body = req.body as ApplicationAuthorizeSchema; - const { - client_id, - scope, - response_type, - redirect_url - } = req.query; - - // TODO: captcha verification - // TODO: MFA verification - - const perms = await getPermission(req.user_id, body.guild_id, undefined, { member_relations: ["user"] }); - // getPermission cache won't exist if we're owner - if (Object.keys(perms.cache || {}).length > 0 && perms.cache.member!.user.bot) throw DiscordApiErrors.UNAUTHORIZED; - perms.hasThrow("MANAGE_GUILD"); - - const app = await Application.findOne({ - where: { - id: client_id as string, - }, - relations: ["bot"], - }); - - // TODO: use DiscordApiErrors - // findOneOrFail throws code 404 - if (!app) throw new ApiError("Unknown Application", 10002, 404); - if (!app.bot) throw new ApiError("OAuth2 application does not have a bot", 50010, 400); - - await Member.addToGuild(app.id, body.guild_id); - - return res.json({ - location: "/oauth2/authorized", // redirect URL - }); -}); +router.post( + "/", + route({ body: "ApplicationAuthorizeSchema" }), + async (req: Request, res: Response) => { + const body = req.body as ApplicationAuthorizeSchema; + const { client_id, scope, response_type, redirect_url } = req.query; + + // TODO: captcha verification + // TODO: MFA verification + + const perms = await getPermission( + req.user_id, + body.guild_id, + undefined, + { member_relations: ["user"] }, + ); + // getPermission cache won't exist if we're owner + if ( + Object.keys(perms.cache || {}).length > 0 && + perms.cache.member!.user.bot + ) + throw DiscordApiErrors.UNAUTHORIZED; + perms.hasThrow("MANAGE_GUILD"); + + const app = await Application.findOne({ + where: { + id: client_id as string, + }, + relations: ["bot"], + }); + + // TODO: use DiscordApiErrors + // findOneOrFail throws code 404 + if (!app) throw new ApiError("Unknown Application", 10002, 404); + if (!app.bot) + throw new ApiError( + "OAuth2 application does not have a bot", + 50010, + 400, + ); + + await Member.addToGuild(app.id, body.guild_id); + + return res.json({ + location: "/oauth2/authorized", // redirect URL + }); + }, +); export default router; diff --git a/src/api/routes/policies/stats.ts b/src/api/routes/policies/stats.ts index 5ef4c3c6..dc4652fc 100644 --- a/src/api/routes/policies/stats.ts +++ b/src/api/routes/policies/stats.ts @@ -1,5 +1,12 @@ import { route } from "@fosscord/api"; -import { Config, getRights, Guild, Member, Message, User } from "@fosscord/util"; +import { + Config, + getRights, + Guild, + Member, + Message, + User, +} from "@fosscord/util"; import { Request, Response, Router } from "express"; const router = Router(); @@ -15,7 +22,7 @@ router.get("/", route({}), async (req: Request, res: Response) => { guild: await Guild.count(), message: await Message.count(), members: await Member.count(), - } + }, }); }); diff --git a/src/api/routes/stop.ts b/src/api/routes/stop.ts index 1b4e1da9..3f49b360 100644 --- a/src/api/routes/stop.ts +++ b/src/api/routes/stop.ts @@ -3,10 +3,14 @@ import { route } from "@fosscord/api"; const router: Router = Router(); -router.post("/", route({ right: "OPERATOR" }), async (req: Request, res: Response) => { - console.log(`/stop was called by ${req.user_id} at ${new Date()}`); - res.sendStatus(200); - process.kill(process.pid, "SIGTERM"); -}); +router.post( + "/", + route({ right: "OPERATOR" }), + async (req: Request, res: Response) => { + console.log(`/stop was called by ${req.user_id} at ${new Date()}`); + res.sendStatus(200); + process.kill(process.pid, "SIGTERM"); + }, +); -export default router; \ No newline at end of file +export default router; diff --git a/src/api/routes/store/published-listings/skus/#sku_id/subscription-plans.ts b/src/api/routes/store/published-listings/skus/#sku_id/subscription-plans.ts index 7c544921..6b49e959 100644 --- a/src/api/routes/store/published-listings/skus/#sku_id/subscription-plans.ts +++ b/src/api/routes/store/published-listings/skus/#sku_id/subscription-plans.ts @@ -16,7 +16,7 @@ const skus = new Map([ sku_id: "521842865731534868", currency: "eur", price: 0, - price_tier: null + price_tier: null, }, { id: "511651860671627264", @@ -27,9 +27,9 @@ const skus = new Map([ sku_id: "521842865731534868", currency: "eur", price: 0, - price_tier: null - } - ] + price_tier: null, + }, + ], ], [ "521846918637420545", @@ -43,7 +43,7 @@ const skus = new Map([ sku_id: "521846918637420545", currency: "eur", price: 0, - price_tier: null + price_tier: null, }, { id: "511651876987469824", @@ -54,7 +54,7 @@ const skus = new Map([ sku_id: "521846918637420545", currency: "eur", price: 0, - price_tier: null + price_tier: null, }, { id: "978380684370378761", @@ -65,9 +65,9 @@ const skus = new Map([ sku_id: "521846918637420545", currency: "eur", price: 0, - price_tier: null - } - ] + price_tier: null, + }, + ], ], [ "521847234246082599", @@ -81,7 +81,7 @@ const skus = new Map([ sku_id: "521847234246082599", currency: "eur", price: 0, - price_tier: null + price_tier: null, }, { id: "511651880837840896", @@ -92,7 +92,7 @@ const skus = new Map([ sku_id: "521847234246082599", currency: "eur", price: 0, - price_tier: null + price_tier: null, }, { id: "511651885459963904", @@ -103,9 +103,9 @@ const skus = new Map([ sku_id: "521847234246082599", currency: "eur", price: 0, - price_tier: null - } - ] + price_tier: null, + }, + ], ], [ "590663762298667008", @@ -120,7 +120,7 @@ const skus = new Map([ discount_price: 0, currency: "eur", price: 0, - price_tier: null + price_tier: null, }, { id: "590665538238152709", @@ -132,9 +132,9 @@ const skus = new Map([ discount_price: 0, currency: "eur", price: 0, - price_tier: null - } - ] + price_tier: null, + }, + ], ], [ "978380684370378762", @@ -158,33 +158,33 @@ const skus = new Map([ { currency: "usd", amount: 0, - exponent: 2 - } - ] + exponent: 2, + }, + ], }, payment_source_prices: { "775487223059316758": [ { currency: "usd", amount: 0, - exponent: 2 - } + exponent: 2, + }, ], "736345864146255982": [ { currency: "usd", amount: 0, - exponent: 2 - } + exponent: 2, + }, ], "683074999590060249": [ { currency: "usd", amount: 0, - exponent: 2 - } - ] - } + exponent: 2, + }, + ], + }, }, "3": { country_prices: { @@ -193,33 +193,33 @@ const skus = new Map([ { currency: "usd", amount: 0, - exponent: 2 - } - ] + exponent: 2, + }, + ], }, payment_source_prices: { "775487223059316758": [ { currency: "usd", amount: 0, - exponent: 2 - } + exponent: 2, + }, ], "736345864146255982": [ { currency: "usd", amount: 0, - exponent: 2 - } + exponent: 2, + }, ], "683074999590060249": [ { currency: "usd", amount: 0, - exponent: 2 - } - ] - } + exponent: 2, + }, + ], + }, }, "4": { country_prices: { @@ -228,33 +228,33 @@ const skus = new Map([ { currency: "usd", amount: 0, - exponent: 2 - } - ] + exponent: 2, + }, + ], }, payment_source_prices: { "775487223059316758": [ { currency: "usd", amount: 0, - exponent: 2 - } + exponent: 2, + }, ], "736345864146255982": [ { currency: "usd", amount: 0, - exponent: 2 - } + exponent: 2, + }, ], "683074999590060249": [ { currency: "usd", amount: 0, - exponent: 2 - } - ] - } + exponent: 2, + }, + ], + }, }, "1": { country_prices: { @@ -263,39 +263,39 @@ const skus = new Map([ { currency: "usd", amount: 0, - exponent: 2 - } - ] + exponent: 2, + }, + ], }, payment_source_prices: { "775487223059316758": [ { currency: "usd", amount: 0, - exponent: 2 - } + exponent: 2, + }, ], "736345864146255982": [ { currency: "usd", amount: 0, - exponent: 2 - } + exponent: 2, + }, ], "683074999590060249": [ { currency: "usd", amount: 0, - exponent: 2 - } - ] - } - } - } - } - ] - ] - ] + exponent: 2, + }, + ], + }, + }, + }, + }, + ], + ], + ], ]); router.get("/", route({}), async (req: Request, res: Response) => { diff --git a/src/api/routes/updates.ts b/src/api/routes/updates.ts index 275c458b..7e9128f4 100644 --- a/src/api/routes/updates.ts +++ b/src/api/routes/updates.ts @@ -8,19 +8,20 @@ router.get("/", route({}), async (req: Request, res: Response) => { const { client } = Config.get(); const platform = req.query.platform; - if (!platform) throw FieldErrors({ - platform: { - code: "BASE_TYPE_REQUIRED", - message: req.t("common:field.BASE_TYPE_REQUIRED"), - } - }); + if (!platform) + throw FieldErrors({ + platform: { + code: "BASE_TYPE_REQUIRED", + message: req.t("common:field.BASE_TYPE_REQUIRED"), + }, + }); const release = await Release.findOneOrFail({ where: { enabled: true, platform: platform as string, }, - order: { pub_date: "DESC" } + order: { pub_date: "DESC" }, }); res.json({ diff --git a/src/api/routes/users/#id/profile.ts b/src/api/routes/users/#id/profile.ts index ac844427..5c649056 100644 --- a/src/api/routes/users/#id/profile.ts +++ b/src/api/routes/users/#id/profile.ts @@ -89,79 +89,94 @@ router.get( bot: user.bot, }; - const userProfile = { - bio: req.user_bot ? null : user.bio, - accent_color: user.accent_color, - banner: user.banner, - pronouns: user.pronouns, - theme_colors: user.theme_colors, - }; - - const guildMemberDto = guild_member - ? { - avatar: guild_member.avatar, - banner: guild_member.banner, - bio: req.user_bot ? null : guild_member.bio, - communication_disabled_until: guild_member.communication_disabled_until, - deaf: guild_member.deaf, - flags: user.flags, - is_pending: guild_member.pending, - pending: guild_member.pending, // why is this here twice, discord? - joined_at: guild_member.joined_at, - mute: guild_member.mute, - nick: guild_member.nick, - premium_since: guild_member.premium_since, - roles: guild_member.roles.map((x) => x.id).filter((id) => id != guild_id), - user: userDto - } - : undefined; - - const guildMemberProfile = { - accent_color: null, - banner: guild_member?.banner || null, - bio: guild_member?.bio || "", - guild_id - }; - res.json({ - connected_accounts: user.connected_accounts, - premium_guild_since: premium_guild_since, // TODO - premium_since: user.premium_since, // TODO - mutual_guilds: mutual_guilds, // TODO {id: "", nick: null} when ?with_mutual_guilds=true - user: userDto, - premium_type: user.premium_type, - profile_themes_experiment_bucket: 4, // TODO: This doesn't make it available, for some reason? - user_profile: userProfile, - guild_member: guild_id && guildMemberDto, - guild_member_profile: guild_id && guildMemberProfile - }); -}); - -router.patch("/", route({ body: "UserProfileModifySchema" }), async (req: Request, res: Response) => { - const body = req.body as UserProfileModifySchema; - - if (body.banner) body.banner = await handleFile(`/banners/${req.user_id}`, body.banner as string); - let user = await User.findOneOrFail({ where: { id: req.user_id }, select: [...PrivateUserProjection, "data"] }); - - user.assign(body); - await user.save(); - - // @ts-ignore - delete user.data; - - // TODO: send update member list event in gateway - await emitEvent({ - event: "USER_UPDATE", - user_id: req.user_id, - data: user - } as UserUpdateEvent); - - res.json({ - accent_color: user.accent_color, - bio: user.bio, - banner: user.banner, - theme_colors: user.theme_colors, - pronouns: user.pronouns, - }); -}); + const userProfile = { + bio: req.user_bot ? null : user.bio, + accent_color: user.accent_color, + banner: user.banner, + pronouns: user.pronouns, + theme_colors: user.theme_colors, + }; + + const guildMemberDto = guild_member + ? { + avatar: guild_member.avatar, + banner: guild_member.banner, + bio: req.user_bot ? null : guild_member.bio, + communication_disabled_until: + guild_member.communication_disabled_until, + deaf: guild_member.deaf, + flags: user.flags, + is_pending: guild_member.pending, + pending: guild_member.pending, // why is this here twice, discord? + joined_at: guild_member.joined_at, + mute: guild_member.mute, + nick: guild_member.nick, + premium_since: guild_member.premium_since, + roles: guild_member.roles + .map((x) => x.id) + .filter((id) => id != guild_id), + user: userDto, + } + : undefined; + + const guildMemberProfile = { + accent_color: null, + banner: guild_member?.banner || null, + bio: guild_member?.bio || "", + guild_id, + }; + res.json({ + connected_accounts: user.connected_accounts, + premium_guild_since: premium_guild_since, // TODO + premium_since: user.premium_since, // TODO + mutual_guilds: mutual_guilds, // TODO {id: "", nick: null} when ?with_mutual_guilds=true + user: userDto, + premium_type: user.premium_type, + profile_themes_experiment_bucket: 4, // TODO: This doesn't make it available, for some reason? + user_profile: userProfile, + guild_member: guild_id && guildMemberDto, + guild_member_profile: guild_id && guildMemberProfile, + }); + }, +); + +router.patch( + "/", + route({ body: "UserProfileModifySchema" }), + async (req: Request, res: Response) => { + const body = req.body as UserProfileModifySchema; + + if (body.banner) + body.banner = await handleFile( + `/banners/${req.user_id}`, + body.banner as string, + ); + let user = await User.findOneOrFail({ + where: { id: req.user_id }, + select: [...PrivateUserProjection, "data"], + }); + + user.assign(body); + await user.save(); + + // @ts-ignore + delete user.data; + + // TODO: send update member list event in gateway + await emitEvent({ + event: "USER_UPDATE", + user_id: req.user_id, + data: user, + } as UserUpdateEvent); + + res.json({ + accent_color: user.accent_color, + bio: user.bio, + banner: user.banner, + theme_colors: user.theme_colors, + pronouns: user.pronouns, + }); + }, +); export default router; diff --git a/src/api/routes/users/@me/guilds/#guild_id/settings.ts b/src/api/routes/users/@me/guilds/#guild_id/settings.ts index 4538785c..436261d4 100644 --- a/src/api/routes/users/@me/guilds/#guild_id/settings.ts +++ b/src/api/routes/users/@me/guilds/#guild_id/settings.ts @@ -32,8 +32,7 @@ router.patch( const user = await Member.findOneOrFail({ where: { id: req.user_id, guild_id: req.params.guild_id }, - select: ["settings"] - + select: ["settings"], }); OrmUtils.mergeDeep(user.settings || {}, body); Member.update({ id: req.user_id, guild_id: req.params.guild_id }, user); diff --git a/src/api/routes/users/@me/index.ts b/src/api/routes/users/@me/index.ts index 3ac48f27..37356d9d 100644 --- a/src/api/routes/users/@me/index.ts +++ b/src/api/routes/users/@me/index.ts @@ -98,7 +98,7 @@ router.patch( } user.data.hash = await bcrypt.hash(body.new_password, 12); user.data.valid_tokens_since = new Date(); - newToken = await generateToken(user.id) as string; + newToken = (await generateToken(user.id)) as string; } if (body.username) { diff --git a/src/api/routes/users/@me/settings.ts b/src/api/routes/users/@me/settings.ts index 0fd8220a..cce366ac 100644 --- a/src/api/routes/users/@me/settings.ts +++ b/src/api/routes/users/@me/settings.ts @@ -21,7 +21,7 @@ router.patch( const user = await User.findOneOrFail({ where: { id: req.user_id, bot: false }, - relations: ["settings"] + relations: ["settings"], }); user.settings.assign(body); diff --git a/src/api/util/handlers/Message.ts b/src/api/util/handlers/Message.ts index 37269185..93dc3bf4 100644 --- a/src/api/util/handlers/Message.ts +++ b/src/api/util/handlers/Message.ts @@ -53,7 +53,7 @@ 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, }); @@ -180,7 +180,7 @@ export async function handleMessage(opts: MessageOptions): Promise<Message> { // TODO: cache link result in db export async function postHandleMessage(message: Message) { - const content = message.content?.replace(/ *\`[^)]*\` */g, ""); // remove markdown + const content = message.content?.replace(/ *\`[^)]*\` */g, ""); // remove markdown var links = content?.match(LINK_REGEX); if (!links) return; @@ -201,8 +201,12 @@ export async function postHandleMessage(message: Message) { } // bit gross, but whatever! - const endpointPublic = Config.get().cdn.endpointPublic || "http://127.0.0.1"; // lol - const handler = url.hostname == new URL(endpointPublic).hostname ? EmbedHandlers["self"] : EmbedHandlers[url.hostname] || EmbedHandlers["default"]; + const endpointPublic = + Config.get().cdn.endpointPublic || "http://127.0.0.1"; // lol + const handler = + url.hostname == new URL(endpointPublic).hostname + ? EmbedHandlers["self"] + : EmbedHandlers[url.hostname] || EmbedHandlers["default"]; try { let res = await handler(url); @@ -218,11 +222,10 @@ export async function postHandleMessage(message: Message) { cachePromises.push(cache.save()); data.embeds.push(embed); } - } - catch (e) { - Sentry.captureException(e, scope => { + } catch (e) { + Sentry.captureException(e, (scope) => { scope.clear(); - scope.setContext("request", { url }) + scope.setContext("request", { url }); return scope; }); continue; @@ -257,7 +260,7 @@ export async function sendMessage(opts: MessageOptions) { } 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/index.ts b/src/api/util/index.ts index ffad0607..5921f011 100644 --- a/src/api/util/index.ts +++ b/src/api/util/index.ts @@ -7,4 +7,4 @@ export * from "./handlers/route"; export * from "./utility/String"; export * from "./handlers/Voice"; export * from "./utility/captcha"; -export * from "./utility/EmbedHandlers"; \ No newline at end of file +export * from "./utility/EmbedHandlers"; diff --git a/src/api/util/utility/EmbedHandlers.ts b/src/api/util/utility/EmbedHandlers.ts index dca264d0..2549937e 100644 --- a/src/api/util/utility/EmbedHandlers.ts +++ b/src/api/util/utility/EmbedHandlers.ts @@ -16,8 +16,13 @@ export const DEFAULT_FETCH_OPTIONS: any = { method: "GET", }; -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); @@ -26,16 +31,20 @@ export const getProxyUrl = (url: URL, width: number, height: number): string => if (imagorServerUrl) { let path = `${width}x${height}/${url.host}${url.pathname}`; - const hash = crypto.createHmac('sha1', secret) + const hash = crypto + .createHmac("sha1", secret) .update(path) - .digest('base64') - .replace(/\+/g, '-').replace(/\//g, '_'); + .digest("base64") + .replace(/\+/g, "-") + .replace(/\//g, "_"); return `${imagorServerUrl}/${hash}/${path}`; } // TODO: Imagor documentation - console.log("Imagor has not been set up correctly. docs.fosscord.com/set/up/a/page/about/this"); + console.log( + "Imagor has not been set up correctly. docs.fosscord.com/set/up/a/page/about/this", + ); return ""; }; @@ -69,8 +78,7 @@ const doFetch = async (url: URL) => { ...DEFAULT_FETCH_OPTIONS, size: Config.get().limits.message.maxEmbedDownloadSize, }); - } - catch (e) { + } catch (e) { return null; } }; @@ -88,12 +96,10 @@ const genericImageHandler = async (url: URL): Promise<Embed | null> => { width = result.width; height = result.height; image = url.href; - } - else if (type.headers.get("content-type")?.indexOf("video") !== -1) { + } else if (type.headers.get("content-type")?.indexOf("video") !== -1) { // TODO return null; - } - else { + } else { // have to download the page, unfortunately const response = await doFetch(url); if (!response) return null; @@ -113,13 +119,15 @@ const genericImageHandler = async (url: URL): Promise<Embed | null> => { height: height, url: url.href, proxy_url: getProxyUrl(new URL(image), width, height), - } + }, }; }; -export const EmbedHandlers: { [key: string]: (url: URL) => Promise<Embed | Embed[] | null>; } = { +export const EmbedHandlers: { + [key: string]: (url: URL) => Promise<Embed | Embed[] | null>; +} = { // the url does not have a special handler - "default": async (url: URL) => { + default: async (url: URL) => { const type = await fetch(url, { ...DEFAULT_FETCH_OPTIONS, method: "HEAD", @@ -154,7 +162,13 @@ export const EmbedHandlers: { [key: string]: (url: URL) => Promise<Embed | Embed width: metas.width, height: metas.height, url: metas.image, - proxy_url: metas.image ? getProxyUrl(new URL(metas.image), metas.width!, metas.height!) : undefined, + proxy_url: metas.image + ? getProxyUrl( + new URL(metas.image), + metas.width!, + metas.height!, + ) + : undefined, }, description: metas.description, }; @@ -169,26 +183,28 @@ export const EmbedHandlers: { [key: string]: (url: URL) => Promise<Embed | Embed // TODO: facebook // have to use their APIs or something because they don't send the metas in initial html - "twitter.com": (url: URL) => { return EmbedHandlers["www.twitter.com"](url); }, + "twitter.com": (url: URL) => { + return EmbedHandlers["www.twitter.com"](url); + }, "www.twitter.com": async (url: URL) => { const token = Config.get().external.twitter; if (!token) return null; - if (!url.href.includes("/status/")) return null; // TODO; - const id = url.pathname.split("/")[3]; // super bad lol + if (!url.href.includes("/status/")) return null; // TODO; + const id = url.pathname.split("/")[3]; // super bad lol if (!parseInt(id)) return null; - const endpointUrl = `https://api.twitter.com/2/tweets/${id}` + + const endpointUrl = + `https://api.twitter.com/2/tweets/${id}` + `?expansions=author_id,attachments.media_keys` + - `&media.fields=url,width,height` + - `&tweet.fields=created_at,public_metrics` + - `&user.fields=profile_image_url`; - + `&media.fields=url,width,height` + + `&tweet.fields=created_at,public_metrics` + + `&user.fields=profile_image_url`; const response = await fetch(endpointUrl, { ...DEFAULT_FETCH_OPTIONS, headers: { authorization: `Bearer ${token}`, - } + }, }); const json = await response.json(); if (json.errors) return null; @@ -196,7 +212,9 @@ export const EmbedHandlers: { [key: string]: (url: URL) => Promise<Embed | Embed const text = json.data.text; const created_at = new Date(json.data.created_at); const metrics = json.data.public_metrics; - let media = json.includes.media?.filter((x: any) => x.type == "photo") as any[]; // TODO: video + let media = json.includes.media?.filter( + (x: any) => x.type == "photo", + ) as any[]; // TODO: video const embed: Embed = { type: EmbedType.rich, @@ -205,19 +223,38 @@ export const EmbedHandlers: { [key: string]: (url: URL) => Promise<Embed | Embed 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, fields: [ - { inline: true, name: "Likes", value: metrics.like_count.toString() }, - { inline: true, name: "Retweet", value: metrics.retweet_count.toString() }, + { + inline: true, + name: "Likes", + value: metrics.like_count.toString(), + }, + { + inline: true, + name: "Retweet", + value: metrics.retweet_count.toString(), + }, ], 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: { @@ -231,7 +268,11 @@ export const EmbedHandlers: { [key: string]: (url: URL) => Promise<Embed | Embed 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(); } @@ -265,17 +306,21 @@ export const EmbedHandlers: { [key: string]: (url: URL) => Promise<Embed | Embed thumbnail: { width: 640, height: 640, - proxy_url: metas.image ? getProxyUrl(new URL(metas.image!), 640, 640) : undefined, + proxy_url: metas.image + ? getProxyUrl(new URL(metas.image!), 640, 640) + : undefined, url: metas.image, }, provider: { url: "https://spotify.com", name: "Spotify", - } + }, }; }, - "pixiv.net": (url: URL) => { return EmbedHandlers["www.pixiv.net"](url); }, + "pixiv.net": (url: URL) => { + return EmbedHandlers["www.pixiv.net"](url); + }, "www.pixiv.net": async (url: URL) => { const response = await doFetch(url); if (!response) return null; @@ -291,12 +336,18 @@ export const EmbedHandlers: { [key: string]: (url: URL) => Promise<Embed | Embed width: metas.width, height: metas.height, url: url.href, - proxy_url: metas.image ? getProxyUrl(new URL(metas.image!), metas.width!, metas.height!) : undefined, + proxy_url: metas.image + ? getProxyUrl( + new URL(metas.image!), + metas.width!, + metas.height!, + ) + : undefined, }, provider: { url: "https://pixiv.net", - name: "Pixiv" - } + name: "Pixiv", + }, }; }, @@ -310,35 +361,42 @@ export const EmbedHandlers: { [key: string]: (url: URL) => Promise<Embed | Embed type: EmbedType.rich, title: metas.title, description: metas.description, - image: { // TODO: meant to be thumbnail. + image: { + // TODO: meant to be thumbnail. // isn't this standard across all of steam? 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", - name: "Steam" + name: "Steam", }, // TODO: fields for release date // TODO: Video }; }, - "reddit.com": (url: URL) => { return EmbedHandlers["www.reddit.com"](url); }, + "reddit.com": (url: URL) => { + return EmbedHandlers["www.reddit.com"](url); + }, "www.reddit.com": async (url: URL) => { const res = await EmbedHandlers["default"](url); return { ...res, color: 16777215, provider: { - name: "reddit" - } + name: "reddit", + }, }; }, - "youtube.com": (url: URL) => { return EmbedHandlers["www.youtube.com"](url); }, + "youtube.com": (url: URL) => { + return EmbedHandlers["www.youtube.com"](url); + }, "www.youtube.com": async (url: URL): Promise<Embed | null> => { const response = await doFetch(url); if (!response) return null; @@ -358,7 +416,13 @@ export const EmbedHandlers: { [key: string]: (url: URL) => Promise<Embed | Embed width: metas.width, height: metas.height, url: metas.image, - proxy_url: metas.image ? getProxyUrl(new URL(metas.image!), metas.width!, metas.height!) : undefined, + proxy_url: metas.image + ? getProxyUrl( + new URL(metas.image!), + metas.width!, + metas.height!, + ) + : undefined, }, provider: { url: "https://www.youtube.com", @@ -369,12 +433,12 @@ export const EmbedHandlers: { [key: string]: (url: URL) => Promise<Embed | Embed author: { name: metas.author, // TODO: author channel url - } + }, }; }, // the url is an image from this instance - "self": async (url: URL): Promise<Embed | null> => { + self: async (url: URL): Promise<Embed | null> => { const result = await probe(url.href); return { @@ -385,7 +449,7 @@ export const EmbedHandlers: { [key: string]: (url: URL) => Promise<Embed | Embed height: result.height, url: url.href, proxy_url: url.href, - } + }, }; }, -};; \ No newline at end of file +}; diff --git a/src/bundle/Server.ts b/src/bundle/Server.ts index 3ceebc06..e6f8d17c 100644 --- a/src/bundle/Server.ts +++ b/src/bundle/Server.ts @@ -75,8 +75,14 @@ async function main() { // Filter breadcrumbs that we don't care about if (x.message?.includes("identified as")) return false; if (x.message?.includes("[WebSocket] closed")) return false; - if (x.message?.includes("Got Resume -> cancel not implemented")) return false; - if (x.message?.includes("[Gateway] New connection from")) return false; + if ( + x.message?.includes( + "Got Resume -> cancel not implemented", + ) + ) + return false; + if (x.message?.includes("[Gateway] New connection from")) + return false; return true; }); diff --git a/src/cdn/Server.ts b/src/cdn/Server.ts index 1fd9ca38..7340a735 100644 --- a/src/cdn/Server.ts +++ b/src/cdn/Server.ts @@ -56,7 +56,7 @@ export class CDNServer extends Server { this.app.use("/splashes/", avatarsRoute); this.log("verbose", "[Server] Route /splashes registered"); - + this.app.use("/discovery-splashes/", avatarsRoute); this.log("verbose", "[Server] Route /discovery-splashes registered"); @@ -75,10 +75,16 @@ export class CDNServer extends Server { this.app.use("/channel-icons/", avatarsRoute); this.log("verbose", "[Server] Route /channel-icons registered"); - this.app.use("/guilds/:guild_id/users/:user_id/avatars", guildProfilesRoute); + this.app.use( + "/guilds/:guild_id/users/:user_id/avatars", + guildProfilesRoute, + ); this.log("verbose", "[Server] Route /guilds/avatars registered"); - this.app.use("/guilds/:guild_id/users/:user_id/banners", guildProfilesRoute); + this.app.use( + "/guilds/:guild_id/users/:user_id/banners", + guildProfilesRoute, + ); this.log("verbose", "[Server] Route /guilds/banners registered"); return super.start(); diff --git a/src/cdn/routes/guild-profiles.ts b/src/cdn/routes/guild-profiles.ts index 98af7f69..2acc4ab7 100644 --- a/src/cdn/routes/guild-profiles.ts +++ b/src/cdn/routes/guild-profiles.ts @@ -12,21 +12,32 @@ import { storage } from "../util/Storage"; // 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(); 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, mimetype, size, originalname, fieldname } = 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 FileType.fromBuffer(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}`; @@ -38,7 +49,7 @@ router.post("/", multer.single("file"), async (req: Request, res: Response) => { id: hash, content_type: type.mime, size, - url: `${endpoint}${req.baseUrl}/${user_id}/${hash}` + url: `${endpoint}${req.baseUrl}/${user_id}/${hash}`, }); }); @@ -73,7 +84,8 @@ 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/util/FileStorage.ts b/src/cdn/util/FileStorage.ts index 9386663f..e8d499e2 100644 --- a/src/cdn/util/FileStorage.ts +++ b/src/cdn/util/FileStorage.ts @@ -35,7 +35,8 @@ export class FileStorage implements Storage { async set(path: string, value: any) { path = getPath(path); - if (!fs.existsSync(dirname(path))) fs.mkdirSync(dirname(path), { recursive: true }); + if (!fs.existsSync(dirname(path))) + fs.mkdirSync(dirname(path), { recursive: true }); value = Readable.from(value); const cleaned_file = fs.createWriteStream(path); diff --git a/src/gateway/events/Connection.ts b/src/gateway/events/Connection.ts index d47ac314..f3694c51 100644 --- a/src/gateway/events/Connection.ts +++ b/src/gateway/events/Connection.ts @@ -12,7 +12,7 @@ import { Config } from "@fosscord/util"; var erlpack: any; try { erlpack = require("@yukikaze-bot/erlpack"); -} catch (error) { } +} catch (error) {} // TODO: check rate limit // TODO: specify rate limit in config @@ -48,7 +48,7 @@ export async function Connection( "open", "ping", "pong", - "unexpected-response" + "unexpected-response", ].forEach((x) => { socket.on(x, (y) => console.log(x, y)); }); diff --git a/src/gateway/events/Message.ts b/src/gateway/events/Message.ts index 57af0c69..6645dd22 100644 --- a/src/gateway/events/Message.ts +++ b/src/gateway/events/Message.ts @@ -10,30 +10,36 @@ const bigIntJson = BigIntJson({ storeAsString: true }); var erlpack: any; try { erlpack = require("@yukikaze-bot/erlpack"); -} catch (error) { } +} catch (error) {} export async function Message(this: WebSocket, buffer: WS.Data) { // TODO: compression var data: Payload; - if ((buffer instanceof Buffer && buffer[0] === 123) || // ASCII 123 = `{`. Bad check for JSON - (typeof buffer === "string")) { + if ( + (buffer instanceof Buffer && buffer[0] === 123) || // ASCII 123 = `{`. Bad check for JSON + typeof buffer === "string" + ) { data = bigIntJson.parse(buffer.toString()); - } - else if (this.encoding === "json" && buffer instanceof Buffer) { + } else if (this.encoding === "json" && buffer instanceof Buffer) { if (this.inflate) { - try { buffer = this.inflate.process(buffer) as any; } - catch { buffer = buffer.toString() as any; } + try { + buffer = this.inflate.process(buffer) as any; + } catch { + buffer = buffer.toString() as any; + } } data = bigIntJson.parse(buffer as string); - } - else if (this.encoding === "etf" && buffer instanceof Buffer) { - try { data = erlpack.unpack(buffer); } - catch { return this.close(CLOSECODES.Decode_error); } - } - else return this.close(CLOSECODES.Decode_error); + } else if (this.encoding === "etf" && buffer instanceof Buffer) { + try { + data = erlpack.unpack(buffer); + } catch { + return this.close(CLOSECODES.Decode_error); + } + } else return this.close(CLOSECODES.Decode_error); - if (process.env.WS_VERBOSE) console.log(`[Websocket] Incomming message: ${JSON.stringify(data)}`); + if (process.env.WS_VERBOSE) + console.log(`[Websocket] Incomming message: ${JSON.stringify(data)}`); check.call(this, PayloadSchema, data); @@ -46,14 +52,17 @@ export async function Message(this: WebSocket, buffer: WS.Data) { return; } - const transaction = data.op != 1 ? Sentry.startTransaction({ - op: OPCODES[data.op], - name: `GATEWAY ${OPCODES[data.op]}`, - data: { - ...data.d, - token: data?.d?.token ? "[Redacted]" : undefined, - }, - }) : undefined; + const transaction = + data.op != 1 + ? Sentry.startTransaction({ + op: OPCODES[data.op], + name: `GATEWAY ${OPCODES[data.op]}`, + data: { + ...data.d, + token: data?.d?.token ? "[Redacted]" : undefined, + }, + }) + : undefined; try { var ret = await OPCodeHandler.call(this, data); diff --git a/src/gateway/opcodes/Identify.ts b/src/gateway/opcodes/Identify.ts index ca3ae66f..d1daff04 100644 --- a/src/gateway/opcodes/Identify.ts +++ b/src/gateway/opcodes/Identify.ts @@ -259,7 +259,10 @@ export async function onIdentify(this: WebSocket, data: Payload) { const d: ReadyEventData = { v: 9, - application: { id: application?.id ?? '', flags: application?.flags ?? 0 }, //TODO: check this code! + application: { + id: application?.id ?? "", + flags: application?.flags ?? 0, + }, //TODO: check this code! user: privateUser, user_settings: user.settings, // @ts-ignore @@ -267,7 +270,7 @@ export async function onIdentify(this: WebSocket, data: Payload) { return { ...new ReadyGuildDTO(x as Guild & { joined_at: Date }).toJSON(), guild_hashes: {}, - joined_at: x.joined_at + joined_at: x.joined_at, }; }), guild_experiments: [], // TODO diff --git a/src/gateway/opcodes/LazyRequest.ts b/src/gateway/opcodes/LazyRequest.ts index e54f64a6..f5bee864 100644 --- a/src/gateway/opcodes/LazyRequest.ts +++ b/src/gateway/opcodes/LazyRequest.ts @@ -159,7 +159,11 @@ async function getMembers(guild_id: string, range: [number, number]) { groups, range, members: items - .map((x) => ("member" in x ? { ...x.member, settings: undefined } : undefined)) + .map((x) => + "member" in x + ? { ...x.member, settings: undefined } + : undefined, + ) .filter((x) => !!x), }; } diff --git a/src/gateway/opcodes/VoiceStateUpdate.ts b/src/gateway/opcodes/VoiceStateUpdate.ts index 49d15425..99160f0d 100644 --- a/src/gateway/opcodes/VoiceStateUpdate.ts +++ b/src/gateway/opcodes/VoiceStateUpdate.ts @@ -62,7 +62,7 @@ export async function onVoiceStateUpdate(this: WebSocket, data: Payload) { } // 'Fix' for this one voice state error. TODO: Find out why this is sent - // It seems to be sent on client load, + // It seems to be sent on client load, // so maybe its trying to find which server you were connected to before disconnecting, if any? if (body.guild_id == null) { return; diff --git a/src/util/config/Config.ts b/src/util/config/Config.ts index b6c725f5..8a057a44 100644 --- a/src/util/config/Config.ts +++ b/src/util/config/Config.ts @@ -17,7 +17,7 @@ import { RegisterConfiguration, SecurityConfiguration, SentryConfiguration, - TemplateConfiguration + TemplateConfiguration, } from "../config"; export class ConfigValue { @@ -40,4 +40,4 @@ export class ConfigValue { sentry: SentryConfiguration = new SentryConfiguration(); defaults: DefaultsConfiguration = new DefaultsConfiguration(); external: ExternalTokensConfiguration = new ExternalTokensConfiguration(); -} \ No newline at end of file +} diff --git a/src/util/config/types/ApiConfiguration.ts b/src/util/config/types/ApiConfiguration.ts index 16b1efba..442a5986 100644 --- a/src/util/config/types/ApiConfiguration.ts +++ b/src/util/config/types/ApiConfiguration.ts @@ -2,4 +2,4 @@ export class ApiConfiguration { defaultVersion: string = "9"; activeVersions: string[] = ["6", "7", "8", "9"]; useFosscordEnhancements: boolean = true; -} \ No newline at end of file +} diff --git a/src/util/config/types/CdnConfiguration.ts b/src/util/config/types/CdnConfiguration.ts index 3c4dd163..ef8a003b 100644 --- a/src/util/config/types/CdnConfiguration.ts +++ b/src/util/config/types/CdnConfiguration.ts @@ -7,4 +7,4 @@ export class CdnConfiguration extends EndpointConfiguration { endpointPublic: string | null = "http://localhost:3001"; endpointPrivate: string | null = "http://localhost:3001"; -} \ No newline at end of file +} diff --git a/src/util/config/types/ClientConfiguration.ts b/src/util/config/types/ClientConfiguration.ts index 0d3c8490..c2d4172c 100644 --- a/src/util/config/types/ClientConfiguration.ts +++ b/src/util/config/types/ClientConfiguration.ts @@ -1,6 +1,6 @@ import { ClientReleaseConfiguration } from "."; export class ClientConfiguration { - releases: ClientReleaseConfiguration = new ClientReleaseConfiguration(); - useTestClient: boolean = false; -} \ No newline at end of file + releases: ClientReleaseConfiguration = new ClientReleaseConfiguration(); + useTestClient: boolean = false; +} diff --git a/src/util/config/types/DefaultsConfiguration.ts b/src/util/config/types/DefaultsConfiguration.ts index 9b02a590..d5ee39e7 100644 --- a/src/util/config/types/DefaultsConfiguration.ts +++ b/src/util/config/types/DefaultsConfiguration.ts @@ -1,6 +1,6 @@ import { GuildDefaults, UserDefaults } from "."; export class DefaultsConfiguration { - guild: GuildDefaults = new GuildDefaults(); - user: UserDefaults = new UserDefaults(); -} \ No newline at end of file + guild: GuildDefaults = new GuildDefaults(); + user: UserDefaults = new UserDefaults(); +} diff --git a/src/util/config/types/EndpointConfiguration.ts b/src/util/config/types/EndpointConfiguration.ts index 87baea31..5e5e8ca9 100644 --- a/src/util/config/types/EndpointConfiguration.ts +++ b/src/util/config/types/EndpointConfiguration.ts @@ -2,4 +2,4 @@ export class EndpointConfiguration { endpointClient: string | null = null; endpointPrivate: string | null = null; endpointPublic: string | null = null; -} \ No newline at end of file +} diff --git a/src/util/config/types/ExternalTokensConfiguration.ts b/src/util/config/types/ExternalTokensConfiguration.ts index 5c020745..22c8b862 100644 --- a/src/util/config/types/ExternalTokensConfiguration.ts +++ b/src/util/config/types/ExternalTokensConfiguration.ts @@ -1,3 +1,3 @@ export class ExternalTokensConfiguration { twitter: string | null = null; -} \ No newline at end of file +} diff --git a/src/util/config/types/GeneralConfiguration.ts b/src/util/config/types/GeneralConfiguration.ts index 7c0ffa66..462f93e2 100644 --- a/src/util/config/types/GeneralConfiguration.ts +++ b/src/util/config/types/GeneralConfiguration.ts @@ -2,11 +2,12 @@ import { Snowflake } from "@fosscord/util"; export class GeneralConfiguration { instanceName: string = "Fosscord Instance"; - instanceDescription: string | null = "This is a Fosscord instance made in the pre-release days"; + instanceDescription: string | null = + "This is a Fosscord instance made in the pre-release days"; frontPage: string | null = null; tosPage: string | null = null; correspondenceEmail: string | null = null; correspondenceUserID: string | null = null; image: string | null = null; instanceId: string = Snowflake.generate(); -} \ No newline at end of file +} diff --git a/src/util/config/types/GifConfiguration.ts b/src/util/config/types/GifConfiguration.ts index 6a2d520d..565c2ac0 100644 --- a/src/util/config/types/GifConfiguration.ts +++ b/src/util/config/types/GifConfiguration.ts @@ -1,5 +1,5 @@ export class GifConfiguration { - enabled: boolean = true; - provider: "tenor" = "tenor"; // more coming soon - apiKey?: string = "LIVDSRZULELA"; -} \ No newline at end of file + enabled: boolean = true; + provider: "tenor" = "tenor"; // more coming soon + apiKey?: string = "LIVDSRZULELA"; +} diff --git a/src/util/config/types/GuildConfiguration.ts b/src/util/config/types/GuildConfiguration.ts index e77d3fce..42ce2044 100644 --- a/src/util/config/types/GuildConfiguration.ts +++ b/src/util/config/types/GuildConfiguration.ts @@ -1,7 +1,7 @@ import { DiscoveryConfiguration, AutoJoinConfiguration } from "."; export class GuildConfiguration { - discovery: DiscoveryConfiguration = new DiscoveryConfiguration(); - autoJoin: AutoJoinConfiguration = new AutoJoinConfiguration(); + discovery: DiscoveryConfiguration = new DiscoveryConfiguration(); + autoJoin: AutoJoinConfiguration = new AutoJoinConfiguration(); defaultFeatures: string[] = []; } diff --git a/src/util/config/types/KafkaConfiguration.ts b/src/util/config/types/KafkaConfiguration.ts index 7932f49e..a3aa8058 100644 --- a/src/util/config/types/KafkaConfiguration.ts +++ b/src/util/config/types/KafkaConfiguration.ts @@ -1,5 +1,5 @@ import { KafkaBroker } from "."; export class KafkaConfiguration { - brokers: KafkaBroker[] | null = null; -} \ No newline at end of file + brokers: KafkaBroker[] | null = null; +} diff --git a/src/util/config/types/LimitConfigurations.ts b/src/util/config/types/LimitConfigurations.ts index 105fd1d6..912d6a4b 100644 --- a/src/util/config/types/LimitConfigurations.ts +++ b/src/util/config/types/LimitConfigurations.ts @@ -1,4 +1,11 @@ -import { ChannelLimits, GlobalRateLimits, GuildLimits, MessageLimits, RateLimits, UserLimits } from "."; +import { + ChannelLimits, + GlobalRateLimits, + GuildLimits, + MessageLimits, + RateLimits, + UserLimits, +} from "."; export class LimitsConfiguration { user: UserLimits = new UserLimits(); diff --git a/src/util/config/types/LoginConfiguration.ts b/src/util/config/types/LoginConfiguration.ts index 255c9451..d8b737b9 100644 --- a/src/util/config/types/LoginConfiguration.ts +++ b/src/util/config/types/LoginConfiguration.ts @@ -1,3 +1,3 @@ export class LoginConfiguration { - requireCaptcha: boolean = false; -} \ No newline at end of file + requireCaptcha: boolean = false; +} diff --git a/src/util/config/types/MetricsConfiguration.ts b/src/util/config/types/MetricsConfiguration.ts index d7cd4937..f6b1d8e6 100644 --- a/src/util/config/types/MetricsConfiguration.ts +++ b/src/util/config/types/MetricsConfiguration.ts @@ -1,3 +1,3 @@ export class MetricsConfiguration { - timeout: number = 30000; -} \ No newline at end of file + timeout: number = 30000; +} diff --git a/src/util/config/types/RabbitMQConfiguration.ts b/src/util/config/types/RabbitMQConfiguration.ts index ce4a9123..bd4b6ca3 100644 --- a/src/util/config/types/RabbitMQConfiguration.ts +++ b/src/util/config/types/RabbitMQConfiguration.ts @@ -1,3 +1,3 @@ export class RabbitMQConfiguration { - host: string | null = null; -} \ No newline at end of file + host: string | null = null; +} diff --git a/src/util/config/types/RegionConfiguration.ts b/src/util/config/types/RegionConfiguration.ts index 09d9271c..ce4bf242 100644 --- a/src/util/config/types/RegionConfiguration.ts +++ b/src/util/config/types/RegionConfiguration.ts @@ -1,16 +1,16 @@ import { Region } from "."; export class RegionConfiguration { - default: string = "fosscord"; - useDefaultAsOptimal: boolean = true; - available: Region[] = [ - { - id: "fosscord", - name: "Fosscord", - endpoint: "127.0.0.1:3004", - vip: false, - custom: false, - deprecated: false, - }, - ]; -} \ No newline at end of file + default: string = "fosscord"; + useDefaultAsOptimal: boolean = true; + available: Region[] = [ + { + id: "fosscord", + name: "Fosscord", + endpoint: "127.0.0.1:3004", + vip: false, + custom: false, + deprecated: false, + }, + ]; +} diff --git a/src/util/config/types/RegisterConfiguration.ts b/src/util/config/types/RegisterConfiguration.ts index 75b40417..b9096e66 100644 --- a/src/util/config/types/RegisterConfiguration.ts +++ b/src/util/config/types/RegisterConfiguration.ts @@ -1,16 +1,20 @@ -import { DateOfBirthConfiguration, EmailConfiguration, PasswordConfiguration } from "."; +import { + DateOfBirthConfiguration, + EmailConfiguration, + PasswordConfiguration, +} from "."; export class RegisterConfiguration { - email: EmailConfiguration = new EmailConfiguration(); - dateOfBirth: DateOfBirthConfiguration = new DateOfBirthConfiguration(); - password: PasswordConfiguration = new PasswordConfiguration(); - disabled: boolean = false; - requireCaptcha: boolean = true; - requireInvite: boolean = false; - guestsRequireInvite: boolean = true; - allowNewRegistration: boolean = true; - allowMultipleAccounts: boolean = true; - blockProxies: boolean = true; - incrementingDiscriminators: boolean = false; // random otherwise - defaultRights: string = "30644591655940"; // See `npm run generate:rights` + email: EmailConfiguration = new EmailConfiguration(); + dateOfBirth: DateOfBirthConfiguration = new DateOfBirthConfiguration(); + password: PasswordConfiguration = new PasswordConfiguration(); + disabled: boolean = false; + requireCaptcha: boolean = true; + requireInvite: boolean = false; + guestsRequireInvite: boolean = true; + allowNewRegistration: boolean = true; + allowMultipleAccounts: boolean = true; + blockProxies: boolean = true; + incrementingDiscriminators: boolean = false; // random otherwise + defaultRights: string = "30644591655940"; // See `npm run generate:rights` } diff --git a/src/util/config/types/SecurityConfiguration.ts b/src/util/config/types/SecurityConfiguration.ts index 0fa396c9..6d505140 100644 --- a/src/util/config/types/SecurityConfiguration.ts +++ b/src/util/config/types/SecurityConfiguration.ts @@ -11,7 +11,8 @@ export class SecurityConfiguration { // X-Forwarded-For for nginx/reverse proxies // CF-Connecting-IP for cloudflare forwadedFor: string | null = null; - ipdataApiKey: string | null = "eca677b284b3bac29eb72f5e496aa9047f26543605efe99ff2ce35c9"; + ipdataApiKey: string | null = + "eca677b284b3bac29eb72f5e496aa9047f26543605efe99ff2ce35c9"; mfaBackupCodeCount: number = 10; statsWorldReadable: boolean = true; defaultRegistrationTokenExpiration: number = 1000 * 60 * 60 * 24 * 7; //1 week diff --git a/src/util/config/types/SentryConfiguration.ts b/src/util/config/types/SentryConfiguration.ts index 836094a1..57f548cd 100644 --- a/src/util/config/types/SentryConfiguration.ts +++ b/src/util/config/types/SentryConfiguration.ts @@ -1,8 +1,9 @@ import { hostname } from "os"; export class SentryConfiguration { - enabled: boolean = false; - endpoint: string = "https://05e8e3d005f34b7d97e920ae5870a5e5@sentry.thearcanebrony.net/6"; - traceSampleRate: number = 1.0; - environment: string = hostname(); -} \ No newline at end of file + enabled: boolean = false; + endpoint: string = + "https://05e8e3d005f34b7d97e920ae5870a5e5@sentry.thearcanebrony.net/6"; + traceSampleRate: number = 1.0; + environment: string = hostname(); +} diff --git a/src/util/config/types/TemplateConfiguration.ts b/src/util/config/types/TemplateConfiguration.ts index 4a9aa8f2..aade2934 100644 --- a/src/util/config/types/TemplateConfiguration.ts +++ b/src/util/config/types/TemplateConfiguration.ts @@ -1,6 +1,6 @@ export class TemplateConfiguration { - enabled: boolean = true; - allowTemplateCreation: boolean = true; - allowDiscordTemplates: boolean = true; - allowRaws: boolean = true; -} \ No newline at end of file + enabled: boolean = true; + allowTemplateCreation: boolean = true; + allowDiscordTemplates: boolean = true; + allowRaws: boolean = true; +} diff --git a/src/util/config/types/index.ts b/src/util/config/types/index.ts index f20fe121..d7251d97 100644 --- a/src/util/config/types/index.ts +++ b/src/util/config/types/index.ts @@ -17,4 +17,4 @@ export * from "./RegisterConfiguration"; export * from "./SecurityConfiguration"; export * from "./SentryConfiguration"; export * from "./TemplateConfiguration"; -export * from "./subconfigurations"; \ No newline at end of file +export * from "./subconfigurations"; diff --git a/src/util/config/types/subconfigurations/client/ClientReleaseConfiguration.ts b/src/util/config/types/subconfigurations/client/ClientReleaseConfiguration.ts index 54e7f365..b082b711 100644 --- a/src/util/config/types/subconfigurations/client/ClientReleaseConfiguration.ts +++ b/src/util/config/types/subconfigurations/client/ClientReleaseConfiguration.ts @@ -1,4 +1,4 @@ export class ClientReleaseConfiguration { - useLocalRelease: boolean = true; //TODO - upstreamVersion: string = "0.0.264"; -} \ No newline at end of file + useLocalRelease: boolean = true; //TODO + upstreamVersion: string = "0.0.264"; +} diff --git a/src/util/config/types/subconfigurations/defaults/GuildDefaults.ts b/src/util/config/types/subconfigurations/defaults/GuildDefaults.ts index 27e8eae7..576cc3bc 100644 --- a/src/util/config/types/subconfigurations/defaults/GuildDefaults.ts +++ b/src/util/config/types/subconfigurations/defaults/GuildDefaults.ts @@ -1,7 +1,7 @@ export class GuildDefaults { - maxPresences: number = 250000; - maxVideoChannelUsers: number = 200; - afkTimeout: number = 300; - defaultMessageNotifications: number = 1; - explicitContentFilter: number = 0; -} \ No newline at end of file + maxPresences: number = 250000; + maxVideoChannelUsers: number = 200; + afkTimeout: number = 300; + defaultMessageNotifications: number = 1; + explicitContentFilter: number = 0; +} diff --git a/src/util/config/types/subconfigurations/defaults/UserDefaults.ts b/src/util/config/types/subconfigurations/defaults/UserDefaults.ts index f20a14b6..2c2f0043 100644 --- a/src/util/config/types/subconfigurations/defaults/UserDefaults.ts +++ b/src/util/config/types/subconfigurations/defaults/UserDefaults.ts @@ -1,5 +1,5 @@ export class UserDefaults { - premium: boolean = true; - premiumType: number = 2; - verified: boolean = true; -} \ No newline at end of file + premium: boolean = true; + premiumType: number = 2; + verified: boolean = true; +} diff --git a/src/util/config/types/subconfigurations/guild/AutoJoin.ts b/src/util/config/types/subconfigurations/guild/AutoJoin.ts index 47dfe5ec..4d7af352 100644 --- a/src/util/config/types/subconfigurations/guild/AutoJoin.ts +++ b/src/util/config/types/subconfigurations/guild/AutoJoin.ts @@ -1,5 +1,5 @@ export class AutoJoinConfiguration { - enabled: boolean = true; - guilds: string[] = []; - canLeave: boolean = true; -} \ No newline at end of file + enabled: boolean = true; + guilds: string[] = []; + canLeave: boolean = true; +} diff --git a/src/util/config/types/subconfigurations/guild/Discovery.ts b/src/util/config/types/subconfigurations/guild/Discovery.ts index 59d8a8ae..a7cb81db 100644 --- a/src/util/config/types/subconfigurations/guild/Discovery.ts +++ b/src/util/config/types/subconfigurations/guild/Discovery.ts @@ -1,6 +1,6 @@ export class DiscoveryConfiguration { - showAllGuilds: boolean = false; - useRecommendation: boolean = false; // TODO: Recommendation, privacy concern? - offset: number = 0; - limit: number = 24; -} \ No newline at end of file + showAllGuilds: boolean = false; + useRecommendation: boolean = false; // TODO: Recommendation, privacy concern? + offset: number = 0; + limit: number = 24; +} diff --git a/src/util/config/types/subconfigurations/kafka/KafkaBroker.ts b/src/util/config/types/subconfigurations/kafka/KafkaBroker.ts index 4f9a5e51..f7dc1cf7 100644 --- a/src/util/config/types/subconfigurations/kafka/KafkaBroker.ts +++ b/src/util/config/types/subconfigurations/kafka/KafkaBroker.ts @@ -1,4 +1,4 @@ export interface KafkaBroker { ip: string; port: number; -} \ No newline at end of file +} diff --git a/src/util/config/types/subconfigurations/limits/ChannelLimits.ts b/src/util/config/types/subconfigurations/limits/ChannelLimits.ts index 2f8f9485..76eeeb41 100644 --- a/src/util/config/types/subconfigurations/limits/ChannelLimits.ts +++ b/src/util/config/types/subconfigurations/limits/ChannelLimits.ts @@ -1,5 +1,5 @@ export class ChannelLimits { - maxPins: number = 500; - maxTopic: number = 1024; - maxWebhooks: number = 100; -} \ No newline at end of file + maxPins: number = 500; + maxTopic: number = 1024; + maxWebhooks: number = 100; +} diff --git a/src/util/config/types/subconfigurations/limits/GlobalRateLimits.ts b/src/util/config/types/subconfigurations/limits/GlobalRateLimits.ts index 4029abbe..d7c8a846 100644 --- a/src/util/config/types/subconfigurations/limits/GlobalRateLimits.ts +++ b/src/util/config/types/subconfigurations/limits/GlobalRateLimits.ts @@ -1,6 +1,14 @@ export class GlobalRateLimits { - register: GlobalRateLimit = { limit: 25, window: 60 * 60 * 1000, enabled: true }; - sendMessage: GlobalRateLimit = { limit: 200, window: 60 * 1000, enabled: true }; + register: GlobalRateLimit = { + limit: 25, + window: 60 * 60 * 1000, + enabled: true, + }; + sendMessage: GlobalRateLimit = { + limit: 200, + window: 60 * 1000, + enabled: true, + }; } export class GlobalRateLimit { diff --git a/src/util/config/types/subconfigurations/limits/GuildLimits.ts b/src/util/config/types/subconfigurations/limits/GuildLimits.ts index c5bc7884..ecd49f1e 100644 --- a/src/util/config/types/subconfigurations/limits/GuildLimits.ts +++ b/src/util/config/types/subconfigurations/limits/GuildLimits.ts @@ -1,7 +1,7 @@ export class GuildLimits { - maxRoles: number = 1000; - maxEmojis: number = 2000; - maxMembers: number = 25000000; - maxChannels: number = 65535; - maxChannelsInCategory: number = 65535; -} \ No newline at end of file + maxRoles: number = 1000; + maxEmojis: number = 2000; + maxMembers: number = 25000000; + maxChannels: number = 65535; + maxChannelsInCategory: number = 65535; +} diff --git a/src/util/config/types/subconfigurations/limits/MessageLimits.ts b/src/util/config/types/subconfigurations/limits/MessageLimits.ts index 51576b90..684a5057 100644 --- a/src/util/config/types/subconfigurations/limits/MessageLimits.ts +++ b/src/util/config/types/subconfigurations/limits/MessageLimits.ts @@ -1,8 +1,8 @@ export class MessageLimits { - maxCharacters: number = 1048576; - maxTTSCharacters: number = 160; - maxReactions: number = 2048; - maxAttachmentSize: number = 1024 * 1024 * 1024; - maxBulkDelete: number = 1000; - maxEmbedDownloadSize: number = 1024 * 1024 * 5; -} \ No newline at end of file + maxCharacters: number = 1048576; + maxTTSCharacters: number = 160; + maxReactions: number = 2048; + maxAttachmentSize: number = 1024 * 1024 * 1024; + maxBulkDelete: number = 1000; + maxEmbedDownloadSize: number = 1024 * 1024 * 5; +} diff --git a/src/util/config/types/subconfigurations/limits/RateLimits.ts b/src/util/config/types/subconfigurations/limits/RateLimits.ts index 3e05a18b..dfce9341 100644 --- a/src/util/config/types/subconfigurations/limits/RateLimits.ts +++ b/src/util/config/types/subconfigurations/limits/RateLimits.ts @@ -4,15 +4,15 @@ export class RateLimits { enabled: boolean = false; ip: Omit<RateLimitOptions, "bot_count"> = { count: 500, - window: 5 + window: 5, }; global: RateLimitOptions = { count: 250, - window: 5 + window: 5, }; error: RateLimitOptions = { count: 10, - window: 5 + window: 5, }; routes: RouteRateLimit = new RouteRateLimit(); } diff --git a/src/util/config/types/subconfigurations/limits/UserLimits.ts b/src/util/config/types/subconfigurations/limits/UserLimits.ts index 0d10e0b3..b8bdcb2d 100644 --- a/src/util/config/types/subconfigurations/limits/UserLimits.ts +++ b/src/util/config/types/subconfigurations/limits/UserLimits.ts @@ -1,5 +1,5 @@ export class UserLimits { - maxGuilds: number = 1048576; - maxUsername: number = 127; - maxFriends: number = 5000; -} \ No newline at end of file + maxGuilds: number = 1048576; + maxUsername: number = 127; + maxFriends: number = 5000; +} diff --git a/src/util/config/types/subconfigurations/limits/ratelimits/Auth.ts b/src/util/config/types/subconfigurations/limits/ratelimits/Auth.ts index df171044..bd45c349 100644 --- a/src/util/config/types/subconfigurations/limits/ratelimits/Auth.ts +++ b/src/util/config/types/subconfigurations/limits/ratelimits/Auth.ts @@ -1,12 +1,12 @@ import { RateLimitOptions } from "./RateLimitOptions"; export class AuthRateLimit { - login: RateLimitOptions = { - count: 5, - window: 60 - }; - register: RateLimitOptions = { - count: 2, - window: 60 * 60 * 12 - }; -} \ No newline at end of file + login: RateLimitOptions = { + count: 5, + window: 60, + }; + register: RateLimitOptions = { + count: 2, + window: 60 * 60 * 12, + }; +} diff --git a/src/util/config/types/subconfigurations/limits/ratelimits/RateLimitOptions.ts b/src/util/config/types/subconfigurations/limits/ratelimits/RateLimitOptions.ts index 7089e28e..829813fb 100644 --- a/src/util/config/types/subconfigurations/limits/ratelimits/RateLimitOptions.ts +++ b/src/util/config/types/subconfigurations/limits/ratelimits/RateLimitOptions.ts @@ -3,4 +3,4 @@ export interface RateLimitOptions { count: number; window: number; onyIp?: boolean; -} \ No newline at end of file +} diff --git a/src/util/config/types/subconfigurations/limits/ratelimits/Route.ts b/src/util/config/types/subconfigurations/limits/ratelimits/Route.ts index 5d73c2cf..5235334a 100644 --- a/src/util/config/types/subconfigurations/limits/ratelimits/Route.ts +++ b/src/util/config/types/subconfigurations/limits/ratelimits/Route.ts @@ -4,15 +4,15 @@ import { RateLimitOptions } from "./RateLimitOptions"; export class RouteRateLimit { guild: RateLimitOptions = { count: 5, - window: 5 + window: 5, }; webhook: RateLimitOptions = { count: 10, - window: 5 + window: 5, }; channel: RateLimitOptions = { count: 10, - window: 5 + window: 5, }; auth: AuthRateLimit = new AuthRateLimit(); // TODO: rate limit configuration for all routes diff --git a/src/util/config/types/subconfigurations/region/Region.ts b/src/util/config/types/subconfigurations/region/Region.ts index a8717e1f..c1bcfd01 100644 --- a/src/util/config/types/subconfigurations/region/Region.ts +++ b/src/util/config/types/subconfigurations/region/Region.ts @@ -9,4 +9,4 @@ export interface Region { vip: boolean; custom: boolean; deprecated: boolean; -} \ No newline at end of file +} diff --git a/src/util/config/types/subconfigurations/register/DateOfBirth.ts b/src/util/config/types/subconfigurations/register/DateOfBirth.ts index 5a3c4e9d..4831a4b7 100644 --- a/src/util/config/types/subconfigurations/register/DateOfBirth.ts +++ b/src/util/config/types/subconfigurations/register/DateOfBirth.ts @@ -1,4 +1,4 @@ export class DateOfBirthConfiguration { - required: boolean = true; - minimum: number = 13; // in years -} \ No newline at end of file + required: boolean = true; + minimum: number = 13; // in years +} diff --git a/src/util/config/types/subconfigurations/register/Email.ts b/src/util/config/types/subconfigurations/register/Email.ts index 115d49e0..7f54faa7 100644 --- a/src/util/config/types/subconfigurations/register/Email.ts +++ b/src/util/config/types/subconfigurations/register/Email.ts @@ -1,7 +1,7 @@ export class EmailConfiguration { - required: boolean = false; - allowlist: boolean = false; - blocklist: boolean = true; - domains: string[] = [];// TODO: efficiently save domain blocklist in database - // domains: fs.readFileSync(__dirname + "/blockedEmailDomains.txt", { encoding: "utf8" }).split("\n"), -} \ No newline at end of file + required: boolean = false; + allowlist: boolean = false; + blocklist: boolean = true; + domains: string[] = []; // TODO: efficiently save domain blocklist in database + // domains: fs.readFileSync(__dirname + "/blockedEmailDomains.txt", { encoding: "utf8" }).split("\n"), +} diff --git a/src/util/config/types/subconfigurations/register/Password.ts b/src/util/config/types/subconfigurations/register/Password.ts index 977473ac..383bdcfa 100644 --- a/src/util/config/types/subconfigurations/register/Password.ts +++ b/src/util/config/types/subconfigurations/register/Password.ts @@ -1,7 +1,7 @@ export class PasswordConfiguration { - required: boolean = false; - minLength: number = 8; - minNumbers: number = 2; - minUpperCase: number =2; - minSymbols: number = 0; -} \ No newline at end of file + required: boolean = false; + minLength: number = 8; + minNumbers: number = 2; + minUpperCase: number = 2; + minSymbols: number = 0; +} diff --git a/src/util/config/types/subconfigurations/security/Captcha.ts b/src/util/config/types/subconfigurations/security/Captcha.ts index ad6aa762..21c4ef44 100644 --- a/src/util/config/types/subconfigurations/security/Captcha.ts +++ b/src/util/config/types/subconfigurations/security/Captcha.ts @@ -1,6 +1,6 @@ export class CaptchaConfiguration { - enabled: boolean = false; - service: "recaptcha" | "hcaptcha" | null = null; // TODO: hcaptcha, custom - sitekey: string | null = null; - secret: string | null = null; -} \ No newline at end of file + enabled: boolean = false; + service: "recaptcha" | "hcaptcha" | null = null; // TODO: hcaptcha, custom + sitekey: string | null = null; + secret: string | null = null; +} diff --git a/src/util/config/types/subconfigurations/security/TwoFactor.ts b/src/util/config/types/subconfigurations/security/TwoFactor.ts index 33a47385..20d2f9ab 100644 --- a/src/util/config/types/subconfigurations/security/TwoFactor.ts +++ b/src/util/config/types/subconfigurations/security/TwoFactor.ts @@ -1,3 +1,3 @@ export class TwoFactorConfiguration { - generateBackupCodes: boolean = true; -} \ No newline at end of file + generateBackupCodes: boolean = true; +} diff --git a/src/util/entities/Application.ts b/src/util/entities/Application.ts index 67475bdd..e37f5ee5 100644 --- a/src/util/entities/Application.ts +++ b/src/util/entities/Application.ts @@ -1,4 +1,11 @@ -import { Column, Entity, JoinColumn, ManyToOne, OneToOne, RelationId } from "typeorm"; +import { + Column, + Entity, + JoinColumn, + ManyToOne, + OneToOne, + RelationId, +} from "typeorm"; import { BaseClass } from "./BaseClass"; import { Guild } from "./Guild"; import { Team } from "./Team"; @@ -8,78 +15,78 @@ import { User } from "./User"; export class Application extends BaseClass { @Column() name: string; - + @Column({ nullable: true }) icon?: string; - + @Column({ nullable: true }) description: string; - + @Column({ nullable: true }) summary: string = ""; - + @Column({ type: "simple-json", nullable: true }) type?: any; - + @Column() hook: boolean = true; - + @Column() bot_public?: boolean = true; - + @Column() bot_require_code_grant?: boolean = false; - + @Column() verify_key: string; - + @JoinColumn({ name: "owner_id" }) @ManyToOne(() => User) owner: User; - + // TODO: enum this? https://discord.com/developers/docs/resources/application#application-object-application-flags @Column() flags: number = 0; - + @Column({ type: "simple-array", nullable: true }) redirect_uris: string[] = []; - + @Column({ nullable: true }) rpc_application_state: number = 0; - + @Column({ nullable: true }) store_application_state: number = 1; - + @Column({ nullable: true }) verification_state: number = 1; - + @Column({ nullable: true }) interactions_endpoint_url?: string; - + @Column({ nullable: true }) integration_public: boolean = true; - + @Column({ nullable: true }) integration_require_code_grant: boolean = false; - + @Column({ nullable: true }) discoverability_state: number = 1; - + @Column({ nullable: true }) discovery_eligibility_flags: number = 2240; - + @JoinColumn({ name: "bot_user_id" }) @OneToOne(() => User) bot?: User; - + @Column({ type: "simple-array", nullable: true }) tags?: string[]; - + @Column({ nullable: true }) cover_image?: string; // the application's default rich presence invite cover image hash - + @Column({ type: "simple-json", nullable: true }) - install_params?: {scopes: string[], permissions: string}; + install_params?: { scopes: string[]; permissions: string }; @Column({ nullable: true }) terms_of_service_url?: string; @@ -91,7 +98,7 @@ export class Application extends BaseClass { //@Column({ type: "simple-array", nullable: true }) //rpc_origins?: string[]; - + //@JoinColumn({ name: "guild_id" }) //@ManyToOne(() => Guild) //guild?: Guild; // if this application is a game sold, this field will be the guild to which it has been linked @@ -105,11 +112,10 @@ export class Application extends BaseClass { @JoinColumn({ name: "team_id" }) @ManyToOne(() => Team, { onDelete: "CASCADE", - nullable: true + nullable: true, }) team?: Team; - - } +} export interface ApplicationCommand { id: string; diff --git a/src/util/entities/Channel.ts b/src/util/entities/Channel.ts index e9e631f1..aaddc001 100644 --- a/src/util/entities/Channel.ts +++ b/src/util/entities/Channel.ts @@ -209,7 +209,10 @@ export class Channel extends BaseClass { ); // Categories skip these checks on discord.com - if (channel.type !== ChannelType.GUILD_CATEGORY || guild.features.includes("IRC_LIKE_CATEGORY_NAMES")) { + if ( + channel.type !== ChannelType.GUILD_CATEGORY || + guild.features.includes("IRC_LIKE_CATEGORY_NAMES") + ) { if (channel.name.includes(" ")) throw new HTTPError( "Channel name cannot include invalid characters", @@ -286,10 +289,10 @@ export class Channel extends BaseClass { Channel.create(channel).save(), !opts?.skipEventEmit ? emitEvent({ - event: "CHANNEL_CREATE", - data: channel, - guild_id: channel.guild_id, - } as ChannelCreateEvent) + event: "CHANNEL_CREATE", + data: channel, + guild_id: channel.guild_id, + } as ChannelCreateEvent) : Promise.resolve(), ]); diff --git a/src/util/entities/EmbedCache.ts b/src/util/entities/EmbedCache.ts index 14881ccf..e182b8c2 100644 --- a/src/util/entities/EmbedCache.ts +++ b/src/util/entities/EmbedCache.ts @@ -9,4 +9,4 @@ export class EmbedCache extends BaseClass { @Column({ type: "simple-json" }) embed: Embed; -} \ No newline at end of file +} diff --git a/src/util/entities/Guild.ts b/src/util/entities/Guild.ts index c86a5787..7f3536fa 100644 --- a/src/util/entities/Guild.ts +++ b/src/util/entities/Guild.ts @@ -79,7 +79,8 @@ export class Guild extends BaseClass { banner?: string; @Column({ nullable: true }) - default_message_notifications?: number = Config.get().defaults.guild.defaultMessageNotifications; + default_message_notifications?: number = + Config.get().defaults.guild.defaultMessageNotifications; @Column({ nullable: true }) description?: string; @@ -88,7 +89,8 @@ export class Guild extends BaseClass { discovery_splash?: string; @Column({ nullable: true }) - explicit_content_filter?: number = Config.get().defaults.guild.explicitContentFilter; + explicit_content_filter?: number = + Config.get().defaults.guild.explicitContentFilter; @Column({ type: "simple-array" }) features: string[] = Config.get().guild.defaultFeatures || []; //TODO use enum @@ -110,7 +112,8 @@ export class Guild extends BaseClass { max_presences?: number = Config.get().defaults.guild.maxPresences; @Column({ nullable: true }) - max_video_channel_users?: number = Config.get().defaults.guild.maxVideoChannelUsers; + max_video_channel_users?: number = + Config.get().defaults.guild.maxVideoChannelUsers; @Column({ nullable: true }) member_count?: number; diff --git a/src/util/entities/Invite.ts b/src/util/entities/Invite.ts index 8f5619fc..4b71ed02 100644 --- a/src/util/entities/Invite.ts +++ b/src/util/entities/Invite.ts @@ -1,10 +1,4 @@ -import { - Column, - Entity, - JoinColumn, - ManyToOne, - RelationId, -} from "typeorm"; +import { Column, Entity, JoinColumn, ManyToOne, RelationId } from "typeorm"; import { Member } from "./Member"; import { BaseClassWithoutId, PrimaryIdColumn } from "./BaseClass"; import { Channel } from "./Channel"; @@ -62,7 +56,7 @@ export class Invite extends BaseClassWithoutId { @JoinColumn({ name: "inviter_id" }) @ManyToOne(() => User, { - onDelete: "CASCADE" + onDelete: "CASCADE", }) inviter: User; diff --git a/src/util/entities/Member.ts b/src/util/entities/Member.ts index eeae181e..f8a91f85 100644 --- a/src/util/entities/Member.ts +++ b/src/util/entities/Member.ts @@ -125,9 +125,9 @@ export class Member extends BaseClassWithoutId { @Column() bio: string; - + @Column({ nullable: true, type: "simple-array" }) - theme_colors?: number[]; // TODO: Separate `User` and `UserProfile` models + theme_colors?: number[]; // TODO: Separate `User` and `UserProfile` models @Column({ nullable: true }) pronouns?: string; @@ -309,9 +309,9 @@ export class Member extends BaseClassWithoutId { guild_id, user: { sessions: { - status: Not("invisible" as "invisible") // lol typescript? - } - } + status: Not("invisible" as "invisible"), // lol typescript? + }, + }, }, take: 10, }); @@ -380,7 +380,7 @@ export class Member extends BaseClassWithoutId { stage_instances: [], threads: [], embedded_activities: [], - voice_states: guild.voice_states + voice_states: guild.voice_states, }, user_id, } as GuildCreateEvent), diff --git a/src/util/entities/User.ts b/src/util/entities/User.ts index e039eb17..34b7ea0e 100644 --- a/src/util/entities/User.ts +++ b/src/util/entities/User.ts @@ -15,13 +15,7 @@ import { ConnectedAccount } from "./ConnectedAccount"; import { Member } from "./Member"; import { UserSettings } from "./UserSettings"; import { Session } from "./Session"; -import { - Config, - FieldErrors, - Snowflake, - trimSpecial, - adjustEmail, -} from ".."; +import { Config, FieldErrors, Snowflake, trimSpecial, adjustEmail } from ".."; export enum PublicUserEnum { username, @@ -68,7 +62,7 @@ export const PrivateUserProjection = [ // Private user data that should never get sent to the client export type PublicUser = Pick<User, PublicUserKeys>; -export interface UserPublic extends Pick<User, PublicUserKeys> { } +export interface UserPublic extends Pick<User, PublicUserKeys> {} export interface UserPrivate extends Pick<User, PrivateUserKeys> { locale: string; @@ -92,7 +86,7 @@ export class User extends BaseClass { banner?: string; // hash of the user banner @Column({ nullable: true, type: "simple-array" }) - theme_colors?: number[]; // TODO: Separate `User` and `UserProfile` models + theme_colors?: number[]; // TODO: Separate `User` and `UserProfile` models @Column({ nullable: true }) pronouns?: string; @@ -140,7 +134,7 @@ export class User extends BaseClass { premium_since: Date = new Date(); // premium date @Column({ select: false }) - verified: boolean = true; // email is verified + verified: boolean = true; // email is verified @Column() disabled: boolean = false; // if the account is disabled @@ -203,7 +197,7 @@ export class User extends BaseClass { @OneToOne(() => UserSettings, { cascade: true, orphanedRowAction: "delete", - eager: false + eager: false, }) @JoinColumn() settings: UserSettings; @@ -270,7 +264,9 @@ export class User extends BaseClass { }); } - public static async generateDiscriminator(username: string): Promise<string | undefined> { + public static async generateDiscriminator( + username: string, + ): Promise<string | undefined> { if (Config.get().register.incrementingDiscriminators) { // discriminator will be incrementally generated @@ -322,7 +318,7 @@ export class User extends BaseClass { password?: string; email?: string; date_of_birth?: Date; // "2000-04-03" - id?: string, + id?: string; req?: any; }) { // trim special uf8 control characters -> Backspace, Newline, ... @@ -347,7 +343,7 @@ export class User extends BaseClass { const settings = UserSettings.create({ locale: language, - }) + }); const user = User.create({ username: username, @@ -367,15 +363,12 @@ export class User extends BaseClass { }); user.validate(); - await Promise.all([ - user.save(), - settings.save(), - ]) + await Promise.all([user.save(), settings.save()]); setImmediate(async () => { if (Config.get().guild.autoJoin.enabled) { for (const guild of Config.get().guild.autoJoin.guilds || []) { - await Member.addToGuild(user.id, guild).catch((e) => { }); + await Member.addToGuild(user.id, guild).catch((e) => {}); } } }); diff --git a/src/util/entities/UserSettings.ts b/src/util/entities/UserSettings.ts index b1a1fe68..995bb262 100644 --- a/src/util/entities/UserSettings.ts +++ b/src/util/entities/UserSettings.ts @@ -3,117 +3,117 @@ import { BaseClassWithoutId } from "./BaseClass"; @Entity("user_settings") export class UserSettings extends BaseClassWithoutId { - @PrimaryGeneratedColumn() + @PrimaryGeneratedColumn() index: string; @Column({ nullable: true }) - afk_timeout: number = 3600; - - @Column({ nullable: true }) - allow_accessibility_detection: boolean = true; - - @Column({ nullable: true }) - animate_emoji: boolean = true; - - @Column({ nullable: true }) - animate_stickers: number = 0; - - @Column({ nullable: true }) - contact_sync_enabled: boolean = false; - - @Column({ nullable: true }) - convert_emoticons: boolean = false; - - @Column({ nullable: true, type: "simple-json" }) - custom_status: CustomStatus | null = null; - - @Column({ nullable: true }) - default_guilds_restricted: boolean = false; - - @Column({ nullable: true }) - detect_platform_accounts: boolean = false; - - @Column({ nullable: true }) - developer_mode: boolean = true; - - @Column({ nullable: true }) - disable_games_tab: boolean = true; - - @Column({ nullable: true }) - enable_tts_command: boolean = false; - - @Column({ nullable: true }) - explicit_content_filter: number = 0; - - @Column({ nullable: true, type: "simple-json" }) - friend_source_flags: FriendSourceFlags = { all: true }; - - @Column({ nullable: true }) - gateway_connected: boolean = false; - - @Column({ nullable: true }) - gif_auto_play: boolean = false; - - @Column({ nullable: true, type: "simple-json" }) - guild_folders: GuildFolder[] = []; // every top guild is displayed as a "folder" - - @Column({ nullable: true, type: "simple-json" }) - guild_positions: string[] = []; // guild ids ordered by position - - @Column({ nullable: true }) - inline_attachment_media: boolean = true; - - @Column({ nullable: true }) - inline_embed_media: boolean = true; - - @Column({ nullable: true }) - locale: string = "en-US"; // en_US - - @Column({ nullable: true }) - message_display_compact: boolean = false; - - @Column({ nullable: true }) - native_phone_integration_enabled: boolean = true; - - @Column({ nullable: true }) - render_embeds: boolean = true; - - @Column({ nullable: true }) - render_reactions: boolean = true; - - @Column({ nullable: true, type: "simple-json" }) - restricted_guilds: string[] = []; - - @Column({ nullable: true }) - show_current_game: boolean = true; - - @Column({ nullable: true }) - status: "online" | "offline" | "dnd" | "idle" | "invisible" = "online"; - - @Column({ nullable: true }) - stream_notifications_enabled: boolean = false; - - @Column({ nullable: true }) - theme: "dark" | "light" = "dark"; // dark - - @Column({ nullable: true }) - timezone_offset: number = 0; // e.g -60 + afk_timeout: number = 3600; + + @Column({ nullable: true }) + allow_accessibility_detection: boolean = true; + + @Column({ nullable: true }) + animate_emoji: boolean = true; + + @Column({ nullable: true }) + animate_stickers: number = 0; + + @Column({ nullable: true }) + contact_sync_enabled: boolean = false; + + @Column({ nullable: true }) + convert_emoticons: boolean = false; + + @Column({ nullable: true, type: "simple-json" }) + custom_status: CustomStatus | null = null; + + @Column({ nullable: true }) + default_guilds_restricted: boolean = false; + + @Column({ nullable: true }) + detect_platform_accounts: boolean = false; + + @Column({ nullable: true }) + developer_mode: boolean = true; + + @Column({ nullable: true }) + disable_games_tab: boolean = true; + + @Column({ nullable: true }) + enable_tts_command: boolean = false; + + @Column({ nullable: true }) + explicit_content_filter: number = 0; + + @Column({ nullable: true, type: "simple-json" }) + friend_source_flags: FriendSourceFlags = { all: true }; + + @Column({ nullable: true }) + gateway_connected: boolean = false; + + @Column({ nullable: true }) + gif_auto_play: boolean = false; + + @Column({ nullable: true, type: "simple-json" }) + guild_folders: GuildFolder[] = []; // every top guild is displayed as a "folder" + + @Column({ nullable: true, type: "simple-json" }) + guild_positions: string[] = []; // guild ids ordered by position + + @Column({ nullable: true }) + inline_attachment_media: boolean = true; + + @Column({ nullable: true }) + inline_embed_media: boolean = true; + + @Column({ nullable: true }) + locale: string = "en-US"; // en_US + + @Column({ nullable: true }) + message_display_compact: boolean = false; + + @Column({ nullable: true }) + native_phone_integration_enabled: boolean = true; + + @Column({ nullable: true }) + render_embeds: boolean = true; + + @Column({ nullable: true }) + render_reactions: boolean = true; + + @Column({ nullable: true, type: "simple-json" }) + restricted_guilds: string[] = []; + + @Column({ nullable: true }) + show_current_game: boolean = true; + + @Column({ nullable: true }) + status: "online" | "offline" | "dnd" | "idle" | "invisible" = "online"; + + @Column({ nullable: true }) + stream_notifications_enabled: boolean = false; + + @Column({ nullable: true }) + theme: "dark" | "light" = "dark"; // dark + + @Column({ nullable: true }) + timezone_offset: number = 0; // e.g -60 } interface CustomStatus { - emoji_id?: string; - emoji_name?: string; - expires_at?: number; - text?: string; + emoji_id?: string; + emoji_name?: string; + expires_at?: number; + text?: string; } interface GuildFolder { - color: number; - guild_ids: string[]; - id: number; - name: string; + color: number; + guild_ids: string[]; + id: number; + name: string; } -interface FriendSourceFlags { - all: boolean -} \ No newline at end of file +interface FriendSourceFlags { + all: boolean; +} diff --git a/src/util/entities/ValidRegistrationTokens.ts b/src/util/entities/ValidRegistrationTokens.ts index 00839324..7db66c1d 100644 --- a/src/util/entities/ValidRegistrationTokens.ts +++ b/src/util/entities/ValidRegistrationTokens.ts @@ -4,10 +4,10 @@ import { BaseEntity, Column, Entity, PrimaryColumn } from "typeorm"; export class ValidRegistrationToken extends BaseEntity { @PrimaryColumn() token: string; - + @Column() created_at: Date = new Date(); @Column() expires_at: Date; -} \ No newline at end of file +} diff --git a/src/util/entities/index.ts b/src/util/entities/index.ts index dc509250..3e64965c 100644 --- a/src/util/entities/index.ts +++ b/src/util/entities/index.ts @@ -33,4 +33,4 @@ export * from "./User"; export * from "./UserSettings"; export * from "./ValidRegistrationTokens"; export * from "./VoiceState"; -export * from "./Webhook"; \ No newline at end of file +export * from "./Webhook"; diff --git a/src/util/index.ts b/src/util/index.ts index 7b4dc936..957fb393 100644 --- a/src/util/index.ts +++ b/src/util/index.ts @@ -6,4 +6,4 @@ export * from "./entities/index"; export * from "./dtos/index"; export * from "./schemas"; export * from "./imports"; -export * from "./config" \ No newline at end of file +export * from "./config"; diff --git a/src/util/interfaces/Event.ts b/src/util/interfaces/Event.ts index f5bccb2f..b772c3e4 100644 --- a/src/util/interfaces/Event.ts +++ b/src/util/interfaces/Event.ts @@ -81,9 +81,9 @@ export interface ReadyEventData { number, null, number, - [[number, { e: number; s: number; }[]]], + [[number, { e: number; s: number }[]]], [number, [[number, [number, number]]]], - { b: number; k: bigint[]; }[], + { b: number; k: bigint[] }[], ][]; guild_join_requests?: any[]; // ? what is this? this is new shard?: [number, number]; @@ -481,7 +481,7 @@ export interface SessionsReplace extends Event { export interface GuildMemberListUpdate extends Event { event: "GUILD_MEMBER_LIST_UPDATE"; data: { - groups: { id: string; count: number; }[]; + groups: { id: string; count: number }[]; guild_id: string; id: string; member_count: number; @@ -489,8 +489,8 @@ export interface GuildMemberListUpdate extends Event { ops: { index: number; item: { - member?: PublicMember & { presence: Presence; }; - group?: { id: string; count: number; }[]; + member?: PublicMember & { presence: Presence }; + group?: { id: string; count: number }[]; }; }[]; }; diff --git a/src/util/schemas/ApplicationAuthorizeSchema.ts b/src/util/schemas/ApplicationAuthorizeSchema.ts index 1a0aae0f..add26c74 100644 --- a/src/util/schemas/ApplicationAuthorizeSchema.ts +++ b/src/util/schemas/ApplicationAuthorizeSchema.ts @@ -3,5 +3,5 @@ export interface ApplicationAuthorizeSchema { guild_id: string; permissions: string; captcha_key?: string; - code?: string; // 2fa code -} \ No newline at end of file + code?: string; // 2fa code +} diff --git a/src/util/schemas/ApplicationCreateSchema.ts b/src/util/schemas/ApplicationCreateSchema.ts index 6a021b46..0801a6c5 100644 --- a/src/util/schemas/ApplicationCreateSchema.ts +++ b/src/util/schemas/ApplicationCreateSchema.ts @@ -1,4 +1,4 @@ export interface ApplicationCreateSchema { name: string; team_id?: string | number; -} \ No newline at end of file +} diff --git a/src/util/schemas/ApplicationModifySchema.ts b/src/util/schemas/ApplicationModifySchema.ts index ab23d57e..5f5bbe1d 100644 --- a/src/util/schemas/ApplicationModifySchema.ts +++ b/src/util/schemas/ApplicationModifySchema.ts @@ -11,4 +11,4 @@ export interface ApplicationModifySchema { bot_public?: boolean; bot_require_code_grant?: boolean; flags?: number; -} \ No newline at end of file +} diff --git a/src/util/schemas/BotModifySchema.ts b/src/util/schemas/BotModifySchema.ts index b801ab27..19a5c54e 100644 --- a/src/util/schemas/BotModifySchema.ts +++ b/src/util/schemas/BotModifySchema.ts @@ -1,4 +1,4 @@ export interface BotModifySchema { avatar?: string; username?: string; -} \ No newline at end of file +} diff --git a/src/util/schemas/ChannelPermissionOverwriteSchema.ts b/src/util/schemas/ChannelPermissionOverwriteSchema.ts index 6d6d6c34..4f5c9712 100644 --- a/src/util/schemas/ChannelPermissionOverwriteSchema.ts +++ b/src/util/schemas/ChannelPermissionOverwriteSchema.ts @@ -1,4 +1,4 @@ import { ChannelPermissionOverwrite } from "@fosscord/util"; export interface ChannelPermissionOverwriteSchema - extends ChannelPermissionOverwrite {} \ No newline at end of file + extends ChannelPermissionOverwrite {} diff --git a/src/util/schemas/ChannelReorderSchema.ts b/src/util/schemas/ChannelReorderSchema.ts index 6eb4cdd5..c6e59ebd 100644 --- a/src/util/schemas/ChannelReorderSchema.ts +++ b/src/util/schemas/ChannelReorderSchema.ts @@ -3,4 +3,4 @@ export type ChannelReorderSchema = { position?: number; lock_permissions?: boolean; parent_id?: string; -}[]; \ No newline at end of file +}[]; diff --git a/src/util/schemas/GatewayPayloadSchema.ts b/src/util/schemas/GatewayPayloadSchema.ts index 324ad1eb..ce27f0dc 100644 --- a/src/util/schemas/GatewayPayloadSchema.ts +++ b/src/util/schemas/GatewayPayloadSchema.ts @@ -5,4 +5,4 @@ export const PayloadSchema = { $d: new Tuple(Object, Number), // or number for heartbeat sequence $s: Number, $t: String, -}; \ No newline at end of file +}; diff --git a/src/util/schemas/GuildUpdateSchema.ts b/src/util/schemas/GuildUpdateSchema.ts index e858a7a2..4e8daacf 100644 --- a/src/util/schemas/GuildUpdateSchema.ts +++ b/src/util/schemas/GuildUpdateSchema.ts @@ -1,6 +1,7 @@ import { GuildCreateSchema } from "@fosscord/util"; -export interface GuildUpdateSchema extends Omit<GuildCreateSchema, "channels" | "name"> { +export interface GuildUpdateSchema + extends Omit<GuildCreateSchema, "channels" | "name"> { name?: string; banner?: string | null; splash?: string | null; diff --git a/src/util/schemas/MemberChangeProfileSchema.ts b/src/util/schemas/MemberChangeProfileSchema.ts index 73c852f3..3c16c359 100644 --- a/src/util/schemas/MemberChangeProfileSchema.ts +++ b/src/util/schemas/MemberChangeProfileSchema.ts @@ -5,7 +5,7 @@ export interface MemberChangeProfileSchema { pronouns?: string; /* - * @items.type integer - */ + * @items.type integer + */ theme_colors?: [number, number]; } diff --git a/src/util/schemas/RolePositionUpdateSchema.ts b/src/util/schemas/RolePositionUpdateSchema.ts index 1019d504..993d1ae0 100644 --- a/src/util/schemas/RolePositionUpdateSchema.ts +++ b/src/util/schemas/RolePositionUpdateSchema.ts @@ -1,4 +1,4 @@ export type RolePositionUpdateSchema = { id: string; position: number; -}[]; \ No newline at end of file +}[]; diff --git a/src/util/schemas/UserGuildSettingsSchema.ts b/src/util/schemas/UserGuildSettingsSchema.ts index e78bbf7c..b9efdbfa 100644 --- a/src/util/schemas/UserGuildSettingsSchema.ts +++ b/src/util/schemas/UserGuildSettingsSchema.ts @@ -6,4 +6,4 @@ export interface UserGuildSettingsSchema channel_overrides?: { [channel_id: string]: Partial<ChannelOverride>; }; -} \ No newline at end of file +} diff --git a/src/util/schemas/UserProfileModifySchema.ts b/src/util/schemas/UserProfileModifySchema.ts index 1e53d9e4..840e9c3e 100644 --- a/src/util/schemas/UserProfileModifySchema.ts +++ b/src/util/schemas/UserProfileModifySchema.ts @@ -5,7 +5,7 @@ export interface UserProfileModifySchema { pronouns?: string; /* - * @items.type integer - */ - theme_colors?: [number, number] + * @items.type integer + */ + theme_colors?: [number, number]; } diff --git a/src/util/schemas/UserSettingsSchema.ts b/src/util/schemas/UserSettingsSchema.ts index db015457..eb9b316d 100644 --- a/src/util/schemas/UserSettingsSchema.ts +++ b/src/util/schemas/UserSettingsSchema.ts @@ -1,3 +1,3 @@ import { UserSettings } from "@fosscord/util"; -export interface UserSettingsSchema extends Partial<UserSettings> {} \ No newline at end of file +export interface UserSettingsSchema extends Partial<UserSettings> {} diff --git a/src/util/schemas/index.ts b/src/util/schemas/index.ts index be4be0c7..e4f565c9 100644 --- a/src/util/schemas/index.ts +++ b/src/util/schemas/index.ts @@ -59,4 +59,4 @@ export * from "./UserSettingsSchema"; export * from "./BotModifySchema"; export * from "./ApplicationModifySchema"; export * from "./ApplicationCreateSchema"; -export * from "./ApplicationAuthorizeSchema"; \ No newline at end of file +export * from "./ApplicationAuthorizeSchema"; diff --git a/src/util/util/BitField.ts b/src/util/util/BitField.ts index e2f4e2a5..413112ca 100644 --- a/src/util/util/BitField.ts +++ b/src/util/util/BitField.ts @@ -138,10 +138,8 @@ export class BitField { const FLAGS = this.FLAGS || this.constructor?.FLAGS; if (typeof bit === "string") { - if (typeof FLAGS[bit] !== "undefined") - return FLAGS[bit]; - else - bit = BigInt(bit); + if (typeof FLAGS[bit] !== "undefined") return FLAGS[bit]; + else bit = BigInt(bit); } if ( diff --git a/src/util/util/Config.ts b/src/util/util/Config.ts index e3ac4177..5d98f5bc 100644 --- a/src/util/util/Config.ts +++ b/src/util/util/Config.ts @@ -14,7 +14,7 @@ var pairs: ConfigEntity[]; export const Config = { init: async function init() { if (config) return config; - console.log('[Config] Loading configuration...'); + console.log("[Config] Loading configuration..."); pairs = await ConfigEntity.find(); config = pairsToConfig(pairs); // TODO: this overwrites existing config values with defaults. @@ -26,16 +26,19 @@ export const Config = { if (Object.keys(config).length == 0) config = new ConfigValue(); if (process.env.CONFIG_PATH) { - console.log(`[Config] Using config path from environment rather than database.`); + console.log( + `[Config] Using config path from environment rather than database.`, + ); try { - const overrideConfig = JSON.parse(fs.readFileSync(overridePath, { encoding: "utf8" })); + const overrideConfig = JSON.parse( + fs.readFileSync(overridePath, { encoding: "utf8" }), + ); config = overrideConfig.merge(config); } catch (error) { fs.writeFileSync(overridePath, JSON.stringify(config, null, 4)); } } - return this.set(config); }, get: function get() { diff --git a/src/util/util/Constants.ts b/src/util/util/Constants.ts index b84a8178..d4431209 100644 --- a/src/util/util/Constants.ts +++ b/src/util/util/Constants.ts @@ -1043,7 +1043,7 @@ export const FosscordApiErrors = { 45006, 501, ), - FEATURE_IS_IMMUTABLE : new ApiError( + FEATURE_IS_IMMUTABLE: new ApiError( "The feature ({}) cannot be edited.", 45007, 403, diff --git a/src/util/util/Database.ts b/src/util/util/Database.ts index da0909ab..2089d453 100644 --- a/src/util/util/Database.ts +++ b/src/util/util/Database.ts @@ -37,7 +37,6 @@ const DataSourceOptions = new DataSource({ migrations: [path.join(__dirname, "..", "migration", DatabaseType, "*.js")], }); - // Gets the existing database connection export function getDatabase(): DataSource | null { // if (!dbConnection) throw new Error("Tried to get database before it was initialised"); @@ -60,8 +59,13 @@ export async function initDatabase(): Promise<DataSource> { if (!process.env.DB_SYNC) { const supported = ["mysql", "mariadb", "postgres", "sqlite"]; if (!supported.includes(DatabaseType)) { - console.log("[Database]" + red(` We don't have migrations for DB type '${DatabaseType}'` + - ` To ignore, set DB_SYNC=true in your env. https://docs.fosscord.com/setup/server/configuration/env/`)); + console.log( + "[Database]" + + red( + ` We don't have migrations for DB type '${DatabaseType}'` + + ` To ignore, set DB_SYNC=true in your env. https://docs.fosscord.com/setup/server/configuration/env/`, + ), + ); process.exit(); } } @@ -71,12 +75,20 @@ export async function initDatabase(): Promise<DataSource> { dbConnection = await DataSourceOptions.initialize(); // Crude way of detecting if the migrations table exists. - const dbExists = async () => { try { await ConfigEntity.count(); return true; } catch (e) { return false; } }; - if (!await dbExists()) { - console.log("[Database] This appears to be a fresh database. Synchronising."); + const dbExists = async () => { + try { + await ConfigEntity.count(); + return true; + } catch (e) { + return false; + } + }; + if (!(await dbExists())) { + console.log( + "[Database] This appears to be a fresh database. Synchronising.", + ); await dbConnection.synchronize(); - } - else { + } else { await dbConnection.runMigrations(); } diff --git a/src/util/util/InvisibleCharacters.ts b/src/util/util/InvisibleCharacters.ts index 82031f53..c45915f4 100644 --- a/src/util/util/InvisibleCharacters.ts +++ b/src/util/util/InvisibleCharacters.ts @@ -1,7 +1,7 @@ // List from https://invisible-characters.com/ export const InvisibleCharacters = [ "\u{9}", //Tab - '\u{c}', //Form feed + "\u{c}", //Form feed //'\u{20}', //Space //categories can have spaces in them "\u{ad}", //Soft hyphen //"\u{34f}", //Combining grapheme joiner diff --git a/src/util/util/Rights.ts b/src/util/util/Rights.ts index 8e54a04f..68a7c840 100644 --- a/src/util/util/Rights.ts +++ b/src/util/util/Rights.ts @@ -32,7 +32,7 @@ export class Rights extends BitField { static FLAGS = { OPERATOR: BitFlag(0), // has all rights MANAGE_APPLICATIONS: BitFlag(1), - MANAGE_GUILDS: BitFlag(2), // Manage all guilds instance-wide + MANAGE_GUILDS: BitFlag(2), // Manage all guilds instance-wide MANAGE_MESSAGES: BitFlag(3), // Can't see other messages but delete/edit them in channels that they can see MANAGE_RATE_LIMITS: BitFlag(4), MANAGE_ROUTING: BitFlag(5), // can create custom message routes to any channel/guild @@ -81,7 +81,7 @@ export class Rights extends BitField { SELF_EDIT_FLAGS: BitFlag(45), // can modify own flags EDIT_FLAGS: BitFlag(46), // can set others' flags MANAGE_GROUPS: BitFlag(47), // can manage others' groups - VIEW_SERVER_STATS: BitFlag(48) // added per @chrischrome's request — can view server stats) + VIEW_SERVER_STATS: BitFlag(48), // added per @chrischrome's request — can view server stats) }; any(permission: RightResolvable, checkOperator = true) { diff --git a/src/util/util/index.ts b/src/util/util/index.ts index f7a273cb..01ef4eae 100644 --- a/src/util/util/index.ts +++ b/src/util/util/index.ts @@ -19,4 +19,4 @@ export * from "./Snowflake"; export * from "./String"; export * from "./Array"; export * from "./TraverseDirectory"; -export * from "./InvisibleCharacters"; \ No newline at end of file +export * from "./InvisibleCharacters"; |