Files
antisocial/test/meta-media.test.ts
KydoimosandClaude Opus 5 fa07b43c1c Share the link-preview fallback between the Meta adapters
Instagram and Threads both ended with the same twelve lines: read the Open
Graph tags, make og:video a video with og:image as its poster, otherwise make
og:image an image, and attach the referrer headers the CDN wants. Facebook
needs the same floor for the same reason, and three copies of a thing is where
it stops being a coincidence.

meta-media.ts already exists because these platforms are one product
underneath. The media schema it normalizes is Instagram's and Threads';
Facebook's is its own, but the headers and the link preview are shared with
both, so that is where this goes.

Co-Authored-By: Claude Opus 5 <[email protected]>
2026-09-12 11:35:16 -03:00

95 lines
3.6 KiB
TypeScript

import assert from 'node:assert/strict';
import { test } from 'node:test';
import {
findCaption,
findMetaMedia,
mediaFromMetaNode,
mediaFromOpenGraph,
} from '../src/platforms/meta-media.ts';
import { fixture } from './helpers.ts';
const REFERER = 'https://www.threads.com/';
test('a Threads image post normalizes to one image with referrer headers', () => {
const node = fixture<Parameters<typeof mediaFromMetaNode>[0]>('threads/image.json');
const media = mediaFromMetaNode(node, REFERER);
assert.equal(media.length, 1);
assert.equal(media[0]?.kind, 'image');
assert.equal(media[0]?.fetchHeaders?.['Referer'], REFERER);
});
test('a second real Threads post normalizes the same way', () => {
// Two captures, so the walk is not quietly fitted to one payload.
const media = mediaFromMetaNode(fixture('threads/second.json'), REFERER);
assert.equal(media.length, 1);
assert.equal(media[0]?.kind, 'image');
});
test('the largest candidate wins', () => {
const media = mediaFromMetaNode(
{
image_versions2: {
candidates: [
{ url: 'https://cdn/small.jpg', width: 320, height: 320 },
{ url: 'https://cdn/large.jpg', width: 1440, height: 1440 },
],
},
},
REFERER,
);
assert.equal(media[0]?.url, 'https://cdn/large.jpg');
});
test('a carousel flattens to its children', () => {
const media = mediaFromMetaNode(
{
carousel_media: [
{ image_versions2: { candidates: [{ url: 'https://cdn/1.jpg', width: 100 }] } },
{
image_versions2: { candidates: [{ url: 'https://cdn/poster.jpg', width: 100 }] },
video_versions: [{ url: 'https://cdn/2.mp4', width: 720 }],
},
],
},
REFERER,
);
assert.deepEqual(media.map((m) => m.kind), ['image', 'video']);
});
test('the media node is found however deeply it is buried', () => {
const real = { image_versions2: { candidates: [{ url: 'https://cdn/i.jpg', width: 100 }] }, tag: 'me' };
const found = findMetaMedia({ a: [{ b: { c: real } }] });
assert.equal((found as { tag?: string })?.tag, 'me');
});
test('a stub node with no candidates is not mistaken for the post', () => {
// These payloads are full of empty placeholders; picking one used to make
// a real post look like it had no media at all.
assert.equal(findMetaMedia({ image_versions2: { candidates: [] }, carousel_media: null }), undefined);
});
test('the caption is found the same way, and an empty one is not a caption', () => {
assert.equal(findCaption({ x: { caption: { text: 'hello' } } }), 'hello');
assert.equal(findCaption({ x: { caption: { text: '' } } }), undefined);
assert.equal(findCaption({ x: { caption: null } }), undefined);
});
test('the link preview stands in for the post when there is nothing better', () => {
const image = mediaFromOpenGraph({ 'og:image': 'https://image.example/a.jpg' }, REFERER);
assert.deepEqual(image.map((item) => [item.kind, item.url]), [['image', 'https://image.example/a.jpg']]);
assert.equal(image[0]?.fetchHeaders?.['Referer'], REFERER);
});
test('a preview naming a video is a video, and its image is the poster', () => {
const media = mediaFromOpenGraph(
{ 'og:video': 'https://video.example/a.mp4', 'og:image': 'https://image.example/a.jpg' },
REFERER,
);
assert.equal(media[0]?.kind, 'video');
assert.equal(media[0]?.kind === 'video' ? media[0].poster?.url : undefined, 'https://image.example/a.jpg');
});
test('a page with no preview at all yields no media rather than an empty asset', () => {
assert.deepEqual(mediaFromOpenGraph({ 'og:title': 'just a title' }, REFERER), []);
});