forked from engineering/cloudservices
Merge branches 'master' and 'master' of https://gitlab.libraryofcode.us/engineering/cloudservices-rewrite
commit
b1c261cb57
|
@ -1,6 +1,6 @@
|
||||||
{
|
{
|
||||||
"name": "cloudservices-rewrite",
|
"name": "cloudservices-rewrite",
|
||||||
"version": "1.1.0",
|
"version": "1.2.0",
|
||||||
"description": "The official LOC Cloud Services system, this is a rewrite of the original version. ",
|
"description": "The official LOC Cloud Services system, this is a rewrite of the original version. ",
|
||||||
"main": "dist/Client.js",
|
"main": "dist/Client.js",
|
||||||
"scripts": {
|
"scripts": {
|
||||||
|
@ -16,6 +16,7 @@
|
||||||
"eris": "^0.10.1",
|
"eris": "^0.10.1",
|
||||||
"eris-pagination": "bsian03/eris-pagination",
|
"eris-pagination": "bsian03/eris-pagination",
|
||||||
"fs-extra": "^8.1.0",
|
"fs-extra": "^8.1.0",
|
||||||
|
"ioredis": "^4.14.1",
|
||||||
"moment": "^2.24.0",
|
"moment": "^2.24.0",
|
||||||
"moment-precise-range-plugin": "^1.3.0",
|
"moment-precise-range-plugin": "^1.3.0",
|
||||||
"mongoose": "^5.7.4",
|
"mongoose": "^5.7.4",
|
||||||
|
@ -25,6 +26,7 @@
|
||||||
},
|
},
|
||||||
"devDependencies": {
|
"devDependencies": {
|
||||||
"@types/fs-extra": "^8.0.0",
|
"@types/fs-extra": "^8.0.0",
|
||||||
|
"@types/ioredis": "^4.0.18",
|
||||||
"@types/mongoose": "^5.5.20",
|
"@types/mongoose": "^5.5.20",
|
||||||
"@types/nodemailer": "^6.2.1",
|
"@types/nodemailer": "^6.2.1",
|
||||||
"@types/signale": "^1.2.1",
|
"@types/signale": "^1.2.1",
|
||||||
|
|
|
@ -1,8 +1,8 @@
|
||||||
import Eris from 'eris';
|
import Eris from 'eris';
|
||||||
|
import Redis from 'ioredis';
|
||||||
import mongoose from 'mongoose';
|
import mongoose from 'mongoose';
|
||||||
import signale from 'signale';
|
import signale from 'signale';
|
||||||
import fs from 'fs-extra';
|
import fs from 'fs-extra';
|
||||||
import path from 'path';
|
|
||||||
import config from './config.json';
|
import config from './config.json';
|
||||||
import { Account, AccountInterface, Moderation, ModerationInterface, Domain, DomainInterface } from './models';
|
import { Account, AccountInterface, Moderation, ModerationInterface, Domain, DomainInterface } from './models';
|
||||||
import { emojis } from './stores';
|
import { emojis } from './stores';
|
||||||
|
@ -19,6 +19,8 @@ export default class Client extends Eris.Client {
|
||||||
|
|
||||||
public db: { Account: mongoose.Model<AccountInterface>; Domain: mongoose.Model<DomainInterface>; Moderation: mongoose.Model<ModerationInterface>; };
|
public db: { Account: mongoose.Model<AccountInterface>; Domain: mongoose.Model<DomainInterface>; Moderation: mongoose.Model<ModerationInterface>; };
|
||||||
|
|
||||||
|
public redis: Redis.Redis;
|
||||||
|
|
||||||
public stores: { emojis: { success: string, loading: string, error: string }; };
|
public stores: { emojis: { success: string, loading: string, error: string }; };
|
||||||
|
|
||||||
public signale: signale.Signale;
|
public signale: signale.Signale;
|
||||||
|
@ -31,6 +33,7 @@ export default class Client extends Eris.Client {
|
||||||
this.util = new Util(this);
|
this.util = new Util(this);
|
||||||
this.commands = new Collection<Command>();
|
this.commands = new Collection<Command>();
|
||||||
this.db = { Account, Domain, Moderation };
|
this.db = { Account, Domain, Moderation };
|
||||||
|
this.redis = new Redis();
|
||||||
this.stores = { emojis };
|
this.stores = { emojis };
|
||||||
this.signale = signale;
|
this.signale = signale;
|
||||||
this.signale.config({
|
this.signale.config({
|
||||||
|
@ -82,13 +85,6 @@ export default class Client extends Eris.Client {
|
||||||
public async init() {
|
public async init() {
|
||||||
const evtFiles = await fs.readdir('./events/');
|
const evtFiles = await fs.readdir('./events/');
|
||||||
Object.values(commands).forEach((c: Function) => this.loadCommand(c));
|
Object.values(commands).forEach((c: Function) => this.loadCommand(c));
|
||||||
/*
|
|
||||||
const commands = await fs.readdir(path.join(__dirname, './commands/'));
|
|
||||||
commands.forEach((command) => {
|
|
||||||
if (command === 'index.js') return;
|
|
||||||
this.loadCommand(`./commands/${command}`);
|
|
||||||
});
|
|
||||||
*/
|
|
||||||
|
|
||||||
evtFiles.forEach((file) => {
|
evtFiles.forEach((file) => {
|
||||||
const eventName = file.split('.')[0];
|
const eventName = file.split('.')[0];
|
||||||
|
@ -105,6 +101,13 @@ export default class Client extends Eris.Client {
|
||||||
this.on('ready', () => {
|
this.on('ready', () => {
|
||||||
this.signale.info(`Connected to Discord as ${this.user.username}#${this.user.discriminator}`);
|
this.signale.info(`Connected to Discord as ${this.user.username}#${this.user.discriminator}`);
|
||||||
});
|
});
|
||||||
|
const intervals = await fs.readdir('./intervals');
|
||||||
|
intervals.forEach((interval) => {
|
||||||
|
// eslint-disable-next-line
|
||||||
|
if (interval === 'index.js') return;
|
||||||
|
require(`./intervals/${interval}`).default(this);
|
||||||
|
this.signale.complete(`Loaded interval ${interval.split('.')[0]}`);
|
||||||
|
});
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -232,11 +232,11 @@ export default class Util {
|
||||||
let color: string;
|
let color: string;
|
||||||
let archType: string;
|
let archType: string;
|
||||||
switch (type) {
|
switch (type) {
|
||||||
default: archType = 'Moderator'; embedTitle = 'Cloud Account | Generic'; color = '0892e1'; break;
|
default: archType = 'Staff'; embedTitle = 'Cloud Account | Generic'; color = '0892e1'; break;
|
||||||
case 0: archType = 'Administrator'; embedTitle = 'Cloud Account | Create'; color = '00ff00'; break;
|
case 0: archType = 'Administrator'; embedTitle = 'Cloud Account | Create'; color = '00ff00'; break;
|
||||||
case 1: archType = 'Moderator'; embedTitle = 'Account Warning | Warn'; color = 'ffff00'; break;
|
case 1: archType = 'Staff'; embedTitle = 'Account Warning | Warn'; color = 'ffff00'; break;
|
||||||
case 2: archType = 'Supervisor'; embedTitle = 'Account Infraction | Lock'; color = 'ff6600'; break;
|
case 2: archType = 'Moderator'; embedTitle = 'Account Infraction | Lock'; color = 'ff6600'; break;
|
||||||
case 3: archType = 'Supervisor'; embedTitle = 'Account Reclaim | Unlock'; color = '0099ff'; break;
|
case 3: archType = 'Moderator'; embedTitle = 'Account Reclaim | Unlock'; color = '0099ff'; break;
|
||||||
case 4: archType = 'Administrator'; embedTitle = 'Cloud Account | Delete'; color = 'ff0000'; break;
|
case 4: archType = 'Administrator'; embedTitle = 'Cloud Account | Delete'; color = 'ff0000'; break;
|
||||||
}
|
}
|
||||||
const embed = new RichEmbed()
|
const embed = new RichEmbed()
|
||||||
|
|
|
@ -9,7 +9,7 @@ export default class Announce extends Command {
|
||||||
this.description = 'Sends an announcement to all active terminals';
|
this.description = 'Sends an announcement to all active terminals';
|
||||||
this.usage = `${this.client.config.prefix}announce Hi there! | ${this.client.config.prefix}announce -e EMERGENCY!`;
|
this.usage = `${this.client.config.prefix}announce Hi there! | ${this.client.config.prefix}announce -e EMERGENCY!`;
|
||||||
this.aliases = ['ann'];
|
this.aliases = ['ann'];
|
||||||
this.permissions = { roles: ['608095934399643649', '521312697896271873'] };
|
this.permissions = { roles: ['475817826251440128', '525441307037007902'] };
|
||||||
this.enabled = true;
|
this.enabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -53,7 +53,9 @@ export default class CWG_Delete extends Command {
|
||||||
await this.client.util.exec('systemctl reload nginx');
|
await this.client.util.exec('systemctl reload nginx');
|
||||||
edit.edit(`***${this.client.stores.emojis.success} Domain ${domain.domain} with port ${domain.port} has been successfully deleted.***`);
|
edit.edit(`***${this.client.stores.emojis.success} Domain ${domain.domain} with port ${domain.port} has been successfully deleted.***`);
|
||||||
// @ts-ignore
|
// @ts-ignore
|
||||||
return message.channel.createMessage({ embed });
|
this.client.createMessage('580950455581147146', { embed });
|
||||||
|
// @ts-ignore
|
||||||
|
return this.client.getDMChannel(domain.account.userID).then((channel) => channel.createMessage({ embed })).catch(() => {});
|
||||||
} catch (error) {
|
} catch (error) {
|
||||||
return this.client.util.handleError(error, message, this);
|
return this.client.util.handleError(error, message, this);
|
||||||
}
|
}
|
||||||
|
|
|
@ -1,6 +1,6 @@
|
||||||
import { Message, PrivateChannel } from 'eris';
|
import { Message, PrivateChannel } from 'eris';
|
||||||
import uuid from 'uuid/v4';
|
import uuid from 'uuid/v4';
|
||||||
import { Command, RichEmbed } from '../class';
|
import { Command } from '../class';
|
||||||
import { Client } from '..';
|
import { Client } from '..';
|
||||||
|
|
||||||
export default class DeleteAccount extends Command {
|
export default class DeleteAccount extends Command {
|
||||||
|
|
|
@ -3,6 +3,7 @@ import moment from 'moment';
|
||||||
import { Client } from '..';
|
import { Client } from '..';
|
||||||
import { RichEmbed, Command } from '../class';
|
import { RichEmbed, Command } from '../class';
|
||||||
import { dataConversion } from '../functions';
|
import { dataConversion } from '../functions';
|
||||||
|
// eslint-disable-next-line import/no-unresolved
|
||||||
import 'moment-precise-range-plugin';
|
import 'moment-precise-range-plugin';
|
||||||
|
|
||||||
export default class Disk extends Command {
|
export default class Disk extends Command {
|
||||||
|
@ -12,7 +13,7 @@ export default class Disk extends Command {
|
||||||
this.description = 'Checks the used disk space by a user';
|
this.description = 'Checks the used disk space by a user';
|
||||||
this.usage = `${this.client.config.prefix}disk [Username/User ID/Email]`;
|
this.usage = `${this.client.config.prefix}disk [Username/User ID/Email]`;
|
||||||
this.permissions = { roles: ['446104438969466890'] };
|
this.permissions = { roles: ['446104438969466890'] };
|
||||||
this.enabled = true;
|
this.enabled = false;
|
||||||
}
|
}
|
||||||
|
|
||||||
async run(message: Message, args: string[]) {
|
async run(message: Message, args: string[]) {
|
||||||
|
|
|
@ -8,7 +8,7 @@ export default class Lock extends Command {
|
||||||
super(client);
|
super(client);
|
||||||
this.name = 'lock';
|
this.name = 'lock';
|
||||||
this.description = 'Locks an account.';
|
this.description = 'Locks an account.';
|
||||||
this.permissions = { roles: ['608095934399643649', '521312697896271873'] };
|
this.permissions = { roles: ['455972169449734144', '643619219988152321'] };
|
||||||
this.enabled = true;
|
this.enabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -18,7 +18,13 @@ export default class Parse extends Command {
|
||||||
if (!args.length) return this.client.commands.get('help').run(message, [this.name]);
|
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, '') }] });
|
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) return message.channel.createMessage(`***${this.client.stores.emojis.error} Cannot find user.***`);
|
||||||
const dir = await fs.readdir(`/home/${account.username}/Validation`);
|
let dir: string[];
|
||||||
|
try {
|
||||||
|
dir = await fs.readdir(`/home/${account.username}/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.***`);
|
||||||
const cert = parseCert(`/home/${account.username}/Validation/${dir[0]}`);
|
const cert = parseCert(`/home/${account.username}/Validation/${dir[0]}`);
|
||||||
const subjectCommonName = cert.subject.commonName ? cert.subject.commonName : 'Not Specified';
|
const subjectCommonName = cert.subject.commonName ? cert.subject.commonName : 'Not Specified';
|
||||||
const subjectEmailAddress = cert.subject.emailAddress ? cert.subject.emailAddress : 'Not Specified';
|
const subjectEmailAddress = cert.subject.emailAddress ? cert.subject.emailAddress : 'Not Specified';
|
||||||
|
|
|
@ -8,7 +8,7 @@ export default class Unlock extends Command {
|
||||||
super(client);
|
super(client);
|
||||||
this.name = 'unlock';
|
this.name = 'unlock';
|
||||||
this.description = 'Unlocks an account.';
|
this.description = 'Unlocks an account.';
|
||||||
this.permissions = { roles: ['608095934399643649', '521312697896271873'] };
|
this.permissions = { roles: ['455972169449734144', '643619219988152321'] };
|
||||||
this.enabled = true;
|
this.enabled = true;
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
|
@ -3,6 +3,7 @@ import moment from 'moment';
|
||||||
import { Message } from 'eris';
|
import { Message } from 'eris';
|
||||||
import { Client } from '..';
|
import { Client } from '..';
|
||||||
import { Command, RichEmbed } from '../class';
|
import { Command, RichEmbed } from '../class';
|
||||||
|
import { dataConversion } from '../functions';
|
||||||
|
|
||||||
export default class Whois extends Command {
|
export default class Whois extends Command {
|
||||||
constructor(client: Client) {
|
constructor(client: Client) {
|
||||||
|
@ -30,6 +31,11 @@ export default class Whois extends Command {
|
||||||
embed.addField('Email Address', account.emailAddress, true);
|
embed.addField('Email Address', account.emailAddress, true);
|
||||||
embed.addField('Created By', `<@${this.client.users.get(account.createdBy).id}>`, true);
|
embed.addField('Created By', `<@${this.client.users.get(account.createdBy).id}>`, true);
|
||||||
embed.addField('Created At', moment(account.createdAt).format('dddd, MMMM Do YYYY, h:mm:ss A'), true);
|
embed.addField('Created At', moment(account.createdAt).format('dddd, MMMM Do YYYY, h:mm:ss A'), true);
|
||||||
|
const cpuUsage = await this.client.util.exec(`top -b -n 1 -u ${account.username} | awk 'NR>7 { sum += $9; } END { print sum; }'`);
|
||||||
|
embed.addField('CPU Usage', cpuUsage.split('\n')[0] ? `${cpuUsage.split('\n')[0]}%` : '0%', true);
|
||||||
|
embed.addField('Memory', dataConversion(Number(await this.client.util.exec(`memory ${account.username}`)) * 1000), true);
|
||||||
|
const data = await this.client.redis.get(`storage-${account.username}`) ? dataConversion(Number(await this.client.redis.get(`storage-${account.username}`))) : 'N/A';
|
||||||
|
embed.addField('Storage', data, true);
|
||||||
let details = '';
|
let details = '';
|
||||||
if (account.locked) details += 'This account is currently locked.\n';
|
if (account.locked) details += 'This account is currently locked.\n';
|
||||||
if (account.permissions.engineer) details += 'This account belongs to an Engineer.\n';
|
if (account.permissions.engineer) details += 'This account belongs to an Engineer.\n';
|
||||||
|
|
|
@ -1,5 +1,8 @@
|
||||||
export default function dataConversion(bytes: number) {
|
export default function dataConversion(bytes) {
|
||||||
const i = Math.floor(Math.log(bytes) / Math.log(1024));
|
const i = Math.floor(Math.log(bytes) / Math.log(1024));
|
||||||
const sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
|
const sizes = ['B', 'KB', 'MB', 'GB', 'TB', 'PB', 'EB', 'ZB', 'YB'];
|
||||||
|
if (bytes === 0) {
|
||||||
|
return '0 KB';
|
||||||
|
}
|
||||||
return `${(bytes / 1024 ** i).toFixed(2)} ${sizes[i]}`;
|
return `${(bytes / 1024 ** i).toFixed(2)} ${sizes[i]}`;
|
||||||
}
|
}
|
||||||
|
|
|
@ -0,0 +1,25 @@
|
||||||
|
/* eslint-disable no-await-in-loop */
|
||||||
|
import fs from 'fs-extra';
|
||||||
|
import { Client } from '..';
|
||||||
|
|
||||||
|
export default async function storage(client: Client) {
|
||||||
|
const main = async () => {
|
||||||
|
const accounts = await client.db.Account.find();
|
||||||
|
for (const account of accounts) {
|
||||||
|
const res = await client.util.exec(`du -bs /home/${account.username}`);
|
||||||
|
let bytes = Number(res.split('/')[0].replace('\t', ''));
|
||||||
|
try {
|
||||||
|
await fs.access(`/var/mail/${account.username}`, fs.constants.F_OK);
|
||||||
|
const res2 = await client.util.exec(`du -bs /var/mail/${account.username}`);
|
||||||
|
bytes += Number(res2.split('/')[0].replace('\t', ''));
|
||||||
|
} catch {
|
||||||
|
bytes += 0;
|
||||||
|
}
|
||||||
|
await client.redis.set(`storage-${account.username}`, bytes);
|
||||||
|
}
|
||||||
|
};
|
||||||
|
await main();
|
||||||
|
setInterval(async () => {
|
||||||
|
await main();
|
||||||
|
}, 900000);
|
||||||
|
}
|
Loading…
Reference in New Issue