Skip to content

Commit fc5a81d

Browse files
authored
Merge pull request #162 from tjjfvi/green-eggs-and-spam
2 parents 852237b + 6cf3211 commit fc5a81d

File tree

1 file changed

+52
-1
lines changed

1 file changed

+52
-1
lines changed

src/modules/mod.ts

Lines changed: 52 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,12 +1,24 @@
11
import { default as CookiecordClient, Module, listener } from 'cookiecord';
2-
import { Message } from 'discord.js';
2+
import { Message, Snowflake, User } from 'discord.js';
33
import { rulesChannelId } from '../env';
44

55
// Most job posts are in this format:
66
// > [FOR HIRE][REMOTE][SOMETHING ELSE]
77
// > Hi, I'm ponyman6000. Hire me!
88
const jobPostRegex = /^(?:\[[A-Z ]+\]){2,}\n/i;
99

10+
const SPAM_CHANNEL_THRESHOLD = 3;
11+
const SPAM_MAX_TIME = 5000;
12+
13+
interface RecentMessageInfo {
14+
author: User;
15+
firstPost: Date;
16+
channels: Set<Snowflake>;
17+
messages: Message[];
18+
}
19+
const recentMessages = new Map<string, RecentMessageInfo>();
20+
const CLEANUP_RECENT_MESSAGES_MAP_INTERVAL = 10000;
21+
1022
export class ModModule extends Module {
1123
constructor(client: CookiecordClient) {
1224
super(client);
@@ -20,4 +32,43 @@ export class ModModule extends Module {
2032
`${msg.author} We don't do job posts here; see <#${rulesChannelId}>`,
2133
);
2234
}
35+
36+
@listener({ event: 'message' })
37+
async onRepeatedMessage(msg: Message) {
38+
if (!msg.guild || msg.author.id === this.client.user!.id) return;
39+
const messageIdentifier = msg.content.trim().toLowerCase();
40+
if (!messageIdentifier) return;
41+
let recentMessageInfo = recentMessages.get(messageIdentifier);
42+
if (
43+
recentMessageInfo &&
44+
recentMessageInfo.author.id === msg.author.id &&
45+
+recentMessageInfo.firstPost + SPAM_MAX_TIME > Date.now()
46+
) {
47+
recentMessageInfo.channels.add(msg.channel.id);
48+
recentMessageInfo.messages.push(msg);
49+
if (recentMessageInfo.channels.size >= SPAM_CHANNEL_THRESHOLD) {
50+
await Promise.all([
51+
msg.guild.members
52+
.fetch(msg.author)
53+
.then(member => void member.kick('Spam')),
54+
...recentMessageInfo.messages.map(msg => void msg.delete()),
55+
]);
56+
}
57+
} else {
58+
recentMessages.set(messageIdentifier, {
59+
author: msg.author,
60+
firstPost: new Date(),
61+
channels: new Set([msg.channel.id]),
62+
messages: [msg],
63+
});
64+
}
65+
}
2366
}
67+
68+
setInterval(() => {
69+
for (const [messageText, recentMessageInfo] of recentMessages) {
70+
if (+recentMessageInfo.firstPost + SPAM_MAX_TIME < Date.now()) {
71+
recentMessages.delete(messageText);
72+
}
73+
}
74+
}, CLEANUP_RECENT_MESSAGES_MAP_INTERVAL);

0 commit comments

Comments
 (0)