2015-04-09 03:44:22 +02:00
|
|
|
/*
|
|
|
|
* MumbleDJ
|
|
|
|
* By Matthieu Grieger
|
|
|
|
* services/youtube/playlist.go
|
|
|
|
* Copyright (c) 2014, 2015 Matthieu Grieger (MIT License)
|
|
|
|
*/
|
|
|
|
|
|
|
|
package youtube
|
2015-04-09 22:20:40 +02:00
|
|
|
|
|
|
|
import (
|
|
|
|
"errors"
|
|
|
|
"fmt"
|
|
|
|
"os"
|
|
|
|
"strconv"
|
|
|
|
"strings"
|
|
|
|
)
|
|
|
|
|
|
|
|
// Playlist holds the metadata for a YouTube playlist.
|
|
|
|
type Playlist struct {
|
|
|
|
id string
|
|
|
|
title string
|
|
|
|
}
|
|
|
|
|
|
|
|
// NewPlaylist gathers the metadata for a YouTube playlist and returns it.
|
|
|
|
func NewPlaylist(user, id string) (*Playlist, error) {
|
|
|
|
// Retrieve title of playlist
|
|
|
|
url := fmt.Sprintf("https://www.googleapis.com/youtube/v3/playlists?part=snippet&id=%s&key=%s",
|
|
|
|
id, os.Getenv("YOUTUBE_API_KEY"))
|
|
|
|
if response, err := PerformGetRequest(url); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
title, _ := response.String("items", "0")
|
|
|
|
|
|
|
|
playlist := &Playlist{
|
|
|
|
id: id,
|
|
|
|
title: title,
|
|
|
|
}
|
|
|
|
|
|
|
|
// Retrieve items in playlist
|
|
|
|
url = fmt.Sprintf("https://www.googleapis.com/youtube/v3/playlistItems?part=snippet&maxResults=25&playlistId=%s&key=%s",
|
|
|
|
id, os.Getenv("YOUTUBE_API_KEY"))
|
|
|
|
if response, err = PerformGetRequest(url); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
numVideos := response.Int("pageInfo", "totalResults")
|
|
|
|
if numVideos > 25 {
|
|
|
|
numVideos = 25
|
|
|
|
}
|
|
|
|
|
|
|
|
for i := 0; i < numVideos; i++ {
|
|
|
|
index := strconv.Itoa(i)
|
|
|
|
videoTitle, _ := response.String("items", index, "snippet", "title")
|
|
|
|
videoID, _ := response.String("items", index, "snippet", "resourceId", "videoId")
|
|
|
|
videoThumbnail, _ := response.String("items", index, "snippet", "thumbnails", "high", "url")
|
|
|
|
|
|
|
|
// A completely separate API call just to get the duration of a video in a
|
|
|
|
// playlist? WHY GOOGLE, WHY?!
|
|
|
|
url = fmt.Sprintf("https://www.googleapis.com/youtube/v3/videos?part=contentDetails&id=%s&key=%s",
|
|
|
|
videoID, os.Getenv("YOUTUBE_API_KEY"))
|
|
|
|
if response, err = PerformGetRequest(url); err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
videoDuration, _ := response.String("items", "0", "contentDetails", "duration")
|
|
|
|
minutes := int(videoDuration[2:strings.Index(videoDuration, "M")])
|
|
|
|
seconds := int(videoDuration[strings.Index(videoDuration, "M")+1 : len(videoDuration)-1])
|
|
|
|
totalSeconds := (minutes * 60) + seconds
|
|
|
|
durationString := fmt.Sprintf("%d:%d", minutes, seconds)
|
|
|
|
|
|
|
|
if dj.conf.General.MaxSongDuration == 0 || totalSeconds <= dj.conf.General.MaxSongDuration {
|
|
|
|
playlistSong := &Song{
|
|
|
|
submitter: user,
|
|
|
|
title: videoTitle,
|
|
|
|
id: videoID,
|
|
|
|
duration: durationString,
|
|
|
|
thumbnail: videoThumbnail,
|
|
|
|
skippers: make([]string, 0),
|
|
|
|
playlist: playlist,
|
|
|
|
dontSkip: false,
|
|
|
|
}
|
|
|
|
dj.queue.AddSong(playlistSong)
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return playlist, nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// AddSkip adds a skip to the playlist's skippers slice.
|
|
|
|
func (p *Playlist) AddSkip(username string) error {
|
|
|
|
for _, user := range dj.playlistSkips[p.id] {
|
|
|
|
if username == user {
|
|
|
|
return errors.New("This user has already skipped the current song.")
|
|
|
|
}
|
|
|
|
}
|
|
|
|
dj.playlistSkips[p.id] = append(dj.playlistSkips[p.id], username)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
|
|
|
|
// RemoveSkip removes a skip from the playlist's skippers slice. If username is not in the slice
|
|
|
|
// an error is returned.
|
|
|
|
func (p *Playlist) RemoveSkip(username string) error {
|
|
|
|
for i, user := range dj.playlistSkips[p.id] {
|
|
|
|
if username == user {
|
|
|
|
dj.playlistSkips[p.id] = append(dj.playlistSkips[p.id][:i], dj.playlistSkips[p.id][i+1:]...)
|
|
|
|
return nil
|
|
|
|
}
|
|
|
|
}
|
|
|
|
return errors.New("This user has not skipped the song.")
|
|
|
|
}
|
|
|
|
|
|
|
|
// DeleteSkippers removes the skippers entry in dj.playlistSkips.
|
|
|
|
func (p *Playlist) DeleteSkippers() {
|
|
|
|
delete(dj.playlistSkips, p.id)
|
|
|
|
}
|
|
|
|
|
|
|
|
// SkipReached calculates the current skip ratio based on the number of users within MumbleDJ's
|
|
|
|
// channel and the number of usernames in the skippers slice. If the value is greater than or equal
|
|
|
|
// to the skip ratio defined in the config, the function returns true, and returns false otherwise.
|
|
|
|
func (p *Playlist) SkipReached(channelUsers int) bool {
|
|
|
|
if float32(len(dj.playlistSkips[p.id]))/float32(channelUsers) >= dj.conf.General.PlaylistSkipRatio {
|
|
|
|
return true
|
|
|
|
}
|
|
|
|
return false
|
|
|
|
}
|