diff options
Diffstat (limited to 'server/src/database')
| -rw-r--r-- | server/src/database/index.ts | 5 | ||||
| -rw-r--r-- | server/src/database/models/DarlingModel.ts | 10 | ||||
| -rw-r--r-- | server/src/database/models/FanArtModel.ts | 12 | ||||
| -rw-r--r-- | server/src/database/models/GoodbyeModel.ts | 12 | ||||
| -rw-r--r-- | server/src/database/models/ReactionGuildModel.ts | 16 | ||||
| -rw-r--r-- | server/src/database/models/ReactionModel.ts | 36 | ||||
| -rw-r--r-- | server/src/database/models/WelcomeModel.ts | 12 | ||||
| -rw-r--r-- | server/src/database/structures/SettingsProvider.ts | 212 | ||||
| -rw-r--r-- | server/src/database/utils/Constants.ts | 8 |
9 files changed, 323 insertions, 0 deletions
diff --git a/server/src/database/index.ts b/server/src/database/index.ts new file mode 100644 index 0000000..dc10553 --- /dev/null +++ b/server/src/database/index.ts @@ -0,0 +1,5 @@ +import ReactionGuildModel from './models/ReactionGuildModel'; +import ReactionModel from './models/ReactionModel'; +import SettingsProvider from './structures/SettingsProvider'; + +export { SettingsProvider };
\ No newline at end of file diff --git a/server/src/database/models/DarlingModel.ts b/server/src/database/models/DarlingModel.ts new file mode 100644 index 0000000..3f98037 --- /dev/null +++ b/server/src/database/models/DarlingModel.ts @@ -0,0 +1,10 @@ +import mongoose from 'mongoose'; +const darlingSchema = new mongoose.Schema({ + _id: mongoose.Schema.Types.ObjectId, + username: String, + userID: String, + guildname: String, + guildID: String, + time: String +}); +export = mongoose.model('Darling', darlingSchema);
\ No newline at end of file diff --git a/server/src/database/models/FanArtModel.ts b/server/src/database/models/FanArtModel.ts new file mode 100644 index 0000000..c2d983e --- /dev/null +++ b/server/src/database/models/FanArtModel.ts @@ -0,0 +1,12 @@ +import mongoose from 'mongoose'; +const fanArtSchema = new mongoose.Schema({ + _id: mongoose.Schema.Types.ObjectId, + username: String, + userID: String, + guildname: String, + guildID: String, + channelname: String, + channelID: String, + time: String +}); +export = mongoose.model('FanArt', fanArtSchema);
\ No newline at end of file diff --git a/server/src/database/models/GoodbyeModel.ts b/server/src/database/models/GoodbyeModel.ts new file mode 100644 index 0000000..04cc7c4 --- /dev/null +++ b/server/src/database/models/GoodbyeModel.ts @@ -0,0 +1,12 @@ +import mongoose from 'mongoose'; +const goodbyeSchema = new mongoose.Schema({ + _id: mongoose.Schema.Types.ObjectId, + username: String, + userID: String, + guildname: String, + guildID: String, + channelname: String, + channelID: String, + time: String +}); +export = mongoose.model('Goodbye', goodbyeSchema);
\ No newline at end of file diff --git a/server/src/database/models/ReactionGuildModel.ts b/server/src/database/models/ReactionGuildModel.ts new file mode 100644 index 0000000..6389b56 --- /dev/null +++ b/server/src/database/models/ReactionGuildModel.ts @@ -0,0 +1,16 @@ +import { Document, Schema, model } from 'mongoose'; + +export interface Guild extends Document { + id: string; + prefix: string; + premium: boolean; + expiresAt: Date; +} + +const Guild: Schema = new Schema({ + id: String, + prefix: String, + premium: Boolean, + expiresAt: Date +}, { strict: false }); +export default model<Guild>('Guild', Guild);
\ No newline at end of file diff --git a/server/src/database/models/ReactionModel.ts b/server/src/database/models/ReactionModel.ts new file mode 100644 index 0000000..509dadd --- /dev/null +++ b/server/src/database/models/ReactionModel.ts @@ -0,0 +1,36 @@ +import { Document, Schema, model } from 'mongoose'; + +export interface Reaction extends Document { + guildID: string; + messageID: string; + channelID: string; + userID: string; + id: string; + emoji: string; + emojiType: string; + roleID: string; + uses: number; + expiresAt?: Date; + type: number; + active: boolean; +} + +const Reaction: Schema = new Schema({ + guildID: String, + messageID: String, + channelID: String, + userID: String, + id: String, + emoji: String, + emojiType: String, + roleID: String, + uses: Number, + expiresAt: Date, + type: Number, + active: { + type: Boolean, + default: true, + }, +}, { strict: false }); + +export default model<Reaction>('Reaction', Reaction); diff --git a/server/src/database/models/WelcomeModel.ts b/server/src/database/models/WelcomeModel.ts new file mode 100644 index 0000000..2a26a6f --- /dev/null +++ b/server/src/database/models/WelcomeModel.ts @@ -0,0 +1,12 @@ +import mongoose from 'mongoose'; +const welcomeSchema = new mongoose.Schema({ + _id: mongoose.Schema.Types.ObjectId, + username: String, + userID: String, + guildname: String, + guildID: String, + channelname: String, + channelID: String, + time: String +}); +export = mongoose.model('Welcome', welcomeSchema);
\ No newline at end of file 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; + } +} diff --git a/server/src/database/utils/Constants.ts b/server/src/database/utils/Constants.ts new file mode 100644 index 0000000..911a28a --- /dev/null +++ b/server/src/database/utils/Constants.ts @@ -0,0 +1,8 @@ +export const MONGO_EVENTS = { + connecting: 'Connecting to MongoDB...', + connected: 'Successfully connected to MongoDB.', + disconnecting: 'Disconnecting from MongoDB...', + disconnected: 'Disconnected from MongoDB...', + close: 'MongoDB connection closed.', + reconnected: 'Successfully reconnected to MongoDB.', +} as { [key: string]: string }; |