import Stripe from 'stripe'; import Redis from 'ioredis'; import eris from 'eris'; import pluris from 'pluris'; import mongoose from 'mongoose'; import { promises as fs } from 'fs'; import Database from 'cr-db'; import * as Sentry from '@sentry/node'; import * as Tracing from '@sentry/tracing'; import { Collection, Command, InteractionCommand, LocalStorage, Queue, Util, ServerManagement, Event } from '.'; import { Config } from '../../types'; // eslint-disable-line // @ts-ignore pluris(eris, { endpoints: false }); export default class Client extends eris.Client { public config: Config; public commands: Collection; public interactions: Collection; public events: Collection; // eslint-disable-next-line no-undef public intervals: Collection; public util: Util; public serverManagement: ServerManagement; public queue: Queue; public stripe: Stripe; public db: { mongo: typeof Database.MongoDBModels, maria: null, redis: Redis.Redis, local: { muted: LocalStorage }, }; constructor(token: string, options?: eris.ClientOptions) { super(token, options); this.setupSentry(); this.commands = new Collection(); this.interactions = new Collection(); this.events = new Collection(); // eslint-disable-next-line no-undef this.intervals = new Collection(); this.queue = new Queue(this); this.db = { mongo: Database.MongoDBModels, redis: new Redis(), local: { muted: new LocalStorage('muted'), }, maria: null, }; } get report() { return this.util.report; } get pbx() { return this.util.pbx; } public setupSentry() { Sentry.init({ dsn: 'https://323f6626a7104be7859088750b91abe1@sentry.libraryofcode.org/2', tracesSampleRate: 0.25, integrations: [ new Sentry.Integrations.Http({ tracing: true }), ], }); Tracing.addExtensionMethods(); } public async loadDatabase() { mongoose.connect(this.config.mongoDB, { minPoolSize: 50, }); const statMessages = await this.db.mongo.Stat.findOne({ name: 'messages' }); const statCommands = await this.db.mongo.Stat.findOne({ name: 'commands' }); const statPages = await this.db.mongo.Stat.findOne({ name: 'pages' }); const statRequests = await this.db.mongo.Stat.findOne({ name: 'requests' }); if (!statMessages) { await (new this.db.mongo.Stat({ name: 'messages', value: 0 }).save()); } if (!statCommands) { await (new this.db.mongo.Stat({ name: 'commands', value: 0 }).save()); } if (!statPages) { await (new this.db.mongo.Stat({ name: 'pages', value: 0 }).save()); } if (!statRequests) { await (new this.db.mongo.Stat({ name: 'requests', value: 0 }).save()); } } public loadPlugins() { this.util = new Util(this); this.serverManagement = new ServerManagement(this); this.stripe = new Stripe(this.config.stripeKey, { apiVersion: null, typescript: true }); } public async loadIntervals() { const intervalFiles = await fs.readdir(`${__dirname}/../intervals`); intervalFiles.forEach((file) => { const intervalName = file.split('.')[0]; if (file === 'index.js') return; // eslint-disable-next-line no-undef const interval: NodeJS.Timeout = (require(`${__dirname}/../intervals/${file}`).default)(this); this.intervals.add(intervalName, interval); this.util.signale.success(`Successfully loaded interval: ${intervalName}`); }); } public async loadEvents(eventFiles: { [s: string]: typeof Event; } | ArrayLike) { const evtFiles = Object.entries(eventFiles); for (const [name, Ev] of evtFiles) { const event = new Ev(this); this.events.add(event.event, event); this.on(event.event, event.run); this.util.signale.success(`Successfully loaded event: ${name}`); delete require.cache[require.resolve(`${__dirname}/../events/${name}`)]; } } public async loadCommands(commandFiles: { [s: string]: typeof Command; } | ArrayLike) { const cmdFiles = Object.values(commandFiles); for (const Cmd of cmdFiles) { const command = new Cmd(this); if (command.subcmds.length) { command.subcmds.forEach((C) => { const cmd: Command = new C(this); command.subcommands.add(cmd.name, cmd); this.util.signale.success(`Successfully loaded subcommand ${cmd.name} under ${command.name}`); }); } delete command.subcmds; this.commands.add(command.name, command); this.util.signale.success(`Successfully loaded command: ${command.name}`); } } public async loadInteractions(interactionFiles: { [s: string]: typeof InteractionCommand; } | ArrayLike) { const intFiles = Object.values(interactionFiles); for (const Int of intFiles) { const interaction = new Int(this); // eslint-disable-next-line no-await-in-loop const c = await this.createGuildCommand(this.config.guildID, interaction.serializeData()); this.interactions.add(c.id, interaction); this.util.signale.success(`Successfully loaded interaction: ${interaction.name}`); } } }