diff --git a/README.md b/README.md index 7f15aac..ebd3090 100644 --- a/README.md +++ b/README.md @@ -12,13 +12,12 @@ out_dir = "./vids" # path to archive vids [provider.youtube] cmd = "./yt-dlp" # path to yt-dlp binary quality = "res:1080" # set the preferred quality -output_path_template = "" # yt-dlp output template +output_path_template = "s%(upload_date>%Y)s/%(channel)s.s%(upload_date>%Y)Se%(upload_date>%m%d)S.%(title)s.%(id)s-1080p.%(ext)s" # yt-dlp output template url = "https://www.youtube.com" # full yt url -throttle = 1 # throttle yt request +throttle = 5 # throttle yt request, 5s works well range = "1:5:1" # downloads videos in range 1-5: [START][:STOP][:STEP] -after_date = "20250326" # not in use -cookies = false # control use of cookies file -cookies_file = "./cookies.txt" # pass user cookies to yt +after_date = "20250326" # only download videos after date +cookies_file = "./cookies.txt" # pass user cookies to yt, blank to disable opml_file = "./opml.xml" # the opml file to use ``` @@ -29,14 +28,14 @@ opml_file = "./opml.xml" # the opml file to use - - - + + + - - - + + + @@ -59,6 +58,38 @@ E.g. from Chromium: yt-dlp --cookies-from-browser chromium --cookies cookies.txt ``` +## Scheduling + +### systemd + +`~/.config/systemd/user/subsyt-archival.service` +``` +[Unit] +Description=subsyt archival of yt subscribtions + +[Service] +Type=oneshot +ExecStart=/home/varl/yt/yt-dlp -U +ExecStart=/home/varl/yt/subsyt +WorkingDirectory=/home/varl/yt + +``` + +`~/.config/systemd/user/subsyt-archival.timer` +``` +[Unit] +Description=subsyt archival on boot and daily + +[Timer] +OnCalendar=*-*-* 4:00:00 +Persistent=true +AccuracySec=1us +RandomizedDelaySec=30 + +[Install] +WantedBy=timers.target +``` + ## Container ``` @@ -97,3 +128,7 @@ podman run --rm \ │   │   └── Technology_Connextras.s2025e0331.An_unplanned_trip_from_Chicago_to_Milwaukee_in_an_electric_car.3GUQdrpduo0-1080p.webm │   └── tvshow.nfo ``` + +## Generate OPML + +E.g. https://github.com/jeb5/YouTube-Subscriptions-RSS diff --git a/internal/config/config.go b/internal/config/config.go index 7bc5ea9..527fb0b 100644 --- a/internal/config/config.go +++ b/internal/config/config.go @@ -13,7 +13,6 @@ type Provider struct { Range string After_date string Cmd string - Cookies bool Cookies_file string Opml_file string Quality string diff --git a/internal/dl/dl.go b/internal/dl/dl.go index 3b9dc3e..cdc9797 100644 --- a/internal/dl/dl.go +++ b/internal/dl/dl.go @@ -10,7 +10,6 @@ import ( "os/exec" "path/filepath" "strconv" - "strings" "sync" "git.meatbag.se/varl/subsyt/internal/config" @@ -27,16 +26,22 @@ func Youtube(d Download, p config.Provider) { archive := filepath.Join(d.OutDir, "archive.txt") outdir := d.OutDir - curl := strings.TrimPrefix(d.Url, "/feed/") - furl, err := url.JoinPath(p.Url, curl, "videos") + opmlUrl, err := url.Parse(d.Url) if err != nil { panic(err) } + q := opmlUrl.Query() + cid := q.Get("channel_id") + + if cid == "" { + log.Fatal("no channel !") + } - fullUrl, err := url.Parse(furl) + fullUrl, err := url.Parse(p.Url) if err != nil { panic(err) } + channelUrl := fullUrl.JoinPath("channel", cid, "videos") throttle := strconv.Itoa(p.Throttle) @@ -70,7 +75,7 @@ func Youtube(d Download, p config.Provider) { args = append(args, "--no-simulate") } - if p.Cookies == true { + if p.Cookies_file != "" { args = append(args, "--cookies") args = append(args, p.Cookies_file) } else { @@ -82,7 +87,7 @@ func Youtube(d Download, p config.Provider) { args = append(args, p.After_date) } - args = append(args, fullUrl.String()) + args = append(args, channelUrl.String()) cmd := exec.Command(p.Cmd, args...) stdout, err := cmd.StdoutPipe() @@ -95,7 +100,7 @@ func Youtube(d Download, p config.Provider) { log.Fatal(err) } - log.Printf("[%s] running yt-dlp for: %s\n", d.OutDir, d.Url) + log.Printf("[%s] running yt-dlp with args: %v\n", d.OutDir, args) var wg sync.WaitGroup wg.Add(2) diff --git a/internal/nfo/nfo.go b/internal/nfo/nfo.go index dbf0c26..4de0024 100644 --- a/internal/nfo/nfo.go +++ b/internal/nfo/nfo.go @@ -25,7 +25,7 @@ func WriteEpisodeNFO(ep models.Episode, info_path string) { } func WriteShowInfo(show models.Show, out_path string) { - log.Printf("writing info from '%s' to '%s'\n", show, out_path) + log.Printf("writing info from '%v' to '%s'\n", show, out_path) xmlData, err := xml.MarshalIndent(show, "", " ") if err != nil { diff --git a/shell.nix b/shell.nix index 4d64004..2378a8b 100644 --- a/shell.nix +++ b/shell.nix @@ -2,6 +2,7 @@ with (import {}); mkShell { buildInputs = [ + go_1_24 yt-dlp ];