From 1b74e7d7d587679bb211836dc5b0f65d8381aca7 Mon Sep 17 00:00:00 2001 From: Matthew R Date: Mon, 21 Sep 2020 02:53:18 -0400 Subject: [PATCH] add offer command --- src/api/loc.sh/routes/internal.ts | 64 ++++++++++++++++++++++++++++--- src/commands/index.ts | 1 + src/commands/offer.ts | 48 +++++++++++++++++++++++ 3 files changed, 107 insertions(+), 6 deletions(-) create mode 100644 src/commands/offer.ts diff --git a/src/api/loc.sh/routes/internal.ts b/src/api/loc.sh/routes/internal.ts index 2695170..178bd3f 100644 --- a/src/api/loc.sh/routes/internal.ts +++ b/src/api/loc.sh/routes/internal.ts @@ -1,16 +1,21 @@ +import { TextChannel } from 'eris'; /* eslint-disable no-shadow */ -import { Route, Server } from '../../../class'; +import jwt from 'jsonwebtoken'; +import { Route, Server, LocalStorage } from '../../../class'; // import acknowledgements from '../../../configs/acknowledgements.json'; export default class Internal extends Route { public timeout: Set; + public acceptedOffers: LocalStorage; + constructor(server: Server) { super(server); this.timeout = new Set(); this.conf = { path: '/int', }; + this.acceptedOffers = new LocalStorage('accepted-offers'); } public bind() { @@ -33,6 +38,50 @@ export default class Internal extends Route { } }); + this.router.get('/offer', async (req, res) => { + try { + res.setHeader('Access-Control-Allow-Origin', '*'); + if (!req.query.code) return res.status(401).json({ code: this.constants.codes.UNAUTHORIZED, message: this.constants.messages.UNAUTHORIZED }); + if (await this.acceptedOffers.get(req.query.code.toString())) return res.status(401).json({ code: this.constants.codes.UNAUTHORIZED, message: this.constants.messages.UNAUTHORIZED }); + let offer: { + userID?: string, + staffID?: string, + channelID?: string, + messageID?: string, + pin?: string, + name?: string, + department?: string, + date?: Date, + }; + + try { + offer = <{ + userID?: string, + staffID?: string, + channelID?: string, + messageID?: string, + pin?: string, + name?: string, + department?: string, + date?: Date, + }> jwt.verify(req.query.code.toString(), this.server.client.config.internalKey); + } catch { + return res.status(401).json({ code: this.constants.codes.UNAUTHORIZED, message: this.constants.messages.UNAUTHORIZED }); + } + const chan = this.server.client.guilds.get(this.constants.discord.SERVER_ID).channels.get(offer.channelID); + await chan.createMessage(`__**PRE-APPROVED OFFER ACCEPTED**__\n<@${offer.staffID}>`); + const message = await chan.getMessage(offer.messageID); + const args = []; + args.push(offer.userID, 'hard'); + `${offer.department}:${offer.name}`.split(' ').forEach((item) => args.push(item)); + await this.server.client.commands.get('score').run(message, args); + await this.acceptedOffers.set(req.query.code.toString(), true); + return res.sendStatus(200); + } catch (err) { + return this.handleError(err, res); + } + }); + this.router.get('/score', async (req, res) => { try { res.setHeader('Access-Control-Allow-Origin', '*'); @@ -45,17 +94,20 @@ export default class Internal extends Route { if (!score) return res.status(401).json({ code: this.constants.codes.UNAUTHORIZED, message: this.constants.messages.UNAUTHORIZED }); const member = await this.server.client.getRESTGuildMember(this.constants.discord.SERVER_ID, score.userID); if (!member) return res.status(401).json({ code: this.constants.codes.UNAUTHORIZED, message: this.constants.messages.UNAUTHORIZED }); - + let updated = false; if (req.query.staff) { const args = req.query.staff.toString(); const staffScore = await this.server.client.db.Score.findOne({ pin: [Number(args.split('-')[0]), Number(args.split('-')[1]), Number(args.split('-')[2])] }).lean().exec(); if (!staffScore) return res.status(401).json({ code: this.constants.codes.UNAUTHORIZED, message: this.constants.messages.UNAUTHORIZED }); if (!staffScore.staff) return res.status(401).json({ code: this.constants.codes.UNAUTHORIZED, message: this.constants.messages.UNAUTHORIZED }); this.timeout.delete(req.ip); - await this.server.client.db.Score.updateOne({ userID: score.userID }, { $addToSet: { softInquiries: { name: 'Library of Code sp-us | Staff Team via report.libraryofcode.org', date: new Date() } } }); - } else { - await this.server.client.db.Score.updateOne({ userID: score.userID }, { $addToSet: { softInquiries: { name: `${member.username} via report.libraryofcode.org @ IP ${req.ip}`, date: new Date() } } }); - } + if (staffScore.userID === score.userID) { + updated = true; + await this.server.client.db.Score.updateOne({ userID: score.userID }, { $addToSet: { softInquiries: { name: `${member.username} via report.libraryofcode.org @ IP ${req.ip}`, date: new Date() } } }); + } else { + await this.server.client.db.Score.updateOne({ userID: score.userID }, { $addToSet: { softInquiries: { name: 'Library of Code sp-us | Staff Team via report.libraryofcode.org', date: new Date() } } }); + } + } else if (!updated) await this.server.client.db.Score.updateOne({ userID: score.userID }, { $addToSet: { softInquiries: { name: `${member.username} via report.libraryofcode.org @ IP ${req.ip}`, date: new Date() } } }); score = await this.server.client.db.Score.findOne({ pin: [Number(args.split('-')[0]), Number(args.split('-')[1]), Number(args.split('-')[2])] }).lean().exec(); let totalScore = '0'; diff --git a/src/commands/index.ts b/src/commands/index.ts index e9ab990..41469fc 100644 --- a/src/commands/index.ts +++ b/src/commands/index.ts @@ -19,6 +19,7 @@ export { default as members } from './members'; export { default as mute } from './mute'; export { default as notes } from './notes'; export { default as npm } from './npm'; +export { default as offer } from './offer'; export { default as page } from './page'; export { default as ping } from './ping'; export { default as rank } from './rank'; diff --git a/src/commands/offer.ts b/src/commands/offer.ts new file mode 100644 index 0000000..749d1f0 --- /dev/null +++ b/src/commands/offer.ts @@ -0,0 +1,48 @@ +/* eslint-disable default-case */ +import jwt from 'jsonwebtoken'; +import { Message } from 'eris'; +import { Client, Command } from '../class'; + +export default class Score extends Command { + constructor(client: Client) { + super(client); + this.name = 'offer'; + this.description = 'Pre-approves a member for an offer. Will run a hard-pull automatically on acceptance.'; + this.usage = `${this.client.config.prefix}offer :`; + this.permissions = 4; + this.aliases = ['qualify']; + this.guildOnly = true; + this.enabled = true; + } + + public async run(message: Message, args: string[]) { + try { + if (!args[0]) return this.client.commands.get('help').run(message, [this.name]); + const member = this.client.util.resolveMember(args[0], this.mainGuild); + if (!member) return this.error(message.channel, 'Could not find member.'); + const score = await this.client.db.Score.findOne({ userID: member.user.id }).lean().exec(); + if (!score) return this.error(message.channel, 'Could not find score report for this user.'); + + const name = args.slice(1).join(' ').split(':')[0]; + const dept = args.slice(1).join(' ').split(':')[1]; + if (!name || !dept) return this.error(message.channel, 'Invalid arguments.'); + + const token = jwt.sign({ + userID: member.user.id, + staffID: message.author.id, + channelID: message.channel.id, + messageID: message.id, + pin: score.pin.join('-'), + name, + department: dept, + date: new Date(), + }, this.client.config.internalKey, { expiresIn: '6h' }); + await this.client.getDMChannel(member.user.id).then((chan) => { + chan.createMessage(`__**Offer Pre-Approval**__\nYou have been pre-approved for an offer! If you wish to accept this offer, please enter the offer code at https://report.libraryofcode.org/. Do not share this code with anyone else. This offer automatically expires in 6 hours. Your report will be Hard Inquiried immedaitely after accepting this offer.\n\n**Department:** ${dept.toUpperCase()}\n**Offer for:** ${name}\n\n\`${token}\``); + }).catch(() => this.error(message.channel, 'Could not DM member.')); + return this.success(message.channel, `Offer sent.\n\n\`${token}\``); + } catch (err) { + return this.client.util.handleError(err, message, this); + } + } +}