1
0
Fork 0

rewrite all commands

refactor/models
Matthew 2020-06-29 02:35:14 -04:00
parent 9d38a8bec7
commit af7fbffe6b
No known key found for this signature in database
GPG Key ID: 210AF32ADE3B5C4B
28 changed files with 73 additions and 277 deletions

View File

@ -16,7 +16,7 @@ export default class Announce extends Command {
public async run(message: Message, args?: string[]) {
try {
if (!args.length) return this.client.commands.get('help').run(message, [this.name]);
const notification = await message.channel.createMessage(`${this.client.stores.emojis.loading} ***Sending announcement, please wait...***`);
const notification = await this.loading(message.channel, 'Sending announcement, please wait...');
if (args[0] === '-e') await this.client.util.exec(`echo "\n\n**************************************************************************\nEMERGENCY SYSTEM BROADCAST MESSAGE | Library of Code sp-us (root enforced)\n--------------------------------------------------------------------------\n\n\n${args.slice(1).join(' ').trim()}\n\n\n\n\n\n\n\n\n\n\n\n\n" | wall -n`);
else await this.client.util.exec(`echo "\nSYSTEM BROADCAST MESSAGE | Library of Code sp-us (root enforced)\n\n\n${args.join(' ').trim()}" | wall -n`);
message.delete();

View File

@ -15,12 +15,12 @@ export default class Bearer extends Command {
public async run(message: Message) {
try {
const account = await this.client.db.Account.findOne({ userID: message.author.id });
if (!account) return message.channel.createMessage(`${this.client.stores.emojis.error} ***Account not found***`);
if (!account) return this.error(message.channel, 'Account not found.');
// eslint-disable-next-line no-underscore-dangle
const bearer = await this.client.server.security.createBearer(account._id);
const dm = await this.client.getDMChannel(message.author.id);
const msg = await dm.createMessage(`__**Library of Code sp-us | Cloud Services [API]**__\n*This message will automatically be deleted in 60 seconds, copy the token and save it. You cannot recover it.*\n\n${bearer}`);
message.channel.createMessage(`***${this.client.stores.emojis.success} Bearer token sent to direct messages.***`);
this.error(message.channel, 'Bearer token sent to direct messages.');
return setTimeout(() => {
msg.delete();
}, 60000);

View File

@ -18,13 +18,13 @@ export default class Cloudflare extends Command {
public async run(message: Message, args: string[]) {
try {
if (!args.length) return this.client.commands.get('help').run(message, ['cloudflare']);
const msg = await message.channel.createMessage(`${this.client.stores.emojis.loading} ***Locating entry...***`);
const msg = await this.loading(message.channel, 'Locating entry...');
const { data } = await axios({
method: 'get',
url: `https://api.cloudflare.com/client/v4/zones/5e82fc3111ed4fbf9f58caa34f7553a7/dns_records?name=${args[0]}`,
headers: { Authorization: `Bearer ${this.client.config.cloudflare}` },
});
if (!data.result.length) return msg.edit(`${this.client.stores.emojis.error} ***Entry not found***`);
if (!data.result.length) return msg.edit(`${this.client.stores.emojis.error} ***Entry not found.***`);
msg.edit(`${this.client.stores.emojis.success} ***Located entry***\n${this.client.stores.emojis.loading} ***Deleting entry...***`);
const { id }: { id: string } = data.result[0];
await axios({

View File

@ -23,19 +23,19 @@ export default class CreateAccount extends Command {
try {
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 (!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.has(args[0])) return this.error(message.channel, 'User not found.');
if (message.channel.guild.members.get(args[0]).bot) return this.error(message.channel, 'I cannot create accounts for bots.');
const checkUser = await this.client.db.Account.findOne({ userID: args[0] });
if (checkUser) return message.channel.createMessage(`${this.client.stores.emojis.error} ***<@${args[0]}> already has an account.***`);
if (checkUser) return this.error(message.channel, `<@${args[0]}> already has an account.`);
const checkEmail = await this.client.db.Account.findOne({ emailAddress: args[1] });
if (checkEmail) return message.channel.createMessage(`${this.client.stores.emojis.error} ***Account already exists with this email address.***`);
if (checkEmail) return this.error(message.channel, 'Account already exists with this email address.');
const checkAccount = await this.client.db.Account.findOne({ username: args[2] });
if (checkAccount) return message.channel.createMessage(`${this.client.stores.emojis.error} ***Account already exists with this username.***`);
if (checkAccount) return this.error(message.channel, 'Account already exists with this username.');
if (!this.client.util.isValidEmail(args[1])) return message.channel.createMessage(`${this.client.stores.emojis.error} ***Invalid email address supplied.***`);
if (!/^[a-z][-a-z0-9]*$/.test(args[2])) return message.channel.createMessage(`${this.client.stores.emojis.error} ***Invalid username supplied.***`);
if (!this.client.util.isValidEmail(args[1])) return this.error(message.channel, 'Invalid email address supplied.');
if (!/^[a-z][-a-z0-9]*$/.test(args[2])) return this.error(message.channel, 'Invalid username supplied.');
const confirmation = await message.channel.createMessage(`${this.client.stores.emojis.loading} ***Creating account...***`);
const confirmation = await this.loading(message.channel, 'Creating account...');
const data = await this.client.util.accounts.createAccount({ userID: args[0], username: args[2], emailAddress: args[1] }, message.author.id);
message.delete();

View File

@ -32,14 +32,14 @@ export default class CWG_Create extends Command {
try {
if (!args[2]) return this.client.commands.get('help').run(message, ['cwg', this.name]);
if (!this.urlRegex.test(args[1])) return message.channel.createMessage(`${this.client.stores.emojis.error} ***Invalid URL***`);
if (Number(args[2]) <= 1024 || Number(args[2]) >= 65535) return message.channel.createMessage(`${this.client.stores.emojis.error} ***Port must be greater than 1024 and less than 65535***`);
if (!args[1].endsWith('.cloud.libraryofcode.org') && !args[4]) return message.channel.createMessage(`${this.client.stores.emojis.error} ***Certificate Chain and Private Key are required for custom domains***`);
if (!this.urlRegex.test(args[1])) return this.error(message.channel, 'Invalid URL supplied.');
if (Number(args[2]) <= 1024 || Number(args[2]) >= 65535) return this.error(message.channel, 'Port must be greater than 1024 and less than 65535.');
if (!args[1].endsWith('.cloud.libraryofcode.org') && !args[4]) return this.error(message.channel, 'Certificate Chain and Private Key are required for custom domains.');
const account = await this.client.db.Account.findOne({ $or: [{ username: args[0] }, { userID: args[0] }] });
if (!account) return message.channel.createMessage(`${this.client.stores.emojis.error} Cannot locate account, please try again.`);
if (!account) return this.error(message.channel, 'Cannot locate account.');
if (await this.client.db.Domain.exists({ domain: args[1] })) return message.channel.createMessage(`${this.client.stores.emojis.error} ***This domain already exists***`);
if (await this.client.db.Domain.exists({ domain: args[1] })) return this.error(message.channel, 'This domain already exists.');
if (await this.client.db.Domain.exists({ port: Number(args[2]) })) {
let answer: Message;
@ -50,24 +50,24 @@ export default class CWG_Create extends Command {
30000, true, ['y', 'n'], (msg) => msg.author.id === message.author.id && msg.channel.id === message.channel.id,
);
} catch (error) {
return message.channel.createMessage(`${this.client.stores.emojis.error} ***Bind request cancelled***`);
return this.error(message.channel, 'Bind request cancelled.');
}
if (answer.content === 'n') return message.channel.createMessage(`${this.client.stores.emojis.error} ***Bind request cancelled***`);
if (answer.content === 'n') return this.error(message.channel, 'Bind request cancelled.');
}
const edit = await message.channel.createMessage(`${this.client.stores.emojis.loading} ***Binding domain...***`);
const edit = await this.loading(message.channel, 'Binding domain...');
let certs: { cert?: string, key?: string } = {};
if (!args[1].endsWith('.cloud.libraryofcode.org')) {
const urls = args.slice(3, 5);
if (urls.some((l) => !l.includes('snippets.cloud.libraryofcode.org/raw/'))) return message.channel.createMessage(`${this.client.stores.emojis.error} ***Invalid snippets URL***`);
if (urls.some((l) => !l.includes('snippets.cloud.libraryofcode.org/raw/'))) return this.error(message.channel, 'Invalid snippets URL. Make sure to use https://snippets.libraryofcode.org/raw/*.');
const tasks = urls.map((l) => axios({ method: 'GET', url: l }));
const response = await Promise.all(tasks);
const certAndPrivateKey: string[] = response.map((r) => r.data);
if (!this.isValidCertificateChain(certAndPrivateKey[0])) return message.channel.createMessage(`${this.client.stores.emojis.error} ***Invalid Certificate Chain***`);
if (!this.isValidPrivateKey(certAndPrivateKey[1])) return message.channel.createMessage(`${this.client.stores.emojis.error} ***Invalid Private Key***`);
if (!this.isValidCertificateChain(certAndPrivateKey[0])) return this.error(message.channel, 'The certificate chain provided is invalid.');
if (!this.isValidPrivateKey(certAndPrivateKey[1])) return this.error(message.channel, 'The private key provided is invalid.');
certs = { cert: certAndPrivateKey[0], key: certAndPrivateKey[1] };
} else {

View File

@ -24,12 +24,12 @@ export default class CWG_Data extends Command {
if (!Number.isNaN(Number(args[0]))) {
try {
await this.client.util.exec(`fuser ${args[0]}/tcp`);
return message.channel.createMessage(`***${this.client.stores.emojis.error} The port you provided is being used by a system process.***`);
return this.error(message.channel, 'The port you provided is being used by a system process.');
} catch (error) {
return message.channel.createMessage(`***${this.client.stores.emojis.error} The domain or port you provided could not be found.***`);
return this.error(message.channel, 'The domain or port you provided could not be found.');
}
}
return message.channel.createMessage(`***${this.client.stores.emojis.error} The domain or port you provided could not be found.***`);
return this.error(message.channel, 'The domain or port you provided could not be found.');
}
const embeds = dom.map((domain) => {
const cert = fs.readFileSync(domain.x509.cert, { encoding: 'utf8' });

View File

@ -19,8 +19,8 @@ export default class CWG_Delete extends Command {
try {
if (!args[0]) return this.client.commands.get('help').run(message, ['cwg', this.name]);
const domain = await this.client.db.Domain.findOne({ $or: [{ domain: args[0] }, { port: Number(args[0]) || 0 }] });
if (!domain) return message.channel.createMessage(`***${this.client.stores.emojis.error} The domain or port you provided could not be found.***`);
const edit = await message.channel.createMessage(`***${this.client.stores.emojis.loading} Deleting domain...***`);
if (!domain) return this.error(message.channel, 'The domain or port you provided could not be found.');
const edit = await this.loading(message.channel, 'Deleting domain...');
const embed = new RichEmbed();
embed.setTitle('Domain Deletion');
embed.addField('Account Username', domain.account.username, true);

View File

@ -19,18 +19,18 @@ export default class CWG_UpdateCert extends Command {
try {
if (!args[2]) return this.client.commands.get('help').run(message, ['cwg', this.name]);
const dom = await this.client.db.Domain.findOne({ $or: [{ domain: args[0] }, { port: Number(args[0]) || 0 }] });
if (!dom) return message.channel.createMessage(`***${this.client.stores.emojis.error} The domain or port you provided could not be found.***`);
if (!dom) return this.error(message.channel, 'The domain or port you provided could not be found.');
const { domain, port, x509, account } = dom;
const { cert, key } = x509;
const urls = args.slice(1, 3); // eslint-disable-line
if (urls.some((l) => !l.includes('snippets.cloud.libraryofcode.org/raw/'))) return message.channel.createMessage(`${this.client.stores.emojis.error} ***Invalid snippets URL***`);
if (urls.some((l) => !l.includes('snippets.cloud.libraryofcode.org/raw/'))) return this.error(message.channel, 'Invalid snippets URL.');
const tasks = urls.map((l) => axios({ method: 'GET', url: l }));
const response = await Promise.all(tasks);
const certAndPrivateKey: string[] = response.map((r) => r.data);
if (!this.isValidCertificateChain(certAndPrivateKey[0])) return message.channel.createMessage(`${this.client.stores.emojis.error} ***Invalid Certificate Chain***`);
if (!this.isValidPrivateKey(certAndPrivateKey[1])) return message.channel.createMessage(`${this.client.stores.emojis.error} ***Invalid Private Key***`);
if (!this.isValidCertificateChain(certAndPrivateKey[0])) return this.error(message.channel, 'The certificate chain provided is invalid.');
if (!this.isValidPrivateKey(certAndPrivateKey[1])) return this.error(message.channel, 'The private key provided is invalid.');
const path = `/opt/CloudServices/temp/${account.id}`;
const temp = [writeFile(`${path}.chain.crt`, certAndPrivateKey[0]), writeFile(`${path}.key.pem`, certAndPrivateKey[1])];
@ -38,13 +38,13 @@ export default class CWG_UpdateCert extends Command {
await Promise.all(temp);
if (!this.isMatchingPair(`${path}.chain.crt`, `${path}.key.pem`)) {
await Promise.all(removeFiles);
return message.channel.createMessage(`${this.client.stores.emojis.error} ***Certificate and private key do not match***`);
return this.error(message.channel, 'The certificate and private key provided do not match');
}
const writeTasks = [writeFile(cert, certAndPrivateKey[0], { encoding: 'utf8' }), writeFile(key, certAndPrivateKey[1], { encoding: 'utf8' }), ...removeFiles];
await Promise.all(writeTasks);
return message.channel.createMessage(`${this.client.stores.emojis.success} ***Updated certificate for ${domain} on port ${port}***`);
return this.success(message.channel, `Updated certificate for ${domain} on port ${port}`);
} catch (error) {
return this.client.util.handleError(error, message, this);
}

View File

@ -1,42 +0,0 @@
import { Message } from 'eris';
import moment from 'moment';
import { Client } from '..';
import { RichEmbed, Command } from '../class';
import { dataConversion } from '../functions';
import 'moment-precise-range-plugin';
export default class Disk extends Command {
constructor(client: Client) {
super(client);
this.name = 'disk';
this.description = 'Checks the used disk space by a user';
this.usage = `${this.client.config.prefix}disk [Username/User ID/Email]`;
this.permissions = { roles: ['662163685439045632', '701454780828221450'] };
this.enabled = false;
}
async run(message: Message, args: string[]) {
try {
if (!args[0]) return this.client.commands.get('help').run(message, [this.name]);
const account = await this.client.db.Account.findOne({ $or: [{ username: args[0] }, { userID: args[0] }, { emailAddress: args[0] }] });
if (!account) return message.channel.createMessage(`${this.client.stores.emojis.error} ***Account not found***`);
if (account.root || args[0].includes('./')) return message.channel.createMessage(`${this.client.stores.emojis.error} ***Permission denied***`);
const diskReply = await message.channel.createMessage(`${this.client.stores.emojis.loading} ***Fetching total disk size may up to 10 minutes. This message will edit when the disk size has been located.***`);
const start = Date.now();
const result = await this.client.util.exec(`du -s ${account.homepath}`);
const end = Date.now();
const totalTime: string = moment.preciseDiff(start, end);
const embed = new RichEmbed();
embed.setTitle('Disk Usage');
embed.setColor('ff0000');
embed.setDescription(result.split(/ +/g)[1]);
embed.addField('Result', dataConversion(Number(result.split(/ +/g)[0])), true);
embed.addField('Time taken', totalTime, true);
embed.setFooter(`Requested by ${message.author.username}#${message.author.discriminator}`, message.author.avatarURL);
embed.setTimestamp();
return diskReply.edit({ content: '', embed });
} catch (error) {
return this.client.util.handleError(error, message, this);
}
}
}

View File

@ -18,7 +18,7 @@ export default class EmailCode extends Command {
try {
if (!args.length) return this.client.commands.get('help').run(message, [this.name]);
const code = randomBytes(5).toString('hex');
if (!this.client.util.isValidEmail(args[0])) return message.channel.createMessage(`${this.client.stores.emojis.error} ***Invalid email address supplied.***`);
if (!this.client.util.isValidEmail(args[0])) return this.error(message.channel, 'The email address provided is invalid.');
this.client.util.transport.sendMail({
to: args[0],
from: 'Library of Code sp-us | Cloud Services <help@libraryofcode.org>',
@ -35,7 +35,7 @@ export default class EmailCode extends Command {
</body>
`,
});
return message.channel.createMessage(`***${this.client.stores.emojis.success} Code: \`${code}\` | Email Address: ${args[0]}***`);
return this.success(message.channel, `Code: \`${code}\` | Email Address: ${args[0]}`);
} catch (error) {
return this.client.util.handleError(error, message, this);
}

View File

@ -18,7 +18,7 @@ export default class Exec extends Command {
try {
if (!args.length) return this.client.commands.get('help').run(message, [this.name]);
const response = await message.channel.createMessage(`${this.client.stores.emojis.loading} ***Executing \`${args.join(' ')}\`***`);
const response = await this.loading(message.channel, `***Executing \`${args.join(' ')}\``);
let result: string;
try {
result = await this.client.util.exec(args.join(' '), { cwd: '/opt/CloudServices' });

View File

@ -14,16 +14,16 @@ export default class Limits_SetRAMNotification extends Command {
public async run(message: Message, args: string[]) {
try {
const account = await this.client.db.Account.findOne({ userID: message.author.id });
if (!account) return message.channel.createMessage(`***${this.client.stores.emojis.error} You do not have a Cloud Account.***`);
if (!account) return this.error(message.channel, 'You do not appear to have an account.');
const tier = await this.client.db.Tier.findOne({ id: account.tier });
if (Number(args[0]) >= tier.resourceLimits.ram) return message.channel.createMessage(`***${this.client.stores.emojis.error} You cannot set your notification limit to be set to or above your hard limit.***`);
if (Number(args[0]) < 0) return message.channel.createMessage(`***${this.client.stores.emojis.error} You cannot set your notification limit to a negative number.***`);
if (Number(args[0]) >= tier.resourceLimits.ram) return this.error(message.channel, 'You cannot set your notification limit to be set to or above your hard limit.');
if (Number(args[0]) < 0) return this.error(message.channel, 'You cannot set your notification limit to a negative number.');
if (Number(args[0]) === 0) {
await account.updateOne({ $set: { ramLimitNotification: 0 } });
return message.channel.createMessage(`***${this.client.stores.emojis.success} You have disabled notifications.***`);
return this.success(message.channel, 'You have disabled notifications.');
}
await account.updateOne({ $set: { ramLimitNotification: Number(args[0]) } });
return message.channel.createMessage(`***${this.client.stores.emojis.success} You will now receive notifications when you go above ${Number(args[0])} MB.***`);
return this.success(message.channel, `You will now receive notifications when you go above ${Number(args[0])} MB.`);
} catch (error) {
return this.client.util.handleError(error, message, this);
}

View File

@ -17,7 +17,7 @@ export default class Load extends Command {
if (!args[0]) return this.client.commands.get('help').run(message, [this.name]);
const allowed = ['config', 'util', 'command'];
const type = args[0].toLowerCase();
if (!allowed.includes(type)) return message.channel.createMessage(`${this.client.stores.emojis.error} ***Invalid type to (re)load***`);
if (!allowed.includes(type)) return this.error(message.channel, 'Invalid type provided to (re)load.');
const corepath = '/opt/CloudServices/dist';
if (type === 'config') {
@ -33,20 +33,20 @@ export default class Load extends Command {
delete require.cache[`${corepath}/commands/${args[1]}.js`];
Object.keys(require.cache).filter((path) => path.includes(`${args[1]}_`)).forEach((path) => delete require.cache[path]);
const cmdIndex = require('.');
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;
let cmd = cmdIndex[args[1]];
if (!cmd) return this.error(message.channel, 'Could not find file.');
cmd = require(`${corepath}/commands/${args[1]}`).default;
this.client.commands.remove(args[1]);
this.client.loadCommand(Cmd);
this.client.loadCommand(cmd);
delete require.cache[`${corepath}/commands/index.js`];
delete require.cache[`${corepath}/commands/${args[1]}.js`];
Object.keys(require.cache).filter((path) => path.includes(`${args[1]}_`)).forEach((path) => delete require.cache[path]);
} catch (error) {
if (error.message.includes('Cannot find module')) return message.channel.createMessage(`${this.client.stores.emojis.error} ***Could not find file***`);
if (error.message.includes('Cannot find module')) return this.error(message.channel, 'Could not find file.');
throw error;
}
}
return message.channel.createMessage(`${this.client.stores.emojis.success} Reloaded ${type}`);
return this.success(message.channel, `Reloaded ${type}.`);
} catch (error) {
return this.client.util.handleError(error, message, this);
}

View File

@ -16,9 +16,9 @@ export default class Lock extends Command {
try {
if (!args.length) return this.client.commands.get('help').run(message, [this.name]);
const account = await this.client.db.Account.findOne({ $or: [{ username: args[0] }, { userID: args[0].replace(/[<@!>]/gi, '') }] });
if (!account) return message.channel.createMessage(`***${this.client.stores.emojis.error} Cannot find user.***`);
if (account.locked) return message.channel.createMessage(`***${this.client.stores.emojis.error} This account is already locked.***`);
const edit = await message.channel.createMessage(`***${this.client.stores.emojis.loading} Locking account...***`);
if (!account) return this.error(message.channel, 'Cannot find user.');
if (account.locked) return this.error(message.channel, 'This account is already locked.');
const edit = await this.loading(message.channel, 'Locking account...');
if (account.username === 'matthew' || account.root) return edit.edit(`***${this.client.stores.emojis.error} Permission denied.***`);
await this.client.util.sendMessageToUserTerminal(account.username, 'ACCOUNT LOCKED BY TECHNICIAN | PREPARING TO LOGOUT').catch(() => { });
await this.client.util.exec(`lock ${account.username}`);

View File

@ -16,7 +16,7 @@ export default class Modlogs extends Command {
public async run(message: Message, args: string[]) {
try {
if (!args.length) return this.client.commands.get('help').run(message, [this.name]);
const msg: Message = await message.channel.createMessage(`***${this.client.stores.emojis.loading} Locating modlogs...***`);
const msg: Message = await this.loading(message.channel, 'Locating modlogs...');
const query = await this.client.db.Moderation.find({ $or: [{ username: args.join(' ') }, { userID: args.filter((a) => a)[0].replace(/[<@!>]/g, '') }] });
if (!query.length) return msg.edit(`***${this.client.stores.emojis.error} Cannot locate modlogs for ${args.join(' ')}***`);

View File

@ -15,7 +15,7 @@ export default class Notify extends Command {
public async run(message: Message, args: string[]) {
try {
if (!args.length) return this.client.commands.get('help').run(message, [this.name]);
const edit = await message.channel.createMessage(`***${this.client.stores.emojis.loading} Sending notification...***`);
const edit = await this.loading(message.channel, 'Sending notification...');
const account = await this.client.db.Account.findOne({ $or: [{ username: args[0] }, { userID: args[0].replace(/[<@!>]/gi, '') }] });
if (!account) return edit.edit(`***${this.client.stores.emojis.error} Cannot find user.***`);
const embed = new RichEmbed()

View File

@ -1,70 +0,0 @@
import fs from 'fs-extra';
import { parseCert } from '@ghaiklor/x509';
import { Message } from 'eris';
import { Client } from '..';
import { Command, RichEmbed } from '../class';
import { parseCertificate, Certificate } from '../functions';
export default class Parse extends Command {
constructor(client: Client) {
super(client);
this.name = 'parse';
this.description = 'Gets information on a user\'s x509 certificate.';
this.usage = `${this.client.config.prefix}parse [username || user ID]`;
this.permissions = { roles: ['446104438969466890'] };
this.enabled = false;
}
public async run(message: Message, args: string[]) { // eslint-disable-line
try {
if (!args.length) return this.client.commands.get('help').run(message, [this.name]);
const account = await this.client.db.Account.findOne({ $or: [{ username: args[0] }, { userID: args[0].replace(/[<@!>]/gi, '') }] });
if (!account) return message.channel.createMessage(`***${this.client.stores.emojis.error} Cannot find user.***`);
let dir: string[];
try {
dir = await fs.readdir(`${account.homepath}/Validation`);
} catch (err) {
return message.channel.createMessage(`***${this.client.stores.emojis.error} Cannot locate Validation directory.***`);
}
if (!dir.length) return message.channel.createMessage(`***${this.client.stores.emojis.error} Cannot locate certificate.***`);
let cert: Certificate;
try {
cert = await parseCertificate(this.client, `${account.homepath}/Validation/${dir[0]}`);
} catch (error) {
if (error.message.includes('panic: Certificate PEM Encode == nil')) return message.channel.createMessage(`***${this.client.stores.emojis.error} Invalid certificate.***`);
}
// const cert = parseCert(`${account.homepath}/Validation/${dir[0]}`);
const subjectCommonName = cert.subject.commonName || 'Not Specified';
const subjectEmailAddress = cert.subject.emailAddress || 'Not Specified';
const subjectOrganization = cert.subject.organizationName || 'Not Specified';
const subjectOrganizationalUnit = cert.subject.organizationalUnitName || 'Not Specified';
const subjectCountry = cert.subject.countryName || 'Not Specified';
const issuerCommonName = cert.issuer.commonName || 'Not Specified';
const issuerEmailAddress = cert.issuer.emailAddress || 'Not Specified';
const issuerOrganization = cert.issuer.organizationName || 'Not Specified';
const issuerOrganizationalUnit = cert.issuer.organizationalUnitName || 'Not Specified';
const issuerCountry = cert.issuer.countryName || 'Not Specified';
const user = this.client.users.get(account.userID) || await this.client.getRESTUser(account.userID);
const embed = new RichEmbed();
embed.setTitle('Parse x509 Certificate');
embed.setDescription(`${account.homepath}/Validation/${dir[0]} | ${account.username} <@${user.id}>`);
embed.setColor(3447003);
embed.addField('Subject', `**Common Name:** ${subjectCommonName}\n**Email Address:** ${subjectEmailAddress}\n**Organization:** ${subjectOrganization}\n**Organizational Unit:** ${subjectOrganizationalUnit}\n**Country:** ${subjectCountry}`, true);
embed.addField('Issuer', `**Common Name:** ${issuerCommonName}\n**Email Address:** ${issuerEmailAddress}\n**Organization:** ${issuerOrganization}\n**Organizational Unit:** ${issuerOrganizationalUnit}\n**Country:** ${issuerCountry}`, true);
embed.addField('Serial Number', cert.serial, true);
embed.addField('Fingerprint', cert.fingerPrint, true);
embed.addField('Signature Algorithm', cert.signatureAlgorithm, true);
embed.addField('Public Key Algorithm', cert.publicKeyAlgorithm, true);
embed.addField('Key Usage', cert.extensions.keyUsage, true);
embed.addField('Extended Key Usage', cert.extensions.extendedKeyUsage.join(', '), true);
embed.addField('Policies', cert.extensions.certificatePolicies.join(', '), true);
embed.addField('Issued On', new Date(cert.notBefore).toLocaleString('en-us'), true);
embed.addField('Expires On', new Date(cert.notAfter).toLocaleString('en-us'), true);
embed.setFooter(this.client.user.username, this.client.user.avatarURL);
embed.setTimestamp();
message.channel.createMessage({ embed });
} catch (error) {
await this.client.util.handleError(error, message, this);
}
}
}

View File

@ -1,73 +0,0 @@
import { parseCert } from '@ghaiklor/x509';
import { Message } from 'eris';
import { readdirSync } from 'fs';
import moment from 'moment';
import 'moment-precise-range-plugin';
import { Client } from '..';
import { Command, RichEmbed } from '../class';
import { parseCertificate, Certificate } from '../functions';
export default class Parseall extends Command {
constructor(client: Client) {
super(client);
this.name = 'parseall';
this.description = 'Displays certificate validation for all accounts';
this.usage = `${this.client.config.prefix}parseall`;
this.permissions = { roles: ['446104438969466890'] };
this.aliases = ['checkcerts', 'verifyall', 'verifycerts'];
this.enabled = false;
}
public async run(message: Message, args: string[]) {
try {
const msg = await message.channel.createMessage(`${this.client.stores.emojis.loading} ***Loading...***`);
const embed = new RichEmbed();
embed.setTitle('Certificate Validation');
embed.setAuthor(this.client.user.username, this.client.user.avatarURL);
embed.setFooter(`Requested by ${message.member.username}#${message.member.discriminator}`, message.member.avatarURL);
embed.setTimestamp();
const search = await this.client.db.Account.find();
const files = search.map((acc) => {
let certfile: string;
try { certfile = readdirSync(`${acc.homepath}/Validation`)[0] } catch (error) { if (error.message.includes('no such file or directory') || error.message.includes('File doesn\'t exist.')) certfile = 'not_found.crt' } // eslint-disable-line
return `${acc.homepath}/Validation/${certfile}`;
});
const parsed = await Promise.allSettled(files.map((c) => parseCertificate(this.client, c)));
const final: string[] = await Promise.all(search.map(async (a) => {
const result = parsed[search.findIndex((acc) => acc === a)];
if (result.status === 'rejected') {
if (result.reason.message.includes('no such file or directory') || result.reason.message.includes('File doesn\'t exist.')) return `${this.client.stores.emojis.error} **${a.username}** Unable to locate certificate`;
if (result.reason.message.includes('panic: Certificate PEM Encode == nil')) return `${this.client.stores.emojis.error} **${a.username}** Invalid certificate`;
throw result.reason;
}
const { notAfter } = result.value;
const timeObject = moment.preciseDiff(new Date(), notAfter, true);
const precise: [number, string][] = [];
const timeArray: number[] = Object.values(timeObject).filter((v) => typeof v === 'number');
timeArray.forEach((t) => { // eslint-disable-line
const index = timeArray.indexOf(t);
const measurements = ['yr', 'mo', 'd', 'h', 'm', 's'];
precise.push([t, measurements[index]]);
});
const time = precise.filter((n) => n[0]).map(((v) => v.join(''))).join(', ');
if (notAfter < new Date()) return `${this.client.stores.emojis.error} **${a.username}** Expired ${time} ago`;
return `${this.client.stores.emojis.success} **${a.username}** Expires in ${time}`;
}));
if (final.join('\n').length < 2048) embed.setDescription(final.join('\n'));
else {
const split = this.client.util.splitString(final.join('\n'), 1024);
split.forEach((s) => embed.addField('\u200B', s));
}
return await msg.edit({ content: '', embed });
} catch (error) {
return this.client.util.handleError(error, message, this);
}
}
}

View File

@ -15,9 +15,9 @@ export default class Pull extends Command {
public async run(message: Message, args: string[]) {
try {
if (this.client.updating) return message.channel.createMessage(`${this.client.stores.emojis.error} ***Update in progress***`);
if (this.client.updating) return this.error(message.channel, 'An update is already in progress.');
this.client.updating = true;
const updateMessage = await message.channel.createMessage(`${this.client.stores.emojis.loading} ***Fetching latest commit...***`);
const updateMessage = await this.loading(message.channel, 'Fetching latest commit...');
let pull: string;
try {

View File

@ -1,19 +0,0 @@
/* eslint-disable consistent-return */
import { Message } from 'eris';
import { Command } from '../class';
import { Client } from '..';
export default class Reload extends Command {
constructor(client: Client) {
super(client);
this.name = 'reload';
this.description = 'Reloads a command.';
this.usage = `${this.client.config.prefix}reload [command name]`;
this.permissions = { roles: ['525441307037007902'] };
this.enabled = true;
}
public run(message: Message, args: string[]) {
if (!args.length) return this.client.commands.get('help').run(message, [this.name]);
}
}

View File

@ -18,10 +18,10 @@ export default class ResetPassword extends Command {
try {
if (!args[0]) return this.client.commands.get('help').run(message, [this.name]);
const account = await this.client.db.Account.findOne({ $or: [{ username: args[0] }, { userID: args[0] }, { emailAddress: args[0] }] });
if (!account) return message.channel.createMessage(`${this.client.stores.emojis.error} ***Account not found***`);
if (account.root) return message.channel.createMessage(`${this.client.stores.emojis.error} ***Permission denied***`);
if (!account) return this.error(message.channel, 'Account not found.');
if (account.root) return this.error(message.channel, 'Permission denied.');
const msg = await message.channel.createMessage(`${this.client.stores.emojis.loading} ***Resetting password for ${account.username}...***`);
const msg = await this.loading(message.channel, `Resetting password for ${account.username}...`);
const tempPass = this.client.util.randomPassword();
await this.client.util.exec(`echo '${account.username}:${tempPass}' | chpasswd && chage -d0 ${account.username}`);

View File

@ -13,9 +13,9 @@ export default class Restart extends Command {
public async run(message: Message, args: string[]) {
try {
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. See CI job on Gitlab***`);
await message.channel.createMessage(`${this.client.stores.emojis.loading} ***Restarting...***`);
if (this.client.updating && args[0] !== '-f') return this.error(message.channel, 'Update in process.');
if (this.client.buildError) return this.error(message.channel, 'Build error detected, please resolve before continuing. See CI job on GitLab.');
await this.loading(message.channel, 'Restarting...');
return process.exit(1);
} catch (error) {
return this.client.util.handleError(error, message, this);

View File

@ -16,10 +16,10 @@ export default class SetLimit_RAM extends Command {
try {
if (!args[0]) return this.client.commands.get('help').run(message, ['setlimit', this.name]);
const tier = await this.client.db.Tier.findOne({ id: Number(args[0]) });
if (!tier) return message.channel.createMessage(`***${this.client.stores.emojis.error} Cannot locate that tier.***`);
if (Number.isNaN(Number(args[1]))) return message.channel.createMessage(`***${this.client.stores.emojis.error} This is not a valid number.***`);
if (!tier) return this.error(message.channel, 'The tier you provided doesn\'t appear to exist.');
if (Number.isNaN(Number(args[1]))) return this.error(message.channel, 'Invalid number in limit argument.');
await tier.updateOne({ 'resourceLimits.ram': Number(args[1]) });
return message.channel.createMessage(`***${this.client.stores.emojis.success} Tier ${tier.id} RAM resource limit set to ${args[1]} MB.***`);
return this.success(message.channel, `Tier ${tier.id} RAM resource limit set to ${args[1]} MB.`);
} catch (error) {
return this.client.util.handleError(error, message, this);
}

View File

@ -27,7 +27,7 @@ export default class SysInfo extends Command {
embed.addField('Load Average (last 15 minutes)', os.loadavg()[2].toFixed(3), true);
embed.addField('Memory/RAM', `${usedMemory} / ${dataConversion(totalmem())}`, true);
embed.addField('Network Interfaces (IPv4)', os.networkInterfaces().enp0s3.filter((r) => r.family === 'IPv4')[0].address, true);
embed.addField('Network Interfaces (IPv6)', os.networkInterfaces().enp0s3.filter((r) => r.family === 'IPv6')[0].address.replace(/:/gi, '\:'), true); // eslint-disable-line
// embed.addField('Network Interfaces (IPv6)', os.networkInterfaces().enp0s3.filter((r) => r.family === 'IPv6')[0].address.replace(/:/gi, '\:'), true); // eslint-disable-line
embed.setFooter(this.client.user.username, this.client.user.avatarURL);
embed.setTimestamp();
message.channel.createMessage({ embed });

View File

@ -15,7 +15,7 @@ export default class Tier extends Command {
public async run(message: Message, args: string[]) {
try {
if (!args.length) return this.client.commands.get('help').run(message, [this.name]);
const edit = await message.channel.createMessage(`***${this.client.stores.emojis.loading} Editing tier...***`);
const edit = await this.loading(message.channel, 'Editing tier...');
const account = await this.client.db.Account.findOne({ $or: [{ username: args[0] }, { userID: args[0].replace(/[<@!>]/gi, '') }] });
if (!account) return edit.edit(`***${this.client.stores.emojis.error} Cannot find user.***`);
if (account.root) return edit.edit(`***${this.client.stores.emojis.error} Permission denied.***`);

View File

@ -15,9 +15,9 @@ export default class Unlock extends Command {
try {
if (!args.length) return this.client.commands.get('help').run(message, [this.name]);
const account = await this.client.db.Account.findOne({ $or: [{ username: args[0] }, { userID: args[0].replace(/[<@!>]/gi, '') }] });
if (!account) return message.channel.createMessage(`***${this.client.stores.emojis.error} Cannot find user.***`);
if (!account.locked) return message.channel.createMessage(`***${this.client.stores.emojis.error} This account is already unlocked.***`);
const edit = await message.channel.createMessage(`***${this.client.stores.emojis.loading} Unlocking account...***`);
if (!account) return this.error(message.channel, 'Cannot find user.');
if (!account.locked) return this.error(message.channel, 'This account is already unlocked.');
const edit = await this.loading(message.channel, 'Unlocking account...');
if (account.username === 'matthew' || account.root) return edit.edit(`***${this.client.stores.emojis.error} Permission denied.***`);
await this.client.util.exec(`unlock ${account.username}`);
await account.updateOne({ locked: false });

View File

@ -15,7 +15,7 @@ export default class Warn extends Command {
public async run(message: Message, args: string[]) {
try {
if (!args.length) return this.client.commands.get('help').run(message, [this.name]);
const edit = await message.channel.createMessage(`***${this.client.stores.emojis.loading} Sending warning...***`);
const edit = await this.loading(message.channel, 'Processing warning...');
const account = await this.client.db.Account.findOne({ $or: [{ username: args[0] }, { userID: args[0].replace(/[<@!>]/gi, '') }] });
if (!account) return edit.edit(`***${this.client.stores.emojis.error} Cannot find user.***`);
if (account.root) return edit.edit(`***${this.client.stores.emojis.error} Permission denied.***`);

View File

@ -28,7 +28,7 @@ export default class Whois extends Command {
const user = args[0] || message.author.id;
if (full) account = await this.client.db.Account.findOne({ $or: [{ username: user }, { userID: user }, { emailAddress: user }, { supportKey: user.toUpperCase() }] });
else account = await this.client.db.Account.findOne({ $or: [{ username: user }, { userID: user }] });
if (!account) return message.channel.createMessage(`***${this.client.stores.emojis.error} Account not found.***`);
if (!account) return this.error(message.channel, 'Account not found.');
const thumbnail = this.client.users.get(account.userID)?.avatarURL || message.channel.guild.iconURL;