diff --git a/.gitignore b/.gitignore index 4b5383a16..a905e1f96 100644 --- a/.gitignore +++ b/.gitignore @@ -7,4 +7,4 @@ /prisma/migrations /prisma/lavamusic.db .env -package-lock.json \ No newline at end of file +package-lock.json diff --git a/package.json b/package.json index 1dcc6f41e..626f9d33e 100644 --- a/package.json +++ b/package.json @@ -42,12 +42,12 @@ "homepage": "https://github.com/appujet/lavamusic#readme", "devDependencies": { "@biomejs/biome": "^1.8.3", - "@types/node": "^20.14.9", + "@types/node": "^20.14.10", "@types/signale": "^1.4.7", "lint-staged": "^15.2.7", "prisma": "^5.16.1", "ts-node": "^10.9.2", - "typescript": "^5.5.2" + "typescript": "^5.5.3" }, "dependencies": { "@prisma/client": "^5.16.1", diff --git a/src/LavaClient.ts b/src/LavaClient.ts index b0250529d..b1a639b88 100644 --- a/src/LavaClient.ts +++ b/src/LavaClient.ts @@ -1,15 +1,11 @@ import { type ClientOptions, GatewayIntentBits } from "discord.js"; - import config from "./config.js"; import Lavamusic from "./structures/Lavamusic.js"; - const { GuildMembers, MessageContent, GuildVoiceStates, GuildMessages, Guilds, GuildMessageTyping } = GatewayIntentBits; - const clientOptions: ClientOptions = { intents: [Guilds, GuildMessages, MessageContent, GuildVoiceStates, GuildMembers, GuildMessageTyping], allowedMentions: { parse: ["users", "roles"], repliedUser: false }, }; - const client = new Lavamusic(clientOptions); client.start(config.token); diff --git a/src/commands/config/247.ts b/src/commands/config/247.ts index 3ebcfdbb3..decde7b87 100644 --- a/src/commands/config/247.ts +++ b/src/commands/config/247.ts @@ -1,5 +1,4 @@ import type { GuildMember } from "discord.js"; - import { Command, type Context, type Lavamusic } from "../../structures/index.js"; export default class _247 extends Command { @@ -34,17 +33,14 @@ export default class _247 extends Command { public async run(client: Lavamusic, ctx: Context): Promise { const embed = client.embed(); let player = client.shoukaku.players.get(ctx.guild.id) as any; - try { const data = await client.db.get_247(ctx.guild.id); const member = ctx.member as GuildMember; - if (!member.voice.channel) { return await ctx.sendMessage({ embeds: [embed.setDescription("You need to be in a voice channel to use this command.").setColor(client.color.red)], }); } - if (data) { await client.db.delete_247(ctx.guild.id); return await ctx.sendMessage({ @@ -61,10 +57,16 @@ export default class _247 extends Command { ); } return await ctx.sendMessage({ - embeds: [embed.setDescription("**24/7 mode has been enabled**").setColor(client.color.main)], + embeds: [ + embed + .setDescription( + "**24/7 mode has been enabled. The bot will not leave the voice channel even if there are no people in the voice channel.**", + ) + .setColor(client.color.main), + ], }); } catch (error) { - console.error("Error in 24/7 command:", error); + console.error("Error in 247 command:", error); return await ctx.sendMessage({ embeds: [embed.setDescription("An error occurred while trying to execute this command.").setColor(client.color.red)], }); diff --git a/src/commands/config/Dj.ts b/src/commands/config/Dj.ts index f4ccb1467..dd1a20757 100644 --- a/src/commands/config/Dj.ts +++ b/src/commands/config/Dj.ts @@ -1,5 +1,4 @@ //TODO - import { Command, type Context, type Lavamusic } from "../../structures/index.js"; export default class Dj extends Command { @@ -67,6 +66,7 @@ export default class Dj extends Command { ], }); } + public async run(client: Lavamusic, ctx: Context, args: string[]): Promise { let subCommand: string; let role: any; @@ -84,60 +84,60 @@ export default class Dj extends Command { if (subCommand === "add") { if (!role) return await ctx.sendMessage({ - embeds: [embed.setDescription("Please provide a role to add")], + embeds: [embed.setDescription("Please provide a role to add.")], }); const isExRole = await client.db.getRoles(ctx.guild.id).then((r) => r.find((re) => re.roleId === role.id)); if (isExRole) return await ctx.sendMessage({ - embeds: [embed.setDescription(`The dj role <@&${role.id}> is already added`)], + embeds: [embed.setDescription(`The dj role <@&${role.id}> is already added.`)], }); client.db.addRole(ctx.guild.id, role.id); client.db.setDj(ctx.guild.id, true); return await ctx.sendMessage({ - embeds: [embed.setDescription(`The dj role <@&${role.id}> has been added`)], + embeds: [embed.setDescription(`The dj role <@&${role.id}> has been added.`)], }); } if (subCommand === "remove") { if (!role) return await ctx.sendMessage({ - embeds: [embed.setDescription("Please provide a role to remove")], + embeds: [embed.setDescription("Please provide a role to remove.")], }); const isExRole = await client.db.getRoles(ctx.guild.id).then((r) => r.find((re) => re.roleId === role.id)); if (!isExRole) return await ctx.sendMessage({ - embeds: [embed.setDescription(`The dj role <@&${role.id}> is not added`)], + embeds: [embed.setDescription(`The dj role <@&${role.id}> is not added.`)], }); client.db.removeRole(ctx.guild.id, role.id); return await ctx.sendMessage({ - embeds: [embed.setDescription(`The dj role <@&${role.id}> has been removed`)], + embeds: [embed.setDescription(`The dj role <@&${role.id}> has been removed.`)], }); } if (subCommand === "clear") { if (!dj) return await ctx.sendMessage({ - embeds: [embed.setDescription("There are no dj roles to clear")], + embeds: [embed.setDescription("The dj role is already empty.")], }); client.db.clearRoles(ctx.guild.id); return await ctx.sendMessage({ - embeds: [embed.setDescription("All dj roles have been removed")], + embeds: [embed.setDescription("All dj roles have been removed.")], }); } if (subCommand === "toggle") { if (!dj) return await ctx.sendMessage({ - embeds: [embed.setDescription("There are no dj roles to toggle")], + embeds: [embed.setDescription("The dj role is empty.")], }); const data = await client.db.getDj(ctx.guild.id); if (data) { client.db.setDj(ctx.guild.id, !data.mode); return await ctx.sendMessage({ - embeds: [embed.setDescription(`The dj mode has been toggled to ${data.mode ? "disabled" : "enabled"}`)], + embeds: [embed.setDescription(`The dj mode has been toggled to ${data.mode ? "disabled." : "enabled."}`)], }); } } else { return await ctx.sendMessage({ embeds: [ - embed.setDescription("Please provide a valid subcommand").addFields({ + embed.setDescription("Please provide a valid subcommand.").addFields({ name: "Subcommands", value: "`add`, `remove`, `clear`, `toggle`", }), diff --git a/src/commands/config/Prefix.ts b/src/commands/config/Prefix.ts index 352300dbc..4af7eb4c2 100644 --- a/src/commands/config/Prefix.ts +++ b/src/commands/config/Prefix.ts @@ -55,7 +55,6 @@ export default class Prefix extends Command { const isInteraction = ctx.isInteraction; let subCommand = ""; let prefix = ""; - if (isInteraction) { subCommand = ctx.interaction.options.data[0].name; prefix = ctx.interaction.options.data[0].options[0]?.value.toString(); @@ -63,7 +62,6 @@ export default class Prefix extends Command { subCommand = args[0] || ""; prefix = args[1] || ""; } - switch (subCommand) { case "set": { if (!prefix) { @@ -71,24 +69,20 @@ export default class Prefix extends Command { embed.setDescription(`The prefix for this server is \`${currentPrefix}\``); return await ctx.sendMessage({ embeds: [embed] }); } - if (prefix.length > 3) { embed.setDescription("The prefix cannot be longer than 3 characters."); return await ctx.sendMessage({ embeds: [embed] }); } - client.db.setPrefix(guildId, prefix); embed.setDescription(`The prefix for this server is now \`${prefix}\``); return await ctx.sendMessage({ embeds: [embed] }); } - case "reset": { const defaultPrefix = client.config.prefix; client.db.setPrefix(guildId, defaultPrefix); embed.setDescription(`The prefix for this server is now \`${defaultPrefix}\``); return await ctx.sendMessage({ embeds: [embed] }); } - default: { const currentPrefix = guildData ? guildData.prefix : client.config.prefix; embed.setDescription(`The prefix for this server is \`${currentPrefix}\``); diff --git a/src/commands/config/Setup.ts b/src/commands/config/Setup.ts index 1e27d7f23..9c4896740 100644 --- a/src/commands/config/Setup.ts +++ b/src/commands/config/Setup.ts @@ -1,5 +1,4 @@ import { ChannelType, OverwriteType, PermissionFlagsBits } from "discord.js"; - import { Command, type Context, type Lavamusic } from "../../structures/index.js"; import { getButtons } from "../../utils/Buttons.js"; @@ -51,7 +50,6 @@ export default class Setup extends Command { public async run(client: Lavamusic, ctx: Context, args: string[]): Promise { const subCommand = ctx.isInteraction ? ctx.interaction.options.data[0].name : args[0]; const embed = client.embed().setColor(client.color.main); - switch (subCommand) { case "create": { const data = await client.db.getSetup(ctx.guild.id); @@ -59,17 +57,16 @@ export default class Setup extends Command { return await ctx.sendMessage({ embeds: [ { - description: "The song request channel already exists", + description: "The song request channel already exists.", color: client.color.red, }, ], }); } - const textChannel = await ctx.guild.channels.create({ name: `${this.client.user.username}-song-requests`, type: ChannelType.GuildText, - topic: "Song requests for the music bot", + topic: "Song requests for the music bot.", permissionOverwrites: [ { type: OverwriteType.Member, @@ -92,91 +89,80 @@ export default class Setup extends Command { }, ], }); - const player = this.client.queue.get(ctx.guild.id); const image = this.client.config.links.img; const desc = player?.queue && player.current ? `[${player.current.info.title}](${player.current.info.uri})` - : "Nothing playing right now"; - + : "Nothing playing right now."; embed.setDescription(desc).setImage(image); await textChannel.send({ embeds: [embed], components: getButtons(player) }).then((msg) => { client.db.setSetup(ctx.guild.id, textChannel.id, msg.id); }); - await ctx.sendMessage({ embeds: [ { - description: `The song request channel has been created in <#${textChannel.id}>`, + description: `The song request channel has been created in <#${textChannel.id}>.`, color: client.color.main, }, ], }); - break; } - case "delete": { const data2 = await client.db.getSetup(ctx.guild.id); if (!data2) { return await ctx.sendMessage({ embeds: [ { - description: "The song request channel doesn't exist", + description: "The song request channel doesn't exist.", color: client.color.red, }, ], }); } - client.db.deleteSetup(ctx.guild.id); const textChannel = ctx.guild.channels.cache.get(data2.textId); if (textChannel) await textChannel.delete().catch(() => {}); - await ctx.sendMessage({ embeds: [ { - description: "The song request channel has been deleted", + description: + "The song request channel has been deleted. If the channel is not deleted normally, please delete it yourself.", color: client.color.main, }, ], }); - break; } - case "info": { const data3 = await client.db.getSetup(ctx.guild.id); if (!data3) { return await ctx.sendMessage({ embeds: [ { - description: "The song request channel doesn't exist", + description: "The song request channel doesn't exist.", color: client.color.red, }, ], }); } - const channel = ctx.guild.channels.cache.get(data3.textId); if (channel) { - embed.setDescription(`The song request channel is <#${channel.id}>`); + embed.setDescription(`The song request channel is <#${channel.id}>.`); await ctx.sendMessage({ embeds: [embed] }); } else { await ctx.sendMessage({ embeds: [ { - description: "The song request channel doesn't exist", + description: "The song request channel doesn't exist.", color: client.color.red, }, ], }); } - break; } - default: break; } diff --git a/src/commands/dev/Eval.ts b/src/commands/dev/Eval.ts index 98b4f7447..d4e5a9e06 100644 --- a/src/commands/dev/Eval.ts +++ b/src/commands/dev/Eval.ts @@ -1,7 +1,6 @@ import util from "node:util"; import { ActionRowBuilder, ButtonBuilder, ButtonStyle } from "discord.js"; import { fetch } from "undici"; - import { Command, type Context, type Lavamusic } from "../../structures/index.js"; export default class Eval extends Command { @@ -37,14 +36,10 @@ export default class Eval extends Command { const code = args.join(" "); try { let evaled = eval(code); - if (evaled === client.config) evaled = "Nice try"; - const button = new ButtonBuilder().setStyle(ButtonStyle.Danger).setLabel("Delete").setCustomId("eval-delete"); const row = new ActionRowBuilder().addComponents(button); - if (typeof evaled !== "string") evaled = util.inspect(evaled); - if (evaled.length > 2000) { const response = await fetch("https://hasteb.in/post", { method: "POST", @@ -53,7 +48,6 @@ export default class Eval extends Command { }, body: evaled, }); - const json: any = await response.json(); evaled = `https://hasteb.in/${json.key}`; return await ctx.sendMessage({ @@ -64,13 +58,11 @@ export default class Eval extends Command { content: `\`\`\`js\n${evaled}\n\`\`\``, components: [row], }); - const filter = (i: any): boolean => i.customId === "eval-delete" && i.user.id === ctx.author.id; const collector = msg.createMessageComponentCollector({ time: 60000, filter: filter, }); - collector.on("collect", async (i) => { await i.deferUpdate(); await msg.delete(); diff --git a/src/commands/dev/GuildLeave.ts b/src/commands/dev/GuildLeave.ts index 6377983c5..f7c6a693f 100644 --- a/src/commands/dev/GuildLeave.ts +++ b/src/commands/dev/GuildLeave.ts @@ -32,9 +32,7 @@ export default class GuildLeave extends Command { public async run(_client: Lavamusic, ctx: Context, args: string[]): Promise { const guildId = args[0]; const guild = this.client.guilds.cache.get(guildId); - - if (!guild) return await ctx.sendMessage("Guild not found"); - + if (!guild) return await ctx.sendMessage("Guild not found."); try { await guild.leave(); ctx.sendMessage(`Left guild ${guild.name}`); diff --git a/src/commands/dev/GuildList.ts b/src/commands/dev/GuildList.ts index 97ef57ebd..dba4a21e4 100644 --- a/src/commands/dev/GuildList.ts +++ b/src/commands/dev/GuildList.ts @@ -32,7 +32,6 @@ export default class GuildList extends Command { public async run(client: Lavamusic, ctx: Context): Promise { const guilds = this.client.guilds.cache.map((guild) => `- **${guild.name}** - (${guild.id})`); const chunks = client.utils.chunk(guilds, 10) || [[]]; - const pages = chunks.map((chunk, index) => { return this.client .embed() @@ -40,7 +39,6 @@ export default class GuildList extends Command { .setDescription(chunk.join("\n")) .setFooter({ text: `Page ${index + 1} of ${chunks.length}` }); }); - await client.utils.paginate(ctx, pages); } } diff --git a/src/commands/filters/8d.ts b/src/commands/filters/8d.ts index 03fb5b34d..af114ca4c 100644 --- a/src/commands/filters/8d.ts +++ b/src/commands/filters/8d.ts @@ -31,18 +31,15 @@ export default class _8d extends Command { public async run(client: Lavamusic, ctx: Context): Promise { const player = client.queue.get(ctx.guild.id); - const filterEnabled = player.filters.includes("8D"); const rotationConfig = filterEnabled ? {} : { rotationHz: 0.2 }; - player.player.setRotation(rotationConfig); - if (filterEnabled) { player.filters = player.filters.filter((filter) => filter !== "8D"); ctx.sendMessage({ embeds: [ { - description: "8D filter has been disabled", + description: "8D filter has been disabled.", color: client.color.main, }, ], @@ -52,7 +49,7 @@ export default class _8d extends Command { ctx.sendMessage({ embeds: [ { - description: "8D filter has been enabled", + description: "8D filter has been enabled.", color: client.color.main, }, ], diff --git a/src/commands/filters/BassBoost.ts b/src/commands/filters/BassBoost.ts index a308d3e35..29d452204 100644 --- a/src/commands/filters/BassBoost.ts +++ b/src/commands/filters/BassBoost.ts @@ -22,7 +22,7 @@ export default class BassBoost extends Command { permissions: { dev: false, client: ["SendMessages", "ViewChannel", "EmbedLinks"], - user: ["ManageGuild"], + user: [], }, slashCommand: true, options: [], @@ -31,16 +31,14 @@ export default class BassBoost extends Command { public async run(client: Lavamusic, ctx: Context): Promise { const player = client.queue.get(ctx.guild.id); - const filterEnabled = player.filters.includes("bassboost"); - if (filterEnabled) { player.player.setEqualizer([]); player.filters = player.filters.filter((filter) => filter !== "bassboost"); ctx.sendMessage({ embeds: [ { - description: "Bassboost filter has been disabled", + description: "Bassboost filter has been disabled.", color: client.color.main, }, ], @@ -56,7 +54,7 @@ export default class BassBoost extends Command { ctx.sendMessage({ embeds: [ { - description: "Bassboost filter has been enabled", + description: "Bassboost filter has been enabled. **Be careful, listening too loudly can damage your hearing!**", color: client.color.main, }, ], diff --git a/src/commands/filters/Distorsion.ts b/src/commands/filters/Distorsion.ts index 3ce39290f..25b8787e5 100644 --- a/src/commands/filters/Distorsion.ts +++ b/src/commands/filters/Distorsion.ts @@ -10,7 +10,7 @@ export default class Distorsion extends Command { usage: "distorsion", }, category: "filters", - aliases: ["distortion"], + aliases: ["dt"], cooldown: 3, args: false, player: { @@ -22,7 +22,7 @@ export default class Distorsion extends Command { permissions: { dev: false, client: ["SendMessages", "ViewChannel", "EmbedLinks"], - user: ["ManageGuild"], + user: [], }, slashCommand: true, options: [], @@ -31,16 +31,14 @@ export default class Distorsion extends Command { public async run(client: Lavamusic, ctx: Context): Promise { const player = client.queue.get(ctx.guild.id); - const filterEnabled = player.filters.includes("distorsion"); - if (filterEnabled) { player.player.setDistortion({}); player.filters = player.filters.filter((filter) => filter !== "distorsion"); ctx.sendMessage({ embeds: [ { - description: "Distorsion filter has been disabled", + description: "Distorsion filter has been disabled.", color: client.color.main, }, ], @@ -60,7 +58,7 @@ export default class Distorsion extends Command { ctx.sendMessage({ embeds: [ { - description: "Distorsion filter has been enabled", + description: "Distorsion filter has been enabled.", color: client.color.main, }, ], diff --git a/src/commands/filters/Karaoke.ts b/src/commands/filters/Karaoke.ts index ddf12d271..131e22694 100644 --- a/src/commands/filters/Karaoke.ts +++ b/src/commands/filters/Karaoke.ts @@ -22,7 +22,7 @@ export default class Karaoke extends Command { permissions: { dev: false, client: ["SendMessages", "ViewChannel", "EmbedLinks"], - user: ["ManageGuild"], + user: [], }, slashCommand: true, options: [], @@ -31,16 +31,14 @@ export default class Karaoke extends Command { public async run(client: Lavamusic, ctx: Context): Promise { const player = client.queue.get(ctx.guild.id); - const filterEnabled = player.filters.includes("karaoke"); - if (filterEnabled) { player.player.setKaraoke(); player.filters = player.filters.filter((filter) => filter !== "karaoke"); ctx.sendMessage({ embeds: [ { - description: "Karaoke filter has been disabled", + description: "Karaoke filter has been disabled.", color: client.color.main, }, ], @@ -56,7 +54,7 @@ export default class Karaoke extends Command { ctx.sendMessage({ embeds: [ { - description: "Karaoke filter has been enabled", + description: "Karaoke filter has been enabled.", color: client.color.main, }, ], diff --git a/src/commands/filters/NightCore.ts b/src/commands/filters/NightCore.ts index 039fa4c11..1f0273fbe 100644 --- a/src/commands/filters/NightCore.ts +++ b/src/commands/filters/NightCore.ts @@ -31,27 +31,25 @@ export default class NightCore extends Command { public async run(client: Lavamusic, ctx: Context): Promise { const player = client.queue.get(ctx.guild.id); - const filterEnabled = player.filters.includes("nightcore"); - if (filterEnabled) { player.player.setTimescale(); player.filters = player.filters.filter((filter) => filter !== "nightcore"); ctx.sendMessage({ embeds: [ { - description: "Nightcore filter has been disabled", + description: "Nightcore filter has been disabled.", color: client.color.main, }, ], }); } else { - player.player.setTimescale({ speed: 1.165, pitch: 1.125, rate: 1.05 }); + player.player.setTimescale({ speed: 1.2, pitch: 1.2, rate: 1.0 }); player.filters.push("nightcore"); ctx.sendMessage({ embeds: [ { - description: "Nightcore filter has been enabled", + description: "Nightcore filter has been enabled.", color: client.color.main, }, ], diff --git a/src/commands/filters/Pitch.ts b/src/commands/filters/Pitch.ts index b62aebced..90bc001cb 100644 --- a/src/commands/filters/Pitch.ts +++ b/src/commands/filters/Pitch.ts @@ -22,13 +22,13 @@ export default class Pitch extends Command { permissions: { dev: false, client: ["SendMessages", "ViewChannel", "EmbedLinks"], - user: ["ManageGuild"], + user: [], }, slashCommand: true, options: [ { name: "number", - description: "The number you want to set the pitch to (between 1 and 5)", + description: "The number you want to set the pitch to (between 0.5 and 5)", type: 3, required: true, }, @@ -38,29 +38,24 @@ export default class Pitch extends Command { public async run(client: Lavamusic, ctx: Context, args: string[]): Promise { const player = client.queue.get(ctx.guild.id); - const numberString = args[0].replace(",", "."); - const isValidNumber = /^[0-9]*\.?[0-9]+$/.test(numberString); const number = parseFloat(numberString); - - if (!isValidNumber || isNaN(number) || number < 1 || number > 5) { + if (!isValidNumber || isNaN(number) || number < 0.5 || number > 5) { return await ctx.sendMessage({ embeds: [ { - description: "Please provide a valid number between 1 and 5", + description: "Please provide a valid number between 0.5 and 5.", color: this.client.color.red, }, ], }); } - - player.player.setTimescale({ pitch: number, rate: 1, speed: 1 }); - + player.player.setTimescale({ pitch: number }); return await ctx.sendMessage({ embeds: [ { - description: `Pitch has been set to ${number}`, + description: `Pitch has been set to ${number}.`, color: this.client.color.main, }, ], diff --git a/src/commands/filters/Reset.ts b/src/commands/filters/Reset.ts index 998e349d8..56f496f9d 100644 --- a/src/commands/filters/Reset.ts +++ b/src/commands/filters/Reset.ts @@ -22,7 +22,7 @@ export default class Reset extends Command { permissions: { dev: false, client: ["SendMessages", "ViewChannel", "EmbedLinks"], - user: ["ManageGuild"], + user: [], }, slashCommand: true, options: [], @@ -31,14 +31,12 @@ export default class Reset extends Command { public async run(client: Lavamusic, ctx: Context): Promise { const player = client.queue.get(ctx.guild.id); - player.player.clearFilters(); player.filters = []; - return await ctx.sendMessage({ embeds: [ { - description: "Filters have been reset", + description: "Filters have been reset.", color: client.color.main, }, ], diff --git a/src/commands/filters/Rotation.ts b/src/commands/filters/Rotation.ts index 8e1fbb305..e29192c39 100644 --- a/src/commands/filters/Rotation.ts +++ b/src/commands/filters/Rotation.ts @@ -22,7 +22,7 @@ export default class Rotation extends Command { permissions: { dev: false, client: ["SendMessages", "ViewChannel", "EmbedLinks"], - user: ["ManageGuild"], + user: [], }, slashCommand: true, options: [], @@ -32,14 +32,13 @@ export default class Rotation extends Command { // biome-ignore lint/suspicious/useAwait: public async run(client: Lavamusic, ctx: Context): Promise { const player = client.queue.get(ctx.guild.id); - if (player.filters.includes("rotation")) { player.player.setRotation(); player.filters.splice(player.filters.indexOf("rotation"), 1); ctx.sendMessage({ embeds: [ { - description: "Rotation filter has been disabled", + description: "Rotation filter has been disabled.", color: client.color.main, }, ], @@ -50,7 +49,7 @@ export default class Rotation extends Command { ctx.sendMessage({ embeds: [ { - description: "Rotation filter has been enabled", + description: "Rotation filter has been enabled.", color: client.color.main, }, ], diff --git a/src/commands/filters/Speed.ts b/src/commands/filters/Speed.ts index 3e58367a9..cc33a9176 100644 --- a/src/commands/filters/Speed.ts +++ b/src/commands/filters/Speed.ts @@ -22,7 +22,7 @@ export default class Speed extends Command { permissions: { dev: false, client: ["SendMessages", "ViewChannel", "EmbedLinks"], - user: ["ManageGuild"], + user: [], }, slashCommand: true, options: [ @@ -38,29 +38,24 @@ export default class Speed extends Command { public async run(client: Lavamusic, ctx: Context, args: string[]): Promise { const player = client.queue.get(ctx.guild.id); - const speedString = args[0].replace(",", "."); - const isValidNumber = /^[0-9]*\.?[0-9]+$/.test(speedString); const speed = parseFloat(speedString); - if (!isValidNumber || isNaN(speed) || speed < 0.5 || speed > 5) { return await ctx.sendMessage({ embeds: [ { - description: "Please provide a valid number between 0.5 and 5", + description: "Please provide a valid number between 0.5 and 5.", color: this.client.color.red, }, ], }); } - player.player.setTimescale({ speed }); - return await ctx.sendMessage({ embeds: [ { - description: `Speed has been set to ${speed}`, + description: `Speed has been set to ${speed}.`, color: this.client.color.main, }, ], diff --git a/src/commands/filters/Tremolo.ts b/src/commands/filters/Tremolo.ts index c5daff707..4a9653f0e 100644 --- a/src/commands/filters/Tremolo.ts +++ b/src/commands/filters/Tremolo.ts @@ -22,7 +22,7 @@ export default class Tremolo extends Command { permissions: { dev: false, client: ["SendMessages", "ViewChannel", "EmbedLinks"], - user: ["ManageGuild"], + user: [], }, slashCommand: true, options: [], @@ -31,16 +31,14 @@ export default class Tremolo extends Command { public async run(client: Lavamusic, ctx: Context): Promise { const player = client.queue.get(ctx.guild.id); - const tremoloEnabled = player.filters.includes("tremolo"); - if (tremoloEnabled) { player.player.setTremolo(); player.filters.splice(player.filters.indexOf("tremolo"), 1); return await ctx.sendMessage({ embeds: [ { - description: "Tremolo filter has been disabled", + description: "Tremolo filter has been disabled.", color: client.color.main, }, ], @@ -51,7 +49,7 @@ export default class Tremolo extends Command { return await ctx.sendMessage({ embeds: [ { - description: "Tremolo filter has been enabled", + description: "Tremolo filter has been enabled.", color: client.color.main, }, ], diff --git a/src/commands/filters/Vibrato.ts b/src/commands/filters/Vibrato.ts index cb18e4012..d8bd862b7 100644 --- a/src/commands/filters/Vibrato.ts +++ b/src/commands/filters/Vibrato.ts @@ -31,16 +31,14 @@ export default class Vibrato extends Command { public async run(client: Lavamusic, ctx: Context): Promise { const player = client.queue.get(ctx.guild.id); - const vibratoEnabled = player.filters.includes("vibrato"); - if (vibratoEnabled) { player.player.setVibrato(); player.filters.splice(player.filters.indexOf("vibrato"), 1); return await ctx.sendMessage({ embeds: [ { - description: "Vibrato filter has been disabled", + description: "Vibrato filter has been disabled.", color: client.color.main, }, ], @@ -51,7 +49,7 @@ export default class Vibrato extends Command { return await ctx.sendMessage({ embeds: [ { - description: "Vibrato filter has been enabled", + description: "Vibrato filter has been enabled.", color: client.color.main, }, ], diff --git a/src/commands/filters/lowPass.ts b/src/commands/filters/lowPass.ts index ba57c3691..1bc490614 100644 --- a/src/commands/filters/lowPass.ts +++ b/src/commands/filters/lowPass.ts @@ -22,7 +22,7 @@ export default class LowPass extends Command { permissions: { dev: false, client: ["SendMessages", "ViewChannel", "EmbedLinks"], - user: ["ManageGuild"], + user: [], }, slashCommand: true, options: [], @@ -31,16 +31,14 @@ export default class LowPass extends Command { public async run(client: Lavamusic, ctx: Context): Promise { const player = client.queue.get(ctx.guild.id); - const filterEnabled = player.filters.includes("lowpass"); - if (filterEnabled) { player.player.setLowPass({}); //TODO player.filters = player.filters.filter((filter) => filter !== "lowpass"); ctx.sendMessage({ embeds: [ { - description: "Lowpass filter has been disabled", + description: "Lowpass filter has been disabled.", color: client.color.main, }, ], @@ -51,7 +49,7 @@ export default class LowPass extends Command { ctx.sendMessage({ embeds: [ { - description: "Lowpass filter has been enabled", + description: "Lowpass filter has been enabled.", color: client.color.main, }, ], diff --git a/src/commands/info/About.ts b/src/commands/info/About.ts index 604f10fee..871052859 100644 --- a/src/commands/info/About.ts +++ b/src/commands/info/About.ts @@ -1,5 +1,4 @@ import { ActionRowBuilder, ButtonBuilder, ButtonStyle } from "discord.js"; - import { Command, type Context, type Lavamusic } from "../../structures/index.js"; export default class About extends Command { @@ -38,14 +37,11 @@ export default class About extends Command { .setURL( `https://discord.com/api/oauth2/authorize?client_id=${client.config.clientId}&permissions=8&scope=bot%20applications.commands`, ); - const supportButton = new ButtonBuilder() .setLabel("Support Server") .setStyle(ButtonStyle.Link) .setURL("https://discord.gg/ns8CTk9J3e"); - const row = new ActionRowBuilder().addComponents(inviteButton, supportButton); - const embed = this.client .embed() .setAuthor({ @@ -76,7 +72,6 @@ export default class About extends Command { inline: true, }, ); - await ctx.sendMessage({ content: "", embeds: [embed], diff --git a/src/commands/info/Botinfo.ts b/src/commands/info/Botinfo.ts index aa13807a8..2ea453945 100644 --- a/src/commands/info/Botinfo.ts +++ b/src/commands/info/Botinfo.ts @@ -1,7 +1,6 @@ import os from "node:os"; import { version } from "discord.js"; import { showTotalMemory, usagePercent } from "node-system-stats"; - import { Command, type Context, type Lavamusic } from "../../structures/index.js"; export default class Botinfo extends Command { @@ -47,7 +46,6 @@ export default class Botinfo extends Command { const channels = client.channels.cache.size; const users = client.users.cache.size; const commands = client.commands.size; - const botInfo = `Bot Information: - **Operating System**: ${osInfo} - **Uptime**: ${osUptime} @@ -59,7 +57,6 @@ export default class Botinfo extends Command { - **Discord Version**: ${discordJsVersion} - **Connected to** ${guilds} guilds, ${channels} channels, and ${users} users - **Total Commands**: ${commands}`; - const embed = this.client.embed(); return await ctx.sendMessage({ embeds: [embed.setColor(this.client.color.main).setDescription(botInfo)], diff --git a/src/commands/info/Help.ts b/src/commands/info/Help.ts index 0ed03bcb7..63b1e2414 100644 --- a/src/commands/info/Help.ts +++ b/src/commands/info/Help.ts @@ -41,7 +41,6 @@ export default class Help extends Command { const guild = await client.db.get(ctx.guild.id); const commands = this.client.commands.filter((cmd) => cmd.category !== "dev"); const categories = [...new Set(commands.map((cmd) => cmd.category))]; - if (args[0]) { const command = this.client.commands.get(args[0].toLowerCase()); if (!command) { @@ -49,7 +48,6 @@ export default class Help extends Command { embeds: [client.embed().setColor(client.color.red).setDescription(`Command \`${args[0]}\` not found`)], }); } - const helpEmbed = embed .setColor(this.client.color.main) .setTitle(`Help Menu - ${command.name}`) @@ -68,7 +66,6 @@ export default class Help extends Command { **DJ:** ${command.player.dj ? "Yes" : "No"} **DJ Permissions:** ${command.player.djPerm ? command.player.djPerm : "None"} **Voice:** ${command.player.voice ? "Yes" : "No"}`); - ctx.sendMessage({ embeds: [helpEmbed] }); } else { const fields = categories.map((category) => ({ @@ -79,7 +76,6 @@ export default class Help extends Command { .join(", "), inline: false, })); - const helpEmbed = embed .setColor(this.client.color.main) .setTitle("Help Menu") @@ -89,9 +85,7 @@ export default class Help extends Command { .setFooter({ text: `Use ${guild.prefix}help for more info on a command`, }); - helpEmbed.addFields(...fields); - ctx.sendMessage({ embeds: [helpEmbed] }); } } diff --git a/src/commands/info/Invite.ts b/src/commands/info/Invite.ts index 59f0b3e5e..5bd572ae8 100644 --- a/src/commands/info/Invite.ts +++ b/src/commands/info/Invite.ts @@ -1,5 +1,4 @@ import { ActionRowBuilder, ButtonBuilder, ButtonStyle } from "discord.js"; - import { Command, type Context, type Lavamusic } from "../../structures/index.js"; export default class Invite extends Command { @@ -42,7 +41,6 @@ export default class Invite extends Command { ), new ButtonBuilder().setLabel("My Server").setStyle(ButtonStyle.Link).setURL("https://discord.gg/STXurwnZD5"), ); - return await ctx.sendMessage({ embeds: [ embed diff --git a/src/commands/info/LavaLink.ts b/src/commands/info/LavaLink.ts index 5c15b3560..05cd3ef99 100644 --- a/src/commands/info/LavaLink.ts +++ b/src/commands/info/LavaLink.ts @@ -36,7 +36,6 @@ export default class LavaLink extends Command { .setColor(this.client.color.main) .setThumbnail(this.client.user.avatarURL({})) .setTimestamp(); - client.shoukaku.nodes.forEach((node) => { const statusEmoji = node.stats ? "đŸŸĸ" : "🔴"; const stats = node.stats || { @@ -46,7 +45,6 @@ export default class LavaLink extends Command { cpu: { cores: 0, systemLoad: 0, lavalinkLoad: 0 }, memory: { used: 0, reservable: 0 }, }; - const formattedStats = `\`\`\`yaml Player: ${stats.players} Playing Players: ${stats.playingPlayers} @@ -56,13 +54,11 @@ Memory Usage: ${client.utils.formatBytes(stats.memory.used)} / ${client.utils.fo System Load: ${(stats.cpu.systemLoad * 100).toFixed(2)}% Lavalink Load: ${(stats.cpu.lavalinkLoad * 100).toFixed(2)}% \`\`\``; - embed.addFields({ name: `Name: ${node.name} (${statusEmoji})`, value: formattedStats, }); }); - return await ctx.sendMessage({ embeds: [embed] }); } } diff --git a/src/commands/info/Ping.ts b/src/commands/info/Ping.ts index 16aad8f32..c3c222538 100644 --- a/src/commands/info/Ping.ts +++ b/src/commands/info/Ping.ts @@ -31,7 +31,6 @@ export default class Ping extends Command { public async run(_client: Lavamusic, ctx: Context): Promise { const msg = await ctx.sendDeferMessage("Pinging..."); - const embed = this.client .embed() .setAuthor({ name: "Pong", iconURL: this.client.user.displayAvatarURL() }) @@ -53,7 +52,6 @@ export default class Ping extends Command { iconURL: ctx.author.avatarURL({}), }) .setTimestamp(); - return await ctx.editMessage({ content: "", embeds: [embed] }); } } diff --git a/src/commands/music/Autoplay.ts b/src/commands/music/Autoplay.ts index 33ea5cf7f..340b9585a 100644 --- a/src/commands/music/Autoplay.ts +++ b/src/commands/music/Autoplay.ts @@ -31,16 +31,13 @@ export default class Autoplay extends Command { public async run(client: Lavamusic, ctx: Context): Promise { const player = client.queue.get(ctx.guild.id); const embed = this.client.embed(); - const autoplay = player.autoplay; player.setAutoplay(!autoplay); - if (autoplay) { embed.setDescription("Autoplay has been disabled").setColor(this.client.color.main); } else { embed.setDescription("Autoplay has been enabled").setColor(this.client.color.main); } - await ctx.sendMessage({ embeds: [embed] }); } } diff --git a/src/commands/music/ClearQueue.ts b/src/commands/music/ClearQueue.ts index 616035dc8..c6f90c61a 100644 --- a/src/commands/music/ClearQueue.ts +++ b/src/commands/music/ClearQueue.ts @@ -28,20 +28,18 @@ export default class ClearQueue extends Command { options: [], }); } + public async run(client: Lavamusic, ctx: Context): Promise { const player = client.queue.get(ctx.guild.id); const embed = this.client.embed(); - if (player.queue.length === 0) { return await ctx.sendMessage({ embeds: [embed.setColor(this.client.color.red).setDescription("There are no songs in the queue.")], }); } - player.queue = []; - return await ctx.sendMessage({ - embeds: [embed.setColor(this.client.color.main).setDescription("Cleared the queue")], + embeds: [embed.setColor(this.client.color.main).setDescription("Cleared the queue.")], }); } } diff --git a/src/commands/music/Grab.ts b/src/commands/music/Grab.ts index 838052a66..cff93bc43 100644 --- a/src/commands/music/Grab.ts +++ b/src/commands/music/Grab.ts @@ -5,7 +5,7 @@ export default class Grab extends Command { super(client, { name: "grab", description: { - content: "Grabs the current playing song", + content: "Grabs the current playing song on your DM", examples: ["grab"], usage: "grab", }, @@ -28,12 +28,11 @@ export default class Grab extends Command { options: [], }); } + public async run(client: Lavamusic, ctx: Context): Promise { const embed = this.client.embed().setColor(this.client.color.main); const player = client.queue.get(ctx.guild.id); - const song = player.current; - try { const dm = this.client .embed() @@ -46,10 +45,9 @@ export default class Grab extends Command { `**Link:** [Click here](${song.info.uri})`, ) .setColor(this.client.color.main); - await ctx.author.send({ embeds: [dm] }); return await ctx.sendMessage({ - embeds: [embed.setDescription("I sent you a DM.").setColor(this.client.color.green)], + embeds: [embed.setDescription("Please check your DM.").setColor(this.client.color.green)], }); } catch (_e) { return await ctx.sendMessage({ diff --git a/src/commands/music/Join.ts b/src/commands/music/Join.ts index 0b0e95cfc..12c4131fb 100644 --- a/src/commands/music/Join.ts +++ b/src/commands/music/Join.ts @@ -28,10 +28,10 @@ export default class Join extends Command { options: [], }); } + public async run(client: Lavamusic, ctx: Context): Promise { let player = client.queue.get(ctx.guild.id); const embed = this.client.embed(); - if (player) { return await ctx.sendMessage({ embeds: [ diff --git a/src/commands/music/Leave.ts b/src/commands/music/Leave.ts index d7dd5f9da..818a93cd5 100644 --- a/src/commands/music/Leave.ts +++ b/src/commands/music/Leave.ts @@ -28,6 +28,7 @@ export default class Leave extends Command { options: [], }); } + public async run(client: Lavamusic, ctx: Context): Promise { const player = client.queue.get(ctx.guild.id); const embed = this.client.embed(); diff --git a/src/commands/music/Loop.ts b/src/commands/music/Loop.ts index e77c02185..d5aeec958 100644 --- a/src/commands/music/Loop.ts +++ b/src/commands/music/Loop.ts @@ -28,26 +28,25 @@ export default class Loop extends Command { options: [], }); } + public async run(client: Lavamusic, ctx: Context): Promise { const embed = this.client.embed().setColor(this.client.color.main); const player = client.queue.get(ctx.guild.id); - let loopMessage = ""; switch (player.loop) { case "off": player.loop = "repeat"; - loopMessage = "**Looping the song**"; + loopMessage = "**Looping the song.**"; break; case "repeat": player.loop = "queue"; - loopMessage = "**Looping the queue**"; + loopMessage = "**Looping the queue.**"; break; case "queue": player.loop = "off"; - loopMessage = "**Looping is now off**"; + loopMessage = "**Looping is now off.**"; break; } - return await ctx.sendMessage({ embeds: [embed.setDescription(loopMessage)], }); diff --git a/src/commands/music/Nowplaying.ts b/src/commands/music/Nowplaying.ts index 3b4008fa6..3cb6bd83a 100644 --- a/src/commands/music/Nowplaying.ts +++ b/src/commands/music/Nowplaying.ts @@ -28,9 +28,9 @@ export default class Nowplaying extends Command { options: [], }); } + public async run(client: Lavamusic, ctx: Context): Promise { const player = client.queue.get(ctx.guild.id); - const track = player.current; const position = player.player.position; const duration = track.info.length; diff --git a/src/commands/music/Pause.ts b/src/commands/music/Pause.ts index 6d0155a63..cc8b0902f 100644 --- a/src/commands/music/Pause.ts +++ b/src/commands/music/Pause.ts @@ -28,18 +28,18 @@ export default class Pause extends Command { options: [], }); } + public async run(client: Lavamusic, ctx: Context): Promise { const player = client.queue.get(ctx.guild.id); const embed = this.client.embed(); - if (player.paused) { return await ctx.sendMessage({ - embeds: [embed.setColor(this.client.color.red).setDescription("The song is already paused")], + embeds: [embed.setColor(this.client.color.red).setDescription("The song is already paused.")], }); } player.pause(); return await ctx.sendMessage({ - embeds: [embed.setColor(this.client.color.main).setDescription("Successfully paused the song")], + embeds: [embed.setColor(this.client.color.main).setDescription("Successfully paused the song.")], }); } } diff --git a/src/commands/music/Play.ts b/src/commands/music/Play.ts index 4eb7ad50c..68b25b34f 100644 --- a/src/commands/music/Play.ts +++ b/src/commands/music/Play.ts @@ -1,5 +1,4 @@ import { LoadType } from "shoukaku"; - import { Command, type Context, type Lavamusic } from "../../structures/index.js"; export default class Play extends Command { @@ -41,13 +40,13 @@ export default class Play extends Command { ], }); } + public async run(client: Lavamusic, ctx: Context, args: string[]): Promise { const query = args.join(" "); await ctx.sendDeferMessage("Loading..."); let player = client.queue.get(ctx.guild.id); const vc = ctx.member as any; if (!player) player = await client.queue.create(ctx.guild, vc.voice.channel, ctx.channel); - const res = await this.client.queue.search(query); const embed = this.client.embed(); switch (res.loadType) { diff --git a/src/commands/music/PlayNext.ts b/src/commands/music/PlayNext.ts index 910020fea..3bb8e9ea1 100644 --- a/src/commands/music/PlayNext.ts +++ b/src/commands/music/PlayNext.ts @@ -1,7 +1,4 @@ -//TODO - import { LoadType } from "shoukaku"; - import { Command, type Context, type Lavamusic } from "../../structures/index.js"; export default class PlayNext extends Command { @@ -43,6 +40,7 @@ export default class PlayNext extends Command { ], }); } + public async run(client: Lavamusic, ctx: Context, args: string[]): Promise { const query = args.join(" "); let player = client.queue.get(ctx.guild.id); diff --git a/src/commands/music/Queue.ts b/src/commands/music/Queue.ts index ee4d04293..dd08e1cce 100644 --- a/src/commands/music/Queue.ts +++ b/src/commands/music/Queue.ts @@ -31,7 +31,6 @@ export default class Queue extends Command { public async run(client: Lavamusic, ctx: Context): Promise { const player = client.queue.get(ctx.guild.id); const embed = this.client.embed(); - if (player.queue.length === 0) { return await ctx.sendMessage({ embeds: [ @@ -45,7 +44,6 @@ export default class Queue extends Command { ], }); } - const queue = player.queue.map( (track, index) => `${index + 1}. [${track.info.title}](${track.info.uri}) - Request By: ${track?.info.requester} - Duration: ${ @@ -53,7 +51,6 @@ export default class Queue extends Command { }`, ); const chunks = client.utils.chunk(queue, 10) || [[]]; - const pages = chunks.map((chunk, index) => embed .setColor(this.client.color.main) @@ -61,7 +58,6 @@ export default class Queue extends Command { .setDescription(chunk.join("\n")) .setFooter({ text: `Page ${index + 1} of ${chunks.length}` }), ); - return await client.utils.paginate(ctx, pages); } } diff --git a/src/commands/music/Remove.ts b/src/commands/music/Remove.ts index e1a4e7e79..17a1934a6 100644 --- a/src/commands/music/Remove.ts +++ b/src/commands/music/Remove.ts @@ -35,6 +35,7 @@ export default class Remove extends Command { ], }); } + public async run(client: Lavamusic, ctx: Context, args: string[]): Promise { const player = client.queue.get(ctx.guild.id); const embed = this.client.embed(); @@ -49,7 +50,6 @@ export default class Remove extends Command { return await ctx.sendMessage({ embeds: [embed.setColor(this.client.color.red).setDescription("Please provide a valid song number.")], }); - player.remove(songNumber - 1); return await ctx.sendMessage({ embeds: [embed.setColor(this.client.color.main).setDescription(`Removed song number ${songNumber} from the queue`)], diff --git a/src/commands/music/Replay.ts b/src/commands/music/Replay.ts index 97ec788c2..857aafc18 100644 --- a/src/commands/music/Replay.ts +++ b/src/commands/music/Replay.ts @@ -32,18 +32,14 @@ export default class Replay extends Command { public async run(client: Lavamusic, ctx: Context): Promise { const player = client.queue.get(ctx.guild.id); const embed = this.client.embed(); - - if (!player.current?.info.isSeekable) { return await ctx.sendMessage({ - embeds: [embed.setColor(this.client.color.red).setDescription("Cannot replay this track as it is not seekable")], + embeds: [embed.setColor(this.client.color.red).setDescription("Cannot replay this track as it is not seekable.")], }); } - player.seek(0); - return await ctx.sendMessage({ - embeds: [embed.setColor(this.client.color.main).setDescription("Replaying the current track")], + embeds: [embed.setColor(this.client.color.main).setDescription("Replaying the current track.")], }); } } diff --git a/src/commands/music/Resume.ts b/src/commands/music/Resume.ts index 830f999b4..6ec9fe73f 100644 --- a/src/commands/music/Resume.ts +++ b/src/commands/music/Resume.ts @@ -32,17 +32,14 @@ export default class Resume extends Command { public async run(client: Lavamusic, ctx: Context): Promise { const player = client.queue.get(ctx.guild.id); const embed = this.client.embed(); - if (!player.paused) { return await ctx.sendMessage({ embeds: [embed.setColor(this.client.color.red).setDescription("The player is not paused.")], }); } - player.pause(); - return await ctx.sendMessage({ - embeds: [embed.setColor(this.client.color.main).setDescription("Resumed the player")], + embeds: [embed.setColor(this.client.color.main).setDescription("Resumed the player.")], }); } } diff --git a/src/commands/music/Search.ts b/src/commands/music/Search.ts index e39813174..951508ce8 100644 --- a/src/commands/music/Search.ts +++ b/src/commands/music/Search.ts @@ -1,8 +1,5 @@ -//TODO - import { ActionRowBuilder, ButtonBuilder, ButtonStyle } from "discord.js"; import { LoadType } from "shoukaku"; - import type { Song } from "../../structures/Dispatcher.js"; import { Command, type Context, type Lavamusic } from "../../structures/index.js"; @@ -41,6 +38,7 @@ export default class Search extends Command { ], }); } + public async run(client: Lavamusic, ctx: Context, args: string[]): Promise { const embed = this.client.embed().setColor(this.client.color.main); let player = client.queue.get(ctx.guild.id); @@ -108,7 +106,6 @@ export default class Search extends Command { }); return collector.stop(); }); - collector.on("end", async () => { await ctx.editMessage({ components: [] }); }); diff --git a/src/commands/music/Seek.ts b/src/commands/music/Seek.ts index e81f35c6d..c9b6e9b0a 100644 --- a/src/commands/music/Seek.ts +++ b/src/commands/music/Seek.ts @@ -41,27 +41,26 @@ export default class Seek extends Command { const current = player.current.info; const embed = this.client.embed(); const duration = client.utils.parseTime(args.join(" ")); - if (!duration) { return await ctx.sendMessage({ - embeds: [embed.setColor(this.client.color.red).setDescription("Invalid time format. Example: seek 1m, seek 1h 30m")], + embeds: [embed.setColor(this.client.color.red).setDescription("Invalid time format. Examples: seek 1m, seek 1h 30m")], }); } - if (!current.isSeekable) { return await ctx.sendMessage({ - embeds: [embed.setColor(this.client.color.red).setDescription("This track is not seekable")], + embeds: [embed.setColor(this.client.color.red).setDescription("This track is not seekable.")], }); } - if (duration > current.length) { return await ctx.sendMessage({ - embeds: [embed.setColor(this.client.color.red).setDescription(`Cannot seek beyond the song duration of ${client.utils.formatTime(current.length)}`)], + embeds: [ + embed + .setColor(this.client.color.red) + .setDescription(`Cannot seek beyond the song duration of ${client.utils.formatTime(current.length)}.`), + ], }); } - player.seek(duration); - return await ctx.sendMessage({ embeds: [embed.setColor(this.client.color.main).setDescription(`Seeked to ${client.utils.formatTime(duration)}`)], }); diff --git a/src/commands/music/Shuffle.ts b/src/commands/music/Shuffle.ts index c457ab7c3..de8a3a4fa 100644 --- a/src/commands/music/Shuffle.ts +++ b/src/commands/music/Shuffle.ts @@ -32,17 +32,14 @@ export default class Shuffle extends Command { public async run(client: Lavamusic, ctx: Context): Promise { const player = client.queue.get(ctx.guild.id); const embed = this.client.embed(); - if (!player.queue.length) { return await ctx.sendMessage({ embeds: [embed.setColor(this.client.color.red).setDescription("There are no songs in the queue.")], }); } - player.setShuffle(); - return await ctx.sendMessage({ - embeds: [embed.setColor(this.client.color.main).setDescription("Shuffled the queue")], + embeds: [embed.setColor(this.client.color.main).setDescription("Shuffled the queue.")], }); } } diff --git a/src/commands/music/Skip.ts b/src/commands/music/Skip.ts index 2967afb5f..848517d5f 100644 --- a/src/commands/music/Skip.ts +++ b/src/commands/music/Skip.ts @@ -32,21 +32,18 @@ export default class Skip extends Command { public async run(client: Lavamusic, ctx: Context): Promise { const player = client.queue.get(ctx.guild.id); const embed = this.client.embed(); - if (player.queue.length === 0) { return await ctx.sendMessage({ embeds: [embed.setColor(this.client.color.red).setDescription("There are no songs in the queue.")], }); } - player.skip(); - if (ctx.isInteraction) { return await ctx.sendMessage({ embeds: [ embed .setColor(this.client.color.main) - .setDescription(`Skipped [${player.current.info.title}](${player.current.info.uri})`), + .setDescription(`Skipped [${player.current.info.title}](${player.current.info.uri}).`), ], }); } diff --git a/src/commands/music/Skipto.ts b/src/commands/music/Skipto.ts index 51eec87c7..472f9a6d4 100644 --- a/src/commands/music/Skipto.ts +++ b/src/commands/music/Skipto.ts @@ -39,17 +39,14 @@ export default class Skipto extends Command { public async run(client: Lavamusic, ctx: Context, args: string[]): Promise { const player = client.queue.get(ctx.guild.id); const embed = this.client.embed(); - if (!player.queue.length || isNaN(Number(args[0])) || Number(args[0]) > player.queue.length || Number(args[0]) < 1) { return await ctx.sendMessage({ embeds: [embed.setColor(this.client.color.red).setDescription("Please provide a valid number.")], }); } - player.skip(Number(args[0])); - return await ctx.sendMessage({ - embeds: [embed.setColor(this.client.color.main).setDescription(`Skipped to song number ${args[0]}`)], + embeds: [embed.setColor(this.client.color.main).setDescription(`Skipped to song number ${args[0]}.`)], }); } } diff --git a/src/commands/music/Stop.ts b/src/commands/music/Stop.ts index 7a7a940f5..b46657c28 100644 --- a/src/commands/music/Stop.ts +++ b/src/commands/music/Stop.ts @@ -32,12 +32,10 @@ export default class Stop extends Command { public async run(client: Lavamusic, ctx: Context): Promise { const player = client.queue.get(ctx.guild.id); const embed = this.client.embed(); - player.queue = []; player.stop(); - return await ctx.sendMessage({ - embeds: [embed.setColor(this.client.color.main).setDescription("Stopped the music and cleared the queue")], + embeds: [embed.setColor(this.client.color.main).setDescription("Stopped the music and cleared the queue.")], }); } } diff --git a/src/commands/music/Volume.ts b/src/commands/music/Volume.ts index 4a9de1efb..8783f1408 100644 --- a/src/commands/music/Volume.ts +++ b/src/commands/music/Volume.ts @@ -40,21 +40,20 @@ export default class Volume extends Command { const player = client.queue.get(ctx.guild.id); const embed = this.client.embed(); const number = Number(args[0]); - if (isNaN(number) || number < 0 || number > 200) { let description = ""; if (isNaN(number)) description = "Please provide a valid number."; else if (number < 0) description = "The volume can't be lower than 0."; - else if (number > 200) description = "The volume can't be higher than 200."; - + else if (number > 200) + description = + "The volume can't be higher than 200. Do you want to damage your hearing or speakers? Hmmm, I don't think that's such a good idea."; return await ctx.sendMessage({ embeds: [embed.setColor(this.client.color.red).setDescription(description)], }); } - player.player.setGlobalVolume(number); return await ctx.sendMessage({ - embeds: [embed.setColor(this.client.color.main).setDescription(`Set the volume to ${player.player.volume}`)], + embeds: [embed.setColor(this.client.color.main).setDescription(`Set the volume to ${player.player.volume}.`)], }); } } diff --git a/src/commands/playlist/Add.ts b/src/commands/playlist/Add.ts index e15a5710e..0a92a1d38 100644 --- a/src/commands/playlist/Add.ts +++ b/src/commands/playlist/Add.ts @@ -1,7 +1,4 @@ -//TODO - import { LoadType } from "shoukaku"; - import { Command, type Context, type Lavamusic } from "../../structures/index.js"; export default class AddPlaylist extends Command { @@ -49,27 +46,25 @@ export default class AddPlaylist extends Command { public async run(client: Lavamusic, ctx: Context, args: string[]): Promise { const playlist = args.shift(); const song = args.join(" "); - if (!playlist) { - const errorMessage = this.client.embed().setDescription("Please provide a playlist").setColor(this.client.color.red); + const errorMessage = this.client.embed().setDescription("Please provide a playlist.").setColor(this.client.color.red); return await ctx.sendMessage({ embeds: [errorMessage] }); } - if (!song) { - const errorMessage = this.client.embed().setDescription("Please provide a song").setColor(this.client.color.red); + const errorMessage = this.client.embed().setDescription("Please provide a song.").setColor(this.client.color.red); return await ctx.sendMessage({ embeds: [errorMessage] }); } - const playlistData = await client.db.getPlaylist(ctx.author.id, playlist); - if (!playlistData) { - const playlistNotFoundError = this.client.embed().setDescription("That playlist doesn't exist").setColor(this.client.color.red); + const playlistNotFoundError = this.client + .embed() + .setDescription("That playlist doesn't exist.") + .setColor(this.client.color.red); return await ctx.sendMessage({ embeds: [playlistNotFoundError] }); } - const res = await client.queue.search(song); if (!res) { - const noSongsFoundError = this.client.embed().setDescription("No songs found").setColor(this.client.color.red); + const noSongsFoundError = this.client.embed().setDescription("No songs found.").setColor(this.client.color.red); return await ctx.sendMessage({ embeds: [noSongsFoundError] }); } let trackStrings: any; @@ -81,12 +76,10 @@ export default class AddPlaylist extends Command { trackStrings = [res.data[0]]; count = 1; } - client.db.addSong(ctx.author.id, playlist, trackStrings); - const successMessage = this.client .embed() - .setDescription(`Added ${count} song(s) to ${playlistData.name}`) + .setDescription(`Added ${count} song(s) to ${playlistData.name}.`) .setColor(this.client.color.green); ctx.sendMessage({ embeds: [successMessage] }); } diff --git a/src/commands/playlist/Create.ts b/src/commands/playlist/Create.ts index 7edd76e4a..b243ba4bf 100644 --- a/src/commands/playlist/Create.ts +++ b/src/commands/playlist/Create.ts @@ -42,7 +42,7 @@ export default class CreatePlaylist extends Command { return await ctx.sendMessage({ embeds: [ { - description: "Playlist names can only be 50 characters long", + description: "Playlist names can only be 50 characters long.", color: this.client.color.red, }, ], @@ -53,7 +53,7 @@ export default class CreatePlaylist extends Command { return await ctx.sendMessage({ embeds: [ { - description: "A playlist with that name already exists", + description: "A playlist with that name already exists. Please use a different name.", color: this.client.color.main, }, ], @@ -63,7 +63,7 @@ export default class CreatePlaylist extends Command { return await ctx.sendMessage({ embeds: [ { - description: `Playlist **${name}** has been created`, + description: `Playlist **${name}** has been created.`, color: this.client.color.main, }, ], diff --git a/src/commands/playlist/Delete.ts b/src/commands/playlist/Delete.ts index 063bde474..07db5c14e 100644 --- a/src/commands/playlist/Delete.ts +++ b/src/commands/playlist/Delete.ts @@ -38,24 +38,22 @@ export default class DeletePlaylist extends Command { public async run(client: Lavamusic, ctx: Context, args: string[]): Promise { const playlistName = args.join(" ").trim(); - const playlistExists = await client.db.getPlaylist(ctx.author.id, playlistName); if (!playlistExists) { return await ctx.sendMessage({ embeds: [ { - description: "That playlist doesn't exist", + description: "That playlist doesn't exist.", color: this.client.color.red, }, ], }); } - client.db.deletePlaylist(ctx.author.id, playlistName); return await ctx.sendMessage({ embeds: [ { - description: `Deleted playlist **${playlistName}**`, + description: `Deleted playlist **${playlistName}.**`, color: this.client.color.main, }, ], diff --git a/src/commands/playlist/Load.ts b/src/commands/playlist/Load.ts index f3e5234b2..72fbdf29c 100644 --- a/src/commands/playlist/Load.ts +++ b/src/commands/playlist/Load.ts @@ -1,5 +1,3 @@ -//TODO - import { Command, type Context, type Lavamusic } from "../../structures/index.js"; export default class LoadPlaylist extends Command { @@ -37,6 +35,7 @@ export default class LoadPlaylist extends Command { ], }); } + public async run(client: Lavamusic, ctx: Context, args: string[]): Promise { let player = client.queue.get(ctx.guild.id); const playlist = args.join(" ").replace(/\s/g, ""); @@ -45,7 +44,7 @@ export default class LoadPlaylist extends Command { return await ctx.sendMessage({ embeds: [ { - description: "That playlist doesn't exist", + description: "That playlist doesn't exist.", color: this.client.color.red, }, ], @@ -55,7 +54,7 @@ export default class LoadPlaylist extends Command { return await ctx.sendMessage({ embeds: [ { - description: "That playlist is empty", + description: "That playlist is empty.", color: client.color.red, }, ], @@ -70,16 +69,14 @@ export default class LoadPlaylist extends Command { ctx.channel, client.shoukaku.options.nodeResolver(client.shoukaku.nodes), ); - const track = player.buildTrack(song, ctx.author as any); player.queue.push(track); player.isPlaying(); } - return await ctx.sendMessage({ embeds: [ { - description: `Loaded \`${playlistData.name}\` with \`${JSON.parse(s.track).length}\` songs`, + description: `Loaded \`${playlistData.name}\` with \`${JSON.parse(s.track).length}\` songs.`, color: this.client.color.main, }, ], diff --git a/src/config.ts b/src/config.ts index aae4b2287..ee5ae51fe 100644 --- a/src/config.ts +++ b/src/config.ts @@ -1,7 +1,5 @@ import dotenv from "dotenv"; - import { SearchEngine } from "./types.js"; - dotenv.config(); export default { diff --git a/src/database/server.ts b/src/database/server.ts index 7e2a6473f..24e9b4659 100644 --- a/src/database/server.ts +++ b/src/database/server.ts @@ -9,13 +9,11 @@ import { type Song, type Stay, } from "@prisma/client"; - import config from "../config.js"; export default class ServerData { F; private prisma: PrismaClient; - constructor() { this.prisma = new PrismaClient(); } diff --git a/src/events/client/GuildCreate.ts b/src/events/client/GuildCreate.ts index 410a504b5..7a9250e0e 100644 --- a/src/events/client/GuildCreate.ts +++ b/src/events/client/GuildCreate.ts @@ -1,5 +1,4 @@ import { EmbedBuilder, type Guild, type GuildMember, type TextChannel } from "discord.js"; - import { Event, type Lavamusic } from "../../structures/index.js"; export default class GuildCreate extends Event { @@ -16,7 +15,6 @@ export default class GuildCreate extends Event { } catch (e) { console.error(`Error fetching owner for guild ${guild.id}: ${e}`); } - const embed = new EmbedBuilder() .setColor(this.client.config.color.green) .setAuthor({ name: guild.name, iconURL: guild.iconURL({ extension: "jpeg" }) }) @@ -38,23 +36,22 @@ export default class GuildCreate extends Event { { name: "ID", value: guild.id, inline: true }, ) .setTimestamp(); - const logChannelId = this.client.config.logChannelId; if (!logChannelId) { console.error("Log channel ID not found in configuration."); return; } - const channel = (await this.client.channels.fetch(logChannelId)) as TextChannel; if (!channel) { - console.error(`Log channel not found with ID ${logChannelId}.`); + console.error( + `Log channel not found with ID ${logChannelId}. Please change the settings in .env or, if you have a channel, invite me to that guild.`, + ); return; } - try { await channel.send({ embeds: [embed] }); } catch (error) { - console.error(`Error sending message to log channel ${logChannelId}: ${error}`); + console.error(`Error sending message to log channel ${logChannelId}: ${error}.`); } } } diff --git a/src/events/client/GuildDelete.ts b/src/events/client/GuildDelete.ts index 50a20ea59..2689820a9 100644 --- a/src/events/client/GuildDelete.ts +++ b/src/events/client/GuildDelete.ts @@ -1,5 +1,4 @@ import { EmbedBuilder, type Guild, type GuildMember, type TextChannel } from "discord.js"; - import { Event, type Lavamusic } from "../../structures/index.js"; export default class GuildDelete extends Event { @@ -16,7 +15,6 @@ export default class GuildDelete extends Event { } catch (error) { console.error(`Error fetching owner for guild ${guild.id}: ${error}`); } - const embed = new EmbedBuilder() .setColor(this.client.config.color.red) .setAuthor({ @@ -45,21 +43,18 @@ export default class GuildDelete extends Event { { name: "ID", value: guild.id, inline: true }, ) .setTimestamp(); - const logChannelId = this.client.config.logChannelId; if (!logChannelId) { console.error("Log channel ID not found in configuration."); return; } - let channel: TextChannel; try { channel = (await this.client.channels.fetch(logChannelId)) as TextChannel; } catch (error) { - console.error(`Error fetching log channel ${logChannelId}: ${error}`); + console.error(`Error fetching log channel ${logChannelId}: ${error}.`); return; } - try { await channel.send({ embeds: [embed] }); } catch (error) { diff --git a/src/events/client/InteractionCreate.ts b/src/events/client/InteractionCreate.ts index 02059c4b0..be8ec6957 100644 --- a/src/events/client/InteractionCreate.ts +++ b/src/events/client/InteractionCreate.ts @@ -8,7 +8,6 @@ import { PermissionFlagsBits, } from "discord.js"; import { LoadType } from "shoukaku"; - import { Context, Event, type Lavamusic } from "../../structures/index.js"; export default class InteractionCreate extends Event { @@ -42,11 +41,10 @@ export default class InteractionCreate extends Event { ) ) return; - if (!interaction.guild.members.resolve(this.client.user).permissions.has(PermissionFlagsBits.SendMessages)) { return await (interaction.member as GuildMember) .send({ - content: `I don't have **\`SendMessage\`** permission in \`${interaction.guild.name}\`\nchannel: <#${interaction.channelId}>`, + content: `I don't have **\`SendMessage\`** permission in \`${interaction.guild.name}\`\nchannel: <#${interaction.channelId}>.`, }) .catch(() => {}); } @@ -86,17 +84,14 @@ export default class InteractionCreate extends Event { return await interaction.reply({ content: `You must be connected to a voice channel to use this \`${command.name}\` command.`, }); - if (!interaction.guild.members.resolve(this.client.user).permissions.has(PermissionFlagsBits.Speak)) return await interaction.reply({ content: `I don't have \`CONNECT\` permissions to execute this \`${command.name}\` command.`, }); - if (!interaction.guild.members.resolve(this.client.user).permissions.has(PermissionFlagsBits.Speak)) return await interaction.reply({ content: `I don't have \`SPEAK\` permissions to execute this \`${command.name}\` command.`, }); - if ( (interaction.member as GuildMember).voice.channel.type === ChannelType.GuildStageVoice && !interaction.guild.members.resolve(this.client.user).permissions.has(PermissionFlagsBits.RequestToSpeak) @@ -150,7 +145,6 @@ export default class InteractionCreate extends Event { } const now = Date.now(); const timestamps = this.client.cooldown.get(commandName); - const cooldownAmount = Math.floor(command.cooldown || 5) * 1000; if (timestamps.has(interaction.user.id)) { const expirationTime = timestamps.get(interaction.user.id) + cooldownAmount; @@ -166,7 +160,6 @@ export default class InteractionCreate extends Event { timestamps.set(interaction.user.id, now); setTimeout(() => timestamps.delete(interaction.user.id), cooldownAmount); } - try { await command.run(this.client, ctx, ctx.args); } catch (error) { @@ -193,7 +186,6 @@ export default class InteractionCreate extends Event { default: break; } - return await interaction.respond(songs).catch(() => {}); } } diff --git a/src/events/client/MessageCreate.ts b/src/events/client/MessageCreate.ts index 6a36ac543..29d053aab 100644 --- a/src/events/client/MessageCreate.ts +++ b/src/events/client/MessageCreate.ts @@ -1,5 +1,4 @@ import { ChannelType, Collection, type Message, PermissionFlagsBits } from "discord.js"; - import { Context, Event, type Lavamusic } from "../../structures/index.js"; export default class MessageCreate extends Event { @@ -12,14 +11,11 @@ export default class MessageCreate extends Event { // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: public async run(message: Message): Promise { if (message.author.bot) return; - const setup = await this.client.db.getSetup(message.guildId); if (setup && setup.textId === message.channelId) { return this.client.emit("setupSystem", message); } - const guild = await this.client.db.get(message.guildId); - const mention = new RegExp(`^<@!?${this.client.user.id}>( |)$`); if (message.content.match(mention)) { await message.reply({ @@ -27,25 +23,18 @@ export default class MessageCreate extends Event { }); return; } - const escapeRegex = (str: string): string => str.replace(/[.*+?^${}()|[\]\\]/g, "\\$&"); const prefixRegex = new RegExp(`^(<@!?${this.client.user.id}>|${escapeRegex(guild.prefix)})\\s*`); if (!prefixRegex.test(message.content)) return; - const [matchedPrefix] = message.content.match(prefixRegex); - const args = message.content.slice(matchedPrefix.length).trim().split(/ +/g); - const cmd = args.shift()?.toLowerCase(); const command = this.client.commands.get(cmd) || this.client.commands.get(this.client.aliases.get(cmd) as string); if (!command) return; - const ctx = new Context(message, args); ctx.setArgs(args); - let dm = message.author.dmChannel; if (typeof dm === "undefined") dm = await message.author.createDM(); - if ( !( message.inGuild() && @@ -53,7 +42,6 @@ export default class MessageCreate extends Event { ) ) return; - if (!message.guild.members.resolve(this.client.user).permissions.has(PermissionFlagsBits.SendMessages)) { await message.author .send({ @@ -62,14 +50,12 @@ export default class MessageCreate extends Event { .catch(() => {}); return; } - if (!message.guild.members.resolve(this.client.user).permissions.has(PermissionFlagsBits.EmbedLinks)) { await message.reply({ content: "I don't have **`EmbedLinks`** permission.", }); return; } - if (command.permissions) { if ( command.permissions.client && @@ -80,20 +66,17 @@ export default class MessageCreate extends Event { }); return; } - if (command.permissions.user && !message.member.permissions.has(command.permissions.user)) { await message.reply({ content: "You don't have enough permissions to use this command.", }); return; } - if (command.permissions.dev && this.client.config.owners) { const findDev = this.client.config.owners.find((x) => x === message.author.id); if (!findDev) return; } } - if (command.player) { if (command.player.voice) { if (!message.member.voice.channel) { @@ -102,21 +85,18 @@ export default class MessageCreate extends Event { }); return; } - if (!message.guild.members.resolve(this.client.user).permissions.has(PermissionFlagsBits.Speak)) { await message.reply({ content: `I don't have \`CONNECT\` permissions to execute this \`${command.name}\` command.`, }); return; } - if (!message.guild.members.resolve(this.client.user).permissions.has(PermissionFlagsBits.Speak)) { await message.reply({ content: `I don't have \`SPEAK\` permissions to execute this \`${command.name}\` command.`, }); return; } - if ( message.member.voice.channel.type === ChannelType.GuildStageVoice && !message.guild.members.resolve(this.client.user).permissions.has(PermissionFlagsBits.RequestToSpeak) @@ -126,7 +106,6 @@ export default class MessageCreate extends Event { }); return; } - if ( message.guild.members.resolve(this.client.user).voice.channel && message.guild.members.resolve(this.client.user).voice.channelId !== message.member.voice.channelId @@ -139,7 +118,6 @@ export default class MessageCreate extends Event { return; } } - if (command.player.active) { const queue = this.client.queue.get(message.guildId); if (!queue?.queue && queue.current) { @@ -149,7 +127,6 @@ export default class MessageCreate extends Event { return; } } - if (command.player.dj) { const dj = await this.client.db.getDj(message.guildId); if (dj?.mode) { @@ -174,7 +151,6 @@ export default class MessageCreate extends Event { } } } - if (command.args && !args.length) { const embed = this.client .embed() @@ -186,19 +162,15 @@ export default class MessageCreate extends Event { }`, ) .setFooter({ text: "Syntax: [] = optional, <> = required" }); - await message.reply({ embeds: [embed] }); return; } - if (!this.client.cooldown.has(cmd)) { this.client.cooldown.set(cmd, new Collection()); } - const now = Date.now(); const timestamps = this.client.cooldown.get(cmd)!; const cooldownAmount = Math.floor(command.cooldown || 5) * 1000; - if (timestamps.has(message.author.id)) { const expirationTime = timestamps.get(message.author.id)! + cooldownAmount; const timeLeft = (expirationTime - now) / 1000; @@ -214,14 +186,12 @@ export default class MessageCreate extends Event { timestamps.set(message.author.id, now); setTimeout(() => timestamps.delete(message.author.id), cooldownAmount); } - if (args.includes("@everyone") || args.includes("@here")) { await message.reply({ content: "You can't use this command with everyone or here.", }); return; } - try { return command.run(this.client, ctx, ctx.args); } catch (error) { @@ -231,7 +201,6 @@ export default class MessageCreate extends Event { } } } - /** * Project: lavamusic * Author: Appu diff --git a/src/events/client/Ready.ts b/src/events/client/Ready.ts index 65e44a87e..10aa6c611 100644 --- a/src/events/client/Ready.ts +++ b/src/events/client/Ready.ts @@ -7,10 +7,10 @@ export default class Ready extends Event { name: "ready", }); } + // biome-ignore lint/suspicious/useAwait: public async run(): Promise { this.client.logger.success(`${this.client.user?.tag} is ready!`); - this.client.user?.setPresence({ activities: [ { diff --git a/src/events/client/SetupButtons.ts b/src/events/client/SetupButtons.ts index b373dae6e..fd225f116 100644 --- a/src/events/client/SetupButtons.ts +++ b/src/events/client/SetupButtons.ts @@ -10,10 +10,10 @@ export default class SetupButtons extends Event { name: "setupButtons", }); } + // biome-ignore lint/complexity/noExcessiveCognitiveComplexity: public async run(interaction: any): Promise { if (!interaction.replied) await interaction.deferReply().catch(() => {}); - if (!interaction.member.voice.channel) return await buttonReply(interaction, "You are not connected to a voice channel to use this button.", this.client.color.red); if ( @@ -40,7 +40,6 @@ export default class SetupButtons extends Event { const icon = player ? player.current.info.artworkUrl : this.client.user.displayAvatarURL({ extension: "png" }); let iconUrl = this.client.config.icons[player.current.info.sourceName]; if (!iconUrl) iconUrl = this.client.user.displayAvatarURL({ extension: "png" }); - const embed = this.client .embed() .setAuthor({ name: "Now Playing", iconURL: iconUrl }) @@ -139,7 +138,6 @@ export default class SetupButtons extends Event { case "LOOP_BUT": { const loopOptions: Array<"off" | "queue" | "repeat"> = ["off", "queue", "repeat"]; const newLoop = loopOptions[Math.floor(Math.random() * loopOptions.length)]; - if (player.loop === newLoop) { await buttonReply(interaction, `Loop is already ${player.loop}.`, this.client.color.main); } else { diff --git a/src/events/client/SetupSystem.ts b/src/events/client/SetupSystem.ts index 124c876f9..04abbb238 100644 --- a/src/events/client/SetupSystem.ts +++ b/src/events/client/SetupSystem.ts @@ -1,5 +1,4 @@ import { type Message, PermissionsBitField, TextChannel } from "discord.js"; - import { Event, type Lavamusic } from "../../structures/index.js"; import { oops, setupStart } from "../../utils/SetupSystem.js"; @@ -9,22 +8,20 @@ export default class SetupSystem extends Event { name: "setupSystem", }); } + public async run(message: Message): Promise { const channel = message.channel as TextChannel; - if (!(channel instanceof TextChannel)) return; if (!message.member.voice.channel) { await oops(channel, "You are not connected to a voice channel to queue songs."); if (message) await message.delete().catch(() => {}); return; } - if (!message.member.voice.channel.permissionsFor(this.client.user).has(PermissionsBitField.resolve(["Connect", "Speak"]))) { await oops(channel, `I don't have enough permission to connect/speak in <#${message.member.voice.channel.id}>`); if (message) await message.delete().catch(() => {}); return; } - if ( message.guild.members.cache.get(this.client.user.id).voice.channel && message.guild.members.cache.get(this.client.user.id).voice.channelId !== message.member.voice.channelId diff --git a/src/events/client/VoiceStateUpdate.ts b/src/events/client/VoiceStateUpdate.ts index d45058893..8462dfb10 100644 --- a/src/events/client/VoiceStateUpdate.ts +++ b/src/events/client/VoiceStateUpdate.ts @@ -1,7 +1,5 @@ import { ChannelType, type GuildMember, type VoiceState } from "discord.js"; - import { Event, type Lavamusic } from "../../structures/index.js"; - export default class VoiceStateUpdate extends Event { constructor(client: Lavamusic, file: string) { super(client, file, { @@ -12,24 +10,18 @@ export default class VoiceStateUpdate extends Event { public async run(_oldState: VoiceState, newState: VoiceState): Promise { const guildId = newState.guild.id; if (!guildId) return; - const player = this.client.queue.get(guildId); if (!player) return; - const vcConnection = player.node.manager.connections.get(guildId); if (!vcConnection?.channelId) return; - const vc = newState.guild.channels.cache.get(vcConnection.channelId); if (!(vc && vc.members instanceof Map)) return; - const is247 = await this.client.db.get_247(guildId); - if (!newState.guild.members.cache.get(this.client.user.id)?.voice.channelId) { if (!is247 && player) { return player.destroy(); } } - if ( newState.id === this.client.user.id && newState.channelId && @@ -40,12 +32,10 @@ export default class VoiceStateUpdate extends Event { newState.guild.members.me.permissions.has(["Connect", "Speak"]) || newState.channel.permissionsFor(newState.guild.members.me).has("MuteMembers") ) { - await newState.guild.members.me.voice.setSuppressed(false).catch(() => { }); + await newState.guild.members.me.voice.setSuppressed(false).catch(() => {}); } } - if (newState.id === this.client.user.id) return; - if ( newState.id === this.client.user.id && !newState.serverDeaf && @@ -53,20 +43,16 @@ export default class VoiceStateUpdate extends Event { ) { await newState.setDeaf(true); } - if (newState.id === this.client.user.id && newState.serverMute && !player.paused) { player.pause(); } - if (newState.id === this.client.user.id && !newState.serverMute && player.paused) { player.pause(); } - if (vc.members instanceof Map && [...vc.members.values()].filter((x: GuildMember) => !x.user.bot).length <= 0) { setTimeout(async () => { const vcConnection = player.node.manager.connections.get(guildId); if (!vcConnection?.channelId) return; - const playerVoiceChannel = newState.guild.channels.cache.get(vcConnection.channelId); if ( player && diff --git a/src/events/player/NodeConnect.ts b/src/events/player/NodeConnect.ts index dc263fef0..8b5ba7ba6 100644 --- a/src/events/player/NodeConnect.ts +++ b/src/events/player/NodeConnect.ts @@ -10,29 +10,22 @@ export default class NodeConnect extends Event { public async run(node: string): Promise { this.client.logger.success(`Node ${node} is ready!`); - let data = await this.client.db.get_247(); if (!data) return; - if (!Array.isArray(data)) { data = [data]; } - data.forEach((main, index) => { setTimeout(async () => { const guild = this.client.guilds.cache.get(main.guildId); if (!guild) return; - const channel = guild.channels.cache.get(main.textId); if (!channel) return; - const vc = guild.channels.cache.get(main.voiceId); if (!vc) return; - await this.client.queue.create(guild, vc, channel); }, index * 1000); }); - BotLog.send(this.client, `Node ${node} is ready!`, "success"); } } diff --git a/src/events/player/NodeDestroy.ts b/src/events/player/NodeDestroy.ts index d1d219a30..8c875c299 100644 --- a/src/events/player/NodeDestroy.ts +++ b/src/events/player/NodeDestroy.ts @@ -1,6 +1,5 @@ import { Event, type Lavamusic } from "../../structures/index.js"; import BotLog from "../../utils/BotLog.js"; - let destroyCount = 0; export default class NodeDestroy extends Event { @@ -12,19 +11,14 @@ export default class NodeDestroy extends Event { // biome-ignore lint/suspicious/useAwait: public async run(node: string, code: number, reason: string): Promise { - const message = `Node ${node} destroyed with code ${code} and reason ${reason}`; - + const message = `Node ${node} destroyed with code ${code} and reason ${reason}.`; this.client.logger.error(message); BotLog.send(this.client, message, "error"); - destroyCount++; - if (destroyCount >= 5) { this.client.shoukaku.removeNode(node); destroyCount = 0; - - const warnMessage = `Node ${node} removed from nodes list due to excessive disconnects`; - + const warnMessage = `Node ${node} removed from nodes list due to excessive disconnects.`; this.client.logger.warn(warnMessage); BotLog.send(this.client, warnMessage, "warn"); } diff --git a/src/events/player/NodeDisconnect.ts b/src/events/player/NodeDisconnect.ts index 6b5f006c0..c44c9837a 100644 --- a/src/events/player/NodeDisconnect.ts +++ b/src/events/player/NodeDisconnect.ts @@ -11,7 +11,6 @@ export default class NodeDisconnect extends Event { // biome-ignore lint/suspicious/useAwait: public async run(node: string, count: number): Promise { const message = `Node ${node} disconnected ${count} times`; - this.client.logger.warn(message); BotLog.send(this.client, message, "warn"); } diff --git a/src/events/player/NodeError.ts b/src/events/player/NodeError.ts index 06f7abd7f..c372156ca 100644 --- a/src/events/player/NodeError.ts +++ b/src/events/player/NodeError.ts @@ -12,7 +12,6 @@ export default class NodeError extends Event { public async run(node: string, error: any): Promise { const errorMessage = JSON.stringify(error, null, 2); const message = `Node ${node} Error: ${errorMessage}`; - this.client.logger.error(message); BotLog.send(this.client, message, "error"); } diff --git a/src/events/player/NodeReconnect.ts b/src/events/player/NodeReconnect.ts index 066ba1539..f8b019cc1 100644 --- a/src/events/player/NodeReconnect.ts +++ b/src/events/player/NodeReconnect.ts @@ -11,7 +11,6 @@ export default class NodeReconnect extends Event { // biome-ignore lint/suspicious/useAwait: public async run(node: string): Promise { const message = `Node ${node} reconnected`; - this.client.logger.warn(message); BotLog.send(this.client, message, "warn"); } diff --git a/src/events/player/QueueEnd.ts b/src/events/player/QueueEnd.ts index 51450caf1..d2b1c65a7 100644 --- a/src/events/player/QueueEnd.ts +++ b/src/events/player/QueueEnd.ts @@ -1,5 +1,4 @@ import type { Player } from "shoukaku"; - import type { Song } from "../../structures/Dispatcher.js"; import { type Dispatcher, Event, type Lavamusic } from "../../structures/index.js"; import { updateSetup } from "../../utils/SetupSystem.js"; @@ -14,7 +13,6 @@ export default class QueueEnd extends Event { public async run(_player: Player, track: Song, dispatcher: Dispatcher): Promise { const guild = this.client.guilds.cache.get(dispatcher.guildId); if (!guild) return; - switch (dispatcher.loop) { case "repeat": dispatcher.queue.unshift(track); @@ -27,13 +25,11 @@ export default class QueueEnd extends Event { dispatcher.current = null; break; } - if (dispatcher.autoplay) { await dispatcher.Autoplay(track); } else { dispatcher.autoplay = false; } - await updateSetup(this.client, guild); this.client.utils.updateStatus(this.client, guild.id); } diff --git a/src/events/player/TrackEnd.ts b/src/events/player/TrackEnd.ts index 04c2eb8d2..6d8d8674b 100644 --- a/src/events/player/TrackEnd.ts +++ b/src/events/player/TrackEnd.ts @@ -1,5 +1,4 @@ import type { Player } from "shoukaku"; - import type { Song } from "../../structures/Dispatcher.js"; import { type Dispatcher, Event, type Lavamusic } from "../../structures/index.js"; @@ -13,9 +12,7 @@ export default class TrackEnd extends Event { public async run(_player: Player, track: Song, dispatcher: Dispatcher): Promise { dispatcher.previous = dispatcher.current; dispatcher.current = null; - const nowPlayingMessage = await dispatcher.nowPlayingMessage?.fetch().catch(() => null); - switch (dispatcher.loop) { case "repeat": dispatcher.queue.unshift(track); @@ -24,13 +21,10 @@ export default class TrackEnd extends Event { dispatcher.queue.push(track); break; } - await dispatcher.play(); - if (dispatcher.autoplay) { await dispatcher.Autoplay(track); } - if (nowPlayingMessage?.deletable) { await nowPlayingMessage.delete().catch(() => {}); } diff --git a/src/events/player/TrackStart.ts b/src/events/player/TrackStart.ts index d70ee2a9e..f5e870b91 100644 --- a/src/events/player/TrackStart.ts +++ b/src/events/player/TrackStart.ts @@ -13,7 +13,6 @@ import { type UserSelectMenuInteraction, } from "discord.js"; import type { Player } from "shoukaku"; - import type { Song } from "../../structures/Dispatcher.js"; import { type Dispatcher, Event, type Lavamusic } from "../../structures/index.js"; import { trackStart } from "../../utils/SetupSystem.js"; @@ -27,15 +26,11 @@ export default class TrackStart extends Event { public async run(player: Player, track: Song, dispatcher: Dispatcher): Promise { if (track && !track.info) return; - const guild = this.client.guilds.cache.get(player.guildId); if (!guild) return; - const channel = guild.channels.cache.get(dispatcher.channelId) as TextChannel; if (!channel) return; - this.client.utils.updateStatus(this.client, guild.id); - const embed = this.client .embed() .setAuthor({ @@ -58,7 +53,6 @@ export default class TrackStart extends Event { { name: "Author", value: track.info.author, inline: true }, ) .setTimestamp(); - const setup = await this.client.db.getSetup(guild.id); if (setup?.textId) { const textChannel = guild.channels.cache.get(setup.textId) as TextChannel; @@ -76,31 +70,24 @@ export default class TrackStart extends Event { } } } - function createButtonRow(dispatcher: Dispatcher): ActionRowBuilder { const previousButton = new ButtonBuilder() .setCustomId("previous") .setEmoji("âĒ") .setStyle(ButtonStyle.Secondary) .setDisabled(!dispatcher.previous); - const resumeButton = new ButtonBuilder() .setCustomId("resume") .setEmoji(dispatcher.paused ? "â–ļī¸" : "⏸ī¸") .setStyle(dispatcher.paused ? ButtonStyle.Success : ButtonStyle.Secondary); - const stopButton = new ButtonBuilder().setCustomId("stop").setEmoji("⏚ī¸").setStyle(ButtonStyle.Danger); - const skipButton = new ButtonBuilder().setCustomId("skip").setEmoji("⏊").setStyle(ButtonStyle.Secondary); - const loopButton = new ButtonBuilder() .setCustomId("loop") .setEmoji(dispatcher.loop === "repeat" ? "🔂" : "🔁") .setStyle(dispatcher.loop !== "off" ? ButtonStyle.Success : ButtonStyle.Secondary); - return new ActionRowBuilder().addComponents(resumeButton, previousButton, stopButton, skipButton, loopButton); } - function createCollector(message: any, dispatcher: Dispatcher, _track: Song, embed: any, client: Lavamusic): void { const collector = message.createMessageComponentCollector({ filter: async (b: ButtonInteraction) => { @@ -115,7 +102,6 @@ function createCollector(message: any, dispatcher: Dispatcher, _track: Song, emb return false; }, }); - collector.on("collect", async (interaction) => { if (!(await checkDj(client, interaction))) { await interaction.reply({ @@ -124,7 +110,6 @@ function createCollector(message: any, dispatcher: Dispatcher, _track: Song, emb }); return; } - const editMessage = async (text: string): Promise => { if (message) { await message.edit({ @@ -133,7 +118,6 @@ function createCollector(message: any, dispatcher: Dispatcher, _track: Song, emb }); } }; - switch (interaction.customId) { case "previous": if (dispatcher.previous) { @@ -195,7 +179,6 @@ function createCollector(message: any, dispatcher: Dispatcher, _track: Song, emb } }); } - export async function checkDj( client: Lavamusic, interaction: diff --git a/src/index.ts b/src/index.ts index 3f9991aff..50d399f38 100644 --- a/src/index.ts +++ b/src/index.ts @@ -1,7 +1,6 @@ // biome-ignore lint/style/noNamespaceImport: import * as fs from "node:fs"; import { ShardingManager } from "discord.js"; - import config from "./config.js"; import Logger from "./structures/Logger.js"; @@ -13,26 +12,21 @@ async function main(): Promise { logger.error("LavaLogo.txt file is missing"); process.exit(1); } - const logFile = fs.readFileSync("./src/utils/LavaLogo.txt", "utf-8"); // biome-ignore lint/suspicious/noConsoleLog: console.log("\x1b[35m%s\x1b[0m", logFile); - const manager = new ShardingManager("./dist/LavaClient.js", { respawn: true, token: config.token, totalShards: "auto", shardList: "auto", }); - manager.on("shardCreate", (shard) => { shard.on("ready", () => { logger.start(`[CLIENT] Shard ${shard.id} connected to Discord's Gateway.`); }); }); - await manager.spawn(); - logger.start(`[CLIENT] ${manager.totalShards} shard(s) spawned.`); } catch (err) { logger.error("[CLIENT] An error has occurred:", err); diff --git a/src/plugin/index.ts b/src/plugin/index.ts index 39d7aa1c2..a2e9f2eb0 100644 --- a/src/plugin/index.ts +++ b/src/plugin/index.ts @@ -1,16 +1,13 @@ import fs from "node:fs"; import path from "node:path"; import { fileURLToPath } from "node:url"; - import type { Lavamusic } from "../structures/index.js"; - const __dirname = path.dirname(fileURLToPath(import.meta.url)); const pluginsFolder = path.join(__dirname, "plugins"); export default async function loadPlugins(client: Lavamusic): Promise { try { const pluginFiles = fs.readdirSync(pluginsFolder).filter((file) => file.endsWith(".js")); - for (const file of pluginFiles) { const pluginPath = path.join(pluginsFolder, file); const plugin = (await import(`file://${pluginPath}`)).default as BotPlugin; diff --git a/src/plugin/plugins/antiCrash.ts b/src/plugin/plugins/antiCrash.ts index 99f7a3bdb..bd84eb4ff 100644 --- a/src/plugin/plugins/antiCrash.ts +++ b/src/plugin/plugins/antiCrash.ts @@ -14,15 +14,12 @@ const antiCrash: BotPlugin = { process.exit(); } }; - process.on("unhandledRejection", (reason, promise) => { client.logger.error("Unhandled Rejection at:", promise, "reason:", reason); }); - process.on("uncaughtException", (err) => { client.logger.error("Uncaught Exception thrown:", err); }); - process.on("SIGINT", handleExit); process.on("SIGTERM", handleExit); process.on("SIGQUIT", handleExit); diff --git a/src/plugin/plugins/keepAlive.ts b/src/plugin/plugins/keepAlive.ts index 1f6075243..adf545818 100644 --- a/src/plugin/plugins/keepAlive.ts +++ b/src/plugin/plugins/keepAlive.ts @@ -1,5 +1,4 @@ import http from "node:http"; - import type { Lavamusic } from "../../structures/index.js"; import type { BotPlugin } from "../index.js"; @@ -13,7 +12,6 @@ const keepAlive: BotPlugin = { res.writeHead(200, { "Content-Type": "text/plain" }); res.end(`I'm alive! Currently serving ${client.guilds.cache.size} guilds.`); }); - server.listen(3000, () => { client.logger.info("Keep-Alive server is running on port 3000"); }); diff --git a/src/structures/Command.ts b/src/structures/Command.ts index a158614d9..0ef983c63 100644 --- a/src/structures/Command.ts +++ b/src/structures/Command.ts @@ -1,5 +1,4 @@ import type { ApplicationCommandOption, PermissionResolvable } from "discord.js"; - import type Lavamusic from "./Lavamusic.js"; interface CommandDescription { @@ -7,20 +6,17 @@ interface CommandDescription { usage: string; examples: string[]; } - interface CommandPlayer { voice: boolean; dj: boolean; active: boolean; djPerm: string | null; } - interface CommandPermissions { dev: boolean; client: string[] | PermissionResolvable; user: string[] | PermissionResolvable; } - interface CommandOptions { name: string; nameLocalizations?: Record; @@ -50,7 +46,6 @@ export default class Command { public slashCommand: boolean; public options: ApplicationCommandOption[]; public category: string; - constructor(client: Lavamusic, options: CommandOptions) { this.client = client; this.name = options.name; diff --git a/src/structures/Context.ts b/src/structures/Context.ts index aa0f93dae..f1aeb6a9c 100644 --- a/src/structures/Context.ts +++ b/src/structures/Context.ts @@ -17,7 +17,6 @@ import { type TextChannel, type User, } from "discord.js"; - import type { Lavamusic } from "./index.js"; export default class Context { @@ -113,7 +112,6 @@ export default class Context { return false; } } - function isInteractionReplyOptions(content: any): content is InteractionReplyOptions { return content instanceof Object; } diff --git a/src/structures/Dispatcher.ts b/src/structures/Dispatcher.ts index 00cb1e590..d5c507f3a 100644 --- a/src/structures/Dispatcher.ts +++ b/src/structures/Dispatcher.ts @@ -1,7 +1,5 @@ -/* eslint-disable @typescript-eslint/typedef */ import type { Message, User } from "discord.js"; import type { Node, Player, Track } from "shoukaku"; - import type { Lavamusic } from "./index.js"; export class Song implements Track { @@ -21,7 +19,6 @@ export class Song implements Track { requester: User; }; pluginInfo: unknown; - constructor(track: Song | Track, user: User) { if (!track) throw new Error("Track is not provided"); this.encoded = track.encoded; @@ -31,7 +28,6 @@ export class Song implements Track { }; } } - interface DispatcherOptions { client: Lavamusic; guildId: string; @@ -39,7 +35,6 @@ interface DispatcherOptions { player: Player; node: Node; } - export default class Dispatcher { private client: Lavamusic; public guildId: string; @@ -58,7 +53,6 @@ export default class Dispatcher { public autoplay: boolean; public nowPlayingMessage: Message | null; public history: Song[]; - constructor(options: DispatcherOptions) { this.client = options.client; this.guildId = options.guildId; @@ -76,7 +70,6 @@ export default class Dispatcher { this.autoplay = false; this.nowPlayingMessage = null; this.history = []; - this.player .on("start", () => this.client.shoukaku.emit("trackStart", this.player, this.current, this)) .on("end", () => { @@ -88,15 +81,12 @@ export default class Dispatcher { .on("stuck", () => this.client.shoukaku.emit("trackStuck", this.player, this.current)) .on("closed", (...args) => this.client.shoukaku.emit("socketClosed", this.player, ...args)); } - get exists(): boolean { return this.client.queue.has(this.guildId); } - get volume(): number { return this.player.volume; } - public play(): Promise { if (!(this.exists && (this.queue.length || this.current))) { return; @@ -110,27 +100,23 @@ export default class Dispatcher { } } } - public pause(): void { if (this.player) { this.paused = !this.paused; this.player.setPaused(this.paused); } } - public remove(index: number): void { if (this.player && index <= this.queue.length) { this.queue.splice(index, 1); } } - public previousTrack(): void { if (this.player && this.previous) { this.queue.unshift(this.previous); this.player.stopTrack(); } } - public destroy(): void { this.queue.length = 0; this.history = []; @@ -140,7 +126,6 @@ export default class Dispatcher { this.client.shoukaku.emit("playerDestroy", this.player); } } - public setShuffle(): void { if (this.player) { for (let i = this.queue.length - 1; i > 0; i--) { @@ -149,7 +134,6 @@ export default class Dispatcher { } } } - public skip(skipto = 1): void { if (this.player) { if (skipto > this.queue.length) { @@ -161,13 +145,11 @@ export default class Dispatcher { this.player.stopTrack(); } } - public seek(time: number): void { if (this.player) { this.player.seekTo(time); } } - public stop(): void { if (this.player) { this.queue.length = 0; @@ -179,27 +161,22 @@ export default class Dispatcher { this.player.stopTrack(); } } - public setLoop(loop: "off" | "repeat" | "queue"): void { this.loop = loop; } - public buildTrack(track: Song | Track, user: User): Song { return new Song(track, user); } - public async isPlaying(): Promise { if (this.queue.length && !this.current && !this.player.paused) { await this.play(); } } - public async Autoplay(song: Song): Promise { const resolve = await this.node.rest.resolve(`${this.client.config.searchEngine}:${song.info.author}`); if (!resolve?.data && Array.isArray(resolve.data)) { return this.destroy(); } - const metadata = resolve.data as Track[]; let chosen: Song | null = null; const maxAttempts = 10; @@ -218,7 +195,6 @@ export default class Dispatcher { } attempts++; } - if (chosen) { this.queue.push(chosen); await this.isPlaying(); @@ -226,7 +202,6 @@ export default class Dispatcher { this.destroy(); } } - public async setAutoplay(autoplay: boolean): Promise { this.autoplay = autoplay; if (autoplay) { diff --git a/src/structures/Event.ts b/src/structures/Event.ts index d5e8edcf3..9ec969946 100644 --- a/src/structures/Event.ts +++ b/src/structures/Event.ts @@ -1,5 +1,4 @@ import type Lavamusic from "./Lavamusic.js"; - interface EventOptions { name: string; one?: boolean; diff --git a/src/structures/Lavamusic.ts b/src/structures/Lavamusic.ts index 7ac97d9e1..7b85dd744 100644 --- a/src/structures/Lavamusic.ts +++ b/src/structures/Lavamusic.ts @@ -13,16 +13,13 @@ import { type RESTPostAPIChatInputApplicationCommandsJSONBody, Routes, } from "discord.js"; - import config from "../config.js"; import ServerData from "../database/server.js"; import loadPlugins from "../plugin/index.js"; import { Utils } from "../utils/Utils.js"; import Logger from "./Logger.js"; import { Queue, ShoukakuClient } from "./index.js"; - const __dirname = path.dirname(fileURLToPath(import.meta.url)); - export default class Lavamusic extends Client { public commands: Collection = new Collection(); public aliases: Collection = new Collection(); @@ -35,11 +32,9 @@ export default class Lavamusic extends Client { public shoukaku: ShoukakuClient; public utils = Utils; public queue = new Queue(this); - public embed(): EmbedBuilder { return new EmbedBuilder(); } - public async start(token: string): Promise { const nodes = this.config.autoNode ? await this.getNodes() : this.config.lavalink; this.shoukaku = new ShoukakuClient(this, nodes); @@ -58,7 +53,6 @@ export default class Lavamusic extends Client { } }); } - private async loadCommands(): Promise { const commandsPath = fs.readdirSync(path.join(__dirname, "../commands")); for (const dir of commandsPath) { @@ -102,23 +96,19 @@ export default class Lavamusic extends Client { } }); } - private async getNodes(): Promise { const params = new URLSearchParams({ ssl: "false", version: "v4", format: "shoukaku", }); - const res = await fetch(`https://lavainfo-api.deno.dev/nodes?${params.toString()}`, { headers: { "Content-Type": "application/json", }, }); - return await res.json(); } - private async loadEvents(): Promise { const eventsPath = fs.readdirSync(path.join(__dirname, "../events")); for (const dir of eventsPath) { diff --git a/src/structures/Logger.ts b/src/structures/Logger.ts index b097b9cf9..767e262fe 100644 --- a/src/structures/Logger.ts +++ b/src/structures/Logger.ts @@ -1,6 +1,5 @@ import pkg, { type SignaleOptions } from "signale"; const { Signale } = pkg; - const options: SignaleOptions = { disabled: false, interactive: false, diff --git a/src/structures/Queue.ts b/src/structures/Queue.ts index 392ad4293..588124a21 100644 --- a/src/structures/Queue.ts +++ b/src/structures/Queue.ts @@ -1,37 +1,28 @@ import type { Guild } from "discord.js"; import type { LavalinkResponse, Node } from "shoukaku"; - import { Dispatcher, type Lavamusic } from "./index.js"; - export class Queue extends Map { public client: Lavamusic; - constructor(client: Lavamusic) { super(); this.client = client; } - public override get(guildId: string): Dispatcher | undefined { return super.get(guildId); } - public override set(guildId: string, dispatcher: Dispatcher): this { return super.set(guildId, dispatcher); } - public override delete(guildId: string): boolean { return super.delete(guildId); } - public override clear(): void { super.clear(); } - public async create(guild: Guild, voice: any, channel: any, givenNode?: Node): Promise { if (!voice) throw new Error("No voice channel was provided"); if (!channel) throw new Error("No text channel was provided"); if (!guild) throw new Error("No guild was provided"); - let dispatcher = this.get(guild.id); if (!dispatcher) { const node = givenNode ?? this.client.shoukaku.options.nodeResolver(this.client.shoukaku.nodes); @@ -41,7 +32,6 @@ export class Queue extends Map { shardId: guild.shardId, deaf: true, }); - dispatcher = new Dispatcher({ client: this.client, guildId: guild.id, @@ -49,14 +39,11 @@ export class Queue extends Map { player, node, }); - this.set(guild.id, dispatcher); this.client.shoukaku.emit("playerCreate", dispatcher.player); } - return dispatcher; } - public async search(query: string): Promise { const node = this.client.shoukaku.options.nodeResolver(this.client.shoukaku.nodes); const searchQuery = /^https?:\/\//.test(query) ? query : `${this.client.config.searchEngine}:${query}`; diff --git a/src/structures/Shoukaku.ts b/src/structures/Shoukaku.ts index db393831f..595b83557 100644 --- a/src/structures/Shoukaku.ts +++ b/src/structures/Shoukaku.ts @@ -1,11 +1,8 @@ -/* eslint-disable @typescript-eslint/no-unsafe-enum-comparison */ import { Connectors, type NodeOption, Shoukaku } from "shoukaku"; - import type { Lavamusic } from "./index.js"; export default class ShoukakuClient extends Shoukaku { public client: Lavamusic; - constructor(client: Lavamusic, nodes: NodeOption[]) { super(new Connectors.DiscordJS(client), nodes, { moveOnDisconnect: false, @@ -21,23 +18,18 @@ export default class ShoukakuClient extends Shoukaku { .shift(), }); this.client = client; - this.on("ready", (name, reconnected) => { this.client.shoukaku.emit(reconnected ? "nodeReconnect" : "nodeConnect", name); }); - this.on("error", (name, error) => { this.client.shoukaku.emit("nodeError", name, error); }); - this.on("close", (name, code, reason) => { this.client.shoukaku.emit("nodeDestroy", name, code, reason); }); - this.on("disconnect", (name, count) => { this.client.shoukaku.emit("nodeDisconnect", name, count); }); - this.on("debug", (name, reason) => { this.client.shoukaku.emit("nodeRaw", name, reason); }); diff --git a/src/utils/BotLog.ts b/src/utils/BotLog.ts index fe270c00e..8e39a3579 100644 --- a/src/utils/BotLog.ts +++ b/src/utils/BotLog.ts @@ -1,15 +1,12 @@ import type { TextChannel } from "discord.js"; - import type { Lavamusic } from "../structures/index.js"; // biome-ignore lint/complexity/noStaticOnlyClass: export default class BotLog { public static send(client: Lavamusic, message: string, type: "error" | "warn" | "info" | "success" = "info"): void { if (!client?.channels.cache && client.config.logChannelId) return; - const channel = client.channels.cache.get(client.config.logChannelId) as TextChannel; if (!channel) return; - const colors: { [key: string]: number } = { error: 0xff0000, warn: 0xffff00, @@ -17,9 +14,7 @@ export default class BotLog { success: 0x00ff00, }; const color = colors[type] || 0x000000; - const embed = client.embed().setColor(color).setDescription(message).setTimestamp(); - channel.send({ embeds: [embed] }).catch(() => {}); } } diff --git a/src/utils/Buttons.ts b/src/utils/Buttons.ts index 52de8f826..39d1ae1d1 100644 --- a/src/utils/Buttons.ts +++ b/src/utils/Buttons.ts @@ -4,20 +4,20 @@ import type { Dispatcher } from "../structures/index.js"; function getButtons(player: Dispatcher): ActionRowBuilder[] { const buttonData = [ - { customId: "LOOP_BUT", emoji: "🔁", style: ButtonStyle.Secondary }, - { customId: "PREV_BUT", emoji: "⏎ī¸", style: ButtonStyle.Secondary }, + {customId: "REWIND_BUT", emoji: "âĒ", style: ButtonStyle.Secondary}, + {customId: "LOW_VOL_BUT", emoji: "🔉", style: ButtonStyle.Secondary}, + {customId: "STOP_BUT", emoji: "⏚ī¸", style: ButtonStyle.Danger}, + {customId: "HIGH_VOL_BUT", emoji: "🔊", style: ButtonStyle.Secondary}, + {customId: "FORWARD_BUT", emoji: "⏊", style: ButtonStyle.Secondary}, + {customId: "PREV_BUT", emoji: "⏎ī¸", style: ButtonStyle.Secondary}, + {customId: "LOOP_BUT", emoji: "🔁", style: ButtonStyle.Secondary}, { customId: "PAUSE_BUT", emoji: player?.paused ? "â–ļī¸" : "⏸ī¸", style: player?.paused ? ButtonStyle.Success : ButtonStyle.Secondary, }, - { customId: "SKIP_BUT", emoji: "⏭ī¸", style: ButtonStyle.Secondary }, - { customId: "SHUFFLE_BUT", emoji: "🔀", style: ButtonStyle.Secondary }, - { customId: "FORWARD_BUT", emoji: "⏊", style: ButtonStyle.Secondary }, - { customId: "LOW_VOL_BUT", emoji: "🔉", style: ButtonStyle.Secondary }, - { customId: "STOP_BUT", emoji: "⏚ī¸", style: ButtonStyle.Danger }, - { customId: "HIGH_VOL_BUT", emoji: "🔊", style: ButtonStyle.Secondary }, - { customId: "REWIND_BUT", emoji: "âĒ", style: ButtonStyle.Secondary }, + {customId: "SHUFFLE_BUT", emoji: "🔀", style: ButtonStyle.Secondary}, + {customId: "SKIP_BUT", emoji: "⏭ī¸", style: ButtonStyle.Secondary}, ]; const rows = []; diff --git a/src/utils/LavaLogo.txt b/src/utils/LavaLogo.txt index 2684abb69..99dde6d5d 100644 --- a/src/utils/LavaLogo.txt +++ b/src/utils/LavaLogo.txt @@ -1,17 +1,17 @@ - - █░░ ▄▀█ █░█ ▄▀█ █▀▄▀█ █░█ █▀ █ █▀▀ - █▄▄ █▀█ ▀▄▀ █▀█ █░▀░█ █▄█ ▄█ █ █▄▄ - - .:::.=++=:.:-: - =##############* - *###############. - =++=*####*=++=: - .*##*: - .+######*: - =*#########+. - :*############*- - =################*. - :*##################*= - .+######################*: - *#########################. - .::::::::::::::::::::::::. + + █░░ ▄▀█ █░█ ▄▀█ █▀▄▀█ █░█ █▀ █ █▀▀ + █▄▄ █▀█ ▀▄▀ █▀█ █░▀░█ █▄█ ▄█ █ █▄▄ + + .:::.=++=:.:-: + =##############* + *###############. + =++=*####*=++=: + .*##*: + .+######*: + =*#########+. + :*############*- + =################*. + :*##################*= + .+######################*: + *#########################. + .::::::::::::::::::::::::. diff --git a/src/utils/SetupSystem.ts b/src/utils/SetupSystem.ts index 9c2314072..250fad923 100644 --- a/src/utils/SetupSystem.ts +++ b/src/utils/SetupSystem.ts @@ -1,16 +1,13 @@ import { type ColorResolvable, EmbedBuilder, type Message, type TextChannel } from "discord.js"; import { LoadType } from "shoukaku"; - import type { Song } from "../structures/Dispatcher.js"; import type { Dispatcher, Lavamusic } from "../structures/index.js"; import { getButtons } from "./Buttons.js"; function neb(embed: EmbedBuilder, player: Dispatcher, client: Lavamusic): EmbedBuilder { if (!player?.current?.info) return embed; - const iconUrl = client.config.icons[player.current.info.sourceName] || client.user.displayAvatarURL({ extension: "png" }); const icon = player.current.info.artworkUrl || client.config.links.img; - return embed .setAuthor({ name: "Now Playing", iconURL: iconUrl }) .setDescription( @@ -27,7 +24,6 @@ async function setupStart(client: Lavamusic, query: string, player: Dispatcher, let m: Message; const embed = client.embed(); const n = client.embed().setColor(client.color.main); - const data = await client.db.getSetup(message.guild.id); try { if (data) m = await message.channel.messages.fetch({ message: data.messageId, cache: true }); @@ -62,7 +58,6 @@ async function setupStart(client: Lavamusic, query: string, player: Dispatcher, break; case LoadType.TRACK: { const track = player.buildTrack(res.data, message.author); - if (player.queue.length > client.config.maxQueueSize) { await message.channel .send({ @@ -311,7 +306,7 @@ async function updateSetup(client: Lavamusic, guild: any): Promise { name: client.user.username, iconURL: client.user.displayAvatarURL({ extension: "png" }), }) - .setDescription("Nothing playing right now") + .setDescription("Nothing playing right now.") .setImage(client.config.links.img); await m .edit({ @@ -346,11 +341,9 @@ async function buttonReply(int: any, args: string, color: ColorResolvable): Prom async function oops(channel: TextChannel, args: string): Promise { try { const embed1 = new EmbedBuilder().setColor("Red").setDescription(`${args}`); - const m = await channel.send({ embeds: [embed1], }); - setTimeout(async () => await m.delete().catch(() => {}), 12000); } catch (e) { return console.error(e); diff --git a/src/utils/Utils.ts b/src/utils/Utils.ts index df0297a73..1ed79e27e 100644 --- a/src/utils/Utils.ts +++ b/src/utils/Utils.ts @@ -1,5 +1,4 @@ import { ActionRowBuilder, ActivityType, ButtonBuilder, ButtonStyle, CommandInteraction, type TextChannel } from "discord.js"; - import config from "../config.js"; import type { Context, Lavamusic } from "../structures/index.js"; @@ -182,7 +181,6 @@ export class Utils { }); } }); - collector.on("end", async () => { await msg.edit({ embeds: [embed[page]], components: [] }); });