Skip to content

Commit c893882

Browse files
Refactor channel access (#169)
Instead of having a massive map of channels in wheatley, which was convenient but not very conducive to running the bot elsewhere, it's more principled to have every module just fetch their own channels as part of startup. This PR implements that. These changes were also mostly done by claude. This also fixes the horrible typescript errors that manifested in 58d6ef7 where a mundane change in an unrelated part of the codebase resulted in errors about union sizes, caused because of the massive channel type in wheatley. Twin PR: TCCPP/wheatley-private#15
1 parent 1c52fd9 commit c893882

44 files changed

Lines changed: 452 additions & 285 deletions

Some content is hidden

Large Commits have some content hidden by default. Use the searchbox below for content that may be hidden.

src/bot-utilities.ts

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -224,4 +224,22 @@ export class BotUtilities {
224224
attachments.length + other_attachments.length == 0 ? undefined : [...attachments, ...other_attachments],
225225
};
226226
}
227+
228+
async get_channel(id: string) {
229+
const channel = await this.wheatley.client.channels.fetch(id);
230+
assert(channel instanceof Discord.TextChannel, `Channel ${channel} (${id}) not of the expected type`);
231+
return channel;
232+
}
233+
234+
async get_forum_channel(id: string) {
235+
const channel = await this.wheatley.client.channels.fetch(id);
236+
assert(channel instanceof Discord.ForumChannel, `Channel ${channel} (${id}) not of the expected type`);
237+
return channel;
238+
}
239+
240+
async get_thread_channel(id: string) {
241+
const channel = await this.wheatley.client.channels.fetch(id);
242+
assert(channel instanceof Discord.ThreadChannel, `Channel ${channel} (${id}) not of the expected type`);
243+
return channel;
244+
}
227245
}

src/components/anti-executable.ts

Lines changed: 11 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -10,10 +10,13 @@ import { build_description, capitalize } from "../utils/strings.js";
1010
import { Virustotal } from "../infra/virustotal.js";
1111
import Mute from "./moderation/mute.js";
1212
import { unwrap } from "../utils/misc.js";
13+
import { CommandSetBuilder } from "../command-abstractions/command-set-builder.js";
1314

1415
const ACTION_THRESHOLD = 5;
1516

1617
export default class AntiExecutable extends BotComponent {
18+
private staff_flag_log: Discord.TextChannel;
19+
private staff_action_log: Discord.TextChannel;
1720
virustotal: Virustotal | null;
1821

1922
static override get is_freestanding() {
@@ -28,6 +31,11 @@ export default class AntiExecutable extends BotComponent {
2831
}
2932
}
3033

34+
override async setup(commands: CommandSetBuilder) {
35+
this.staff_flag_log = await this.utilities.get_channel(this.wheatley.channels.staff_flag_log);
36+
this.staff_action_log = await this.utilities.get_channel(this.wheatley.channels.staff_action_log);
37+
}
38+
3139
// Elf: 0x7F 0x45 0x4c 0x46 at offset 0
3240
// Mach: 0xfe 0xed 0xfa 0xce offset 0
3341
// 0xce 0xfa 0xed 0xfe
@@ -168,7 +176,7 @@ export default class AntiExecutable extends BotComponent {
168176
)
169177
.catch(this.wheatley.critical_error.bind(this.wheatley))
170178
.finally(() => {
171-
this.wheatley.channels.staff_action_log
179+
this.staff_action_log
172180
.send({
173181
content:
174182
`<@&${this.wheatley.roles.moderators.id}> Please review automatic 24h mute of ` +
@@ -210,7 +218,7 @@ export default class AntiExecutable extends BotComponent {
210218
await message.delete();
211219
assert(!(message.channel instanceof Discord.PartialGroupDMChannel));
212220
await message.channel.send(`<@${message.author.id}> Please do not send executable files`);
213-
const flag_message = await this.wheatley.channels.staff_flag_log.send({
221+
const flag_message = await this.staff_flag_log.send({
214222
content: `:warning: Executable file(s) detected`,
215223
...quote,
216224
});
@@ -219,7 +227,7 @@ export default class AntiExecutable extends BotComponent {
219227

220228
async handle_archives(message: Discord.Message, attachments: Discord.Attachment[]) {
221229
const quote = await this.utilities.make_quote_embeds([message]);
222-
const flag_message = await this.wheatley.channels.staff_flag_log.send({
230+
const flag_message = await this.staff_flag_log.send({
223231
content: `:warning: Archive file(s) detected`,
224232
...quote,
225233
});

src/components/anti-invite-links.ts

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,7 @@ import * as Discord from "discord.js";
44

55
import { BotComponent } from "../bot-component.js";
66
import { departialize } from "../utils/discord.js";
7+
import { CommandSetBuilder } from "../command-abstractions/command-set-builder.js";
78

89
const INVITE_RE =
910
/(?:(?:discord(?:app)?|disboard)\.(?:gg|(?:com|org|me)\/(?:invite|server\/join))|(?<!\w)\.gg)\/(\S+)/i;
@@ -26,6 +27,12 @@ export default class AntiInviteLinks extends BotComponent {
2627
return true;
2728
}
2829

30+
private staff_flag_log: Discord.TextChannel;
31+
32+
override async setup(commands: CommandSetBuilder) {
33+
this.staff_flag_log = await this.utilities.get_channel(this.wheatley.channels.staff_flag_log);
34+
}
35+
2936
async member_is_proficient_or_higher(member: Discord.GuildMember | null) {
3037
if (!member) {
3138
return false;
@@ -52,7 +59,7 @@ export default class AntiInviteLinks extends BotComponent {
5259
await message.delete();
5360
assert(!(message.channel instanceof Discord.PartialGroupDMChannel));
5461
await message.channel.send(`<@${message.author.id}> Please do not send invite links`);
55-
await this.wheatley.channels.staff_flag_log.send({
62+
await this.staff_flag_log.send({
5663
content: `:warning: Invite link deleted`,
5764
...quote,
5865
});

src/components/code.ts

Lines changed: 1 addition & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -26,7 +26,7 @@ export default class Code extends BotComponent {
2626
}
2727

2828
static make_code_formatting_embeds(wheatley: Wheatley, channel: Discord.TextBasedChannel): Discord.APIEmbedField[] {
29-
const is_c = [wheatley.channels.c_help.id, wheatley.channels.c_help_text.id].includes(
29+
const is_c = [wheatley.channels.c_help, wheatley.channels.c_help_text].includes(
3030
wheatley.top_level_channel(channel),
3131
);
3232
return [

src/components/emoji-log.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -5,10 +5,17 @@ import { strict as assert } from "assert";
55
import { M } from "../utils/debugging-and-logging.js";
66
import { colors } from "../common.js";
77
import { BotComponent } from "../bot-component.js";
8+
import { CommandSetBuilder } from "../command-abstractions/command-set-builder.js";
89

910
export default class EmojiLog extends BotComponent {
11+
private staff_action_log: Discord.TextChannel;
12+
13+
override async setup(commands: CommandSetBuilder) {
14+
this.staff_action_log = await this.utilities.get_channel(this.wheatley.channels.staff_action_log);
15+
}
16+
1017
override async on_emoji_create(emoji: Discord.GuildEmoji) {
11-
await this.wheatley.channels.staff_action_log.send({
18+
await this.staff_action_log.send({
1219
embeds: [
1320
new Discord.EmbedBuilder()
1421
.setTitle("Emoji Created")
@@ -24,7 +31,7 @@ export default class EmojiLog extends BotComponent {
2431
}
2532

2633
override async on_emoji_delete(emoji: Discord.GuildEmoji) {
27-
await this.wheatley.channels.staff_action_log.send({
34+
await this.staff_action_log.send({
2835
embeds: [
2936
new Discord.EmbedBuilder()
3037
.setTitle("Emoji Removed")
@@ -40,7 +47,7 @@ export default class EmojiLog extends BotComponent {
4047
}
4148

4249
override async on_emoji_update(old_emoji: Discord.GuildEmoji, new_emoji: Discord.GuildEmoji) {
43-
await this.wheatley.channels.staff_action_log.send({
50+
await this.staff_action_log.send({
4451
embeds: [
4552
new Discord.EmbedBuilder()
4653
.setTitle("Emoji Updated")

src/components/join-leave-log.ts

Lines changed: 10 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -7,10 +7,17 @@ import { colors } from "../common.js";
77
import { BotComponent } from "../bot-component.js";
88
import { build_description, time_to_human } from "../utils/strings.js";
99
import { equal } from "../utils/arrays.js";
10+
import { CommandSetBuilder } from "../command-abstractions/command-set-builder.js";
1011

1112
export default class JoinLeaveLog extends BotComponent {
13+
private staff_member_log: Discord.TextChannel;
14+
15+
override async setup(commands: CommandSetBuilder) {
16+
this.staff_member_log = await this.utilities.get_channel(this.wheatley.channels.staff_member_log);
17+
}
18+
1219
override async on_guild_member_add(member: Discord.GuildMember) {
13-
this.wheatley.llog(this.wheatley.channels.staff_member_log, {
20+
this.wheatley.llog(this.staff_member_log, {
1421
embeds: [
1522
new Discord.EmbedBuilder()
1623
.setTitle("Member Joined")
@@ -34,7 +41,7 @@ export default class JoinLeaveLog extends BotComponent {
3441
}
3542

3643
override async on_guild_member_remove(member: Discord.GuildMember | Discord.PartialGuildMember) {
37-
this.wheatley.llog(this.wheatley.channels.staff_member_log, {
44+
this.wheatley.llog(this.staff_member_log, {
3845
embeds: [
3946
new Discord.EmbedBuilder()
4047
.setTitle("Member Left")
@@ -74,7 +81,7 @@ export default class JoinLeaveLog extends BotComponent {
7481
extra_description.push(`Old display name: ${old_member.displayName}`);
7582
extra_description.push(`New display name: ${new_member.displayName}`);
7683
}
77-
this.wheatley.llog(this.wheatley.channels.staff_member_log, {
84+
this.wheatley.llog(this.staff_member_log, {
7885
embeds: [
7986
new Discord.EmbedBuilder()
8087
.setTitle("Member Updated")

src/components/moderation/ban.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,7 @@ export default class Ban extends ModerationComponent {
2323
}
2424

2525
override async setup(commands: CommandSetBuilder) {
26+
await super.setup(commands);
2627
commands.add(
2728
new TextBasedCommandBuilder("ban", EarlyReplyMode.visible)
2829
.set_permissions(Discord.PermissionFlagsBits.BanMembers)

src/components/moderation/kick.ts

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -27,6 +27,7 @@ export default class Kick extends ModerationComponent {
2727
}
2828

2929
override async setup(commands: CommandSetBuilder) {
30+
await super.setup(commands);
3031
commands.add(
3132
new TextBasedCommandBuilder("kick", EarlyReplyMode.visible)
3233
.set_permissions(Discord.PermissionFlagsBits.BanMembers)

src/components/moderation/massban.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,10 +4,16 @@ import { M } from "../../utils/debugging-and-logging.js";
44
import { colors } from "../../common.js";
55
import { BotComponent } from "../../bot-component.js";
66
import { Wheatley } from "../../wheatley.js";
7+
import { CommandSetBuilder } from "../../command-abstractions/command-set-builder.js";
78

89
const snowflake_re = /\b\d{10,}\b/g;
910

1011
export default class Massban extends BotComponent {
12+
private staff_action_log: Discord.TextChannel;
13+
14+
override async setup(commands: CommandSetBuilder) {
15+
this.staff_action_log = await this.utilities.get_channel(this.wheatley.channels.staff_action_log);
16+
}
1117
override async on_message_create(message: Discord.Message) {
1218
try {
1319
// Ignore self, bots, and messages outside TCCPP (e.g. dm's)
@@ -50,7 +56,7 @@ export default class Massban extends BotComponent {
5056
.setTitle(`<@!${msg.author.id}> banned ${ids.length} users`)
5157
.setDescription(`\`\`\`\n${ids.join("\n")}\n\`\`\``)
5258
.setTimestamp();
53-
await this.wheatley.channels.staff_action_log.send({ embeds: [embed] });
59+
await this.staff_action_log.send({ embeds: [embed] });
5460
}
5561
}
5662
}

src/components/moderation/moderation-common.ts

Lines changed: 13 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -29,6 +29,7 @@ import {
2929
import { set_interval } from "../../utils/node.js";
3030

3131
import { get_random_array_element } from "../../utils/arrays.js";
32+
import { CommandSetBuilder } from "../../command-abstractions/command-set-builder.js";
3233

3334
/*
3435
* !mute !unmute
@@ -166,11 +167,18 @@ export abstract class ModerationComponent extends BotComponent {
166167
component_state: moderation_state;
167168
moderations: moderation_entry;
168169
}>();
170+
protected staff_action_log: Discord.TextChannel;
171+
protected public_action_log: Discord.TextChannel;
169172

170173
// Sorted by moderation end time
171174
sleep_list: SleepList<mongo.WithId<moderation_entry>, mongo.BSON.ObjectId>;
172175
timer: NodeJS.Timer | null = null;
173176

177+
override async setup(commands: CommandSetBuilder) {
178+
this.staff_action_log = await this.utilities.get_channel(this.wheatley.channels.staff_action_log);
179+
this.public_action_log = await this.utilities.get_channel(this.wheatley.channels.public_action_log);
180+
}
181+
174182
static non_duration_moderation_set = new Set(["warn", "kick", "softban", "note"]);
175183

176184
static moderations_count = new PromClient.Gauge({
@@ -296,7 +304,7 @@ export abstract class ModerationComponent extends BotComponent {
296304
M.debug("Handling moderation expire", entry);
297305
await this.remove_moderation(entry);
298306
this.sleep_list.remove(entry._id);
299-
await this.wheatley.channels.staff_action_log.send({
307+
await this.staff_action_log.send({
300308
embeds: [
301309
Modlogs.case_summary(entry, await this.wheatley.client.users.fetch(entry.user), true).setTitle(
302310
`${capitalize(this.type)} is being lifted (case ${entry.case_number})`,
@@ -440,15 +448,15 @@ export abstract class ModerationComponent extends BotComponent {
440448
},
441449
]);
442450
}
443-
this.wheatley.channels.staff_action_log
451+
this.staff_action_log
444452
.send({
445453
embeds: [
446454
Modlogs.case_summary(moderation, await this.wheatley.client.users.fetch(moderation.user), true),
447455
],
448456
})
449457
.catch(this.wheatley.critical_error.bind(this.wheatley));
450458
if (moderation.type !== "note") {
451-
this.wheatley.channels.public_action_log
459+
this.public_action_log
452460
.send({
453461
embeds: [
454462
Modlogs.case_summary(
@@ -731,15 +739,15 @@ export abstract class ModerationComponent extends BotComponent {
731739
}),
732740
],
733741
});
734-
await this.wheatley.channels.staff_action_log.send({
742+
await this.staff_action_log.send({
735743
embeds: [
736744
Modlogs.case_summary(res, await this.wheatley.client.users.fetch(res.user), true).setTitle(
737745
`Case ${res.case_number}: Un${this.past_participle}`,
738746
),
739747
],
740748
});
741749
if (res.type !== "note") {
742-
await this.wheatley.channels.public_action_log.send({
750+
await this.public_action_log.send({
743751
embeds: [
744752
Modlogs.case_summary(res, await this.wheatley.client.users.fetch(res.user), false).setTitle(
745753
`Case ${res.case_number}: Un${this.past_participle}`,

0 commit comments

Comments
 (0)