Merge branch 'master' of gitlab.libraryofcode.org:engineering/cloudservices

merge-requests/1/merge
Matthew 2019-12-11 22:21:11 -05:00
commit 0838022eae
No known key found for this signature in database
GPG Key ID: 766BE43AE75F7559
11 changed files with 105 additions and 76 deletions

View File

@ -14,7 +14,7 @@
"@ghaiklor/x509": "^1.0.0", "@ghaiklor/x509": "^1.0.0",
"axios": "^0.19.0", "axios": "^0.19.0",
"body-parser": "^1.19.0", "body-parser": "^1.19.0",
"eris": "^0.10.1", "eris": "abalabahaha/eris#dev",
"eris-pagination": "bsian03/eris-pagination", "eris-pagination": "bsian03/eris-pagination",
"express": "^4.17.1", "express": "^4.17.1",
"fs-extra": "^8.1.0", "fs-extra": "^8.1.0",

View File

@ -28,7 +28,9 @@ export default class Client extends Eris.Client {
public server: Server; public server: Server;
public updating: Boolean; public updating: boolean;
public buildError: boolean
constructor() { constructor() {
super(config.token, { getAllUsers: true, restMode: true, defaultImageFormat: 'png' }); super(config.token, { getAllUsers: true, restMode: true, defaultImageFormat: 'png' });
@ -47,6 +49,7 @@ export default class Client extends Eris.Client {
displayFilename: true, displayFilename: true,
}); });
this.updating = false; this.updating = false;
this.buildError = false;
this.events(); this.events();
this.loadFunctions(); this.loadFunctions();
this.init(); this.init();
@ -115,6 +118,8 @@ export default class Client extends Eris.Client {
this.signale.complete(`Loaded interval ${interval.split('.')[0]}`); this.signale.complete(`Loaded interval ${interval.split('.')[0]}`);
}); });
this.server = new Server(this, { port: this.config.port }); this.server = new Server(this, { port: this.config.port });
require.cache = Object.create(null);
} }
} }

View File

@ -2,7 +2,7 @@
import { promisify } from 'util'; import { promisify } from 'util';
import childProcess from 'child_process'; import childProcess from 'child_process';
import nodemailer from 'nodemailer'; import nodemailer from 'nodemailer';
import { Message, PrivateChannel, Member, User } from 'eris'; import { Message, PrivateChannel, GroupChannel, Member, User } from 'eris';
import uuid from 'uuid/v4'; import uuid from 'uuid/v4';
import moment from 'moment'; import moment from 'moment';
import fs from 'fs'; import fs from 'fs';
@ -38,50 +38,29 @@ export default class Util {
/** /**
* Resolves a command * Resolves a command
* @param command Parent command label * @param query Command input
* @param args Use to resolve subcommands
* @param message Only used to check for errors * @param message Only used to check for errors
*/ */
public resolveCommand(command: string, args?: string[], message?: Message): Promise<{cmd: Command, args: string[] }> { public resolveCommand(query: string | string[], message?: Message): Promise<{cmd: Command, args: string[] }> {
try { try {
let resolvedCommand: Command; let resolvedCommand: Command;
if (typeof query === 'string') query = query.split(' ');
const commands = this.client.commands.toArray();
resolvedCommand = commands.find((c) => c.name === query[0].toLowerCase() || c.aliases.includes(query[0].toLowerCase()));
if (this.client.commands.has(command)) resolvedCommand = this.client.commands.get(command); if (!resolvedCommand) return Promise.resolve(null);
else { query.shift();
for (const cmd of this.client.commands.toArray()) { while (resolvedCommand.subcommands.size && query.length) {
if (cmd.aliases.includes(command)) { resolvedCommand = cmd; break; } const subCommands = resolvedCommand.subcommands.toArray();
} const found = subCommands.find((c) => c.name === query[0].toLowerCase() || c.aliases.includes(query[0].toLowerCase()));
if (!found) break;
resolvedCommand = found;
query.shift();
} }
if (!resolvedCommand) return Promise.resolve({ cmd: null, args }); return Promise.resolve({ cmd: resolvedCommand, args: query });
let parentLabel = '';
let hasSubCommands = true;
while (hasSubCommands) {
if (!resolvedCommand.subcommands.size) {
hasSubCommands = false; break;
} else if (!args[0]) {
hasSubCommands = false; break;
} else if (resolvedCommand.subcommands.has(args[0])) {
parentLabel += `${resolvedCommand.name} `;
resolvedCommand = resolvedCommand.subcommands.get(args[0]); args.shift();
} else {
const subcommandArray = resolvedCommand.subcommands.toArray();
for (const subCmd of subcommandArray) {
if (subCmd.aliases.includes(args[0])) {
parentLabel += `${resolvedCommand.name} `; resolvedCommand = subCmd; args.shift(); break;
}
if (subcommandArray.findIndex((v) => v === subCmd) === subcommandArray.length - 1) {
hasSubCommands = false; break;
}
}
}
}
const finalCommand = resolvedCommand;
finalCommand.parentName = parentLabel;
return Promise.resolve({ cmd: finalCommand, args });
} catch (error) { } catch (error) {
this.handleError(error, message); if (message) this.handleError(error, message);
else this.handleError(error);
return Promise.reject(error); return Promise.reject(error);
} }
} }
@ -99,7 +78,7 @@ export default class Util {
embed.addField('User', `${message.author.mention} (\`${message.author.id}\`)`, true); embed.addField('User', `${message.author.mention} (\`${message.author.id}\`)`, true);
embed.addField('Channel', message.channel.mention, true); embed.addField('Channel', message.channel.mention, true);
let guild: string; let guild: string;
if (message.channel instanceof PrivateChannel) guild = '@me'; if (message.channel instanceof PrivateChannel || message.channel instanceof GroupChannel) guild = '@me';
else guild = message.channel.guild.id; else guild = message.channel.guild.id;
embed.addField('Message link', `[Click here](https://discordapp.com/channels/${guild}/${message.channel.id}/${message.id})`, true); embed.addField('Message link', `[Click here](https://discordapp.com/channels/${guild}/${message.channel.id}/${message.id})`, true);
embed.setTimestamp(new Date(message.timestamp)); embed.setTimestamp(new Date(message.timestamp));
@ -107,9 +86,7 @@ export default class Util {
} }
await this.client.createMessage('595788220764127272', info); await this.client.createMessage('595788220764127272', info);
const msg = message.content.slice(this.client.config.prefix.length).trim().split(/ +/g); const msg = message.content.slice(this.client.config.prefix.length).trim().split(/ +/g);
const label = msg[0]; if (command) this.resolveCommand(msg).then((c) => { c.cmd.enabled = false; });
const args = msg.slice(1);
if (command) this.resolveCommand(label, args).then((c) => { c.cmd.enabled = false; });
if (message) message.channel.createMessage(`***${this.client.stores.emojis.error} An unexpected error has occured - please contact a member of the Engineering Team.${command ? ' This command has been disabled.' : ''}***`); if (message) message.channel.createMessage(`***${this.client.stores.emojis.error} An unexpected error has occured - please contact a member of the Engineering Team.${command ? ' This command has been disabled.' : ''}***`);
} catch (err) { } catch (err) {
this.client.signale.error(err); this.client.signale.error(err);

View File

@ -1,4 +1,4 @@
import { Message, PrivateChannel } from 'eris'; import { Message, PrivateChannel, GroupChannel } from 'eris';
import uuid from 'uuid/v4'; import uuid from 'uuid/v4';
import { Client } from '..'; import { Client } from '..';
import { Command, RichEmbed } from '../class'; import { Command, RichEmbed } from '../class';
@ -22,7 +22,7 @@ export default class CreateAccount extends Command {
public async run(message: Message, args: string[]) { public async run(message: Message, args: string[]) {
try { try {
if (message.channel instanceof PrivateChannel) return message; // Stop TS being gay if (message.channel instanceof PrivateChannel || message.channel instanceof GroupChannel) return message; // Stop TS being gay
if (!args[2]) return this.client.commands.get('help').run(message, [this.name]); if (!args[2]) return this.client.commands.get('help').run(message, [this.name]);
if (!message.channel.guild.members.has(args[0])) return message.channel.createMessage(`${this.client.stores.emojis.error} ***User not found***`); if (!message.channel.guild.members.has(args[0])) return message.channel.createMessage(`${this.client.stores.emojis.error} ***User not found***`);
if (message.channel.guild.members.get(args[0]).bot) return message.channel.createMessage(`${this.client.stores.emojis.error} ***I cannot create accounts for bots***`); if (message.channel.guild.members.get(args[0]).bot) return message.channel.createMessage(`${this.client.stores.emojis.error} ***I cannot create accounts for bots***`);

View File

@ -1,4 +1,3 @@
/* eslint-disable consistent-return */
import { Message, PrivateChannel } from 'eris'; import { Message, PrivateChannel } from 'eris';
import uuid from 'uuid/v4'; import uuid from 'uuid/v4';
import { Command } from '../class'; import { Command } from '../class';
@ -57,7 +56,7 @@ export default class DeleteAccount extends Command {
`, `,
}); });
deleting.edit(`${this.client.stores.emojis.success} ***Account ${username} has been deleted by Engineer ${message.author.username}#${message.author.discriminator}***`); return deleting.edit(`${this.client.stores.emojis.success} ***Account ${username} has been deleted by Engineer ${message.author.username}#${message.author.discriminator}***`);
} catch (error) { } catch (error) {
return this.client.util.handleError(error, message, this); return this.client.util.handleError(error, message, this);
} }

View File

@ -44,7 +44,7 @@ export default class Help extends Command {
if (cmdPages.length === 1) return message.channel.createMessage({ embed: cmdPages[0] }); if (cmdPages.length === 1) return message.channel.createMessage({ embed: cmdPages[0] });
return createPaginationEmbed(message, this.client, cmdPages); return createPaginationEmbed(message, this.client, cmdPages);
} }
const { cmd } = await this.client.util.resolveCommand(args[0], args.slice(1), message); const { cmd } = await this.client.util.resolveCommand(args, message);
if (!cmd) return message.channel.createMessage(`${this.client.stores.emojis.error} **Command not found!**`); if (!cmd) return message.channel.createMessage(`${this.client.stores.emojis.error} **Command not found!**`);
const perms: string[] = []; const perms: string[] = [];
let allowedRoles = cmd.permissions && cmd.permissions.roles && cmd.permissions.roles.map((r) => `<@&${r}>`).join(', '); let allowedRoles = cmd.permissions && cmd.permissions.roles && cmd.permissions.roles.map((r) => `<@&${r}>`).join(', ');

View File

@ -1,23 +1,24 @@
export { default as Announce } from './announce'; export { default as announce } from './announce';
export { default as Bearer } from './bearer'; export { default as bearer } from './bearer';
export { default as CreateAccount } from './createaccount'; export { default as createAccount } from './createaccount';
export { default as CWG } from './cwg'; export { default as cwg } from './cwg';
export { default as DeleteAccount } from './deleteaccount'; export { default as deleteaccount } from './deleteaccount';
export { default as Disk } from './disk'; export { default as disk } from './disk';
export { default as Eval } from './eval'; export { default as eval } from './eval';
export { default as Exec } from './exec'; export { default as exec } from './exec';
export { default as Help } from './help'; export { default as help } from './help';
export { default as Lock } from './lock'; export { default as load } from './load';
export { default as Modlogs } from './modlogs'; export { default as lock } from './lock';
export { default as Notify } from './notify'; export { default as modlogs } from './modlogs';
export { default as Parse } from './parse'; export { default as notify } from './notify';
export { default as Parseall } from './parseall'; export { default as parse } from './parse';
export { default as Ping } from './ping'; export { default as parseall } from './parseall';
export { default as Pull } from './pull'; export { default as ping } from './ping';
export { default as Restart } from './restart'; export { default as pull } from './pull';
export { default as SecureSign } from './securesign'; export { default as restart } from './restart';
export { default as Sysinfo } from './sysinfo'; export { default as securesign } from './securesign';
export { default as Unban } from './unban'; export { default as sysinfo } from './sysinfo';
export { default as Unlock } from './unlock'; export { default as unban } from './unban';
export { default as Warn } from './warn'; export { default as unlock } from './unlock';
export { default as Whois } from './whois'; export { default as warn } from './warn';
export { default as whois } from './whois';

45
src/commands/load.ts Normal file
View File

@ -0,0 +1,45 @@
import { Message } from 'eris';
import { Client } from '..';
import { Command } from '../class';
export default class Load extends Command {
constructor(client: Client) {
super(client);
this.name = 'load';
this.description = '(Re)loads command, config or util';
this.aliases = ['reload'];
this.permissions = { users: ['253600545972027394', '278620217221971968'] };
this.enabled = false;
}
public async run(message: Message, args: string[]) {
try {
if (!args[0]) return this.client.commands.get('help').run(message, [this.name]);
const allowed = ['config', 'util', 'command', 'function'];
const type = args[0].toLowerCase();
if (!allowed.includes(type)) return message.channel.createMessage(`${this.client.stores.emojis.error} ***Invalid type to (re)load***`);
const corepath = '/var/CloudServices/dist';
if (type === 'config') this.client.config = require(`${corepath}/config.json`);
else if (type === 'util') {
const Util = require(`${corepath}/class/Util`);
this.client.util = new Util(this.client);
} else {
try {
const cmdIndex = require('../commands');
let Cmd = cmdIndex[args[1]];
if (!Cmd) return message.channel.createMessage(`${this.client.stores.emojis.error} ***Could not find file***`);
Cmd = require(`${corepath}/commands/${args[1]}`).default;
this.client.commands.remove(args[1]);
this.client.loadCommand(Cmd);
} catch (error) {
if (error.message.includes('Cannot find module')) return message.channel.createMessage(`${this.client.stores.emojis} ***Cannot find file***`);
throw error;
}
}
return message.channel.createMessage(`${this.client.stores.emojis.success} Reloaded ${type}`);
} catch (error) {
return this.client.util.handleError(error, message, this);
}
}
}

View File

@ -14,6 +14,7 @@ export default class Pull extends Command {
public async run(message: Message) { public async run(message: Message) {
try { try {
if (this.client.updating) return message.channel.createMessage(`${this.client.stores.emojis.error} ***Update in progress***`);
this.client.updating = true; this.client.updating = true;
const updateMessage = await message.channel.createMessage(`${this.client.stores.emojis.loading} ***Fetching latest commit...***\n\`\`\`sh\ngit pull\n\`\`\``); const updateMessage = await message.channel.createMessage(`${this.client.stores.emojis.loading} ***Fetching latest commit...***\n\`\`\`sh\ngit pull\n\`\`\``);
let pull: string; let pull: string;
@ -74,12 +75,14 @@ export default class Pull extends Command {
} catch (error) { } catch (error) {
const updatedMessage = updatedPackages.content.replace(`${this.client.stores.emojis.loading} ***Rebuilding files...***`, `${this.client.stores.emojis.error} ***Failed to rebuild files***`) const updatedMessage = updatedPackages.content.replace(`${this.client.stores.emojis.loading} ***Rebuilding files...***`, `${this.client.stores.emojis.error} ***Failed to rebuild files***`)
.replace(/```$/, `${error.message}\n\`\`\``); .replace(/```$/, `${error.message}\n\`\`\``);
this.client.buildError = true;
this.client.updating = false; this.client.updating = false;
return updateMessage.edit(updatedMessage); return updateMessage.edit(updatedMessage);
} }
const finalMessage = updatedPackages.content.replace(`${this.client.stores.emojis.loading} ***Rebuilding files...***`, `${this.client.stores.emojis.success} ***Files rebuilt***`) const finalMessage = updatedPackages.content.replace(`${this.client.stores.emojis.loading} ***Rebuilding files...***`, `${this.client.stores.emojis.success} ***Files rebuilt***`)
.replace(/```$/, `${build}\n\`\`\``); .replace(/```$/, `${build}\n\`\`\``);
this.client.updating = false; this.client.updating = false;
this.client.buildError = false;
return updateMessage.edit(finalMessage); return updateMessage.edit(finalMessage);
} catch (error) { } catch (error) {
this.client.updating = false; this.client.updating = false;

View File

@ -14,6 +14,7 @@ export default class Restart extends Command {
public async run(message: Message, args: string[]) { public async run(message: Message, args: string[]) {
try { try {
if (this.client.updating && args[0] !== '-f') return message.channel.createMessage(`${this.client.stores.emojis.error} ***Update in progress***`); if (this.client.updating && args[0] !== '-f') return message.channel.createMessage(`${this.client.stores.emojis.error} ***Update in progress***`);
if (this.client.buildError) return message.channel.createMessage(`${this.client.stores.emojis.error} ***Build error, resolve before restarting***`);
await message.channel.createMessage(`${this.client.stores.emojis.loading} ***Restarting...***`); await message.channel.createMessage(`${this.client.stores.emojis.loading} ***Restarting...***`);
return process.exit(1); return process.exit(1);
} catch (error) { } catch (error) {

View File

@ -14,10 +14,8 @@ export default class {
if (message.author.bot) return; if (message.author.bot) return;
if (message.content.indexOf(this.client.config.prefix) !== 0) return; if (message.content.indexOf(this.client.config.prefix) !== 0) return;
const noPrefix: string[] = message.content.slice(this.client.config.prefix.length).trim().split(/ +/g); const noPrefix: string[] = message.content.slice(this.client.config.prefix.length).trim().split(/ +/g);
const command: string = noPrefix[0].toLowerCase(); const resolved = await this.client.util.resolveCommand(noPrefix, message);
const args: string[] = noPrefix.slice(1); if (!resolved) return;
const resolved = await this.client.util.resolveCommand(command, args, message);
if (!resolved.cmd) return;
if (resolved.cmd.guildOnly && !(message.channel instanceof TextChannel)) return; if (resolved.cmd.guildOnly && !(message.channel instanceof TextChannel)) return;
let hasUserPerms: boolean; let hasUserPerms: boolean;
if (resolved.cmd.permissions.users) { if (resolved.cmd.permissions.users) {