forked from engineering/cloudservices
fixes
parent
cbb5c1585a
commit
b15b7b514f
|
@ -1,135 +1,134 @@
|
|||
import Eris from 'eris';
|
||||
import Redis from 'ioredis';
|
||||
import mongoose from 'mongoose';
|
||||
import signale from 'signale';
|
||||
import fs from 'fs-extra';
|
||||
import config from '../config.json';
|
||||
import CSCLI from '../cscli/main';
|
||||
import { Server } from '../api';
|
||||
import { Account, AccountInterface, Moderation, ModerationInterface, Domain, DomainInterface, Tier, TierInterface } from '../models';
|
||||
import { emojis } from '../stores';
|
||||
import { Command, Util, Collection } from '.';
|
||||
import * as commands from '../commands';
|
||||
|
||||
|
||||
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 util: Util;
|
||||
|
||||
public commands: Collection<Command>;
|
||||
|
||||
public db: { Account: mongoose.Model<AccountInterface>; Domain: mongoose.Model<DomainInterface>; Moderation: mongoose.Model<ModerationInterface>; Tier: mongoose.Model<TierInterface>; };
|
||||
|
||||
public redis: Redis.Redis;
|
||||
|
||||
public stores: { emojis: { success: string, loading: string, error: string }; };
|
||||
|
||||
public functions: Collection<Function>;
|
||||
|
||||
public signale: signale.Signale;
|
||||
|
||||
public server: Server;
|
||||
|
||||
public updating: boolean;
|
||||
|
||||
public buildError: boolean
|
||||
|
||||
constructor() {
|
||||
super(config.token, { getAllUsers: true, restMode: true, defaultImageFormat: 'png' });
|
||||
|
||||
process.title = 'cloudservices';
|
||||
this.config = config;
|
||||
this.util = new Util(this);
|
||||
this.commands = new Collection<Command>();
|
||||
this.functions = new Collection<Function>();
|
||||
this.db = { Account, Domain, Moderation, Tier };
|
||||
this.redis = new Redis();
|
||||
this.stores = { emojis };
|
||||
this.signale = signale;
|
||||
this.signale.config({
|
||||
displayDate: true,
|
||||
displayTimestamp: true,
|
||||
displayFilename: true,
|
||||
});
|
||||
this.updating = false;
|
||||
this.buildError = false;
|
||||
this.events();
|
||||
this.loadFunctions();
|
||||
this.init();
|
||||
}
|
||||
|
||||
private async events() {
|
||||
process.on('unhandledRejection', (error) => {
|
||||
this.signale.error(error);
|
||||
});
|
||||
}
|
||||
|
||||
private async loadFunctions() {
|
||||
const functions = await fs.readdir('../functions');
|
||||
functions.forEach(async (func) => {
|
||||
if (func === 'index.ts' || func === 'index.js') return;
|
||||
try {
|
||||
const funcRequire: Function = require(`../functions/${func}`).default;
|
||||
this.functions.set(func.split('.')[0], funcRequire);
|
||||
} catch (error) {
|
||||
this.signale.error(`Error occured loading ${func}`);
|
||||
await this.util.handleError(error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public loadCommand(CommandFile: any) {
|
||||
// eslint-disable-next-line no-useless-catch
|
||||
try {
|
||||
// eslint-disable-next-line
|
||||
const command: Command = new CommandFile(this);
|
||||
if (command.subcmds.length) {
|
||||
command.subcmds.forEach((C) => {
|
||||
const cmd: Command = new C(this);
|
||||
command.subcommands.add(cmd.name, cmd);
|
||||
});
|
||||
}
|
||||
delete command.subcmds;
|
||||
this.commands.add(command.name, command);
|
||||
this.signale.complete(`Loaded command ${command.name}`);
|
||||
} catch (err) { throw err; }
|
||||
}
|
||||
|
||||
public async init() {
|
||||
const evtFiles = await fs.readdir('../events/');
|
||||
Object.values(commands).forEach((c: Function) => this.loadCommand(c));
|
||||
|
||||
evtFiles.forEach((file) => {
|
||||
const eventName = file.split('.')[0];
|
||||
if (file === 'index.js') return;
|
||||
// eslint-disable-next-line
|
||||
const event = new (require(`../events/${file}`).default)(this);
|
||||
this.signale.complete(`Loaded event ${eventName}`);
|
||||
this.on(eventName, (...args) => event.run(...args));
|
||||
delete require.cache[require.resolve(`../events/${file}`)];
|
||||
});
|
||||
|
||||
await mongoose.connect(config.mongoURL, { useNewUrlParser: true, useUnifiedTopology: true });
|
||||
await this.connect();
|
||||
this.on('ready', () => {
|
||||
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]}`);
|
||||
});
|
||||
this.server = new Server(this, { port: this.config.port });
|
||||
// eslint-disable-next-line no-new
|
||||
new CSCLI(this);
|
||||
|
||||
const corepath = '/opt/CloudServices/dist';
|
||||
const cmdFiles = await fs.readdir('/opt/CloudServices/dist/commands');
|
||||
cmdFiles.forEach((f) => delete require.cache[`${corepath}/${f}`]);
|
||||
delete require.cache[`${corepath}/config.json`];
|
||||
delete require.cache[`${corepath}/class/Util`];
|
||||
}
|
||||
}
|
||||
import Eris from 'eris';
|
||||
import Redis from 'ioredis';
|
||||
import mongoose from 'mongoose';
|
||||
import signale from 'signale';
|
||||
import fs from 'fs-extra';
|
||||
import config from '../config.json';
|
||||
import CSCLI from '../cscli/main';
|
||||
import { Account, AccountInterface, Moderation, ModerationInterface, Domain, DomainInterface, Tier, TierInterface } from '../models';
|
||||
import { emojis } from '../stores';
|
||||
import { Command, Util, Collection, Server } from '.';
|
||||
import * as commands from '../commands';
|
||||
|
||||
|
||||
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 util: Util;
|
||||
|
||||
public commands: Collection<Command>;
|
||||
|
||||
public db: { Account: mongoose.Model<AccountInterface>; Domain: mongoose.Model<DomainInterface>; Moderation: mongoose.Model<ModerationInterface>; Tier: mongoose.Model<TierInterface>; };
|
||||
|
||||
public redis: Redis.Redis;
|
||||
|
||||
public stores: { emojis: { success: string, loading: string, error: string }; };
|
||||
|
||||
public functions: Collection<Function>;
|
||||
|
||||
public signale: signale.Signale;
|
||||
|
||||
public server: Server;
|
||||
|
||||
public updating: boolean;
|
||||
|
||||
public buildError: boolean
|
||||
|
||||
constructor() {
|
||||
super(config.token, { getAllUsers: true, restMode: true, defaultImageFormat: 'png' });
|
||||
|
||||
process.title = 'cloudservices';
|
||||
this.config = config;
|
||||
this.util = new Util(this);
|
||||
this.commands = new Collection<Command>();
|
||||
this.functions = new Collection<Function>();
|
||||
this.db = { Account, Domain, Moderation, Tier };
|
||||
this.redis = new Redis();
|
||||
this.stores = { emojis };
|
||||
this.signale = signale;
|
||||
this.signale.config({
|
||||
displayDate: true,
|
||||
displayTimestamp: true,
|
||||
displayFilename: true,
|
||||
});
|
||||
this.updating = false;
|
||||
this.buildError = false;
|
||||
this.events();
|
||||
this.loadFunctions();
|
||||
this.init();
|
||||
}
|
||||
|
||||
private async events() {
|
||||
process.on('unhandledRejection', (error) => {
|
||||
this.signale.error(error);
|
||||
});
|
||||
}
|
||||
|
||||
private async loadFunctions() {
|
||||
const functions = await fs.readdir('../functions');
|
||||
functions.forEach(async (func) => {
|
||||
if (func === 'index.ts' || func === 'index.js') return;
|
||||
try {
|
||||
const funcRequire: Function = require(`../functions/${func}`).default;
|
||||
this.functions.set(func.split('.')[0], funcRequire);
|
||||
} catch (error) {
|
||||
this.signale.error(`Error occured loading ${func}`);
|
||||
await this.util.handleError(error);
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public loadCommand(CommandFile: any) {
|
||||
// eslint-disable-next-line no-useless-catch
|
||||
try {
|
||||
// eslint-disable-next-line
|
||||
const command: Command = new CommandFile(this);
|
||||
if (command.subcmds.length) {
|
||||
command.subcmds.forEach((C) => {
|
||||
const cmd: Command = new C(this);
|
||||
command.subcommands.add(cmd.name, cmd);
|
||||
});
|
||||
}
|
||||
delete command.subcmds;
|
||||
this.commands.add(command.name, command);
|
||||
this.signale.complete(`Loaded command ${command.name}`);
|
||||
} catch (err) { throw err; }
|
||||
}
|
||||
|
||||
public async init() {
|
||||
const evtFiles = await fs.readdir('../events/');
|
||||
Object.values(commands).forEach((c: Function) => this.loadCommand(c));
|
||||
|
||||
evtFiles.forEach((file) => {
|
||||
const eventName = file.split('.')[0];
|
||||
if (file === 'index.js') return;
|
||||
// eslint-disable-next-line
|
||||
const event = new (require(`../events/${file}`).default)(this);
|
||||
this.signale.complete(`Loaded event ${eventName}`);
|
||||
this.on(eventName, (...args) => event.run(...args));
|
||||
delete require.cache[require.resolve(`../events/${file}`)];
|
||||
});
|
||||
|
||||
await mongoose.connect(config.mongoURL, { useNewUrlParser: true, useUnifiedTopology: true });
|
||||
await this.connect();
|
||||
this.on('ready', () => {
|
||||
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]}`);
|
||||
});
|
||||
this.server = new Server(this, { port: this.config.port });
|
||||
// eslint-disable-next-line no-new
|
||||
new CSCLI(this);
|
||||
|
||||
const corepath = '/opt/CloudServices/dist';
|
||||
const cmdFiles = await fs.readdir('/opt/CloudServices/dist/commands');
|
||||
cmdFiles.forEach((f) => delete require.cache[`${corepath}/${f}`]);
|
||||
delete require.cache[`${corepath}/config.json`];
|
||||
delete require.cache[`${corepath}/class/Util`];
|
||||
}
|
||||
}
|
||||
|
|
|
@ -1,85 +1,85 @@
|
|||
/* eslint-disable no-case-declarations */
|
||||
/* eslint-disable consistent-return */
|
||||
import net from 'net';
|
||||
import crypto from 'crypto';
|
||||
import { promises as fs } from 'fs';
|
||||
import Client from '../class/Client';
|
||||
import { dataConversion } from '../functions';
|
||||
|
||||
export default class CSCLI {
|
||||
public client: Client;
|
||||
|
||||
public server: net.Server;
|
||||
|
||||
#hmac: string;
|
||||
|
||||
constructor(client: Client) {
|
||||
this.client = client;
|
||||
this.loadKeys();
|
||||
this.server = net.createServer((socket) => {
|
||||
socket.on('data', async (data) => {
|
||||
try {
|
||||
await this.handle(socket, data);
|
||||
} catch (err) {
|
||||
await this.client.util.handleError(err);
|
||||
socket.destroy();
|
||||
}
|
||||
});
|
||||
});
|
||||
this.init();
|
||||
}
|
||||
|
||||
public async handle(socket: net.Socket, data: Buffer) {
|
||||
const args = data.toString().trim().split('$');
|
||||
const verification = this.verifyConnection(args[1], args[0]);
|
||||
if (!verification) {
|
||||
socket.write('UNAUTHORIZED TO EXECUTE ON THIS SERVER\n');
|
||||
return socket.destroy();
|
||||
}
|
||||
const parsed: { Username: string, Type: string, Message?: string, HMAC: string } = JSON.parse(args[0]);
|
||||
// FINISH VERIFICATION CHECKS
|
||||
switch (parsed.Type) {
|
||||
case 'lock':
|
||||
await this.client.util.accounts.lock(parsed.Username, this.client.user.id, { reason: parsed.Message });
|
||||
break;
|
||||
case 'killpid':
|
||||
await this.client.util.exec(`kill -9 ${parsed.Message}`);
|
||||
break;
|
||||
case 'ram':
|
||||
const memoryConversion = dataConversion(Number(await this.client.util.exec(`memory ${parsed.Username}`)) * 1000);
|
||||
socket.write(`${memoryConversion}\n`);
|
||||
socket.destroy();
|
||||
break;
|
||||
case 'storage':
|
||||
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.destroy();
|
||||
break;
|
||||
default:
|
||||
socket.destroy();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public verifyConnection(key: string, data: any): boolean {
|
||||
const hmac = crypto.createHmac('sha256', this.#hmac);
|
||||
hmac.update(data);
|
||||
const computed = hmac.digest('hex');
|
||||
if (computed === key) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public async loadKeys() {
|
||||
const key = await fs.readFile('/etc/cscli.conf', { encoding: 'utf8' });
|
||||
this.#hmac = key.toString().trim();
|
||||
}
|
||||
|
||||
public init() {
|
||||
this.server.on('error', (err) => {
|
||||
this.client.util.handleError(err);
|
||||
});
|
||||
this.server.listen(8124, () => {
|
||||
this.client.signale.success('TCP socket is now listening for connections.');
|
||||
});
|
||||
}
|
||||
}
|
||||
/* eslint-disable no-case-declarations */
|
||||
/* eslint-disable consistent-return */
|
||||
import net from 'net';
|
||||
import crypto from 'crypto';
|
||||
import { promises as fs } from 'fs';
|
||||
import { Client } from '../class';
|
||||
import { dataConversion } from '../functions';
|
||||
|
||||
export default class CSCLI {
|
||||
public client: Client;
|
||||
|
||||
public server: net.Server;
|
||||
|
||||
#hmac: string;
|
||||
|
||||
constructor(client: Client) {
|
||||
this.client = client;
|
||||
this.loadKeys();
|
||||
this.server = net.createServer((socket) => {
|
||||
socket.on('data', async (data) => {
|
||||
try {
|
||||
await this.handle(socket, data);
|
||||
} catch (err) {
|
||||
await this.client.util.handleError(err);
|
||||
socket.destroy();
|
||||
}
|
||||
});
|
||||
});
|
||||
this.init();
|
||||
}
|
||||
|
||||
public async handle(socket: net.Socket, data: Buffer) {
|
||||
const args = data.toString().trim().split('$');
|
||||
const verification = this.verifyConnection(args[1], args[0]);
|
||||
if (!verification) {
|
||||
socket.write('UNAUTHORIZED TO EXECUTE ON THIS SERVER\n');
|
||||
return socket.destroy();
|
||||
}
|
||||
const parsed: { Username: string, Type: string, Message?: string, HMAC: string } = JSON.parse(args[0]);
|
||||
// FINISH VERIFICATION CHECKS
|
||||
switch (parsed.Type) {
|
||||
case 'lock':
|
||||
await this.client.util.accounts.lock(parsed.Username, this.client.user.id, { reason: parsed.Message });
|
||||
break;
|
||||
case 'killpid':
|
||||
await this.client.util.exec(`kill -9 ${parsed.Message}`);
|
||||
break;
|
||||
case 'ram':
|
||||
const memoryConversion = dataConversion(Number(await this.client.util.exec(`memory ${parsed.Username}`)) * 1000);
|
||||
socket.write(`${memoryConversion}\n`);
|
||||
socket.destroy();
|
||||
break;
|
||||
case 'storage':
|
||||
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.destroy();
|
||||
break;
|
||||
default:
|
||||
socket.destroy();
|
||||
break;
|
||||
}
|
||||
}
|
||||
|
||||
public verifyConnection(key: string, data: any): boolean {
|
||||
const hmac = crypto.createHmac('sha256', this.#hmac);
|
||||
hmac.update(data);
|
||||
const computed = hmac.digest('hex');
|
||||
if (computed === key) return true;
|
||||
return false;
|
||||
}
|
||||
|
||||
public async loadKeys() {
|
||||
const key = await fs.readFile('/etc/cscli.conf', { encoding: 'utf8' });
|
||||
this.#hmac = key.toString().trim();
|
||||
}
|
||||
|
||||
public init() {
|
||||
this.server.on('error', (err) => {
|
||||
this.client.util.handleError(err);
|
||||
});
|
||||
this.server.listen(8124, () => {
|
||||
this.client.signale.success('TCP socket is now listening for connections.');
|
||||
});
|
||||
}
|
||||
}
|
||||
|
|
Loading…
Reference in New Issue