Anti-bot: cookie freshness + anonymous-jar warning

Stale or anonymous cookies make YouTube's bot-detection WORSE than no
cookies — so warn the user before downloads start captcha-failing.

cookies_freshness() parses the Netscape jar and reports:
- expires_at / expired / days_left: earliest expiry among the auth
  cookies that actually gate login (SID, SAPISID, __Secure-*PSID,
  LOGIN_INFO, …). Non-auth cookies (PREF, consent) are ignored so their
  expiry doesn't trigger false warnings.
- no_auth_cookies: the jar has cookies but NONE of the login ones — i.e.
  it's an anonymous/visitor session, not signed in. This is the worst
  case for bot-detection and a common foot-gun (exporting cookies from a
  browser that wasn't logged in to YouTube).

Surfaced in GET /api/cookies and both Settings UIs (web + desktop) with
graded severity: anonymous (red) > expired (red) > expiring-soon
(yellow) > fine.

5 tests cover expired, fresh, session/non-auth ignored, and the
anonymous-jar case. 91 pass.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
Luna 2026-06-01 15:15:51 -07:00
parent 2f711604f0
commit d098e5f6c5
3 changed files with 168 additions and 3 deletions

View file

@ -1386,6 +1386,16 @@ async function openSettings(){
const logoutBtn=cur.download_password_required?`<button onclick="logout()">Log out</button>`:'';
let ck={exists:false,cookies:0};try{ck=await(await api('/api/cookies')).json()}catch{}
const cookiesStatus=ck.exists?`${ck.cookies} cookie(s) loaded`:'no cookies.txt';
// Freshness nudge: expired/soon-to-expire auth cookies make YouTube's
// bot-detection worse, so flag them prominently.
let cookieWarn='';
if(ck.exists&&ck.no_auth_cookies){
cookieWarn=`<div class="settings-hint" style="color:#f87171;font-weight:600">⚠ These cookies are anonymous — they have no YouTube login session (no SID/SAPISID/LOGIN_INFO). YouTube captchas anonymous requests most aggressively. Export a fresh cookies.txt while signed in to YouTube.</div>`;
}else if(ck.exists&&ck.expired){
cookieWarn=`<div class="settings-hint" style="color:#f87171;font-weight:600">⚠ Your login cookies have expired (${Math.abs(ck.days_left||0)}d ago). Refresh them below — stale cookies make YouTube's bot-detection worse.</div>`;
}else if(ck.exists&&ck.days_left!=null&&ck.days_left<=3){
cookieWarn=`<div class="settings-hint" style="color:#facc15">⚠ Login cookies expire in ${ck.days_left}d. Refresh soon to avoid captcha errors.</div>`;
}
const bg=document.createElement('div');bg.className='modal-bg';bg.onclick=e=>{if(e.target===bg)bg.remove()};
bg.innerHTML=`<div class="modal" style="max-width:420px;overflow-y:auto">
<div class="modal-hdr" style="position:sticky;top:0;background:var(--panel);z-index:1;padding-bottom:6px"><h2>Settings</h2></div>
@ -1412,6 +1422,7 @@ async function openSettings(){
<div class="settings-row" style="flex-direction:column;align-items:flex-start;gap:6px">
<label>Cookies (cookies.txt)</label>
<div class="settings-hint" id="cookies-status">${cookiesStatus}</div>
${cookieWarn}
<input type="file" id="cf-cookies-file" accept=".txt,text/plain" onchange="loadCookieFile(this)" style="font-size:11px;color:var(--muted)">
<textarea id="cf-cookies" placeholder="…or paste Netscape-format cookies.txt here" style="width:100%;height:70px;background:var(--bg);color:var(--text);border:1px solid var(--border);border-radius:4px;padding:6px 8px;font-family:monospace;font-size:11px;resize:vertical"></textarea>
<div style="display:flex;gap:6px">