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) <noreply@anthropic.com>
109 lines
4.4 KiB
JavaScript
109 lines
4.4 KiB
JavaScript
const { describe, it } = require('node:test');
|
|
const assert = require('node:assert/strict');
|
|
|
|
const { __test } = require('../lib/hosters');
|
|
|
|
describe('hosters helpers', () => {
|
|
it('extracts VOE file_code from nested result payloads', () => {
|
|
assert.deepEqual(__test.parseVoeResult({ result: { file: { file_code: 'abc123' } } }), {
|
|
download_url: 'https://voe.sx/abc123',
|
|
embed_url: 'https://voe.sx/e/abc123',
|
|
file_code: 'abc123'
|
|
});
|
|
});
|
|
|
|
it('extracts VOE file_code from flat fallback payloads', () => {
|
|
assert.deepEqual(__test.parseVoeResult({ file_code: 'xyz789' }), {
|
|
download_url: 'https://voe.sx/xyz789',
|
|
embed_url: 'https://voe.sx/e/xyz789',
|
|
file_code: 'xyz789'
|
|
});
|
|
});
|
|
|
|
it('extracts upload server URLs from nested API responses', () => {
|
|
const url = __test.extractUploadServerUrl({
|
|
result: {
|
|
server: {
|
|
upload_url: 'https://delivery-hydra.voe-network.net/upload/01'
|
|
}
|
|
}
|
|
}, 'https://voe.sx');
|
|
|
|
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.
|
|
for (const bad of [null, undefined, 'string', 42, true]) {
|
|
const r = __test.parseDoodstreamResult(bad);
|
|
assert.equal(r.file_code, null);
|
|
assert.equal(r.download_url, null);
|
|
assert.equal(r.embed_url, null);
|
|
}
|
|
});
|
|
|
|
it('parseDoodstreamResult handles result-as-array and result-as-object', () => {
|
|
const arr = __test.parseDoodstreamResult({ result: [{ filecode: 'AB1', protected_dl: 'https://x/1', protected_embed: 'https://x/e/1' }] });
|
|
assert.equal(arr.file_code, 'AB1');
|
|
assert.equal(arr.download_url, 'https://x/1');
|
|
assert.equal(arr.embed_url, 'https://x/e/1');
|
|
|
|
const obj = __test.parseDoodstreamResult({ result: { filecode: 'OBJ1', download_url: 'https://x/2' } });
|
|
assert.equal(obj.file_code, 'OBJ1');
|
|
assert.equal(obj.download_url, 'https://x/2');
|
|
});
|
|
|
|
it('parseByseResult tolerates null/non-object payload without throwing', () => {
|
|
for (const bad of [null, undefined, 'string', 42, []]) {
|
|
const r = __test.parseByseResult(bad);
|
|
assert.equal(r.file_code, null);
|
|
assert.equal(r.download_url, null);
|
|
assert.equal(r.embed_url, null);
|
|
}
|
|
});
|
|
|
|
it('parseByseResult handles malformed files entries (null, missing fields)', () => {
|
|
// Files array with a null first element (server returned [null])
|
|
const a = __test.parseByseResult({ files: [null] });
|
|
assert.equal(a.file_code, null);
|
|
// Files array with object missing both filecode and status
|
|
const b = __test.parseByseResult({ files: [{}] });
|
|
assert.equal(b.file_code, null);
|
|
});
|
|
|
|
it('parseByseResult throws fileRejected for non-OK status with empty filecode', () => {
|
|
assert.throws(
|
|
() => __test.parseByseResult({ files: [{ status: 'Not video file format' }] }),
|
|
(err) => err.fileRejected === true && /Not video file format/i.test(err.message)
|
|
);
|
|
});
|
|
|
|
it('parseByseResult flips to accountError for storage-exhausted phrasing', () => {
|
|
assert.throws(
|
|
() => __test.parseByseResult({ files: [{ status: 'not enough disk space on your account' }] }),
|
|
(err) => err.accountError === true
|
|
);
|
|
});
|
|
|
|
it('parseByseResult succeeds with valid filecode in files[0]', () => {
|
|
const r = __test.parseByseResult({ files: [{ filecode: 'GOOD123', status: 'OK' }] });
|
|
assert.equal(r.file_code, 'GOOD123');
|
|
assert.equal(r.download_url, 'https://byse.sx/d/GOOD123');
|
|
assert.equal(r.embed_url, 'https://byse.sx/e/GOOD123');
|
|
});
|
|
});
|