04632e4179acd3b3bb8b847471278a1fc4dbcd52

Author
TheEdgeOfRage <git@theedgeofrage.com>
Committer
TheEdgeOfRage <git@theedgeofrage.com>
Date

Message

Add support for passing --cookies to yt-dlp

Diff

  1diff --git a/README.md b/README.md
  2index 543ea166e2197fd15441e08a37af66eceafc873f..af5a7bcb66c37fbf0000642f7b478dba061a374a 100644
  3--- a/README.md
  4+++ b/README.md
  5@@ -38,6 +38,9 @@ POSTGRES_URL=postgres://ytrssil:ytrssil@localhost:5432/ytrssil?sslmode=disable
  6 # Where downloaded videos are saved
  7 DOWNLOADS_DIR=/var/lib/ytrssil/downloads
  8 
  9+# Optional Netscape-format cookie file passed to yt-dlp
 10+YTDLP_COOKIES_FILE=/path/to/cookies.txt
 11+
 12 # How often to check for new videos (default: 5m)
 13 FETCH_INTERVAL=5m
 14 
 15diff --git a/cmd/main.go b/cmd/main.go
 16index 9f7211e0320b86f7071a1f8a96e63a5a403deb1b..f3895e57412388067ecae2fc6aad2ef978f30627 100644
 17--- a/cmd/main.go
 18+++ b/cmd/main.go
 19@@ -71,7 +71,7 @@ func main() {
 20 
 21 	parser := feedparser.NewParser(logger)
 22 	youTubeClient := youtube.NewYouTubeClient(logger, cfg.YouTubeAPIKey)
 23-	downloader := downloader.NewYtdlpDownloader(logger)
 24+	downloader := downloader.NewYtdlpDownloader(logger, cfg.YTDLPCookiesFile)
 25 	if err := downloader.ValidateInstallation(); err != nil {
 26 		logger.Error("yt-dlp validation failed", "error", err)
 27 		return
 28diff --git a/config/config.go b/config/config.go
 29index 2f786f354bb36c960aa3da15611e418db8e022fa..2387f685caf6c2a011b4e893e64d15229276a885 100644
 30--- a/config/config.go
 31+++ b/config/config.go
 32@@ -10,15 +10,16 @@ import (
 33 )
 34 
 35 type Config struct {
 36-	Dev             bool          `long:"dev" env:"DEV"`
 37-	Port            int           `long:"port" env:"PORT" default:"8080"`
 38-	DBURI           string        `long:"db-uri" env:"DB_URI"`
 39-	AuthToken       string        `long:"auth-token" env:"AUTH_TOKEN"`
 40-	YouTubeAPIKey   string        `long:"youtube-api-key" env:"YOUTUBE_API_KEY"`
 41-	DownloadsDir    string        `long:"downloads-dir" env:"DOWNLOADS_DIR" default:"/var/lib/ytrssil/downloads"`
 42-	FetchInterval   time.Duration `long:"fetch-interval" env:"FETCH_INTERVAL" default:"5m"`
 43-	CleanupInterval time.Duration `long:"cleanup-interval" env:"CLEANUP_INTERVAL" default:"1h"`
 44-	CleanupAge      time.Duration `long:"cleanup-age" env:"CLEANUP_AGE" default:"48h"`
 45+	Dev              bool          `long:"dev" env:"DEV"`
 46+	Port             int           `long:"port" env:"PORT" default:"8080"`
 47+	DBURI            string        `long:"db-uri" env:"DB_URI"`
 48+	AuthToken        string        `long:"auth-token" env:"AUTH_TOKEN"`
 49+	YouTubeAPIKey    string        `long:"youtube-api-key" env:"YOUTUBE_API_KEY"`
 50+	DownloadsDir     string        `long:"downloads-dir" env:"DOWNLOADS_DIR" default:"/var/lib/ytrssil/downloads"`
 51+	YTDLPCookiesFile string        `long:"ytdlp-cookies-file" env:"YTDLP_COOKIES_FILE"`
 52+	FetchInterval    time.Duration `long:"fetch-interval" env:"FETCH_INTERVAL" default:"5m"`
 53+	CleanupInterval  time.Duration `long:"cleanup-interval" env:"CLEANUP_INTERVAL" default:"1h"`
 54+	CleanupAge       time.Duration `long:"cleanup-age" env:"CLEANUP_AGE" default:"48h"`
 55 }
 56 
 57 func getenvOrDefault(key string, defaultValue string) string {
 58diff --git a/go.mod b/go.mod
 59index e2c99a248ba81cd2c81fb568d13876222ae171d1..ca9b9164d013689def7ddd144b91334fd2886edd 100644
 60--- a/go.mod
 61+++ b/go.mod
 62@@ -9,7 +9,7 @@ require (
 63 	github.com/golang-migrate/migrate/v4 v4.19.1
 64 	github.com/jackc/pgx/v5 v5.10.0
 65 	github.com/jessevdk/go-flags v1.6.1
 66-	github.com/oklog/ulid/v2 v2.1.1
 67+	github.com/oklog/ulid/v2 v2.1.2
 68 	github.com/paulrosania/go-charset v0.0.0-20190326053356-55c9d7a5834c
 69 	github.com/starfederation/datastar-go v1.2.2
 70 	github.com/stretchr/testify v1.11.1
 71@@ -21,14 +21,14 @@ require (
 72 	github.com/andybalholm/brotli v1.2.2 // indirect
 73 	github.com/bytedance/gopkg v0.1.4 // indirect
 74 	github.com/bytedance/sonic v1.15.2 // indirect
 75-	github.com/bytedance/sonic/loader v0.5.1 // indirect
 76+	github.com/bytedance/sonic/loader v0.5.2 // indirect
 77 	github.com/cenkalti/backoff/v4 v4.3.0 // indirect
 78 	github.com/cli/browser v1.3.0 // indirect
 79 	github.com/cloudwego/base64x v0.1.7 // indirect
 80 	github.com/davecgh/go-spew v1.1.2-0.20180830191138-d8f796af33cc // indirect
 81 	github.com/fatih/color v1.19.0 // indirect
 82 	github.com/fsnotify/fsnotify v1.10.1 // indirect
 83-	github.com/gabriel-vasile/mimetype v1.4.13 // indirect
 84+	github.com/gabriel-vasile/mimetype v1.4.15 // indirect
 85 	github.com/gin-contrib/sse v1.1.1 // indirect
 86 	github.com/go-playground/locales v0.14.1 // indirect
 87 	github.com/go-playground/universal-translator v0.18.1 // indirect
 88@@ -39,19 +39,19 @@ require (
 89 	github.com/jackc/pgservicefile v0.0.0-20240606120523-5a60cdf6a761 // indirect
 90 	github.com/jackc/puddle/v2 v2.2.2 // indirect
 91 	github.com/json-iterator/go v1.1.12 // indirect
 92-	github.com/klauspost/compress v1.19.0 // indirect
 93+	github.com/klauspost/compress v1.19.1 // indirect
 94 	github.com/klauspost/cpuid/v2 v2.4.0 // indirect
 95-	github.com/leodido/go-urn v1.4.0 // indirect
 96+	github.com/leodido/go-urn v1.5.0 // indirect
 97 	github.com/lib/pq v1.12.3 // indirect
 98 	github.com/mattn/go-colorable v0.1.15 // indirect
 99-	github.com/mattn/go-isatty v0.0.22 // indirect
100+	github.com/mattn/go-isatty v0.0.24 // indirect
101 	github.com/modern-go/concurrent v0.0.0-20180306012644-bacd9c7ef1dd // indirect
102 	github.com/modern-go/reflect2 v1.0.2 // indirect
103 	github.com/natefinch/atomic v1.0.1 // indirect
104 	github.com/pelletier/go-toml/v2 v2.4.3 // indirect
105 	github.com/pmezard/go-difflib v1.0.1-0.20181226105442-5d4384ee4fb2 // indirect
106 	github.com/quic-go/qpack v0.6.0 // indirect
107-	github.com/quic-go/quic-go v0.60.0 // indirect
108+	github.com/quic-go/quic-go v0.61.0 // indirect
109 	github.com/rogpeppe/go-internal v1.15.0 // indirect
110 	github.com/twitchyliquid64/golang-asm v0.15.1 // indirect
111 	github.com/ugorji/go/codec v1.3.1 // indirect
112diff --git a/go.sum b/go.sum
113index 33fa1b9ea83758f3eb6587f484f0ab8eec38d8a5..f3a12438427eab6d6a6276e54a80743fd55442a3 100644
114--- a/go.sum
115+++ b/go.sum
116@@ -15,8 +15,8 @@ github.com/bytedance/gopkg v0.1.4 h1:oZnQwnX82KAIWb7033bEwtxvTqXcYMxDBaQxo5JJHWM
117 github.com/bytedance/gopkg v0.1.4/go.mod h1:v1zWfPm21Fb+OsyXN2VAHdL6TBb2L88anLQgdyje6R4=
118 github.com/bytedance/sonic v1.15.2 h1:90H+rcF/FwLXwfB1cudOLq/je83n683Utf4Cbp0xHCo=
119 github.com/bytedance/sonic v1.15.2/go.mod h1:mT2NbXunuaEbnZ+mRIX/vYqKISmgEuHFDI4UzmKx2SA=
120-github.com/bytedance/sonic/loader v0.5.1 h1:Ygpfa9zwRCCKSlrp5bBP/b/Xzc3VxsAW+5NIYXrOOpI=
121-github.com/bytedance/sonic/loader v0.5.1/go.mod h1:AR4NYCk5DdzZizZ5djGqQ92eEhCCcdf5x77udYiSJRo=
122+github.com/bytedance/sonic/loader v0.5.2 h1:0QtP1gevc1OZ6/H8Lb9BRZiCXd1Ftjd3OKuj1T1lBIo=
123+github.com/bytedance/sonic/loader v0.5.2/go.mod h1:AR4NYCk5DdzZizZ5djGqQ92eEhCCcdf5x77udYiSJRo=
124 github.com/cenkalti/backoff/v4 v4.3.0 h1:MyRJ/UdXutAwSAT+s3wNd7MfTIcy71VQueUuFK343L8=
125 github.com/cenkalti/backoff/v4 v4.3.0/go.mod h1:Y3VNntkOUPxTVeUxJ/G5vcM//AlwfmyYozVcomhLiZE=
126 github.com/cli/browser v1.3.0 h1:LejqCrpWr+1pRqmEPDGnTZOjsMe7sehifLynZJuqJpo=
127@@ -49,8 +49,8 @@ github.com/felixge/httpsnoop v1.0.4 h1:NFTV2Zj1bL4mc9sqWACXbQFVBBg2W3GPvqp8/ESS2
128 github.com/felixge/httpsnoop v1.0.4/go.mod h1:m8KPJKqk1gH5J9DgRY2ASl2lWCfGKXixSwevea8zH2U=
129 github.com/fsnotify/fsnotify v1.10.1 h1:b0/UzAf9yR5rhf3RPm9gf3ehBPpf0oZKIjtpKrx59Ho=
130 github.com/fsnotify/fsnotify v1.10.1/go.mod h1:TLheqan6HD6GBK6PrDWyDPBaEV8LspOxvPSjC+bVfgo=
131-github.com/gabriel-vasile/mimetype v1.4.13 h1:46nXokslUBsAJE/wMsp5gtO500a4F3Nkz9Ufpk2AcUM=
132-github.com/gabriel-vasile/mimetype v1.4.13/go.mod h1:d+9Oxyo1wTzWdyVUPMmXFvp4F9tea18J8ufA774AB3s=
133+github.com/gabriel-vasile/mimetype v1.4.15 h1:05iP/CYtZ/w455R/KZM6rZ5ieAdh99UPtd+d3YzLmaI=
134+github.com/gabriel-vasile/mimetype v1.4.15/go.mod h1:azpTcoLcDZRNgFou5j+APrqQx9HqVPWa6ijYQIIVswQ=
135 github.com/gin-contrib/sse v1.1.1 h1:uGYpNwTacv5R68bSGMapo62iLTRa9l5zxGCps4hK6ko=
136 github.com/gin-contrib/sse v1.1.1/go.mod h1:QXzuVkA0YO7o/gun03UI1Q+FTI8ZV/n5t03kIQAI89s=
137 github.com/gin-gonic/gin v1.12.0 h1:b3YAbrZtnf8N//yjKeU2+MQsh2mY5htkZidOM7O0wG8=
138@@ -93,8 +93,8 @@ github.com/jessevdk/go-flags v1.6.1/go.mod h1:Mk8T1hIAWpOiJiHa9rJASDK2UGWji0EuPG
139 github.com/json-iterator/go v1.1.12 h1:PV8peI4a0ysnczrg+LtxykD8LfKY9ML6u2jnxaEnrnM=
140 github.com/json-iterator/go v1.1.12/go.mod h1:e30LSqwooZae/UwlEbR2852Gd8hjQvJoHmT4TnhNGBo=
141 github.com/klauspost/compress v1.16.7/go.mod h1:ntbaceVETuRiXiv4DpjP66DpAtAGkEQskQzEyD//IeE=
142-github.com/klauspost/compress v1.19.0 h1:sXLILfc9jV2QYWkzFOPWStmcUVH2RHEB1JCdY2oVvCQ=
143-github.com/klauspost/compress v1.19.0/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ=
144+github.com/klauspost/compress v1.19.1 h1:VsB4HPswih7mmZ8WleSFQ75c/Ui1M4trX5oAsJnhSlk=
145+github.com/klauspost/compress v1.19.1/go.mod h1:cwPg85FWrGar70rWktvGQj8/hthj3wpl0PGDogxkrSQ=
146 github.com/klauspost/cpuid/v2 v2.4.0 h1:S6Hrbc7+ywsr0r+RLapfGBHfyefhCTwEh3A0tV913Dw=
147 github.com/klauspost/cpuid/v2 v2.4.0/go.mod h1:19jmZ9mjzoF//ddRSUsv0zfBTJWh3QJh9FNxZTMrGxU=
148 github.com/klauspost/pgzip v1.2.6/go.mod h1:Ch1tH69qFZu15pkjo5kYi6mth2Zzwzt50oCQKQE9RUs=
149@@ -102,14 +102,14 @@ github.com/kr/pretty v0.3.1 h1:flRD4NNwYAUpkphVc1HcthR4KEIFJ65n8Mw5qdRn3LE=
150 github.com/kr/pretty v0.3.1/go.mod h1:hoEshYVHaxMs3cyo3Yncou5ZscifuDolrwPKZanG3xk=
151 github.com/kr/text v0.2.0 h1:5Nx0Ya0ZqY2ygV366QzturHI13Jq95ApcVaJBhpS+AY=
152 github.com/kr/text v0.2.0/go.mod h1:eLer722TekiGuMkidMxC/pM04lWEeraHUUmBw8l2grE=
153-github.com/leodido/go-urn v1.4.0 h1:WT9HwE9SGECu3lg4d/dIA+jxlljEa1/ffXKmRjqdmIQ=
154-github.com/leodido/go-urn v1.4.0/go.mod h1:bvxc+MVxLKB4z00jd1z+Dvzr47oO32F/QSNjSBOlFxI=
155+github.com/leodido/go-urn v1.5.0 h1:pLqT2kq1zpHW/1D18QMjMpdtX7cekxqtJJjg5ANyWw0=
156+github.com/leodido/go-urn v1.5.0/go.mod h1:9BORnCDhdPBJNDEX+w1bJisa8yOKYi116VeO96s4ifE=
157 github.com/lib/pq v1.12.3 h1:tTWxr2YLKwIvK90ZXEw8GP7UFHtcbTtty8zsI+YjrfQ=
158 github.com/lib/pq v1.12.3/go.mod h1:/p+8NSbOcwzAEI7wiMXFlgydTwcgTr3OSKMsD2BitpA=
159 github.com/mattn/go-colorable v0.1.15 h1:+u9SLTRGnXv73cEsnsmoZBom+dMU88B2M0aDcWy0/jY=
160 github.com/mattn/go-colorable v0.1.15/go.mod h1:6LmQG8QLFO4G5z1gPvYEzlUgJ2wF+stgPZH1UqBm1s8=
161-github.com/mattn/go-isatty v0.0.22 h1:j8l17JJ9i6VGPUFUYoTUKPSgKe/83EYU2zBC7YNKMw4=
162-github.com/mattn/go-isatty v0.0.22/go.mod h1:ZXfXG4SQHsB/w3ZeOYbR0PrPwLy+n6xiMrJlRFqopa4=
163+github.com/mattn/go-isatty v0.0.24 h1:tGZZoVgT/KiqK1c8ocVLeDS8BSWMRd47J3Lbz7vsReI=
164+github.com/mattn/go-isatty v0.0.24/go.mod h1:nMCL3Zebbrt45jsMDgnfIwz6ydEQApk5oEI3HqDio6A=
165 github.com/moby/docker-image-spec v1.3.1 h1:jMKff3w6PgbfSa69GfNg+zN/XLhfXJGnEx3Nl2EsFP0=
166 github.com/moby/docker-image-spec v1.3.1/go.mod h1:eKmb5VW8vQEh/BAr2yvVNvuiJuY6UIocYsFu/DxxRpo=
167 github.com/moby/term v0.5.0 h1:xt8Q1nalod/v7BqbG21f8mQPqH+xAaC9C3N3wfWbVP0=
168@@ -123,8 +123,8 @@ github.com/morikuni/aec v1.0.0 h1:nP9CBfwrvYnBRgY6qfDQkygYDmYwOilePFkwzv4dU8A=
169 github.com/morikuni/aec v1.0.0/go.mod h1:BbKIizmSmc5MMPqRYbxO4ZU0S0+P200+tUnFx7PXmsc=
170 github.com/natefinch/atomic v1.0.1 h1:ZPYKxkqQOx3KZ+RsbnP/YsgvxWQPGxjC0oBt2AhwV0A=
171 github.com/natefinch/atomic v1.0.1/go.mod h1:N/D/ELrljoqDyT3rZrsUmtsuzvHkeB/wWjHV22AZRbM=
172-github.com/oklog/ulid/v2 v2.1.1 h1:suPZ4ARWLOJLegGFiZZ1dFAkqzhMjL3J1TzI+5wHz8s=
173-github.com/oklog/ulid/v2 v2.1.1/go.mod h1:rcEKHmBBKfef9DhnvX7y1HZBYxjXb0cP5ExxNsTT1QQ=
174+github.com/oklog/ulid/v2 v2.1.2 h1:IEclFb9JNvzYA6MW2SCxbLzcHTVsfqm3PrqGQJH5zec=
175+github.com/oklog/ulid/v2 v2.1.2/go.mod h1:rcEKHmBBKfef9DhnvX7y1HZBYxjXb0cP5ExxNsTT1QQ=
176 github.com/opencontainers/go-digest v1.0.0 h1:apOUWs51W5PlhuyGyz9FCeeBIOUDA/6nW8Oi/yOhh5U=
177 github.com/opencontainers/go-digest v1.0.0/go.mod h1:0JzlMkj0TRzQZfJkVvzbP0HBR3IKzErnv2BNG4W4MAM=
178 github.com/opencontainers/image-spec v1.1.0 h1:8SG7/vwALn54lVB/0yZ/MMwhFrPYtpEHQb2IpWsCzug=
179@@ -145,8 +145,8 @@ github.com/quic-go/go-ossfuzz-seeds v0.1.0 h1:APacT+iIaNF6fd8AGEiN3bT/Jtkd2jz4v4
180 github.com/quic-go/go-ossfuzz-seeds v0.1.0/go.mod h1:3IOHRbJIc+L6YKMwfDtJAM9Vj9k0YY4muhuyUYk5tbk=
181 github.com/quic-go/qpack v0.6.0 h1:g7W+BMYynC1LbYLSqRt8PBg5Tgwxn214ZZR34VIOjz8=
182 github.com/quic-go/qpack v0.6.0/go.mod h1:lUpLKChi8njB4ty2bFLX2x4gzDqXwUpaO1DP9qMDZII=
183-github.com/quic-go/quic-go v0.60.0 h1:xcQioE8OM66UQLeUMHltK1CCcOu3JbVB4JAQdDQSB+0=
184-github.com/quic-go/quic-go v0.60.0/go.mod h1:wpKpjmPpftl30sL6pFh7REVpjbcCVy4zt2vDyK1TuJk=
185+github.com/quic-go/quic-go v0.61.0 h1:ui88A53s8MSVYLC56en0KQ17HARk+9986Dn0SBfKNvA=
186+github.com/quic-go/quic-go v0.61.0/go.mod h1:9So2anK4Tp22URSQq00k+Vo2PNkle96ycDPDHL4s9vs=
187 github.com/rogpeppe/go-internal v1.15.0 h1:D0RCU5rMAp+SpgkiNdrjfJ+LX4J1M32V2NeCY7EJ6hc=
188 github.com/rogpeppe/go-internal v1.15.0/go.mod h1:DrUVZyrJU+txYW5/1kwtXQSMFio52ZOxX7yM1VHvnxs=
189 github.com/starfederation/datastar-go v1.2.2 h1:f+U2y5FY5tXgXaTVXkuKu+Tz9uh7BU1j8jxthYmcC9Q=
190diff --git a/lib/downloader/downloader.go b/lib/downloader/downloader.go
191index 50be9a0e79056e9fc4aa9fcfac5921d69525f34c..d88ce39cda33b7ac01f928ddf909ac7f4d001ba8 100644
192--- a/lib/downloader/downloader.go
193+++ b/lib/downloader/downloader.go
194@@ -16,11 +16,12 @@ type Downloader interface {
195 }
196 
197 type ytdlpDownloader struct {
198-	log *slog.Logger
199+	log             *slog.Logger
200+	cookiesFilePath string
201 }
202 
203-func NewYtdlpDownloader(log *slog.Logger) *ytdlpDownloader {
204-	return &ytdlpDownloader{log: log}
205+func NewYtdlpDownloader(log *slog.Logger, cookiesFilePath string) *ytdlpDownloader {
206+	return &ytdlpDownloader{log: log, cookiesFilePath: cookiesFilePath}
207 }
208 
209 func (d *ytdlpDownloader) ValidateInstallation() error {
210@@ -49,17 +50,20 @@ func (d *ytdlpDownloader) Download(
211 		resolution = defaultResolution
212 	}
213 	outputTemplate := filepath.Join(outputDir, fmt.Sprintf("%s.%%(ext)s", videoID))
214-
215-	cmd := exec.CommandContext(ctx,
216-		"yt-dlp",
217+	args := []string{
218 		"--format", formatSelector(resolution),
219 		"--output", outputTemplate,
220 		"--no-playlist",
221 		"--no-warnings",
222 		"--quiet",
223 		"--progress",
224-		fmt.Sprintf("https://www.youtube.com/watch?v=%s", videoID),
225-	)
226+	}
227+	if d.cookiesFilePath != "" {
228+		args = append(args, "--cookies", d.cookiesFilePath)
229+	}
230+	args = append(args, fmt.Sprintf("https://www.youtube.com/watch?v=%s", videoID))
231+
232+	cmd := exec.CommandContext(ctx, "yt-dlp", args...)
233 
234 	output, err := cmd.CombinedOutput()
235 	if err != nil {