package main import ( "bytes" "context" "crypto/rand" "encoding/binary" "encoding/json" "errors" "io" "log" "time" mrand "math/rand" "github.com/sosodev/duration" "google.golang.org/api/option" "google.golang.org/api/youtube/v3" ) var yt_svc *youtube.Service func init() { log.Println("youtube.go loading..") var err error apikey := config.GetString("youtube.apikey") yt_svc, err = youtube.NewService(context.Background(), option.WithAPIKey(apikey)) 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 } type VideoInfo struct { Title string Channel string Len time.Duration Uri string } 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"}) call.MaxResults(1) call.Id(vid) resp, err := call.Do() if err != nil { return nil, err } if len(resp.Items) != 1 { return nil, errors.New("response contains not 1 item") } 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 } func YTPlaylist(playlist string) ([]string, error) { call := yt_svc.PlaylistItems.List([]string{"contentDetails"}) 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 } call.PageToken(pageToken) } return list, nil }