From 2cf68e1fd687f720be8688e6df01c66369249272 Mon Sep 17 00:00:00 2001 From: Callum Seabrook Date: Sun, 4 May 2025 15:09:11 +0100 Subject: [PATCH 1/2] feat: skip multiple tracks at once --- commands/music.go | 7 +++++++ commands/skip.go | 17 ++++++++++++----- lavalinkbot/queue.go | 11 ++++++++--- 3 files changed, 27 insertions(+), 8 deletions(-) diff --git a/commands/music.go b/commands/music.go index 9e80554..4f57211 100644 --- a/commands/music.go +++ b/commands/music.go @@ -240,6 +240,13 @@ var music = discord.SlashCommandCreate{ discord.ApplicationCommandOptionSubCommand{ Name: "skip", Description: "Skips the current track", + Options: []discord.ApplicationCommandOption{ + discord.ApplicationCommandOptionInt{ + Name: "count", + Description: "The number of tracks to skip", + Required: false, + }, + }, }, discord.ApplicationCommandOptionSubCommand{ Name: "pause", diff --git a/commands/skip.go b/commands/skip.go index 5636b7b..a490022 100644 --- a/commands/skip.go +++ b/commands/skip.go @@ -2,6 +2,7 @@ package commands import ( "context" + "fmt" "time" "github.com/disgoorg/disgo/discord" @@ -9,24 +10,30 @@ import ( "github.com/disgoorg/disgolink/v3/lavalink" ) -func (c *Commands) Skip(_ discord.SlashCommandInteractionData, e *handler.CommandEvent) error { +func (c *Commands) Skip(data discord.SlashCommandInteractionData, e *handler.CommandEvent) error { ctx, cancel := context.WithTimeout(e.Ctx, 10*time.Second) defer cancel() + + var trackCount = data.Int("count") + if trackCount == 0 { + trackCount = 1 + } + player := c.Lavalink.ExistingPlayer(*e.GuildID()) - track, ok := c.MusicQueue.Next(*e.GuildID()) + track, ok := c.MusicQueue.NextCount(*e.GuildID(), trackCount) if !ok { return e.CreateMessage(discord.MessageCreate{ - Content: "No more tracks in queue", + Content: "Not enough tracks to skip", Flags: discord.MessageFlagEphemeral, }) } if err := player.Update(ctx, lavalink.WithTrack(track)); err != nil { return e.CreateMessage(discord.MessageCreate{ - Content: "Failed to play skip track", + Content: "Failed to skip track(s)", }) } return e.CreateMessage(discord.MessageCreate{ - Content: "⏭ Skipped track", + Content: fmt.Sprintf("⏭ Skipped %d track(s)", trackCount), }) } diff --git a/lavalinkbot/queue.go b/lavalinkbot/queue.go index 9a8bbe4..3394eca 100644 --- a/lavalinkbot/queue.go +++ b/lavalinkbot/queue.go @@ -132,6 +132,10 @@ func (q *PlayerManager) SetRepeatMode(guildID snowflake.ID, mode RepeatMode) { } func (q *PlayerManager) Next(guildID snowflake.ID) (lavalink.Track, bool) { + return q.NextCount(guildID, 1) +} + +func (q *PlayerManager) NextCount(guildID snowflake.ID, count int) (lavalink.Track, bool) { q.mu.Lock() defer q.mu.Unlock() @@ -139,15 +143,16 @@ func (q *PlayerManager) Next(guildID snowflake.ID) (lavalink.Track, bool) { if !ok { return lavalink.Track{}, false } - if len(qq.tracks) == 0 { + if len(qq.tracks) < count { return lavalink.Track{}, false } - track := qq.tracks[0] + + track := qq.tracks[count-1] if qq.mode != RepeatModeTrack { if qq.mode == RepeatModeQueue { qq.tracks = append(qq.tracks, track) } - qq.tracks = qq.tracks[1:] + qq.tracks = qq.tracks[count:] } return track, true } From 23b41b54d6b4e9d0c7ba92b3b954a9a602c87685 Mon Sep 17 00:00:00 2001 From: Callum Seabrook Date: Sun, 4 May 2025 15:27:21 +0100 Subject: [PATCH 2/2] feat: implement remove command --- commands/music.go | 1 + commands/remove.go | 21 +++++++++++++++++++++ lavalinkbot/queue.go | 10 ++++++++-- main.go | 2 +- 4 files changed, 31 insertions(+), 3 deletions(-) create mode 100644 commands/remove.go diff --git a/commands/music.go b/commands/music.go index 4f57211..a705917 100644 --- a/commands/music.go +++ b/commands/music.go @@ -352,6 +352,7 @@ var music = discord.SlashCommandCreate{ Description: "The index of the track to remove", Required: true, Autocomplete: true, + MinValue: json.Ptr(0), }, }, }, diff --git a/commands/remove.go b/commands/remove.go new file mode 100644 index 0000000..429dfe8 --- /dev/null +++ b/commands/remove.go @@ -0,0 +1,21 @@ +package commands + +import ( + "fmt" + "github.com/disgoorg/disgo/discord" + "github.com/disgoorg/disgo/handler" +) + +func (c *Commands) Remove(data discord.SlashCommandInteractionData, e *handler.CommandEvent) error { + index := data.Int("index") + ok := c.MusicQueue.Remove(*e.GuildID(), index-1, index) + if !ok { + return e.CreateMessage(discord.MessageCreate{ + Content: fmt.Sprintf("Failed to remove track %d from queue", index), + }) + } + + return e.CreateMessage(discord.MessageCreate{ + Content: fmt.Sprintf("Removed track %d from queue", index), + }) +} diff --git a/lavalinkbot/queue.go b/lavalinkbot/queue.go index 3394eca..ab3eab7 100644 --- a/lavalinkbot/queue.go +++ b/lavalinkbot/queue.go @@ -76,13 +76,18 @@ func (q *PlayerManager) Add(guildID snowflake.ID, channelID snowflake.ID, tracks qq.tracks = append(qq.tracks, tracks...) } -func (q *PlayerManager) Remove(guildID snowflake.ID, from int, to int) { +func (q *PlayerManager) Remove(guildID snowflake.ID, from int, to int) bool { q.mu.Lock() defer q.mu.Unlock() qq, ok := q.queues[guildID] if !ok { - return + return false + } + + queueLen := len(qq.tracks) + if from >= queueLen || to >= queueLen { + return false } if to == 0 { @@ -90,6 +95,7 @@ func (q *PlayerManager) Remove(guildID snowflake.ID, from int, to int) { } qq.tracks = append(qq.tracks[:from], qq.tracks[to:]...) + return true } func (q *PlayerManager) Clear(guildID snowflake.ID) { diff --git a/main.go b/main.go index 8f3c4ba..059a4a6 100644 --- a/main.go +++ b/main.go @@ -97,7 +97,7 @@ func main() { r.SlashCommand("/queue", cmds.Queue) r.SlashCommand("/now-playing", cmds.NowPlaying) // r.SlashCommand("/lyrics", cmds.Lyrics) - // r.SlashCommand("/remove", cmds.Remove) + r.SlashCommand("/remove", cmds.Remove) // r.SlashCommand("/move", cmds.Move) // r.SlashCommand("/swap", cmds.Swap) // r.SlashCommand("/clear", cmds.Clear)