first commit
This commit is contained in:
92
commands/misc/pinguser.js
Normal file
92
commands/misc/pinguser.js
Normal file
@ -0,0 +1,92 @@
|
||||
const { Client, Interaction, SlashCommandBuilder } = require("discord.js");
|
||||
|
||||
const cooldowns = new Map();
|
||||
var isDisabled = false;
|
||||
|
||||
/**
|
||||
* Handles the ping user command.
|
||||
* @param {Interaction} interaction - The interaction object.
|
||||
*/
|
||||
async function handlePingCommand(interaction) {
|
||||
const user = interaction.options.getUser("user"); // Get the user from the interaction
|
||||
const times = interaction.options.getInteger("times") || 1; // Default to 1 if not provided
|
||||
|
||||
try {
|
||||
// Ensure the user exists in the guild
|
||||
const userPing = await interaction.guild.members.fetch(user.id);
|
||||
if (!userPing) {
|
||||
await interaction.reply("That user doesn't exist in this server.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Prevent the bot from pinging itself
|
||||
if (userPing.id === interaction.guild.members.me.id) {
|
||||
await interaction.reply("I can't ping myself.");
|
||||
return;
|
||||
}
|
||||
|
||||
// Cooldown logic
|
||||
const coolDown = 24 * 60 * 60 * 1000; // 24 hours in milliseconds
|
||||
const now = Date.now();
|
||||
const lastExec = cooldowns.get(interaction.user.id);
|
||||
|
||||
if (lastExec && now - lastExec < coolDown) {
|
||||
const timeLeft = coolDown - (now - lastExec);
|
||||
|
||||
const days = Math.floor(timeLeft / (1000 * 60 * 60 * 24));
|
||||
const hours = Math.floor((timeLeft % (1000 * 60 * 60 * 24)) / (1000 * 60 * 60));
|
||||
const minutes = Math.floor((timeLeft % (1000 * 60 * 60)) / (1000 * 60));
|
||||
const seconds = Math.floor((timeLeft % (1000 * 60)) / 1000);
|
||||
|
||||
await interaction.reply(
|
||||
`You need to wait ${days} days, ${hours} hours, ${minutes} minutes, and ${seconds} seconds before using this command again.`,
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
// Send the pings
|
||||
await interaction.reply({ content: "Ok, sending pings.", ephemeral: false });
|
||||
|
||||
for (let i = 0; i < times; i++) {
|
||||
await interaction.channel.send(`Pinging ${userPing}`);
|
||||
await new Promise((resolve) => setTimeout(resolve, 300)); // Wait 300ms between pings
|
||||
}
|
||||
|
||||
// Update the cooldown
|
||||
cooldowns.set(interaction.user.id, now);
|
||||
} catch (error) {
|
||||
console.error("There was an error in pinguser: ", error);
|
||||
await interaction.reply({
|
||||
content: "An error occurred while executing the command.",
|
||||
ephemeral: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
data: new SlashCommandBuilder()
|
||||
.setName("pinguser")
|
||||
.setDescription("Ping the mentioned user")
|
||||
.addUserOption((option) =>
|
||||
option.setName("user").setDescription("The user to ping").setRequired(true),
|
||||
)
|
||||
.addIntegerOption((option) =>
|
||||
option
|
||||
.setName("times")
|
||||
.setDescription("Number of times to ping the user")
|
||||
.setRequired(false),
|
||||
),
|
||||
async execute(interaction) {
|
||||
try {
|
||||
if (isDisabled) {
|
||||
return interaction.reply({
|
||||
content: "The command is disabled... Try again later.",
|
||||
ephemeral: true,
|
||||
});
|
||||
}
|
||||
await handlePingCommand(interaction); // Ensure we await this function
|
||||
} catch (error) {
|
||||
console.error("There was an error executing the command: ", error);
|
||||
}
|
||||
},
|
||||
};
|
||||
92
commands/moderation/ban.js
Normal file
92
commands/moderation/ban.js
Normal file
@ -0,0 +1,92 @@
|
||||
const {
|
||||
Client,
|
||||
Interaction,
|
||||
ApplicationCommandOptionType,
|
||||
PermissionFlagsBits,
|
||||
SlashCommandBuilder,
|
||||
} = require("discord.js");
|
||||
|
||||
async function handleBanCommand(interaction) {
|
||||
if (!interaction.member.permissions.has(PermissionFlagsBits.BanMembers)) {
|
||||
await interaction.reply({
|
||||
content: "You do not have permission to ban members.",
|
||||
ephemeral: true,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const targetID = interaction.options.get("user").value;
|
||||
const reason =
|
||||
interaction.options.get("reason")?.value || "No reason provided";
|
||||
|
||||
await interaction.deferReply();
|
||||
const targetUser = await interaction.guild.members.fetch(targetID);
|
||||
|
||||
if (!targetUser) {
|
||||
await interaction.editReply("That user is not in the server");
|
||||
return;
|
||||
}
|
||||
|
||||
if (targetUser.id === interaction.guild.ownerId) {
|
||||
await interaction.editReply("I can't ban the server owner");
|
||||
return;
|
||||
}
|
||||
|
||||
if (targetUser.id === interaction.guild.members.me) {
|
||||
await interaction.editReply("I cant't ban myself");
|
||||
return;
|
||||
}
|
||||
|
||||
const targetUserRolePostion = targetUser.roles.highest.postion; // check the user highest role
|
||||
const requestUserRolePostion = interaction.member.roles.highest.postion; // check the user issuing the command is higher than the target
|
||||
const botRolePostion = interaction.guild.members.me.roles.highest.postion; // check the bot has permissions
|
||||
|
||||
if (targetUserRolePostion >= requestUserRolePostion) {
|
||||
await interaction.editReply(
|
||||
"You can't ban someone that has the same/higher role than you."
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
if (targetUserRolePostion >= botRolePostion) {
|
||||
await interaction.editReply(
|
||||
"I can't ban that user because they have the same/higher role than me."
|
||||
);
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await targetUser.ban({ reason });
|
||||
await interaction.editReply(
|
||||
`User ${targetUser} was banned. Reason: ${reason}`
|
||||
);
|
||||
} catch (error) {
|
||||
console.error("There was an error banning the target: ", error);
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
data: new SlashCommandBuilder()
|
||||
.setName("ban")
|
||||
.setDescription("Bans the specified user")
|
||||
.addUserOption((option) =>
|
||||
option
|
||||
.setName("user")
|
||||
.setDescription("Mention the user to ban")
|
||||
.setRequired(true)
|
||||
)
|
||||
.addStringOption((option) =>
|
||||
option
|
||||
.setName("reason")
|
||||
.setDescription("Specify the reason for banning")
|
||||
.setRequired(false)
|
||||
)
|
||||
.setDefaultMemberPermissions(PermissionFlagsBits.BanMembers),
|
||||
async execute(interaction) {
|
||||
try {
|
||||
handleBanCommand(interaction);
|
||||
} catch (error) {
|
||||
console.error("There was an error in banning: ", error);
|
||||
}
|
||||
},
|
||||
};
|
||||
75
commands/moderation/kick.js
Normal file
75
commands/moderation/kick.js
Normal file
@ -0,0 +1,75 @@
|
||||
const {
|
||||
Client,
|
||||
Interaction,
|
||||
ApplicationCommandOptionType,
|
||||
PermissionFlagsBits,
|
||||
SlashCommandBuilder,
|
||||
} = require("discord.js");
|
||||
|
||||
async function handleKickCommand(interaction) {
|
||||
if (!interaction.member.permissions.has(PermissionFlagsBits.KickMembers)) {
|
||||
await interaction.reply({
|
||||
content: "You do not have permission to kick members.",
|
||||
ephemeral: true,
|
||||
});
|
||||
return;
|
||||
}
|
||||
|
||||
const targetID = interaction.options.get('user').value;
|
||||
const reason = interaction.options.get("reason")?.value || "No reason provided";
|
||||
|
||||
await interaction.deferReply();
|
||||
const targetUser = await interaction.guild.members.fetch(targetID)
|
||||
|
||||
if (!targetUser) {
|
||||
await interaction.editReply('That user does not exist in this server');
|
||||
return;
|
||||
}
|
||||
|
||||
if (targetUser.id === interaction.guild.ownerId) {
|
||||
await interaction.editReply("I can't kick the server owner")
|
||||
return;
|
||||
}
|
||||
|
||||
if (targetUser.id === interaction.guild.members.me) {
|
||||
await interaction.editReply("I can't kick myself")
|
||||
return;
|
||||
}
|
||||
|
||||
const targetUserRolePostion = targetUser.roles.highest.postion;
|
||||
const requestUserRolePostion = interaction.member.roles.highest.postion
|
||||
const botRolePostion = interaction.guild.members.me.roles.highest.postion
|
||||
|
||||
if (targetUserRolePostion >= requestUserRolePostion) {
|
||||
await interaction.editReply("You can't kick someone that has the same/higher role than you")
|
||||
return;
|
||||
}
|
||||
|
||||
if (targetUserRolePostion >= botRolePostion) {
|
||||
await interaction.editReply("I can't kick that user because they have the same/higher role than me.")
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
await targetUser.kick({ reason })
|
||||
await interaction.editReply(`User ${targetUser} was kicked. Reason: ${reason}`)
|
||||
} catch (error) {
|
||||
console.error('There was a problem kicking: ', error)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
data: new SlashCommandBuilder()
|
||||
.setName("kick")
|
||||
.setDescription("Kicks the specified user")
|
||||
.addUserOption((option) => option.setName("user").setDescription("Mention the user to kick").setRequired(true))
|
||||
.addStringOption((option) => option.setName('reason').setDescription('Specify the reason for kicking').setRequired(false))
|
||||
.setDefaultMemberPermissions(PermissionFlagsBits.KickMembers),
|
||||
async execute(interaction) {
|
||||
try {
|
||||
handleKickCommand(interaction)
|
||||
} catch (error) {
|
||||
console.error('There was an error in kicking:', error)
|
||||
}
|
||||
}
|
||||
};
|
||||
132
commands/music/bplay.js
Normal file
132
commands/music/bplay.js
Normal file
@ -0,0 +1,132 @@
|
||||
const { Client, Interaction, SlashCommandBuilder, VoiceChannel } = require('discord.js');
|
||||
const { playFromQueue, queue} = require('../../playback');
|
||||
const ytdl = require('ytdl-core');
|
||||
const { default: axios } = require('axios');
|
||||
const { setStopped, cancelTimer } = require('../../playback')
|
||||
var isDisabled = false
|
||||
|
||||
const API_KEY = process.env.YoutubeToken
|
||||
/**
|
||||
*
|
||||
* @param {Client} client
|
||||
* @param {Interaction} interaction
|
||||
*/
|
||||
|
||||
|
||||
async function addToQueue(interaction, link, songName) {
|
||||
const voiceChannel = interaction.member.voice.channel;
|
||||
const textChannel = interaction.channel;
|
||||
const getMember = interaction.member.displayName;
|
||||
|
||||
const wasQueueEmpty = queue.length === 0;
|
||||
queue.push({interaction, getMember, link, songName})
|
||||
cancelTimer()
|
||||
if (wasQueueEmpty) {
|
||||
await playFromQueue(voiceChannel, textChannel, getMember, link, songName)
|
||||
} else {
|
||||
//console.log(queue)
|
||||
interaction.reply(`Added to queue: ${songName}`)
|
||||
}
|
||||
}
|
||||
|
||||
async function searchYoutubeSong(input) {
|
||||
try {
|
||||
const response = await axios.get('https://www.googleapis.com/youtube/v3/search', {
|
||||
params: {
|
||||
part: 'snippet',
|
||||
q: input,
|
||||
key: API_KEY,
|
||||
maxResults: 1,
|
||||
type: 'video',
|
||||
}
|
||||
});
|
||||
|
||||
if (response.data.items && response.data.items.length > 0) {
|
||||
const video = response.data.items[0];
|
||||
const videoId = video.id.videoId;
|
||||
const videoTitle = video.snippet.title;
|
||||
const videoUrl = `https://www.youtube.com/watch?v=${videoId}`;
|
||||
return { videoUrl, videoTitle}
|
||||
} else {
|
||||
return null;
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error searching Youtube: ', error)
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
async function handlePlayCommand(interaction, input) {
|
||||
const voiceChannel = interaction.member.voice.channel;
|
||||
|
||||
if (!voiceChannel) {
|
||||
return interaction.reply({
|
||||
content: 'You need to be in a voice channel to use this command.',
|
||||
ephemeral: true
|
||||
});
|
||||
}
|
||||
|
||||
try {
|
||||
let link = '';
|
||||
let songName = input;
|
||||
|
||||
if (ytdl.validateURL(input)) {
|
||||
// If it's a valid YouTube URL, extract the song information
|
||||
const videoInfo = await ytdl.getBasicInfo(input);
|
||||
songName = videoInfo.videoDetails.title;
|
||||
link = input;
|
||||
} else {
|
||||
// If it's a search query, find the video
|
||||
const searchResult = await searchYoutubeSong(input);
|
||||
if (searchResult) {
|
||||
link = searchResult.videoUrl;
|
||||
songName = searchResult.videoTitle;
|
||||
} else {
|
||||
return interaction.reply({
|
||||
content: 'No results found for your query.',
|
||||
ephemeral: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
// Add the song to the queue and play if needed
|
||||
await addToQueue(interaction, link, songName);
|
||||
|
||||
} catch (error) {
|
||||
console.error('Error handling play command:', error);
|
||||
await interaction.reply({
|
||||
content: 'An error occurred while processing your request.',
|
||||
ephemeral: true,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
module.exports = {
|
||||
data: new SlashCommandBuilder()
|
||||
.setName('bplay')
|
||||
.setDescription('Plays a song')
|
||||
.addStringOption(option =>
|
||||
option.setName('query')
|
||||
.setDescription('The song name or URL to play')
|
||||
.setRequired(true)
|
||||
),
|
||||
|
||||
async execute(interaction) {
|
||||
try {
|
||||
if (isDisabled) return interaction.reply({ content: 'The command is Disabled... Try again later', ephemeral: true})
|
||||
const query = interaction.options.getString('query');
|
||||
setStopped(false)
|
||||
await handlePlayCommand(interaction, query);
|
||||
} catch (error) {
|
||||
console.error('Error executing play command:', error);
|
||||
await interaction.reply({
|
||||
content: 'An error occurred while processing your request.',
|
||||
ephemeral: true
|
||||
});
|
||||
}
|
||||
}
|
||||
};
|
||||
|
||||
|
||||
36
commands/music/queue.js
Normal file
36
commands/music/queue.js
Normal file
@ -0,0 +1,36 @@
|
||||
const { Client, Interaction, SlashCommandBuilder, EmbedBuilder } = require('discord.js')
|
||||
const { queue } = require('./../../playback')
|
||||
const { musicQueueEmbed } = require('../../embeds/queue');
|
||||
|
||||
async function checkQueue(interaction) {
|
||||
if (!queue || queue.length === 0 ) {
|
||||
interaction.reply('The queue is empty.')
|
||||
return
|
||||
}
|
||||
|
||||
try {
|
||||
const embed = musicQueueEmbed(queue);
|
||||
await interaction.reply({ embeds: [embed] })
|
||||
} catch (error) {
|
||||
console.log('There is an error in the queue command: ', error)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
data: new SlashCommandBuilder()
|
||||
.setName('queue')
|
||||
.setDescription('Check the playback queue'),
|
||||
async execute(interaction) {
|
||||
const voiceChannel = interaction.member.voice.channel
|
||||
const textChannel = interaction.textChannel
|
||||
|
||||
if (!voiceChannel) {
|
||||
return interaction.reply({
|
||||
content: 'You need to be in a voice channel to use that queue',
|
||||
ephemeral: true
|
||||
})
|
||||
}
|
||||
|
||||
await checkQueue(interaction, voiceChannel, textChannel)
|
||||
}
|
||||
}
|
||||
60
commands/music/skip.js
Normal file
60
commands/music/skip.js
Normal file
@ -0,0 +1,60 @@
|
||||
const { Client, Interaction, SlashCommandBuilder } = require('discord.js')
|
||||
|
||||
const { playFromQueue, queue } = require('../../playback');
|
||||
const { getVoiceConnection } = require('@discordjs/voice')
|
||||
|
||||
async function skipSong(voiceChannel, textChannel) {
|
||||
const connection = getVoiceConnection(voiceChannel.guild.id)
|
||||
|
||||
if (!connection) {
|
||||
console.log('No active voice connections')
|
||||
textChannel.send('No active voice connections')
|
||||
return
|
||||
}
|
||||
|
||||
if (!queue || queue.length === 0) {
|
||||
console.log('Queue is empty. No songs to skip')
|
||||
connection.state.subscription.player.stop();
|
||||
return;
|
||||
}
|
||||
|
||||
try {
|
||||
queue.shift()
|
||||
|
||||
if (queue.length > 0 ) {
|
||||
const nextSong = queue[0];
|
||||
await playFromQueue(voiceChannel, textChannel, nextSong.getMember, nextSong.link, nextSong.songName)
|
||||
} else {
|
||||
textChannel.send('No more songs in the queue')
|
||||
}
|
||||
} catch (error) {
|
||||
console.error('Error skipping song: ', error)
|
||||
}
|
||||
}
|
||||
|
||||
module.exports = {
|
||||
data: new SlashCommandBuilder()
|
||||
.setName('skip')
|
||||
.setDescription('Skips a song in the queue'),
|
||||
async execute(interaction) {
|
||||
const voiceChannel = interaction.member.voice.channel
|
||||
const textChannel = interaction.channel
|
||||
if (!voiceChannel) {
|
||||
return interaction.reply({
|
||||
content: 'You need to be in a voice channel to use the command',
|
||||
ephemeral: true
|
||||
});
|
||||
}
|
||||
|
||||
try {
|
||||
await skipSong(voiceChannel, textChannel)
|
||||
interaction.reply('Skipped the current song')
|
||||
} catch (error) {
|
||||
console.error('Error in skip command: ', error)
|
||||
interaction.reply({
|
||||
content: 'An error has occurred while processing the command',
|
||||
ephemeral: true
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
20
commands/music/stop.js
Normal file
20
commands/music/stop.js
Normal file
@ -0,0 +1,20 @@
|
||||
const { SlashCommandBuilder } = require("discord.js");
|
||||
const { resetAll, setStopped } = require("../../playback");
|
||||
|
||||
module.exports = {
|
||||
data: new SlashCommandBuilder()
|
||||
.setName("stop")
|
||||
.setDescription("Stop playback and leave the voice channel"),
|
||||
|
||||
async execute(interaction) {
|
||||
const voiceChannel = interaction.member.voice.channel;
|
||||
if (!voiceChannel) {
|
||||
return interaction.reply({ content: "You need to be in a voice channel to use this command.", ephemeral: true });
|
||||
}
|
||||
|
||||
setStopped(true); // Mark playback as stopped
|
||||
resetAll(voiceChannel.guild.id); // Reset everything for a clean state
|
||||
|
||||
return interaction.reply("Stopped playback and left the voice channel.");
|
||||
},
|
||||
};
|
||||
46
commands/utility/auto-welcome.js
Normal file
46
commands/utility/auto-welcome.js
Normal file
@ -0,0 +1,46 @@
|
||||
const {
|
||||
Client,
|
||||
Interaction,
|
||||
ApplicationCommandOptionType,
|
||||
PermissionFlagsBits,
|
||||
SlashCommandBuilder,
|
||||
} = require("discord.js");
|
||||
const db = require("../../db");
|
||||
|
||||
module.exports = {
|
||||
data: new SlashCommandBuilder()
|
||||
.setName("autowelcome")
|
||||
.setDescription("Enable or disable auto-welcome messages.")
|
||||
.addChannelOption((option) =>
|
||||
option
|
||||
.setName("channel")
|
||||
.setDescription(
|
||||
"Channel Id to send welcome messages (required when enabling)"
|
||||
)
|
||||
.setRequired(false)
|
||||
)
|
||||
.setDefaultMemberPermissions(PermissionFlagsBits.Administrator),
|
||||
|
||||
async execute(interaction) {
|
||||
const channelId = interaction.options.getChannel("channel");
|
||||
const guildId = interaction.guild.id;
|
||||
|
||||
if (channelId) {
|
||||
await db.query(
|
||||
`INSERT INTO auto_welcome (guild_id, channel_id, enabled)
|
||||
VALUES ($1, $2, $3)
|
||||
ON CONFLICT (guild_id) DO UPDATE SET channel_id = $2, enabled = $3`,
|
||||
[guildId, channelId.id, true]
|
||||
);
|
||||
return interaction.reply(
|
||||
`Auto-welcome enabled! Messages will be sent to <#${channelId.id}>.`
|
||||
);
|
||||
} else {
|
||||
await db.query(
|
||||
`UPDATE auto_welcome SET enabled = $1 WHERE guild_id = $2`,
|
||||
[false, guildId]
|
||||
);
|
||||
return interaction.reply("Auto-welcome has been disabled.");
|
||||
}
|
||||
},
|
||||
};
|
||||
17
commands/utility/ping.js
Normal file
17
commands/utility/ping.js
Normal file
@ -0,0 +1,17 @@
|
||||
const { SlashCommandBuilder } = require("discord.js");
|
||||
|
||||
module.exports = {
|
||||
data: new SlashCommandBuilder()
|
||||
.setName("ping")
|
||||
.setDescription("Replies with Pong! and websocket ping"),
|
||||
async execute(interaction) {
|
||||
// Send the initial reply and wait for it to be sent
|
||||
const reply = await interaction.reply({
|
||||
content: "Pong!",
|
||||
fetchReply: true // This ensures we can get the reply object
|
||||
});
|
||||
|
||||
const ping = reply.createdTimestamp - interaction.createdTimestamp; // Calculate the ping
|
||||
await interaction.editReply(`Pong! client ${ping}ms | websocket: ${interaction.client.ws.ping}ms`);
|
||||
},
|
||||
};
|
||||
33
commands/utility/setBluChannel.js
Normal file
33
commands/utility/setBluChannel.js
Normal file
@ -0,0 +1,33 @@
|
||||
const { Client, Interaction, ApplicationCommandOptionType, PermissionFlagsBits, SlashCommandBuilder } = require("discord.js");
|
||||
const db = require("../../db");
|
||||
|
||||
module.exports = {
|
||||
data: new SlashCommandBuilder()
|
||||
.setName("setbluchannel")
|
||||
.setDescription("Set the channel for Blu to send messages.")
|
||||
.addChannelOption((option) =>
|
||||
option
|
||||
.setName("channel")
|
||||
.setDescription("Channel to set for Blu messages")
|
||||
.setRequired(true)
|
||||
)
|
||||
.setDefaultMemberPermissions(PermissionFlagsBits.Administrator),
|
||||
async execute(interaction) {
|
||||
const channelId = interaction.options.getChannel("channel");
|
||||
const guildId = interaction.guild.id;
|
||||
const guildName = interaction.guild.name;
|
||||
const channelName = channelId.name;
|
||||
|
||||
if (channelId) {
|
||||
await db.query(
|
||||
`INSERT INTO bot_channel (guild_id, channel_id, guild_name, channel_name)
|
||||
VALUES ($1, $2, $3, $4)
|
||||
ON CONFLICT (guild_id) DO UPDATE SET Channel_id = $2, guild_name = $3, channel_name = $4`,
|
||||
[guildId, channelId.id, guildName, channelName]
|
||||
);
|
||||
return interaction.reply(`Blu messages will be sent to <#${channelId.id}>.`);
|
||||
} else {
|
||||
return interaction.reply("Please provide a valid channel.");
|
||||
}
|
||||
},
|
||||
}
|
||||
Reference in New Issue
Block a user