mirror of
https://github.com/aydenjahola/discord-multipurpose-bot.git
synced 2025-09-21 06:41:35 +01:00
Some checks are pending
Docker / build (push) Waiting to run
* add simple music functionality * update workflow * update Dockerfile * update Dockerfile * update Dockerfile * update Dockerfile * add few more music commands * add lyrics command * update lyrics command * add loop, and add categories to all commands * change discord status * seperate distube and change startup console theme * Update README * UPDATE LICENSE file * fix docker compose image, add better error handling for distube and update tagging workflow * switch to node-alpine image for docker * switch to node-alpine image for docker * update ascii * music commands imporvements, implement live lyrics, some guards and bot leaving on empty * use ffmpeg package rather than ffmpeg-static
140 lines
4.7 KiB
JavaScript
140 lines
4.7 KiB
JavaScript
const { SlashCommandBuilder } = require("discord.js");
|
||
const { requireVC, requireQueue } = require("../../utils/musicGuards");
|
||
|
||
module.exports = {
|
||
data: new SlashCommandBuilder()
|
||
.setName("skip")
|
||
.setDescription(
|
||
"Skips the current song (or jump to a specific upcoming track)."
|
||
)
|
||
.addIntegerOption((o) =>
|
||
o
|
||
.setName("to")
|
||
.setDescription(
|
||
"Queue index to jump to (as shown in /queue). 1 = next song."
|
||
)
|
||
.setMinValue(1)
|
||
),
|
||
category: "Music",
|
||
|
||
async execute(interaction, client) {
|
||
try {
|
||
await interaction.deferReply();
|
||
|
||
requireVC(interaction);
|
||
const queue = requireQueue(client, interaction);
|
||
|
||
const toIndex = interaction.options.getInteger("to"); // 1-based (1 = next)
|
||
const total = queue.songs.length;
|
||
const upcomingCount = Math.max(0, total - 1);
|
||
|
||
if (upcomingCount === 0 && !queue.autoplay) {
|
||
// Nothing to skip to, and autoplay is off -> stop and leave
|
||
try {
|
||
queue.stop();
|
||
} catch {}
|
||
client.distube.voices.leave(interaction.guildId);
|
||
try {
|
||
const live = require("../../utils/liveLyricsManager");
|
||
await live.stop(interaction.guildId, { deleteThread: true });
|
||
} catch {}
|
||
return interaction.followUp(
|
||
"🏁 No more songs — stopped and left the voice channel."
|
||
);
|
||
}
|
||
|
||
// If user specified a target index (jump)
|
||
if (toIndex != null) {
|
||
if (toIndex > upcomingCount) {
|
||
// Jumping past the end
|
||
// Clear all upcoming; then behave like “no more songs”
|
||
queue.songs.splice(1); // remove all upcoming
|
||
if (!queue.autoplay) {
|
||
try {
|
||
queue.stop();
|
||
} catch {}
|
||
client.distube.voices.leave(interaction.guildId);
|
||
try {
|
||
const live = require("../../utils/liveLyricsManager");
|
||
await live.stop(interaction.guildId, { deleteThread: true });
|
||
} catch {}
|
||
return interaction.followUp(
|
||
`⏭️ Skipped past the end (${toIndex}). Queue empty — stopped and left.`
|
||
);
|
||
}
|
||
// Autoplay on: try to skip and let autoplay find a related track
|
||
try {
|
||
queue.skip(); // will trigger autoplay resolution
|
||
} catch {}
|
||
try {
|
||
const live = require("../../utils/liveLyricsManager");
|
||
await live.stop(interaction.guildId, { deleteThread: true });
|
||
} catch {}
|
||
return interaction.followUp(
|
||
`⏭️ Skipped past the end (${toIndex}). Autoplay will pick something.`
|
||
);
|
||
}
|
||
|
||
// Remove the tracks between current and target (keep current at index 0)
|
||
// Example: toIndex=1 -> remove none, we’ll just skip once below.
|
||
if (toIndex > 1) {
|
||
// delete from position 1..(toIndex-1)
|
||
queue.songs.splice(1, toIndex - 1);
|
||
}
|
||
|
||
// Now the desired target is at index 1, skip once to play it
|
||
try {
|
||
queue.skip();
|
||
} catch (e) {
|
||
// If skip throws but autoplay is on, let autoplay do its thing
|
||
if (!queue.autoplay) throw e;
|
||
}
|
||
|
||
// Stop any active live-lyrics thread for the current song
|
||
try {
|
||
const live = require("../../utils/liveLyricsManager");
|
||
await live.stop(interaction.guildId, { deleteThread: true });
|
||
} catch {}
|
||
|
||
return interaction.followUp(
|
||
`⏭️ Jumped to track **#${toIndex}** in the queue.`
|
||
);
|
||
}
|
||
|
||
// Simple “skip next”
|
||
try {
|
||
queue.skip();
|
||
} catch (e) {
|
||
// If there’s no next but autoplay is on, allow autoplay
|
||
if (!queue.autoplay) {
|
||
// Fallback: nothing to skip to
|
||
try {
|
||
queue.stop();
|
||
} catch {}
|
||
client.distube.voices.leave(interaction.guildId);
|
||
try {
|
||
const live = require("../../utils/liveLyricsManager");
|
||
await live.stop(interaction.guildId, { deleteThread: true });
|
||
} catch {}
|
||
return interaction.followUp(
|
||
"🏁 No more songs — stopped and left the voice channel."
|
||
);
|
||
}
|
||
}
|
||
|
||
try {
|
||
const live = require("../../utils/liveLyricsManager");
|
||
await live.stop(interaction.guildId, { deleteThread: true });
|
||
} catch {}
|
||
|
||
return interaction.followUp("⏭️ Skipped the current song!");
|
||
} catch (e) {
|
||
console.error("skip command failed:", e);
|
||
const msg = e?.message || "❌ Failed to skip.";
|
||
if (interaction.deferred || interaction.replied) {
|
||
return interaction.followUp({ content: msg, ephemeral: true });
|
||
}
|
||
return interaction.reply({ content: msg, ephemeral: true });
|
||
}
|
||
},
|
||
};
|