✨ feat: import upload log to remove already-uploaded jobs from queue
New 'Log importieren' button in queue actions. Opens file picker for .log/.txt files, parses the fileuploader.log format: date|hoster|link||filename| Matches each log entry against queue jobs by filename+hoster (case- insensitive). Removes matching jobs that are already uploaded, shows toast with count. Use case: after a crash/restart, import the log from a previous session to skip files that were already successfully uploaded. Co-Authored-By: Claude Opus 4.6 (1M context) <noreply@anthropic.com>
This commit is contained in:
parent
ad9299e74c
commit
e07db0532a
26
main.js
26
main.js
@ -845,6 +845,32 @@ ipcMain.handle('import-backup', async (_event, password) => {
|
||||
return { ok: true, config: configStore.load() };
|
||||
});
|
||||
|
||||
ipcMain.handle('import-upload-log', async () => {
|
||||
const { canceled, filePaths } = await dialog.showOpenDialog(mainWindow, {
|
||||
title: 'Upload-Log importieren',
|
||||
filters: [
|
||||
{ name: 'Log-Dateien', extensions: ['log', 'txt'] },
|
||||
{ name: 'Alle Dateien', extensions: ['*'] }
|
||||
],
|
||||
properties: ['openFile']
|
||||
});
|
||||
if (canceled || !filePaths.length) return { canceled: true };
|
||||
const content = fs.readFileSync(filePaths[0], 'utf-8');
|
||||
// Parse log format: date|hoster|link||filename|
|
||||
const entries = [];
|
||||
for (const line of content.split('\n')) {
|
||||
const trimmed = line.trim();
|
||||
if (!trimmed || trimmed.startsWith('#')) continue;
|
||||
const parts = trimmed.split('|');
|
||||
if (parts.length >= 5) {
|
||||
const hoster = (parts[1] || '').trim();
|
||||
const fileName = (parts[4] || '').trim();
|
||||
if (hoster && fileName) entries.push({ hoster, fileName });
|
||||
}
|
||||
}
|
||||
return { entries, path: filePaths[0] };
|
||||
});
|
||||
|
||||
ipcMain.handle('copy-to-clipboard', (_event, text) => {
|
||||
clipboard.writeText(text);
|
||||
return true;
|
||||
|
||||
@ -38,6 +38,9 @@ contextBridge.exposeInMainWorld('api', {
|
||||
finishAfterActive: () => ipcRenderer.invoke('finish-after-active'),
|
||||
runHealthCheck: (payload) => ipcRenderer.invoke('run-health-check', payload),
|
||||
|
||||
// Log import
|
||||
importUploadLog: () => ipcRenderer.invoke('import-upload-log'),
|
||||
|
||||
// Clipboard
|
||||
copyToClipboard: (text) => ipcRenderer.invoke('copy-to-clipboard', text),
|
||||
|
||||
|
||||
@ -3098,6 +3098,7 @@ function setupListeners() {
|
||||
queueJobs.forEach(j => { if (j.status === 'error') selectedJobIds.add(j.id); });
|
||||
retrySelectedJobs();
|
||||
});
|
||||
document.getElementById('importLogBtn').addEventListener('click', importUploadLog);
|
||||
document.getElementById('confirmHosterModalBtn').addEventListener('click', applyHosterSelection);
|
||||
document.getElementById('cancelHosterModalBtn').addEventListener('click', cancelHosterModal);
|
||||
document.getElementById('closeHosterModalBtn').addEventListener('click', cancelHosterModal);
|
||||
@ -3280,6 +3281,47 @@ function handleShutdownCountdown(data) {
|
||||
}, 1000);
|
||||
}
|
||||
|
||||
// --- Log import: remove already-uploaded file+hoster combos from queue ---
|
||||
async function importUploadLog() {
|
||||
const result = await window.api.importUploadLog();
|
||||
if (!result || result.canceled) return;
|
||||
const entries = result.entries || [];
|
||||
if (entries.length === 0) {
|
||||
showCopyToast('Keine Einträge im Log gefunden');
|
||||
return;
|
||||
}
|
||||
|
||||
// Build lookup Set: "filename_lower|hoster"
|
||||
const logKeys = new Set();
|
||||
for (const entry of entries) {
|
||||
logKeys.add(`${entry.fileName.toLowerCase()}|${entry.hoster.toLowerCase()}`);
|
||||
}
|
||||
|
||||
// Find queue jobs that match (already uploaded)
|
||||
let removed = 0;
|
||||
queueJobs = queueJobs.filter(job => {
|
||||
const key = `${job.fileName.toLowerCase()}|${job.hoster.toLowerCase()}`;
|
||||
if (logKeys.has(key) && job.status !== 'done') {
|
||||
removeJobFromIndex(job);
|
||||
removed++;
|
||||
return false;
|
||||
}
|
||||
return true;
|
||||
});
|
||||
|
||||
if (removed > 0) {
|
||||
selectedJobIds.clear();
|
||||
syncSelectedFilesFromQueue();
|
||||
rebuildJobIndex();
|
||||
renderQueueTable();
|
||||
updateUploadView();
|
||||
updateStatusBar();
|
||||
persistQueueStateSoon(true);
|
||||
}
|
||||
|
||||
showCopyToast(`${removed} bereits hochgeladene Jobs aus Queue entfernt (${entries.length} Log-Einträge gelesen)`);
|
||||
}
|
||||
|
||||
// --- Link operations ---
|
||||
function copyAllLinks() {
|
||||
const links = queueJobs
|
||||
|
||||
@ -94,6 +94,7 @@
|
||||
<div class="queue-actions" id="queueActions" style="display:none">
|
||||
<button class="btn btn-xs btn-primary" id="copyAllLinksBtn">Alle Links kopieren</button>
|
||||
<button class="btn btn-xs btn-secondary" id="retryFailedBtn" style="display:none">Fehlgeschlagene erneut</button>
|
||||
<button class="btn btn-xs btn-secondary" id="importLogBtn" title="Log importieren — bereits hochgeladene aus Queue entfernen">Log importieren</button>
|
||||
</div>
|
||||
|
||||
<div class="resize-handle" id="recentFilesResizer"></div>
|
||||
|
||||
Loading…
Reference in New Issue
Block a user