Reached feature parity with Lua MumbleDJ
This commit is contained in:
parent
8c15a1d5bd
commit
ecc0cd30c1
108
commands.go
108
commands.go
|
@ -8,9 +8,11 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/kennygrant/sanitize"
|
"github.com/kennygrant/sanitize"
|
||||||
"github.com/layeh/gumble/gumble"
|
"github.com/layeh/gumble/gumble"
|
||||||
|
"os"
|
||||||
"regexp"
|
"regexp"
|
||||||
"strconv"
|
"strconv"
|
||||||
"strings"
|
"strings"
|
||||||
|
@ -33,9 +35,16 @@ func parseCommand(user *gumble.User, username, command string) {
|
||||||
if argument == "" {
|
if argument == "" {
|
||||||
user.Send(NO_ARGUMENT_MSG)
|
user.Send(NO_ARGUMENT_MSG)
|
||||||
} else {
|
} else {
|
||||||
success, songTitle := add(username, argument)
|
if songTitle, err := add(username, argument); err == nil {
|
||||||
if success {
|
|
||||||
dj.client.Self().Channel().Send(fmt.Sprintf(SONG_ADDED_HTML, username, songTitle), false)
|
dj.client.Self().Channel().Send(fmt.Sprintf(SONG_ADDED_HTML, username, songTitle), false)
|
||||||
|
if dj.queue.Len() == 1 && !dj.audioStream.IsPlaying() {
|
||||||
|
dj.currentSong = dj.queue.NextSong()
|
||||||
|
if err := dj.currentSong.Download(); err == nil {
|
||||||
|
dj.currentSong.Play()
|
||||||
|
} else {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
} else {
|
} else {
|
||||||
user.Send(INVALID_URL_MSG)
|
user.Send(INVALID_URL_MSG)
|
||||||
}
|
}
|
||||||
|
@ -45,19 +54,16 @@ func parseCommand(user *gumble.User, username, command string) {
|
||||||
}
|
}
|
||||||
case dj.conf.Aliases.SkipAlias:
|
case dj.conf.Aliases.SkipAlias:
|
||||||
if dj.HasPermission(username, dj.conf.Permissions.AdminSkip) {
|
if dj.HasPermission(username, dj.conf.Permissions.AdminSkip) {
|
||||||
success := skip(username, false)
|
if err := skip(username, false); err == nil {
|
||||||
if success {
|
|
||||||
fmt.Println("Skip successful!")
|
|
||||||
dj.client.Self().Channel().Send(fmt.Sprintf(SKIP_ADDED_HTML, username), false)
|
dj.client.Self().Channel().Send(fmt.Sprintf(SKIP_ADDED_HTML, username), false)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
user.Send(NO_PERMISSION_MSG)
|
user.Send(NO_PERMISSION_MSG)
|
||||||
}
|
}
|
||||||
case dj.conf.Aliases.AdminSkipAlias:
|
case dj.conf.Aliases.AdminSkipAlias:
|
||||||
if dj.HasPermission(username, dj.conf.Permissions.AdminSkip) {
|
if dj.HasPermission(username, true) {
|
||||||
success := skip(username, true)
|
if err := skip(username, true); err == nil {
|
||||||
if success {
|
dj.client.Self().Channel().Send(ADMIN_SONG_SKIP_MSG, false)
|
||||||
fmt.Println("Forceskip successful!")
|
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
user.Send(NO_PERMISSION_MSG)
|
user.Send(NO_PERMISSION_MSG)
|
||||||
|
@ -67,9 +73,10 @@ func parseCommand(user *gumble.User, username, command string) {
|
||||||
if argument == "" {
|
if argument == "" {
|
||||||
dj.client.Self().Channel().Send(fmt.Sprintf(CUR_VOLUME_HTML, dj.conf.Volume.DefaultVolume), false)
|
dj.client.Self().Channel().Send(fmt.Sprintf(CUR_VOLUME_HTML, dj.conf.Volume.DefaultVolume), false)
|
||||||
} else {
|
} else {
|
||||||
success := volume(username, argument)
|
if err := volume(username, argument); err == nil {
|
||||||
if success {
|
dj.client.Self().Channel().Send(fmt.Sprintf(VOLUME_SUCCESS_HTML, username, argument), false)
|
||||||
fmt.Println("Volume change successful!")
|
} else {
|
||||||
|
user.Send(NOT_IN_VOLUME_RANGE_MSG)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
|
@ -80,8 +87,7 @@ func parseCommand(user *gumble.User, username, command string) {
|
||||||
if argument == "" {
|
if argument == "" {
|
||||||
user.Send(NO_ARGUMENT_MSG)
|
user.Send(NO_ARGUMENT_MSG)
|
||||||
} else {
|
} else {
|
||||||
success := move(username, argument)
|
if err := move(argument); err == nil {
|
||||||
if success {
|
|
||||||
fmt.Printf("%s has been moved to %s.", dj.client.Self().Name(), argument)
|
fmt.Printf("%s has been moved to %s.", dj.client.Self().Name(), argument)
|
||||||
} else {
|
} else {
|
||||||
user.Send(CHANNEL_DOES_NOT_EXIST_MSG)
|
user.Send(CHANNEL_DOES_NOT_EXIST_MSG)
|
||||||
|
@ -103,9 +109,11 @@ func parseCommand(user *gumble.User, username, command string) {
|
||||||
}
|
}
|
||||||
case dj.conf.Aliases.KillAlias:
|
case dj.conf.Aliases.KillAlias:
|
||||||
if dj.HasPermission(username, dj.conf.Permissions.AdminKill) {
|
if dj.HasPermission(username, dj.conf.Permissions.AdminKill) {
|
||||||
success := kill(username)
|
if err := kill(); err == nil {
|
||||||
if success {
|
fmt.Println("Kill successful. Goodbye!")
|
||||||
fmt.Println("Kill successful!")
|
os.Exit(0)
|
||||||
|
} else {
|
||||||
|
user.Send(KILL_ERROR_MSG)
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
user.Send(NO_PERMISSION_MSG)
|
user.Send(NO_PERMISSION_MSG)
|
||||||
|
@ -115,7 +123,7 @@ func parseCommand(user *gumble.User, username, command string) {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func add(user, url string) (bool, string) {
|
func add(user, url string) (string, error) {
|
||||||
youtubePatterns := []string{
|
youtubePatterns := []string{
|
||||||
`https?:\/\/www\.youtube\.com\/watch\?v=([\w-]+)`,
|
`https?:\/\/www\.youtube\.com\/watch\?v=([\w-]+)`,
|
||||||
`https?:\/\/youtube\.com\/watch\?v=([\w-]+)`,
|
`https?:\/\/youtube\.com\/watch\?v=([\w-]+)`,
|
||||||
|
@ -126,8 +134,7 @@ func add(user, url string) (bool, string) {
|
||||||
matchFound := false
|
matchFound := false
|
||||||
|
|
||||||
for _, pattern := range youtubePatterns {
|
for _, pattern := range youtubePatterns {
|
||||||
re, err := regexp.Compile(pattern)
|
if re, err := regexp.Compile(pattern); err == nil {
|
||||||
if err == nil {
|
|
||||||
if re.MatchString(url) {
|
if re.MatchString(url) {
|
||||||
matchFound = true
|
matchFound = true
|
||||||
break
|
break
|
||||||
|
@ -139,39 +146,68 @@ func add(user, url string) (bool, string) {
|
||||||
urlMatch := strings.Split(url, "=")
|
urlMatch := strings.Split(url, "=")
|
||||||
shortUrl := urlMatch[1]
|
shortUrl := urlMatch[1]
|
||||||
newSong := NewSong(user, shortUrl)
|
newSong := NewSong(user, shortUrl)
|
||||||
if dj.queue.AddSong(newSong) {
|
if err := dj.queue.AddSong(newSong); err == nil {
|
||||||
return true, newSong.title
|
return newSong.title, nil
|
||||||
} else {
|
} else {
|
||||||
return false, ""
|
return "", errors.New("Could not add the Song to the queue.")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return false, ""
|
return "", errors.New("The URL provided did not match a YouTube URL.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func skip(user string, admin bool) bool {
|
func skip(user string, admin bool) error {
|
||||||
return true
|
if err := dj.currentSong.AddSkip(user); err == nil {
|
||||||
|
if dj.currentSong.SkipReached(len(dj.client.Self().Channel().Users())) || admin {
|
||||||
|
if err := dj.audioStream.Stop(); err == nil {
|
||||||
|
dj.OnSongFinished()
|
||||||
|
return nil
|
||||||
|
} else {
|
||||||
|
return errors.New("An error occurred while stopping the current song.")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return errors.New("Not enough skips have been reached to skip the song.")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return errors.New("An error occurred while adding a skip to the current song.")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func volume(user, value string) bool {
|
func volume(user, value string) error {
|
||||||
parsedVolume, err := strconv.ParseFloat(value, 32)
|
if parsedVolume, err := strconv.ParseFloat(value, 32); err == nil {
|
||||||
if err == nil {
|
|
||||||
newVolume := float32(parsedVolume)
|
newVolume := float32(parsedVolume)
|
||||||
if newVolume >= dj.conf.Volume.LowestVolume && newVolume <= dj.conf.Volume.HighestVolume {
|
if newVolume >= dj.conf.Volume.LowestVolume && newVolume <= dj.conf.Volume.HighestVolume {
|
||||||
dj.conf.Volume.DefaultVolume = newVolume
|
dj.conf.Volume.DefaultVolume = newVolume
|
||||||
return true
|
return nil
|
||||||
} else {
|
} else {
|
||||||
return false
|
return errors.New("The volume supplied was not in the allowed range.")
|
||||||
}
|
}
|
||||||
} else {
|
} else {
|
||||||
return false
|
return errors.New("An error occurred while parsing the volume string.")
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func move(user, channel string) bool {
|
func move(channel string) error {
|
||||||
return true
|
if dj.client.Channels().Find(channel) != nil {
|
||||||
|
dj.client.Self().Move(dj.client.Channels().Find(channel))
|
||||||
|
return nil
|
||||||
|
} else {
|
||||||
|
return errors.New("The channel provided does not exist.")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func kill(user string) bool {
|
func kill() error {
|
||||||
return true
|
songsDir := fmt.Sprintf("%s/.mumbledj/songs", dj.homeDir)
|
||||||
|
if err := os.RemoveAll(songsDir); err != nil {
|
||||||
|
return errors.New("An error occurred while deleting the audio files.")
|
||||||
|
} else {
|
||||||
|
if err := os.Mkdir(songsDir, 0777); err != nil {
|
||||||
|
return errors.New("An error occurred while recreating the songs directory.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
if err := dj.client.Disconnect(); err == nil {
|
||||||
|
return nil
|
||||||
|
} else {
|
||||||
|
return errors.New("An error occurred while disconnecting from the server.")
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
37
main.go
37
main.go
|
@ -11,7 +11,9 @@ import (
|
||||||
"flag"
|
"flag"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/layeh/gumble/gumble"
|
"github.com/layeh/gumble/gumble"
|
||||||
|
"github.com/layeh/gumble/gumble_ffmpeg"
|
||||||
"github.com/layeh/gumble/gumbleutil"
|
"github.com/layeh/gumble/gumbleutil"
|
||||||
|
"os/user"
|
||||||
)
|
)
|
||||||
|
|
||||||
// MumbleDJ type declaration
|
// MumbleDJ type declaration
|
||||||
|
@ -22,6 +24,9 @@ type mumbledj struct {
|
||||||
defaultChannel string
|
defaultChannel string
|
||||||
conf DjConfig
|
conf DjConfig
|
||||||
queue *SongQueue
|
queue *SongQueue
|
||||||
|
currentSong *Song
|
||||||
|
audioStream *gumble_ffmpeg.Stream
|
||||||
|
homeDir string
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dj *mumbledj) OnConnect(e *gumble.ConnectEvent) {
|
func (dj *mumbledj) OnConnect(e *gumble.ConnectEvent) {
|
||||||
|
@ -31,13 +36,22 @@ func (dj *mumbledj) OnConnect(e *gumble.ConnectEvent) {
|
||||||
fmt.Println("Channel doesn't exist, staying in root channel...")
|
fmt.Println("Channel doesn't exist, staying in root channel...")
|
||||||
}
|
}
|
||||||
|
|
||||||
err := loadConfiguration()
|
if currentUser, err := user.Current(); err == nil {
|
||||||
if err == nil {
|
dj.homeDir = currentUser.HomeDir
|
||||||
|
}
|
||||||
|
|
||||||
|
if err := loadConfiguration(); err == nil {
|
||||||
fmt.Println("Configuration successfully loaded!")
|
fmt.Println("Configuration successfully loaded!")
|
||||||
} else {
|
} else {
|
||||||
panic(err)
|
panic(err)
|
||||||
}
|
}
|
||||||
dj.queue = NewSongQueue()
|
|
||||||
|
if audioStream, err := gumble_ffmpeg.New(dj.client); err == nil {
|
||||||
|
dj.audioStream = audioStream
|
||||||
|
dj.audioStream.Done = dj.OnSongFinished
|
||||||
|
} else {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (dj *mumbledj) OnDisconnect(e *gumble.DisconnectEvent) {
|
func (dj *mumbledj) OnDisconnect(e *gumble.DisconnectEvent) {
|
||||||
|
@ -63,6 +77,23 @@ func (dj *mumbledj) HasPermission(username string, command bool) bool {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func (dj *mumbledj) OnSongFinished() {
|
||||||
|
if err := dj.currentSong.Delete(); err == nil {
|
||||||
|
if dj.queue.Len() != 0 {
|
||||||
|
dj.currentSong = dj.queue.NextSong()
|
||||||
|
if dj.currentSong != nil {
|
||||||
|
if err := dj.currentSong.Download(); err == nil {
|
||||||
|
dj.currentSong.Play()
|
||||||
|
} else {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
panic(err)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
var dj = mumbledj{
|
var dj = mumbledj{
|
||||||
keepAlive: make(chan bool),
|
keepAlive: make(chan bool),
|
||||||
queue: NewSongQueue(),
|
queue: NewSongQueue(),
|
||||||
|
|
|
@ -11,7 +11,6 @@ import (
|
||||||
"code.google.com/p/gcfg"
|
"code.google.com/p/gcfg"
|
||||||
"errors"
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"os/user"
|
|
||||||
)
|
)
|
||||||
|
|
||||||
type DjConfig struct {
|
type DjConfig struct {
|
||||||
|
@ -46,9 +45,8 @@ type DjConfig struct {
|
||||||
}
|
}
|
||||||
|
|
||||||
func loadConfiguration() error {
|
func loadConfiguration() error {
|
||||||
usr, err := user.Current()
|
if gcfg.ReadFileInto(&dj.conf, fmt.Sprintf("%s/.mumbledj/config/mumbledj.gcfg", dj.homeDir)) == nil {
|
||||||
if err == nil {
|
return nil
|
||||||
return gcfg.ReadFileInto(&dj.conf, fmt.Sprintf("%s/.mumbledj/config/mumbledj.gcfg", usr.HomeDir))
|
|
||||||
} else {
|
} else {
|
||||||
return errors.New("Configuration load failed.")
|
return errors.New("Configuration load failed.")
|
||||||
}
|
}
|
||||||
|
|
111
song.go
111
song.go
|
@ -8,15 +8,14 @@
|
||||||
package main
|
package main
|
||||||
|
|
||||||
import (
|
import (
|
||||||
//"github.com/layeh/gumble/gumble_ffmpeg"
|
|
||||||
"encoding/json"
|
"encoding/json"
|
||||||
|
"errors"
|
||||||
"fmt"
|
"fmt"
|
||||||
"github.com/jmoiron/jsonq"
|
"github.com/jmoiron/jsonq"
|
||||||
"io/ioutil"
|
"io/ioutil"
|
||||||
"net/http"
|
"net/http"
|
||||||
"os"
|
"os"
|
||||||
"os/exec"
|
"os/exec"
|
||||||
"os/user"
|
|
||||||
"strings"
|
"strings"
|
||||||
)
|
)
|
||||||
|
|
||||||
|
@ -31,12 +30,11 @@ type Song struct {
|
||||||
|
|
||||||
func NewSong(user, id string) *Song {
|
func NewSong(user, id string) *Song {
|
||||||
jsonUrl := fmt.Sprintf("http://gdata.youtube.com/feeds/api/videos/%s?v=2&alt=jsonc", id)
|
jsonUrl := fmt.Sprintf("http://gdata.youtube.com/feeds/api/videos/%s?v=2&alt=jsonc", id)
|
||||||
response, err := http.Get(jsonUrl)
|
|
||||||
jsonString := ""
|
jsonString := ""
|
||||||
if err == nil {
|
|
||||||
|
if response, err := http.Get(jsonUrl); err == nil {
|
||||||
defer response.Body.Close()
|
defer response.Body.Close()
|
||||||
body, err := ioutil.ReadAll(response.Body)
|
if body, err := ioutil.ReadAll(response.Body); err == nil {
|
||||||
if err == nil {
|
|
||||||
jsonString = string(body)
|
jsonString = string(body)
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
@ -47,7 +45,7 @@ func NewSong(user, id string) *Song {
|
||||||
jq := jsonq.NewQuery(jsonData)
|
jq := jsonq.NewQuery(jsonData)
|
||||||
|
|
||||||
videoTitle, _ := jq.String("data", "title")
|
videoTitle, _ := jq.String("data", "title")
|
||||||
videoThumbnail, _ := jq.String("data", "thumbnail", "sqDefault")
|
videoThumbnail, _ := jq.String("data", "thumbnail", "hqDefault")
|
||||||
duration, _ := jq.Int("data", "duration")
|
duration, _ := jq.Int("data", "duration")
|
||||||
videoDuration := fmt.Sprintf("%d:%02d", duration/60, duration%60)
|
videoDuration := fmt.Sprintf("%d:%02d", duration/60, duration%60)
|
||||||
|
|
||||||
|
@ -61,58 +59,57 @@ func NewSong(user, id string) *Song {
|
||||||
return song
|
return song
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Song) Download() bool {
|
func (s *Song) Download() error {
|
||||||
err := exec.Command(fmt.Sprintf("youtube-dl --output \"~/.mumbledj/songs/%(id)s.%(ext)s\" --quiet --format m4a %s", s.youtubeId))
|
cmd := exec.Command("youtube-dl", "--output", fmt.Sprintf(`~/.mumbledj/songs/%s.m4a`, s.youtubeId), "--format", "m4a", s.youtubeId)
|
||||||
if err == nil {
|
if err := cmd.Run(); err == nil {
|
||||||
|
return nil
|
||||||
|
} else {
|
||||||
|
return errors.New("Song download failed.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Song) Play() {
|
||||||
|
dj.audioStream.Play(fmt.Sprintf("%s/.mumbledj/songs/%s.m4a", dj.homeDir, s.youtubeId))
|
||||||
|
dj.client.Self().Channel().Send(fmt.Sprintf(NOW_PLAYING_HTML, s.thumbnailUrl, s.youtubeId, s.title, s.duration, s.submitter), false)
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Song) Delete() error {
|
||||||
|
filePath := fmt.Sprintf("%s/.mumbledj/songs/%s.m4a", dj.homeDir, s.youtubeId)
|
||||||
|
if _, err := os.Stat(filePath); err == nil {
|
||||||
|
if err := os.Remove(filePath); err == nil {
|
||||||
|
return nil
|
||||||
|
} else {
|
||||||
|
return errors.New("Error occurred while deleting audio file.")
|
||||||
|
}
|
||||||
|
} else {
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Song) AddSkip(username string) error {
|
||||||
|
for _, user := range s.skippers {
|
||||||
|
if username == user {
|
||||||
|
return errors.New("This user has already skipped the current song.")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
s.skippers = append(s.skippers, username)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Song) RemoveSkip(username string) error {
|
||||||
|
for i, user := range s.skippers {
|
||||||
|
if username == user {
|
||||||
|
s.skippers = append(s.skippers[:i], s.skippers[i+1:]...)
|
||||||
|
return nil
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return errors.New("This user has not skipped the song.")
|
||||||
|
}
|
||||||
|
|
||||||
|
func (s *Song) SkipReached(channelUsers int) bool {
|
||||||
|
if float32(len(s.skippers))/float32(channelUsers) >= dj.conf.General.SkipRatio {
|
||||||
return true
|
return true
|
||||||
} else {
|
} else {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (s *Song) Play() bool {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Song) Delete() bool {
|
|
||||||
usr, err := user.Current()
|
|
||||||
if err == nil {
|
|
||||||
filePath := fmt.Sprintf("%s/.mumbledj/songs/%s.m4a", usr.HomeDir, s.youtubeId)
|
|
||||||
if _, err := os.Stat(filePath); err == nil {
|
|
||||||
err := os.Remove(filePath)
|
|
||||||
if err == nil {
|
|
||||||
return true
|
|
||||||
} else {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
} else {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Song) AddSkip(username string) bool {
|
|
||||||
for _, user := range s.skippers {
|
|
||||||
if username == user {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
}
|
|
||||||
s.skippers = append(s.skippers, username)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Song) RemoveSkip(username string) bool {
|
|
||||||
for i, user := range s.skippers {
|
|
||||||
if username == user {
|
|
||||||
s.skippers = append(s.skippers[:i], s.skippers[i+1:]...)
|
|
||||||
return true
|
|
||||||
}
|
|
||||||
}
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
||||||
func (s *Song) SkipReached(channelUsers int) bool {
|
|
||||||
return false
|
|
||||||
}
|
|
||||||
|
|
15
songqueue.go
15
songqueue.go
|
@ -7,6 +7,10 @@
|
||||||
|
|
||||||
package main
|
package main
|
||||||
|
|
||||||
|
import (
|
||||||
|
"errors"
|
||||||
|
)
|
||||||
|
|
||||||
type SongQueue struct {
|
type SongQueue struct {
|
||||||
queue *Queue
|
queue *Queue
|
||||||
}
|
}
|
||||||
|
@ -17,21 +21,20 @@ func NewSongQueue() *SongQueue {
|
||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *SongQueue) AddSong(s *Song) bool {
|
func (q *SongQueue) AddSong(s *Song) error {
|
||||||
beforeLen := q.queue.Len()
|
beforeLen := q.queue.Len()
|
||||||
q.queue.Push(s)
|
q.queue.Push(s)
|
||||||
if q.queue.Len() == beforeLen+1 {
|
if q.queue.Len() == beforeLen+1 {
|
||||||
return true
|
return nil
|
||||||
} else {
|
} else {
|
||||||
return false
|
return errors.New("Could not add Song to the SongQueue.")
|
||||||
}
|
}
|
||||||
return true
|
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *SongQueue) NextSong() *Song {
|
func (q *SongQueue) NextSong() *Song {
|
||||||
return q.queue.Poll().(*Song)
|
return q.queue.Poll().(*Song)
|
||||||
}
|
}
|
||||||
|
|
||||||
func (q *SongQueue) CurrentSong() *Song {
|
func (q *SongQueue) Len() int {
|
||||||
return q.queue.Peek().(*Song)
|
return q.queue.Len()
|
||||||
}
|
}
|
||||||
|
|
14
strings.go
14
strings.go
|
@ -29,12 +29,15 @@ const NO_ARGUMENT_MSG = "The command you issued requires an argument and you did
|
||||||
// Message shown to users when they try to change the volume to a value outside the volume range.
|
// Message shown to users when they try to change the volume to a value outside the volume range.
|
||||||
const NOT_IN_VOLUME_RANGE_MSG = "Out of range. The volume must be between %g and %g."
|
const NOT_IN_VOLUME_RANGE_MSG = "Out of range. The volume must be between %g and %g."
|
||||||
|
|
||||||
// Message shown to users when they successfully change the volume.
|
|
||||||
const VOLUME_SUCCESS_MSG = "You have successfully changed the volume to the following: %g."
|
|
||||||
|
|
||||||
// Message shown to user when a successful configuration reload finishes.
|
// Message shown to user when a successful configuration reload finishes.
|
||||||
const CONFIG_RELOAD_SUCCESS_MSG = "The configuration has been successfully reloaded."
|
const CONFIG_RELOAD_SUCCESS_MSG = "The configuration has been successfully reloaded."
|
||||||
|
|
||||||
|
// Message shown to user when an admin skips a song.
|
||||||
|
const ADMIN_SONG_SKIP_MSG = "An admin has decided to skip the current song."
|
||||||
|
|
||||||
|
// Message shown to user when the kill command errors.
|
||||||
|
const KILL_ERROR_MSG = "An error occurred while attempting to kill the bot."
|
||||||
|
|
||||||
// Message shown to a channel when a new song starts playing.
|
// Message shown to a channel when a new song starts playing.
|
||||||
const NOW_PLAYING_HTML = `
|
const NOW_PLAYING_HTML = `
|
||||||
<table>
|
<table>
|
||||||
|
@ -69,3 +72,8 @@ const CUR_VOLUME_HTML = `
|
||||||
const SKIP_ADDED_HTML = `
|
const SKIP_ADDED_HTML = `
|
||||||
<b>%s</b> has voted to skip the current song.
|
<b>%s</b> has voted to skip the current song.
|
||||||
`
|
`
|
||||||
|
|
||||||
|
// Message shown to users when they successfully change the volume.
|
||||||
|
const VOLUME_SUCCESS_HTML = `
|
||||||
|
<b>%s</b> has changed the volume to <b>%s</b>.
|
||||||
|
`
|
||||||
|
|
Reference in a new issue