From 53a8ad31628f098db21462f271db24a4b0af1b16 Mon Sep 17 00:00:00 2001 From: Advaith Date: Sun, 6 Sep 2020 22:56:47 -0700 Subject: [PATCH] switch to djs client.api, clean up form validation and error handling, and other stuff major backend update closes #100 #94 --- @types/custom.d.ts | 7 +- package-lock.json | 56 +- package.json | 10 +- src/Routes/authentication.ts | 54 +- src/Routes/bots.ts | 1277 +++++++++++------------------- src/Routes/servers.ts | 525 +++++------- src/Routes/staff.ts | 12 +- src/Routes/templates.ts | 303 +++---- src/Routes/users.ts | 60 +- src/Util/Function/main.ts | 10 +- src/Util/Function/permissions.ts | 57 +- src/Util/Function/variables.ts | 13 +- src/Util/Services/discord.ts | 16 +- 13 files changed, 942 insertions(+), 1458 deletions(-) diff --git a/@types/custom.d.ts b/@types/custom.d.ts index b47e9ecf..31bbe517 100644 --- a/@types/custom.d.ts +++ b/@types/custom.d.ts @@ -71,6 +71,11 @@ declare module "express-serve-static-core" { interface Response { session: any; user: any; - __: any; + /** get i18n string + * + * https://github.com/discordextremelist/i18n/tree/master/website + * https://translate.discordextremelist.xyz + */ + __(key: string, args?: any): string; } } diff --git a/package-lock.json b/package-lock.json index 75f0b954..4bd42be9 100644 --- a/package-lock.json +++ b/package-lock.json @@ -242,9 +242,9 @@ "dev": true }, "@types/express": { - "version": "4.17.7", - "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.7.tgz", - "integrity": "sha512-dCOT5lcmV/uC2J9k0rPafATeeyz+99xTt54ReX11/LObZgfzJqZNcW27zGhYyX+9iSEGXGt5qLPwRSvBZcLvtQ==", + "version": "4.17.8", + "resolved": "https://registry.npmjs.org/@types/express/-/express-4.17.8.tgz", + "integrity": "sha512-wLhcKh3PMlyA2cNAB9sjM1BntnhPMiM0JOBwPBqttjHev2428MLEB4AYVN+d8s2iyCVZac+o41Pflm/ZH5vLXQ==", "dev": true, "requires": { "@types/body-parser": "*", @@ -254,9 +254,9 @@ } }, "@types/express-serve-static-core": { - "version": "4.17.8", - "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.8.tgz", - "integrity": "sha512-1SJZ+R3Q/7mLkOD9ewCBDYD2k0WyZQtWYqF/2VvoNN2/uhI49J9CDN4OAm+wGMA0DbArA4ef27xl4+JwMtGggw==", + "version": "4.17.12", + "resolved": "https://registry.npmjs.org/@types/express-serve-static-core/-/express-serve-static-core-4.17.12.tgz", + "integrity": "sha512-EaEdY+Dty1jEU7U6J4CUWwxL+hyEGMkO5jan5gplfegUgCUsIUWqXxqw47uGjimeT4Qgkz/XUfwoau08+fgvKA==", "dev": true, "requires": { "@types/node": "*", @@ -277,9 +277,9 @@ "dev": true }, "@types/ioredis": { - "version": "4.17.3", - "resolved": "https://registry.npmjs.org/@types/ioredis/-/ioredis-4.17.3.tgz", - "integrity": "sha512-G0pN/WZb7OBMFksZOBcqATBUeBII00IZ7C9OW0bm7VG3XMXBI75stTXWLBxm6iNLQxdjFZgzThRbc3gBXBhZGw==", + "version": "4.17.4", + "resolved": "https://registry.npmjs.org/@types/ioredis/-/ioredis-4.17.4.tgz", + "integrity": "sha512-kb5+thmQJ7HHyOAnCOeqRJlF2fyvadHghnLLLKZzCNyShStJeIQtNGGDjA30gWqj6UFSDAWBfGEMKrFDrGfvzQ==", "dev": true, "requires": { "@types/node": "*" @@ -292,15 +292,15 @@ "dev": true }, "@types/mime": { - "version": "2.0.2", - "resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.2.tgz", - "integrity": "sha512-4kPlzbljFcsttWEq6aBW0OZe6BDajAmyvr2xknBG92tejQnvdGtT9+kXSZ580DqpxY9qG2xeQVF9Dq0ymUTo5Q==", + "version": "2.0.3", + "resolved": "https://registry.npmjs.org/@types/mime/-/mime-2.0.3.tgz", + "integrity": "sha512-Jus9s4CDbqwocc5pOAnh8ShfrnMcPHuJYzVcSUU7lrh8Ni5HuIqX3oilL86p3dlTrk0LzHRCgA/GQ7uNCw6l2Q==", "dev": true }, "@types/mongodb": { - "version": "3.5.26", - "resolved": "https://registry.npmjs.org/@types/mongodb/-/mongodb-3.5.26.tgz", - "integrity": "sha512-p0X2VJgIBNHfNBdZdzzG8eQ/3bf6mQoXDT0UhVyVEdSzXEa1+2pFcwGvEZp72sjztyBwfRKlgrXMjCVavLcuGg==", + "version": "3.5.27", + "resolved": "https://registry.npmjs.org/@types/mongodb/-/mongodb-3.5.27.tgz", + "integrity": "sha512-1jxKDgdfJEOO9zp+lv43p8jOqRs02xPrdUTzAZIVK9tVEySfCEmktL2jEu9A3wOBEOs18yKzpVIKUh8b8ALk3w==", "dev": true, "requires": { "@types/bson": "*", @@ -317,9 +317,9 @@ } }, "@types/node": { - "version": "14.6.2", - "resolved": "https://registry.npmjs.org/@types/node/-/node-14.6.2.tgz", - "integrity": "sha512-onlIwbaeqvZyniGPfdw/TEhKIh79pz66L1q06WUQqJLnAb6wbjvOtepLYTGHTqzdXgBYIE3ZdmqHDGsRsbBz7A==", + "version": "14.6.4", + "resolved": "https://registry.npmjs.org/@types/node/-/node-14.6.4.tgz", + "integrity": "sha512-Wk7nG1JSaMfMpoMJDKUsWYugliB2Vy55pdjLpmLixeyMi7HizW2I/9QoxsPCkXl3dO+ZOVqPumKaDUv5zJu2uQ==", "dev": true }, "@types/oauth": { @@ -363,9 +363,9 @@ } }, "@types/qs": { - "version": "6.9.3", - "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.3.tgz", - "integrity": "sha512-7s9EQWupR1fTc2pSMtXRQ9w9gLOcrJn+h7HOXw4evxyvVqMi4f+q7d2tnFe3ng3SNHjtK+0EzGMGFUQX4/AQRA==", + "version": "6.9.4", + "resolved": "https://registry.npmjs.org/@types/qs/-/qs-6.9.4.tgz", + "integrity": "sha512-+wYo+L6ZF6BMoEjtf8zB2esQsqdV6WsjRK/GP9WOgLPrq87PbNWgIxS76dS5uvl/QXtHGakZmwTznIfcPXcKlQ==", "dev": true }, "@types/range-parser": { @@ -384,9 +384,9 @@ } }, "@types/serve-static": { - "version": "1.13.4", - "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.4.tgz", - "integrity": "sha512-jTDt0o/YbpNwZbQmE/+2e+lfjJEJJR0I3OFaKQKPWkASkCoW3i6fsUnqudSMcNAfbtmADGu8f4MV4q+GqULmug==", + "version": "1.13.5", + "resolved": "https://registry.npmjs.org/@types/serve-static/-/serve-static-1.13.5.tgz", + "integrity": "sha512-6M64P58N+OXjU432WoLLBQxbA0LRGBCRm7aAGQJ+SMC1IMl0dgRVi9EFfoDcS2a7Xogygk/eGN94CfwU9UF7UQ==", "dev": true, "requires": { "@types/express-serve-static-core": "*", @@ -990,7 +990,7 @@ "dev": true }, "del-i18n": { - "version": "github:discordextremelist/i18n#c8a3fb9db819632306cb05505924b861d7f64a94", + "version": "github:discordextremelist/i18n#af3e710cd411e6e3436038e299ce163edeec3cbe", "from": "github:discordextremelist/i18n" }, "delayed-stream": { @@ -2772,9 +2772,9 @@ "dev": true }, "node-fetch": { - "version": "2.6.0", - "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.0.tgz", - "integrity": "sha512-8dG4H5ujfvFiqDmVu9fQ5bOHUC15JMjMY/Zumv26oOvvVJjM67KF8koCWIabKQ1GJIa9r2mMZscBq/TbdOcmNA==" + "version": "2.6.1", + "resolved": "https://registry.npmjs.org/node-fetch/-/node-fetch-2.6.1.tgz", + "integrity": "sha512-V4aYg89jEoVRxRb2fJdAg8FHvI7cEyYdVAh94HH0UIK8oJxUfkjlDQN9RbMx+bEjP7+ggMiFRprSti032Oipxw==" }, "node-gyp": { "version": "3.8.0", diff --git a/package.json b/package.json index ee1c2970..d8cb80d6 100644 --- a/package.json +++ b/package.json @@ -32,7 +32,7 @@ "monaco-editor": "^0.20.0", "mongodb": "~3.5.10", "morgan": "~1.10.0", - "node-fetch": "^2.6.0", + "node-fetch": "^2.6.1", "passport": "^0.4.1", "passport-discord": "^0.1.4", "request": "^2.88.2", @@ -48,13 +48,13 @@ "@types/cookie-session": "^2.0.41", "@types/datadog-metrics": "^0.6.0", "@types/ejs": "^3.0.4", - "@types/express": "^4.17.7", + "@types/express": "^4.17.8", "@types/http-errors": "^1.8.0", "@types/i18n": "^0.8.7", - "@types/ioredis": "^4.17.3", - "@types/mongodb": "^3.5.26", + "@types/ioredis": "^4.17.4", + "@types/mongodb": "^3.5.27", "@types/morgan": "^1.9.1", - "@types/node": "^14.6.2", + "@types/node": "^14.6.4", "@types/passport": "^1.0.4", "@types/passport-discord": "^0.1.3", "@types/sanitize-html": "^1.23.3", diff --git a/src/Routes/authentication.ts b/src/Routes/authentication.ts index a10af346..3505d99a 100644 --- a/src/Routes/authentication.ts +++ b/src/Routes/authentication.ts @@ -22,8 +22,9 @@ import { Request, Response } from "express"; import bodyParser from "body-parser"; import passport from "passport"; -import * as https from "https"; import { Strategy } from "passport-discord"; +import * as discord from "../Util/Services/discord"; +import { DiscordAPIError } from "discord.js"; import * as settings from "../../settings.json"; import * as tokenManager from "../Util/Services/adminTokenManager"; @@ -58,7 +59,7 @@ router.use( }) ); -router.get("/login/joinGuild", (req: Request, res: Response, next) => { +router.get("/login/joinGuild", (req: Request, res: Response) => { req.session.joinGuild = true; res.redirect("/auth/login/continue"); }); @@ -256,47 +257,26 @@ router.get( if (req.session.joinGuild && req.session.joinGuild === true) { req.session.joinGuild = false; - const data = JSON.stringify({ - access_token: req.user.accessToken - }); - - const options = { - hostname: "discord.com", - port: 443, - path: `/api/v6/guilds/${settings.guild.main}/members/${req.user.id}`, - method: "PUT", - headers: { - "Content-Type": "application/json", - "Content-Length": data.length, - Authorization: "Bot " + settings.secrets.discord.token - } - }; - - const msReq = https.request(options, (response) => { - if (response.statusCode === 403 && !req.user.impersonator) { - return res.status(403).render("status", { - title: res.__("common.error"), - status: 403, - subtitle: res.__("common.error.notMember"), - req, - type: "Error" - }); - } else next(); - }); - - msReq.on("error", (e) => { - console.error(e); - }); - - msReq.write(data); - msReq.end(); + discord.bot.api.guilds(settings.guild.main).members(req.user.id).put({ data: { access_token: req.user.accessToken } }) + .catch((error: DiscordAPIError) => { + console.error(error) + if (error.httpStatus === 403 && !req.user.impersonator) { + return res.status(403).render("status", { + title: res.__("common.error"), + status: 403, + subtitle: res.__("common.error.notMember"), + req, + type: "Error" + }); + } else next(); + }); } res.redirect(req.session.redirectTo || "/"); } ); -router.get("/logout", async (req: Request, res: Response, next) => { +router.get("/logout", async (req: Request, res: Response) => { if (!req.user.impersonator) { req.session.logoutJust = true; if (req.user.db.rank.admin) await tokenManager.tokenReset(req.user.id); diff --git a/src/Routes/bots.ts b/src/Routes/bots.ts index e87cdf9c..c831939d 100644 --- a/src/Routes/bots.ts +++ b/src/Routes/bots.ts @@ -39,13 +39,14 @@ import * as userCache from "../Util/Services/userCaching"; import * as libraryCache from "../Util/Services/libCaching"; import * as tokenManager from "../Util/Services/adminTokenManager"; import { URL } from "url"; +import { DiscordAPIError } from "discord.js"; const md = require("markdown-it")(); const Entities = require("html-entities").XmlEntities; const entities = new Entities(); const router = express.Router(); -router.get("/search", (req: Request, res: Response, next) => { +router.get("/search", (req: Request, res: Response) => { res.redirect("/search"); }); @@ -53,7 +54,7 @@ router.get( "/submit", variables, permission.auth, - async (req: Request, res: Response, next) => { + async (req: Request, res: Response) => { res.locals.premidPageInfo = res.__("premid.bots.submit"); res.render("templates/bots/submit", { @@ -75,7 +76,7 @@ router.post( variables, permission.auth, permission.member, - async (req: Request, res: Response, next) => { + async (req: Request, res: Response) => { res.locals.premidPageInfo = res.__("premid.bots.submit"); let error = false; @@ -94,433 +95,383 @@ router.post( errors: [res.__("common.error.bot.conflict")] }); - if (!req.body.id) - return res.status(400).json({ - error: true, - status: 400, - errors: [res.__("common.error.listing.arr.IDRequired")] - }); + if (!req.body.id) { + error = true + errors.push(res.__("common.error.listing.arr.IDRequired")) + } - if (isNaN(req.body.id) || req.body.id.includes(" ")) - return res.status(400).json({ - error: true, - status: 400, - errors: [res.__("common.error.bot.arr.invalidID")] - }); + if (isNaN(req.body.id) || req.body.id.includes(" ")) { + error = true + errors.push(res.__("common.error.bot.arr.invalidID")) + } - if (req.body.id.length > 32) - return res.status(400).json({ - error: true, - status: 400, - errors: [res.__("common.error.bot.arr.idTooLong")] - }); + if (req.body.id.length > 32) { + error = true + errors.push(res.__("common.error.bot.arr.idTooLong")) + } if (req.body.clientID) { - if (isNaN(req.body.clientID) || req.body.clientID.includes(" ")) - return res.status(400).json({ - error: true, - status: 400, - errors: [res.__("common.error.bot.arr.invalidClientID")] - }); - - if (req.body.clientID && req.body.clientID.length > 32) - return res.status(400).json({ - error: true, - status: 400, - errors: [res.__("common.error.bot.arr.clientIDTooLong")] - }); + if (isNaN(req.body.clientID) || req.body.clientID.includes(" ")) { + error = true + errors.push(res.__("common.error.bot.arr.invalidClientID")) + } - await fetch( - `https://discord.com/api/v6/users/${req.body.clientID}`, - { - method: "GET", - headers: { - Authorization: `Bot ${settings.secrets.discord.token}` - } - } - ).then((fetchRes: fetchRes) => { - if (fetchRes.status !== 404) { + if (req.body.clientID && req.body.clientID.length > 32) { + error = true + errors.push(res.__("common.error.bot.arr.clientIDTooLong")) + } + + discord.bot.api.users(req.body.clientID).get() + .then(() => { error = true - return res.status(400).json({ - error: true, - status: 400, - errors: [res.__("common.error.bot.arr.clientIDIsUser")] - }); - } - }); + errors.push(res.__("common.error.bot.arr.clientIDIsUser")) + }) + .catch(() => {}) } - if(error) return - - fetch(`https://discord.com/api/v6/users/${req.body.id}`, { - method: "GET", - headers: { Authorization: `Bot ${settings.secrets.discord.token}` } - }) - .then(async (fetchRes: fetchRes) => { - const bot = (await fetchRes.json()) as APIUser; - if ( - // @ts-expect-error - bot.code === RESTJSONErrorCodes.UnknownUser && - req.body.id - ) { - error = true; - errors.push(res.__("common.error.bot.arr.notFound")); - } else if (fetchRes.status === 400) { - error = true; - errors.push( - `${res.__( - "common.error.bot.arr.fetchError" - )}: ${JSON.stringify(bot)}` - ); - } else if (!bot.bot && req.body.id) { - error = true; - errors.push(res.__("common.error.bot.arr.isUser")); - } + if (req.body.invite === "") { + invite = `https://discord.com/api/oauth2/authorize?client_id=${ + req.body.clientID || req.body.id + }&scope=bot`; + } else { + if (typeof req.body.invite !== "string") { + error = true; + errors.push( + res.__("common.error.listing.arr.invite.invalid") + ); + } else if (req.body.invite.length > 2000) { + error = true; + errors.push( + res.__("common.error.listing.arr.invite.tooLong") + ); + } else if (!functions.isURL(req.body.invite)) { + error = true; + errors.push( + res.__("common.error.listing.arr.invite.urlInvalid") + ); + } else if (req.body.invite.includes("discordapp.com")) { + error = true; + errors.push( + res.__("common.error.listing.arr.invite.discordapp") + ); + } else { + invite = req.body.invite; + } + } - if (req.body.invite === "") { - invite = `https://discord.com/api/oauth2/authorize?client_id=${ - req.body.clientID || req.body.id - }&scope=bot`; - } else { - if (typeof req.body.invite !== "string") { - error = true; - errors.push( - res.__("common.error.listing.arr.invite.invalid") - ); - } else if (req.body.invite.length > 2000) { - error = true; - errors.push( - res.__("common.error.listing.arr.invite.tooLong") - ); - } else if (!functions.isURL(req.body.invite)) { - error = true; - errors.push( - res.__("common.error.listing.arr.invite.urlInvalid") - ); - } else if (req.body.invite.includes("discordapp.com")) { - error = true; - errors.push( - res.__("common.error.listing.arr.invite.discordapp") - ); - } else { - invite = req.body.invite; - } - } + if ( + req.body.supportServer && + !functions.isURL(req.body.supportServer) + ) { + error = true; + errors.push( + res.__( + "common.error.listing.arr.invalidURL.supportServer" + ) + ); + } - if ( - req.body.supportServer && - !functions.isURL(req.body.supportServer) - ) { - error = true; - errors.push( - res.__( - "common.error.listing.arr.invalidURL.supportServer" - ) - ); - } + if (req.body.website && !functions.isURL(req.body.website)) { + error = true; + errors.push( + res.__("common.error.listing.arr.invalidURL.website") + ); + } - if (req.body.website && !functions.isURL(req.body.website)) { - error = true; - errors.push( - res.__("common.error.listing.arr.invalidURL.website") - ); - } + if ( + req.body.donationUrl && + !functions.isURL(req.body.donationUrl) + ) { + error = true; + errors.push( + res.__("common.error.listing.arr.invalidURL.donation") + ); + } - if ( - req.body.donationUrl && - !functions.isURL(req.body.donationUrl) - ) { - error = true; - errors.push( - res.__("common.error.listing.arr.invalidURL.donation") - ); - } + if (req.body.repo && !functions.isURL(req.body.repo)) { + error = true; + errors.push( + res.__("common.error.listing.arr.invalidURL.repo") + ); + } - if (req.body.repo && !functions.isURL(req.body.repo)) { - error = true; - errors.push( - res.__("common.error.listing.arr.invalidURL.repo") - ); - } + if ( + req.body.invite && + functions.isURL(req.body.invite) && + Number( + new URL(req.body.invite).searchParams.get("permissions") + ) & 8 + ) { + error = true; + errors.push( + res.__("common.error.listing.arr.inviteHasAdmin") + ); + } - if ( - req.body.invite && - functions.isURL(req.body.invite) && - Number( - new URL(req.body.invite).searchParams.get("permissions") - ) & 8 - ) { - error = true; - errors.push( - res.__("common.error.listing.arr.inviteHasAdmin") - ); - } + if (req.body.banner && !functions.isURL(req.body.banner)) { + error = true; + errors.push( + res.__("common.error.listing.arr.invalidURL.banner") + ); + } - if (req.body.banner && !functions.isURL(req.body.banner)) { - error = true; - errors.push( - res.__("common.error.listing.arr.invalidURL.banner") - ); - } + if (req.body.widgetServer && !req.body.widgetChannel) { + error = true; + errors.push( + res.__( + "common.error.listing.arr.widgetbot.serverButNotChannel" + ) + ); + } - if (req.body.widgetServer && !req.body.widgetChannel) { - error = true; - errors.push( - res.__( - "common.error.listing.arr.widgetbot.serverButNotChannel" - ) - ); - } + if (req.body.widgetChannel && !req.body.widgetServer) { + error = true; + errors.push( + res.__( + "common.error.listing.arr.widgetbot.channelButNotServer" + ) + ); + } - if (req.body.widgetChannel && !req.body.widgetServer) { - error = true; - errors.push( - res.__( - "common.error.listing.arr.widgetbot.channelButNotServer" - ) - ); - } + if (req.body.widgetServer && req.body.widgetChannel) { + let fetchServer = true; + + if ( + isNaN(req.body.widgetServer) || + req.body.widgetServer.includes(" ") + ) { + error = true; + errors.push( + res.__( + "common.error.listing.arr.widgetbot.serverID.invalid" + ) + ); + fetchServer = false; + } + if ( + req.body.widgetServer && + req.body.widgetServer.length > 32 + ) { + error = true; + errors.push( + res.__( + "common.error.listing.arr.widgetbot.serverID.tooLong" + ) + ); + fetchServer = false; + } - if (req.body.widgetServer && req.body.widgetChannel) { - let fetchServer = true; + if (fetchServer) + await discord.bot.api.guilds(req.body.widgetServer).channels.get() + .catch((e: DiscordAPIError) => { + if([400, 404].includes(e.httpStatus)) { + error = true; + errors.push( + res.__( + "common.error.listing.arr.widgetbot.serverID.nonexistent" + ) + ); + fetchServer = false; + } + }) - if ( - isNaN(req.body.widgetServer) || - req.body.widgetServer.includes(" ") - ) { - error = true; - errors.push( - res.__( - "common.error.listing.arr.widgetbot.serverID.invalid" - ) - ); - fetchServer = false; - } - if ( - req.body.widgetServer && - req.body.widgetServer.length > 32 - ) { + if (fetchServer) + await fetch( + `https://stonks.widgetbot.io/api/graphql?query={guild(id:"${req.body.widgetServer}"){id}}` + ).then(async (fetchRes: fetchRes) => { + const { data } = await fetchRes.json(); + if (data && !data.guild?.id) { error = true; errors.push( res.__( - "common.error.listing.arr.widgetbot.serverID.tooLong" + "common.error.listing.arr.widgetbot.guildNotFound" ) ); - fetchServer = false; } + }); - if (fetchServer) - await fetch( - `https://discord.com/api/v6/guilds/${req.body.widgetServer}/channels`, - { - headers: { - Authorization: `Bot ${settings.secrets.discord.token}` - } - } - ).then((fetchRes: fetchRes) => { - if ( - fetchRes.status === 400 || - fetchRes.status === 404 - ) { - error = true; - errors.push( - res.__( - "common.error.listing.arr.widgetbot.serverID.nonexistent" - ) - ); - fetchServer = false; - } - }); + let fetchChannel = true; - if (fetchServer) - await fetch( - `https://stonks.widgetbot.io/api/graphql?query={guild(id:"${req.body.widgetServer}"){id}}` - ).then(async (fetchRes: fetchRes) => { - const { data } = await fetchRes.json(); - if (!data.guild?.id) { - error = true; - errors.push( - res.__( - "common.error.listing.arr.widgetbot.guildNotFound" - ) - ); - } - }); + if ( + isNaN(req.body.widgetChannel) || + req.body.widgetChannel.includes(" ") + ) { + error = true; + errors.push( + res.__( + "common.error.listing.arr.widgetbot.channelID.invalid" + ) + ); + fetchChannel = false; + } + if ( + req.body.widgetChannel && + req.body.widgetChannel.length > 32 + ) { + error = true; + errors.push( + res.__( + "common.error.listing.arr.widgetbot.channelID.tooLong" + ) + ); + fetchChannel = false; + } - let fetchChannel = true; + if (fetchChannel) + await discord.bot.api.channels(req.body.widgetChannel).get() + .catch((e: DiscordAPIError) => { + if([400, 404].includes(e.httpStatus)) { + error = true; + errors.push( + res.__( + "common.error.listing.arr.widgetbot.channelID.nonexistent" + ) + ); + fetchChannel = false; + } + }) - if ( - isNaN(req.body.widgetChannel) || - req.body.widgetChannel.includes(" ") - ) { - error = true; - errors.push( - res.__( - "common.error.listing.arr.widgetbot.channelID.invalid" - ) - ); - fetchChannel = false; - } - if ( - req.body.widgetChannel && - req.body.widgetChannel.length > 32 - ) { + if (fetchChannel) + await fetch( + `https://stonks.widgetbot.io/api/graphql?query={channel(id:"${req.body.widgetChannel}"){id}}` + ).then(async (fetchRes: fetchRes) => { + const { data } = await fetchRes.json(); + if (!data.channel?.id) { error = true; errors.push( res.__( - "common.error.listing.arr.widgetbot.channelID.tooLong" + "common.error.listing.arr.widgetbot.channelNotFound" ) ); - fetchChannel = false; } + }); + } - if (fetchChannel) - await fetch( - `https://discord.com/api/v6/channels/${req.body.widgetChannel}`, - { - headers: { - Authorization: `Bot ${settings.secrets.discord.token}` - } - } - ).then((fetchRes: fetchRes) => { - if ( - fetchRes.status === 400 || - fetchRes.status === 404 - ) { - error = true; - errors.push( - res.__( - "common.error.listing.arr.widgetbot.channelID.nonexistent" - ) - ); - fetchChannel = false; - } - }); + if (!req.body.shortDescription) { + error = true; + errors.push( + res.__("common.error.listing.arr.shortDescRequired") + ); + } - if (fetchChannel) - await fetch( - `https://stonks.widgetbot.io/api/graphql?query={channel(id:"${req.body.widgetChannel}"){id}}` - ).then(async (fetchRes: fetchRes) => { - const { data } = await fetchRes.json(); - if (!data.channel?.id) { - error = true; - errors.push( - res.__( - "common.error.listing.arr.widgetbot.channelNotFound" - ) - ); - } - }); - } + if (!req.body.longDescription) { + error = true; + errors.push( + res.__("common.error.listing.arr.longDescRequired") + ); + } - if (!req.body.shortDescription) { - error = true; - errors.push( - res.__("common.error.listing.arr.shortDescRequired") - ); - } + if ( + req.body.longDescription && + req.body.longDescription.length < 150 + ) { + error = true; + errors.push( + res.__("common.error.listing.arr.notAtMinChars", "150") + ); + } - if (!req.body.longDescription) { - error = true; - errors.push( - res.__("common.error.listing.arr.longDescRequired") - ); - } + if (req.body.longDescription.includes("http://")) { + error = true; + errors.push( + res.__("common.error.listing.arr.containsHttp") + ) + } - if ( - req.body.longDescription && - req.body.longDescription.length < 150 - ) { - error = true; - errors.push( - res.__("common.error.listing.arr.notAtMinChars", "150") - ); - } + if (!req.body.prefix) { + error = true; + errors.push( + res.__("common.error.listing.arr.prefixRequired") + ); + } - if (req.body.longDescription.includes("http://")) { - error = true; - errors.push( - res.__("common.error.listing.arr.containsHttp") + if (req.body.privacyPolicy) { + if ( + req.body.privacyPolicy.includes("discord.bot/privacy") + ) { + error = true; + errors.push( + res.__( + "common.error.listing.arr.privacyPolicy.placeholder" ) - } + ); + } + if ( + req.body.privacyPolicy.includes("discord.com/privacy") + ) { + error = true; + errors.push( + res.__( + "common.error.listing.arr.privacyPolicy.discord" + ) + ); + } + if (/(yardım|yardim)/.test(req.body.privacyPolicy)) { + error = true; + errors.push( + res.__( + "common.error.listing.arr.privacyPolicy.yardim" + ) + ); + } + if (req.body.privacyPolicy.includes("help")) { + error = true; + errors.push( + res.__( + "common.error.listing.arr.privacyPolicy.help" + ) + ); + } + } else { + error = true; + errors.push( + res.__("common.error.listing.arr.privacyPolicyRequired") + ); + } + + const library = libraryCache.hasLib(req.body.library) + ? req.body.library + : "Other"; + + let tags: string[] = []; + if (req.body.fun === true) tags.push("Fun"); + if (req.body.social === true) tags.push("Social"); + if (req.body.economy === true) tags.push("Economy"); + if (req.body.utility === true) tags.push("Utility"); + if (req.body.moderation === true) tags.push("Moderation"); + if (req.body.multipurpose === true) tags.push("Multipurpose"); + if (req.body.music === true) tags.push("Music"); - if (!req.body.prefix) { - error = true; - errors.push( - res.__("common.error.listing.arr.prefixRequired") - ); - } + let editors: any[]; - if (req.body.privacyPolicy) { - if ( - req.body.privacyPolicy.includes("discord.bot/privacy") - ) { - error = true; - errors.push( - res.__( - "common.error.listing.arr.privacyPolicy.placeholder" - ) - ); - } - if ( - req.body.privacyPolicy.includes("discord.com/privacy") - ) { - error = true; - errors.push( - res.__( - "common.error.listing.arr.privacyPolicy.discord" - ) - ); - } - if (req.body.privacyPolicy.includes("!yardım")) { - error = true; - errors.push( - res.__( - "common.error.listing.arr.privacyPolicy.yardim" - ) - ); - } - } else { - error = true; - errors.push( - res.__("common.error.listing.arr.privacyPolicyRequired") - ); - } + if (req.body.editors !== "") { + editors = [...new Set(req.body.editors.split(/\D+/g))]; + } else { + editors = []; + } - const library = libraryCache.hasLib(req.body.library) - ? req.body.library - : "Other"; - let tags: string[] = []; - if (req.body.fun === true) tags.push("Fun"); - if (req.body.social === true) tags.push("Social"); - if (req.body.economy === true) tags.push("Economy"); - if (req.body.utility === true) tags.push("Utility"); - if (req.body.moderation === true) tags.push("Moderation"); - if (req.body.multipurpose === true) tags.push("Multipurpose"); - if (req.body.music === true) tags.push("Music"); - - let editors: any[]; - - if (req.body.editors !== "") { - editors = [...new Set(req.body.editors.split(/\D+/g))]; - } else { - editors = []; - } + if (editors.includes(req.user.id)) { + error = true; + errors.push( + res.__("common.error.listing.arr.removeYourselfEditor") + ); + } - if (editors.includes(req.user.id)) { - error = true; - errors.push( - res.__("common.error.listing.arr.removeYourselfEditor") - ); - } + if (error === true) + return res.status(400).json({ + error: true, + status: 400, + errors: errors + }); - if (error === true) { + discord.bot.api.users(req.body.id).get() + .then(async (bot: APIUser) => { + if (!bot.bot) return res.status(400).json({ error: true, status: 400, - errors: errors + errors: [res.__("common.error.bot.arr.isUser")] }); - } await global.db.collection("bots").insertOne({ _id: req.body.id, @@ -584,7 +535,7 @@ router.post( siteBot: false, archived: false } - }); + } as delBot); (discord.bot.channels.cache.get( settings.channels.webLog @@ -663,7 +614,7 @@ router.post( siteBot: false, archived: false } - } + } as delBot } }); await botCache.updateBot(req.params.id); @@ -676,286 +627,25 @@ router.post( errors: [] }); }) - .catch(async () => { - if (req.body.invite !== "") { - if (typeof req.body.invite !== "string") { - error = true; - errors.push( - res.__("common.error.listing.arr.invite.invalid") - ); - } else if (req.body.invite.length > 2000) { - error = true; - errors.push( - res.__("common.error.listing.arr.invite.tooLong") - ); - } else if (!functions.isURL(req.body.invite)) { - error = true; - errors.push(res.__("Invite needs to be a valid URL.")); - } else { - invite = req.body.invite; - } - } - - if ( - req.body.invite && - functions.isURL(req.body.invite) && - Number( - new URL(req.body.invite).searchParams.get("permissions") - ) & 8 - ) { - error = true; - errors.push( - res.__("common.error.listing.arr.inviteHasAdmin") - ); - } - - if (req.body.widgetServer && !req.body.widgetChannel) { - error = true; - errors.push( - res.__( - "common.error.listing.arr.widgetbot.serverButNotChannel" - ) - ); - } - - if (req.body.widgetChannel && !req.body.widgetServer) { - error = true; - errors.push( - res.__( - "common.error.listing.arr.widgetbot.channelButNotServer" - ) - ); - } - - if (req.body.widgetServer && req.body.widgetChannel) { - let fetchServer = true; - - if ( - isNaN(req.body.widgetServer) || - req.body.widgetServer.includes(" ") - ) { - error = true; - errors.push( - res.__( - "common.error.listing.arr.widgetbot.serverID.invalid" - ) - ); - fetchServer = false; - } - if ( - req.body.widgetServer && - req.body.widgetServer.length > 32 - ) { - error = true; - errors.push( - res.__( - "common.error.listing.arr.widgetbot.serverID.tooLong" - ) - ); - fetchServer = false; - } - - if (fetchServer) - await fetch( - `https://discord.com/api/v6/guilds/${req.body.widgetServer}/channels`, - { - headers: { - Authorization: `Bot ${settings.secrets.discord.token}` - } - } - ).then((fetchRes: fetchRes) => { - if ( - fetchRes.status === 400 || - fetchRes.status === 404 - ) { - error = true; - errors.push( - res.__( - "common.error.listing.arr.widgetbot.serverID.nonexistent" - ) - ); - fetchServer = false; - } - }); - - if (fetchServer) - await fetch( - `https://stonks.widgetbot.io/api/graphql?query={guild(id:"${req.body.widgetServer}"){id}}` - ).then(async (fetchRes: fetchRes) => { - const { data } = await fetchRes.json(); - if (!data.guild?.id) { - error = true; - errors.push( - res.__( - "common.error.listing.arr.widgetbot.guildNotFound" - ) - ); - } - }); - - let fetchChannel = true; - - if ( - isNaN(req.body.widgetChannel) || - req.body.widgetChannel.includes(" ") - ) { - error = true; - errors.push( - res.__( - "common.error.listing.arr.widgetbot.channelID.invalid" - ) - ); - fetchChannel = false; - } - if ( - req.body.widgetChannel && - req.body.widgetChannel.length > 32 - ) { - error = true; - errors.push( - res.__( - "common.error.listing.arr.widgetbot.channelID.tooLong" - ) - ); - fetchChannel = false; - } - - if (fetchChannel) - await fetch( - `https://discord.com/api/v6/channels/${req.body.widgetChannel}`, - { - headers: { - Authorization: `Bot ${settings.secrets.discord.token}` - } - } - ).then((fetchRes: fetchRes) => { - if ( - fetchRes.status === 400 || - fetchRes.status === 404 - ) { - error = true; - errors.push( - res.__( - "common.error.listing.arr.widgetbot.channelID.nonexistent" - ) - ); - fetchChannel = false; - } - }); - - if (fetchChannel) - await fetch( - `https://stonks.widgetbot.io/api/graphql?query={channel(id:"${req.body.widgetChannel}"){id}}` - ).then(async (fetchRes: fetchRes) => { - const { data } = await fetchRes.json(); - if (!data.channel?.id) { - error = true; - errors.push( - res.__( - "common.error.listing.arr.widgetbot.channelNotFound" - ) - ); - } - }); - } - - if (!req.body.shortDescription) { - error = true; - errors.push( - res.__("common.error.listing.arr.shortDescRequired") - ); - } - - if (!req.body.longDescription) { - error = true; - errors.push( - res.__("common.error.listing.arr.longDescRequired") - ); - } - - if ( - req.body.longDescription && - req.body.longDescription.length < 150 - ) { - error = true; - errors.push( - res.__("common.error.listing.arr.notAtMinChars", "150") - ); - } - - if (req.body.longDescription.includes("http://")) { - error = true; - errors.push( - res.__("common.error.listing.arr.containsHttp") - ) - } - - if (!req.body.prefix) { - error = true; - errors.push( - res.__("common.error.listing.arr.prefixRequired") - ); - } - - if (req.body.privacyPolicy) { - if ( - req.body.privacyPolicy.includes("discord.bot/privacy") - ) { - error = true; - errors.push( - res.__( - "common.error.listing.arr.privacyPolicy.placeholder" - ) - ); - } - - if ( - req.body.privacyPolicy.includes("discord.com/privacy") - ) { - error = true; - errors.push( - res.__( - "common.error.listing.arr.privacyPolicy.discord" - ) - ); - } - - let test: string; - if (["yardım", "yardim"].some(test.includes.bind(req.body.privacyPolicy))) { - error = true; - errors.push( - res.__( - "common.error.listing.arr.privacyPolicy.yardim" - ) - ); - } - - if (req.body.privacyPolicy.includes("help")) { - error = true; - errors.push( - res.__( - "common.error.listing.arr.privacyPolicy.help" - ) - ); - } - } else { - error = true; - errors.push( - res.__("common.error.listing.arr.privacyPolicyRequired") - ); - } + .catch((error: DiscordAPIError) => { + if(error.code === RESTJSONErrorCodes.UnknownUser) + return res.status(400).json({ + error: true, + status: 400, + errors: [res.__("common.error.bot.arr.notFound")] + }); return res.status(400).json({ error: true, status: 400, - errors: errors + errors: [res.__("common.error.bot.arr.fetchError"), `${error.name}: ${error.message}`, `${error.httpStatus} ${error.method} ${error.path}`] }); }); } ); /* TODO: Add preview for long description on edit & submit page -router.post("/preview_post", async (req: Request, res: Response, next) => { +router.post("/preview_post", async (req: Request, res: Response) => { const dirty = entities.decode(md.render(req.body.longDesc)); const clean = sanitizeHtml(dirty, { @@ -1007,7 +697,7 @@ router.get( "/:id/tokenreset", variables, permission.auth, - async (req: Request, res: Response, next) => { + async (req: Request, res: Response) => { const botExists = await global.db .collection("bots") .findOne({ _id: req.params.id }); @@ -1068,7 +758,7 @@ router.post( "/:id/setvanity", variables, permission.auth, - async (req: Request, res: Response, next) => { + async (req: Request, res: Response) => { const botExists = await global.db .collection("bots") .findOne({ _id: req.params.id }); @@ -1229,7 +919,7 @@ router.get( "/:id/edit", variables, permission.auth, - async (req: Request, res: Response, next) => { + async (req: Request, res: Response) => { const botExists = await global.db .collection("bots") .findOne({ _id: req.params.id }); @@ -1282,7 +972,7 @@ router.post( variables, permission.auth, permission.member, - async (req: Request, res: Response, next) => { + async (req: Request, res: Response) => { let error = false; let errors = []; @@ -1295,24 +985,15 @@ router.post( error = true; errors.push(res.__("common.error.bot.arr.clientIDTooLong")); } - if (req.body.clientID !== req.params.id) - await fetch( - `https://discord.com/api/v6/users/${req.body.clientID}`, - { - method: "GET", - headers: { - Authorization: `Bot ${settings.secrets.discord.token}` - } - } - ).then((fetchRes: fetchRes) => { - if (fetchRes.status !== 404) { + discord.bot.api.users(req.body.clientID).get() + .then(() => { error = true; errors.push( res.__("common.error.bot.arr.clientIDIsUser") ); - } - }); + }) + .catch(() => {}) } const botExists: delBot | undefined = await global.db @@ -1447,31 +1128,25 @@ router.post( } if (fetchServer) - await fetch( - `https://discord.com/api/v6/guilds/${req.body.widgetServer}/channels`, - { - headers: { - Authorization: `Bot ${settings.secrets.discord.token}` + await discord.bot.api.guilds(req.body.widgetServer).channels.get() + .catch((e: DiscordAPIError) => { + if([400, 404].includes(e.httpStatus)) { + error = true; + errors.push( + res.__( + "common.error.listing.arr.widgetbot.serverID.nonexistent" + ) + ); + fetchServer = false; } - } - ).then((fetchRes: fetchRes) => { - if (fetchRes.status === 400 || fetchRes.status === 404) { - error = true; - errors.push( - res.__( - "common.error.listing.arr.widgetbot.serverID.nonexistent" - ) - ); - fetchServer = false; - } - }); + }) if (fetchServer) await fetch( `https://stonks.widgetbot.io/api/graphql?query={guild(id:"${req.body.widgetServer}"){id}}` ).then(async (fetchRes: fetchRes) => { const { data } = await fetchRes.json(); - if (!data.guild?.id) { + if (data && !data.guild?.id) { error = true; errors.push( res.__( @@ -1506,24 +1181,18 @@ router.post( } if (fetchChannel) - await fetch( - `https://discord.com/api/v6/channels/${req.body.widgetChannel}`, - { - headers: { - Authorization: `Bot ${settings.secrets.discord.token}` + await discord.bot.api.channels(req.body.widgetChannel).get() + .catch((e: DiscordAPIError) => { + if([400, 404].includes(e.httpStatus)) { + error = true; + errors.push( + res.__( + "common.error.listing.arr.widgetbot.channelID.nonexistent" + ) + ); + fetchChannel = false; } - } - ).then((fetchRes: fetchRes) => { - if (fetchRes.status === 400 || fetchRes.status === 404) { - error = true; - errors.push( - res.__( - "common.error.listing.arr.widgetbot.channelID.nonexistent" - ) - ); - fetchChannel = false; - } - }); + }) if (fetchChannel) await fetch( @@ -1593,8 +1262,7 @@ router.post( ); } - let test: string; - if (["yardım", "yardim"].some(test.includes.bind(req.body.privacyPolicy))) { + if (/(yardım|yardim)/.test(req.body.privacyPolicy)) { error = true; errors.push( res.__( @@ -1658,12 +1326,8 @@ router.post( }); } - await fetch(`https://discord.com/api/v6/users/${req.params.id}`, { - method: "GET", - headers: { Authorization: `Bot ${settings.secrets.discord.token}` } - }) - .then(async (fetchRes: fetchRes) => { - const bot = (await fetchRes.json()) as APIUser; + discord.bot.api.users(req.params.id).get() + .then(async (bot: APIUser) => { await global.db.collection("bots").updateOne( { _id: req.params.id }, { @@ -1750,7 +1414,7 @@ router.post( options: botExists.widgetbot.options, server: botExists.widgetbot.server } - }, + } as delBot, new: { clientID: req.body.clientID, name: bot.username, @@ -1786,16 +1450,23 @@ router.post( options: req.body.widgetOptions, server: req.body.widgetServer } - } + } as delBot } }); await botCache.updateBot(req.params.id); }) - .catch((_) => { - return res.status(502).json({ + .catch((error: DiscordAPIError) => { + if(error.code === RESTJSONErrorCodes.UnknownUser) + return res.status(400).json({ + error: true, + status: 400, + errors: [res.__("common.error.bot.arr.notFound")] + }); + + return res.status(400).json({ error: true, - status: 502, - errors: [res.__("common.error.dapiFail")] + status: 400, + errors: [res.__("common.error.bot.arr.fetchError"), `${error.name}: ${error.message}`, `${error.httpStatus} ${error.method} ${error.path}`] }); }); @@ -1825,7 +1496,7 @@ router.post( } ); -router.get("/:id", variables, async (req: Request, res: Response, next) => { +router.get("/:id", variables, async (req: Request, res: Response) => { res.locals.pageType = { server: false, bot: true, @@ -1952,7 +1623,7 @@ router.get( variables, permission.auth, permission.admin, - async (req: Request, res: Response, next) => { + async (req: Request, res: Response) => { if (req.params.id === "@me") { if (!req.user) return res.redirect("/auth/login"); req.params.id = req.user.id; @@ -1980,7 +1651,7 @@ router.get( "/:id/upvote", variables, permission.auth, - async (req: Request, res: Response, next) => { + async (req: Request, res: Response) => { let bot = await global.db .collection("bots") .findOne({ _id: req.params.id }); @@ -2093,7 +1764,7 @@ router.get( "/:id/downvote", variables, permission.auth, - async (req: Request, res: Response, next) => { + async (req: Request, res: Response) => { let bot = await global.db .collection("bots") .findOne({ _id: req.params.id }); @@ -2206,7 +1877,7 @@ router.get( "/:id/delete", variables, permission.auth, - async (req: Request, res: Response, next) => { + async (req: Request, res: Response) => { let bot = await global.db .collection("bots") .findOne({ _id: req.params.id }); @@ -2269,7 +1940,7 @@ router.get( "/:id/resubmit", variables, permission.auth, - async (req: Request, res: Response, next) => { + async (req: Request, res: Response) => { const botExists = await global.db .collection("bots") .findOne({ _id: req.params.id }); @@ -2326,7 +1997,7 @@ router.post( variables, permission.auth, permission.member, - async (req: Request, res: Response, next) => { + async (req: Request, res: Response) => { let error = false; let errors = []; @@ -2346,24 +2017,16 @@ router.post( }); if (req.body.clientID !== req.params.id) - await fetch( - `https://discord.com/api/v6/users/${req.body.clientID}`, - { - method: "GET", - headers: { - Authorization: `Bot ${settings.secrets.discord.token}` - } - } - ).then((fetchRes: fetchRes) => { - if (fetchRes.status !== 404) + discord.bot.api.users(req.body.clientID).get() + .then(() => { + error = true return res.status(400).json({ error: true, status: 400, - errors: [ - res.__("common.error.bot.arr.clientIDIsUser") - ] + errors: [res.__("common.error.bot.arr.clientIDIsUser")] }); - }); + }) + .catch(() => {}) } const botExists: delBot | undefined = await global.db @@ -2507,31 +2170,25 @@ router.post( } if (fetchServer) - await fetch( - `https://discord.com/api/v6/guilds/${req.body.widgetServer}/channels`, - { - headers: { - Authorization: `Bot ${settings.secrets.discord.token}` + await discord.bot.api.guilds(req.body.widgetServer).channels.get() + .catch((e: DiscordAPIError) => { + if([400, 404].includes(e.httpStatus)) { + error = true; + errors.push( + res.__( + "common.error.listing.arr.widgetbot.serverID.nonexistent" + ) + ); + fetchServer = false; } - } - ).then((fetchRes: fetchRes) => { - if (fetchRes.status === 400 || fetchRes.status === 404) { - error = true; - errors.push( - res.__( - "common.error.listing.arr.widgetbot.serverID.nonexistent" - ) - ); - fetchServer = false; - } - }); + }) if (fetchServer) await fetch( `https://stonks.widgetbot.io/api/graphql?query={guild(id:"${req.body.widgetServer}"){id}}` ).then(async (fetchRes: fetchRes) => { const { data } = await fetchRes.json(); - if (!data.guild?.id) { + if (data && !data.guild?.id) { error = true; errors.push( res.__( @@ -2566,24 +2223,18 @@ router.post( } if (fetchChannel) - await fetch( - `https://discord.com/api/v6/channels/${req.body.widgetChannel}`, - { - headers: { - Authorization: `Bot ${settings.secrets.discord.token}` + await discord.bot.api.channels(req.body.widgetChannel).get() + .catch((e: DiscordAPIError) => { + if([400, 404].includes(e.httpStatus)) { + error = true; + errors.push( + res.__( + "common.error.listing.arr.widgetbot.channelID.nonexistent" + ) + ); + fetchChannel = false; } - } - ).then((fetchRes: fetchRes) => { - if (fetchRes.status === 400 || fetchRes.status === 404) { - error = true; - errors.push( - res.__( - "common.error.listing.arr.widgetbot.channelID.nonexistent" - ) - ); - fetchChannel = false; - } - }); + }) if (fetchChannel) await fetch( @@ -2653,8 +2304,7 @@ router.post( ); } - let test: string; - if (["yardım", "yardim"].some(test.includes.bind(req.body.privacyPolicy))) { + if (/(yardım|yardim)/.test(req.body.privacyPolicy)) { error = true; errors.push( res.__( @@ -2705,20 +2355,15 @@ router.post( ); } - if (error === true) { + if (error === true) return res.status(400).json({ error: true, status: 400, errors: errors }); - } - await fetch(`https://discord.com/api/v6/users/${req.params.id}`, { - method: "GET", - headers: { Authorization: `Bot ${settings.secrets.discord.token}` } - }) - .then(async (fetchRes: fetchRes) => { - const bot = (await fetchRes.json()) as APIUser; + discord.bot.api.users(req.params.id).get() + .then(async (bot: APIUser) => { await global.db.collection("bots").updateOne( { _id: req.params.id }, { @@ -2800,7 +2445,7 @@ router.post( status: { archived: true } - }, + } as delBot, new: { clientID: req.body.clientID, name: bot.username, @@ -2839,16 +2484,23 @@ router.post( status: { archived: false } - } + } as delBot } }); await botCache.updateBot(req.params.id); }) - .catch((_) => { - return res.status(502).json({ + .catch((error: DiscordAPIError) => { + if(error.code === RESTJSONErrorCodes.UnknownUser) + return res.status(400).json({ + error: true, + status: 400, + errors: [res.__("common.error.bot.arr.notFound")] + }); + + return res.status(400).json({ error: true, - status: 502, - errors: [res.__("common.error.dapiFail")] + status: 400, + errors: [res.__("common.error.bot.arr.fetchError"), `${error.name}: ${error.message}`, `${error.httpStatus} ${error.method} ${error.path}`] }); }); @@ -2883,7 +2535,7 @@ router.get( variables, permission.auth, permission.mod, - async (req: Request, res: Response, next) => { + async (req: Request, res: Response) => { const bot: delBot | undefined = await global.db .collection("bots") .findOne({ _id: req.params.id }); @@ -3017,7 +2669,7 @@ router.get( variables, permission.auth, permission.assistant, - async (req: Request, res: Response, next) => { + async (req: Request, res: Response) => { const bot: delBot | undefined = await global.db .collection("bots") .findOne({ _id: req.params.id }); @@ -3095,7 +2747,7 @@ router.get( variables, permission.auth, permission.assistant, - async (req: Request, res: Response, next) => { + async (req: Request, res: Response) => { const bot: delBot | undefined = await global.db .collection("bots") .findOne({ _id: req.params.id }); @@ -3146,7 +2798,7 @@ router.get( variables, permission.auth, permission.mod, - async (req: Request, res: Response, next) => { + async (req: Request, res: Response) => { const bot: delBot | undefined = await global.db .collection("bots") .findOne({ _id: req.params.id }); @@ -3191,7 +2843,7 @@ router.post( variables, permission.auth, permission.mod, - async (req: Request, res: Response, next) => { + async (req: Request, res: Response) => { const bot: delBot | undefined = await global.db .collection("bots") .findOne({ _id: req.params.id }); @@ -3305,7 +2957,7 @@ router.get( variables, permission.auth, permission.mod, - async (req: Request, res: Response, next) => { + async (req: Request, res: Response) => { const bot: delBot | undefined = await global.db .collection("bots") .findOne({ _id: req.params.id }); @@ -3345,7 +2997,7 @@ router.post( variables, permission.auth, permission.mod, - async (req: Request, res: Response, next) => { + async (req: Request, res: Response) => { const bot: delBot | undefined = await global.db .collection("bots") .findOne({ _id: req.params.id }); @@ -3460,7 +3112,7 @@ router.get( variables, permission.auth, permission.mod, - async (req: Request, res: Response, next) => { + async (req: Request, res: Response) => { const bot: delBot | undefined = await global.db .collection("bots") .findOne({ _id: req.params.id }); @@ -3500,7 +3152,7 @@ router.post( variables, permission.auth, permission.mod, - async (req: Request, res: Response, next) => { + async (req: Request, res: Response) => { const bot: delBot | undefined = await global.db .collection("bots") .findOne({ _id: req.params.id }); @@ -3630,12 +3282,8 @@ router.get( const bot = botExists; - await fetch(`https://discord.com/api/v6/users/${req.params.id}`, { - method: "GET", - headers: { Authorization: `Bot ${settings.secrets.discord.token}` } - }) - .then(async (fetchRes: fetchRes) => { - const bot = (await fetchRes.json()) as APIUser; + discord.bot.api.users(req.params.id).get() + .then(async (bot: APIUser) => { await global.db.collection("bots").updateOne( { _id: req.params.id }, { @@ -3646,7 +3294,7 @@ router.get( hash: bot.avatar, url: `https://cdn.discordapp.com/avatars/${req.params.id}/${bot.avatar}` } - } + } as delBot } ); @@ -3664,7 +3312,7 @@ router.get( hash: botExists.avatar.hash, url: botExists.avatar.url } - }, + } as delBot, new: { name: bot.username, flags: bot.public_flags, @@ -3672,16 +3320,23 @@ router.get( hash: bot.avatar, url: `https://cdn.discordapp.com/avatars/${req.params.id}/${bot.avatar}` } - } + } as delBot } }); await botCache.updateBot(req.params.id); }) - .catch((_) => { - return res.status(502).json({ + .catch((error: DiscordAPIError) => { + if(error.code === RESTJSONErrorCodes.UnknownUser) + return res.status(400).json({ + error: true, + status: 400, + errors: [res.__("common.error.bot.arr.notFound")] + }); + + return res.status(400).json({ error: true, - status: 502, - errors: [res.__("common.error.dapiFail")] + status: 400, + errors: [res.__("common.error.bot.arr.fetchError"), `${error.name}: ${error.message}`, `${error.httpStatus} ${error.method} ${error.path}`] }); }); diff --git a/src/Routes/servers.ts b/src/Routes/servers.ts index d723a261..5165a141 100644 --- a/src/Routes/servers.ts +++ b/src/Routes/servers.ts @@ -23,7 +23,7 @@ import { Response as fetchRes } from "../../@types/fetch"; import { APIInvite, RESTJSONErrorCodes } from "discord-api-types/v6"; import * as fetch from "node-fetch"; -import * as Discord from "discord.js"; +import { TextChannel, DiscordAPIError } from "discord.js"; import sanitizeHtml from "sanitize-html"; import * as settings from "../../settings.json"; @@ -45,7 +45,7 @@ router.get( "/submit", variables, permission.auth, - (req: Request, res: Response, next) => { + (req: Request, res: Response) => { res.locals.premidPageInfo = res.__("premid.servers.submit"); res.render("templates/servers/submit", { @@ -60,186 +60,163 @@ router.post( "/submit", variables, permission.auth, - async (req: Request, res: Response, next) => { + async (req: Request, res: Response) => { res.locals.premidPageInfo = res.__("premid.servers.submit"); let error = false; let errors: string[] = []; - if (req.body.invite.includes(" ")) - return res.status(400).json({ - error: true, - status: 400, - errors: [res.__("common.error.listing.arr.invite.invalid")] - }); + if (!req.body.invite || typeof req.body.invite !== "string" || req.body.invite.includes(" ")) { + error = true + errors.push(res.__("common.error.listing.arr.invite.invalid")) + } + + if(req.body.invite.length > 2000) { + error = true + errors.push(res.__("common.error.listing.arr.invite.tooLong")) + } + + if(functions.isURL(req.body.invite)) { + error = true + errors.push(res.__("common.error.listing.arr.invite.isURL")) + } - fetch(`https://discord.com/api/v6/invites/${req.body.invite}`, { - method: "GET", - headers: { Authorization: `Bot ${settings.secrets.discord.token}` } - }) - .then(async (fetchRes: fetchRes) => { - const invite = (await fetchRes.json()) as APIInvite; - - // @ts-expect-error - if (invite.code !== RESTJSONErrorCodes.UnknownInvite) { - const serverExists: - | delServer - | undefined = await global.db - .collection("servers") - .findOne({ _id: invite.guild.id }); - if (serverExists) - return res.status(409).json({ - error: true, - status: 409, - errors: [res.__("common.error.server.conflict")] - }); - - if (!req.body.longDescription) { - error = true; - errors.push( - res.__("common.error.listing.arr.longDescRequired") - ); - } + if(req.body.invite.includes("discord.gg")) { + error = true + errors.push(res.__("common.error.server.arr.invite.dgg")) + } + + if (req.body.website && !functions.isURL(req.body.website)) { + error = true; + errors.push( + res.__("common.error.listing.arr.invalidURL.website") + ); + } - if (!req.body.shortDescription) { - error = true; - errors.push( - res.__("common.error.listing.arr.shortDescRequired") - ); - } - } else { - error = true; - errors.push( - res.__("common.error.listing.arr.invite.invalid") - ); - } + if ( + req.body.donationUrl && + !functions.isURL(req.body.donationUrl) + ) { + error = true; + errors.push( + res.__("common.error.listing.arr.invalidURL.donation") + ); + } - if (req.body.website && !functions.isURL(req.body.website)) { - error = true; - errors.push( - res.__("common.error.listing.arr.invalidURL.website") - ); - } + if (req.body.previewChannel) { + let fetchChannel = true; - if ( - req.body.donationUrl && - !functions.isURL(req.body.donationUrl) - ) { - error = true; - errors.push( - res.__("common.error.listing.arr.invalidURL.donation") - ); - } + if ( + isNaN(req.body.previewChannel) || + req.body.previewChannel.includes(" ") + ) { + error = true; + errors.push( + res.__( + "common.error.server.arr.previewChannel.invalid" + ) + ); + fetchChannel = false; + } + if ( + req.body.previewChannel && + req.body.previewChannel.length > 32 + ) { + error = true; + errors.push( + res.__( + "common.error.server.arr.previewChannel.tooLong" + ) + ); + fetchChannel = false; + } - if (req.body.previewChannel) { - let fetchChannel = true; + if (fetchChannel) + await discord.bot.api.channels(req.body.previewChannel).get() + .catch((e: DiscordAPIError) => { + if([400, 404].includes(e.httpStatus)) { + error = true; + errors.push( + res.__( + "common.error.server.arr.previewChannel.nonexistent" + ) + ); + fetchChannel = false; + } + }) - if ( - isNaN(req.body.previewChannel) || - req.body.previewChannel.includes(" ") - ) { - error = true; - errors.push( - res.__( - "common.error.server.arr.previewChannel.invalid" - ) - ); - fetchChannel = false; - } - if ( - req.body.previewChannel && - req.body.previewChannel.length > 32 - ) { + if (fetchChannel) + await fetch( + `https://stonks.widgetbot.io/api/graphql?query={channel(id:"${req.body.previewChannel}"){id}}` + ).then(async (fetchRes: fetchRes) => { + const { data } = await fetchRes.json(); + if (!data.channel?.id) { error = true; errors.push( res.__( - "common.error.server.arr.previewChannel.tooLong" + "common.error.listing.arr.widgetbot.channelNotFound" ) ); - fetchChannel = false; } + }); + } - if (fetchChannel) - await fetch( - `https://discord.com/api/v6/channels/${req.body.previewChannel}`, - { - headers: { - Authorization: `Bot ${settings.secrets.discord.token}` - } - } - ).then((fetchRes: fetchRes) => { - if ( - fetchRes.status === 400 || - fetchRes.status === 404 - ) { - error = true; - errors.push( - res.__( - "common.error.server.arr.previewChannel.invalid" - ) - ); - fetchChannel = false; - } - }); - - if (fetchChannel) - await fetch( - `https://stonks.widgetbot.io/api/graphql?query={channel(id:"${req.body.previewChannel}"){id}}` - ).then(async (fetchRes: fetchRes) => { - const { data } = await fetchRes.json(); - if (!data.channel?.id) { - error = true; - errors.push( - res.__( - "common.error.listing.arr.widgetbot.channelNotFound" - ) - ); - } - }); - } + if (!req.body.shortDescription) { + error = true; + errors.push( + res.__("common.error.listing.arr.shortDescRequired") + ); + } - if (!req.body.shortDescription) { - error = true; - errors.push( - res.__("common.error.listing.arr.shortDescRequired") - ); - } + if (!req.body.longDescription) { + error = true; + errors.push( + res.__("common.error.listing.arr.longDescRequired") + ); + } - if (!req.body.longDescription) { - error = true; - errors.push( - res.__("common.error.listing.arr.longDescRequired") - ); - } + let tags: string[] = []; - let tags: string[] = []; - - if (req.body.gaming === true) tags.push("Gaming"); - if (req.body.music === true) tags.push("Music"); - if (req.body.mediaEntertain === "on") - tags.push("Media & Entertainment"); - if (req.body.createArts === true) tags.push("Creative Arts"); - if (req.body.sciTech === true) tags.push("Science & Tech"); - if (req.body.edu === true) tags.push("Education"); - if (req.body.fashBeaut === true) tags.push("Fashion & Beauty"); - - if (req.body.relIdentity === "on") - tags.push("Relationships & Identity"); - if (req.body.travelCuis === true) tags.push("Travel & Food"); - if (req.body.fitHealth === true) tags.push("Fitness & Health"); - if (req.body.finance === true) tags.push("Finance"); - - let reviewRequired = false; - if (req.body.lgbt === true) { - tags.push("LGBT"); - reviewRequired = true; - } + if (req.body.gaming === true) tags.push("Gaming"); + if (req.body.music === true) tags.push("Music"); + if (req.body.mediaEntertain === true) + tags.push("Media & Entertainment"); + if (req.body.createArts === true) tags.push("Creative Arts"); + if (req.body.sciTech === true) tags.push("Science & Tech"); + if (req.body.edu === true) tags.push("Education"); + if (req.body.fashBeaut === true) tags.push("Fashion & Beauty"); - if (error === true) - return res.status(400).json({ + if (req.body.relIdentity === true) + tags.push("Relationships & Identity"); + if (req.body.travelCuis === true) tags.push("Travel & Food"); + if (req.body.fitHealth === true) tags.push("Fitness & Health"); + if (req.body.finance === true) tags.push("Finance"); + + let reviewRequired = false; + if (req.body.lgbt === true) { + tags.push("LGBT"); + reviewRequired = true; + } + + if (error === true) + return res.status(400).json({ + error: true, + status: 400, + errors: errors + }); + + discord.bot.api.invites(req.body.invite).get() + .then(async (invite: APIInvite) => { + const serverExists: + | delServer + | undefined = await global.db + .collection("servers") + .findOne({ _id: invite.guild.id }); + if (serverExists) + return res.status(409).json({ error: true, - status: 400, - errors: errors + status: 409, + errors: [res.__("common.error.server.conflict")] }); await global.db.collection("servers").insertOne({ @@ -265,11 +242,11 @@ router.post( status: { reviewRequired: reviewRequired } - }); + } as delServer); (discord.bot.channels.cache.get( settings.channels.webLog - ) as Discord.TextChannel).send( + ) as TextChannel).send( `${settings.emoji.addBot} **${functions.escapeFormatting( req.user.db.fullUsername )}** \`(${ @@ -310,7 +287,7 @@ router.post( status: { reviewRequired: reviewRequired } - } + } as delServer } }); @@ -325,78 +302,24 @@ router.post( id: invite.guild.id }); }) - .catch(async (fetchRes: fetchRes) => { - if (!req.body.invite) { - error = true; - errors.push( - res.__("common.error.listing.arr.invite.invalid") - ); - } else { - if (typeof req.body.invite !== "string") { - error = true; - errors.push( - res.__("common.error.listing.arr.invite.invalid") - ); - } else if (req.body.invite.length > 2000) { - error = true; - errors.push( - res.__("common.error.listing.arr.invite.tooLong") - ); - } else if (functions.isURL(req.body.invite)) { - error = true; - errors.push( - res.__("common.error.listing.arr.invite.isURL") - ); - } else if (req.body.invite.includes("discord.gg")) { - error = true; - errors.push( - res.__("common.error.server.arr.invite.dgg") - ); - } - } - - if (!req.body.shortDescription) { - error = true; - errors.push( - res.__("common.error.listing.arr.shortDescRequired") - ); - } - - if (!req.body.longDescription) { - error = true; - errors.push( - res.__("common.error.listing.arr.longDescRequired") - ); - } - - let tags: string[] = []; - - if (req.body.gaming === true) tags.push("Gaming"); - if (req.body.music === true) tags.push("Music"); - if (req.body.mediaEntertain === "on") - tags.push("Media & Entertainment"); - if (req.body.createArts === true) tags.push("Creative Arts"); - if (req.body.sciTech === true) tags.push("Science & Tech"); - if (req.body.edu === true) tags.push("Education"); - if (req.body.fashBeaut === true) tags.push("Fashion & Beauty"); - - if (req.body.relIdentity === "on") - tags.push("Relationships & Identity"); - if (req.body.travelCuis === true) tags.push("Travel & Food"); - if (req.body.fitHealth === true) tags.push("Fitness & Health"); - if (req.body.finance === true) tags.push("Finance"); - if (req.body.lgbt === true) tags.push("LGBT"); + .catch((error: DiscordAPIError) => { + if(error.code === RESTJSONErrorCodes.UnknownInvite) + return res.status(400).json({ + error: true, + status: 400, + errors: [res.__("common.error.listing.arr.invite.invalid")] + }); return res.status(400).json({ error: true, status: 400, - errors: errors + errors: [`${error.name}: ${error.message}`, `${error.httpStatus} ${error.method} ${error.path}`] }); }); } ); -router.get("/:id", variables, async (req: Request, res: Response, next) => { +router.get("/:id", variables, async (req: Request, res: Response) => { res.locals.pageType = { server: true, bot: false @@ -458,7 +381,7 @@ router.get( variables, permission.auth, permission.admin, - async (req: Request, res: Response, next) => { + async (req: Request, res: Response) => { if (req.params.id === "@me") { if (!req.user) return res.redirect("/auth/login"); req.params.id = req.user.id; @@ -485,7 +408,7 @@ router.get( "/:id/edit", variables, permission.auth, - async (req: Request, res: Response, next) => { + async (req: Request, res: Response) => { const server: delServer | undefined = await global.db .collection("servers") .findOne({ _id: req.params.id }); @@ -534,7 +457,7 @@ router.post( "/:id/edit", variables, permission.auth, - async (req: Request, res: Response, next) => { + async (req: Request, res: Response) => { let error = false; let errors: string[] = []; @@ -618,24 +541,18 @@ router.post( } if (fetchChannel) - await fetch( - `https://discord.com/api/v6/channels/${req.body.previewChannel}`, - { - headers: { - Authorization: `Bot ${settings.secrets.discord.token}` + await discord.bot.api.channels(req.body.previewChannel).get() + .catch((e: DiscordAPIError) => { + if([400, 404].includes(e.httpStatus)) { + error = true; + errors.push( + res.__( + "common.error.server.arr.previewChannel.nonexistent" + ) + ); + fetchChannel = false; } - } - ).then((fetchRes: fetchRes) => { - if (fetchRes.status === 400 || fetchRes.status === 404) { - error = true; - errors.push( - res.__( - "common.error.server.arr.previewChannel.nonexistent" - ) - ); - fetchChannel = false; - } - }); + }) if (fetchChannel) await fetch( @@ -686,31 +603,20 @@ router.post( if (!server.tags.includes("LGBT")) reviewRequired = true; } - fetch(`https://discord.com/api/v6/invites/${req.body.invite}`, { - method: "GET", - headers: { Authorization: `Bot ${settings.secrets.discord.token}` } - }) - .then(async (fetchRes: fetchRes) => { - const invite = (await fetchRes.json()) as APIInvite; - - // @ts-expect-error - if (invite.code === RESTJSONErrorCodes.UnknownInvite) { - error = true; - errors.push( - res.__("common.error.listing.arr.invite.invalid") - ); - } else if (invite.guild.id !== server._id) { - error = true; - errors.push( - res.__("common.error.server.arr.invite.sameServer") - ); - } + if (error === true) + return res.status(400).json({ + error: true, + status: 400, + errors: errors + }); - if (error === true) + discord.bot.api.invites(req.body.invite).get() + .then(async (invite: APIInvite) => { + if (invite.guild.id !== server._id) return res.status(400).json({ error: true, status: 400, - errors: errors + errors: [res.__("common.error.server.arr.invite.sameServer")] }); await global.db.collection("servers").updateOne( @@ -735,13 +641,13 @@ router.post( status: { reviewRequired: reviewRequired } - } + } as delServer } ); (discord.bot.channels.cache.get( settings.channels.webLog - ) as Discord.TextChannel).send( + ) as TextChannel).send( `${settings.emoji.editBot} **${functions.escapeFormatting( req.user.db.fullUsername )}** \`(${ @@ -779,7 +685,7 @@ router.post( status: { reviewRequired: reviewRequired } - }, + } as delServer, old: { name: server.name, shortDesc: server.shortDesc, @@ -799,7 +705,7 @@ router.post( status: { reviewRequired: server.status.reviewRequired } - } + } as delServer } }); @@ -812,11 +718,18 @@ router.post( id: invite.guild.id }); }) - .catch(() => { - return res.status(502).json({ + .catch((error: DiscordAPIError) => { + if(error.code === RESTJSONErrorCodes.UnknownInvite) + return res.status(400).json({ + error: true, + status: 400, + errors: [res.__("common.error.listing.arr.invite.invalid")] + }); + + return res.status(400).json({ error: true, - status: 502, - errors: [res.__("common.error.dapiFail")] + status: 400, + errors: [`${error.name}: ${error.message}`, `${error.httpStatus} ${error.method} ${error.path}`] }); }); } @@ -827,7 +740,7 @@ router.get( variables, permission.auth, permission.mod, - async (req: Request, res: Response, next) => { + async (req: Request, res: Response) => { const server: delServer | undefined = await global.db .collection("servers") .findOne({ _id: req.params.id }); @@ -881,7 +794,7 @@ router.post( variables, permission.auth, permission.mod, - async (req: Request, res: Response, next) => { + async (req: Request, res: Response) => { const server: delServer | undefined = await global.db .collection("servers") .findOne({ _id: req.params.id }); @@ -951,7 +864,7 @@ router.post( (discord.bot.channels.cache.get( settings.channels.webLog - ) as Discord.TextChannel).send( + ) as TextChannel).send( `${settings.emoji.cross} **${functions.escapeFormatting( req.user.db.fullUsername )}** \`(${ @@ -992,7 +905,7 @@ router.get( variables, permission.auth, permission.mod, - async (req: Request, res: Response, next) => { + async (req: Request, res: Response) => { const server: delServer | undefined = await global.db .collection("servers") .findOne({ _id: req.params.id }); @@ -1048,7 +961,7 @@ router.get( (discord.bot.channels.cache.get( settings.channels.webLog - ) as Discord.TextChannel) + ) as TextChannel) .send( `${settings.emoji.check} **${functions.escapeFormatting( req.user.db.fullUsername @@ -1088,7 +1001,7 @@ router.get( "/:id/delete", variables, permission.auth, - async (req: Request, res: Response, next) => { + async (req: Request, res: Response) => { const server: delServer | undefined = await global.db .collection("servers") .findOne({ _id: req.params.id }); @@ -1113,7 +1026,7 @@ router.get( (discord.bot.channels.cache.get( settings.channels.webLog - ) as Discord.TextChannel).send( + ) as TextChannel).send( `${settings.emoji.botDeleted} **${functions.escapeFormatting( req.user.db.fullUsername )}** \`(${ @@ -1146,7 +1059,7 @@ router.get( variables, permission.auth, permission.mod, - async (req: Request, res: Response, next) => { + async (req: Request, res: Response) => { const server: delServer | undefined = await global.db .collection("servers") .findOne({ _id: req.params.id }); @@ -1180,7 +1093,7 @@ router.post( variables, permission.auth, permission.mod, - async (req: Request, res: Response, next) => { + async (req: Request, res: Response) => { const server: delServer | undefined = await global.db .collection("servers") .findOne({ _id: req.params.id }); @@ -1218,7 +1131,7 @@ router.post( (discord.bot.channels.cache.get( settings.channels.webLog - ) as Discord.TextChannel).send( + ) as TextChannel).send( `${settings.emoji.botDeleted} **${functions.escapeFormatting( req.user.db.fullUsername )}** \`(${ @@ -1270,25 +1183,8 @@ router.get( req: req }); - await fetch(`https://discord.com/api/v6/invites/${server.inviteCode}`, { - method: "GET", - headers: { Authorization: `Bot ${settings.secrets.discord.token}` } - }) - .then(async (fetchRes: fetchRes) => { - const invite = (await fetchRes.json()) as APIInvite; - - // @ts-expect-error - if (invite.code === RESTJSONErrorCodes.UnknownInvite) - return res.status(400).render("status", { - title: res.__("common.error"), - status: 400, - subtitle: res.__( - "common.error.listing.arr.invite.invalid" - ), - req, - type: "Error" - }); - + discord.bot.api.invites(server.inviteCode).get() + .then(async (invite: APIInvite) => { if (invite.guild.id !== server._id) return res.status(400).render("status", { title: res.__("common.error"), @@ -1309,7 +1205,7 @@ router.get( hash: invite.guild.icon, url: `https://cdn.discordapp.com/icons/${invite.guild.id}/${invite.guild.icon}` } - } + } as delServer } ); @@ -1326,14 +1222,14 @@ router.get( hash: invite.guild.icon, url: `https://cdn.discordapp.com/icons/${invite.guild.id}/${invite.guild.icon}` } - }, + } as delServer, old: { name: server.name, icon: { hash: server.icon.hash, url: server.icon.url } - } + } as delServer } }); @@ -1341,11 +1237,20 @@ router.get( res.redirect(`/servers/${req.params.id}`); }) - .catch(() => { - return res.status(404).render("status", { + .catch((error: DiscordAPIError) => { + if(error.code === RESTJSONErrorCodes.UnknownInvite) + return res.status(400).render("status", { + title: res.__("common.error"), + status: 400, + subtitle: res.__("common.error.listing.arr.invite.invalid"), + req, + type: "Error" + }); + + return res.status(400).render("status", { title: res.__("common.error"), - status: 404, - subtitle: res.__("common.error.dapiFail"), + status: 400, + subtitle: `${error.name}: ${error.message} | ${error.httpStatus} ${error.method} ${error.path}`, req, type: "Error" }); diff --git a/src/Routes/staff.ts b/src/Routes/staff.ts index a8e8a567..48db1762 100644 --- a/src/Routes/staff.ts +++ b/src/Routes/staff.ts @@ -19,11 +19,8 @@ along with this program. If not, see . import express from "express"; import { Request, Response } from "express"; -import { Response as fetchRes } from "../../@types/fetch"; import { APIUser } from "discord-api-types/v6"; -import * as fetch from "node-fetch"; - import * as settings from "../../settings.json"; import * as permission from "../Util/Function/permissions"; import * as functions from "../Util/Function/main"; @@ -923,13 +920,8 @@ router.get( .collection("users") .findOne({ _id: req.params.id }); - fetch(`https://discord.com/api/v6/users/${req.params.id}`, { - method: "GET", - headers: { Authorization: `Bot ${settings.secrets.discord.token}` } - }) - .then(async (fetchRes: fetchRes) => { - const discordUser = (await fetchRes.json()) as APIUser; - + discord.bot.api.users(req.params.id).get() + .then(async (discordUser: APIUser) => { if (!user) { await global.db.collection("users").insertOne({ _id: req.params.id, diff --git a/src/Routes/templates.ts b/src/Routes/templates.ts index 1e643cdd..dcf46971 100644 --- a/src/Routes/templates.ts +++ b/src/Routes/templates.ts @@ -19,10 +19,7 @@ along with this program. If not, see . import express from "express"; import { Request, Response } from "express"; -import { Response as fetchRes } from "../../@types/fetch"; -import * as fetch from "node-fetch"; -import * as Discord from "discord.js"; import sanitizeHtml from "sanitize-html"; import * as settings from "../../settings.json"; @@ -35,6 +32,7 @@ import * as templateCache from "../Util/Services/templateCaching"; import { variables } from "../Util/Function/variables"; import * as tokenManager from "../Util/Services/adminTokenManager"; import { APITemplate } from "../../@types/discord"; +import { TextChannel, DiscordAPIError } from "discord.js"; const md = require("markdown-it")(); const Entities = require("html-entities").XmlEntities; @@ -45,7 +43,7 @@ router.get( "/submit", variables, permission.auth, - (req: Request, res: Response, next) => { + (req: Request, res: Response) => { res.locals.premidPageInfo = res.__("premid.templates.submit"); res.render("templates/serverTemplates/submit", { @@ -60,77 +58,85 @@ router.post( "/submit", variables, permission.auth, - async (req: Request, res: Response, next) => { + async (req: Request, res: Response) => { res.locals.premidPageInfo = res.__("premid.templates.submit"); let error = false; let errors: string[] = []; - if (req.body.code.includes(" ")) + if (!req.body.code || typeof req.body.code !== "string" || req.body.code.includes(" ")) { + error = true; + errors.push( + res.__("common.error.template.arr.invite.invalid") + ); + } + + if (req.body.code.length > 2000) { + error = true; + errors.push( + res.__("common.error.template.arr.invite.tooLong") + ); + } + + if (functions.isURL(req.body.code)) { + error = true; + errors.push( + res.__("common.error.template.arr.invite.isURL") + ); + } + + if (req.body.code.includes("discord.new")) { + error = true; + errors.push( + res.__("common.error.template.arr.invite.dnew") + ); + } + + const templateExists: + | delTemplate + | undefined = await global.db + .collection("templates") + .findOne({ _id: req.body.code }); + if (templateExists) + return res.status(409).json({ + error: true, + status: 409, + errors: [res.__("common.error.template.conflict")] + }); + + if (!req.body.shortDescription) { + error = true; + errors.push( + res.__("common.error.listing.arr.shortDescRequired") + ); + } + + let tags: string[] = []; + + if (req.body.gaming === true) tags.push("Gaming"); + if (req.body.music === true) tags.push("Music"); + if (req.body.mediaEntertain === true) + tags.push("Media & Entertainment"); + if (req.body.createArts === true) tags.push("Creative Arts"); + if (req.body.sciTech === true) tags.push("Science & Tech"); + if (req.body.edu === true) tags.push("Education"); + if (req.body.fashBeaut === true) tags.push("Fashion & Beauty"); + + if (req.body.relIdentity === true) + tags.push("Relationships & Identity"); + if (req.body.travelCuis === true) tags.push("Travel & Food"); + if (req.body.fitHealth === true) tags.push("Fitness & Health"); + if (req.body.finance === true) tags.push("Finance"); + + if (error === true) return res.status(400).json({ error: true, status: 400, - errors: [res.__("common.error.template.arr.invite.invalid")] + errors: errors }); - fetch(`https://discord.com/api/v6/guilds/templates/${req.body.code}`, { - method: "GET", - headers: { Authorization: `Bot ${settings.secrets.discord.token}` } - }) - .then(async (fetchRes: fetchRes) => { - const template = (await fetchRes.json()) as APITemplate; - - // @ts-expect-error - if (template.code !== 10057) { - const templateExists: - | delTemplate - | undefined = await global.db - .collection("templates") - .findOne({ _id: template.code }); - if (templateExists) - return res.status(409).json({ - error: true, - status: 409, - errors: [res.__("common.error.template.conflict")] - }); - - if (!req.body.shortDescription) { - error = true; - errors.push( - res.__("common.error.listing.arr.shortDescRequired") - ); - } - } else { - error = true; - errors.push( - res.__("common.error.template.arr.invite.invalid") - ); - } - - let tags: string[] = []; - - if (req.body.gaming === true) tags.push("Gaming"); - if (req.body.music === true) tags.push("Music"); - if (req.body.mediaEntertain === "on") - tags.push("Media & Entertainment"); - if (req.body.createArts === true) tags.push("Creative Arts"); - if (req.body.sciTech === true) tags.push("Science & Tech"); - if (req.body.edu === true) tags.push("Education"); - if (req.body.fashBeaut === true) tags.push("Fashion & Beauty"); - - if (req.body.relIdentity === "on") - tags.push("Relationships & Identity"); - if (req.body.travelCuis === true) tags.push("Travel & Food"); - if (req.body.fitHealth === true) tags.push("Fitness & Health"); - if (req.body.finance === true) tags.push("Finance"); - - if (error === true) - return res.status(400).json({ - error: true, - status: 400, - errors: errors - }); - + discord.bot.api.guilds.templates(req.body.code).get() + .then(async (template: APITemplate) => { await global.db.collection("templates").insertOne({ _id: template.code, name: template.name, @@ -163,11 +169,11 @@ router.post( linkToServerPage: false, template: `https://discord.new/${template.code}` } - }); + } as delTemplate); await (discord.bot.channels.cache.get( settings.channels.webLog - ) as Discord.TextChannel).send( + ) as TextChannel).send( `${settings.emoji.addBot} **${functions.escapeFormatting( req.user.db.fullUsername )}** \`(${ @@ -237,70 +243,24 @@ router.post( id: template.code }); }) - .catch(async (fetchRes: fetchRes) => { - if (!req.body.code) { - error = true; - errors.push( - res.__("common.error.template.arr.invite.invalid") - ); - } else { - if (typeof req.body.code !== "string") { - error = true; - errors.push( - res.__("common.error.template.arr.invite.invalid") - ); - } else if (req.body.code.length > 2000) { - error = true; - errors.push( - res.__("common.error.template.arr.invite.tooLong") - ); - } else if (functions.isURL(req.body.code)) { - error = true; - errors.push( - res.__("common.error.template.arr.invite.isURL") - ); - } else if (req.body.code.includes("discord.new")) { - error = true; - errors.push( - res.__("common.error.template.arr.invite.dnew.") - ); - } - } - - if (!req.body.shortDescription) { - error = true; - errors.push( - res.__("common.error.listing.arr.shortDescRequired") - ); - } - - let tags: string[] = []; - - if (req.body.gaming === true) tags.push("Gaming"); - if (req.body.music === true) tags.push("Music"); - if (req.body.mediaEntertain === "on") - tags.push("Media & Entertainment"); - if (req.body.createArts === true) tags.push("Creative Arts"); - if (req.body.sciTech === true) tags.push("Science & Tech"); - if (req.body.edu === true) tags.push("Education"); - if (req.body.fashBeaut === true) tags.push("Fashion & Beauty"); - - if (req.body.relIdentity === "on") - tags.push("Relationships & Identity"); - if (req.body.travelCuis === true) tags.push("Travel & Food"); - if (req.body.fitHealth === true) tags.push("Fitness & Health"); - if (req.body.finance === true) tags.push("Finance"); + .catch((error: DiscordAPIError) => { + if(error.code === 10057) + return res.status(400).json({ + error: true, + status: 400, + errors: [res.__("common.error.template.arr.invite.invalid")] + }); return res.status(400).json({ error: true, status: 400, - errors: errors + errors: [`${error.name}: ${error.message}`, `${error.httpStatus} ${error.method} ${error.path}`] }); }); } ); -router.get("/:id", variables, async (req: Request, res: Response, next) => { +router.get("/:id", variables, async (req: Request, res: Response) => { res.locals.pageType = { server: false, bot: false, @@ -361,7 +321,7 @@ router.get( variables, permission.auth, permission.admin, - async (req: Request, res: Response, next) => { + async (req: Request, res: Response) => { if (req.params.id === "@me") { if (!req.user) return res.redirect("/auth/login"); req.params.id = req.user.id; @@ -387,7 +347,7 @@ router.get( "/:id/edit", variables, permission.auth, - async (req: Request, res: Response, next) => { + async (req: Request, res: Response) => { const template: delTemplate | undefined = await global.db .collection("templates") .findOne({ _id: req.params.id }); @@ -439,7 +399,7 @@ router.post( "/:id/edit", variables, permission.auth, - async (req: Request, res: Response, next) => { + async (req: Request, res: Response) => { let error = false; let errors = []; @@ -510,20 +470,15 @@ router.post( if (req.body.fitHealth === true) tags.push("Fitness & Health"); if (req.body.finance === true) tags.push("Finance"); - fetch(`https://discord.com/api/v6/guilds/templates/${req.body.code}`, { - method: "GET", - headers: { Authorization: `Bot ${settings.secrets.discord.token}` } - }) - .then(async (fetchRes: fetchRes) => { - const template = (await fetchRes.json()) as APITemplate; - - if (error === true) - return res.status(400).json({ - error: true, - status: 400, - errors: errors - }); + if (error === true) + return res.status(400).json({ + error: true, + status: 400, + errors: errors + }); + discord.bot.api.guilds.templates(req.body.code).get() + .then(async (template: APITemplate) => { await global.db.collection("templates").updateOne( { _id: req.params.id }, { @@ -559,13 +514,13 @@ router.post( linkToServerPage: linkToServerPage, template: `https://discord.new/${dbTemplate._id}` } - } + } as delTemplate } ); await (discord.bot.channels.cache.get( settings.channels.webLog - ) as Discord.TextChannel).send( + ) as TextChannel).send( `${settings.emoji.editBot} **${functions.escapeFormatting( req.user.db.fullUsername )}** \`(${ @@ -617,7 +572,7 @@ router.post( linkToServerPage: linkToServerPage, template: `https://discord.new/${dbTemplate._id}` } - }, + } as delTemplate, old: { name: dbTemplate.name, region: dbTemplate.region, @@ -642,7 +597,7 @@ router.post( linkToServerPage: linkToServerPage, template: `https://discord.new/${dbTemplate._id}` } - } + } as delTemplate } }); @@ -655,11 +610,18 @@ router.post( id: template.code }); }) - .catch(() => { - return res.status(502).json({ + .catch((error: DiscordAPIError) => { + if(error.code === 10057) + return res.status(400).json({ + error: true, + status: 400, + errors: [res.__("common.error.template.arr.invite.invalid")] + }); + + return res.status(400).json({ error: true, - status: 502, - errors: [res.__("common.error.dapiFail")] + status: 400, + errors: [`${error.name}: ${error.message}`, `${error.httpStatus} ${error.method} ${error.path}`] }); }); } @@ -669,7 +631,7 @@ router.get( "/:id/delete", variables, permission.auth, - async (req: Request, res: Response, next) => { + async (req: Request, res: Response) => { const template: delTemplate | undefined = await global.db .collection("templates") .findOne({ _id: req.params.id }); @@ -696,7 +658,7 @@ router.get( (discord.bot.channels.cache.get( settings.channels.webLog - ) as Discord.TextChannel).send( + ) as TextChannel).send( `${settings.emoji.botDeleted} **${functions.escapeFormatting( req.user.db.fullUsername )}** \`(${ @@ -731,7 +693,7 @@ router.get( variables, permission.auth, permission.mod, - async (req: Request, res: Response, next) => { + async (req: Request, res: Response) => { const template: delTemplate | undefined = await global.db .collection("templates") .findOne({ _id: req.params.id }); @@ -764,7 +726,7 @@ router.post( variables, permission.auth, permission.mod, - async (req: Request, res: Response, next) => { + async (req: Request, res: Response) => { const template: delTemplate | undefined = await global.db .collection("templates") .findOne({ _id: req.params.id }); @@ -803,7 +765,7 @@ router.post( (discord.bot.channels.cache.get( settings.channels.webLog - ) as Discord.TextChannel).send( + ) as TextChannel).send( `${settings.emoji.botDeleted} **${functions.escapeFormatting( req.user.db.fullUsername )}** \`(${ @@ -857,18 +819,8 @@ router.get( type: "Error" }); - await fetch( - `https://discord.com/api/v6/guilds/templates/${req.params.id}`, - { - method: "GET", - headers: { - Authorization: `Bot ${settings.secrets.discord.token}` - } - } - ) - .then(async (fetchRes: fetchRes) => { - const template = (await fetchRes.json()) as APITemplate; - + discord.bot.api.guilds.templates(req.params.id).get() + .then(async (template: APITemplate) => { await global.db.collection("templates").updateOne( { _id: req.params.id }, { @@ -897,7 +849,7 @@ router.get( template.serialized_source_guild.icon_hash, url: `https://cdn.discordapp.com/icons/${template.source_guild_id}/${template.serialized_source_guild.icon_hash}` } - } + } as delTemplate } ); @@ -933,7 +885,7 @@ router.get( template.serialized_source_guild.icon_hash, url: `https://cdn.discordapp.com/icons/${template.source_guild_id}/${template.serialized_source_guild.icon_hash}` } - }, + } as delTemplate, old: { name: dbTemplate.name, region: dbTemplate.region, @@ -950,19 +902,24 @@ router.get( hash: dbTemplate.icon.hash, url: dbTemplate.icon.url } - } + } as delTemplate } }); await templateCache.updateTemplate(req.params.id); }) - .catch(() => { - return res.status(404).render("status", { - title: res.__("common.error"), - status: 404, - subtitle: res.__("common.error.dapiFail"), - req, - type: "Error" + .catch((error: DiscordAPIError) => { + if(error.code === 10057) + return res.status(400).json({ + error: true, + status: 400, + errors: [res.__("common.error.template.arr.invite.invalid")] + }); + + return res.status(400).json({ + error: true, + status: 400, + errors: [`${error.name}: ${error.message}`, `${error.httpStatus} ${error.method} ${error.path}`] }); }); diff --git a/src/Routes/users.ts b/src/Routes/users.ts index 8efe9784..3c5ad72f 100644 --- a/src/Routes/users.ts +++ b/src/Routes/users.ts @@ -31,15 +31,13 @@ import * as serverCache from "../Util/Services/serverCaching"; import * as templateCache from "../Util/Services/templateCaching"; import * as userCache from "../Util/Services/userCaching"; import * as tokenManager from "../Util/Services/adminTokenManager"; -import * as fetch from "node-fetch"; -import { Response as fetchRes } from "../../@types/fetch"; -import * as settings from "../../settings.json"; +import { DiscordAPIError } from "discord.js"; const Entities = require("html-entities").XmlEntities; const entities = new Entities(); const router = express.Router(); -router.get("/:id", variables, async (req: Request, res: Response, next) => { +router.get("/:id", variables, async (req: Request, res: Response) => { if (req.params.id === "@me") { if (!req.user) { if (req.session.logoutJustCont === true) { @@ -130,7 +128,7 @@ router.get( variables, permission.auth, permission.assistant, - async (req: Request, res: Response, next) => { + async (req: Request, res: Response) => { const targetUser: delUser = await global.db .collection("users") .findOne({ _id: req.params.id }); @@ -179,7 +177,7 @@ router.post( variables, permission.auth, permission.assistant, - async (req: Request, res: Response, next) => { + async (req: Request, res: Response) => { const targetUser: delUser = await global.db .collection("users") .findOne({ _id: req.params.id }); @@ -308,7 +306,7 @@ router.get( variables, permission.auth, permission.admin, - async (req: Request, res: Response, next) => { + async (req: Request, res: Response) => { if (req.params.id === "@me") { if (!req.user) return res.redirect("/auth/login"); req.params.id = req.user.id; @@ -338,7 +336,7 @@ router.get( variables, permission.auth, permission.admin, - async (req: Request, res: Response, next) => { + async (req: Request, res: Response) => { if (!req.query.token) return res.json({}); const tokenCheck = await tokenManager.verifyToken( req.user.id, @@ -350,7 +348,7 @@ router.get( } ); -router.get("/profile/:id", (req: Request, res: Response, next) => { +router.get("/profile/:id", (req: Request, res: Response) => { res.redirect("/" + req.params.id); }); @@ -358,7 +356,7 @@ router.get( "/profile/:id/edit", variables, permission.auth, - async (req: Request, res: Response, next) => { + async (req: Request, res: Response) => { if (req.params.id === "@me") { req.params.id = req.user.id; } @@ -408,7 +406,7 @@ router.post( "/profile/:id/edit", variables, permission.auth, - async (req: Request, res: Response, next) => { + async (req: Request, res: Response) => { if (req.params.id === "@me") { req.params.id = req.user.id; } @@ -509,7 +507,7 @@ router.get( "/:id/sync", variables, permission.auth, - async (req: Request, res: Response, next) => { + async (req: Request, res: Response) => { if (req.params.id === "@me") { req.params.id = req.user.id; } @@ -525,12 +523,8 @@ router.get( req: req }); - await fetch(`https://discord.com/api/v6/users/${req.params.id}`, { - method: "GET", - headers: { Authorization: `Bot ${settings.secrets.discord.token}` } - }) - .then(async (fetchRes: fetchRes) => { - const user = (await fetchRes.json()) as APIUser; + discord.bot.api.users(req.params.id).get() + .then(async (user: APIUser) => { await global.db.collection("users").updateOne( { _id: req.params.id }, { @@ -559,7 +553,7 @@ router.get( hash: userProfile.avatar.hash, url: userProfile.avatar.url } - }, + } as delUser, new: { name: user.username, flags: user.public_flags, @@ -567,16 +561,18 @@ router.get( hash: user.avatar, url: `https://cdn.discordapp.com/avatars/${req.params.id}/${user.avatar}` } - } + } as delUser } }); await userCache.updateUser(req.params.id); }) - .catch((_) => { - return res.status(502).json({ - error: true, - status: 502, - errors: [res.__("common.error.dapiFail")] + .catch((error: DiscordAPIError) => { + return res.status(400).render("status", { + title: res.__("common.error"), + status: 400, + subtitle: `${error.name}: ${error.message} | ${error.httpStatus} ${error.method} ${error.path}`, + req, + type: "Error" }); }); @@ -588,7 +584,7 @@ router.get( "/game/snake", variables, permission.auth, - async (req: Request, res: Response, next) => { + async (req: Request, res: Response) => { res.locals.premidPageInfo = res.__("premid.snake"); res.render("templates/users/snake", { @@ -602,7 +598,7 @@ router.get( router.get( "/game/snake/leaderboard", variables, - async (req: Request, res: Response, next) => { + async (req: Request, res: Response) => { res.locals.premidPageInfo = res.__("premid.snake.lb"); const users = await userCache.getAllUsers(); @@ -622,7 +618,7 @@ router.get( "/profile/game/snakes", variables, permission.auth, - async (req: Request, res: Response, next) => { + async (req: Request, res: Response) => { const user: delUser = await global.db .collection("users") .findOne({ _id: req.user.id }); @@ -639,7 +635,7 @@ router.post( "/profile/game/snakes", variables, permission.auth, - async (req: Request, res: Response, next) => { + async (req: Request, res: Response) => { if (req.body.score <= req.user.db.game.snakes.maxScore) return res.status(202).json({ error: false, @@ -704,7 +700,7 @@ router.get( "/account/preferences", variables, permission.auth, - async (req: Request, res: Response, next) => { + async (req: Request, res: Response) => { res.locals.premidPageInfo = res.__("premid.preferences"); res.render("templates/users/accountPreferences", { @@ -722,7 +718,7 @@ router.post( "/account/preferences", variables, permission.auth, - async (req: Request, res: Response, next) => { + async (req: Request, res: Response) => { let gamePreferences: boolean, experiments: boolean, theme: number; // Refer to docs/THEME.md in the root directory of this project. @@ -813,7 +809,7 @@ router.get( "/account/preferences/reset", variables, permission.auth, - async (req: Request, res: Response, next) => { + async (req: Request, res: Response) => { await global.db.collection("users").updateOne( { _id: req.user.id }, { diff --git a/src/Util/Function/main.ts b/src/Util/Function/main.ts index 54edef0e..4b9b0b77 100644 --- a/src/Util/Function/main.ts +++ b/src/Util/Function/main.ts @@ -348,12 +348,12 @@ export function shuffleArray(array: Array) { return array; } -export function isURL(string: string): boolean { +export function isURL(string: string) { try { - new URL(string); - } catch (_) { + if (new URL(string).protocol === 'https:') { + return true + } else return false + } catch { return false; } - - return true; } diff --git a/src/Util/Function/permissions.ts b/src/Util/Function/permissions.ts index 02be4813..7aa7047e 100644 --- a/src/Util/Function/permissions.ts +++ b/src/Util/Function/permissions.ts @@ -19,8 +19,9 @@ along with this program. If not, see . import { Request, Response } from "express"; import { bot } from "../Services/discord"; -import * as https from "https"; import * as settings from "../../../settings.json"; +import * as discord from "../Services/discord"; +import { DiscordAPIError } from "discord.js"; export const auth = (req: Request, res: Response, next: () => void) => { if (req.session.logoutJustCont === true) { @@ -48,44 +49,22 @@ export const member = (req: Request, res: Response, next: () => void) => { .get(settings.guild.main) .members.cache.get(req.user.id) ) { - const data = JSON.stringify({ - access_token: req.user.accessToken - }); - - const options = { - hostname: "discord.com", - port: 443, - path: `/api/v6/guilds/${settings.guild.main}/members/${req.user.id}`, - method: "PUT", - headers: { - "Content-Type": "application/json", - "Content-Length": data.length, - Authorization: "Bot " + settings.secrets.discord.token - } - }; - - const msReq = https.request(options, (response) => { - if (response.statusCode === 403 && !req.user.impersonator) { - return res.status(400).json({ - error: true, - status: 400, - errors: [ - res.__("common.error.failedJoin", { - a: - '', - ea: "" - }) - ] - }); - } else next(); - }); - - msReq.on("error", (e) => { - console.error(e); - }); - - msReq.write(data); - msReq.end(); + discord.bot.api.guilds(settings.guild.main).members(req.user.id).put({ data: { access_token: req.user.accessToken } }) + .catch((error: DiscordAPIError) => { + if (error.httpStatus === 403 && !req.user.impersonator) { + return res.status(400).json({ + error: true, + status: 400, + errors: [ + res.__("common.error.failedJoin", { + a: + '', + ea: "" + }) + ] + }); + } else next(); + }); } next(); diff --git a/src/Util/Function/variables.ts b/src/Util/Function/variables.ts index dd2aba83..6506e073 100644 --- a/src/Util/Function/variables.ts +++ b/src/Util/Function/variables.ts @@ -72,12 +72,13 @@ export const variables = async ( ]; if ( - !req.originalUrl.includes("/audio/") || - !req.originalUrl.includes("/auth/") || - !req.originalUrl.includes("/css/") || - !req.originalUrl.includes("/fonts/") || - !req.originalUrl.includes("/img/") || - !req.originalUrl.includes("/js/") + !req.originalUrl.includes("/audio/") && + !req.originalUrl.includes("/auth/") && + !req.originalUrl.includes("/css/") && + !req.originalUrl.includes("/fonts/") && + !req.originalUrl.includes("/img/") && + !req.originalUrl.includes("/js/") && + !req.originalUrl.includes("/auth/login") ) req.session.redirectTo = req.originalUrl; diff --git a/src/Util/Services/discord.ts b/src/Util/Services/discord.ts index a1d1250b..7fe2200c 100644 --- a/src/Util/Services/discord.ts +++ b/src/Util/Services/discord.ts @@ -26,7 +26,21 @@ const prefix = "statuses"; metrics.init({ host: "", prefix: "", apiKey: settings.secrets.datadog }); -export const bot = new Discord.Client({ +// @ts-expect-error +class Client extends Discord.Client { + readonly api: { + channels: any; + gateway: any; + guilds: any; + invites: any; + oauth2: any; + users: any; + voice: any; + webhooks: any; + } +} + +export const bot = new Client({ allowedMentions: { parse: [] }, ws: { intents: ["GUILDS", "GUILD_MEMBERS", "GUILD_PRESENCES"] } });