diff --git a/pkg/bot/bot.go b/pkg/bot/bot.go index b62819c..4d3f653 100644 --- a/pkg/bot/bot.go +++ b/pkg/bot/bot.go @@ -105,6 +105,7 @@ func (bot *MusicBot) registerCommands() { bot.registerCommand(currentCommand) bot.registerCommand(queueCommand) bot.registerCommand(flushCommand) + bot.registerCommand(shuffleCommand) bot.registerCommand(whiteListCommand) bot.registerCommand(volCommand) bot.registerCommand(aboutCommand) diff --git a/pkg/bot/commands.go b/pkg/bot/commands.go index 1dae771..36bf177 100644 --- a/pkg/bot/commands.go +++ b/pkg/bot/commands.go @@ -197,6 +197,19 @@ var flushCommand = &Command{ }, } +var shuffleCommand = &Command{ + Name: "shuffle", + Function: func(bot *MusicBot, message Message) { + bot.musicPlayer.GetQueue().Shuffle() + + if message.IsPrivate { + bot.BroadcastMessage(fmt.Sprintf("%s shuffled the queue", message.Sender.NickName)) + } + + bot.ReplyToMessage(message, "Queue shuffled") + }, +} + var whiteListCommand = &Command{ Name: "whitelist", MasterOnly: true, diff --git a/pkg/music/queue.go b/pkg/music/queue.go index d14fa6d..62ad9f7 100644 --- a/pkg/music/queue.go +++ b/pkg/music/queue.go @@ -2,6 +2,7 @@ package music import ( "log" + "math/rand" "sync" "errors" @@ -16,8 +17,9 @@ const ( // Queue holds an array of songs type Queue struct { *eventemitter.Emitter - songs []*Song - lock sync.Mutex + songs []*Song + lock sync.Mutex + randSource *rand.Rand } func (queue *Queue) Append(songs ...*Song) { @@ -88,6 +90,16 @@ func (queue *Queue) GetNextN(limit int) ([]Song, error) { return result, nil } +func (queue *Queue) Shuffle() { + queue.lock.Lock() + defer queue.lock.Unlock() + + // Shuffle numbers, swapping corresponding entries in letters at the same time. + queue.randSource.Shuffle(len(queue.songs), func(i, j int) { + queue.songs[i], queue.songs[j] = queue.songs[j], queue.songs[i] + }) +} + func (queue *Queue) Flush() { queue.lock.Lock() defer queue.lock.Unlock() @@ -115,7 +127,8 @@ func (queue *Queue) WaitForNext() *Song { // NewQueue creates a new instance of Queue func NewQueue() *Queue { return &Queue{ - songs: make([]*Song, 0), - Emitter: eventemitter.NewEmitter(true), + songs: make([]*Song, 0), + Emitter: eventemitter.NewEmitter(true), + randSource: rand.New(rand.NewSource(time.Now().UTC().UnixNano())), } } diff --git a/pkg/music/queue_test.go b/pkg/music/queue_test.go index 5c9ea5e..9e6f0ea 100644 --- a/pkg/music/queue_test.go +++ b/pkg/music/queue_test.go @@ -2,6 +2,7 @@ package music import ( "github.com/stretchr/testify/assert" + "math/rand" "testing" "time" ) @@ -124,6 +125,22 @@ func TestQueue_GetTotalDuration(t *testing.T) { assert.Equal(t, 2*time.Minute, queue.GetTotalDuration()) } +func TestQueue_Shuffle(t *testing.T) { + queue, _, _ := getTestQueue() + + queue.Append(&Song{ + Duration: time.Minute, + Name: "song3", + }) + + queue.randSource = rand.New(rand.NewSource(1)) + original := append([]*Song(nil), queue.songs...) + + queue.Shuffle() + + assert.NotEqual(t, original, queue.songs) +} + func TestQueue_WaitForNext(t *testing.T) { t.Parallel()