Commit Graph
14 Commits
Author SHA1 Message Date
mozempkandClaude Sonnet 4.6 6830c8b5a8 ci: add Gitea Actions build+deploy workflow
Build and publish docker image / deploy_ovh (push) Successful in 32s
Build and publish docker image / Build and push image to Gitea's registry (push) Successful in 10s
Automates Docker image build+push to Gitea registry and SSH deploy
to OVH on every push to master. Mirrors the ovh org CI pattern.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 18:04:08 +02:00
mozempkandClaude Sonnet 4.6 924cd0cf0b fix: Instagram probe check HTTP 200 not status:ok field
/api/v1/accounts/current_user/ returns {user:{...}} on success (HTTP 200),
not {status:"ok"}. Checking data.status === 'ok' always failed even with
valid cookies. Use HTTP status code instead.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 17:09:43 +02:00
mozempkandClaude Sonnet 4.6 f33f906c46 fix: follow redirects in cookie probes; handle GDPR consent on YouTube
YouTube /feed/library redirects to consent.youtube.com from EU servers (OVH/FR)
before reaching the login check. httpsGetFollow now follows up to 4 hops,
stopping only if we land on accounts.google.com (= session expired).
Facebook probe also follows its redirect chain.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 00:19:44 +02:00
mozempkandClaude Sonnet 4.6 6cb42a1a02 fix: replace yt-dlp probe with platform-specific HTTP checks
yt-dlp --simulate on profile pages returned non-zero for non-auth reasons
(no extractable media), incorrectly marking valid cookies as expired.
yt-dlp also has no Threads extractor so that probe always failed.

New probes:
- instagram/threads: Instagram Private API /api/v1/accounts/current_user/
  returns {status:"ok"} when sessionid is valid
- facebook: mbasic.facebook.com — logged-out page contains id="login_form"
- youtube: /feed/library — logged-out triggers redirect to accounts.google.com

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-16 00:16:53 +02:00
mozempkandClaude Sonnet 4.6 f269ba0f90 feat: in-app cookie refresh — sync back updated tokens after probes and downloads
- probeAllCookies now re-reads the temp cookie file after each yt-dlp probe; any
  short-lived tokens refreshed by the platform during the request are persisted back
  to the encrypted DB store (syncCookiesFromFile)
- queue does the same after every successful download
- probe interval: 24h → 12h so tokens stay warm

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-15 18:19:17 +02:00
mozempkandClaude Sonnet 4.6 865cc834db feat: split retention into file purge (2d) and db cleanup (14d), add re-download
- FILE_RETENTION_DAYS (default 2): delete files, mark job 'purged', null filePath/fileSize
- RETENTION_DAYS (default 14): delete DB records for purged/failed/cancelled jobs
- 'purged' status: files gone but URL preserved; Re-download button re-queues the job
- JobCard shows Re-download (blue) for purged status with yellow badge
- Detail page shows Re-download button for purged jobs
- retry resets filePath/fileSize so stale values don't linger

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-15 18:12:52 +02:00
mozempkandClaude Sonnet 4.6 d3ce4aacdf fix: resolve YouTube n-challenge with js-runtimes + remote-components
tv player_client alone insufficient; node js-runtime + ejs remote component
bypasses the n-signature decryption requirement.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-15 17:59:52 +02:00
mozempkandClaude Sonnet 4.6 11688ccf30 Fix Threads URL detection: add threads.com alongside threads.net
threads.net now redirects to threads.com; detectExtractor only checked
threads.net so all threads.com URLs fell through to generic extractor,
bypassing the custom downloadThreads() handler.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-15 17:40:31 +02:00
mozempkandClaude Sonnet 4.6 1d7aa3c6e0 Fix docker-compose network name, add cookie upload script
- docker-compose.yml: rename network npm_network → proxy (matches ideapad stack)
- scripts/upload-cookies.sh: curl-based helper to login + bulk-upload all
  cookie files to a running instance via /api/cookies

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-15 17:17:13 +02:00
mozempkandClaude Sonnet 4.6 767da84772 Add Threads downloader via Instagram private API
yt-dlp has no Threads extractor. Implemented custom downloader in
threads.ts that converts Threads post shortcodes to Instagram media_ids,
queries i.instagram.com/api/v1/media/{id}/info/, and downloads the
highest-quality video version with progress reporting.

- queue.ts routes extractor=threads to downloadThreads()
- cookies-*.txt added to .gitignore
- generate-cookies.ts: fix domainFlag column, add flag-file proceed mechanism
- Add playwright + tsx as dev deps for cookie generation script

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-15 17:15:15 +02:00
mozempkandClaude Sonnet 4.6 471b8b71f1 Fix production migration: replace drizzle-kit with drizzle-orm migrator
drizzle-kit is a devDependency and is pruned from the production image.
Replaced npm run db:migrate with a plain Node CJS script that uses
drizzle-orm/better-sqlite3/migrator directly. Auto-detects migrations
path (drizzle/migrations in prod, src/lib/server/db/migrations in dev).
Simplified entrypoint.sh — no more fallback needed.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-15 16:10:38 +02:00
mozempkandClaude Sonnet 4.6 96f6f1d294 Fix env lazy evaluation, svelte warnings, unused imports
env.ts: use property getters so $env/dynamic/private is not evaluated
at Vite build time (Docker builder has no env vars set).

JobCard: $derived + $state override pattern eliminates
state_referenced_locally warnings. jobs/[id]: untrack() for initial
job snapshot. settings: associate labels with form controls. retention:
drop unused drizzle-orm imports.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-15 00:18:12 +02:00
mozempkandClaude Sonnet 4.6 40ea92f53c Initial implementation — self-hosted yt-dlp PWA
SvelteKit 5 + adapter-node, better-sqlite3 + Drizzle ORM, jose JWT
(HS256), web-push VAPID, Tailwind 4. Fire-and-forget video downloads
via Web Share Target with SSE progress and push notifications on
completion/failure. Per-extractor cookies, 14d retention, p-limit
concurrency cap, Range-aware file serving.

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-15 00:12:22 +02:00
mozempkandClaude Sonnet 4.6 c78f63d43a Initial implementation: self-hosted yt-dlp PWA
SvelteKit 5 + adapter-node PWA with:
- JWT auth (HS256, OIDC-ready interface) with auto-seeded admin
- Web Share Target (POST /share) for fire-and-forget URL sharing
- yt-dlp queue with p-limit concurrency (MAX_CONCURRENT=2)
- SSE progress streaming from yt-dlp --newline output
- Web Push notifications (VAPID) on complete/fail
- Per-extractor cookies store (AES-256-GCM encrypted at rest)
- 14-day retention cleanup with orphan sweep
- Local Playwright cookie generator script (scripts/generate-cookies.ts)
- Docker single-container (Alpine + ffmpeg + yt-dlp via pip)
- NPM proxy-network deployment (npm_network external)
- Drizzle ORM + better-sqlite3 (WAL mode)

Co-Authored-By: Claude Sonnet 4.6 <noreply@anthropic.com>
2026-05-14 01:58:51 +02:00