merge-requests/4/head
Matthew 2020-06-29 03:00:27 -04:00
parent cbb5c1585a
commit b15b7b514f
No known key found for this signature in database
GPG Key ID: 210AF32ADE3B5C4B
2 changed files with 219 additions and 220 deletions

View File

@ -1,135 +1,134 @@
import Eris from 'eris'; import Eris from 'eris';
import Redis from 'ioredis'; 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 config from '../config.json'; import config from '../config.json';
import CSCLI from '../cscli/main'; import CSCLI from '../cscli/main';
import { Server } from '../api'; import { Account, AccountInterface, Moderation, ModerationInterface, Domain, DomainInterface, Tier, TierInterface } from '../models';
import { Account, AccountInterface, Moderation, ModerationInterface, Domain, DomainInterface, Tier, TierInterface } from '../models'; import { emojis } from '../stores';
import { emojis } from '../stores'; import { Command, Util, Collection, Server } from '.';
import { Command, Util, Collection } from '.'; import * as commands from '../commands';
import * as commands from '../commands';
export default class Client extends Eris.Client {
export default class Client extends Eris.Client { public config: { 'token': string; 'cloudflare': string; 'prefix': string; 'emailPass': string; 'mongoURL': string; 'port': number; 'keyPair': { 'publicKey': string; 'privateKey': string; }; };
public config: { 'token': string; 'cloudflare': string; 'prefix': string; 'emailPass': string; 'mongoURL': string; 'port': number; 'keyPair': { 'publicKey': string; 'privateKey': string; }; };
public util: Util;
public util: Util;
public commands: Collection<Command>;
public commands: Collection<Command>;
public db: { Account: mongoose.Model<AccountInterface>; Domain: mongoose.Model<DomainInterface>; Moderation: mongoose.Model<ModerationInterface>; Tier: mongoose.Model<TierInterface>; };
public db: { Account: mongoose.Model<AccountInterface>; Domain: mongoose.Model<DomainInterface>; Moderation: mongoose.Model<ModerationInterface>; Tier: mongoose.Model<TierInterface>; };
public redis: Redis.Redis;
public redis: Redis.Redis;
public stores: { emojis: { success: string, loading: string, error: string }; };
public stores: { emojis: { success: string, loading: string, error: string }; };
public functions: Collection<Function>;
public functions: Collection<Function>;
public signale: signale.Signale;
public signale: signale.Signale;
public server: Server;
public server: Server;
public updating: boolean;
public updating: boolean;
public buildError: boolean
public buildError: boolean
constructor() {
constructor() { super(config.token, { getAllUsers: true, restMode: true, defaultImageFormat: 'png' });
super(config.token, { getAllUsers: true, restMode: true, defaultImageFormat: 'png' });
process.title = 'cloudservices';
process.title = 'cloudservices'; this.config = config;
this.config = config; this.util = new Util(this);
this.util = new Util(this); this.commands = new Collection<Command>();
this.commands = new Collection<Command>(); this.functions = new Collection<Function>();
this.functions = new Collection<Function>(); this.db = { Account, Domain, Moderation, Tier };
this.db = { Account, Domain, Moderation, Tier }; this.redis = new Redis();
this.redis = new Redis(); this.stores = { emojis };
this.stores = { emojis }; this.signale = signale;
this.signale = signale; this.signale.config({
this.signale.config({ displayDate: true,
displayDate: true, displayTimestamp: true,
displayTimestamp: true, displayFilename: true,
displayFilename: true, });
}); this.updating = false;
this.updating = false; this.buildError = false;
this.buildError = false; this.events();
this.events(); this.loadFunctions();
this.loadFunctions(); this.init();
this.init(); }
}
private async events() {
private async events() { process.on('unhandledRejection', (error) => {
process.on('unhandledRejection', (error) => { this.signale.error(error);
this.signale.error(error); });
}); }
}
private async loadFunctions() {
private async loadFunctions() { const functions = await fs.readdir('../functions');
const functions = await fs.readdir('../functions'); functions.forEach(async (func) => {
functions.forEach(async (func) => { if (func === 'index.ts' || func === 'index.js') return;
if (func === 'index.ts' || func === 'index.js') return; try {
try { const funcRequire: Function = require(`../functions/${func}`).default;
const funcRequire: Function = require(`../functions/${func}`).default; this.functions.set(func.split('.')[0], funcRequire);
this.functions.set(func.split('.')[0], funcRequire); } catch (error) {
} catch (error) { this.signale.error(`Error occured loading ${func}`);
this.signale.error(`Error occured loading ${func}`); await this.util.handleError(error);
await this.util.handleError(error); }
} });
}); }
}
public loadCommand(CommandFile: any) {
public loadCommand(CommandFile: any) { // eslint-disable-next-line no-useless-catch
// eslint-disable-next-line no-useless-catch try {
try { // eslint-disable-next-line
// eslint-disable-next-line const command: Command = new CommandFile(this);
const command: Command = new CommandFile(this); if (command.subcmds.length) {
if (command.subcmds.length) { command.subcmds.forEach((C) => {
command.subcmds.forEach((C) => { const cmd: Command = new C(this);
const cmd: Command = new C(this); command.subcommands.add(cmd.name, cmd);
command.subcommands.add(cmd.name, cmd); });
}); }
} delete command.subcmds;
delete command.subcmds; this.commands.add(command.name, command);
this.commands.add(command.name, command); this.signale.complete(`Loaded command ${command.name}`);
this.signale.complete(`Loaded command ${command.name}`); } catch (err) { throw err; }
} catch (err) { throw err; } }
}
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));
evtFiles.forEach((file) => {
evtFiles.forEach((file) => { const eventName = file.split('.')[0];
const eventName = file.split('.')[0]; if (file === 'index.js') return;
if (file === 'index.js') return; // eslint-disable-next-line
// eslint-disable-next-line const event = new (require(`../events/${file}`).default)(this);
const event = new (require(`../events/${file}`).default)(this); this.signale.complete(`Loaded event ${eventName}`);
this.signale.complete(`Loaded event ${eventName}`); this.on(eventName, (...args) => event.run(...args));
this.on(eventName, (...args) => event.run(...args)); delete require.cache[require.resolve(`../events/${file}`)];
delete require.cache[require.resolve(`../events/${file}`)]; });
});
await mongoose.connect(config.mongoURL, { useNewUrlParser: true, useUnifiedTopology: true });
await mongoose.connect(config.mongoURL, { useNewUrlParser: true, useUnifiedTopology: true }); await this.connect();
await this.connect(); 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');
const intervals = await fs.readdir('../intervals'); intervals.forEach((interval) => {
intervals.forEach((interval) => { // eslint-disable-next-line
// eslint-disable-next-line if (interval === 'index.js') return;
if (interval === 'index.js') return; require(`../intervals/${interval}`).default(this);
require(`../intervals/${interval}`).default(this); 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 }); // eslint-disable-next-line no-new
// eslint-disable-next-line no-new new CSCLI(this);
new CSCLI(this);
const corepath = '/opt/CloudServices/dist';
const corepath = '/opt/CloudServices/dist'; const cmdFiles = await fs.readdir('/opt/CloudServices/dist/commands');
const cmdFiles = await fs.readdir('/opt/CloudServices/dist/commands'); cmdFiles.forEach((f) => delete require.cache[`${corepath}/${f}`]);
cmdFiles.forEach((f) => delete require.cache[`${corepath}/${f}`]); delete require.cache[`${corepath}/config.json`];
delete require.cache[`${corepath}/config.json`]; delete require.cache[`${corepath}/class/Util`];
delete require.cache[`${corepath}/class/Util`]; }
} }
}

View File

@ -1,85 +1,85 @@
/* eslint-disable no-case-declarations */ /* eslint-disable no-case-declarations */
/* eslint-disable consistent-return */ /* eslint-disable consistent-return */
import net from 'net'; import net from 'net';
import crypto from 'crypto'; import crypto from 'crypto';
import { promises as fs } from 'fs'; import { promises as fs } from 'fs';
import Client from '../class/Client'; import { Client } from '../class';
import { dataConversion } from '../functions'; import { dataConversion } from '../functions';
export default class CSCLI { export default class CSCLI {
public client: Client; public client: Client;
public server: net.Server; public server: net.Server;
#hmac: string; #hmac: string;
constructor(client: Client) { constructor(client: Client) {
this.client = client; this.client = client;
this.loadKeys(); this.loadKeys();
this.server = net.createServer((socket) => { this.server = net.createServer((socket) => {
socket.on('data', async (data) => { socket.on('data', async (data) => {
try { try {
await this.handle(socket, data); await this.handle(socket, data);
} catch (err) { } catch (err) {
await this.client.util.handleError(err); await this.client.util.handleError(err);
socket.destroy(); socket.destroy();
} }
}); });
}); });
this.init(); this.init();
} }
public async handle(socket: net.Socket, data: Buffer) { public async handle(socket: net.Socket, data: Buffer) {
const args = data.toString().trim().split('$'); const args = data.toString().trim().split('$');
const verification = this.verifyConnection(args[1], args[0]); const verification = this.verifyConnection(args[1], args[0]);
if (!verification) { if (!verification) {
socket.write('UNAUTHORIZED TO EXECUTE ON THIS SERVER\n'); socket.write('UNAUTHORIZED TO EXECUTE ON THIS SERVER\n');
return socket.destroy(); return socket.destroy();
} }
const parsed: { Username: string, Type: string, Message?: string, HMAC: string } = JSON.parse(args[0]); const parsed: { Username: string, Type: string, Message?: string, HMAC: string } = JSON.parse(args[0]);
// FINISH VERIFICATION CHECKS // FINISH VERIFICATION CHECKS
switch (parsed.Type) { switch (parsed.Type) {
case 'lock': case 'lock':
await this.client.util.accounts.lock(parsed.Username, this.client.user.id, { reason: parsed.Message }); await this.client.util.accounts.lock(parsed.Username, this.client.user.id, { reason: parsed.Message });
break; break;
case 'killpid': case 'killpid':
await this.client.util.exec(`kill -9 ${parsed.Message}`); await this.client.util.exec(`kill -9 ${parsed.Message}`);
break; break;
case 'ram': case 'ram':
const memoryConversion = dataConversion(Number(await this.client.util.exec(`memory ${parsed.Username}`)) * 1000); const memoryConversion = dataConversion(Number(await this.client.util.exec(`memory ${parsed.Username}`)) * 1000);
socket.write(`${memoryConversion}\n`); socket.write(`${memoryConversion}\n`);
socket.destroy(); socket.destroy();
break; break;
case 'storage': case 'storage':
const res = await this.client.redis.get(`storage-${parsed.Username}`) ? dataConversion(Number(await this.client.redis.get(`storage-${parsed.Username}`))) : 'N/A'; const res = await this.client.redis.get(`storage-${parsed.Username}`) ? dataConversion(Number(await this.client.redis.get(`storage-${parsed.Username}`))) : 'N/A';
socket.write(`${res}\n`); socket.write(`${res}\n`);
socket.destroy(); socket.destroy();
break; break;
default: default:
socket.destroy(); socket.destroy();
break; break;
} }
} }
public verifyConnection(key: string, data: any): boolean { public verifyConnection(key: string, data: any): boolean {
const hmac = crypto.createHmac('sha256', this.#hmac); const hmac = crypto.createHmac('sha256', this.#hmac);
hmac.update(data); hmac.update(data);
const computed = hmac.digest('hex'); const computed = hmac.digest('hex');
if (computed === key) return true; if (computed === key) return true;
return false; return false;
} }
public async loadKeys() { public async loadKeys() {
const key = await fs.readFile('/etc/cscli.conf', { encoding: 'utf8' }); const key = await fs.readFile('/etc/cscli.conf', { encoding: 'utf8' });
this.#hmac = key.toString().trim(); this.#hmac = key.toString().trim();
} }
public init() { public init() {
this.server.on('error', (err) => { this.server.on('error', (err) => {
this.client.util.handleError(err); this.client.util.handleError(err);
}); });
this.server.listen(8124, () => { this.server.listen(8124, () => {
this.client.signale.success('TCP socket is now listening for connections.'); this.client.signale.success('TCP socket is now listening for connections.');
}); });
} }
} }