Skip to content

Commit 50e5598

Browse files
authored
Create honeypotService.js
1 parent 938aebc commit 50e5598

1 file changed

Lines changed: 93 additions & 0 deletions

File tree

src/services/honeypotService.js

Lines changed: 93 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,93 @@
1+
import { EmbedBuilder, ActionRowBuilder, ButtonBuilder, ButtonStyle } from 'discord.js';
2+
import { getFromDb, setInDb } from '../utils/database/wrapper.js';
3+
import { ModerationService } from './moderationService.js';
4+
import { logger } from '../utils/logger.js';
5+
6+
const getHoneypotKey = (guildId) => `guild:${guildId}:honeypot`;
7+
const HONEYPOT_IMAGE = 'https://honeypot.riskymh.dev/honeypot.png';
8+
9+
export async function getHoneypotConfig(guildId) {
10+
try {
11+
const data = await getFromDb(getHoneypotKey(guildId), null);
12+
return data || { channelId: null, enabled: false, banCount: 0 };
13+
} catch (err) {
14+
logger.error(`Failed to get honeypot config for ${guildId}:`, err);
15+
return { channelId: null, enabled: false, banCount: 0 };
16+
}
17+
}
18+
19+
export async function setHoneypotConfig(guildId, config) {
20+
try {
21+
await setInDb(getHoneypotKey(guildId), config);
22+
return true;
23+
} catch (err) {
24+
logger.error(`Failed to set honeypot config for ${guildId}:`, err);
25+
return false;
26+
}
27+
}
28+
29+
export function buildHoneypotWarningEmbed(banCount = 0) {
30+
return new EmbedBuilder()
31+
.setColor(0xFF0000)
32+
.setTitle('DO NOT SEND MESSAGES IN THIS CHANNEL')
33+
.setDescription(
34+
'This channel is used to catch spam bots and scammers.\n' +
35+
'Any messages sent here will result in a **ban**.',
36+
)
37+
.setThumbnail(HONEYPOT_IMAGE);
38+
}
39+
40+
export function buildHoneypotComponents(banCount = 0) {
41+
return new ActionRowBuilder().addComponents(
42+
new ButtonBuilder()
43+
.setCustomId('honeypot_ban_count')
44+
.setLabel(`🍯 Kicks: ${banCount}`)
45+
.setStyle(ButtonStyle.Danger)
46+
.setDisabled(true),
47+
);
48+
}
49+
50+
export async function refreshHoneypotMessage(client, guildId) {
51+
try {
52+
const config = await getHoneypotConfig(guildId);
53+
if (!config.channelId || !config.messageId) return;
54+
55+
const channel = client.channels.cache.get(config.channelId);
56+
if (!channel) return;
57+
58+
const msg = await channel.messages.fetch(config.messageId).catch(() => null);
59+
if (!msg) return;
60+
61+
await msg.edit({
62+
embeds: [buildHoneypotWarningEmbed(config.banCount)],
63+
components: [buildHoneypotComponents(config.banCount)],
64+
});
65+
} catch (err) {
66+
logger.error(`Honeypot: failed to refresh warning message in guild ${guildId}:`, err);
67+
}
68+
}
69+
70+
71+
export async function handleHoneypotMessage(message, client) {
72+
const { guild, author } = message;
73+
await message.delete().catch(() => null);
74+
const botMember = guild.members.me;
75+
76+
try {
77+
await ModerationService.banUser({
78+
guild,
79+
user: author,
80+
moderator: botMember,
81+
reason: 'Honeypot triggered — sent a message in a protected channel.',
82+
deleteDays: 1,
83+
});
84+
85+
logger.info(`Honeypot: banned ${author.tag} (${author.id}) in guild ${guild.id}`);
86+
const config = await getHoneypotConfig(guild.id);
87+
const newCount = (config.banCount || 0) + 1;
88+
await setHoneypotConfig(guild.id, { ...config, banCount: newCount });
89+
await refreshHoneypotMessage(client, guild.id);
90+
} catch (err) {
91+
logger.error(`Honeypot: failed to ban ${author.tag} in guild ${guild.id}:`, err);
92+
}
93+
}

0 commit comments

Comments
 (0)