dndmusicbot/youtube.go

171 lines
3.2 KiB
Go
Raw Normal View History

2022-11-18 21:18:12 +00:00
package main
import (
"bytes"
2022-11-18 21:18:12 +00:00
"context"
"crypto/rand"
"encoding/binary"
"encoding/json"
"errors"
2022-11-18 21:18:12 +00:00
"io"
"log"
"math/big"
"time"
mrand "math/rand"
"github.com/faiface/beep"
"github.com/sosodev/duration"
2022-11-18 21:18:12 +00:00
"google.golang.org/api/option"
"google.golang.org/api/youtube/v3"
)
var (
yt_url = "https://www.youtube.com/watch?v=%s"
)
func init() {
log.Println("youtube.go loading..")
var err error
apikey := config.GetString("youtube.apikey")
app.youtube, err = youtube.NewService(context.Background(), option.WithAPIKey(apikey))
if err != nil {
log.Fatal(err)
}
log.Println("youtube.go done.")
}
type YT struct {
dst io.WriteCloser
pcm io.ReadCloser
dur time.Duration
pos time.Duration
f beep.Format
}
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
}
func (app *App) GetSong(list []string) string {
return list[app.plidx]
2022-11-18 21:18:12 +00:00
}
func (app *App) GetNextSong(list []string) string {
app.plidx++
if app.plidx >= len(app.active) {
app.plidx = 0
}
return list[app.plidx]
2022-11-18 21:18:12 +00:00
}
func (app *App) GetPrevSong(list []string) string {
app.plidx--
if app.plidx < 0 {
app.plidx = len(list)
}
return list[app.plidx]
2022-11-18 21:18:12 +00:00
}
func GetRandomSong(list []string) string {
if !(len(list) > 0) {
return ""
}
idx, err := rand.Int(rand.Reader, big.NewInt(int64(len(list)-1)))
if err != nil {
log.Println("Failed to get random int, ", err)
return ""
}
return list[idx.Int64()]
}
type VideoInfo struct {
Title string
Channel string
Len time.Duration
Uri string
}
func (app App) Video(vid string) (out VideoInfo, err error) {
_, r, err := app.cache.GetOrCreate(vid+".videoinfo", func() (io.ReadCloser, error) {
call := app.youtube.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
2022-11-18 21:18:12 +00:00
}
func (app App) Playlist(playlist string) ([]string, error) {
call := app.youtube.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
}
}
return list, nil
//return fmt.Sprintf(yt_url, list[rand.Intn(len(list))])
}