Resolve external embed previews and keep their real MIME types

This commit is contained in:
Fisto
2026-09-16 12:52:44 +02:00
parent 7fa6118b6f
commit 1b5fcfed2f
11 changed files with 313 additions and 41 deletions
+25 -4
View File
@@ -13,6 +13,7 @@ import {
videoPoster,
type DownloadOptions
} from "./download.js";
import { resolveEmbedPreview } from "./embed-preview.js";
import {
createScrapeDirs,
listScrapes,
@@ -358,18 +359,38 @@ export class ScrapeEngine {
return;
}
const outcome = await downloadPreview(row, join(dir, "thumbs"), options);
// Some providers (fxtwitter, vxReddit, ...) ship no thumbnail in Discord's data;
// resolve one from the provider or the page before caching it.
let previewRow = row;
if (row.source === "embed" && !row.preview_url) {
const resolved = await resolveEmbedPreview(row, options);
if (!resolved) {
store.markPreviewError(row.id, "no preview source");
this.persist(dir, meta);
await this.sleep(downloadGapMs(options));
continue;
}
previewRow = { ...row, preview_url: resolved };
}
const outcome = await downloadPreview(previewRow, join(dir, "thumbs"), options);
if (outcome.state === "downloaded" && outcome.hash) {
store.markPreview(row.id, { hash: outcome.hash, bytes: outcome.bytes ?? 0 });
const ext = outcome.ext ?? "webp";
store.markPreview(row.id, { hash: outcome.hash, bytes: outcome.bytes ?? 0, ext });
meta.previewed = (meta.previewed ?? 0) + 1;
// Embed thumbnails also land in the custom destination, so the download has a
// viewable poster for embeds while the media tab keeps its local copy.
if (options.destinationDir && row.source === "embed") {
const target = join(options.destinationDir, meta.id, "thumbnails", `${outcome.hash}.webp`);
const target = join(
options.destinationDir,
meta.id,
"thumbnails",
`${outcome.hash}.${ext}`
);
mkdirSync(dirname(target), { recursive: true });
copyFileSync(join(dir, "thumbs", `${outcome.hash}.webp`), target);
copyFileSync(join(dir, "thumbs", `${outcome.hash}.${ext}`), target);
}
} else {
store.markPreviewError(row.id, outcome.error ?? outcome.state);