From f3e1e8a2e3978e6e4c7b4b3bba364d9fc62d742d Mon Sep 17 00:00:00 2001 From: jellz Date: Tue, 7 May 2019 22:09:31 +1000 Subject: [PATCH] improve error responses, format code using Prettier --- server/client.js | 4 +- server/index.js | 29 +++-- server/ratelimits.js | 2 +- server/routes/auth.js | 108 +++++++++++------ server/routes/bots.js | 214 +++++++++++++++++++++++++-------- server/routes/users.js | 21 +++- server/schemas/createBot.js | 34 ++++-- server/schemas/editBot.js | 20 +-- server/schemas/postBotStats.js | 12 +- server/util.js | 45 +++++-- 10 files changed, 352 insertions(+), 137 deletions(-) diff --git a/server/client.js b/server/client.js index fcae42e..f669187 100644 --- a/server/client.js +++ b/server/client.js @@ -1,7 +1,7 @@ var { Client } = require('discord.js'); -var client = module.exports = new Client({ disableEveryone: true }); +var client = (module.exports = new Client({ disableEveryone: true })); client.once('ready', () => { console.log(`[discord] logged in as ${client.user.tag}`); client.user.setActivity('with boats'); -}); \ No newline at end of file +}); diff --git a/server/index.js b/server/index.js index 50aefea..bd7905c 100644 --- a/server/index.js +++ b/server/index.js @@ -6,8 +6,14 @@ var logger = require('morgan'); var app = express(); // constants -const r = module.exports.r = require('rethinkdbdash')({ db: 'discordboatsclub_v4', port: process.env.RETHINKDB_PORT || 28015, host: process.env.RETHINKDB_HOST || 'localhost' }); -const JWT_KEY = module.exports.JWT_KEY = fs.readFileSync('keys/jwt.key').toString(); +const r = (module.exports.r = require('rethinkdbdash')({ + db: 'discordboatsclub_v4', + port: process.env.RETHINKDB_PORT || 28015, + host: process.env.RETHINKDB_HOST || 'localhost' +})); +const JWT_KEY = (module.exports.JWT_KEY = fs + .readFileSync('keys/jwt.key') + .toString()); const PORT = process.env.PORT || 3001; var client = require('./client'); @@ -19,12 +25,18 @@ app.use(express.json()); app.use(express.urlencoded({ extended: false })); app.use(logger('dev')); -app.use(require('express-jwt')({ secret: JWT_KEY, credentialsRequired: false }), async (req, res, next) => { - if (!req.user) return next(); - let user = await r.table('users').get(req.user).run(); //req.user is the user id - req.user = user; //now req.user is the user object - next(); -}); +app.use( + require('express-jwt')({ secret: JWT_KEY, credentialsRequired: false }), + async (req, res, next) => { + if (!req.user) return next(); + let user = await r + .table('users') + .get(req.user) + .run(); //req.user is the user id + req.user = user; //now req.user is the user object + next(); + } +); // TODO: improve error responses, use 204 when supposed to // TODO: revamp permission system @@ -44,6 +56,7 @@ app.use(require('express-jwt')({ secret: JWT_KEY, credentialsRequired: false }), // TODO: discord bot lookup features // TODO: auto create rdb tables // TODO: hash IP addresses +// TODO: make code readable app.use('/api/auth', require('./routes/auth')); app.use('/api/bots', require('./routes/bots')); app.use('/api/users', require('./routes/users')); diff --git a/server/ratelimits.js b/server/ratelimits.js index 9711f9c..d20eae8 100644 --- a/server/ratelimits.js +++ b/server/ratelimits.js @@ -7,4 +7,4 @@ exports.editBotLimiter = ratelimit({ keyGenerator: (req) => { return req.cf_ip; } -}); \ No newline at end of file +}); diff --git a/server/routes/auth.js b/server/routes/auth.js index 0e56d89..30b65e5 100644 --- a/server/routes/auth.js +++ b/server/routes/auth.js @@ -4,65 +4,95 @@ var fetch = require('node-fetch'); var btoa = require('btoa'); const { r, JWT_KEY } = require('../'); -var router = module.exports = express.Router(); +var router = (module.exports = express.Router()); -router.get('/login', (req, res) => res.redirect(`https://discordapp.com/oauth2/authorize?client_id=${process.env.DISCORD_CLIENT_ID}&redirect_uri=${encodeURIComponent(process.env.OAUTH_CALLBACK_URL)}&response_type=code&scope=identify%20email&prompt=none`)); +router.get('/login', (req, res) => + res.redirect( + `https://discordapp.com/oauth2/authorize?client_id=${ + process.env.DISCORD_CLIENT_ID + }&redirect_uri=${encodeURIComponent( + process.env.OAUTH_CALLBACK_URL + )}&response_type=code&scope=identify%20email&prompt=none` + ) +); router.get('/callback', async (req, res) => { if (!req.query.code) return res.sendStatus(400); - let creds = btoa(`${process.env.DISCORD_CLIENT_ID}:${process.env.DISCORD_CLIENT_SECRET}`); - let accessResponse = await fetch(`https://discordapp.com/api/oauth2/token?grant_type=authorization_code&code=${req.query.code}&redirect_uri=${encodeURIComponent(process.env.OAUTH_CALLBACK_URL)}`, - { - method: 'POST', - headers: { - 'Authorization': `Basic ${creds}`, - 'User-Agent': 'discordboats.club/4.0 (https://github.com/discordboats-club/website-v4)', - 'Content-Type': 'application/x-www-form-urlencoded' + let creds = btoa( + `${process.env.DISCORD_CLIENT_ID}:${process.env.DISCORD_CLIENT_SECRET}` + ); + let accessResponse = await fetch( + `https://discordapp.com/api/oauth2/token?grant_type=authorization_code&code=${ + req.query.code + }&redirect_uri=${encodeURIComponent(process.env.OAUTH_CALLBACK_URL)}`, + { + method: 'POST', + headers: { + Authorization: `Basic ${creds}`, + 'User-Agent': + 'discordboats.club/4.0 (https://github.com/discordboats-club/website-v4)', + 'Content-Type': 'application/x-www-form-urlencoded' + } } - }); + ); let access = await accessResponse.json(); if (access.error) return res.sendStatus(500); - let userResponse = await fetch(`https://discordapp.com/api/users/@me`, - { + let userResponse = await fetch(`https://discordapp.com/api/users/@me`, { headers: { - 'Authorization': `Bearer ${access.access_token}`, + Authorization: `Bearer ${access.access_token}`, 'User-Agent': 'discordboats.club/2.0 (https://discordboats.club)' } }); let user = await userResponse.json(); if (!user.email) res.status(400).json({ error: 'Email scope not included' }); - if (!await r.table('users').get(user.id).run()) { - await r.table('users').insert({ - id: user.id, - username: user.username, - locale: user.locale, - avatar: `https://cdn.discordapp.com/avatars/${user.id}/${user.avatar}.png`, - tag: user.username + '#' + user.discriminator, - discrim: user.discriminator, - flags: [], + if ( + !(await r + .table('users') + .get(user.id) + .run()) + ) { + await r + .table('users') + .insert({ + id: user.id, + username: user.username, + locale: user.locale, + avatar: `https://cdn.discordapp.com/avatars/${user.id}/${ + user.avatar + }.png`, + tag: user.username + '#' + user.discriminator, + discrim: user.discriminator, + flags: [], - email: user.email, + email: user.email, - discordAT: access.access_token, - discordRT: access.refresh_token - }).run(); + discordAT: access.access_token, + discordRT: access.refresh_token + }) + .run(); } else { - await r.table('users').get(user.id).update({ - username: user.username, - locale: user.locale, - avatar: `https://cdn.discordapp.com/avatars/${user.id}/${user.avatar}.png`, - tag: user.username + '#' + user.discriminator, - discrim: user.discriminator, + await r + .table('users') + .get(user.id) + .update({ + username: user.username, + locale: user.locale, + avatar: `https://cdn.discordapp.com/avatars/${user.id}/${ + user.avatar + }.png`, + tag: user.username + '#' + user.discriminator, + discrim: user.discriminator, - email: user.email, + email: user.email, - discordAT: access.access_token, - discordRT: access.refresh_token - }).run(); + discordAT: access.access_token, + discordRT: access.refresh_token + }) + .run(); } - + const JWT_TOKEN = await jwt.sign(user.id, JWT_KEY); res.json({ token: JWT_TOKEN }); -}); \ No newline at end of file +}); diff --git a/server/routes/bots.js b/server/routes/bots.js index e435785..7ce0b4a 100644 --- a/server/routes/bots.js +++ b/server/routes/bots.js @@ -3,32 +3,53 @@ var createBotSchema = require('../schemas/createBot'); var editBotSchema = require('../schemas/editBot'); var postBotStats = require('../schemas/postBotStats'); var randomString = require('randomstring'); -var { handleJoi, libraries, filterUnexpectedData, safeBot, getBadBots } = require('../util'); +var { + handleJoi, + libraries, + filterUnexpectedData, + safeBot, + getBadBots +} = require('../util'); var { editBotLimiter } = require('../ratelimits'); var { r } = require('../'); var client = require('../client'); -var router = module.exports = express.Router(); +var router = (module.exports = express.Router()); router.post('/', async (req, res) => { if (!req.user) return res.sendStatus(401); if (!handleJoi(req, res, createBotSchema)) return; let badBots = await getBadBots(); - if (badBots.includes(req.body.id)) return res.status(403).json({ error: 'ValidationError', details: ['This bot is blacklisted']}); + if (badBots.includes(req.body.id)) + return res.status(403).json({ error: 'This bot is blacklisted' }); - if (req.body.github && !req.body.github.toLowerCase().startsWith('https://github.com')) return res.status(400).json({ error: 'ValidationError', details: ['Invalid Github URL'] }); - if (req.body.library && !libraries.includes(req.body.library)) return res.status(400).json({ error: 'ValidationError', details: ['Invalid library'] }); + if ( + req.body.github && + !req.body.github.toLowerCase().startsWith('https://github.com') + ) + return res.status(400).json({ error: 'Invalid GitHub URL' }); + if (req.body.library && !libraries.includes(req.body.library)) + return res.status(400).json({ error: 'Invalid library' }); - let botUser = client.users.get(req.body.id) || await client.users.fetch(req.body.id); + let botUser = + client.users.get(req.body.id) || (await client.users.fetch(req.body.id)); let ownerUser = await client.users.fetch(req.user.id); - if (!ownerUser) return res.status(400).json({ error: 'ValidationError', details: ['Owner is not in discordboats discord guild'] }); - if (!botUser) return res.status(404).json({ error: 'BotRetrievalError', details: ['Invalid bot'] }); - if (!botUser.bot) return res.status(400).json({ error: 'ValidationError', details: ['Bot must be a bot'] }); + if (!ownerUser) + return res.status(400).json({ error: 'Owner is not in Discord guild' }); + if (!botUser) return res.status(404).json({ error: 'Invalid bot' }); + if (!botUser.bot) return res.status(400).json({ error: 'Bot must be a bot' }); - if (await r.table('bots').get(req.body.id).run()) return res.status(409).json({ error: 'ValidationError', details: ['Bot already exists'] }); + if ( + await r + .table('bots') + .get(req.body.id) + .run() + ) + return res.status(409).json({ error: 'Bot already exists' }); - let bot = filterUnexpectedData(req.body, + let bot = filterUnexpectedData( + req.body, { username: botUser.username, discrim: botUser.discriminator, @@ -44,15 +65,26 @@ router.post('/', async (req, res) => { verified: null, verifiedAt: null, verifiedBy: null - }, createBotSchema + }, + createBotSchema ); await r.table('bots').insert(bot); - let botLogChannel = client.guilds.get(process.env.DISCORD_GUILD_MAIN_ID).channels.find(c => c.name == 'bot-log'); - let modRole = client.guilds.get(process.env.DISCORD_GUILD_MAIN_ID).roles.find(r => r.name == 'Moderator'); - await botLogChannel.send(`📥 <@${req.user.id}> added **${botUser.tag}** (<@&${modRole.id}>)`); - await ownerUser.send(`📥 Your bot **${botUser.tag}** has been added to the queue! Please wait for a moderator to review it.`); + let botLogChannel = client.guilds + .get(process.env.DISCORD_GUILD_MAIN_ID) + .channels.find((c) => c.name == 'bot-log'); + let modRole = client.guilds + .get(process.env.DISCORD_GUILD_MAIN_ID) + .roles.find((r) => r.name == 'Moderator'); + await botLogChannel.send( + `📥 <@${req.user.id}> added **${botUser.tag}** (<@&${modRole.id}>)` + ); + await ownerUser.send( + `📥 Your bot **${ + botUser.tag + }** has been added to the queue! Please wait for a moderator to review it.` + ); res.sendStatus(201); }); @@ -60,37 +92,55 @@ router.post('/', async (req, res) => { router.delete('/:id', async (req, res) => { if (!req.user) return res.sendStatus(401); if (!req.params.id) return res.sendStatus(400); - let bot = await r.table('bots').get(req.params.id).run(); - if (!bot) return res.status(404).json({ error: 'BotRetrievalError', details: ['Invalid bot'] }); + let bot = await r + .table('bots') + .get(req.params.id) + .run(); + if (!bot) return res.status(404).json({ error: 'Invalid bot' }); // TODO: allow moderators to delete bots (i need to make a permission system first) if (bot.ownerId !== req.user.id) return res.sendStatus(403); - await r.table('bots').get(req.params.id).delete().run(); + await r + .table('bots') + .get(req.params.id) + .delete() + .run(); - let botLogChannel = client.guilds.get(process.env.DISCORD_GUILD_MAIN_ID).channels.find(c => c.name == 'bot-log'); + let botLogChannel = client.guilds + .get(process.env.DISCORD_GUILD_MAIN_ID) + .channels.find((c) => c.name == 'bot-log'); await botLogChannel.send(`📤 <@${req.user.id}> deleted ${bot.tag}`); let ownerUser = await client.users.fetch(req.user.id); - if (ownerUser) ownerUser.send(`📤 Your bot **${bot.tag}** has been deleted by <@${req.user.id}>`); + if (ownerUser) + ownerUser.send( + `📤 Your bot **${bot.tag}** has been deleted by <@${req.user.id}>` + ); res.sendStatus(204); }); router.get('/', async (req, res) => { let botsFromDatabase = await r.table('bots').run(); - res.json(botsFromDatabase.map(bot => safeBot(bot))); + res.json(botsFromDatabase.map((bot) => safeBot(bot))); }); // TODO: add endpoints for bots for homepage - /featured, /trending, /top, /new - limit response to 12 bots? router.get('/featured', async (req, res) => { - let featuredBots = await r.table('bots').filter({ featured: true }).run(); - res.json(featuredBots.map(bot => safeBot(bot))); + let featuredBots = await r + .table('bots') + .filter({ featured: true }) + .run(); + res.json(featuredBots.map((bot) => safeBot(bot))); }); router.get('/:id', async (req, res) => { - let bot = await r.table('bots').get(req.params.id).run(); - if (!bot) return res.status(404).json({ error: 'BotRetrievalError', details: ['Invalid bot'] }); + let bot = await r + .table('bots') + .get(req.params.id) + .run(); + if (!bot) return res.status(404).json({ error: 'Invalid bot' }); res.json(safeBot(bot)); }); @@ -98,46 +148,114 @@ router.patch('/:id', editBotLimiter, async (req, res) => { if (!req.user) return res.sendStatus(401); if (!handleJoi(req, res, editBotSchema)) return; - let bot = await r.table('bots').get(req.params.id).run(); - if (!bot) return res.status(404).json({ error: 'BotRetrievalError', details: ['Invalid bot'] }); + let bot = await r + .table('bots') + .get(req.params.id) + .run(); + if (!bot) return res.status(404).json({ error: 'Invalid bot' }); if (bot.ownerId !== req.user.id) return res.sendStatus(403); let data = filterUnexpectedData(req.body, { verified: false }, editBotSchema); - if (req.body.github && !req.body.github.toLowerCase().startsWith('https://github.com')) return res.status(400).json({ error: 'ValidationError', details: ['Invalid Github URL'] }); - if (req.body.library && !libraries.includes(req.body.library)) return res.status(400).json({ error: 'ValidationError', details: ['Invalid library'] }); + if ( + req.body.github && + !req.body.github.toLowerCase().startsWith('https://github.com') + ) + return res + .status(400) + .json({ error: 'ValidationError', details: ['Invalid Github URL'] }); + if (req.body.library && !libraries.includes(req.body.library)) + return res + .status(400) + .json({ error: 'ValidationError', details: ['Invalid library'] }); - let botUser = client.users.get(bot.id) || await client.users.fetch(bot.id); + let botUser = client.users.get(bot.id) || (await client.users.fetch(bot.id)); - await r.table('bots').get(bot.id).update(data).run(); + await r + .table('bots') + .get(bot.id) + .update(data) + .run(); - let botLogChannel = client.guilds.get(process.env.DISCORD_GUILD_MAIN_ID).channels.find(c => c.name == 'bot-log'); - let modRole = client.guilds.get(process.env.DISCORD_GUILD_MAIN_ID).roles.get(process.env.DISCORD_ROLE_MODERATOR_ID); - await botLogChannel.send(`📝 <@${req.user.id}> edited **${botUser.tag}** (reverify, <@&${modRole.id}>)`); + let botLogChannel = client.guilds + .get(process.env.DISCORD_GUILD_MAIN_ID) + .channels.find((c) => c.name == 'bot-log'); + let modRole = client.guilds + .get(process.env.DISCORD_GUILD_MAIN_ID) + .roles.get(process.env.DISCORD_ROLE_MODERATOR_ID); + await botLogChannel.send( + `📝 <@${req.user.id}> edited **${botUser.tag}** (reverify, <@&${ + modRole.id + }>)` + ); res.sendStatus(204); }); +// TODO: block multiple verification for same bot router.post('/:id/verify', async (req, res) => { - if (!req.user || !req.user.flags.includes('MODERATOR')) return res.sendStatus(403); + if (!req.user || !req.user.flags.includes('moderator')) + return res.sendStatus(403); if (req.query.verified == null) return res.sendStatus(400); - let bot = await r.table('bots').get(req.params.id).run(); - if (!bot) return res.status(404).json({ error: 'BotRetrievalError', details: ['Invalid bot'] }); - await r.table('bots').get(req.params.id).update({ verified: req.query.verified, verifiedAt: Date.now(), verifiedBy: req.user.id }).run(); - if (!JSON.parse(req.query.verified)) await r.table('bots').get(req.params.id).delete().run(); - let botLogChannel = client.guilds.get(process.env.DISCORD_GUILD_MAIN_ID).channels.find(c => c.name == 'bot-log'); - await botLogChannel.send(`${JSON.parse(req.query.verified) ? '🎉' : '😦'} <@${req.user.id}> ${JSON.parse(req.query.verified) ? 'verified' : 'rejected'} **${bot.tag}** by <@${bot.ownerId}>`); + let verified = JSON.parse(req.query.verified); + + let bot = await r + .table('bots') + .get(req.params.id) + .run(); + if (!bot) return res.status(404).json({ error: 'Invalid bot' }); + + await r + .table('bots') + .get(req.params.id) + .update({ + verified: req.query.verified, + verifiedAt: Date.now(), + verifiedBy: req.user.id + }) + .run(); + if (!verified) + await r + .table('bots') + .get(req.params.id) + .delete() + .run(); + + let botLogChannel = client.guilds + .get(process.env.DISCORD_GUILD_MAIN_ID) + .channels.find((c) => c.name == 'bot-log'); + await botLogChannel.send( + `${verified ? '🎉' : '😦'} <@${req.user.id}> ${ + verified ? 'verified' : 'rejected' + } **${bot.tag}** by <@${bot.ownerId}>` + ); + let ownerUser = await client.users.fetch(bot.ownerId); - await ownerUser.send(`${JSON.parse(req.query.verified) ? '🎉' : '😦'} Your bot **${bot.tag}** has been ${JSON.parse(req.query.verified) ? 'verified' : 'rejected'}`); + await ownerUser.send( + `${verified ? '🎉' : '😦'} Your bot **${bot.tag}** has been ${ + verified ? 'verified' : 'rejected' + }` + ); + res.json({ verified: req.query.verified }); }); router.post('/:id/stats', async (req, res) => { if (!handleJoi(req, res, postBotStats)) return; - let bot = await r.table('bots').get(req.params.id).run(); - if (!bot) return res.status(404).json({ error: 'BotRetrievalError', details: ['Invalid bot'] }); + + let bot = await r + .table('bots') + .get(req.params.id) + .run(); + if (!bot) return res.status(404).json({ error: 'Invalid bot' }); + if (!req.headers.authorization) return res.sendStatus(401); - if (bot.apiKey !== req.headers.authorization.split(' ')[1]) return res.sendStatus(403); - await r.table('bots').get(req.params.id).update({ guildCount: req.body.guildCount }); + if (bot.apiKey !== req.headers.authorization.split(' ')[1]) + return res.sendStatus(403); + + await r + .table('bots') + .get(req.params.id) + .update({ guildCount: req.body.guildCount }); res.sendStatus(204); -}); \ No newline at end of file +}); diff --git a/server/routes/users.js b/server/routes/users.js index 6eab5d2..67f3374 100644 --- a/server/routes/users.js +++ b/server/routes/users.js @@ -2,21 +2,30 @@ var express = require('express'); var { r } = require('../'); var { safeUser } = require('../util'); -var router = module.exports = express.Router(); +var router = (module.exports = express.Router()); router.get('/:id', async (req, res) => { let id = req.params.id; if (id == '@me' && req.user) id = req.user.id; - var user = await r.table('users').get(id).run(); + var user = await r + .table('users') + .get(id) + .run(); res.json(safeUser(user)); }); router.delete('/@me', async (req, res) => { if (!req.user) return res.sendStatus(401); var ownedBots = await r.table('bots').filter({ ownerId: req.user.id }); - ownedBots.forEach(async bot => { - await r.table('bots').delete(bot.id).run(); + ownedBots.forEach(async (bot) => { + await r + .table('bots') + .delete(bot.id) + .run(); }); - await r.table('users').delete(req.user.id).run(); + await r + .table('users') + .delete(req.user.id) + .run(); res.sendStatus(204); -}); \ No newline at end of file +}); diff --git a/server/schemas/createBot.js b/server/schemas/createBot.js index 3c67470..d538a3b 100644 --- a/server/schemas/createBot.js +++ b/server/schemas/createBot.js @@ -1,12 +1,26 @@ var Joi = require('joi'); -module.exports = Joi.object().required().keys({ - id: Joi.string().min(10).max(26).regex(/\d./g).required(), - prefix: Joi.string().max(10).required(), - library: Joi.string(), - invite: Joi.string().uri({ scheme: ['https'] }).required(), - website: Joi.string().uri({ scheme: ['https'] }), - github: Joi.string().uri({ scheme: ['https'] }), - shortDescription: Joi.string().max(2000).required(), - longDescription: Joi.string().max(12000).required() -}); \ No newline at end of file +module.exports = Joi.object() + .required() + .keys({ + id: Joi.string() + .min(10) + .max(26) + .regex(/\d./g) + .required(), + prefix: Joi.string() + .max(10) + .required(), + library: Joi.string(), + invite: Joi.string() + .uri({ scheme: ['https'] }) + .required(), + website: Joi.string().uri({ scheme: ['https'] }), + github: Joi.string().uri({ scheme: ['https'] }), + shortDescription: Joi.string() + .max(2000) + .required(), + longDescription: Joi.string() + .max(12000) + .required() + }); diff --git a/server/schemas/editBot.js b/server/schemas/editBot.js index 2392704..9b086fc 100644 --- a/server/schemas/editBot.js +++ b/server/schemas/editBot.js @@ -1,11 +1,13 @@ var Joi = require('joi'); -module.exports = Joi.object().required().keys({ - prefix: Joi.string().max(10), - library: Joi.string(), - invite: Joi.string().uri({ scheme: ['https'] }), - website: Joi.string().uri({ scheme: ['https'] }), - github: Joi.string().uri({ scheme: ['https'] }), - shortDescription: Joi.string().max(2000), - longDescription: Joi.string().max(12000) -}); \ No newline at end of file +module.exports = Joi.object() + .required() + .keys({ + prefix: Joi.string().max(10), + library: Joi.string(), + invite: Joi.string().uri({ scheme: ['https'] }), + website: Joi.string().uri({ scheme: ['https'] }), + github: Joi.string().uri({ scheme: ['https'] }), + shortDescription: Joi.string().max(2000), + longDescription: Joi.string().max(12000) + }); diff --git a/server/schemas/postBotStats.js b/server/schemas/postBotStats.js index 7180066..b0c2a44 100644 --- a/server/schemas/postBotStats.js +++ b/server/schemas/postBotStats.js @@ -1,6 +1,10 @@ var Joi = require('joi'); -module.exports = Joi.object().required().keys({ - guildCount: Joi.number().positive().required() - /* TODO: sharding support */ -}); \ No newline at end of file +module.exports = Joi.object() + .required() + .keys({ + guildCount: Joi.number() + .positive() + .required() + /* TODO: sharding support */ + }); diff --git a/server/util.js b/server/util.js index 02122ee..bb93d05 100644 --- a/server/util.js +++ b/server/util.js @@ -7,35 +7,60 @@ exports.getBadBots = async () => { if (!badbots) { let res = await fetch('https://i.ronthecookie.me/badbots.txt'); let text = await res.text(); - badbots = await text.split('\n').map(e => e.split(' ')[0]); + badbots = await text.split('\n').map((e) => e.split(' ')[0]); return badbots; } else { return badbots; } -} +}; exports.handleJoi = (req, res, schema) => { let result = Joi.validate(req.body, schema); if (result.error) { if (!result.error.isJoi) { - console.error(`Error while running Joi at ${Date.now()}: ${result.error}`); + console.error( + `Error while running Joi at ${Date.now()}: ${result.error}` + ); res.sendStatus(500); return false; } - res.status(400).json({ error: result.error.name, details: result.error.details.map(item => item.message) }); + res + .status(400) + .json({ + error: result.error.name, + details: result.error.details.map((item) => item.message) + }); return false; } else return true; -} +}; -exports.libraries = ['discordcr', 'Discord.Net', 'DSharpPlus', 'dscord', 'DiscordGo', 'Discord4j', 'JDA', 'discord.js', 'Eris', 'Discordia', 'RestCord', 'Yasmin', 'discord.py', 'disco', 'discordrb', 'discord-rs', 'Sword']; +exports.libraries = [ + 'discordcr', + 'Discord.Net', + 'DSharpPlus', + 'dscord', + 'DiscordGo', + 'Discord4j', + 'JDA', + 'discord.js', + 'Eris', + 'Discordia', + 'RestCord', + 'Yasmin', + 'discord.py', + 'disco', + 'discordrb', + 'discord-rs', + 'Sword' +]; exports.filterUnexpectedData = (subject, stuffToAdd, schema) => { let data = Object.assign({}, stuffToAdd); - Object.keys(schema.describe().children).forEach(key => { + Object.keys(schema.describe().children).forEach((key) => { data[key] = subject[key]; }); return data; -} +}; exports.safeUser = (user) => { delete user.discordAT; @@ -43,9 +68,9 @@ exports.safeUser = (user) => { delete user.ips; delete user.email; return user; -} +}; exports.safeBot = (bot) => { delete bot.apiKey; return bot; -} \ No newline at end of file +};