Skip to content

Commit 9ee4d90

Browse files
committed
Move invite spam config to global Config
- Add InviteSpamConfig interface to config.type.ts - Add inviteSpam defaults to both dev and prod configs - Remove local config from listener, read from global config directly
1 parent c2e206c commit 9ee4d90

4 files changed

Lines changed: 39 additions & 30 deletions

File tree

src/Config.prod.ts

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -72,9 +72,15 @@ export const config: Config = {
7272
archiveChannel: "1415283787440328836",
7373
channel: "1415283659350741062",
7474
},
75+
inviteSpam: {
76+
maxViolations: 4,
77+
maxChannels: 3,
78+
violationWindowMs: 30_000,
79+
accountAgeDays: 0,
80+
},
7581
devbin: {
7682
url: "https://devbin.developerden.org",
77-
api_url: "https://devbin-api.developerden.org",
83+
api_url: "https://devbin-api.developerden.org",
7884
threshold: 20,
7985
},
8086
branding: {

src/Config.ts

Lines changed: 6 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -23,6 +23,12 @@ const devConfig: Config = {
2323
commands: {
2424
daily: "1029850807794937949",
2525
},
26+
inviteSpam: {
27+
maxViolations: 4,
28+
maxChannels: 3,
29+
violationWindowMs: 30_000,
30+
accountAgeDays: 0,
31+
},
2632
deletedMessageLog: {
2733
cacheTtlMs: 1000 * 60 * 60 * 24,
2834
excludedChannels: [],

src/config.type.ts

Lines changed: 17 additions & 5 deletions
Original file line numberDiff line numberDiff line change
@@ -54,6 +54,17 @@ export interface ThreatDetectionConfig {
5454
};
5555
}
5656

57+
export interface InviteSpamConfig {
58+
/** Max violations before auto-ban */
59+
maxViolations: number;
60+
/** Max unique channels before auto-ban */
61+
maxChannels: number;
62+
/** Time window in ms for tracking violations */
63+
violationWindowMs: number;
64+
/** Only auto-ban accounts that joined the server less than X days ago. 0 = disabled (everyone is considered) */
65+
accountAgeDays: number;
66+
}
67+
5768
export interface Config {
5869
guildId: string;
5970
clientId: string;
@@ -62,11 +73,11 @@ export interface Config {
6273
yesEmojiId: string;
6374
noEmojiId: string;
6475
};
65-
devbin: {
66-
url: string;
67-
api_url: string;
68-
threshold: number
69-
};
76+
devbin: {
77+
url: string;
78+
api_url: string;
79+
threshold: number;
80+
};
7081
channels: {
7182
welcome: string;
7283
botCommands: string;
@@ -117,6 +128,7 @@ export interface Config {
117128
branding: BrandingConfig;
118129
informationMessage?: InformationMessage;
119130
threatDetection?: ThreatDetectionConfig;
131+
inviteSpam: InviteSpamConfig;
120132
reputation?: {
121133
enabled: boolean;
122134
warningThresholds: {

src/modules/moderation/discordInvitesMonitor.listener.ts

Lines changed: 9 additions & 24 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,7 @@
11
import * as Sentry from "@sentry/bun";
22
import type { GuildMember, Message } from "discord.js";
33
import ExpiryMap from "expiry-map";
4+
import { config } from "../../Config.js";
45
import { logger } from "../../logging.js";
56
import { getOrCreateUserById } from "../../store/models/DDUser.js";
67
import { getMember } from "../../util/member.js";
@@ -18,31 +19,13 @@ const invitePatterns = [
1819

1920
const whitelistDomains: string[] = []; // For any .gg domains that are not discord.gg
2021

21-
interface InviteSpamConfig {
22-
/** Max violations before auto-ban (default: 4) */
23-
maxViolations: number;
24-
/** Max unique channels before auto-ban (default: 3) */
25-
maxChannels: number;
26-
/** Time window in ms for tracking violations (default: 30s) */
27-
violationWindowMs: number;
28-
/** Only auto-ban accounts that joined the server less than X days ago. 0 = disabled (everyone is considered) */
29-
accountAgeDays: number;
30-
}
31-
32-
const inviteSpamConfig: InviteSpamConfig = {
33-
maxViolations: 4,
34-
maxChannels: 3,
35-
violationWindowMs: 30_000,
36-
accountAgeDays: 0,
37-
};
38-
3922
interface InviteViolation {
4023
count: number;
4124
channels: Set<string>;
4225
}
4326

4427
const inviteViolationCache = new ExpiryMap<string, InviteViolation>(
45-
inviteSpamConfig.violationWindowMs,
28+
config.inviteSpam.violationWindowMs,
4629
);
4730

4831
const isAllowedToSendDiscordInvites = async (member: GuildMember) => {
@@ -51,14 +34,14 @@ const isAllowedToSendDiscordInvites = async (member: GuildMember) => {
5134
};
5235

5336
const isSubjectToAutoban = (member: GuildMember): boolean => {
54-
if (inviteSpamConfig.accountAgeDays === 0) return true;
37+
if (config.inviteSpam.accountAgeDays === 0) return true;
5538

5639
const joinedAt = member.joinedAt;
5740
if (!joinedAt) return true;
5841

5942
const daysSinceJoin =
6043
(Date.now() - joinedAt.getTime()) / (1000 * 60 * 60 * 24);
61-
return daysSinceJoin < inviteSpamConfig.accountAgeDays;
44+
return daysSinceJoin < config.inviteSpam.accountAgeDays;
6245
};
6346

6447
export function parseInvites(message: Message<true>) {
@@ -101,7 +84,9 @@ async function banForInviteSpam(
10184
violation: InviteViolation,
10285
) {
10386
const triggerReason =
104-
violation.channels.size >= 3 ? "cross_channel" : "same_channel";
87+
violation.channels.size >= config.inviteSpam.maxChannels
88+
? "cross_channel"
89+
: "same_channel";
10590

10691
try {
10792
await member
@@ -160,8 +145,8 @@ async function handleInvite(
160145
inviteViolationCache.set(member.id, violation);
161146

162147
const shouldBan =
163-
violation.count >= inviteSpamConfig.maxViolations ||
164-
violation.channels.size >= inviteSpamConfig.maxChannels;
148+
violation.count >= config.inviteSpam.maxViolations ||
149+
violation.channels.size >= config.inviteSpam.maxChannels;
165150

166151
if (shouldBan && isSubjectToAutoban(member)) {
167152
await banForInviteSpam(message, member, violation);

0 commit comments

Comments
 (0)