From 040ae17c1246146e54a2f7db9eb718814b0e69b7 Mon Sep 17 00:00:00 2001 From: Giancarmine Salucci Date: Tue, 12 May 2026 22:29:12 +0200 Subject: [PATCH] fix(ui): add ic-btn-reset CSS + auto-convert auth.json to cookies.txt - layout.css: add button.ic-btn-reset rule so all icon buttons (bell, back, close, retry, etc.) get proper background:none reset instead of browser-default white/grey appearance in dark mode - instagram-extractor.ts: auto-convert secrets/auth.json (Playwright storage format) to Netscape cookies.txt at runtime whenever auth.json is newer; ensures sessionid and all Instagram session cookies are passed to yt-dlp, fixing empty media response Co-authored-by: Copilot <223556219+Copilot@users.noreply.github.com> --- src/lib/server/instagram-extractor.ts | 53 ++++++++++++++++++++++++++- src/routes/layout.css | 3 +- 2 files changed, 54 insertions(+), 2 deletions(-) diff --git a/src/lib/server/instagram-extractor.ts b/src/lib/server/instagram-extractor.ts index 76001ec..3298f8d 100644 --- a/src/lib/server/instagram-extractor.ts +++ b/src/lib/server/instagram-extractor.ts @@ -9,7 +9,7 @@ import { execFile } from 'node:child_process'; import { promisify } from 'node:util'; -import { existsSync } from 'node:fs'; +import { existsSync, readFileSync, writeFileSync, statSync } from 'node:fs'; import { logError } from './utils/logger'; import type { ExtractedContent, ProgressCallback } from './extraction'; @@ -20,9 +20,60 @@ const IMAGE_FETCH_TIMEOUT_MS = 10_000; const USER_AGENT = 'Mozilla/5.0 (iPhone; CPU iPhone OS 17_0 like Mac OS X) AppleWebKit/605.1.15 (KHTML, like Gecko) Version/17.0 Mobile/15E148 Safari/604.1'; +const AUTH_PATHS = ['/app/secrets/auth.json', './secrets/auth.json']; const COOKIE_PATHS = ['/app/secrets/cookies.txt', './secrets/cookies.txt']; +interface PlaywrightCookie { + name: string; + value: string; + domain: string; + path: string; + expires: number; + httpOnly?: boolean; + secure?: boolean; +} + +/** Convert Playwright auth.json → Netscape cookies.txt next to it. */ +function maybeConvertAuthJson(): void { + for (let i = 0; i < AUTH_PATHS.length; i++) { + const authPath = AUTH_PATHS[i]; + const cookiePath = COOKIE_PATHS[i]; + if (!existsSync(authPath)) continue; + + // Re-generate whenever auth.json is newer than the existing cookies.txt + const authMtime = statSync(authPath).mtimeMs; + const cookieMtime = existsSync(cookiePath) ? statSync(cookiePath).mtimeMs : 0; + if (cookieMtime >= authMtime) continue; + + try { + const auth = JSON.parse(readFileSync(authPath, 'utf8')) as { + cookies?: PlaywrightCookie[]; + }; + const cookies: PlaywrightCookie[] = auth.cookies ?? []; + const lines = [ + '# Netscape HTTP Cookie File', + '# Auto-generated from auth.json by InstaChef.', + '' + ]; + for (const c of cookies) { + const domain = c.domain.startsWith('.') ? c.domain : `.${c.domain}`; + const includeSubdomains = 'TRUE'; + const secure = c.secure ? 'TRUE' : 'FALSE'; + const expiry = Math.floor(c.expires > 0 ? c.expires : 0); + lines.push( + [domain, includeSubdomains, c.path ?? '/', secure, expiry, c.name, c.value].join('\t') + ); + } + writeFileSync(cookiePath, lines.join('\n') + '\n', 'utf8'); + } catch { + // Non-fatal: yt-dlp will just run without cookies + } + break; + } +} + function resolveCookiePath(): string | null { + maybeConvertAuthJson(); for (const p of COOKIE_PATHS) { if (existsSync(p)) return p; } diff --git a/src/routes/layout.css b/src/routes/layout.css index ebe4b9e..6cd5974 100644 --- a/src/routes/layout.css +++ b/src/routes/layout.css @@ -99,7 +99,8 @@ html, body { } .ic-scroll::-webkit-scrollbar { display: none; } -button.ic-btn { +button.ic-btn, +button.ic-btn-reset { background: none; border: 0; padding: 0;