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.