error handling refactor x2

master
Matthew 2022-03-22 12:15:54 -04:00
parent 26102c3bf4
commit c94ff17e2b
No known key found for this signature in database
GPG Key ID: 210AF32ADE3B5C4B
70 changed files with 7616 additions and 5970 deletions

View File

@ -32,6 +32,8 @@
},
"dependencies": {
"@google-cloud/text-to-speech": "^3.4.0",
"@sentry/node": "^6.19.1",
"@sentry/tracing": "^6.19.1",
"ari-client": "^2.2.0",
"asterisk-manager": "^0.2.0",
"auth0": "^2.37.0",

View File

@ -5,6 +5,8 @@ import pluris from 'pluris';
import mongoose from 'mongoose';
import { promises as fs } from 'fs';
import Database from 'cr-db';
import * as Sentry from '@sentry/node';
import * as Tracing from '@sentry/tracing';
import { Collection, Command, InteractionCommand, LocalStorage, Queue, Util, ServerManagement, Event } from '.';
import { Config } from '../../types'; // eslint-disable-line
@ -40,6 +42,7 @@ export default class Client extends eris.Client {
constructor(token: string, options?: eris.ClientOptions) {
super(token, options);
this.setupSentry();
this.commands = new Collection<Command>();
this.interactions = new Collection<InteractionCommand>();
this.events = new Collection<Event>();
@ -65,6 +68,13 @@ export default class Client extends eris.Client {
}
public setupSentry() {
Sentry.init({
dsn: 'https://323f6626a7104be7859088750b91abe1@sentry.libraryofcode.org/2',
tracesSampleRate: 0.25,
});
}
public async loadDatabase() {
mongoose.connect(this.config.mongoDB, {
minPoolSize: 50,

View File

@ -45,6 +45,7 @@ export default class Command {
* Determines if the command is enabled or not.
*/
// eslint-disable-next-line no-use-before-define
public subcommands?: Collection<Command>;
public subcmds?: any[];

View File

@ -1,7 +1,7 @@
import { Client } from '.';
export default class Event {
public client: Client
public client: Client;
public event: string;

View File

@ -8,7 +8,7 @@ export default class Handler {
public options: {
available?: boolean,
}
};
constructor(pbx: PBX) {
this.pbx = pbx;

View File

@ -7,7 +7,7 @@ type JSONData = [{ key: string, value: any }?];
/**
* Persistant local JSON-based storage.
* Persistent local JSON-based storage.
* - auto-locking system to prevent corrupted data
* - uses gzip compression to keep DB storage space utilization low
* @author Matthew <matthew@staff.libraryofcode.org>

View File

@ -3,31 +3,31 @@
import { EmbedOptions } from 'eris';
export default class RichEmbed implements EmbedOptions {
title?: string
title?: string;
type?: string
type?: string;
description?: string
description?: string;
url?: string
url?: string;
timestamp?: string | Date
timestamp?: string | Date;
color?: number
color?: number;
footer?: { text: string, icon_url?: string, proxy_icon_url?: string}
footer?: { text: string, icon_url?: string, proxy_icon_url?: string};
image?: { url?: string, proxy_url?: string, height?: number, width?: number }
image?: { url?: string, proxy_url?: string, height?: number, width?: number };
thumbnail?: { url?: string, proxy_url?: string, height?: number, width?: number }
thumbnail?: { url?: string, proxy_url?: string, height?: number, width?: number };
video?: { url: string, height?: number, width?: number }
video?: { url: string, height?: number, width?: number };
provider?: { name: string, url?: string}
provider?: { name: string, url?: string};
author?: { name: string, url?: string, proxy_icon_url?: string, icon_url?: string}
author?: { name: string, url?: string, proxy_icon_url?: string, icon_url?: string};
fields?: {name: string, value: string, inline?: boolean}[]
fields?: {name: string, value: string, inline?: boolean}[];
constructor(data: EmbedOptions = {}) {
this.title = data.title;

View File

@ -6,6 +6,7 @@ import childProcess from 'child_process';
import { promisify } from 'util';
import signale from 'signale';
import { Member, Message, Guild, PrivateChannel, GroupChannel, Role, AnyGuildChannel, WebhookPayload } from 'eris';
import * as Sentry from '@sentry/node';
import { Client, Command, Moderation, PBX, Report, RichEmbed } from '.';
import { statusMessages as emotes } from '../configs/emotes.json';
@ -232,24 +233,8 @@ export default class Util {
public async handleError(error: Error, message?: Message, command?: Command, disable = true): Promise<void> {
try {
Sentry.captureException(error);
this.signale.error(error);
const info: WebhookPayload = { content: `\`\`\`js\n${error.stack || error}\n\`\`\``, embeds: [] };
if (message) {
const embed = new RichEmbed();
embed.setColor('FF0000');
embed.setAuthor(`Error caused by ${message.author.username}#${message.author.discriminator}`, message.author.avatarURL);
embed.setTitle('Message content');
embed.setDescription(message.content);
embed.addField('User', `${message.author.mention} (\`${message.author.id}\`)`, true);
embed.addField('Channel', message.channel.mention, true);
let guild: string;
if (message.channel instanceof PrivateChannel || message.channel instanceof GroupChannel) guild = '@me';
else guild = message.channel.guild.id;
embed.addField('Message link', `[Click here](https://discordapp.com/channels/${guild}/${message.channel.id}/${message.id})`, true);
embed.setTimestamp(new Date(message.timestamp));
info.embeds.push(embed);
}
await this.client.executeWebhook(this.client.config.webhookID, this.client.config.webhookToken, info);
const msg = message ? message.content.slice(this.client.config.prefix.length).trim().split(/ +/g) : [];
if (command && disable) this.resolveCommand(msg).then((c) => { c.cmd.enabled = false; });
if (message) message.channel.createMessage(`***${this.emojis.ERROR} An unexpected error has occured - please contact a Staff member.${command && disable ? ' This command has been disabled.' : ''}***`);
@ -344,7 +329,6 @@ export default class Util {
}
public capsFirstLetter(string?: string): string | void {
if (typeof string !== 'string') return undefined;
return string.substring(0, 1).toUpperCase() + string.substring(1);
}
}

View File

@ -12,7 +12,6 @@ export default class AddItem extends Command {
}
public async run(message: Message, args: string[]) {
try {
if (args.length < 1) {
const embed = new RichEmbed();
embed.setTitle('Whois Data Codes');
@ -53,8 +52,5 @@ export default class AddItem extends Command {
return message.channel.createMessage(`***${this.client.util.emojis.SUCCESS} Added language code ${args[0]} to profile.***`);
}
return message.channel.createMessage(`***${this.client.util.emojis.ERROR} Invalid data code.***`);
} catch (err) {
return this.client.util.handleError(err, message, this);
}
}
}

View File

@ -15,7 +15,6 @@ export default class AddMerchant extends Command {
}
public async run(message: Message, args: string[]) {
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.');
@ -28,8 +27,5 @@ export default class AddMerchant extends Command {
pulls: [],
})).save();
return this.success(message.channel, `Created merchant (${merchant._id}). \`${args.slice(2).join(' ')}\`\n\n\`${key}\``);
} catch (err) {
return this.client.util.handleError(err, message, this);
}
}
}

View File

@ -13,7 +13,6 @@ export default class AddNote extends Command {
}
public async run(message: Message, args: string[]) {
try {
if (!args[0] || args.length < 1) return this.client.commands.get('help').run(message, [this.name]);
let user = this.client.util.resolveMember(args[0], this.mainGuild)?.user;
if (!user) user = await this.client.getRESTUser(args[0]);
@ -33,8 +32,5 @@ export default class AddNote extends Command {
}
const saved = await (new this.client.db.mongo.Note(note).save());
return this.success(message.channel, `Successfully created Note # \`${saved._id}\`.`);
} catch (err) {
return this.client.util.handleError(err, message, this);
}
}
}

View File

@ -14,7 +14,6 @@ export default class AddPromoCode extends Command {
}
public async run(message: Message, args: string[]) {
try {
if (!args[0]) return this.client.commands.get('help').run(message, [this.name]);
try {
const pcd = await this.client.stripe.promotionCodes.retrieve(args[0]);
@ -26,8 +25,5 @@ export default class AddPromoCode extends Command {
} catch (err) {
return this.error(message.channel, 'Promotional API ID doesn\'t exist.');
}
} catch (err) {
return this.client.util.handleError(err, message, this);
}
}
}

View File

@ -13,7 +13,6 @@ export default class AddRank extends Command {
}
public async run(message: Message, args: string[]) {
try {
if (!args[0]) return this.client.commands.get('help').run(message, [this.name]);
if (!args[1]) return this.error(message.channel, 'Permissions are required.');
if (!args[2]) return this.error(message.channel, 'A description is required');
@ -38,8 +37,5 @@ export default class AddRank extends Command {
});
await entry.save();
return this.success(message.channel, `Role ${role.name} is now self-assignable.`);
} catch (err) {
return this.client.util.handleError(err, message, this);
}
}
}

View File

@ -13,7 +13,6 @@ export default class AddRedirect extends Command {
}
public async run(message: Message, args: string[]) {
try {
if (!args[0]) return this.client.commands.get('help').run(message, [this.name]);
const check = await this.client.db.mongo.Redirect.findOne({ key: args[1].toLowerCase() });
if (check) return this.error(message.channel, `Redirect key ${args[1].toLowerCase()} already exists. Linked to: ${check.to}`);
@ -31,8 +30,5 @@ export default class AddRedirect extends Command {
});
await redirect.save();
return this.success(message.channel, `Redirect https://loc.sh/${args[1].toLowerCase()} -> ${args[0]} is now active.`);
} catch (err) {
return this.client.util.handleError(err, message, this);
}
}
}

View File

@ -177,7 +177,6 @@ export default class Apply extends Command {
}
public async run(message: Message, args: string[]) {
try {
if (!args[0] || args[0] === 'full') {
const embed = new RichEmbed();
embed.setTitle('Instant Application Service [IAS]');
@ -205,10 +204,7 @@ export default class Apply extends Command {
if (!test) return this.error(message.channel, 'A condition exists which prevents you from applying, please try again later.');
if (service.saaOnly) return this.error(message.channel, 'This application can only be ran as a Staff-Assisted Application and cannot be ran automatically. Please DM <@457750238208327691> to apply.');
const msg = await this.loading(message.channel, 'Thank you for submitting an application. We are currently processing it, you will receive a DM with a 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 ? service.func.toString() : undefined);
} catch (err) {
return this.client.util.handleError(err, message, this);
}
return this.client.queue.processApplication({ channelID: message.channel.id, guildID: this.mainGuild.id, messageID: msg.id }, service.url, message.author.id, service.func ? service.func.toString() : undefined);
}
public static async apply(client: Client, url: string, userID: string) {

View File

@ -14,7 +14,6 @@ export default class Ban extends Command {
}
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);
let user: User;
@ -46,8 +45,5 @@ export default class Ban extends Command {
}
await this.client.util.moderation.ban(user, message.member, momentMilliseconds, reason);
return this.success(message.channel, `${user.username}#${user.discriminator} has been banned.`);
} catch (err) {
return this.client.util.handleError(err, message, this, false);
}
}
}

View File

@ -19,7 +19,6 @@ export default class Billing extends Command {
}
public async run(message: Message) {
try {
const response = <{
found: boolean,
emailAddress?: string,
@ -47,10 +46,7 @@ export default class Billing extends Command {
const chan = await this.client.getDMChannel(message.author.id);
await chan.createMessage(`__***Billing Account Portal***__\nClick here: https://loc.sh/${uid}\n\nYou will be redirected to your billing portal, please note the link expires after 5 minutes.`)
.catch(() => { return this.error(message.channel, 'Failed to privately send your billing portal link to you.'); });
return await this.success(message.channel, 'Your Billing Portal information has been DMed to you.');
} catch (err) {
return this.client.util.handleError(err, message, this);
}
.catch(() => this.error(message.channel, 'Failed to privately send your billing portal link to you.'));
return this.success(message.channel, 'Your Billing Portal information has been DMed to you.');
}
}

View File

@ -16,7 +16,6 @@ export default class Billing_T3 extends Command {
}
public async run(message: Message, args: string[]) {
try {
await message.delete();
const response = <{
found: boolean,
@ -55,8 +54,5 @@ export default class Billing_T3 extends Command {
const chan = await this.client.getDMChannel(message.author.id);
await chan.createMessage(`__**Invoice for New Subscription**__\n${invoice.hosted_invoice_url}\n\n*Please click on the link above to pay for your subscription.*`);
return this.success(message.channel, 'Transaction processed.');
} catch (err) {
return this.client.util.handleError(err, message, this);
}
}
}

View File

@ -16,7 +16,6 @@ export default class Callback extends Command {
}
public async run(message: Message, args: string[]) {
try {
if (!args[0]) return this.client.commands.get('help').run(message, [this.name]);
if (message.channel.type === 0) await message.delete();
const member = this.mainGuild.members.get(message.author.id);
@ -45,8 +44,5 @@ export default class Callback extends Command {
const msg = await chan.createMessage({ content: '<@&780519428873781298>', embed });
await msg.addReaction('modSuccess:578750988907970567');
return message.channel.createMessage('__**Callback Request**__\nYour callback request has been sent to our agents, you should receive a callback within 1-24 hours from the date of this request. The number you will be called from is listed below.\n\n**Callback Number:** +1 202-750-2585\n**Callback Region:** Washington, D.C., United States\n\n\n*Your number is never stored on our systems at any time, as soon as your call is taken by an agent your number is deleted from notification channels.*');
} catch (err) {
return this.client.util.handleError(err, message, this);
}
}
}

View File

@ -12,7 +12,6 @@ export default class DelItem extends Command {
}
public async run(message: Message, args: string[]) {
try {
if (args.length < 1) {
const embed = new RichEmbed();
embed.setTitle('Whois Data Codes');
@ -39,8 +38,5 @@ export default class DelItem extends Command {
return message.channel.createMessage(`***${this.client.util.emojis.SUCCESS} Removed language code ${args[0]} from profile.***`);
}
return message.channel.createMessage(`***${this.client.util.emojis.ERROR} Invalid data code.***`);
} catch (err) {
return this.client.util.handleError(err, message, this);
}
}
}

View File

@ -14,13 +14,9 @@ export default class DelMerchant extends Command {
}
public async run(message: Message, args: string[]) {
try {
if (!args[0]) return this.client.commands.get('help').run(message, [this.name]);
const merchant = await this.client.db.mongo.Merchant.findOne({ key: args[0] });
if (!merchant) return this.error(message.channel, 'Merchant specified does not exist.');
return this.success(message.channel, `Deleted merchant \`${merchant._id}\`.`);
} catch (err) {
return this.client.util.handleError(err, message, this);
}
}
}

View File

@ -13,14 +13,10 @@ export default class DelNote extends Command {
}
public async run(message: Message, args: string[]) {
try {
if (!args[0]) return this.client.commands.get('help').run(message, [this.name]);
const note = await this.client.db.mongo.Note.findOne({ _id: args[0] }).lean().exec().catch(() => {});
if (!note) return this.error(message.channel, 'Could not locate that note.');
await this.client.db.mongo.Note.deleteOne({ _id: note._id });
return this.success(message.channel, `Note # \`${note._id}\` has been deleted.`);
} catch (err) {
return this.client.util.handleError(err, message, this);
}
}
}

View File

@ -14,7 +14,6 @@ export default class DeletePromoCode extends Command {
}
public async run(message: Message, args: string[]) {
try {
if (!args[0]) return this.client.commands.get('help').run(message, [this.name]);
try {
await this.client.stripe.promotionCodes.retrieve(args[0]);
@ -22,8 +21,5 @@ export default class DeletePromoCode extends Command {
} catch (err) {
return this.error(message.channel, 'Promotional API ID doesn\'t exist.');
}
} catch (err) {
return this.client.util.handleError(err, message, this);
}
}
}

View File

@ -13,7 +13,6 @@ export default class DelRank extends Command {
}
public async run(message: Message, args: string[]) {
try {
if (!args[0]) return this.client.commands.get('help').run(message, [this.name]);
const role = this.client.util.resolveRole(args[0], this.mainGuild);
if (!role) return this.error(message.channel, 'The role you specified doesn\'t appear to exist.');
@ -23,8 +22,5 @@ export default class DelRank extends Command {
await this.client.db.mongo.Rank.deleteOne({ roleID: role.id });
return this.success(message.channel, `Role ${role.name} is no longer self-assignable.`);
} catch (err) {
return this.client.util.handleError(err, message, this);
}
}
}

View File

@ -13,14 +13,10 @@ export default class DelRedirect extends Command {
}
public async run(message: Message, args: string[]) {
try {
if (!args[0]) return this.client.commands.get('help').run(message, [this.name]);
const check = await this.client.db.mongo.Redirect.findOne({ key: args[0].toLowerCase() });
if (!check) return this.error(message.channel, `Redirect key ${args[0].toLowerCase()} doesn't exist.`);
await this.client.db.mongo.Redirect.deleteOne({ key: args[0].toLowerCase() });
return this.success(message.channel, `Deleted redirect https://loc.sh/${args[0].toLowerCase()}.`);
} catch (err) {
return this.client.util.handleError(err, message, this);
}
}
}

View File

@ -14,7 +14,6 @@ export default class DJS extends Command {
}
public async run(message: Message, args: string[]) {
try {
if (!args[0]) return this.client.commands.get('help').run(message, [this.name]);
let res: AxiosResponse<EmbedOptions>;
@ -30,8 +29,5 @@ export default class DJS extends Command {
embed.setFooter(this.client.user.username, this.client.user.avatarURL);
embed.setTimestamp();
return message.channel.createMessage({ embed });
} catch (err) {
return this.client.util.handleError(err, message, this);
}
}
}

View File

@ -14,7 +14,6 @@ export default class Eris extends Command {
}
public async run(message: Message, args: string[]) {
try {
if (!args[0]) return this.client.commands.get('help').run(message, [this.name]);
let res: AxiosResponse<{embed: EmbedOptions}>;
@ -26,8 +25,5 @@ export default class Eris extends Command {
}
return message.channel.createMessage(res.data);
} catch (err) {
return this.client.util.handleError(err, message, this);
}
}
}

View File

@ -15,7 +15,6 @@ export default class Eval extends Command {
}
public async run(message: Message, args: string[]) {
try {
const evalMessage = message.content.slice(this.client.config.prefix.length).trim().split(' ').slice(1);
let evalString = evalMessage.join(' ').trim();
let evaled: any;
@ -61,8 +60,5 @@ export default class Eval extends Command {
}
return display.forEach((m) => message.channel.createMessage(`\`\`\`js\n${m}\n\`\`\``));
} catch (err) {
return this.client.util.handleError(err, message, this, false);
}
}
}

View File

@ -2,6 +2,7 @@
import { Activity, Member, Message } from 'eris';
import { Client, Command, RichEmbed } from '../class';
// eslint-disable-next-line no-shadow
enum ActivityType {
PLAYING,
STREAMING,
@ -23,7 +24,6 @@ export default class Game extends Command {
}
public async run(message: Message, args: string[]) {
try {
let member: Member;
if (!args[0]) member = message.member;
else {
@ -57,8 +57,5 @@ export default class Game extends Command {
return this.error(message.channel, 'Only Spotify games are supported at this time.');
}
return message.channel.createMessage({ embed });
} catch (err) {
return this.client.util.handleError(err, message, this);
}
}
}

View File

@ -14,7 +14,6 @@ export default class Help extends Command {
}
public async run(message: Message, args: string[]) {
try {
if (args.length > 0) {
const resolved = await this.client.util.resolveCommand(args, message);
if (!resolved) return this.error(message.channel, 'The command you provided doesn\'t exist.');
@ -118,8 +117,5 @@ export default class Help extends Command {
});
if (cmdPages.length === 1) return message.channel.createMessage({ embed: cmdPages[0] });
return createPaginationEmbed(message, cmdPages);
} catch (err) {
return this.client.util.handleError(err, message, this, false);
}
}
}

View File

@ -1,6 +1,7 @@
import { Message } from 'eris';
import { totalmem } from 'os';
import { Client, Command, RichEmbed } from '../class';
// eslint-disable-next-line import/no-relative-packages
import { version as tsVersion } from '../../node_modules/typescript/package.json';
export default class Info extends Command {
@ -14,11 +15,11 @@ export default class Info extends Command {
}
public async run(message: Message) {
try {
const embed = new RichEmbed();
embed.setTitle('Information');
embed.setThumbnail(this.client.user.avatarURL);
embed.setDescription(`*See \`${this.client.config.prefix}sysinfo\` for more information on libraries used by this application.*`);
embed.addField('Developers', 'Library of Code sp-us | Dept. of Engineering', true);
embed.addField('Version', 'Rolling Release', true);
embed.addField('Language(s)', '<:TypeScript:703451285789343774> TypeScript', true);
embed.addField('Runtime', `Node (${process.version})`, true);
@ -30,8 +31,5 @@ export default class Info extends Command {
embed.setFooter(this.client.user.username, this.client.user.avatarURL);
embed.setTimestamp();
message.channel.createMessage({ embed });
} catch (err) {
this.client.util.handleError(err, message, this);
}
}
}

View File

@ -20,7 +20,6 @@ export default class Inquiry extends Command {
}
public async run(message: Message, args: string[]) {
try {
if (!args[0]) return this.client.commands.get('help').run(message, [this.name]);
const inquiry = await this.client.db.mongo.Inquiry.findOne({ iid: args[0] });
@ -95,8 +94,5 @@ export default class Inquiry extends Command {
embed.setTimestamp();
embed.setFooter('Inquiry performed on', this.client.user.avatarURL);
return message.channel.createMessage({ embed });
} catch (err) {
return this.client.util.handleError(err, message, this);
}
}
}

View File

@ -1,4 +1,5 @@
import { Message, TextChannel } from 'eris';
import axios from 'axios';
import { apply as Apply } from '.';
import { Client, Command, RichEmbed } from '../class';
@ -17,12 +18,11 @@ export default class Inquiry_Remove extends Command {
}
public async run(message: Message, args: string[]) {
try {
if (!args[0]) return this.client.commands.get('help').run(message, [this.name]);
const inquiry = await this.client.db.mongo.Inquiry.findOne({ iid: args[0] });
if (!inquiry) return this.error(message.channel, 'Unable to find Inquiry.');
const member = await this.client.util.resolveMember(inquiry.userID, this.mainGuild);
const member = this.client.util.resolveMember(inquiry.userID, this.mainGuild);
if (!member) return this.error(message.channel, 'Unable to locate member.');
const report = await this.client.db.mongo.Score.findOne({ userID: member.id });
if (!report) return this.error(message.channel, 'Unable to locate Community Report.');
@ -40,6 +40,15 @@ export default class Inquiry_Remove extends Command {
embed.setFooter(this.client.user.username, this.client.user.avatarURL);
embed.setTimestamp();
try {
await axios({
method: 'DELETE',
url: `https://eds.libraryofcode.org/dec/${inquiry.iid}?auth=${this.client.config.internalKey}`,
});
} catch (e) {
this.error(message.channel, `An error occurred while changing EDS data: ${e}\n*(This does not mean that the operation failed.)*`);
}
const log = <TextChannel> this.client.guilds.get(this.client.config.guildID).channels.get('611584771356622849');
log.createMessage({ embed });
@ -49,8 +58,5 @@ export default class Inquiry_Remove extends Command {
}
return this.success(message.channel, 'Inquiry successfully deleted.');
} catch (err) {
return this.client.util.handleError(err, message, this);
}
}
}

View File

@ -14,7 +14,6 @@ export default class Intercom extends Command {
}
public async run(message: Message, args: string[]) {
try {
if (!args[0]) return this.client.commands.get('help').run(message, [this.name]);
const loading = await this.loading(message.channel, 'Synthesizing text...');
@ -38,8 +37,5 @@ export default class Intercom extends Command {
return loading.edit(`***${this.client.util.emojis.SUCCESS} Successfully queued intercom message to EXT \`${args[0]}\`.***`);
});
return undefined;
} catch (err) {
return this.client.util.handleError(err, message, this, false);
}
}
}

View File

@ -17,10 +17,6 @@ export default class Judgement extends Command {
}
public async run(message: Message, args: string[]) {
try {
if (!args[0]) return this.client.commands.get('help').run(message, [this.name]);
} catch (err) {
return this.client.util.handleError(err, message, this);
}
}
}

View File

@ -15,7 +15,6 @@ export default class Judgement_Add extends Command {
}
public async run(message: Message, args: string[]) {
try {
if (!args[0]) return this.client.commands.get('help').run(message, ['judgement', 'add']);
if (args.length < 4) return this.client.commands.get('help').run(message, ['judgement', 'add']);
@ -84,8 +83,5 @@ export default class Judgement_Add extends Command {
log.createMessage({ embed });
return this.success(message.channel, `Judgement \`${jid}\` successfully recorded.`);
} catch (err) {
return this.client.util.handleError(err, message, this);
}
}
}

View File

@ -14,7 +14,6 @@ export default class Judgement_Delete extends Command {
}
public async run(message: Message, args: string[]) {
try {
if (!args[0]) return this.client.commands.get('help').run(message, ['judgement', 'delete']);
const member = this.client.util.resolveMember(args[0], this.mainGuild);
@ -35,8 +34,5 @@ export default class Judgement_Delete extends Command {
embed.setTimestamp();
log.createMessage({ embed });
return this.success(message.channel, `Judgement \`${args[0]}\` successfully rescinded.`);
} catch (err) {
return this.client.util.handleError(err, message, this);
}
}
}

View File

@ -13,7 +13,6 @@ export default class Kick extends Command {
}
public async run(message: Message, args: string[]) {
try {
if (!args[0]) return this.client.commands.get('help').run(message, [this.name]);
let user: Member = this.client.util.resolveMember(args[0], this.mainGuild);
if (!user) {
@ -30,8 +29,5 @@ export default class Kick extends Command {
if (reason.length > 512) return this.error(message.channel, 'Kick reasons cannot be longer than 512 characters.');
await this.client.util.moderation.kick(user, message.member, reason);
return this.success(message.channel, `${user.username}#${user.discriminator} has been kicked.`);
} catch (err) {
return this.client.util.handleError(err, message, this, false);
}
}
}

View File

@ -14,7 +14,6 @@ export default class DelRedirect extends Command {
}
public async run(message: Message, args: string[]) {
try {
if (args[0]) {
const redirects = await this.client.db.mongo.Redirect.find({ $or: [{ key: args[0].toLowerCase() }, { to: args[0].toLowerCase() }] });
if (redirects.length <= 0) return this.error(message.channel, 'Could not find an entry matching that query.');
@ -45,8 +44,5 @@ export default class DelRedirect extends Command {
});
if (cmdPages.length === 1) return message.channel.createMessage({ embed: cmdPages[0] });
return createPaginationEmbed(message, cmdPages);
} catch (err) {
return this.client.util.handleError(err, message, this);
}
}
}

View File

@ -14,7 +14,6 @@ export default class Market extends Command {
}
public async run(message: Message, args: string[]) {
try {
if (!args[0]) return this.client.commands.get('help').run(message, [this.name]);
let stock: stockInfo.Stock;
try {
@ -52,8 +51,5 @@ export default class Market extends Command {
embed.setFooter(this.client.user.username, this.client.user.avatarURL);
embed.setTimestamp();
return message.channel.createMessage({ embed });
} catch (err) {
return this.client.util.handleError(err, message, this, false);
}
}
}

View File

@ -14,7 +14,6 @@ export default class Members extends Command {
}
public async run(message: Message, args: string[]) {
try {
await this.mainGuild.fetchAllMembers();
if (!args[0]) {
const embed = new RichEmbed();
@ -80,8 +79,5 @@ export default class Members extends Command {
});
if (cmdPages.length === 1) return message.channel.createMessage({ embed: cmdPages[0] });
return createPaginationEmbed(message, cmdPages);
} catch (err) {
return this.client.util.handleError(err, message, this);
}
}
}

View File

@ -14,7 +14,6 @@ export default class Mute extends Command {
}
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, 'Cannot find user.');
@ -38,8 +37,5 @@ export default class Mute extends Command {
}
await this.client.util.moderation.mute(member.user, message.member, momentMilliseconds, reason);
return this.success(message.channel, `${member.user.username}#${member.user.discriminator} has been muted.`);
} catch (err) {
return this.client.util.handleError(err, message, this, false);
}
}
}

View File

@ -14,7 +14,6 @@ export default class Notes extends Command {
}
public async run(message: Message, args: string[]) {
try {
if (!args[0]) return this.client.commands.get('help').run(message, [this.name]);
let member: Member | User = this.client.util.resolveMember(args[0], this.mainGuild);
if (!member) {
@ -84,8 +83,5 @@ export default class Notes extends Command {
});
if (cmdPages.length === 1) return message.channel.createMessage({ embed: cmdPages[0] });
return createPaginationEmbed(message, cmdPages);
} catch (err) {
return this.client.util.handleError(err, message, this);
}
}
}

View File

@ -14,7 +14,6 @@ export default class NPM extends Command {
}
public async run(message: Message, args: string[]) {
try {
if (!args[0]) return this.client.commands.get('help').run(message, [this.name]);
const res = await axios.get(`https://registry.npmjs.com/${args[0]}`, { validateStatus: (_) => true });
@ -58,8 +57,5 @@ export default class NPM extends Command {
embed.addField('Modification Date', modification, true);
return message.channel.createMessage({ embed });
} catch (err) {
return this.client.util.handleError(err, message, this);
}
}
}

View File

@ -16,7 +16,6 @@ export default class Offer extends Command {
}
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.');
@ -43,8 +42,5 @@ export default class Offer extends Command {
chan.createMessage(`__**Offer Pre-Qualified**__\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 12 hours. Your report will be Hard Inquiried immediately 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);
}
}
}

View File

@ -41,7 +41,6 @@ export default class Page extends Command {
}
public async run(message: Message, args: string[]) {
try {
if (!args[0]) {
this.client.commands.get('help').run(message, [this.name]);
const embed = new RichEmbed();
@ -97,9 +96,6 @@ export default class Page extends Command {
}
loading.delete();
return this.error(message.channel, page.message);
} catch (err) {
return this.client.util.handleError(err, message, this);
}
}
public logPage(sender: { number: string, user?: string }, recipient: { number: string, user?: string }, type: 'discord' | 'email' | 'phone', code: string): void {

View File

@ -12,12 +12,8 @@ export default class Ping extends Command {
}
public async run(message: Message) {
try {
const clientStart: number = Date.now();
const msg: Message = await message.channel.createMessage('🏓 Pong!');
msg.edit(`🏓 Pong!\nClient: \`${Date.now() - clientStart}ms\`\nResponse: \`${msg.createdAt - message.createdAt}ms\``);
} catch (err) {
this.client.util.handleError(err, message, this);
}
}
}

View File

@ -14,7 +14,6 @@ export default class Rank extends Command {
}
public async run(message: Message, args: string[]) {
try {
if (!args[0]) {
const roles = await this.client.db.mongo.Rank.find();
const rankArray: [{ name: string, value: string }?] = [];
@ -66,8 +65,5 @@ export default class Rank extends Command {
this.success(message.channel, `You have removed ${entry.name}.`);
}
return null;
} catch (err) {
return this.client.util.handleError(err, message, this);
}
}
}

View File

@ -12,7 +12,6 @@ export default class Role extends Command {
}
public async run(message: Message, args: string[]) {
try {
if (args.length < 2) 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, 'Member not found');
@ -66,8 +65,5 @@ export default class Role extends Command {
rolesToAdd.forEach((role) => member.addRole(role.id));
rolesToRemove.forEach((role) => member.removeRole(role.id));
return this.success(message.channel, `Changed roles for ${member.username}#${member.discriminator}${rolesToAdd.length > 0 ? `, added \`${rolesToAdd.map((r) => r.name).join('`, `')}\`` : ''}${rolesToRemove.length > 0 ? `, removed \`${rolesToRemove.map((r) => r.name).join('`, `')}\`` : ''}`);
} catch (err) {
return this.client.util.handleError(err, message, this);
}
}
}

View File

@ -14,7 +14,6 @@ export default class Roleinfo extends Command {
}
public async run(message: Message, args: string[]) {
try {
if (!args[0]) return this.client.commands.get('help').run(message, [this.name]);
const role = this.client.util.resolveRole(args.join(' '), this.mainGuild);
@ -50,8 +49,5 @@ export default class Roleinfo extends Command {
embed.addField('Permissions', permsArray.join(', '), true);
}
return message.channel.createMessage({ embed });
} catch (err) {
return this.client.util.handleError(err, message, this);
}
}
}

View File

@ -22,7 +22,6 @@ export default class StaffAssistedApplication extends Command {
}
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);
@ -104,8 +103,5 @@ export default class StaffAssistedApplication extends Command {
chan.createMessage({ embed: notificationEmbed }).then(() => this.success(message.channel, 'SAA successfully queued.')).catch(() => this.error(message.channel, 'Unable to deliver notification to user.'));
loading.delete().catch(() => {});
} catch (err) {
return this.client.util.handleError(err, message, this);
}
}
}

View File

@ -19,7 +19,6 @@ export default class SAA_Approve extends Command {
}
public async run(message: Message, args: string[]) {
try {
if (!args[0]) return this.client.commands.get('help').run(message, [this.name]);
const saa = await this.client.db.mongo.SAA.findOne({ applicationID: args[0] }).lean().exec();
@ -63,8 +62,5 @@ export default class SAA_Approve extends Command {
}
await this.client.db.mongo.SAA.deleteOne({ _id: saa._id }).lean().exec();
} catch (err) {
return this.client.util.handleError(err, message, this);
}
}
}

View File

@ -18,7 +18,6 @@ export default class SAA_Decline extends Command {
}
public async run(message: Message, args: string[]) {
try {
if (!args[0]) return this.client.commands.get('help').run(message, [this.name]);
const saa = await this.client.db.mongo.SAA.findOne({ applicationID: args[0] }).lean().exec();
@ -50,8 +49,5 @@ export default class SAA_Decline extends Command {
chan.createMessage({ embed }).then(() => this.success(message.channel, 'SAA successfully processed.')).catch(() => this.error(message.channel, 'Unable to deliver decision to user.'));
await this.client.db.mongo.SAA.deleteOne({ _id: saa._id }).lean().exec();
} catch (err) {
return this.client.util.handleError(err, message, this);
}
}
}

View File

@ -23,7 +23,6 @@ export default class Score extends Command {
}
public async run(message: Message, args: string[]) {
try {
let check = false;
let user: User;
if (!args[0] || !this.checkCustomPermissions(this.client.util.resolveMember(message.author.id, this.mainGuild), 4)) {
@ -198,11 +197,8 @@ export default class Score extends Command {
await whoisMessage.delete();
const modlogsMessage = await message.channel.createMessage(`=modlogs ${user.id}`);
await modlogsMessage.delete();
return await message.channel.createMessage('***===END ADDITIONAL INFORMATION===***');
return message.channel.createMessage('***===END ADDITIONAL INFORMATION===***');
}
return message.channel.createMessage({ embed });
} catch (err) {
return this.client.util.handleError(err, message, this);
}
}
}

View File

@ -18,7 +18,6 @@ export default class Score_Hist extends Command {
}
public async run(message: Message, args: string[]) {
try {
let user: User;
if (!this.checkCustomPermissions(message.member, 4)) {
user = message.author;
@ -33,6 +32,7 @@ export default class Score_Hist extends Command {
user = this.client.util.resolveMember(sc.userID, this.mainGuild)?.user;
let name = '';
// eslint-disable-next-line no-unreachable-loop
for (const role of this.client.util.resolveMember(message.author.id, this.mainGuild).roles.map((r) => this.mainGuild.roles.get(r)).sort((a, b) => b.position - a.position)) {
name = `Library of Code sp-us | ${role.name} - [HISTORICAL]`;
break;
@ -126,8 +126,5 @@ export default class Score_Hist extends Command {
embed.setFooter(this.client.user.username, this.client.user.avatarURL);
return message.channel.createMessage({ embed });
} catch (err) {
return this.client.util.handleError(err, message, this);
}
}
}

View File

@ -13,7 +13,6 @@ export default class Score_Notify extends Command {
}
public async run(message: Message, args: string[]) {
try {
const user = message.author;
if (!user) return this.error(message.channel, 'Member not found.');
const score = await this.client.db.mongo.Score.findOne({ userID: message.author.id });
@ -29,8 +28,5 @@ export default class Score_Notify extends Command {
default:
return this.error(message.channel, 'Invalid option. Valid options are `on` and `off`.');
}
} catch (err) {
return this.client.util.handleError(err, message, this);
}
}
}

View File

@ -13,7 +13,6 @@ export default class Score_Pref extends Command {
}
public async run(message: Message, args: string[]) {
try {
if (!message.author) return this.error(message.channel, 'Member not found.');
const score = await this.client.db.mongo.Score.findOne({ userID: message.author.id });
if (!score) return this.error(message.channel, 'Score not calculated yet.');
@ -28,8 +27,5 @@ export default class Score_Pref extends Command {
default:
return this.error(message.channel, 'Invalid input');
}
} catch (err) {
return this.client.util.handleError(err, message, this);
}
}
}

View File

@ -13,7 +13,6 @@ export default class Setnick extends Command {
}
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, 'Cannot find user.');
@ -22,8 +21,5 @@ export default class Setnick extends Command {
if (nickname?.length > 32) return this.error(message.channel, 'New nickname may not be more than 32 characters long.');
await member.edit({ nick: nickname });
return this.success(message.channel, `Updated the nickname of ${member.user.username}#${member.user.discriminator}.`);
} catch (err) {
return this.client.util.handleError(err, message, this, false);
}
}
}

View File

@ -16,7 +16,6 @@ export default class SIP extends Command {
}
public async run(message: Message, args: string[]) {
try {
const staff = await this.client.db.mongo.Staff.findOne({ userID: message.author.id });
if (!staff || !staff?.extension) return this.error(message.channel, 'You must have an extension to complete this action.');
this.success(message.channel, 'Queued call.');
@ -80,8 +79,5 @@ export default class SIP extends Command {
await receiver.hangup().catch(() => {});
await bridge.destroy().catch(() => {});
});
} catch (err) {
return this.client.util.handleError(err, message, this);
}
}
}

View File

@ -17,7 +17,6 @@ export default class Slowmode extends Command {
}
public async run(message: Message<GuildTextableChannel>, args: string[]) {
try {
if (!args[0]) return this.client.commands.get('help').run(message, [this.name]);
const [length, unit] = args[0].match(this.regex);
@ -27,8 +26,5 @@ export default class Slowmode extends Command {
if (momentSeconds > 21600 || momentSeconds < 0) return this.error(message.channel, 'Slowmode must be between 0 seconds and 6 hours.');
return message.channel.edit({ rateLimitPerUser: momentSeconds }).then((c) => message.addReaction(':success:477618704155410452'));
} catch (err) {
return this.client.util.handleError(err, message, this);
}
}
}

View File

@ -22,10 +22,6 @@ export default class StaffAccountSelfServ extends Command {
}
public async run(message: Message) {
try {
return this.client.commands.get('help').run(message, [this.name]);
} catch (err) {
return this.client.util.handleError(err, message, this);
}
}
}

View File

@ -13,7 +13,6 @@ export default class Stats extends Command {
}
public async run(message: Message) {
try {
const messages = await this.client.db.mongo.Stat.findOne({ name: 'messages' });
const commands = await this.client.db.mongo.Stat.findOne({ name: 'commands' });
const pages = await this.client.db.mongo.Stat.findOne({ name: 'pages' });
@ -30,8 +29,5 @@ export default class Stats extends Command {
embed.setFooter(this.client.user.username, this.client.user.avatarURL);
embed.setTimestamp();
return message.channel.createMessage({ embed });
} catch (err) {
return this.client.util.handleError(err, message, this);
}
}
}

View File

@ -15,7 +15,6 @@ export default class StoreMessages extends Command {
}
public async run(message: Message, args: string[]) {
try {
if (!args[0]) return this.client.commands.get('help').run(message, [this.name]);
const check = this.client.util.resolveGuildChannel(args[0], this.mainGuild, false);
if (!check || check.type !== 0) return this.error(message.channel, 'The channel you specified either doesn\'t exist or isn\'t a textable guild channel.');
@ -45,8 +44,5 @@ export default class StoreMessages extends Command {
loadingMessage.delete();
this.client.getDMChannel(message.author.id).then((c) => c.createMessage(`https://cr.ins/m/${identifier}.html.gz || https://cr.ins/m/${identifier}.html?d=1`)).catch(() => this.error(message.channel, 'Could not send a DM to you.'));
return this.success(message.channel, `Fetched messages for <#${chan.id}>. Check your DMs for link to access.`);
} catch (err) {
return this.client.util.handleError(err, message, this);
}
}
}

View File

@ -1,3 +1,4 @@
/* eslint-disable import/no-relative-packages */
// ?e require('mongoose').connections[0].db.command({ buildInfo: 1 })
import { Message } from 'eris';
@ -25,7 +26,6 @@ export default class SysInfo extends Command {
}
public async run(message: Message) {
try {
const embed = new RichEmbed();
embed.setTitle('System & Service Information');
embed.setDescription('__Format of Services__\n- {Server/Service Name} + {various server stats} | {Node Library Used for Communication w/ Server or Service}');
@ -47,8 +47,5 @@ export default class SysInfo extends Command {
embed.setFooter(this.client.user.username, this.client.user.avatarURL);
embed.setTimestamp();
message.channel.createMessage({ embed });
} catch (err) {
this.client.util.handleError(err, message, this);
}
}
}

View File

@ -15,7 +15,6 @@ export default class TTS extends Command {
}
public async run(message: Message, args: string[]) {
try {
if (!args[0]) return this.client.commands.get('help').run(message, [this.name]);
if (args.length > 200) return this.error(message.channel, 'Cannot synthesize more than 200 characters.');
const msg = await this.loading(message.channel, 'Synthesizing...');
@ -29,8 +28,5 @@ export default class TTS extends Command {
});
msg.delete();
return message.channel.createMessage(undefined, { name: `${uuid()}.mp3`, file: d.data });
} catch (err) {
return this.client.util.handleError(err, message, this);
}
}
}

View File

@ -13,7 +13,6 @@ export default class Unban extends Command {
}
public async run(message: Message, args: string[]) {
try {
if (!args[0]) return this.client.commands.get('help').run(message, [this.name]);
let user: User;
try {
@ -30,8 +29,5 @@ export default class Unban extends Command {
await this.client.util.moderation.unban(user.id, message.member, args.slice(1).join(' '));
return this.success(message.channel, `${user.username}#${user.discriminator} has been unbanned.`);
} catch (err) {
return this.client.util.handleError(err, message, this, false);
}
}
}

View File

@ -13,7 +13,6 @@ export default class Unmute extends Command {
}
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, 'Cannot find user.');
@ -27,8 +26,5 @@ export default class Unmute extends Command {
await this.client.util.moderation.unmute(member.user.id, message.member, args.slice(1).join(' '));
return this.success(message.channel, `${member.user.username}#${member.user.discriminator} has been unmuted.`);
} catch (err) {
return this.client.util.handleError(err, message, this, false);
}
}
}

View File

@ -25,7 +25,6 @@ export default class Whois extends Command {
}
public async run(message: Message, args: string[]) {
try {
let member: Member;
if (!args[0]) member = message.member;
else {
@ -242,8 +241,5 @@ export default class Whois extends Command {
embed.setFooter(this.client.user.username, this.client.user.avatarURL);
embed.setTimestamp();
return message.channel.createMessage({ embed });
} catch (err) {
return this.client.util.handleError(err, message, this);
}
}
}

View File

@ -1,5 +1,6 @@
/* eslint-disable no-useless-return */
import { Message, TextChannel, NewsChannel } from 'eris';
import * as Sentry from '@sentry/node';
import { Client, Event } from '../class';
export default class CommandHandler extends Event {
@ -11,6 +12,7 @@ export default class CommandHandler extends Event {
}
public async run(message: Message) {
const transaction = Sentry.startTransaction({ name: 'command-handler' });
try {
this.client.db.mongo.Stat.updateOne({ name: 'messages' }, { $inc: { value: 1 } }).exec();
if (message.author.bot) return;
@ -25,10 +27,17 @@ export default class CommandHandler extends Event {
message.channel.guild.members.add(await message.channel.guild.getRESTMember(message.author.id));
}
this.client.util.signale.log(`User '${message.author.username}#${message.author.discriminator}' ran command '${resolved.cmd.name}' in '${message.channel.id}'.`);
try {
await resolved.cmd.run(message, resolved.args);
} catch (err) {
this.client.util.handleError(err, message, resolved.cmd);
} finally {
this.client.db.mongo.Stat.updateOne({ name: 'commands' }, { $inc: { value: 1 } }).exec();
}
} catch (err) {
this.client.util.handleError(err, message);
} finally {
transaction.finish();
}
}
}

9259
yarn.lock

File diff suppressed because it is too large Load Diff