diff --git a/commands.go b/commands.go
index 5d3d0de..ac5b332 100644
--- a/commands.go
+++ b/commands.go
@@ -152,6 +152,15 @@ func parseCommand(user *gumble.User, username, command string) {
} else {
dj.SendPrivateMessage(user, NO_PERMISSION_MSG)
}
+
+ // Shuffle command
+ case dj.conf.Aliases.ShuffleAlias:
+ if dj.HasPermission(username, dj.conf.Permissions.AdminShuffle) {
+ shuffleSongs(user, username)
+ } else {
+ dj.SendPrivateMessage(user, NO_PERMISSION_MSG)
+ }
+
default:
dj.SendPrivateMessage(user, COMMAND_DOESNT_EXIST_MSG)
}
@@ -391,3 +400,13 @@ func deleteSongs() error {
}
return nil
}
+
+// shuffles the song list
+func shuffleSongs(user *gumble.User, username string) {
+ if dj.queue.Len() > 1 {
+ dj.queue.ShuffleSongs()
+ dj.client.Self.Channel.Send(fmt.Sprintf(SHUFFLE_SUCCESS_MSG, username), false)
+ } else {
+ dj.SendPrivateMessage(user, CANT_SHUFFLE_MSG)
+ }
+}
diff --git a/config.gcfg b/config.gcfg
index db67c05..1b6a6a2 100644
--- a/config.gcfg
+++ b/config.gcfg
@@ -55,7 +55,7 @@ LowestVolume = 0.01
# DEFAULT VALUE: 0.8
HighestVolume = 0.8
-
+
[Aliases]
# Alias used for add command
@@ -126,6 +126,9 @@ CacheSizeAlias = "cachesize"
# DEFAULT VALUE: "kill"
KillAlias = "kill"
+# Alias used for shuffle command
+# DEFAULT VALUE: "shuffle"
+ShuffleAlias = "shuffle"
[Permissions]
@@ -201,3 +204,7 @@ AdminCacheSize = true
# Make kill an admin command?
# DEFAULT VALUE: true (I recommend never changing this to false)
AdminKill = true
+
+# Make shuffle an admin command?
+# DEFAULT VALUE: true
+AdminShuffle = true
diff --git a/parseconfig.go b/parseconfig.go
index 9da7ec2..f0ff824 100644
--- a/parseconfig.go
+++ b/parseconfig.go
@@ -51,6 +51,7 @@ type DjConfig struct {
NumCachedAlias string
CacheSizeAlias string
KillAlias string
+ ShuffleAlias string
}
Permissions struct {
AdminsEnabled bool
@@ -70,6 +71,7 @@ type DjConfig struct {
AdminNumCached bool
AdminCacheSize bool
AdminKill bool
+ AdminShuffle bool
}
}
diff --git a/songqueue.go b/songqueue.go
index f1bdc1c..c596fb1 100644
--- a/songqueue.go
+++ b/songqueue.go
@@ -11,8 +11,13 @@ import (
"errors"
"fmt"
"time"
+ "math/rand"
)
+func init() {
+ rand.Seed(time.Now().UTC().UnixNano())
+}
+
// SongQueue type declaration.
type SongQueue struct {
queue []Song
@@ -104,3 +109,11 @@ func (q *SongQueue) PrepareAndPlayNextSong() {
q.OnSongFinished()
}
}
+
+// Shuffles the songqueue using inside-out algorithm
+func (q *SongQueue) ShuffleSongs() {
+ for i := range q.queue[1:] { //Don't touch currently playing song
+ j := rand.Intn(i + 1)
+ q.queue[i + 1], q.queue[j + 1] = q.queue[j + 1], q.queue[i + 1]
+ }
+}
diff --git a/strings.go b/strings.go
index 76b7541..6a59fad 100644
--- a/strings.go
+++ b/strings.go
@@ -71,6 +71,12 @@ const CACHE_SIZE_MSG = "The cache is currently %g MB in size."
// Message shown to user when they attempt to issue a cache-related command when caching is not enabled.
const CACHE_NOT_ENABLED_MSG = "The cache is not currently enabled."
+// Message shown to user when they attempt to shuffle the a playlist with less than 2 elements.
+const CANT_SHUFFLE_MSG = "Can't shuffle the playlist if there is less than 2 songs."
+
+// Message shown to user when the playlist has been successfully shuffled.
+const SHUFFLE_SUCCESS_MSG = "The playlist has been successfully shuffled by %s (starting from next song)."
+
// Message shown to channel when a song is added to the queue by a user.
const SONG_ADDED_HTML = `
%s has added "%s" to the queue.
@@ -107,6 +113,7 @@ const HELP_HTML = `
!reset - An admin command that resets the song queue.
!forceskip - An admin command that forces a song skip.
!forceskipplaylist - An admin command that forces a playlist skip.
+!shuffle - An admin command that shuffles the playlist.
!move - Moves MumbleDJ into channel if it exists.
!reload - Reloads mumbledj.gcfg configuration settings.
!setcomment - Sets the comment for the bot.