|
|
|
|
import { Collection, Db, MongoClient } from 'mongodb';
|
|
|
|
|
import structuredClone from '@ungap/structured-clone';
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export const Entry = data => {
|
|
|
|
|
data = data ?? {};
|
|
|
|
|
data.getKey = key => data[key]
|
|
|
|
|
return {
|
|
|
|
|
get(target, prop, receiver) {
|
|
|
|
|
let dataToReturn = data[prop]
|
|
|
|
|
if (dataToReturn === null ) return Reflect.get(target, prop, receiver);
|
|
|
|
|
if (typeof dataToReturn === "object" && !Array.isArray(dataToReturn)) dataToReturn = new Proxy(
|
|
|
|
|
Reflect.get(target, prop, receiver),
|
|
|
|
|
Entry(dataToReturn),
|
|
|
|
|
)
|
|
|
|
|
return dataToReturn ?? Reflect.get(target, prop, receiver);
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
|
|
|
|
|
export default class Database {
|
|
|
|
|
mongoClient: MongoClient;
|
|
|
|
|
database: Db;
|
|
|
|
|
guilds: Collection<GuildConfig>;
|
|
|
|
|
defaultData: GuildConfig;
|
|
|
|
|
|
|
|
|
|
constructor(url) {
|
|
|
|
|
this.mongoClient = new MongoClient(url);
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async connect() {
|
|
|
|
|
await this.mongoClient.connect()
|
|
|
|
|
this.database = this.mongoClient.db("Nucleus");
|
|
|
|
|
this.guilds = this.database.collection<GuildConfig>("guilds");
|
|
|
|
|
await this.guilds.createIndex({ id: "text" }, { unique: true });
|
|
|
|
|
this.defaultData = (await import("../config/default.json", { assert: { type: "json" }})).default as unknown as GuildConfig;
|
|
|
|
|
return this;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async read(guild: string) {
|
|
|
|
|
let entry = await this.guilds.findOne({ id: guild });
|
|
|
|
|
return new Proxy(structuredClone(this.defaultData), Entry(entry)) as unknown as GuildConfig
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
async write(guild: string, set: object = {}, unset: string[] = []) {
|
|
|
|
|
let uo = {}
|
|
|
|
|
for (let key of unset) {
|
|
|
|
|
uo[key] = "";
|
|
|
|
|
}
|
|
|
|
|
await this.guilds.updateOne({ id: guild }, {
|
|
|
|
|
$unset: uo,
|
|
|
|
|
$set: set
|
|
|
|
|
}, { upsert: true });
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
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, value: any) {
|
|
|
|
|
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 });
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
export interface GuildConfig {
|
|
|
|
|
id: string,
|
|
|
|
|
version: number,
|
|
|
|
|
singleEventNotifications: {
|
|
|
|
|
statsChannelDeleted: boolean
|
|
|
|
|
}
|
|
|
|
|
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: {
|
|
|
|
|
users: string[],
|
|
|
|
|
channels: string[],
|
|
|
|
|
roles: string[]
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
pings: {
|
|
|
|
|
mass: number,
|
|
|
|
|
everyone: boolean,
|
|
|
|
|
roles: boolean,
|
|
|
|
|
allowed: {
|
|
|
|
|
roles: string[],
|
|
|
|
|
rolesToMention: string[],
|
|
|
|
|
users: string[],
|
|
|
|
|
channels: string[]
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
welcome: {
|
|
|
|
|
enabled: boolean,
|
|
|
|
|
verificationRequired: {
|
|
|
|
|
message: boolean,
|
|
|
|
|
role: string | null
|
|
|
|
|
},
|
|
|
|
|
welcomeRole: string | null,
|
|
|
|
|
channel: string | null,
|
|
|
|
|
message: string | null,
|
|
|
|
|
}
|
|
|
|
|
stats: {
|
|
|
|
|
enabled: boolean,
|
|
|
|
|
channel: string | null,
|
|
|
|
|
text: string | null,
|
|
|
|
|
}[]
|
|
|
|
|
logging: {
|
|
|
|
|
logs: {
|
|
|
|
|
enabled: boolean,
|
|
|
|
|
channel: string | null,
|
|
|
|
|
toLog: string | null,
|
|
|
|
|
},
|
|
|
|
|
staff: {
|
|
|
|
|
channel: string | null,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
verify: {
|
|
|
|
|
enabled: boolean,
|
|
|
|
|
role: string | null,
|
|
|
|
|
}
|
|
|
|
|
tickets: {
|
|
|
|
|
enabled: boolean,
|
|
|
|
|
category: string | null,
|
|
|
|
|
types: string | null,
|
|
|
|
|
customTypes: string[],
|
|
|
|
|
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,
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
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,
|
|
|
|
|
role: string
|
|
|
|
|
}[]
|
|
|
|
|
}[]
|
|
|
|
|
}
|
|
|
|
|
tags: {}
|
|
|
|
|
};
|