Base reddit cookie expiry warning on reddit_session, the only cookie actually required.

Co-Authored-By: Claude Opus 5.5 <noreply@anthropic.com>
This commit is contained in:
2026-11-05 22:49:09 +01:00
co-authored by Claude Opus 5.5
parent 309a99755c
commit 6582bac049
2 changed files with 24 additions and 8 deletions
+1 -1
View File
@@ -27,7 +27,7 @@ The pipeline runs from `src/app.js`:
### Reddit client (`src/reddit/client.js`), the core of this branch
- Calls reddit's public `.json` endpoints on `www.reddit.com` (`/user/x/about.json`, `/user/x/submitted.json`, `/comments/id.json`, `/api/morechildren.json`) with `raw_json=1`. There is no OAuth.
- Anonymous requests run into reddit's bot challenge, so a logged-in session's cookies (`config.reddit.cookies`, a cookie-jar string, or `config.reddit.cookie`, a raw header) are sent. If reddit returns HTML instead of JSON, the cookies have most likely expired. The client warns when the soonest cookie expires within 48h.
- Anonymous requests run into reddit's bot challenge, so a logged-in session's cookies (`config.reddit.cookies`, a cookie-jar string, or `config.reddit.cookie`, a raw header) are sent. Live testing (2026-11) showed that only `reddit_session` (the login, valid ~6 months) is required; without it, reddit returns a 403 HTML page. The client warns when `reddit_session` is missing or expires within 48h.
- Social links have no public JSON endpoint (the widgets API needs OAuth). They are scraped from the profile page HTML (`data-faceplate-tracking-context` attributes), which is fragile and breaks whenever reddit changes its markup.
- All reddit requests go through **one Bottleneck limiter**: `maxConcurrent: 1`, reservoir 6/min, `minTime` 1500ms (`config.reddit.throttle`). This is deliberately slow, because being flagged as a bot defeats the purpose. Retries for 429/503 and network errors happen **outside** `limiter.schedule()`. Retrying inside it previously caused a deadlock; keep it that way.
- Avoid unnecessary reddit calls: gallery posts reuse `media_metadata`/`gallery_data` from the submission listing (`curate/posts.js` → `methods/redditAlbum.js`). `getSubmission` (post only, cheap) is separate from `getSubmissionWithComments` (full comment tree including `more` stubs, which is expensive and only used for self posts).
+23 -7
View File
@@ -38,17 +38,29 @@ function parseCookieJar(raw) {
.join('; ');
}
function soonestExpiry(raw) {
const expiries = raw
// per live testing (2026-11), reddit_session (the login itself, valid for ~6 months) is the
// only cookie needed to get past the bot challenge - everything else in a browser export
// (token_v2 ~24h, seeker_session a few hours, ...) is irrelevant here, and warning about those
// expiring just cries wolf. Only fall back to the soonest-expiring cookie if there's no
// reddit_session in the jar at all.
function loginExpiry(raw) {
const cookies = raw
.split('\n')
.map((line) => line.trim())
.filter((line) => line && !line.startsWith('#'))
.map((line) => line.split('\t'))
.filter((fields) => fields.length === 7)
.map(([, , , , expiry]) => Number(expiry))
.filter((expiry) => expiry > 0);
.map(([, , , , expiry, name]) => ({ name, expiry: Number(expiry) }));
return expiries.length ? Math.min(...expiries) : null;
const session = cookies.find(({ name }) => name === 'reddit_session');
if (session) {
return { name: session.name, expiry: session.expiry > 0 ? session.expiry : null };
}
const expiring = cookies.filter(({ expiry }) => expiry > 0).sort((a, b) => a.expiry - b.expiry);
return expiring[0] || { name: null, expiry: null };
}
let cachedCookieHeader;
@@ -64,11 +76,15 @@ function cookieHeader() {
: 'No reddit cookies configured, requesting unauthenticated');
if (config.reddit.cookies) {
const expiry = soonestExpiry(config.reddit.cookies);
const { name, expiry } = loginExpiry(config.reddit.cookies);
const hoursLeft = expiry ? (expiry - Date.now() / 1000) / 3600 : null;
if (name !== 'reddit_session') {
logger.warn('No reddit_session cookie in config.reddit.cookies - reddit will likely block requests');
}
if (hoursLeft !== null && hoursLeft < 48) {
logger.warn(`Soonest-expiring reddit cookie expires in ${hoursLeft.toFixed(1)}h (${new Date(expiry * 1000).toISOString()}) - refresh config/cookies.js before then`);
logger.warn(`Reddit cookie '${name}' expires in ${hoursLeft.toFixed(1)}h (${new Date(expiry * 1000).toISOString()}) - refresh config/cookies.js before then`);
}
}
}