diff options
| author | 8cy <[email protected]> | 2020-07-23 23:24:17 -0700 |
|---|---|---|
| committer | 8cy <[email protected]> | 2020-07-23 23:24:17 -0700 |
| commit | bb511abc03bb66848947e37a999502b813c77269 (patch) | |
| tree | 612c010fc8317e1cdf11471a18aad0270819d33e /server/src/database/structures | |
| parent | fix: if clear amount equal or over 100, round down to 99 (diff) | |
| download | dep-core-bb511abc03bb66848947e37a999502b813c77269.tar.xz dep-core-bb511abc03bb66848947e37a999502b813c77269.zip | |
goodbye old uwufier :cry:
Diffstat (limited to 'server/src/database/structures')
| -rw-r--r-- | server/src/database/structures/SettingsProvider.ts | 212 |
1 files changed, 212 insertions, 0 deletions
diff --git a/server/src/database/structures/SettingsProvider.ts b/server/src/database/structures/SettingsProvider.ts new file mode 100644 index 0000000..0a2325a --- /dev/null +++ b/server/src/database/structures/SettingsProvider.ts @@ -0,0 +1,212 @@ +import { Collection } from 'discord.js'; +import { connect, Model, connection, Connection } from 'mongoose'; +import { Logger } from 'winston'; +import ReactionModel, { Reaction } from '../models/ReactionModel'; +import GuildModel, { Guild } from '../models/ReactionGuildModel'; +import { MONGO_EVENTS } from '../utils/Constants' +import BotClient from '../../client/BotClient'; +import { mongoDBUri } from '../../Config'; + +let i = 0; + +/** + * The key, model and cached collection of a database model. + * @interface + */ +interface Combo { + key: string; + model: Model<any>; + cache: Collection<string, any>; +} + +/** + * The Settings Provider that handles all database reads and rights. + * @private + */ +export default class SettingsProvider { + protected readonly client: BotClient; + + protected readonly guilds: Collection<string, Guild> = new Collection(); + protected readonly reactions: Collection<string, Reaction> = new Collection(); + + protected readonly GuildModel = GuildModel; + protected readonly ReactionModel = ReactionModel; + + /** + * + * @param {GiveawayClient} client - The extended Akairo Client + */ + public constructor(client: BotClient) { + this.client = client; + } + + /** + * Retuns all the collection caches. + * @returns {Object} + */ + public get cache() { + return { + guilds: this.guilds, + reactions: this.reactions, + }; + } + + /** + * Returns the database combos + * @returns {Combo[]} + */ + public get combos(): Combo[] { + return [ + { + key: 'guild', + model: this.GuildModel, + cache: this.guilds, + }, + { + key: 'reaction', + model: this.ReactionModel, + cache: this.reactions, + }, + ]; + } + + /** + * Creates a new database document with the provided collection name and data. + * @param {string} type - The collection name + * @param {object} data - The data for the new document + * @returns {Docuement} + */ + public async new(type: 'guild', data: Partial<Guild>): Promise<Guild>; + public async new(type: 'reaction', data: Partial<Reaction>): Promise<Reaction>; + public async new(type: string, data: object): Promise<object> { + const combo = this.combos.find(c => c.key === type); + if (combo) { + const document = new combo.model(data); + await document.save(); + this.client.logger.data(`[DATABASE] Made new ${combo.model.modelName} document with ID of ${document._id}.`); + combo.cache.set(document.id, document); + return document; + } + throw Error(`"${type}" is not a valid model key.`); + } + + /** + * Updates the a database document's data. + * @param {Types} type - The collection name + * @param {object} key - The search paramaters for the document + * @param {object} data - The data you wish to overwrite in the update + * @returns {Promise<Faction | Guild | null>} + */ + public async set(type: 'guild', key: Partial<Guild>, data: Partial<Guild>): Promise<Guild | null>; + public async set(type: 'reaction', key: Partial<Reaction>, data: Partial<Reaction>): Promise<Reaction | null>; + public async set(type: string, key: object, data: object): Promise<object | null> { + const combo = this.combos.find(c => c.key === type); + if (combo) { + const document = await combo.model.findOneAndUpdate(key, { $set: data }, { new: true }); + if (document) { + this.client.logger.verbose(`[DATABASE] Edited ${combo.model.modelName} document with ID of ${document._id}.`); + combo.cache.set(document.id, document); + return document; + } + return null; + } + throw Error(`"${type}" is not a valid model key.`); + } + + /** + * Removes a database document. + * @param {Types} type - The collection name + * @param {object} data - The search paramaters for the document + * @returns {Promise<Faction | Guild | null>>} The document that was removed, if any. + */ + public async remove(type: 'guild', data: Partial<Guild>): Promise<Guild | null>; + public async remove(type: 'user', data: Partial<Reaction>): Promise<Reaction | null>; + public async remove(type: string, data: object): Promise<object | null> { + const combo = this.combos.find(c => c.key === type); + if (combo) { + const document = await combo.model.findOneAndRemove(data); + if (document) { + this.client.logger.verbose(`[DATABASE] Edited ${combo.model.modelName} document with ID of ${document._id}.`); + combo.cache.delete(document.id); + return document; + } + return null; + } + throw Error(`"${type}" is not a valid model key.`); + } + + /** + * Caching all database documents. + * @returns {number} The amount of documents cached total. + * @private + */ + private async _cacheAll(): Promise<number> { + for (const combo of this.combos) await this._cache(combo); + return i; + } + + /** + * Caching each collection's documents. + * @param {Combo} combo - The combo name + * @returns {number} The amount of documents cached from that collection. + * @private + */ + private async _cache(combo: Combo): Promise<any> { + const items = await combo.model.find(); + for (const i of items) combo.cache.set(i.id, i); + this.client.logger.verbose( + `[DATABASE]: Cached ${items.length.toLocaleString('en-US')} items from ${combo.model.modelName}.`, + ); + return (i += items.length); + } + + /** + * Connect to the database + * @param {string} url - the mongodb uri + * @returns {Promise<number | Logger>} Returns a + */ + private async _connect(url: string | undefined): Promise<Logger | number> { + if (url) { + const start = Date.now(); + try { + await connect(url, { + useCreateIndex: true, + useNewUrlParser: true, + useFindAndModify: false, + useUnifiedTopology: true, + }); + } catch (err) { + this.client.logger.error(`[DATABASE] Error when connecting to MongoDB:\n${err.stack}`); + process.exit(1); + } + return this.client.logger.verbose(`[DATABASE] Connected to MongoDB in ${Date.now() - start}ms.`); + } + this.client.logger.error('[DATABASE] No MongoDB url provided!'); + return process.exit(1); + } + + /** + * Adds all the listeners to the mongo connection. + * @param connection - The mongoose connection + * @returns {void} + * @private + */ + private _addListeners(connection: Connection): void { + for (const [event, msg] of Object.entries(MONGO_EVENTS)) { + connection.on(event, () => this.client.logger.data(`[DATABASE]: ${msg}`)); + } + } + + /** + * Starts the Settings Provider + * @returns {SettingsProvider} + */ + public async init(): Promise<this> { + this._addListeners(connection); + await this._connect(mongoDBUri); + this.client.logger.verbose(`[DATABASE]: Now caching ${this.combos.length} schema documents.`); + await this._cacheAll(); + this.client.logger.info(`[DATABASE] [LAUNCHED] Successfully connected and cached ${i} documents.`); + return this; + } +} |