From 46888c0220c80265ebceb47b6fb2347f641ccef6 Mon Sep 17 00:00:00 2001 From: Administrator Date: Fri, 19 Jun 2026 02:19:59 +0200 Subject: [PATCH] fix(byse): reject truncated upload-server hostnames so the lookup retries for a valid one MIME-Version: 1.0 Content-Type: text/plain; charset=UTF-8 Content-Transfer-Encoding: 8bit In v3.3.77 the byse uploads started failing with "getaddrinfo ENOTFOUND s1065.filemoon" / "s1070.filemoon" / "s1075.filemoon". The hostname has no TLD, so DNS cannot resolve it. Root cause: byse's GET /upload/server is INTERMITTENTLY handing back a truncated upload-server host — "sNNNN.filemoon" with the TLD dropped (consistent with byse's ongoing filemoon migration; their own docs already expose an old_domain/new_domain embed switch). Some uploads still work because byse returns the complete host on those; the failing ones got truncated. byse did not change the API contract — this is malformed data from their server pool. The correct upload domain is NOT externally verifiable: every TLD that resolves for these server IDs is a parked/squatter domain (filemoon.art -> ParkLogic "lander" PTR; filemoon.nl -> a shared catch-all cert for kaobei.cc/babesex.xyz/...). Appending a TLD would point uploads at a parking page (or a third party) — so we do NOT guess one. Instead, treat an obviously-truncated host as "no valid server": normalizeAbsoluteUrl now returns null for any host ending in the bare ".filemoon" label (never a real TLD). extractUploadServerUrl then yields nothing for that response, so getUploadServer falls through to its existing machinery — it retries the lookup (SERVER_RETRY_ATTEMPTS) to get a different server and, crucially, returns the last-known-good server from LAST_UPLOAD_SERVERS once one has been cached. So after any single complete response, the truncated ones transparently reuse the good server instead of uploading into a DNS void. If byse's whole pool is truncating (cold cache), the lookup fails CLEAN as hosterTransient (no cascade, no blacklist — the v3.3.77 behavior), and the next batch tries again. This composes with v3.3.77: ENOTFOUND was already transient (retry same account, no failover); this stops the unresolvable host from ever reaching the POST in the first place when a working server is available. Tests: extractUploadServerUrl rejects https://sNNNN.filemoon / bare sNNNN.filemoon / https://filemoon and keeps a complete host (https://s1065.filemoon.sx/...) untouched. Suite 313/313. Co-Authored-By: Claude Opus 4.8 (1M context) --- lib/hosters.js | 2 ++ tests/hosters.test.js | 13 +++++++++++++ 2 files changed, 15 insertions(+) diff --git a/lib/hosters.js b/lib/hosters.js index 1069243..b28c981 100644 --- a/lib/hosters.js +++ b/lib/hosters.js @@ -8,6 +8,7 @@ const API_TIMEOUT = 45000; // 45 seconds const SERVER_RETRY_ATTEMPTS = 6; const SERVER_RETRY_DELAY_MS = 2500; const LAST_UPLOAD_SERVERS = new Map(); +const TRUNCATED_UPLOAD_HOST = /(^|\.)filemoon$/i; function appendRawQuery(url, rawQuery) { const parsed = new URL(url); @@ -79,6 +80,7 @@ function normalizeAbsoluteUrl(raw, apiBase) { try { const parsed = new URL(candidate); if (!['http:', 'https:'].includes(parsed.protocol)) return null; + if (TRUNCATED_UPLOAD_HOST.test(parsed.hostname)) return null; return parsed.href; } catch { return null; diff --git a/tests/hosters.test.js b/tests/hosters.test.js index 9f41eef..56b8ba5 100644 --- a/tests/hosters.test.js +++ b/tests/hosters.test.js @@ -32,6 +32,19 @@ describe('hosters helpers', () => { assert.equal(url, 'https://delivery-hydra.voe-network.net/upload/01'); }); + it('rejects byse truncated upload hosts (TLD dropped) so the lookup retries for a valid server', () => { + assert.equal(__test.extractUploadServerUrl({ result: 'https://s1065.filemoon/upload/01' }, 'https://api.byse.sx'), null); + assert.equal(__test.extractUploadServerUrl({ result: 's1070.filemoon' }, 'https://api.byse.sx'), null); + assert.equal(__test.extractUploadServerUrl({ result: 'https://filemoon/upload/01' }, 'https://api.byse.sx'), null); + }); + + it('keeps a complete byse upload host (real TLD present) untouched', () => { + assert.equal( + __test.extractUploadServerUrl({ result: 'https://s1065.filemoon.sx/upload/01' }, 'https://api.byse.sx'), + 'https://s1065.filemoon.sx/upload/01' + ); + }); + it('parseDoodstreamResult tolerates null/non-object payload without throwing', () => { // Direct callers may bypass uploadFile's normalisation. The parser must // never throw on bad input — empty fields are the contract.