Resolve external embed previews and keep their real MIME types
This commit is contained in:
@@ -10,6 +10,7 @@ import { existsSync, mkdirSync, mkdtempSync, rmSync } from "node:fs";
|
||||
import { tmpdir } from "node:os";
|
||||
import { join } from "node:path";
|
||||
import { downloadOne, downloadPreview, previewUrlFor, videoPoster } from "../src/download.js";
|
||||
import { ogImageFromHtml, resolveEmbedPreview } from "../src/embed-preview.js";
|
||||
import { ScrapeEngine, type FetchPage, type ScrapeBackend } from "../src/engine.js";
|
||||
import { extractMedia } from "../src/extract.js";
|
||||
import { PuppetBackend } from "../src/puppet-backend.js";
|
||||
@@ -549,6 +550,17 @@ void (async () => {
|
||||
assert.equal(outcome.state, "downloaded");
|
||||
assert.equal(outcome.path, `${outcome.hash}.webp`);
|
||||
assert.equal(existsSync(join(dir, `${outcome.hash}.webp`)), true);
|
||||
|
||||
const jpeg = await downloadPreview(
|
||||
{ id: 10, url: "https://cdn.discordapp.com/attachments/1/2/pic.png", kind: "image", source: "attachment", preview_url: null },
|
||||
dir,
|
||||
{
|
||||
fetchImpl: async () =>
|
||||
new Response("jpeg-bytes", { status: 200, headers: { "content-type": "image/jpeg" } })
|
||||
}
|
||||
);
|
||||
assert.equal(jpeg.path, `${jpeg.hash}.jpg`);
|
||||
assert.equal(existsSync(join(dir, `${jpeg.hash}.jpg`)), true);
|
||||
});
|
||||
|
||||
await test("embed thumbnails download only when enabled", async () => {
|
||||
@@ -635,6 +647,7 @@ void (async () => {
|
||||
const row = store.queryMedia({ kind: "image" })[0];
|
||||
assert.ok(row.preview_hash);
|
||||
assert.ok((row.preview_bytes ?? 0) > 0);
|
||||
assert.equal(row.preview_ext, "webp");
|
||||
store.close();
|
||||
assert.equal(existsSync(join(root, started.id, "thumbs", `${row.preview_hash}.webp`)), true);
|
||||
});
|
||||
@@ -704,14 +717,82 @@ void (async () => {
|
||||
|
||||
const embed = store.queryMedia({ kind: "video" })[0];
|
||||
assert.ok(embed.preview_hash);
|
||||
assert.equal(
|
||||
existsSync(join(dest, started.id, "thumbnails", `${embed.preview_hash}.webp`)),
|
||||
true
|
||||
);
|
||||
assert.equal(existsSync(join(root, started.id, "thumbs", `${embed.preview_hash}.webp`)), true);
|
||||
const previewFile = `${embed.preview_hash}.${embed.preview_ext ?? "webp"}`;
|
||||
assert.equal(existsSync(join(dest, started.id, "thumbnails", previewFile)), true);
|
||||
assert.equal(existsSync(join(root, started.id, "thumbs", previewFile)), true);
|
||||
store.close();
|
||||
});
|
||||
|
||||
await test("embed previews resolve from providers and og:image", async () => {
|
||||
const fetchImpl = async (input: any) => {
|
||||
const url = String(input);
|
||||
if (url.includes("youtube.com/oembed")) {
|
||||
return new Response(JSON.stringify({ thumbnail_url: "https://i.ytimg.com/ok.jpg" }), {
|
||||
status: 200
|
||||
});
|
||||
}
|
||||
if (url.includes("api.fxtwitter.com")) {
|
||||
return new Response(
|
||||
JSON.stringify({ tweet: { media: { videos: [{ thumbnail_url: "https://pbs.twimg.com/ok.jpg" }] } } }),
|
||||
{ status: 200 }
|
||||
);
|
||||
}
|
||||
if (url.includes("vxreddit.com")) {
|
||||
return new Response(
|
||||
'<html><head><meta property="og:image" content="https://i.redd.it/ok.jpg"></head></html>',
|
||||
{ status: 200 }
|
||||
);
|
||||
}
|
||||
return new Response("no", { status: 404 });
|
||||
};
|
||||
|
||||
assert.equal(
|
||||
await resolveEmbedPreview(
|
||||
{ url: "https://youtu.be/abc", source: "embed", preview_url: null },
|
||||
{ fetchImpl }
|
||||
),
|
||||
"https://i.ytimg.com/ok.jpg"
|
||||
);
|
||||
assert.equal(
|
||||
await resolveEmbedPreview(
|
||||
{ url: "https://fxtwitter.com/u/status/12345", source: "embed", preview_url: null },
|
||||
{ fetchImpl }
|
||||
),
|
||||
"https://pbs.twimg.com/ok.jpg"
|
||||
);
|
||||
assert.equal(
|
||||
await resolveEmbedPreview(
|
||||
{ url: "https://vxreddit.com/r/x/comments/1", source: "embed", preview_url: null },
|
||||
{ fetchImpl }
|
||||
),
|
||||
"https://i.redd.it/ok.jpg"
|
||||
);
|
||||
assert.equal(
|
||||
await resolveEmbedPreview(
|
||||
{ url: "https://x.com/u/status/1", source: "embed", preview_url: "https://stored/ok.jpg" },
|
||||
{ fetchImpl }
|
||||
),
|
||||
"https://stored/ok.jpg"
|
||||
);
|
||||
assert.equal(
|
||||
await resolveEmbedPreview(
|
||||
{ url: "https://cdn.discordapp.com/x.png", source: "attachment", preview_url: null },
|
||||
{ fetchImpl }
|
||||
),
|
||||
null
|
||||
);
|
||||
|
||||
assert.equal(
|
||||
ogImageFromHtml('<meta content="https://a/1.jpg" property="og:image">'),
|
||||
"https://a/1.jpg"
|
||||
);
|
||||
assert.equal(
|
||||
ogImageFromHtml('<meta name="twitter:image" content="https://a/2.jpg">'),
|
||||
"https://a/2.jpg"
|
||||
);
|
||||
assert.equal(ogImageFromHtml("<html></html>"), null);
|
||||
});
|
||||
|
||||
await test("videoPoster extracts a cached frame", async () => {
|
||||
const dir = join(root, "poster-test");
|
||||
mkdirSync(dir, { recursive: true });
|
||||
|
||||
Reference in New Issue
Block a user