add application services

pull/29/head
Matthew 2020-10-30 22:33:21 -04:00
parent c13c19c080
commit d4b24ddec2
No known key found for this signature in database
GPG Key ID: 210AF32ADE3B5C4B
4 changed files with 106 additions and 1 deletions

View File

@ -1,7 +1,11 @@
/* eslint-disable no-eval */
import Bull from 'bull';
import { Client } from '.';
import { TextableChannel } from 'eris';
import { Client, RichEmbed } from '.';
import { ScoreInterface } from '../models';
import { apply as Apply } from '../commands';
export default class Queue {
public client: Client;
@ -42,6 +46,9 @@ export default class Queue {
this.queues.score.on('completed', (job) => {
this.client.util.signale.success(`Job with id ${job.id} has been completed`);
});
this.queues.score.on('error', async (err) => {
this.client.util.handleError(err);
});
}
protected setProcessors() {
@ -51,9 +58,30 @@ export default class Queue {
await this.client.db.Score.updateOne({ userID: job.data.score.userID }, { $set: { pin: [this.client.util.randomNumber(100, 999), this.client.util.randomNumber(10, 99), this.client.util.randomNumber(1000, 9999)] } });
}
});
this.queues.score.process('score::apply', async (job: Bull.Job<{ channelInformation: { messageID: string, guildID: string, channelID: string }, url: string, userID: string, func: string }>) => {
const application = await Apply.apply(this.client, job.data.url, job.data.userID);
const guild = this.client.guilds.get(job.data.channelInformation.guildID);
const channel = <TextableChannel> guild.channels.get(job.data.channelInformation.channelID);
const message = await channel.getMessage(job.data.channelInformation.messageID);
await message.delete();
const embed = new RichEmbed();
embed.setTitle('Application Decision');
embed.addField('Status', application.decision, true);
embed.addField('UserID', job.data.userID, true);
embed.addField('Job ID', job.id.toString(), true);
embed.setFooter(this.client.user.username, this.client.user.avatarURL);
embed.setTimestamp();
await channel.createMessage({ content: `<@${job.data.userID}>`, embed });
const func = eval(job.data.func);
if (application.status === 'SUCCESS' && application.decision === 'APPROVED') await func(this.client, job.data.userID);
});
}
public updateScore(score: ScoreInterface, total: number, activity: number, roles: number, moderation: number, cloudServices: number, other: number, staff: number) {
this.queues.score.add('score::update', { score, total, activity, roles, moderation, cloudServices, other, staff });
}
public processApplication(channelInformation: { messageID: string, guildID: string, channelID: string }, url: string, userID: string, func: string) {
return this.queues.score.add('score::apply', { channelInformation, url, userID, func });
}
}

View File

@ -18,10 +18,12 @@ export default class AddMerchant extends Command {
try {
if (!args[1]) return this.client.commands.get('help').run(message, [this.name]);
if ((Number(args[0]) !== 0) && (Number(args[0]) !== 1)) return this.error(message.channel, 'Invalid permissions.');
if ((Number(args[1]) !== 0) && (Number(args[1]) !== 1)) return this.error(message.channel, 'Invalid permissions.');
const key = randomBytes(20).toString('hex');
const merchant = await (new this.client.db.Merchant({
name: args.slice(2).join(' '),
privileged: Number(args[0]),
type: Number(args[1]),
key,
pulls: [],
})).save();

74
src/commands/apply.ts Normal file
View File

@ -0,0 +1,74 @@
import type { AxiosError } from 'axios';
import axios from 'axios';
import { Member, Message } from 'eris';
import { Client, Command, RichEmbed } from '../class';
export default class Apply extends Command {
public services: Map<string, { description: string, url: string, validation: (...cond: any) => Promise<boolean> | boolean, func: Function }>;
constructor(client: Client) {
super(client);
this.name = 'apply';
this.description = 'apply';
this.usage = `${this.client.config.prefix}apply [serviceName]`;
this.permissions = 0;
this.guildOnly = true;
this.enabled = true;
this.setServices();
}
protected setServices() {
this.services = new Map();
this.services.set('role::constants', {
description: 'Constants role assignment.',
url: 'https://eds.libraryofcode.org/roles/constants',
validation: (member: Member) => !member.roles.includes('511771731891847168'),
func: async (client: Client, ...data: any[]) => {
const member = await client.guilds.get('446067825673633794').getRESTMember(data[0]);
await member.addRole('511771731891847168');
},
});
}
public async run(message: Message, args: string[]) {
try {
if (!args[0]) {
const embed = new RichEmbed();
embed.setTitle('Available Instant Applications');
for (const service of this.services) {
embed.addField(service[0], `${service[1].description} | Run \`${this.client.config.prefix}apply ${service[0]}\` to apply.`, true);
}
embed.setFooter(this.client.user.username, this.client.user.avatarURL);
embed.setTimestamp();
return message.channel.createMessage({ embed });
}
if (!this.services.has(args[0])) return this.error(message.channel, 'Invalid service/product name.');
const service = this.services.get(args[0]);
const test = await this.services.get(args[0]).validation(message.member);
if (!test) return this.error(message.channel, 'A condition exists which prevents you from applying, please try again later.');
const msg = await this.loading(message.channel, 'Thank you for submitting an application. We are currently processing it, you will be pinged here shortly with the decision.');
return await this.client.queue.processApplication({ channelID: message.channel.id, guildID: this.mainGuild.id, messageID: msg.id }, service.url, message.author.id, service.func.toString());
} catch (err) {
return this.client.util.handleError(err, message, this);
}
}
public static async apply(client: Client, url: string, userID: string) {
try {
const { data } = await axios({
method: 'get',
url: `${url}?userID=${userID}&auth=${client.config.internalKey}`,
});
return {
status: 'SUCCESS',
decision: data.decision,
};
} catch (err) {
const error = <AxiosError>err;
if (error.response?.status === 404 || error.response.status === 400 || error.response.status === 401) return { status: 'CLIENT_ERROR', decision: 'PRE-DECLINED' };
return { status: 'SERVER_ERROR', decision: 'PRE-DECLINED' };
}
}
}

View File

@ -3,6 +3,7 @@ export { default as addmerchant } from './addmerchant';
export { default as addnote } from './addnote';
export { default as addrank } from './addrank';
export { default as addredirect } from './addredirect';
export { default as apply } from './apply';
export { default as ban } from './ban';
export { default as delitem } from './delitem';
export { default as delmerchant } from './delmerchant';