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, now time.Time) (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 } ent.Date = now // TODO Get published date 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 }