diff --git a/backend/nsfwapp.exe b/backend/nsfwapp.exe index 76429d0..427d53c 100644 Binary files a/backend/nsfwapp.exe and b/backend/nsfwapp.exe differ diff --git a/backend/recorder.go b/backend/recorder.go index 7bb31eb..6799271 100644 --- a/backend/recorder.go +++ b/backend/recorder.go @@ -451,23 +451,56 @@ func runJob(ctx context.Context, job *RecordJob, req RecordRequest) { return } - // pre-queue auto delete (small) + // ✅ harte Schranke: leere / ungültige Output-Dateien nie in den Postwork schicken { - s := getSettings() - minMB := s.AutoDeleteSmallDownloadsBelowMB - if s.AutoDeleteSmallDownloads && minMB > 0 { - threshold := int64(minMB) * 1024 * 1024 - if fi, serr := os.Stat(out); serr == nil && fi != nil && !fi.IsDir() { - jobsMu.Lock() - job.SizeBytes = fi.Size() - jobsMu.Unlock() - notifyJobsChanged() + fi, serr := os.Stat(out) + if serr != nil || fi == nil || fi.IsDir() || fi.Size() <= 0 { + _ = removeWithRetry(out) + purgeDurationCacheForPath(out) + + jobsMu.Lock() + delete(jobs, job.ID) + jobsMu.Unlock() + + notifyJobsChanged() + notifyDoneChanged() + + if shouldLogRecordInfo(req) { + if serr != nil { + fmt.Println("🧹 removed invalid output before postwork:", filepath.Base(out), "(stat error:", serr, ")") + } else if fi == nil || fi.IsDir() { + fmt.Println("🧹 removed invalid output before postwork:", filepath.Base(out), "(not a regular file)") + } else { + fmt.Println("🧹 removed empty output before postwork:", filepath.Base(out), "(0 bytes)") + } + } + return + } + } + + // pre-queue gate: nur in die Nachbearbeitung, wenn Datei behalten werden soll + { + fi, serr := os.Stat(out) + if serr == nil && fi != nil && !fi.IsDir() { + jobsMu.Lock() + job.SizeBytes = fi.Size() + jobsMu.Unlock() + notifyJobsChanged() + + s := getSettings() + minMB := s.AutoDeleteSmallDownloadsBelowMB + + // ✅ Wenn AutoDelete aktiv ist und Datei unter Schwellwert liegt: + // NICHT in die Postwork-Queue aufnehmen, sondern direkt löschen + return. + if s.AutoDeleteSmallDownloads && minMB > 0 { + threshold := int64(minMB) * 1024 * 1024 if fi.Size() > 0 && fi.Size() < threshold { base := filepath.Base(out) id := stripHotPrefix(strings.TrimSuffix(base, filepath.Ext(base))) - if derr := removeWithRetry(out); derr == nil || os.IsNotExist(derr) { + derr := removeWithRetry(out) + if derr == nil || os.IsNotExist(derr) { removeGeneratedForID(id) purgeDurationCacheForPath(out) @@ -479,12 +512,12 @@ func runJob(ctx context.Context, job *RecordJob, req RecordRequest) { notifyDoneChanged() if shouldLogRecordInfo(req) { - fmt.Println("🧹 auto-deleted (pre-queue):", base, "(size: "+formatBytesSI(fi.Size())+")") + fmt.Println("🧹 auto-deleted before enqueue:", base, "(size: "+formatBytesSI(fi.Size())+", threshold: "+formatBytesSI(threshold)+")") } return - } else { - fmt.Println("⚠️ auto-delete (pre-queue) failed:", derr) } + + fmt.Println("⚠️ auto-delete before enqueue failed:", derr) } } } @@ -556,6 +589,34 @@ func runJob(ctx context.Context, job *RecordJob, req RecordRequest) { // 2) Move to done setPhase("moving", 78) + + // ✅ auch nach Remux nochmal hart prüfen: keine 0-Byte-Dateien nach done verschieben + { + fi, serr := os.Stat(out) + if serr != nil || fi == nil || fi.IsDir() || fi.Size() <= 0 { + _ = removeWithRetry(out) + purgeDurationCacheForPath(out) + + jobsMu.Lock() + delete(jobs, job.ID) + jobsMu.Unlock() + + notifyJobsChanged() + notifyDoneChanged() + + if shouldLogRecordInfo(req) { + if serr != nil { + fmt.Println("🧹 removed invalid post-remux output:", filepath.Base(out), "(stat error:", serr, ")") + } else if fi == nil || fi.IsDir() { + fmt.Println("🧹 removed invalid post-remux output:", filepath.Base(out), "(not a regular file)") + } else { + fmt.Println("🧹 removed empty post-remux output:", filepath.Base(out), "(0 bytes)") + } + } + return nil + } + } + if moved, err2 := moveToDoneDir(out); err2 == nil && strings.TrimSpace(moved) != "" { out = strings.TrimSpace(moved) jobsMu.Lock()