download job: also write a reference sidecar for FAILED items
A failed download has no media file, so its description was lost — no way to tell which video was missed. Now a failure writes a `<title>.txt` (or `<videoId>.txt` when untitled) holding the URL + description, so every missed item leaves a recoverable reference. Always written (even with an empty description — the URL is the reference); skipped only on a deliberate Stop, not a genuine error. Verified: successful item → "<media base>.txt" (description); failed item → "<title>.txt" (url + description); spaces preserved in both. Co-Authored-By: Claude Opus 4.8 <noreply@anthropic.com>
This commit is contained in:
@@ -15,6 +15,26 @@ async function writeDescriptionSidecar(dir: string, mediaFilename: string, descr
|
||||
}
|
||||
}
|
||||
|
||||
const FS_ILLEGAL = /[/\\:*?"<>|\u0000-\u001f]/g;
|
||||
const safeName = (s: string) => s.replace(FS_ILLEGAL, '_').replace(/\s+/g, ' ').trim().slice(0, 180);
|
||||
|
||||
// On a FAILED download there's no media file to pair with — still drop a reference so the missed video is
|
||||
// recoverable: a `<title>.txt` (or `<videoId>.txt` when untitled) holding the URL + the description. Always
|
||||
// written (even with an empty description — the URL is the reference).
|
||||
async function writeMissedSidecar(
|
||||
dir: string,
|
||||
item: { url: string; title: string; description: string },
|
||||
): Promise<void> {
|
||||
const vid = item.url.match(/[?&]v=([\w-]+)/)?.[1];
|
||||
const name = safeName(item.title) || vid || 'missed';
|
||||
const content = [item.url, item.description.trim()].filter(Boolean).join('\n\n');
|
||||
try {
|
||||
await writeFile(join(dir, `${name}.txt`), content, 'utf8');
|
||||
} catch {
|
||||
/* best-effort */
|
||||
}
|
||||
}
|
||||
|
||||
// The download-job executor — pure scripting, no agent. Two phases:
|
||||
// 1. metadata — fetch each item's info (title + validity); keep the ones that resolve, skip the errors
|
||||
// (private / deleted / unavailable). The title is required: ReClip names the output file
|
||||
@@ -132,6 +152,7 @@ export async function executeDownload(params: ExecuteDownloadParams): Promise<vo
|
||||
} catch {
|
||||
checkAbort(); // an abort surfaces as a throw here — re-check so it stops instead of counting as a skip
|
||||
progress.dl.failed++;
|
||||
void writeMissedSidecar(absDir, item); // no media file — leave a reference to what we missed
|
||||
}
|
||||
emit();
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user