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.
+`