Skip to content

Commit a59cd45

Browse files
Refactor database stuff
1 parent 2150a6c commit a59cd45

33 files changed

+383
-379
lines changed

src/components/moderation/ban.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -126,7 +126,7 @@ export default class Ban extends ModerationComponent {
126126
return true;
127127
} catch (e) {
128128
// fallback to the database
129-
const res = await this.wheatley.database.moderations.findOne({
129+
const res = await this.database.moderations.findOne({
130130
user: moderation.user,
131131
type: this.type,
132132
active: true,

src/components/massban.ts renamed to src/components/moderation/massban.ts

+4-4
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,9 @@
11
import * as Discord from "discord.js";
22
import { strict as assert } from "assert";
3-
import { M } from "../utils/debugging-and-logging.js";
4-
import { colors } from "../common.js";
5-
import { BotComponent } from "../bot-component.js";
6-
import { Wheatley } from "../wheatley.js";
3+
import { M } from "../../utils/debugging-and-logging.js";
4+
import { colors } from "../../common.js";
5+
import { BotComponent } from "../../bot-component.js";
6+
import { Wheatley } from "../../wheatley.js";
77

88
const snowflake_re = /\b\d{10,}\b/g;
99

src/components/moderation/moderation-common.ts

+21-19
Original file line numberDiff line numberDiff line change
@@ -20,6 +20,7 @@ import { colors, DAY, HOUR, MINUTE, MONTH, SECOND, WEEK, YEAR } from "../../comm
2020
import Modlogs from "./modlogs.js";
2121
import { TextBasedCommand } from "../../command-abstractions/text-based-command.js";
2222
import {
23+
moderation_state,
2324
moderation_type,
2425
moderation_entry,
2526
basic_moderation_with_user,
@@ -161,6 +162,11 @@ export abstract class ModerationComponent extends BotComponent {
161162
return false;
162163
}
163164

165+
database = this.wheatley.database.create_proxy<{
166+
component_state: { id: "moderation" } & moderation_state;
167+
moderations: moderation_entry;
168+
}>();
169+
164170
// Sorted by moderation end time
165171
sleep_list: SleepList<mongo.WithId<moderation_entry>, mongo.BSON.ObjectId>;
166172
timer: NodeJS.Timer | null = null;
@@ -196,11 +202,11 @@ export abstract class ModerationComponent extends BotComponent {
196202
(async () => {
197203
ModerationComponent.moderations_count
198204
.labels({ type: this.type })
199-
.set(await this.wheatley.database.moderations.countDocuments({ type: this.type }));
205+
.set(await this.database.moderations.countDocuments({ type: this.type }));
200206
if (!this.is_once_off) {
201207
ModerationComponent.active_moderations_count
202208
.labels({ type: this.type })
203-
.set(await this.wheatley.database.moderations.countDocuments({ type: this.type, active: true }));
209+
.set(await this.database.moderations.countDocuments({ type: this.type, active: true }));
204210
}
205211
})().catch(this.wheatley.critical_error.bind(this.wheatley));
206212
}
@@ -209,7 +215,7 @@ export abstract class ModerationComponent extends BotComponent {
209215
this.update_counters();
210216
// Handle re-applications and sleep lists
211217
// If once-off active is false so the rest is all fine
212-
const moderations = await this.wheatley.database.moderations.find({ type: this.type, active: true }).toArray();
218+
const moderations = await this.database.moderations.find({ type: this.type, active: true }).toArray();
213219
const moderations_to_sleep = moderations.filter(
214220
entry => entry.duration !== null || entry.removed || entry.expunged,
215221
);
@@ -260,10 +266,10 @@ export abstract class ModerationComponent extends BotComponent {
260266
assert(!this.is_once_off);
261267
// It's possible the moderation could have been removed or been updated by the time this runs, so fetch the
262268
// current state
263-
const entry = unwrap(await this.wheatley.database.moderations.findOne({ _id: entry_from_sleep._id }));
269+
const entry = unwrap(await this.database.moderations.findOne({ _id: entry_from_sleep._id }));
264270
// Check for active but removed (can happen from data import)
265271
if (entry.active && (entry.removed || entry.expunged)) {
266-
await this.wheatley.database.moderations.updateOne(
272+
await this.database.moderations.updateOne(
267273
{ _id: entry._id },
268274
{
269275
$set: {
@@ -302,7 +308,7 @@ export abstract class ModerationComponent extends BotComponent {
302308
}
303309
// Check if moderation is still marked active, if so resolve it
304310
if (entry.active) {
305-
await this.wheatley.database.moderations.updateOne(
311+
await this.database.moderations.updateOne(
306312
{ _id: entry._id },
307313
{
308314
$set: {
@@ -389,7 +395,7 @@ export abstract class ModerationComponent extends BotComponent {
389395
if (this.is_once_off) {
390396
return;
391397
}
392-
const moderations = await this.wheatley.database.moderations
398+
const moderations = await this.database.moderations
393399
.find({ user: member.user.id, type: this.type, active: true })
394400
.toArray();
395401
for (const moderation of moderations) {
@@ -403,20 +409,17 @@ export abstract class ModerationComponent extends BotComponent {
403409
// Moderation entry handling
404410
//
405411

406-
async get_case_id() {
407-
return (await this.wheatley.database.get_bot_singleton()).moderation_case_number;
408-
}
409-
410412
async increment_case_id() {
411-
const res = await this.wheatley.database.wheatley.updateOne(
412-
{ id: "main" },
413+
const res = await this.database.component_state.findOneAndUpdate(
414+
{ id: "moderation" },
413415
{
414416
$inc: {
415-
moderation_case_number: 1,
417+
case_number: 1,
416418
},
417419
},
420+
{ upsert: true, returnDocument: "after" },
418421
);
419-
assert(res.acknowledged);
422+
return unwrap(res).case_number;
420423
}
421424

422425
static case_id_mutex = new Mutex();
@@ -426,9 +429,8 @@ export abstract class ModerationComponent extends BotComponent {
426429
try {
427430
await ModerationComponent.case_id_mutex.lock();
428431
await this.apply_moderation(moderation);
429-
moderation.case_number = await this.get_case_id();
430-
const res = await this.wheatley.database.moderations.insertOne(moderation);
431-
await this.increment_case_id();
432+
moderation.case_number = await this.increment_case_id();
433+
const res = await this.database.moderations.insertOne(moderation);
432434
if (moderation.duration) {
433435
this.sleep_list.insert([
434436
moderation.issued_at + moderation.duration,
@@ -689,7 +691,7 @@ export abstract class ModerationComponent extends BotComponent {
689691
) {
690692
assert(!this.is_once_off);
691693
try {
692-
const res = await this.wheatley.database.moderations.findOneAndUpdate(
694+
const res = await this.database.moderations.findOneAndUpdate(
693695
{ user: user.id, type: this.type, active: true, ...additional_moderation_properties },
694696
{
695697
$set: {

src/components/moderation/moderation-control.ts

+10-5
Original file line numberDiff line numberDiff line change
@@ -7,13 +7,18 @@ import { M } from "../../utils/debugging-and-logging.js";
77
import { BotComponent } from "../../bot-component.js";
88
import { Wheatley } from "../../wheatley.js";
99
import { ModerationComponent, parse_duration } from "./moderation-common.js";
10+
import { moderation_entry } from "../../infra/schemata/moderation.js";
1011
import { CommandSetBuilder } from "../../command-abstractions/command-set-builder.js";
1112
import { colors } from "../../common.js";
1213
import Modlogs from "./modlogs.js";
1314
import { EarlyReplyMode, TextBasedCommandBuilder } from "../../command-abstractions/text-based-command-builder.js";
1415
import { TextBasedCommand } from "../../command-abstractions/text-based-command.js";
1516

1617
export default class ModerationControl extends BotComponent {
18+
database = this.wheatley.database.create_proxy<{
19+
moderations: moderation_entry;
20+
}>();
21+
1722
override async setup(commands: CommandSetBuilder) {
1823
commands.add(
1924
new TextBasedCommandBuilder("reason", EarlyReplyMode.visible)
@@ -113,7 +118,7 @@ export default class ModerationControl extends BotComponent {
113118
}
114119

115120
async reason(command: TextBasedCommand, case_number: number, reason: string) {
116-
const res = await this.wheatley.database.moderations.findOneAndUpdate(
121+
const res = await this.database.moderations.findOneAndUpdate(
117122
{ case_number },
118123
{
119124
$set: {
@@ -149,7 +154,7 @@ export default class ModerationControl extends BotComponent {
149154
}
150155

151156
async context_add(command: TextBasedCommand, case_number: number, context: string) {
152-
const res = await this.wheatley.database.moderations.findOneAndUpdate(
157+
const res = await this.database.moderations.findOneAndUpdate(
153158
{ case_number },
154159
{
155160
$push: {
@@ -175,7 +180,7 @@ export default class ModerationControl extends BotComponent {
175180
}
176181

177182
async duration(command: TextBasedCommand, case_number: number, duration: string) {
178-
const item = await this.wheatley.database.moderations.findOne({ case_number });
183+
const item = await this.database.moderations.findOne({ case_number });
179184
if (!item) {
180185
await this.reply_with_error(command, `Case ${case_number} not found`);
181186
return;
@@ -184,7 +189,7 @@ export default class ModerationControl extends BotComponent {
184189
await this.reply_with_error(command, `Case ${case_number} can't take a duration`);
185190
return;
186191
}
187-
const res = await this.wheatley.database.moderations.findOneAndUpdate(
192+
const res = await this.database.moderations.findOneAndUpdate(
188193
{ case_number },
189194
{
190195
$set: {
@@ -222,7 +227,7 @@ export default class ModerationControl extends BotComponent {
222227
}
223228

224229
async expunge(command: TextBasedCommand, case_number: number, reason: string | null) {
225-
const res = await this.wheatley.database.moderations.findOneAndUpdate(
230+
const res = await this.database.moderations.findOneAndUpdate(
226231
{ case_number },
227232
{
228233
$set: {

src/components/moderation/modlogs.ts

+6-2
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,10 @@ import { discord_timestamp } from "../../utils/discord.js";
1919
const moderations_per_page = 5;
2020

2121
export default class Modlogs extends BotComponent {
22+
database = this.wheatley.database.create_proxy<{
23+
moderations: moderation_entry;
24+
}>();
25+
2226
override async setup(commands: CommandSetBuilder) {
2327
commands.add(
2428
new TextBasedCommandBuilder("modlogs", EarlyReplyMode.visible)
@@ -141,7 +145,7 @@ export default class Modlogs extends BotComponent {
141145
if (!show_private_logs) {
142146
query.type = { $ne: "note" };
143147
}
144-
const moderations = await this.wheatley.database.moderations.find(query).sort({ issued_at: -1 }).toArray();
148+
const moderations = await this.database.moderations.find(query).sort({ issued_at: -1 }).toArray();
145149
const pages = Math.ceil(moderations.length / moderations_per_page);
146150
const buttons: Discord.ButtonBuilder[] = [];
147151
if (pages <= 1) {
@@ -228,7 +232,7 @@ export default class Modlogs extends BotComponent {
228232
}
229233

230234
async case_info(command: TextBasedCommand, case_number: number) {
231-
const moderation = await this.wheatley.database.moderations.findOne({ case_number });
235+
const moderation = await this.database.moderations.findOne({ case_number });
232236
if (moderation) {
233237
await command.reply({
234238
embeds: [

src/components/modmail.ts renamed to src/components/moderation/modmail.ts

+25-14
Original file line numberDiff line numberDiff line change
@@ -1,14 +1,15 @@
11
import { strict as assert } from "assert";
22
import * as Discord from "discord.js";
33

4-
import { get_url_for } from "../utils/discord.js";
5-
import { M } from "../utils/debugging-and-logging.js";
6-
import { colors, HOUR, MINUTE } from "../common.js";
7-
import { BotComponent } from "../bot-component.js";
8-
import { Wheatley } from "../wheatley.js";
9-
import { SelfClearingMap } from "../utils/containers.js";
10-
import { unwrap } from "../utils/misc.js";
11-
import { set_timeout } from "../utils/node.js";
4+
import { get_url_for } from "../../utils/discord.js";
5+
import { M } from "../../utils/debugging-and-logging.js";
6+
import { colors, HOUR, MINUTE } from "../../common.js";
7+
import { BotComponent } from "../../bot-component.js";
8+
import { Wheatley } from "../../wheatley.js";
9+
import { moderation_state } from "../../infra/schemata/moderation.js";
10+
import { SelfClearingMap } from "../../utils/containers.js";
11+
import { unwrap } from "../../utils/misc.js";
12+
import { set_timeout } from "../../utils/node.js";
1213

1314
/*
1415
* Flow:
@@ -32,13 +33,24 @@ function create_embed(title: string, msg: string) {
3233
export default class Modmail extends BotComponent {
3334
// Spam prevention, user is added to the timeout set when clicking the modmail_continue button,
3435
readonly timeout_set = new Set<string>();
35-
modmail_id_counter = -1;
3636

3737
readonly monke_set = new SelfClearingMap<Discord.Snowflake, number>(HOUR, HOUR);
3838

39-
override async on_ready() {
40-
const singleton = await this.wheatley.database.get_bot_singleton();
41-
this.modmail_id_counter = singleton.modmail_id_counter;
39+
database = this.wheatley.database.create_proxy<{
40+
component_state: { id: "moderation" } & moderation_state;
41+
}>();
42+
43+
async increment_modmail_id() {
44+
const res = await this.database.component_state.findOneAndUpdate(
45+
{ id: "moderation" },
46+
{
47+
$inc: {
48+
modmail_id: 1,
49+
},
50+
},
51+
{ upsert: true, returnDocument: "after" },
52+
);
53+
return unwrap(res).modmail_id;
4254
}
4355

4456
async create_modmail_thread(interaction: Discord.ModalSubmitInteraction | Discord.ButtonInteraction) {
@@ -48,8 +60,7 @@ export default class Modmail extends BotComponent {
4860
assert(interaction.member);
4961
const member = await this.wheatley.TCCPP.members.fetch(interaction.member.user.id);
5062
// make the thread
51-
const id = this.modmail_id_counter++;
52-
await this.wheatley.database.update_bot_singleton({ modmail_id_counter: this.modmail_id_counter });
63+
const id = await this.increment_modmail_id();
5364
const thread = await this.wheatley.channels.rules.threads.create({
5465
type: Discord.ChannelType.PrivateThread,
5566
invitable: false,

src/components/modstats.ts renamed to src/components/moderation/modstats.ts

+14-9
Original file line numberDiff line numberDiff line change
@@ -1,17 +1,22 @@
11
import * as Discord from "discord.js";
22
import { strict as assert } from "assert";
33

4-
import { BotComponent } from "../bot-component.js";
5-
import { CommandSetBuilder } from "../command-abstractions/command-set-builder.js";
6-
import { EarlyReplyMode, TextBasedCommandBuilder } from "../command-abstractions/text-based-command-builder.js";
7-
import { TextBasedCommand } from "../command-abstractions/text-based-command.js";
4+
import { BotComponent } from "../../bot-component.js";
5+
import { CommandSetBuilder } from "../../command-abstractions/command-set-builder.js";
6+
import { EarlyReplyMode, TextBasedCommandBuilder } from "../../command-abstractions/text-based-command-builder.js";
7+
import { TextBasedCommand } from "../../command-abstractions/text-based-command.js";
88

9-
import { Wheatley } from "../wheatley.js";
10-
import { colors, DAY } from "../common.js";
11-
import { unwrap } from "../utils/misc.js";
12-
import { capitalize } from "../utils/strings.js";
9+
import { Wheatley } from "../../wheatley.js";
10+
import { moderation_entry } from "../../infra/schemata/moderation.js";
11+
import { colors, DAY } from "../../common.js";
12+
import { unwrap } from "../../utils/misc.js";
13+
import { capitalize } from "../../utils/strings.js";
1314

1415
export default class ModStats extends BotComponent {
16+
database = this.wheatley.database.create_proxy<{
17+
moderations: moderation_entry;
18+
}>();
19+
1520
override async setup(commands: CommandSetBuilder) {
1621
commands.add(
1722
new TextBasedCommandBuilder("modstats", EarlyReplyMode.none)
@@ -27,7 +32,7 @@ export default class ModStats extends BotComponent {
2732
}
2833

2934
async get_stats(moderator: Discord.User | null, cutoff = 0) {
30-
const res = await this.wheatley.database.moderations
35+
const res = await this.database.moderations
3136
.aggregate([
3237
{
3338
$match: moderator

src/components/moderation/mute.ts

+1-1
Original file line numberDiff line numberDiff line change
@@ -98,7 +98,7 @@ export default class Mute extends ModerationComponent {
9898
return member.roles.cache.filter(role => role.id == this.wheatley.roles.muted.id).size > 0;
9999
} else {
100100
// if the member isn't in the guild then lookup
101-
const res = await this.wheatley.database.moderations.findOne({
101+
const res = await this.database.moderations.findOne({
102102
user: moderation.user,
103103
type: this.type,
104104
active: true,

src/components/notify-about-brand-new-users.ts renamed to src/components/moderation/notify-about-brand-new-users.ts

+5-5
Original file line numberDiff line numberDiff line change
@@ -1,10 +1,10 @@
11
import * as Discord from "discord.js";
22
import { strict as assert } from "assert";
3-
import { time_to_human } from "../utils/strings.js";
4-
import { colors, MINUTE } from "../common.js";
5-
import { BotComponent } from "../bot-component.js";
6-
import { Wheatley } from "../wheatley.js";
7-
import { discord_timestamp } from "../utils/discord.js";
3+
import { time_to_human } from "../../utils/strings.js";
4+
import { colors, MINUTE } from "../../common.js";
5+
import { BotComponent } from "../../bot-component.js";
6+
import { Wheatley } from "../../wheatley.js";
7+
import { discord_timestamp } from "../../utils/discord.js";
88

99
const NEW_USER_THRESHOLD = MINUTE * 30;
1010

src/components/notify-about-formerly-banned-users.ts renamed to src/components/moderation/notify-about-formerly-banned-users.ts

+11-7
Original file line numberDiff line numberDiff line change
@@ -1,13 +1,17 @@
11
import * as Discord from "discord.js";
22
import { strict as assert } from "assert";
3-
import { build_description, time_to_human } from "../utils/strings.js";
4-
import { colors, MINUTE } from "../common.js";
5-
import { BotComponent } from "../bot-component.js";
6-
import { Wheatley } from "../wheatley.js";
7-
import { discord_timestamp } from "../utils/discord.js";
8-
import { moderation_entry } from "../infra/schemata/moderation.js";
3+
import { build_description, time_to_human } from "../../utils/strings.js";
4+
import { colors, MINUTE } from "../../common.js";
5+
import { BotComponent } from "../../bot-component.js";
6+
import { Wheatley } from "../../wheatley.js";
7+
import { discord_timestamp } from "../../utils/discord.js";
8+
import { moderation_entry } from "../../infra/schemata/moderation.js";
99

1010
export default class NotifyAboutFormerlyBannedUsers extends BotComponent {
11+
database = this.wheatley.database.create_proxy<{
12+
moderations: moderation_entry;
13+
}>();
14+
1115
async alert(member: Discord.GuildMember, most_recent: moderation_entry) {
1216
const action = most_recent.type == "kick" ? "kicked" : "banned";
1317
const embed = new Discord.EmbedBuilder()
@@ -30,7 +34,7 @@ export default class NotifyAboutFormerlyBannedUsers extends BotComponent {
3034
}
3135

3236
async find_most_recent_kick_or_ban(member: Discord.GuildMember) {
33-
return await this.wheatley.database.moderations.findOne(
37+
return await this.database.moderations.findOne(
3438
{
3539
user: member.id,
3640
$or: [{ type: "ban" }, { type: "softban" }, { type: "kick" }],

0 commit comments

Comments
 (0)