From e510ea1830a39ed4b3a8a38620006e6a29ea9b25 Mon Sep 17 00:00:00 2001 From: svenwiltink Date: Wed, 30 May 2018 23:38:34 +0200 Subject: [PATCH] added a duration to songs (#45) * added a duration to songs * broadcast who skipped a song. Fixes #41 * gofmt --- Gopkg.lock | 18 +++++++++-- Gopkg.toml | 8 +++++ bot/commands.go | 35 ++++++++++++++------- music/dataprovider/nts/nts.go | 3 +- music/dataprovider/soundcloud/soundcloud.go | 14 ++++++--- music/dataprovider/youtube/youtube.go | 13 +++++++- music/player.go | 7 +++-- music/player/musicplayer.go | 30 ++++++++++++------ music/song.go | 3 ++ 9 files changed, 99 insertions(+), 32 deletions(-) diff --git a/Gopkg.lock b/Gopkg.lock index c1cf9ba..db2d45b 100644 --- a/Gopkg.lock +++ b/Gopkg.lock @@ -1,6 +1,12 @@ # This file is autogenerated, do not edit; changes may be undone by the next 'dep ensure'. +[[projects]] + branch = "master" + name = "github.com/ChannelMeter/iso8601duration" + packages = ["."] + revision = "8da3af7a2a61a4eb5ae9bddec06bf637fa9593da" + [[projects]] branch = "master" name = "github.com/DexterLB/mpvipc" @@ -23,6 +29,12 @@ revision = "c34cdb4725f4c3844d095133c6e40e448b86589b" version = "v1.1.1" +[[projects]] + branch = "master" + name = "github.com/svenwiltink/youtube-dl" + packages = ["."] + revision = "08954d006d6a7f3571639fd5480e8846128a562a" + [[projects]] branch = "master" name = "github.com/vansante/go-event-emitter" @@ -38,7 +50,7 @@ "internal/socks", "proxy" ] - revision = "5f9ae10d9af5b1c89ae6904293b14b064d4ada23" + revision = "75944861c7512f64725d687546cfbc757626151f" [[projects]] branch = "master" @@ -50,7 +62,7 @@ "googleapi/transport", "youtube/v3" ] - revision = "2b26f0d5dbe6eea8c0924349bb024673f8105fd9" + revision = "de943baf05a022a8f921b544b7827bacaba1aed5" [[projects]] branch = "v2" @@ -61,6 +73,6 @@ [solve-meta] analyzer-name = "dep" analyzer-version = 1 - inputs-digest = "809bb27bbfa32e399f64c88964398d156f68e270d4f58c10927f2c2268ca0af3" + inputs-digest = "f3d3c945de3edf7a89b45e0e14f9a5a31ea393c5ee2ac5d9cecf77f002042c40" solver-name = "gps-cdcl" solver-version = 1 diff --git a/Gopkg.toml b/Gopkg.toml index a92d39d..ef5c9c3 100644 --- a/Gopkg.toml +++ b/Gopkg.toml @@ -44,3 +44,11 @@ [[constraint]] branch = "master" name = "google.golang.org/api" + +[[constraint]] + branch = "master" + name = "github.com/svenwiltink/youtube-dl" + +[[constraint]] + branch = "master" + name = "github.com/ChannelMeter/iso8601duration" diff --git a/bot/commands.go b/bot/commands.go index ec1b2dc..e886779 100644 --- a/bot/commands.go +++ b/bot/commands.go @@ -6,6 +6,7 @@ import ( "github.com/svenwiltink/go-musicbot/music" "strconv" + "time" ) type Command struct { @@ -44,9 +45,9 @@ var addCommand = &Command{ bot.ReplyToMessage(message, err.Error()) } else { if message.IsPrivate { - bot.BroadcastMessage(fmt.Sprintf("%s added by %s", song.Name, message.Sender.NickName)) + bot.BroadcastMessage(fmt.Sprintf("%s - %s added by %s", song.Artist, song.Name, message.Sender.NickName)) } - bot.ReplyToMessage(message, fmt.Sprintf("%s added", song.Name)) + bot.ReplyToMessage(message, fmt.Sprintf("%s - %s added", song.Artist, song.Name)) } }, } @@ -60,7 +61,11 @@ var searchAddCommand = &Command{ return } - songs, _ := bot.musicPlayer.Search(words[2]) + songs, err := bot.musicPlayer.Search(words[2]) + + if err != nil { + bot.ReplyToMessage(message, fmt.Sprintf("error: %v", err)) + } if len(songs) == 0 { bot.ReplyToMessage(message, "No song found") @@ -68,7 +73,7 @@ var searchAddCommand = &Command{ } song := songs[0] - err := bot.musicPlayer.AddSong(song) + err = bot.musicPlayer.AddSong(song) if err != nil { bot.ReplyToMessage(message, fmt.Sprintf("Error: %v", err)) @@ -76,10 +81,10 @@ var searchAddCommand = &Command{ } if message.IsPrivate { - bot.BroadcastMessage(fmt.Sprintf("%s added by %s", song.Name, message.Sender.NickName)) + bot.BroadcastMessage(fmt.Sprintf("%s - %s added by %s", song.Artist, song.Name, message.Sender.NickName)) } - bot.ReplyToMessage(message, fmt.Sprintf("%s added", song.Name)) + bot.ReplyToMessage(message, fmt.Sprintf("%s - %s added", song.Artist, song.Name)) }, } @@ -91,7 +96,7 @@ var nextCommand = &Command{ bot.ReplyToMessage(message, fmt.Sprintf("Could not skip song: %v", err)) } else { if message.IsPrivate { - bot.BroadcastMessage("Skipping song") + bot.BroadcastMessage(fmt.Sprintf("%s skipped the song", message.Sender.NickName)) } bot.ReplyToMessage(message, "Skipping song") } @@ -137,12 +142,21 @@ var playCommand = &Command{ var currentCommand = &Command{ Name: "current", Function: func(bot *MusicBot, message Message) { - song := bot.musicPlayer.GetCurrentSong() + song, durationLeft := bot.musicPlayer.GetCurrentSong() if song == nil { bot.ReplyToMessage(message, "Nothing currently playing") return } - bot.ReplyToMessage(message, fmt.Sprintf("Current song: %s %s", song.Artist, song.Name)) + + if song.SongType == music.SongTypeSong { + bot.ReplyToMessage( + message, + fmt.Sprintf("Current song: %s %s. %s remaining (%s)", song.Artist, song.Name, durationLeft.String(), song.Duration.Round(time.Second).String())) + } else { + bot.ReplyToMessage( + message, + fmt.Sprintf("Current song: %s %s. This is a livestream, use the next command to skip", song.Artist, song.Name)) + } }, } @@ -240,7 +254,6 @@ var volCommand = &Command{ } } - if message.IsPrivate { bot.BroadcastMessage(fmt.Sprintf("Volume set to %d by %s", volume, message.Sender.NickName)) } @@ -254,4 +267,4 @@ var aboutCommand = &Command{ Function: func(bot *MusicBot, message Message) { bot.ReplyToMessage(message, "go-MusicBot by Sven Wiltink: https://github.com/svenwiltink/go-MusicBot") }, -} \ No newline at end of file +} diff --git a/music/dataprovider/nts/nts.go b/music/dataprovider/nts/nts.go index 150e874..ec31a1e 100644 --- a/music/dataprovider/nts/nts.go +++ b/music/dataprovider/nts/nts.go @@ -26,7 +26,8 @@ func (DataProvider) ProvideData(song *music.Song) error { link = link + `2` } - song.Artist = song.Path + song.Name = song.Path + song.Artist = "nts" song.Path = link song.SongType = music.SongTypeStream diff --git a/music/dataprovider/soundcloud/soundcloud.go b/music/dataprovider/soundcloud/soundcloud.go index 5883c16..0eeac82 100644 --- a/music/dataprovider/soundcloud/soundcloud.go +++ b/music/dataprovider/soundcloud/soundcloud.go @@ -4,6 +4,8 @@ import ( "regexp" "github.com/svenwiltink/go-musicbot/music" + "github.com/svenwiltink/youtube-dl" + "time" ) var soundCloudRegex = regexp.MustCompile(`^https://soundcloud.com/([a-zA-Z0-9\-_]+)/([a-zA-Z0-9\-_]+)`) @@ -15,10 +17,14 @@ func (DataProvider) CanProvideData(song *music.Song) bool { } func (DataProvider) ProvideData(song *music.Song) error { - matches := soundCloudRegex.FindStringSubmatch(song.Path) - - song.Artist = matches[1] - song.Name = matches[2] + data, err := youtubedl.GetMetaData(song.Path) + if err != nil { + return err + } + + song.Artist = data.Uploader + song.Name = data.Title + song.Duration = time.Second * time.Duration(data.Duration) return nil } diff --git a/music/dataprovider/youtube/youtube.go b/music/dataprovider/youtube/youtube.go index 965ee0c..f3183af 100644 --- a/music/dataprovider/youtube/youtube.go +++ b/music/dataprovider/youtube/youtube.go @@ -8,9 +8,10 @@ import ( "regexp" "strings" + isoduration "github.com/ChannelMeter/iso8601duration" "github.com/svenwiltink/go-musicbot/music" "google.golang.org/api/googleapi/transport" - youtube "google.golang.org/api/youtube/v3" + "google.golang.org/api/youtube/v3" ) const ( @@ -83,6 +84,16 @@ func (provider *DataProvider) provideDataForIdentifier(identifier string, song * } song.Name = item.Snippet.Title + song.Artist = item.Snippet.ChannelTitle + + duration, err := isoduration.FromString(item.ContentDetails.Duration) + + if err != nil { + return err + } + + song.Duration = duration.ToDuration() + song.Path = fmt.Sprintf(youTubeVideoURL, identifier) return nil } diff --git a/music/player.go b/music/player.go index f6ce469..98c6d8e 100644 --- a/music/player.go +++ b/music/player.go @@ -1,6 +1,9 @@ package music -import "github.com/vansante/go-event-emitter" +import ( + "github.com/vansante/go-event-emitter" + "time" +) const ( EventSongStarted = "song-started" @@ -23,7 +26,7 @@ type Player interface { Play() error Stop() GetStatus() PlayerStatus - GetCurrentSong() *Song + GetCurrentSong() (*Song, time.Duration) } type PlayerStatus string diff --git a/music/player/musicplayer.go b/music/player/musicplayer.go index dedca0f..725c9be 100644 --- a/music/player/musicplayer.go +++ b/music/player/musicplayer.go @@ -7,18 +7,20 @@ import ( "errors" "github.com/svenwiltink/go-musicbot/music" "github.com/vansante/go-event-emitter" + "time" ) // MusicPlayer is responsible for playing music type MusicPlayer struct { *eventemitter.Emitter - Queue *Queue - Status music.PlayerStatus - dataProviders []music.DataProvider - musicProviders []music.Provider - activeProvider music.Provider - currentSong *music.Song - shouldStop bool + Queue *Queue + Status music.PlayerStatus + dataProviders []music.DataProvider + musicProviders []music.Provider + activeProvider music.Provider + currentSong *music.Song + shouldStop bool + currentSongEnds time.Time } func (player *MusicPlayer) Pause() error { @@ -54,8 +56,12 @@ func (player *MusicPlayer) GetStatus() music.PlayerStatus { return player.Status } -func (player *MusicPlayer) GetCurrentSong() *music.Song { - return player.currentSong +func (player *MusicPlayer) GetCurrentSong() (*music.Song, time.Duration) { + if player.currentSong != nil { + return player.currentSong, player.currentSongEnds.Sub(time.Now()).Round(time.Second) + } + + return nil, time.Duration(0) } func (player *MusicPlayer) SetVolume(percentage int) error { @@ -114,7 +120,10 @@ func (player *MusicPlayer) Search(searchString string) ([]*music.Song, error) { songs := make([]*music.Song, 0) for _, provider := range player.dataProviders { - results, _ := provider.Search(searchString) + results, err := provider.Search(searchString) + if err != nil { + return nil, err + } if results != nil { songs = append(songs, results...) @@ -198,6 +207,7 @@ func (player *MusicPlayer) playLoop() { continue } + player.currentSongEnds = time.Now().Add(song.Duration) player.EmitEvent(music.EventSongStarted, song) player.Status = music.PlayerStatusPlaying provider.Wait() diff --git a/music/song.go b/music/song.go index 1e2474e..7c8e394 100644 --- a/music/song.go +++ b/music/song.go @@ -1,5 +1,7 @@ package music +import "time" + type SongType string const ( @@ -12,4 +14,5 @@ type Song struct { Artist string Path string SongType SongType + Duration time.Duration }