Moderation example — !ban, !kick, !unban, !perms.
moderation-bot.js · 187 lines
Moderation example — !ban, !kick, !unban, !perms.
View on GitHubnode examples/moderation-bot.js
javascript
/**
* Moderation example — !ban, !kick, !unban, !perms.
*
* Requires Ban Members / Kick Members (server owner has all permissions).
*
* Usage:
* FLUXER_BOT_TOKEN=your_token node examples/moderation-bot.js
*
* @see https://fluxerjs.blstmo.com/guides/permissions/
* @see https://fluxerjs.blstmo.com/guides/moderation/
*/
import {
Client,
Events,
EmbedBuilder,
FluxerError,
ErrorCodes,
PermissionFlags,
parsePrefixCommand,
parseUserMention,
} from '@fluxerjs/core';
const PREFIX = '!';
async function getModeratorPerms(message) {
const guild =
message.guild ??
(message.guildId ? await message.client.guilds.fetch(message.guildId).catch(() => null) : null);
if (!guild) return null;
const member =
guild.members.get(message.author.id) ??
(await guild.fetchMember(message.author.id).catch(() => null));
return member?.permissions ?? null;
}
function getPermissionNames(perms) {
return Object.keys(PermissionFlags).filter((name) => perms.has(PermissionFlags[name]));
}
const client = new Client({ intents: 0 });
client.on(Events.Ready, () => {
console.log(`Logged in as ${client.user?.username}. Commands: !ban, !kick, !unban, !perms`);
});
client.on(Events.MessageCreate, async (message) => {
if (message.author.bot || !message.content) return;
const parsed = parsePrefixCommand(message.content, PREFIX);
if (!parsed) return;
const { command, args } = parsed;
const targetArg = args[0];
const reason = args.slice(1).join(' ') || null;
const guild =
message.guild ??
(message.guildId ? await message.client.guilds.fetch(message.guildId).catch(() => null) : null);
if (!guild) {
await message.reply('Moderation commands only work in a server.');
return;
}
const userId = targetArg ? parseUserMention(targetArg) : null;
const perms = await getModeratorPerms(message);
if (!perms) {
await message.reply(
'Could not load your member data. The bot may need access to view server members.',
);
return;
}
const canBan = perms.has(PermissionFlags.BanMembers) || perms.has(PermissionFlags.Administrator);
const canKick =
perms.has(PermissionFlags.KickMembers) || perms.has(PermissionFlags.Administrator);
if (command === 'perms') {
const names = getPermissionNames(perms);
await message.reply(
names.length > 0
? `**Your server permissions:**\n\`\`\`\n${names.join(', ')}\n\`\`\``
: 'You have no server permissions.',
);
return;
}
if (command === 'ban') {
if (!canBan) {
await message.reply('You need the Ban Members permission to use this command.');
return;
}
if (!userId) {
await message.reply('Usage: `!ban @user [reason]`');
return;
}
try {
await guild.ban(userId, {
reason: reason ?? undefined,
deleteMessageDays: 1,
});
const targetUser = message.mentions.find((u) => u.id === userId) ?? { username: 'Unknown' };
const embed = new EmbedBuilder()
.setTitle('User Banned')
.setColor(0xe74c3c)
.addFields(
{ name: 'User', value: `<@${userId}> (${targetUser.username})`, inline: true },
{ name: 'Moderator', value: `${message.author.username}`, inline: true },
)
.setTimestamp();
if (reason) embed.addFields({ name: 'Reason', value: reason });
await message.reply({ embeds: [embed] });
} catch (err) {
const code = err instanceof FluxerError ? err.code : null;
const status = err?.statusCode ?? err?.cause?.statusCode;
const msg =
code === ErrorCodes.MemberNotFound || status === 404
? 'User not found or not in this server.'
: (err?.message ?? 'Failed to ban user.');
await message.reply(`Error: ${msg}`);
}
return;
}
if (command === 'kick') {
if (!canKick) {
await message.reply('You need the Kick Members permission to use this command.');
return;
}
if (!userId) {
await message.reply('Usage: `!kick @user [reason]`');
return;
}
try {
await guild.kick(userId);
const targetUser = message.mentions.find((u) => u.id === userId) ?? { username: 'Unknown' };
const embed = new EmbedBuilder()
.setTitle('User Kicked')
.setColor(0xf39c12)
.addFields(
{ name: 'User', value: `<@${userId}> (${targetUser.username})`, inline: true },
{ name: 'Moderator', value: `${message.author.username}`, inline: true },
)
.setTimestamp();
if (reason) embed.addFields({ name: 'Reason', value: reason });
await message.reply({ embeds: [embed] });
} catch (err) {
const code = err instanceof FluxerError ? err.code : null;
const status = err?.statusCode ?? err?.cause?.statusCode;
const msg =
code === ErrorCodes.MemberNotFound || status === 404
? 'User not found or not in this server.'
: (err?.message ?? 'Failed to kick user.');
await message.reply(`Error: ${msg}`);
}
return;
}
if (command === 'unban') {
if (!canBan) {
await message.reply('You need the Ban Members permission to use this command.');
return;
}
if (!userId) {
await message.reply('Usage: `!unban @user`');
return;
}
try {
await guild.unban(userId);
await message.reply(`Unbanned <@${userId}>.`);
} catch (err) {
const status = err?.statusCode ?? err?.cause?.statusCode;
const msg =
status === 404 ? 'User is not banned.' : (err?.message ?? 'Failed to unban user.');
await message.reply(`Error: ${msg}`);
}
}
});
client.on(Events.Error, (err) => console.error('[fluxer]', err));
try {
await client.login(process.env.FLUXER_BOT_TOKEN);
} catch (err) {
console.error('Login failed:', err);
process.exit(1);
}