blob: 4e37652267272a9a969687af09fc4965841f12db [file] [log] [blame]
pineafan6fb3e072022-05-20 19:27:23 +01001import { Collection, Db, MongoClient } from 'mongodb';
pineafan6702cef2022-06-13 17:52:37 +01002import structuredClone from '@ungap/structured-clone';
pineafan6fb3e072022-05-20 19:27:23 +01003
4
5export const Entry = data => {
6 data = data ?? {};
pineafan6702cef2022-06-13 17:52:37 +01007 data.getKey = key => data[key]
pineafan6fb3e072022-05-20 19:27:23 +01008 return {
9 get(target, prop, receiver) {
10 let dataToReturn = data[prop]
11 if (dataToReturn === null ) return Reflect.get(target, prop, receiver);
12 if (typeof dataToReturn === "object" && !Array.isArray(dataToReturn)) dataToReturn = new Proxy(
13 Reflect.get(target, prop, receiver),
14 Entry(dataToReturn),
15 )
16 return dataToReturn ?? Reflect.get(target, prop, receiver);
17 }
18 }
19}
20
21
22export default class Database {
23 mongoClient: MongoClient;
24 database: Db;
25 guilds: Collection<GuildConfig>;
26 defaultData: GuildConfig;
27
28 constructor(url) {
29 this.mongoClient = new MongoClient(url);
30 }
31
32 async connect() {
33 await this.mongoClient.connect()
34 this.database = this.mongoClient.db("Nucleus");
35 this.guilds = this.database.collection<GuildConfig>("guilds");
36 await this.guilds.createIndex({ id: "text" }, { unique: true });
37 this.defaultData = (await import("../config/default.json", { assert: { type: "json" }})).default as unknown as GuildConfig;
38 return this;
39 }
40
41 async read(guild: string) {
42 let entry = await this.guilds.findOne({ id: guild });
pineafan6702cef2022-06-13 17:52:37 +010043 return new Proxy(structuredClone(this.defaultData), Entry(entry)) as unknown as GuildConfig
pineafan6fb3e072022-05-20 19:27:23 +010044 }
45
pineafan6702cef2022-06-13 17:52:37 +010046 async write(guild: string, set: object = {}, unset: string[] = []) {
47 let uo = {}
48 for (let key of unset) {
49 uo[key] = "";
50 }
51 await this.guilds.updateOne({ id: guild }, {
52 $unset: uo,
53 $set: set
54 }, { upsert: true });
55 }
56
57 async append(guild: string, key: string, value: any) {
58 if (Array.isArray(value)) {
59 await this.guilds.updateOne({ id: guild }, {
60 $addToSet: { [key]: { $each: value } }
61 }, { upsert: true });
62 } else {
63 await this.guilds.updateOne({ id: guild }, {
64 $addToSet: { [key]: value }
65 }, { upsert: true });
66 }
67 }
68
69 async remove(guild: string, key: string, value: any) {
70 if (Array.isArray(value)) {
71 await this.guilds.updateOne({ id: guild }, {
72 $pullAll: { [key]: value }
73 }, { upsert: true });
74 } else {
75 await this.guilds.updateOne({ id: guild }, {
76 $pullAll: { [key]: [value] }
77 }, { upsert: true });
78 }
pineafan6fb3e072022-05-20 19:27:23 +010079 }
80}
81
82export interface GuildConfig {
83 id: string,
84 version: number,
85 singleEventNotifications: {
86 statsChannelDeleted: boolean
87 }
88 filters: {
89 images: {
90 NSFW: boolean,
91 size: boolean
92 },
93 malware: boolean,
94 wordFilter: {
95 enabled: boolean,
96 words: {
97 strict: string[],
98 loose: string[]
99 },
100 allowed: {
101 users: string[],
102 roles: string[],
103 channels: string[]
104 }
105 },
106 invite: {
107 enabled: boolean,
108 allowed: {
109 users: string[],
110 channels: string[],
111 roles: string[]
112 }
113 },
114 pings: {
115 mass: number,
116 everyone: boolean,
117 roles: boolean,
118 allowed: {
119 roles: string[],
120 rolesToMention: string[],
121 users: string[],
122 channels: string[]
123 }
124 }
125 }
126 welcome: {
127 enabled: boolean,
128 verificationRequired: {
129 message: boolean,
pineafan6702cef2022-06-13 17:52:37 +0100130 role: string | null
pineafan6fb3e072022-05-20 19:27:23 +0100131 },
pineafan6702cef2022-06-13 17:52:37 +0100132 welcomeRole: string | null,
133 channel: string | null,
134 message: string | null,
pineafan6fb3e072022-05-20 19:27:23 +0100135 }
136 stats: {
137 enabled: boolean,
pineafan6702cef2022-06-13 17:52:37 +0100138 channel: string | null,
139 text: string | null,
pineafan6fb3e072022-05-20 19:27:23 +0100140 }[]
141 logging: {
142 logs: {
143 enabled: boolean,
pineafan6702cef2022-06-13 17:52:37 +0100144 channel: string | null,
145 toLog: string | null,
pineafan6fb3e072022-05-20 19:27:23 +0100146 },
147 staff: {
pineafan6702cef2022-06-13 17:52:37 +0100148 channel: string | null,
pineafan6fb3e072022-05-20 19:27:23 +0100149 }
150 }
151 verify: {
152 enabled: boolean,
pineafan6702cef2022-06-13 17:52:37 +0100153 role: string | null,
pineafan6fb3e072022-05-20 19:27:23 +0100154 }
155 tickets: {
156 enabled: boolean,
pineafan6702cef2022-06-13 17:52:37 +0100157 category: string | null,
158 types: string | null,
pineafan6fb3e072022-05-20 19:27:23 +0100159 customTypes: string[],
pineafan6702cef2022-06-13 17:52:37 +0100160 useCustom: boolean,
161 supportRole: string | null,
pineafan6fb3e072022-05-20 19:27:23 +0100162 maxTickets: number
163 }
164 moderation: {
165 mute: {
166 timeout: boolean,
pineafan6702cef2022-06-13 17:52:37 +0100167 role: string | null,
168 text: string | null,
169 link: string | null
pineafan6fb3e072022-05-20 19:27:23 +0100170 },
171 kick: {
pineafan6702cef2022-06-13 17:52:37 +0100172 text: string | null,
173 link: string | null
pineafan6fb3e072022-05-20 19:27:23 +0100174 },
175 ban: {
pineafan6702cef2022-06-13 17:52:37 +0100176 text: string | null,
177 link: string | null
pineafan6fb3e072022-05-20 19:27:23 +0100178 },
179 softban: {
pineafan6702cef2022-06-13 17:52:37 +0100180 text: string | null,
181 link: string | null
pineafan6fb3e072022-05-20 19:27:23 +0100182 },
183 warn: {
pineafan6702cef2022-06-13 17:52:37 +0100184 text: string | null,
185 link: string | null
pineafan6fb3e072022-05-20 19:27:23 +0100186 },
187 role: {
pineafan6702cef2022-06-13 17:52:37 +0100188 role: string | null,
pineafan6fb3e072022-05-20 19:27:23 +0100189 }
190 }
191 tracks: {
192 name: string,
193 retainPrevious: boolean,
194 nullable: boolean,
195 track: string[],
196 manageableBy: string[]
197 }[]
198 roleMenu: {
199 enabled: boolean,
200 allowWebUI: boolean,
201 options: {
202 name: string,
203 description: string,
204 min: number,
205 max: number,
206 options: {
207 name: string,
208 description: string,
209 role: string
210 }[]
211 }[]
212 }
213 tags: {}
214};