@zerrodevs/discord-bot-utils
Version:
A comprehensive utility package for Discord.js bots providing moderation, interaction, logging, and tax calculation features
446 lines (406 loc) • 12.8 kB
JavaScript
const { EmbedUtil } = require('./embed');
const { TaxUtil } = require('../index');
const { ModerationUtil } = require('../index');
const { InteractionUtil } = require('../index');
const { PermissionFlagsBits } = require('discord.js');
class PresetCommands {
static async handlePing(interaction) {
const ping = interaction.client.ws.ping;
const embed = EmbedUtil.createInfoEmbed('🏓 Pong!', `Latency: ${ping}ms`);
return interaction.reply({ embeds: [embed] });
}
static async handleAvatar(interaction) {
const user = interaction.options.getUser('user') || interaction.user;
const embed = EmbedUtil.createCustomEmbed({
title: `${user.username}'s Avatar`,
image: user.displayAvatarURL({ dynamic: true, size: 4096 }),
color: '#00ff00'
});
return interaction.reply({ embeds: [embed] });
}
static async handleKick(interaction) {
const member = interaction.options.getMember('user');
const reason = interaction.options.getString('reason') || 'No reason provided';
if (!interaction.member.permissions.has(PermissionFlagsBits.KickMembers)) {
return interaction.reply({
embeds: [EmbedUtil.createErrorEmbed('You do not have permission to kick members!')],
ephemeral: true
});
}
if (!member.kickable) {
return interaction.reply({
embeds: [EmbedUtil.createErrorEmbed('I cannot kick this user!')],
ephemeral: true
});
}
await member.kick(reason);
return interaction.reply({
embeds: [EmbedUtil.createSuccessEmbed(`Successfully kicked ${member.user.tag}\nReason: ${reason}`)]
});
}
static async handleBan(interaction) {
const user = interaction.options.getUser('user');
const reason = interaction.options.getString('reason') || 'No reason provided';
const days = interaction.options.getInteger('days') || 0;
if (!interaction.member.permissions.has(PermissionFlagsBits.BanMembers)) {
return interaction.reply({
embeds: [EmbedUtil.createErrorEmbed('You do not have permission to ban members!')],
ephemeral: true
});
}
try {
await interaction.guild.members.ban(user, { reason, deleteMessageDays: days });
return interaction.reply({
embeds: [EmbedUtil.createSuccessEmbed(`Successfully banned ${user.tag}\nReason: ${reason}`)]
});
} catch (error) {
return interaction.reply({
embeds: [EmbedUtil.createErrorEmbed('Failed to ban the user!')],
ephemeral: true
});
}
}
static async handleShortLink(interaction) {
const url = interaction.options.getString('url');
try {
const response = await fetch('https://tinyurl.com/api-create.php?url=' + encodeURIComponent(url));
const shortUrl = await response.text();
return interaction.reply({
embeds: [EmbedUtil.createSuccessEmbed(`Original URL: ${url}\nShortened URL: ${shortUrl}`)]
});
} catch (error) {
return interaction.reply({
embeds: [EmbedUtil.createErrorEmbed('Failed to shorten the URL!')],
ephemeral: true
});
}
}
static async handleTax(interaction, options = { userDefined: false, fixedRate: 15 }) {
const amount = interaction.options.getNumber('amount');
const taxRate = options.userDefined ? interaction.options.getNumber('tax_rate') : options.fixedRate;
const displayType = interaction.options.getString('display') || 'embed';
const taxInfo = TaxUtil.calculateTax(amount, taxRate);
if (displayType === 'message') {
return interaction.reply(TaxUtil.createTaxMessageResponse(taxInfo));
} else {
return interaction.reply({ embeds: [TaxUtil.createTaxEmbed(taxInfo)] });
}
}
static async handleTimeout(interaction) {
const member = interaction.options.getMember('user');
const duration = interaction.options.getString('duration');
const reason = interaction.options.getString('reason') || 'No reason provided';
if (!ModerationUtil.validateModPermissions(interaction.member, PermissionFlagsBits.ModerateMembers)) {
return interaction.reply({
embeds: [EmbedUtil.createErrorEmbed('You do not have permission to timeout members!')],
ephemeral: true
});
}
const parsedDuration = ModerationUtil.parseDuration(duration);
if (!parsedDuration) {
return interaction.reply({
embeds: [EmbedUtil.createErrorEmbed('Invalid duration format! Use 1s, 1m, 1h, or 1d')],
ephemeral: true
});
}
const success = await ModerationUtil.timeout(member, parsedDuration, reason);
if (success) {
return interaction.reply({
embeds: [EmbedUtil.createSuccessEmbed(`Successfully timed out ${member.user.tag} for ${duration}\nReason: ${reason}`)]
});
} else {
return interaction.reply({
embeds: [EmbedUtil.createErrorEmbed('Failed to timeout the user!')],
ephemeral: true
});
}
}
static async handleClear(interaction) {
const amount = interaction.options.getInteger('amount');
const user = interaction.options.getUser('user');
const contains = interaction.options.getString('contains');
if (!ModerationUtil.validateModPermissions(interaction.member, PermissionFlagsBits.ManageMessages)) {
return interaction.reply({
embeds: [EmbedUtil.createErrorEmbed('You do not have permission to manage messages!')],
ephemeral: true
});
}
const filter = {
user: user || null,
contains: contains || null
};
const deleted = await ModerationUtil.clearMessages(interaction.channel, amount, filter);
return interaction.reply({
embeds: [EmbedUtil.createSuccessEmbed(`Successfully deleted ${deleted} messages`)],
ephemeral: true
});
}
static async handleRoleInfo(interaction) {
const role = interaction.options.getRole('role');
try {
const roleInfo = await InteractionUtil.getRoleInfo(role);
const embed = InteractionUtil.createRoleInfoEmbed(roleInfo);
return interaction.reply({ embeds: [embed] });
} catch (error) {
return interaction.reply({
embeds: [EmbedUtil.createErrorEmbed('Failed to fetch role information!')],
ephemeral: true
});
}
}
static async handlePoll(interaction) {
const question = interaction.options.getString('question');
const optionsString = interaction.options.getString('options') || 'Yes,No';
const options = optionsString.split(',').map(opt => opt.trim());
if (options.length > 10) {
return interaction.reply({
embeds: [EmbedUtil.createErrorEmbed('Maximum 10 options allowed!')],
ephemeral: true
});
}
const poll = InteractionUtil.createPoll(question, options);
const message = await interaction.reply({
embeds: [poll.embed],
components: poll.components,
fetchReply: true
});
const votes = new Map();
const userVotes = new Map();
const collector = message.createMessageComponentCollector({ time: 24 * 60 * 60 * 1000 }); // 24 hours
collector.on('collect', async i => {
const optionIndex = parseInt(i.customId.split('_')[1]);
// Remove previous vote if exists
if (userVotes.has(i.user.id)) {
const previousVote = userVotes.get(i.user.id);
votes.set(previousVote, (votes.get(previousVote) || 1) - 1);
}
// Add new vote
votes.set(optionIndex, (votes.get(optionIndex) || 0) + 1);
userVotes.set(i.user.id, optionIndex);
const updated = InteractionUtil.updatePollResults(i, votes);
await i.update({
embeds: [updated.embed],
components: updated.components
});
});
}
static async handleSlowmode(interaction) {
const duration = interaction.options.getString('duration');
if (!ModerationUtil.validateModPermissions(interaction.member, PermissionFlagsBits.ManageChannels)) {
return interaction.reply({
embeds: [EmbedUtil.createErrorEmbed('You do not have permission to manage channels!')],
ephemeral: true
});
}
const parsedDuration = ModerationUtil.parseDuration(duration);
if (!parsedDuration) {
return interaction.reply({
embeds: [EmbedUtil.createErrorEmbed('Invalid duration format! Use 1s, 1m, 1h, or 1d')],
ephemeral: true
});
}
const success = await ModerationUtil.setSlowmode(interaction.channel, parsedDuration);
if (success) {
return interaction.reply({
embeds: [EmbedUtil.createSuccessEmbed(`Set slowmode to ${duration}`)]
});
} else {
return interaction.reply({
embeds: [EmbedUtil.createErrorEmbed('Failed to set slowmode!')],
ephemeral: true
});
}
}
static getPresetCommands() {
return [
{
name: 'ping',
description: 'Check bot latency'
},
{
name: 'avatar',
description: 'Get user avatar',
options: [{
name: 'user',
type: 6, // USER type
description: 'The user to get avatar for',
required: false
}]
},
{
name: 'kick',
description: 'Kick a member',
options: [
{
name: 'user',
type: 6,
description: 'The user to kick',
required: true
},
{
name: 'reason',
type: 3, // STRING type
description: 'Reason for kick',
required: false
}
]
},
{
name: 'ban',
description: 'Ban a user',
options: [
{
name: 'user',
type: 6,
description: 'The user to ban',
required: true
},
{
name: 'reason',
type: 3,
description: 'Reason for ban',
required: false
},
{
name: 'days',
type: 4, // INTEGER type
description: 'Number of days of messages to delete',
required: false,
choices: [
{ name: 'None', value: 0 },
{ name: '1 day', value: 1 },
{ name: '7 days', value: 7 }
]
}
]
},
{
name: 'shortlink',
description: 'Shorten a URL',
options: [{
name: 'url',
type: 3,
description: 'The URL to shorten',
required: true
}]
},
{
name: 'tax',
description: 'Calculate tax on an amount',
options: [
{
name: 'amount',
type: 10, // NUMBER type
description: 'The amount to calculate tax on',
required: true
},
{
name: 'tax_rate',
type: 10,
description: 'Custom tax rate percentage',
required: false
},
{
name: 'display',
type: 3, // STRING type
description: 'Display style (embed/message)',
required: false,
choices: [
{ name: 'Embed', value: 'embed' },
{ name: 'Message', value: 'message' }
]
}
]
},
{
name: 'timeout',
description: 'Timeout a user',
options: [
{
name: 'user',
type: 6,
description: 'The user to timeout',
required: true
},
{
name: 'duration',
type: 3,
description: 'Duration (1s, 1m, 1h, 1d)',
required: true
},
{
name: 'reason',
type: 3,
description: 'Reason for timeout',
required: false
}
]
},
{
name: 'clear',
description: 'Clear messages',
options: [
{
name: 'amount',
type: 4,
description: 'Number of messages to delete',
required: true
},
{
name: 'user',
type: 6,
description: 'Filter messages by user',
required: false
},
{
name: 'contains',
type: 3,
description: 'Filter messages containing text',
required: false
}
]
},
{
name: 'slowmode',
description: 'Set channel slowmode',
options: [
{
name: 'duration',
type: 3,
description: 'Duration (1s, 1m, 1h, 1d)',
required: true
}
]
},
{
name: 'roleinfo',
description: 'Get information about a role',
options: [{
name: 'role',
type: 8, // ROLE type
description: 'The role to get information about',
required: true
}]
},
{
name: 'poll',
description: 'Create a poll',
options: [
{
name: 'question',
type: 3,
description: 'The poll question',
required: true
},
{
name: 'options',
type: 3,
description: 'Comma-separated options (max 10)',
required: false
}
]
}
];
}
}
module.exports = PresetCommands;