-
Notifications
You must be signed in to change notification settings - Fork 43
/
database.js
412 lines (352 loc) · 9.61 KB
/
database.js
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
168
169
170
171
172
173
174
175
176
177
178
179
180
181
182
183
184
185
186
187
188
189
190
191
192
193
194
195
196
197
198
199
200
201
202
203
204
205
206
207
208
209
210
211
212
213
214
215
216
217
218
219
220
221
222
223
224
225
226
227
228
229
230
231
232
233
234
235
236
237
238
239
240
241
242
243
244
245
246
247
248
249
250
251
252
253
254
255
256
257
258
259
260
261
262
263
264
265
266
267
268
269
270
271
272
273
274
275
276
277
278
279
280
281
282
283
284
285
286
287
288
289
290
291
292
293
294
295
296
297
298
299
300
301
302
303
304
305
306
307
308
309
310
311
312
313
314
315
316
317
318
319
320
321
322
323
324
325
326
327
328
329
330
331
332
333
334
335
336
337
338
339
340
341
342
343
344
345
346
347
348
349
350
351
352
353
354
355
356
357
358
359
360
361
362
363
364
365
366
367
368
369
370
371
372
373
374
375
376
377
378
379
380
381
382
383
384
385
386
387
388
389
390
391
392
393
394
395
396
397
398
399
400
401
402
403
404
405
406
407
408
409
410
411
412
import { createRequire } from 'node:module';
import pg from 'pg';
const require = createRequire(import.meta.url);
const {defaultSettings} = require('./util/default.json');
const db = new pg.Client(process.env.PGSSL === 'true' ? {ssl: true} : {});
db.on( 'error', dberror => {
console.log( '- Error while connecting to the database: ' + dberror );
} );
const schema = [`
BEGIN TRANSACTION;
CREATE TABLE versions (
type TEXT PRIMARY KEY
UNIQUE
NOT NULL,
version INTEGER NOT NULL
);
CREATE TABLE patreons (
patreon TEXT PRIMARY KEY
UNIQUE
NOT NULL,
count INTEGER NOT NULL
);
CREATE INDEX idx_patreons_patreon ON patreons (
patreon
);
CREATE TABLE discord (
main TEXT UNIQUE
CHECK (main = guild),
guild TEXT NOT NULL
REFERENCES discord (main) ON DELETE CASCADE,
channel TEXT,
wiki TEXT NOT NULL
DEFAULT '${defaultSettings.wiki}',
lang TEXT NOT NULL
DEFAULT '${defaultSettings.lang}',
role TEXT,
inline INTEGER,
desclength INTEGER,
fieldcount INTEGER,
fieldlength INTEGER,
sectionlength INTEGER,
sectiondesclength INTEGER,
prefix TEXT NOT NULL
DEFAULT '${process.env.prefix}',
whitelist TEXT,
patreon TEXT REFERENCES patreons (patreon) ON DELETE SET NULL,
UNIQUE (
guild,
channel
)
);
CREATE INDEX idx_discord_channel ON discord (
guild,
channel DESC
NULLS LAST
);
CREATE INDEX idx_discord_wiki ON discord (
wiki
);
CREATE INDEX idx_discord_patreon ON discord (
patreon
)
WHERE patreon IS NOT NULL;
CREATE TABLE subprefix (
guild TEXT NOT NULL
REFERENCES discord (main) ON DELETE CASCADE,
prefixchar TEXT NOT NULL,
prefixwiki TEXT NOT NULL,
UNIQUE (
guild,
prefixchar
)
);
CREATE INDEX idx_subprefix_guild ON subprefix (
guild
);
CREATE INDEX idx_subprefix_prefixwiki ON subprefix (
prefixwiki
);
CREATE TABLE verification (
guild TEXT NOT NULL
REFERENCES discord (main) ON DELETE CASCADE,
configid INTEGER NOT NULL,
channel TEXT NOT NULL,
role TEXT NOT NULL,
editcount INTEGER NOT NULL
DEFAULT 0,
postcount INTEGER DEFAULT 0,
usergroup TEXT NOT NULL
DEFAULT 'user',
accountage INTEGER NOT NULL
DEFAULT 0,
rename INTEGER NOT NULL
DEFAULT 0,
UNIQUE (
guild,
configid
)
);
CREATE INDEX idx_verification_config ON verification (
guild,
configid ASC,
channel
);
CREATE TABLE verifynotice (
guild TEXT UNIQUE
NOT NULL
REFERENCES discord (main) ON DELETE CASCADE,
logchannel TEXT,
onsuccess TEXT,
onmatch TEXT,
flags INTEGER NOT NULL
DEFAULT 0
);
CREATE INDEX idx_verifynotice_guild ON verifynotice (
guild
);
CREATE TABLE oauthusers (
userid TEXT NOT NULL,
site TEXT NOT NULL,
token TEXT,
UNIQUE (
userid,
site
)
);
CREATE INDEX idx_oauthusers_userid ON oauthusers (
userid,
site
);
CREATE TABLE rcgcdw (
guild TEXT NOT NULL
REFERENCES discord (main) ON DELETE CASCADE,
configid INTEGER NOT NULL,
webhook TEXT NOT NULL
UNIQUE,
wiki TEXT NOT NULL,
lang TEXT NOT NULL
DEFAULT '${defaultSettings.lang}',
display INTEGER NOT NULL
DEFAULT 1,
buttons TEXT,
rcid INTEGER,
postid TEXT DEFAULT '-1',
UNIQUE (
guild,
configid
)
);
CREATE INDEX idx_rcgcdw_wiki ON rcgcdw (
wiki
);
CREATE INDEX idx_rcgcdw_webhook ON rcgcdw (
webhook
);
CREATE INDEX idx_rcgcdw_config ON rcgcdw (
guild,
configid ASC
);
CREATE TABLE blocklist (
wiki TEXT UNIQUE
NOT NULL,
reason TEXT
);
CREATE INDEX idx_blocklist_wiki ON blocklist (
wiki
);
CREATE TABLE oauthrevert (
userid TEXT NOT NULL,
site TEXT NOT NULL,
access TEXT NOT NULL,
refresh TEXT NOT NULL,
UNIQUE (
userid,
site
)
);
CREATE INDEX idx_oauthrevert_userid ON oauthrevert (
userid,
site
);
INSERT INTO versions(type, version) VALUES ('discord', 9)
ON CONFLICT (type) DO UPDATE SET version = excluded.version;
COMMIT TRANSACTION;
`,`
BEGIN TRANSACTION;
CREATE TABLE verifynotice (
guild TEXT UNIQUE
NOT NULL
REFERENCES discord (main) ON DELETE CASCADE,
logchannel TEXT,
onsuccess TEXT,
onmatch TEXT
);
CREATE INDEX idx_verifynotice_guild ON verifynotice (
guild
);
ALTER DATABASE "${process.env.PGDATABASE}" SET my.version TO 2;
COMMIT TRANSACTION;
`,`
BEGIN TRANSACTION;
ALTER TABLE verifynotice
ADD COLUMN flags INTEGER NOT NULL DEFAULT 0;
ALTER DATABASE "${process.env.PGDATABASE}" SET my.version TO 3;
COMMIT TRANSACTION;
`,`
BEGIN TRANSACTION;
CREATE TABLE oauthusers (
userid TEXT NOT NULL,
site TEXT NOT NULL,
token TEXT,
UNIQUE (
userid,
site
)
);
CREATE INDEX idx_oauthusers_userid ON oauthusers (
userid,
site
);
ALTER DATABASE "${process.env.PGDATABASE}" SET my.version TO 4;
COMMIT TRANSACTION;
`,`
BEGIN TRANSACTION;
CREATE TABLE versions (
type TEXT PRIMARY KEY
UNIQUE
NOT NULL,
version INTEGER NOT NULL
);
DROP INDEX idx_discord_voice;
ALTER TABLE discord
DROP COLUMN voice;
INSERT INTO versions(type, version) VALUES ('discord', 5)
ON CONFLICT (type) DO UPDATE SET version = excluded.version;
COMMIT TRANSACTION;
`,`
BEGIN TRANSACTION;
CREATE TABLE subprefix (
guild TEXT NOT NULL
REFERENCES discord (main) ON DELETE CASCADE,
prefixchar TEXT NOT NULL,
prefixwiki TEXT NOT NULL,
UNIQUE (
guild,
prefixchar
)
);
CREATE INDEX idx_subprefix_guild ON subprefix (
guild
);
CREATE INDEX idx_subprefix_prefixwiki ON subprefix (
prefixwiki
);
INSERT INTO versions(type, version) VALUES ('discord', 6)
ON CONFLICT (type) DO UPDATE SET version = excluded.version;
COMMIT TRANSACTION;
`,`
BEGIN TRANSACTION;
ALTER TABLE discord
ADD COLUMN desclength INTEGER,
ADD COLUMN fieldcount INTEGER,
ADD COLUMN fieldlength INTEGER,
ADD COLUMN sectionlength INTEGER,
ADD COLUMN sectiondesclength INTEGER;
INSERT INTO versions(type, version) VALUES ('discord', 7)
ON CONFLICT (type) DO UPDATE SET version = excluded.version;
COMMIT TRANSACTION;
`,`
BEGIN TRANSACTION;
ALTER TABLE discord
ADD COLUMN whitelist TEXT;
INSERT INTO versions(type, version) VALUES ('discord', 8)
ON CONFLICT (type) DO UPDATE SET version = excluded.version;
COMMIT TRANSACTION;
`,`
BEGIN TRANSACTION;
CREATE TABLE oauthrevert (
userid TEXT NOT NULL,
site TEXT NOT NULL,
access TEXT NOT NULL,
refresh TEXT NOT NULL,
UNIQUE (
userid,
site
)
);
CREATE INDEX idx_oauthrevert_userid ON oauthrevert (
userid,
site
);
ALTER TABLE rcgcdw
ADD COLUMN buttons TEXT;
INSERT INTO versions(type, version) VALUES ('discord', 9)
ON CONFLICT (type) DO UPDATE SET version = excluded.version;
COMMIT TRANSACTION;
`];
export default await db.connect().then( () => {
return db.query( 'SELECT version FROM versions WHERE type = $1', ['discord'] ).then( result => {
if ( result.rows.length ) return result;
return db.query( 'SELECT CURRENT_SETTING($1, $2) AS version', ['my.version', true] );
}, dberror => {
if ( dberror?.code !== '42P01' ) return Promise.reject(dberror);
return db.query( 'SELECT CURRENT_SETTING($1, $2) AS version', ['my.version', true] );
} ).then( ({rows:[row]}) => {
if ( row.version === null ) {
if ( process.env.READONLY ) return Promise.reject();
return db.query( schema[0] ).then( () => {
console.log( '- The database has been updated to: v' + schema.length );
}, dberror => {
console.log( '- Error while updating the database: ' + dberror );
return Promise.reject();
} );
}
row.version = parseInt(row.version, 10);
if ( isNaN(row.version) || row.version > schema.length ) {
console.log( '- Invalid database version: v' + row.version );
return Promise.reject();
}
if ( row.version === schema.length ) {
console.log( '- The database is up to date: v' + row.version );
return;
}
console.log( '- The database is outdated: v' + row.version );
if ( process.env.READONLY ) return Promise.reject();
return db.query( schema.filter( (sql, version) => {
if ( row.version === 0 ) return ( version === 0 );
return ( row.version <= version );
} ).join('\n') ).then( () => {
console.log( '- The database has been updated to: v' + schema.length );
}, dberror => {
console.log( '- Error while updating the database: ' + dberror );
return Promise.reject();
} );
}, dberror => {
console.log( '- Error while getting the database version: ' + dberror );
return Promise.reject();
} );
}, dberror => {
console.log( '- Error while connecting to the database: ' + dberror );
return Promise.reject();
} ).then( () => {
return db;
}, () => {
return db.end().then( () => {
console.log( '- Closed the database connection.' );
}, dberror => {
console.log( '- Error while closing the database connection: ' + dberror );
} ).then( () => {
process.exit(1);
} );
} );