Compare commits

..

No commits in common. "b7336eefb8d21d8555afe8d39a9818fbd4c375cd" and "796aeb520dedda932b3c4740911561b431837f2e" have entirely different histories.

5 changed files with 5 additions and 76 deletions

View File

@ -56,34 +56,6 @@ class UploadManager extends EventEmitter {
this.emit('rot-log', { ts: Date.now(), event, ...data });
}
// Error classes that mean "this account is the problem, retrying on it won't
// help" — we skip the remaining retries and go straight to the fallback
// account. Keeps single runs fast when an account is rate-limited, banned,
// or out of quota. Transient network issues still go through the normal
// retry loop on the same account.
_shouldSkipRetryOnAccountError(err) {
if (!err || !err.message) return false;
const m = String(err.message);
const PATTERNS = [
/Kein Upload-Server/i,
/No upload server/i,
/kein server/i,
/quota/i,
/limit (reached|exceeded|überschritten)/i,
/rate[- ]?limit/i,
/too many requests/i,
/\b(401|403)\b/,
/Falscher (User|Username|Passwort)/i,
/Incorrect (Login|Password)/i,
/invalid (credentials|api[- ]?key|token|session)/i,
/(account|user) (banned|suspended|disabled|gesperrt)/i,
/not authorized/i,
/forbidden/i,
/session (expired|abgelaufen)/i
];
return PATTERNS.some(p => p.test(m));
}
updateSettings(hosterSettings, globalSettings) {
this.hosterSettings = hosterSettings || this.hosterSettings;
this.globalSettings = globalSettings || this.globalSettings;
@ -497,15 +469,6 @@ class UploadManager extends EventEmitter {
}
lastError = err;
// Account-specific errors — don't waste retries on the same account,
// jump straight to rotation.
if (this._shouldSkipRetryOnAccountError(err)) {
this._rotLog('fast-fail', {
hoster: task.hoster, fileName, accountId: task.accountId,
attempt, error: err && err.message ? err.message : String(err)
});
break;
}
if (attempt >= maxAttempts) break;
// Wait 3 seconds before retry
await this._sleep(3000, signal);

39
main.js
View File

@ -108,24 +108,12 @@ function rotLog(msg, ts) {
try {
const iso = new Date(ts || Date.now()).toISOString();
const line = `[${iso}] ${msg}\n`;
// Write synchronously. Rotation events are rare (a handful per batch) so
// the batching optimization from debugLog doesn't buy us anything, and
// syncing guarantees the user can refresh the file and see fresh entries
// without waiting on a flush timer.
const candidates = [
getRotLogPath(),
path.join(app.getPath('desktop') || app.getPath('userData'), 'account-rotation.log'),
path.join(app.getPath('userData'), 'account-rotation.log')
];
for (const target of candidates) {
try {
fs.mkdirSync(path.dirname(target), { recursive: true });
fs.appendFileSync(target, line, 'utf-8');
break;
} catch {}
}
_rotLogBuffer.push(line);
// Mirror into the main debug log for single-file-grep convenience.
_debugLogBuffer.push(`[${iso}] [ROT] ${msg}\n`);
if (!_rotLogFlushTimer) {
_rotLogFlushTimer = setTimeout(() => { _rotLogFlushTimer = null; _flushRotLog(); }, 500);
}
if (!_debugLogFlushTimer) {
_debugLogFlushTimer = setTimeout(() => { _debugLogFlushTimer = null; _flushDebugLog(); }, 500);
}
@ -1201,25 +1189,6 @@ ipcMain.handle('finish-after-active', () => {
return true;
});
ipcMain.handle('open-log-folder', async () => {
// Reveal the active log file (or its directory) in the OS file manager.
// Prefers the configured log path, then the rotation log, then just the
// parent dir.
const { shell } = require('electron');
const primary = getLogFilePath();
if (fs.existsSync(primary)) { shell.showItemInFolder(primary); return { ok: true, path: primary }; }
const rot = getRotLogPath();
if (fs.existsSync(rot)) { shell.showItemInFolder(rot); return { ok: true, path: rot }; }
try {
const dir = path.dirname(primary);
fs.mkdirSync(dir, { recursive: true });
shell.openPath(dir);
return { ok: true, path: dir };
} catch (err) {
return { ok: false, error: err.message };
}
});
ipcMain.handle('clear-history', async () => {
await configStore.clearHistory();
return true;

View File

@ -1,6 +1,6 @@
{
"name": "multi-hoster-uploader",
"version": "3.0.4",
"version": "3.0.3",
"description": "Upload files to doodstream, voe, vidmoly, byse simultaneously",
"main": "main.js",
"scripts": {

View File

@ -107,7 +107,6 @@ contextBridge.exposeInMainWorld('api', {
onAccountRotationLog: (callback) => {
ipcRenderer.on('account-rotation-log', (_event, data) => callback(data));
},
openLogFolder: () => ipcRenderer.invoke('open-log-folder'),
// Remote Control
remoteGetSettings: () => ipcRenderer.invoke('remote:get-settings'),
remoteSaveSettings: (settings) => ipcRenderer.invoke('remote:save-settings', settings),

View File

@ -2291,7 +2291,6 @@ function renderSettings() {
<label>FileUploader Log</label>
<input type="text" class="key-input settings-autosave" id="logFilePathInput" value="${escapeAttr(globalSettings.logFilePath || '')}" placeholder="Standardpfad verwenden">
<button class="btn btn-xs btn-secondary" id="chooseLogFilePathBtn">Ordner wählen</button>
<button class="btn btn-xs btn-secondary" id="openLogFolderBtn" title="Log-Ordner im Explorer öffnen">Öffnen</button>
</div>
<div class="settings-row">
<label>Neues Log pro Tag</label>
@ -2585,7 +2584,6 @@ function renderSettings() {
}
document.getElementById('chooseLogFilePathBtn')?.addEventListener('click', chooseLogFilePath);
document.getElementById('openLogFolderBtn')?.addEventListener('click', () => window.api.openLogFolder());
document.getElementById('manualUpdateCheckBtn')?.addEventListener('click', async (e) => {
const btn = e.target;
btn.disabled = true;