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>
/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>
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>
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>
- 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>
- 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>
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>
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>
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>
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>