This commit is contained in:
Matthieu Grieger 2015-05-09 21:45:00 -07:00
parent 35f673447f
commit 34431c9fa5
4 changed files with 61 additions and 20 deletions

View file

@ -164,27 +164,32 @@ func add(user *gumble.User, username, url string) {
dj.SendPrivateMessage(user, NO_ARGUMENT_MSG)
} else {
youtubePatterns := []string{
`https?:\/\/www\.youtube\.com\/watch\?v=([\w-]+)`,
`https?:\/\/youtube\.com\/watch\?v=([\w-]+)`,
`https?:\/\/youtu.be\/([\w-]+)`,
`https?:\/\/youtube.com\/v\/([\w-]+)`,
`https?:\/\/www.youtube.com\/v\/([\w-]+)`,
`https?:\/\/www\.youtube\.com\/watch\?v=([\w-]+)(\&t=\d*m?\d*s?)?`,
`https?:\/\/youtube\.com\/watch\?v=([\w-]+)(\&t=\d*m?\d*s?)?`,
`https?:\/\/youtu.be\/([\w-]+)(\?t=\d*m?\d*s?)?`,
`https?:\/\/youtube.com\/v\/([\w-]+)(\?t=\d*m?\d*s?)?`,
`https?:\/\/www.youtube.com\/v\/([\w-]+)(\?t=\d*m?\d*s?)?`,
}
matchFound := false
shortUrl := ""
shortURL := ""
startOffset := ""
for _, pattern := range youtubePatterns {
if re, err := regexp.Compile(pattern); err == nil {
if re.MatchString(url) {
matchFound = true
shortUrl = re.FindStringSubmatch(url)[1]
matches := re.FindAllStringSubmatch(url, -1)
shortURL = matches[0][1]
if len(matches[0]) == 3 {
startOffset = matches[0][2]
}
break
}
}
}
if matchFound {
if newSong, err := NewYouTubeSong(username, shortUrl, nil); err == nil {
if newSong, err := NewYouTubeSong(username, shortURL, startOffset, nil); err == nil {
dj.client.Self.Channel.Send(fmt.Sprintf(SONG_ADDED_HTML, username, newSong.title), false)
if dj.queue.Len() == 1 && !dj.audioStream.IsPlaying() {
if err := dj.queue.CurrentSong().Download(); err == nil {
@ -206,9 +211,9 @@ func add(user *gumble.User, username, url string) {
if re, err := regexp.Compile(youtubePlaylistPattern); err == nil {
if re.MatchString(url) {
if dj.HasPermission(username, dj.conf.Permissions.AdminAddPlaylists) {
shortUrl = re.FindStringSubmatch(url)[1]
shortURL = re.FindStringSubmatch(url)[1]
oldLength := dj.queue.Len()
if newPlaylist, err := NewYouTubePlaylist(username, shortUrl); err == nil {
if newPlaylist, err := NewYouTubePlaylist(username, shortURL); err == nil {
dj.client.Self.Channel.Send(fmt.Sprintf(PLAYLIST_ADDED_HTML, username, newPlaylist.title), false)
if oldLength == 0 && dj.queue.Len() != 0 && !dj.audioStream.IsPlaying() {
if err := dj.queue.CurrentSong().Download(); err == nil {

View file

@ -45,12 +45,8 @@ func (dj *mumbledj) OnConnect(e *gumble.ConnectEvent) {
fmt.Println("Channel doesn't exist or one was not provided, staying in root channel...")
}
if audioStream, err := gumble_ffmpeg.New(dj.client); err == nil {
dj.audioStream = audioStream
dj.audioStream.Volume = dj.conf.Volume.DefaultVolume
} else {
panic(err)
}
dj.audioStream = gumble_ffmpeg.New(dj.client)
dj.audioStream.Volume = dj.conf.Volume.DefaultVolume
dj.client.AudioEncoder.SetApplication(gopus.Audio)

View file

@ -17,8 +17,10 @@ import (
"os/exec"
"strconv"
"strings"
"time"
"github.com/jmoiron/jsonq"
"github.com/layeh/gumble/gumble_ffmpeg"
)
// ------------
@ -30,6 +32,7 @@ type YouTubeSong struct {
submitter string
title string
id string
offset int
filename string
duration string
thumbnail string
@ -40,7 +43,7 @@ type YouTubeSong struct {
// NewYouTubeSong gathers the metadata for a song extracted from a YouTube video, and returns
// the song.
func NewYouTubeSong(user, id string, playlist *YouTubePlaylist) (*YouTubeSong, error) {
func NewYouTubeSong(user, id, offset string, playlist *YouTubePlaylist) (*YouTubeSong, error) {
var apiResponse *jsonq.JsonQuery
var err error
url := fmt.Sprintf("https://www.googleapis.com/youtube/v3/videos?part=snippet,contentDetails&id=%s&key=%s",
@ -49,6 +52,24 @@ func NewYouTubeSong(user, id string, playlist *YouTubePlaylist) (*YouTubeSong, e
return nil, err
}
var offsetMinutes, offsetSeconds int64
if offset != "" {
if strings.Contains(offset, "m") {
offsetMinutes, _ = strconv.ParseInt(offset[3:strings.Index(offset, "m")], 10, 32)
if strings.Contains(offset, "s") {
offsetSeconds, _ = strconv.ParseInt(offset[strings.Index(offset, "m")+1:strings.Index(offset, "s")], 10, 32)
} else {
offsetSeconds = 0
}
} else if strings.Contains(offset, "s") {
offsetMinutes = 0
offsetSeconds, _ = strconv.ParseInt(offset[3:strings.Index(offset, "s")], 10, 32)
}
} else {
offsetMinutes = 0
offsetSeconds = 0
}
title, _ := apiResponse.String("items", "0", "snippet", "title")
thumbnail, _ := apiResponse.String("items", "0", "snippet", "thumbnails", "high", "url")
duration, _ := apiResponse.String("items", "0", "contentDetails", "duration")
@ -64,14 +85,18 @@ func NewYouTubeSong(user, id string, playlist *YouTubePlaylist) (*YouTubeSong, e
} else {
seconds = 0
}
combinedMinutes := minutes - offsetMinutes
combinedSeconds := seconds - offsetSeconds
totalSeconds := int((minutes * 60) + seconds)
durationString := fmt.Sprintf("%d:%02d", minutes, seconds)
durationString := fmt.Sprintf("%d:%02d", combinedMinutes, combinedSeconds)
if dj.conf.General.MaxSongDuration == 0 || totalSeconds <= dj.conf.General.MaxSongDuration {
song := &YouTubeSong{
submitter: user,
title: title,
id: id,
offset: int((offsetMinutes * 60) + offsetSeconds),
filename: id + ".m4a",
duration: durationString,
thumbnail: thumbnail,
@ -104,7 +129,12 @@ func (s *YouTubeSong) Download() error {
// Play plays the song. Once the song is playing, a notification is displayed in a text message that features the video
// thumbnail, URL, title, duration, and submitter.
func (s *YouTubeSong) Play() {
if err := dj.audioStream.Play(fmt.Sprintf("%s/.mumbledj/songs/%s.m4a", dj.homeDir, s.ID()), dj.queue.OnSongFinished); err != nil {
if s.offset != 0 {
offsetDuration, _ := time.ParseDuration(fmt.Sprintf("%ds", s.offset))
dj.audioStream.Offset = offsetDuration
}
dj.audioStream.Source = gumble_ffmpeg.SourceFile(fmt.Sprintf("%s/.mumbledj/songs/%s", dj.homeDir, s.Filename()))
if err := dj.audioStream.Play(); err != nil {
panic(err)
} else {
if s.Playlist() == nil {
@ -143,6 +173,10 @@ func (s *YouTubeSong) Play() {
dj.client.Self.Channel.Send(fmt.Sprintf(message, s.Thumbnail(), s.ID(),
s.Title(), s.Duration(), s.Submitter(), s.Playlist().Title()), false)
}
go func() {
dj.audioStream.Wait()
dj.queue.OnSongFinished()
}()
}
}

View file

@ -7,7 +7,11 @@
package main
import "errors"
import (
"errors"
"fmt"
"time"
)
// SongQueue type declaration.
type SongQueue struct {
@ -75,6 +79,8 @@ func (q *SongQueue) Traverse(visit func(i int, s Song)) {
// OnSongFinished event. Deletes Song that just finished playing, then queues the next Song (if exists).
func (q *SongQueue) OnSongFinished() {
resetOffset, _ := time.ParseDuration(fmt.Sprintf("%ds", 0))
dj.audioStream.Offset = resetOffset
if q.Len() != 0 {
if dj.queue.CurrentSong().DontSkip() == true {
dj.queue.CurrentSong().SetDontSkip(false)