Compare commits
3 Commits
9794efde46
...
1e6bb27404
| Author | SHA1 | Date | |
|---|---|---|---|
|
|
1e6bb27404 | ||
|
|
3a23d76f24 | ||
|
|
52751df735 |
@ -198,6 +198,8 @@ class DoodstreamUploader {
|
||||
// Use the standard upload server endpoint
|
||||
const res = await this._fetch(BASE_URL + '/?op=upload_server');
|
||||
const text = await res.text();
|
||||
const ctype = (res.headers && res.headers.get) ? (res.headers.get('content-type') || '') : '';
|
||||
_debugLog(`upload_server: status=${res.status} ctype=${ctype} body(800)=${(text || '').slice(0, 800)}`);
|
||||
let json;
|
||||
try { json = JSON.parse(text); } catch { json = null; }
|
||||
|
||||
@ -211,8 +213,18 @@ class DoodstreamUploader {
|
||||
const srvMatch = html.match(/srv_url['":\s]+['"]?(https?:\/\/[^'">\s]+)['"]?/i);
|
||||
if (srvMatch) return srvMatch[1];
|
||||
|
||||
// Last resort fallback
|
||||
return 'https://tr1128ve.cloudatacdn.com/upload/01';
|
||||
// No upload server could be extracted. We MUST NOT silently fall back to a
|
||||
// hardcoded node: that node is stale and accepts the bytes but returns an
|
||||
// empty form (no filecode) — so the user wastes ~90s uploading 95 MB into a
|
||||
// dead end and gets a cryptic "kein Filecode" 90s later. Fail fast and put
|
||||
// the raw responses in the error so the real format change is diagnosable.
|
||||
const urlHints = (html.match(/https?:\/\/[^'">\s]+/g) || []).slice(0, 4).join(' , ');
|
||||
_debugLog(`upload_server: NO SERVER. upload-page html(2000)=${(html || '').slice(0, 2000)}`);
|
||||
throw new Error(
|
||||
`Doodstream: konnte Upload-Server nicht ermitteln (Endpoint geaendert?). ` +
|
||||
`op=upload_server status=${res.status} ctype=${ctype} body=${(text || '').slice(0, 300)} ` +
|
||||
`| upload-page URL-Treffer: ${urlHints || 'keine'}`
|
||||
);
|
||||
}
|
||||
|
||||
/**
|
||||
|
||||
@ -1,6 +1,6 @@
|
||||
{
|
||||
"name": "multi-hoster-uploader",
|
||||
"version": "3.3.24",
|
||||
"version": "3.3.25",
|
||||
"description": "Upload files to doodstream, voe, vidmoly, byse simultaneously",
|
||||
"main": "main.js",
|
||||
"scripts": {
|
||||
|
||||
@ -29,3 +29,14 @@
|
||||
**Symptom:** User wartet 5+ min auf Tauri-Build den ich mit "1-2min" angekündigt habe.
|
||||
**Regel:** Tauri-Release-Builds brauchen real 3-6 min (Rust + NSIS + MSI). Keine Zeitangabe oder ehrlich "kann 3-6min dauern" schreiben.
|
||||
**Wie anwenden:** Wenn User nach Status fragt: sofort `tail` des Logs + `ls` des Bundle-Ordners zitieren, nicht raten.
|
||||
|
||||
## 2026-05-24 — Packaged-Electron Log-Pfade: nie __dirname/.. zum Schreiben
|
||||
**Symptom:** doodstream-debug.log hatte auf dem Server null aktuelle Einträge; nur alte Dev-Logs. Fehler "kein Filecode" war nicht diagnostizierbar.
|
||||
**Root cause:** `path.join(__dirname, '..', 'x.log')` zeigt im gepackten Build in `resources/app.asar` (read-only). `fs.appendFileSync` wirft EACCES, der `try/catch` schluckt es → null Production-Logs.
|
||||
**Regel:** Schreibbare Pfade IMMER über `app.getPath('userData')` (lazy `require('electron')`, Fallback `__dirname/..` nur für Tests/plain-node). Gilt für jede Datei die der gepackte App schreibt.
|
||||
**Wie anwenden:** Bei jedem neuen Log/Cache/State-File prüfen: wohin schreibt das im NSIS-Build? Nicht ins Install-Verzeichnis, nicht in asar.
|
||||
|
||||
## 2026-05-24 — Hoster-Fehler: echten Status surfacen, nicht generisch schlucken
|
||||
**Symptom:** "upload_result Seite hat keinen filecode (<leeres textarea>)" — nichtssagend; User dachte doodstream-Format geändert.
|
||||
**Root cause:** XFileSharing liefert den echten Grund im `st`-Feld (Error: duplicate / file too big / …). Code ignorierte `st` komplett und warf nur den leeren Body.
|
||||
**Regel:** Bei Hoster-Parsefehlern immer die Server-Statusfelder (st/msg/code) + Kontext (welcher CDN-Node, war filecode da) in die Fehlermeldung packen. Format-Struktur unverändert + leerer Inhalt = Backend-Ablehnung, kein Parsing-Bug.
|
||||
|
||||
@ -63,3 +63,39 @@ test('happy path: link in result page wins', async () => {
|
||||
const res = await up._parseUploadResponse(cdnForm({ fn: 'jjsuhr931ds9', st: 'OK' }));
|
||||
assert.equal(res.file_code, 'jjsuhr931ds9');
|
||||
});
|
||||
|
||||
// --- _getUploadServer: discovery must never fall back to a hardcoded node ---
|
||||
function fakeRes(body, { status = 200, ctype = 'text/html' } = {}) {
|
||||
return { status, headers: { get: (h) => (h.toLowerCase() === 'content-type' ? ctype : null) }, text: async () => body };
|
||||
}
|
||||
|
||||
test('getUploadServer: returns JSON result when present', async () => {
|
||||
const up = new DoodstreamUploader();
|
||||
up._fetch = async (url) => {
|
||||
assert.match(url, /op=upload_server/);
|
||||
return fakeRes(JSON.stringify({ result: 'https://node42.cloudatacdn.com/upload/01' }), { ctype: 'application/json' });
|
||||
};
|
||||
assert.equal(await up._getUploadServer(), 'https://node42.cloudatacdn.com/upload/01');
|
||||
});
|
||||
|
||||
test('getUploadServer: falls back to srv_url in upload-page HTML', async () => {
|
||||
const up = new DoodstreamUploader();
|
||||
up._fetch = async (url) => {
|
||||
if (/op=upload_server/.test(url)) return fakeRes('<html>not json</html>');
|
||||
return fakeRes('<script>var srv_url: "https://node7.cloudatacdn.com/upload/01";</script>');
|
||||
};
|
||||
assert.equal(await up._getUploadServer(), 'https://node7.cloudatacdn.com/upload/01');
|
||||
});
|
||||
|
||||
test('getUploadServer: throws (no silent dead fallback) when discovery fails', async () => {
|
||||
const up = new DoodstreamUploader();
|
||||
up._fetch = async () => fakeRes('<html><body>login required</body></html>', { status: 200 });
|
||||
await assert.rejects(
|
||||
() => up._getUploadServer(),
|
||||
(err) => {
|
||||
assert.match(err.message, /konnte Upload-Server nicht ermitteln/);
|
||||
assert.doesNotMatch(err.message, /tr1128ve\.cloudatacdn\.com/); // never the hardcoded node
|
||||
return true;
|
||||
}
|
||||
);
|
||||
});
|
||||
|
||||
Loading…
Reference in New Issue
Block a user