my-log/ytdlp/fetch.go

130 lines
2.9 KiB
Go
Raw Normal View History

package ytdlp
import (
"context"
"fmt"
"strings"
"time"
"codeberg.org/danjones000/my-log/models"
ytd "github.com/lrstanley/go-ytdlp"
)
// Fetch fetches info from a video on YouTube or other sites supported by yt-dlp
func Fetch(ctx context.Context, url string) (*ytd.ExtractedInfo, error) {
dl := ytd.New().DumpJSON().RemoteComponents("ejs:github")
// TODO Add cookies if available
res, err := dl.Run(ctx, url)
if err != nil {
return nil, err
}
infos, err := res.GetExtractedInfo()
if err != nil {
return nil, err
}
if len(infos) != 1 {
return nil, fmt.Errorf("%d infos", len(infos))
}
return infos[0], nil
}
func GetLog(ctx context.Context, url string) (models.Log, error) {
select {
case <-ctx.Done():
return models.Log{}, context.Cause(ctx)
default:
}
var ent models.Entry
info, err := Fetch(ctx, url)
if err != nil {
return models.Log{}, err
}
now := time.Now()
ent.Date = now
metas := &ent.Fields
*metas = metas.Set("id", getID(now, info))
source := FirstNonZero(info.ExtractorKey, info.WebpageURLDomain, new("Web Video"))
*metas = metas.Set("source", source)
ent.Title = FirstNonZero(info.Title, info.AltTitle, new(fmt.Sprintf("%s %s", source, info.ID)))
setNote(metas, info)
setArtist(metas, info)
setTags(metas, info)
setUrl(metas, info, url)
// TODO Add show info
return models.Log{Name: "watched", Entries: []models.Entry{ent}}, nil
}
func getID(now time.Time, info *ytd.ExtractedInfo) string {
id := new(strings.Builder)
id.WriteString("tag:")
id.WriteString(FirstNonZero(info.WebpageURLDomain, new("goodevilgenius.org")))
id.WriteByte(',')
id.WriteString(now.Format("2006"))
id.WriteRune(':')
id.WriteString(info.ID)
id.WriteRune('/')
fmt.Fprintf(id, "%d", now.Unix())
return id.String()
}
func setNote(metas *models.Metas, info *ytd.ExtractedInfo) {
desc := FirstNonZero(info.Description)
if desc != "" {
desc = strings.SplitN(desc, "\n", 2)[0]
*metas = metas.Set("note", desc)
}
}
func setArtist(metas *models.Metas, info *ytd.ExtractedInfo) {
art := FirstNonZero(info.Artist, info.AlbumArtist, info.Uploader)
if art != "" {
*metas = metas.Set("artist", art)
}
}
func setTags(metas *models.Metas, info *ytd.ExtractedInfo) {
lng := len(info.Tags) + len(info.Categories)
if lng < 1 {
return
}
tags := make([]any, 0, lng)
for _, t := range info.Tags {
tags = append(tags, t)
}
for _, c := range info.Categories {
tags = append(tags, c)
}
*metas = metas.Set("tags", tags)
}
func setDuration(metas *models.Metas, info *ytd.ExtractedInfo) {
dur := FirstNonZero(info.Duration)
if dur > 0 {
*metas = metas.Set("duration", dur)
}
}
func setUrl(metas *models.Metas, info *ytd.ExtractedInfo, origUrl string) {
url := FirstNonZero(info.WebpageURL, info.PageURL, info.URL, &origUrl)
*metas = metas.Set("url", url)
}
func FirstNonZero[T comparable](vals ...*T) T {
var z T
for _, v := range vals {
if v != nil && *v != z {
return *v
}
}
return z
}