diff --git a/lib/config-store.js b/lib/config-store.js index 1a467a5..416f0d1 100644 --- a/lib/config-store.js +++ b/lib/config-store.js @@ -11,7 +11,8 @@ const HOSTER_SETTINGS_DEFAULTS = { timeIntervalSec: 0, // delay between jobs maxSizeMb: 0, // 0 = unlimited logToFile: true, // write this hoster's successful links to fileuploader.log - rotateAccounts: false + rotateAccounts: false, + sizeMemoEnabled: true }; // Template for each hoster type (used as defaults for new accounts) diff --git a/lib/upload-manager.js b/lib/upload-manager.js index 4963340..f88c026 100644 --- a/lib/upload-manager.js +++ b/lib/upload-manager.js @@ -17,7 +17,8 @@ const DEFAULT_SETTINGS = { parallelCount: 2, restartBelowKbs: 0, timeIntervalSec: 0, - maxSizeMb: 0 + maxSizeMb: 0, + sizeMemoEnabled: true }; class UploadManager extends EventEmitter { @@ -116,6 +117,7 @@ class UploadManager extends EventEmitter { } _suspectMemoBlocks(hoster, accountId, fileSize) { + if (this.hosterSettings[hoster] && this.hosterSettings[hoster].sizeMemoEnabled === false) return false; const memo = this._suspectSizeMemo.get(hoster + ':' + accountId); return !!memo && memo.count >= 2 && fileSize > memo.size; } diff --git a/renderer/app.js b/renderer/app.js index eabc32f..8f13ad3 100644 --- a/renderer/app.js +++ b/renderer/app.js @@ -3678,6 +3678,11 @@ function _buildHosterSettingsHtml(name) { Verteilt die Dateien reihum auf alle aktiven Accounts dieses Hosters (Datei 1 → Account 1, Datei 2 → Account 2 …). Hält z. B. byse-Accounts aktiv. Nur ein Account = kein Effekt. +
+ + + Überspringt nach zwei verdächtigen Ablehnungen auf einem Account größere Dateien dort vorab ("Bekanntes Größen-Limit"). Abschalten = jede Datei wird immer wirklich versucht. +
`; diff --git a/tests/config-store.test.js b/tests/config-store.test.js index bf2f804..794cb14 100644 --- a/tests/config-store.test.js +++ b/tests/config-store.test.js @@ -112,6 +112,17 @@ describe('ConfigStore', () => { } }); + it('sizeMemoEnabled defaults to true for every hoster and persists when disabled', async () => { + const fresh = store.load(); + for (const name of ['doodstream.com', 'voe.sx', 'vidmoly.me', 'byse.sx', 'clouddrop.cc']) { + assert.equal(fresh.hosterSettings[name].sizeMemoEnabled, true, `${name} should default sizeMemoEnabled=true`); + } + await store.save({ hosterSettings: { 'byse.sx': { sizeMemoEnabled: false } } }); + const config = store.load(); + assert.equal(config.hosterSettings['byse.sx'].sizeMemoEnabled, false, 'explicit false preserved'); + assert.equal(config.hosterSettings['voe.sx'].sizeMemoEnabled, true, 'other hoster still defaults on'); + }); + it('logToFile=false persists and survives reload', async () => { await store.save({ hosterSettings: { 'voe.sx': { logToFile: false } } }); const config = store.load(); diff --git a/tests/suspect-reject-alternates.test.js b/tests/suspect-reject-alternates.test.js index d962566..dc95654 100644 --- a/tests/suspect-reject-alternates.test.js +++ b/tests/suspect-reject-alternates.test.js @@ -205,6 +205,33 @@ describe('suspect-reject alternate accounts', () => { assert.ok(rotEvents.includes('suspect-memo-skip'), 'the larger third file must skip its primary via the armed size memo'); }); + it('sizeMemoEnabled:false disables the pre-skip — the larger third file still gets a real attempt on its primary', async () => { + const mgr = poolMgr([ + { id: 'acc1', apiKey: 'key1' }, + { id: 'acc2', apiKey: 'key2' }, + { id: 'acc3', apiKey: 'key3' } + ], { parallelCount: 1, sizeMemoEnabled: false }); + mockUploadFile.mock.mockImplementation(async (hoster, file, apiKey) => { + if (apiKey === 'key1' || apiKey === 'key2') throw suspectErr(); + return { download_url: 'https://byse.sx/d/three', embed_url: null, file_code: 'three' }; + }); + const rotEvents = []; + mgr.on('rot-log', (e) => rotEvents.push(e.event)); + let summary = null; + mgr.on('batch-done', (s) => { summary = s; }); + + await mgr.startBatch([ + { file: '/test/a-1gb.mkv', hoster: 'byse.sx', apiKey: 'key1', accountId: 'acc1' }, + { file: '/test/b-1gb.mkv', hoster: 'byse.sx', apiKey: 'key1', accountId: 'acc1' }, + { file: '/test/c-2gb.mkv', hoster: 'byse.sx', apiKey: 'key1', accountId: 'acc1' } + ]); + + assert.equal(summary.succeeded, 3); + const keys = mockUploadFile.mock.calls.map(c => c.arguments[2]); + assert.equal(keys.filter(k => k === 'key1').length, 3, 'with the memo off every file gets a real attempt on the primary — including the larger third'); + assert.ok(!rotEvents.includes('suspect-memo-skip'), 'the disabled memo must never short-circuit a primary'); + }); + it('plain fileRejected without suspect flag keeps the old fast-fail behavior', async () => { const mgr = poolMgr([ { id: 'acc1', apiKey: 'key1' },