diff --git a/lib/hosters.js b/lib/hosters.js index f9f9961..434fbe5 100644 --- a/lib/hosters.js +++ b/lib/hosters.js @@ -378,7 +378,13 @@ async function getUploadServer(hosterName, hosterConfig, apiKey, signal) { } if (lastMessage) { - throw new Error(`Kein Upload-Server erhalten: ${lastMessage}`); + const e = new Error(`Kein Upload-Server erhalten: ${lastMessage}`); + // "no servers available" / busy / try-again is a transient hoster-side + // condition, not an account fault — tag it so the account isn't blacklisted. + // Genuine auth failures (invalid key / unauthorized / forbidden) make + // shouldRetryServerLookup return false and stay classified as account errors. + if (shouldRetryServerLookup(lastMessage)) e.hosterTransient = true; + throw e; } throw new Error('Kein Upload-Server erhalten. API-Key pruefen.'); } @@ -545,9 +551,18 @@ async function uploadFile(hosterName, filePath, apiKey, onProgress, signal, thro const isOkishNoPayload = /^(ok|success|done|accepted)$/i.test(msg); if (isOkishNoPayload || !msg) { const snippet = JSON.stringify(payload).slice(0, 400); - throw new Error( + // 2xx with no filecode: the hoster accepted the upload (bytes sent, status + // OK) but returned no usable link. For doodstream this is the API-path + // analog of the web empty-form — the backend file-registration timing out + // under large-file load. It's a hoster-side flake, NOT an account problem, + // so tag it hosterTransient: the upload-manager then fails this file WITHOUT + // blacklisting the account (same protection the web path got in 3.3.29) and + // the account stays usable for the next retry/batch. + const err = new Error( `Upload zu ${hosterName} lieferte keine file_code-Antwort (Payload: ${snippet})` ); + err.hosterTransient = true; + throw err; } throw new Error(msg); }