From 13ff41aa9571741051afbbd8fd8b5148fa1b494f Mon Sep 17 00:00:00 2001 From: Sucukdeluxe Date: Mon, 2 Mar 2026 10:40:28 +0100 Subject: [PATCH] Add item-recovery for stuck downloads with completed files on disk When post-processing runs, detect items in idle states (queued/paused) whose target file already exists on disk with non-zero size, and auto-recover them to "completed" status. This ensures allDone becomes true, triggering final extraction with archive cleanup (delete mode). Co-Authored-By: Claude Opus 4.6 --- package.json | 2 +- src/main/download-manager.ts | 30 ++++++++++++++++++++++++++++++ 2 files changed, 31 insertions(+), 1 deletion(-) diff --git a/package.json b/package.json index eb44e7a..14724c7 100644 --- a/package.json +++ b/package.json @@ -1,6 +1,6 @@ { "name": "real-debrid-downloader", - "version": "1.4.77", + "version": "1.4.78", "description": "Real-Debrid Downloader Desktop (Electron + React + TypeScript)", "main": "build/main/main/main.js", "author": "Sucukdeluxe", diff --git a/src/main/download-manager.ts b/src/main/download-manager.ts index 53a2c4f..67165db 100644 --- a/src/main/download-manager.ts +++ b/src/main/download-manager.ts @@ -4720,6 +4720,36 @@ export class DownloadManager extends EventEmitter { return; } const items = pkg.itemIds.map((id) => this.session.items[id]).filter(Boolean) as DownloadItem[]; + + // Recover items whose file exists on disk but status was never set to "completed". + // Only recover items in idle states (queued/paused), never active ones (downloading/validating). + for (const item of items) { + if (isFinishedStatus(item.status)) { + continue; + } + if (item.status === "downloading" || item.status === "validating" || item.status === "integrity_check") { + continue; + } + if (!item.targetPath) { + continue; + } + try { + const stat = fs.statSync(item.targetPath); + if (stat.size > 0) { + logger.info(`Item-Recovery: ${item.fileName} war "${item.status}" aber Datei existiert (${humanSize(stat.size)}), setze auf completed`); + item.status = "completed"; + item.fullStatus = this.settings.autoExtract ? "Entpacken - Ausstehend" : `Fertig (${humanSize(stat.size)})`; + item.downloadedBytes = stat.size; + item.progressPercent = 100; + item.speedBps = 0; + item.updatedAt = nowMs(); + this.recordRunOutcome(item.id, "completed"); + } + } catch { + // file doesn't exist, nothing to recover + } + } + const success = items.filter((item) => item.status === "completed").length; const failed = items.filter((item) => item.status === "failed").length; const cancelled = items.filter((item) => item.status === "cancelled").length;