Add drop:yt command and refine ytdlp.Drop functionality

This commit is contained in:
Dan Jones 2026-02-28 23:36:08 -06:00
commit b0f6628817
3 changed files with 98 additions and 16 deletions

69
cli/ytdrop.go Normal file
View file

@ -0,0 +1,69 @@
/*
Copyright © 2026 Dan Jones <danjones@goodevilgenius.org>
This program is free software: you can redistribute it and/or modify
it under the terms of the GNU Affero General Public License as published by
the Free Software Foundation, either version 3 of the License, or
(at your option) any later version.
This program is distributed in the hope that it will be useful,
but WITHOUT ANY WARRANTY; without even the implied warranty of
MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the
GNU Affero General Public License for more details.
You should have received a copy of the GNU Affero General Public License
along with this program. If not, see <http://www.gnu.org/licenses/>.
*/
package cli
import (
"fmt"
"my-log-wynter/ytdlp"
mycli "codeberg.org/danjones000/my-log/cli"
"codeberg.org/danjones000/my-log/config"
"codeberg.org/danjones000/my-log/formatters"
"github.com/spf13/cobra"
)
var outJson bool
// YtDropCmd represents the drop command
var YtDropCmd = &cobra.Command{
Use: "drop:yt url",
Short: "Add a new YouTube video to the watched log",
// Long: ``,
Args: cobra.ExactArgs(1),
SilenceUsage: true,
RunE: func(cmd *cobra.Command, args []string) error {
if outJson {
config.Overrides["output.stdout.config.format"] = "json"
}
url := args[0]
log, err := ytdlp.Drop(cmd.Context(), url)
if err != nil {
return err
}
form, err := formatters.Preferred()
if err != nil {
return err
}
out, err := form.Log(log)
if err != nil {
return err
}
if len(out) > 0 && out[len(out)-1] != 10 {
out = append(out, 10)
}
fmt.Fprintf(cmd.OutOrStdout(), "%s", out)
return nil
},
}
func init() {
mycli.RootCmd.AddCommand(YtDropCmd)
YtDropCmd.Flags().BoolVarP(&outJson, "output_json", "o", false, "Output result as JSON")
}

View file

@ -16,8 +16,12 @@ along with this program. If not, see <http://www.gnu.org/licenses/>.
*/ */
package main package main
import "codeberg.org/danjones000/my-log/cli" import (
_ "my-log-wynter/cli"
mylog "codeberg.org/danjones000/my-log/cli"
)
func main() { func main() {
cli.Execute() mylog.Execute()
} }

View file

@ -12,23 +12,25 @@ import (
) )
// Drop adds the URL specified by the url to the watched log. // Drop adds the URL specified by the url to the watched log.
func Drop(ctx context.Context, url string) (models.Entry, error) { func Drop(ctx context.Context, url string) (models.Log, error) {
var ent models.Entry var ent models.Entry
var log models.Log
if ctx.Err() != nil { if ctx.Err() != nil {
return ent, context.Cause(ctx) return log, context.Cause(ctx)
} }
info, err := Fetch(ctx, url) info, err := Fetch(ctx, url)
if err != nil { if err != nil {
return ent, err return log, err
} }
now := time.Now() now := time.Now()
ent.Date = now
metas := &ent.Fields metas := &ent.Fields
metas.Set("id", getID(now, info)) *metas = metas.Set("id", getID(now, info))
source := FirstNonZero(info.ExtractorKey, info.WebpageURLDomain, new("Web Video")) source := FirstNonZero(info.ExtractorKey, info.WebpageURLDomain, new("Web Video"))
metas.Set("source", source) *metas = metas.Set("source", source)
ent.Title = FirstNonZero(info.Title, info.AltTitle, new(fmt.Sprintf("%s %s", source, info.ID))) ent.Title = FirstNonZero(info.Title, info.AltTitle, new(fmt.Sprintf("%s %s", source, info.ID)))
@ -39,12 +41,12 @@ func Drop(ctx context.Context, url string) (models.Entry, error) {
// TODO Add show info // TODO Add show info
log := models.Log{Name: "watched", Entries: []models.Entry{ent}} log = models.Log{Name: "watched", Entries: []models.Entry{ent}}
if err := files.Append(log); err != nil { if err := files.Append(log); err != nil {
return ent, err return log, err
} }
return ent, nil return log, nil
} }
func getID(now time.Time, info *ytd.ExtractedInfo) string { func getID(now time.Time, info *ytd.ExtractedInfo) string {
@ -63,34 +65,41 @@ func getID(now time.Time, info *ytd.ExtractedInfo) string {
func setNote(metas *models.Metas, info *ytd.ExtractedInfo) { func setNote(metas *models.Metas, info *ytd.ExtractedInfo) {
desc := FirstNonZero(info.Description) desc := FirstNonZero(info.Description)
if desc != "" { if desc != "" {
metas.Set("note", desc) desc = strings.SplitN(desc, "\n", 2)[0]
*metas = metas.Set("note", desc)
} }
} }
func setArtist(metas *models.Metas, info *ytd.ExtractedInfo) { func setArtist(metas *models.Metas, info *ytd.ExtractedInfo) {
art := FirstNonZero(info.Artist, info.AlbumArtist, info.Uploader) art := FirstNonZero(info.Artist, info.AlbumArtist, info.Uploader)
if art != "" { if art != "" {
metas.Set("artist", art) *metas = metas.Set("artist", art)
} }
} }
func setTags(metas *models.Metas, info *ytd.ExtractedInfo) { func setTags(metas *models.Metas, info *ytd.ExtractedInfo) {
tags := append(info.Tags, info.Categories...) tags := make([]any, 0, len(info.Tags)+len(info.Categories))
for _, t := range info.Tags {
tags = append(tags, t)
}
for _, c := range info.Categories {
tags = append(tags, c)
}
if len(tags) > 0 { if len(tags) > 0 {
metas.Set("tags", tags) *metas = metas.Set("tags", tags)
} }
} }
func setDuration(metas *models.Metas, info *ytd.ExtractedInfo) { func setDuration(metas *models.Metas, info *ytd.ExtractedInfo) {
dur := FirstNonZero(info.Duration) dur := FirstNonZero(info.Duration)
if dur > 0 { if dur > 0 {
metas.Set("duration", dur) *metas = metas.Set("duration", dur)
} }
} }
func setUrl(metas *models.Metas, info *ytd.ExtractedInfo, origUrl string) { func setUrl(metas *models.Metas, info *ytd.ExtractedInfo, origUrl string) {
url := FirstNonZero(info.WebpageURL, info.PageURL, info.URL, &origUrl) url := FirstNonZero(info.WebpageURL, info.PageURL, info.URL, &origUrl)
metas.Set("url", url) *metas = metas.Set("url", url)
} }
func FirstNonZero[T comparable](vals ...*T) T { func FirstNonZero[T comparable](vals ...*T) T {