diff --git a/commands.go b/commands.go index 034abfa..4fdd055 100644 --- a/commands.go +++ b/commands.go @@ -95,6 +95,13 @@ func parseCommand(user *gumble.User, username, command string) { } else { user.Send(NO_PERMISSION_MSG) } + // Numsongs command + case dj.conf.Aliases.NumSongsAlias: + if dj.HasPermission(username, dj.conf.Permissions.AdminNumSongs) { + numSongs() + } else { + user.Send(NO_PERMISSION_MSG) + } // Kill command case dj.conf.Aliases.KillAlias: if dj.HasPermission(username, dj.conf.Permissions.AdminKill) { @@ -284,6 +291,17 @@ func reset(username string) { } } +// Performs numsongs functionality. Uses the SongQueue traversal function to traverse the +// queue with a function call that increments a counter. Once finished, the bot outputs +// the number of songs in the queue to chat. +func numSongs() { + songCount := 0 + dj.queue.Traverse(func(i int, item QueueItem) { + songCount += 1 + }) + dj.client.Self().Channel().Send(fmt.Sprintf(NUM_SONGS_HTML, songCount), false) +} + // Performs kill functionality. First cleans the ~/.mumbledj/songs directory to get rid of any // excess m4a files. The bot then safely disconnects from the server. func kill() { diff --git a/mumbledj.gcfg b/mumbledj.gcfg index 7db62e4..f9be6cc 100644 --- a/mumbledj.gcfg +++ b/mumbledj.gcfg @@ -67,6 +67,10 @@ ReloadAlias = "reload" # DEFAULT VALUE: "reset" ResetAlias = "reset" +# Alias used for numsongs command +# DEFAULT VALUE: "numsongs" +NumSongsAlias = "numsongs" + # Alias used for kill command # DEFAULT VALUE: "kill" KillAlias = "kill" @@ -115,6 +119,10 @@ AdminReload = true # DEFAULT VALUE: true AdminReset = true +# Make numsongs an admin command? +# DEFAULT VALUE: false +AdminNumSongs = false + # Make kill an admin command? # DEFAULT VALUE: true (I recommend never changing this to false) AdminKill = true diff --git a/parseconfig.go b/parseconfig.go index dcd407d..3a0e2be 100644 --- a/parseconfig.go +++ b/parseconfig.go @@ -35,6 +35,7 @@ type DjConfig struct { MoveAlias string ReloadAlias string ResetAlias string + NumSongsAlias string KillAlias string } Permissions struct { @@ -47,6 +48,7 @@ type DjConfig struct { AdminMove bool AdminReload bool AdminReset bool + AdminNumSongs bool AdminKill bool } } diff --git a/songqueue.go b/songqueue.go index bce90e2..f1bc082 100644 --- a/songqueue.go +++ b/songqueue.go @@ -58,6 +58,21 @@ func (q *SongQueue) Len() int { return len(q.queue) } +// A traversal function for SongQueue. Allows a visit function to be passed in which performs +// the specified action on each queue item. Traverses all individual songs, and all songs +// within playlists. +func (q *SongQueue) Traverse(visit func(i int, item QueueItem)) { + for iQueue, queueItem := range q.queue { + if queueItem.ItemType() == "playlist" { + for iPlaylist, playlistItem := range q.queue[iQueue].(*Playlist).songs.queue { + visit(iPlaylist, playlistItem) + } + } else { + visit(iQueue, queueItem) + } + } +} + // OnItemFinished event. Deletes item that just finished playing, then queues the next item. func (q *SongQueue) OnItemFinished() { if q.Len() != 0 { diff --git a/strings.go b/strings.go index 8cfe78d..ef9b947 100644 --- a/strings.go +++ b/strings.go @@ -106,3 +106,8 @@ const VOLUME_SUCCESS_HTML = ` const QUEUE_RESET_HTML = ` %s has cleared the song queue. ` + +// Message shown to users when a user asks how many songs are in the queue. +const NUM_SONGS_HTML = ` + There are currently %d song(s) in the queue. +`