2022-11-18 21:18:12 +00:00
|
|
|
package main
|
|
|
|
|
|
|
|
import (
|
2022-11-19 16:37:49 +00:00
|
|
|
"bytes"
|
2022-11-18 21:18:12 +00:00
|
|
|
"context"
|
|
|
|
"crypto/rand"
|
|
|
|
"encoding/binary"
|
2022-11-19 16:37:49 +00:00
|
|
|
"encoding/json"
|
|
|
|
"errors"
|
2022-11-18 21:18:12 +00:00
|
|
|
"io"
|
|
|
|
"log"
|
|
|
|
"time"
|
|
|
|
|
|
|
|
mrand "math/rand"
|
|
|
|
|
2022-11-19 16:37:49 +00:00
|
|
|
"github.com/sosodev/duration"
|
2022-11-18 21:18:12 +00:00
|
|
|
"google.golang.org/api/option"
|
|
|
|
"google.golang.org/api/youtube/v3"
|
|
|
|
)
|
|
|
|
|
2022-12-22 11:43:40 +00:00
|
|
|
var yt_svc *youtube.Service
|
|
|
|
|
2022-11-18 21:18:12 +00:00
|
|
|
func init() {
|
|
|
|
log.Println("youtube.go loading..")
|
|
|
|
|
|
|
|
var err error
|
|
|
|
|
|
|
|
apikey := config.GetString("youtube.apikey")
|
|
|
|
|
2022-12-22 11:43:40 +00:00
|
|
|
yt_svc, err = youtube.NewService(context.Background(), option.WithAPIKey(apikey))
|
2022-11-18 21:18:12 +00:00
|
|
|
if err != nil {
|
|
|
|
log.Fatal(err)
|
|
|
|
}
|
|
|
|
log.Println("youtube.go done.")
|
|
|
|
}
|
|
|
|
|
|
|
|
func ShufflePlaylist(list []string) ([]string, error) {
|
|
|
|
seedb := make([]byte, 32)
|
|
|
|
_, err := rand.Read(seedb)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
seed := binary.BigEndian.Uint64(seedb)
|
|
|
|
mrand.Seed(int64(seed))
|
|
|
|
mrand.Shuffle(len(list), func(i, j int) { list[i], list[j] = list[j], list[i] })
|
|
|
|
|
|
|
|
return list, nil
|
|
|
|
}
|
|
|
|
|
2022-11-19 16:37:49 +00:00
|
|
|
type VideoInfo struct {
|
|
|
|
Title string
|
|
|
|
Channel string
|
|
|
|
Len time.Duration
|
|
|
|
Uri string
|
|
|
|
}
|
|
|
|
|
2022-12-22 11:43:40 +00:00
|
|
|
func YTVideo(vid string) (out VideoInfo, err error) {
|
|
|
|
_, r, err := cache.GetOrCreate(vid+".videoinfo", func() (io.ReadCloser, error) {
|
|
|
|
call := yt_svc.Videos.List([]string{"snippet", "contentDetails"})
|
2022-11-19 16:37:49 +00:00
|
|
|
call.MaxResults(1)
|
|
|
|
call.Id(vid)
|
|
|
|
resp, err := call.Do()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
if len(resp.Items) != 1 {
|
2022-11-20 16:30:22 +00:00
|
|
|
return nil, errors.New("response contains not 1 item")
|
2022-11-19 16:37:49 +00:00
|
|
|
}
|
|
|
|
|
|
|
|
video := resp.Items[0]
|
|
|
|
|
|
|
|
songdur, err := duration.Parse(video.ContentDetails.Duration)
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
|
|
|
|
out := new(VideoInfo)
|
|
|
|
out.Len = songdur.ToTimeDuration()
|
|
|
|
out.Title = video.Snippet.Title
|
|
|
|
out.Channel = video.Snippet.ChannelTitle
|
|
|
|
out.Uri = vid
|
|
|
|
|
|
|
|
var buf bytes.Buffer
|
|
|
|
|
|
|
|
json.NewEncoder(&buf).Encode(out)
|
|
|
|
|
|
|
|
return io.NopCloser(&buf), nil
|
|
|
|
|
|
|
|
})
|
|
|
|
if err != nil {
|
|
|
|
return
|
|
|
|
}
|
|
|
|
json.NewDecoder(r).Decode(&out)
|
|
|
|
|
|
|
|
return out, nil
|
2022-11-18 21:18:12 +00:00
|
|
|
}
|
|
|
|
|
2022-12-22 11:43:40 +00:00
|
|
|
func YTPlaylist(playlist string) ([]string, error) {
|
|
|
|
call := yt_svc.PlaylistItems.List([]string{"contentDetails"})
|
2022-11-18 21:18:12 +00:00
|
|
|
pageToken := ""
|
|
|
|
call = call.MaxResults(50)
|
|
|
|
call = call.PlaylistId(playlist)
|
|
|
|
if pageToken != "" {
|
|
|
|
call = call.PageToken(pageToken)
|
|
|
|
}
|
|
|
|
|
|
|
|
var list []string
|
|
|
|
for {
|
|
|
|
response, err := call.Do()
|
|
|
|
if err != nil {
|
|
|
|
return nil, err
|
|
|
|
}
|
|
|
|
for _, item := range response.Items {
|
|
|
|
list = append(list, item.ContentDetails.VideoId)
|
|
|
|
}
|
|
|
|
pageToken = response.NextPageToken
|
|
|
|
if pageToken == "" {
|
|
|
|
break
|
|
|
|
}
|
2022-11-21 22:49:43 +00:00
|
|
|
call.PageToken(pageToken)
|
2022-11-18 21:18:12 +00:00
|
|
|
}
|
|
|
|
return list, nil
|
|
|
|
}
|