import type Discord from "discord.js"; import { Collection, MongoClient } from "mongodb"; import config from "../config/main.json" assert { type: "json" }; const mongoClient = new MongoClient(config.mongoUrl); await mongoClient.connect(); const database = mongoClient.db("Nucleus"); export class Guilds { guilds: Collection; defaultData: GuildConfig | null; constructor() { this.guilds = database.collection("guilds"); this.defaultData = null; } async setup(): Promise { this.defaultData = (await import("../config/default.json", { assert: { type: "json" } })) .default as unknown as GuildConfig; return this; } async read(guild: string): Promise { const entry = await this.guilds.findOne({ id: guild }); return Object.assign({}, this.defaultData, entry); } async write(guild: string, set: object | null, unset: string[] | string = []) { // eslint-disable-next-line @typescript-eslint/no-explicit-any const uo: Record = {}; if (!Array.isArray(unset)) unset = [unset]; for (const key of unset) { uo[key] = null; } const out = { $set: {}, $unset: {} }; if (set) out.$set = set; if (unset.length) out.$unset = uo; await this.guilds.updateOne({ id: guild }, out, { upsert: true }); } // eslint-disable-next-line @typescript-eslint/no-explicit-any async append(guild: string, key: string, value: any) { if (Array.isArray(value)) { await this.guilds.updateOne( { id: guild }, { $addToSet: { [key]: { $each: value } } }, { upsert: true } ); } else { await this.guilds.updateOne( { id: guild }, { $addToSet: { [key]: value } }, { upsert: true } ); } } async remove( guild: string, key: string, // eslint-disable-next-line @typescript-eslint/no-explicit-any value: any, innerKey?: string | null ) { console.log(Array.isArray(value)); if (innerKey) { await this.guilds.updateOne( { id: guild }, { $pull: { [key]: { [innerKey]: { $eq: value } } } }, { upsert: true } ); } else if (Array.isArray(value)) { await this.guilds.updateOne( { id: guild }, { $pullAll: { [key]: value } }, { upsert: true } ); } else { await this.guilds.updateOne( { id: guild }, { $pullAll: { [key]: [value] } }, { upsert: true } ); } } async delete(guild: string) { await this.guilds.deleteOne({ id: guild }); } } export class History { histories: Collection; constructor() { this.histories = database.collection("history"); } async create( type: string, guild: string, user: Discord.User, moderator: Discord.User | null, reason: string | null, before?: string | null, after?: string | null, amount?: string | null ) { await this.histories.insertOne({ type: type, guild: guild, user: user.id, moderator: moderator ? moderator.id : null, reason: reason, occurredAt: new Date(), before: before ?? null, after: after ?? null, amount: amount ?? null }); } async read(guild: string, user: string, year: number) { const entry = (await this.histories .find({ guild: guild, user: user, occurredAt: { $gte: new Date(year - 1, 11, 31, 23, 59, 59), $lt: new Date(year + 1, 0, 1, 0, 0, 0) } }) .toArray()) as HistorySchema[]; return entry; } async delete(guild: string) { await this.histories.deleteMany({ guild: guild }); } } export class PerformanceTest { performanceData: Collection; constructor() { this.performanceData = database.collection("performance"); } async record(data: PerformanceDataSchema) { data.timestamp = new Date(); await this.performanceData.insertOne(data); } async read() { return await this.performanceData.find({}).toArray(); } } export interface PerformanceDataSchema { timestamp?: Date; discord: number; databaseRead: number; resources: { cpu: number; memory: number; temperature: number; } } export class ModNotes { modNotes: Collection; constructor() { this.modNotes = database.collection("modNotes"); } async create(guild: string, user: string, note: string | null) { await this.modNotes.updateOne({ guild: guild, user: user }, { $set: { note: note } }, { upsert: true }); } async read(guild: string, user: string) { const entry = await this.modNotes.findOne({ guild: guild, user: user }); return entry?.note ?? null; } } export class Premium { premium: Collection; constructor() { this.premium = database.collection("premium"); } async hasPremium(guild: string) { const entry = await this.premium.findOne({ appliesTo: { $in: [guild] } }); return entry !== null; } } export interface GuildConfig { id: string; version: number; singleEventNotifications: Record; filters: { images: { NSFW: boolean; size: boolean; }; malware: boolean; wordFilter: { enabled: boolean; words: { strict: string[]; loose: string[]; }; allowed: { users: string[]; roles: string[]; channels: string[]; }; }; invite: { enabled: boolean; allowed: { channels: string[]; roles: string[]; users: string[]; }; }; pings: { mass: number; everyone: boolean; roles: boolean; allowed: { roles: string[]; rolesToMention: string[]; users: string[]; channels: string[]; }; }; }; welcome: { enabled: boolean; role: string | null; ping: string | null; channel: string | null; message: string | null; }; stats: Record; logging: { logs: { enabled: boolean; channel: string | null; toLog: string; }; staff: { channel: string | null; }; attachments: { channel: string | null; saved: Record; }; }; verify: { enabled: boolean; role: string | null; }; tickets: { enabled: boolean; category: string | null; types: string; customTypes: string[] | null; useCustom: boolean; supportRole: string | null; maxTickets: number; }; moderation: { mute: { timeout: boolean; role: string | null; text: string | null; link: string | null; }; kick: { text: string | null; link: string | null; }; ban: { text: string | null; link: string | null; }; softban: { text: string | null; link: string | null; }; warn: { text: string | null; link: string | null; }; role: { role: string | null; text: null; link: null; }; }; tracks: { name: string; retainPrevious: boolean; nullable: boolean; track: string[]; manageableBy: string[]; }[]; roleMenu: { enabled: boolean; allowWebUI: boolean; options: { name: string; description: string; min: number; max: number; options: { name: string; description: string | null; role: string; }[]; }[]; }; tags: Record; } export interface HistorySchema { type: string; guild: string; user: string; moderator: string | null; reason: string | null; occurredAt: Date; before: string | null; after: string | null; amount: string | null; } export interface ModNoteSchema { guild: string; user: string; note: string | null; } export interface PremiumSchema { user: string; level: number; expires: Date; appliesTo: string[]; }