fix(x-bot): 만료되는 트위터 카드 이미지를 원본 OG 이미지로 대체

Nitter가 주는 pbs.twimg.com/card_img 이미지는 시간이 지나면 404로
만료됨. resolveCard에서 카드 이미지가 없거나 해당 만료성 URL이면
원본 URL의 OG 이미지(i.ytimg 등 안정적)로 대체.

Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
caadiq 2026-06-07 09:30:59 +09:00
parent 134f5836b7
commit 0b730405a6

View file

@ -59,22 +59,27 @@ async function xBotPlugin(fastify, opts) {
*/ */
async function resolveCard(tweet) { async function resolveCard(tweet) {
const nitter = tweet.card && (tweet.card.title || tweet.card.image) ? tweet.card : null; const nitter = tweet.card && (tweet.card.title || tweet.card.image) ? tweet.card : null;
// Nitter 카드에 이미지가 있으면 그대로 사용
if (nitter && nitter.image) return nitter;
// 이미지가 없으면 OG로 보강 (YouTube 등 Nitter가 카드 이미지를 안 주는 경우 복구) // pbs.twimg.com/card_img 이미지는 시간이 지나면 만료(404)되므로 안정적인 원본 OG 이미지로 대체.
const url = (nitter && nitter.url) || extractFirstUrl(tweet.text); // 이미지가 없거나 만료성 트위터 카드 이미지면 OG 보강 시도.
if (url) { const isEphemeral = nitter?.image && /pbs\.twimg\.com\/card_img\//.test(nitter.image);
try { const needsImage = !nitter || !nitter.image || isEphemeral;
const og = await fetchOgCard(url);
if (og) { if (needsImage) {
// Nitter 카드가 있으면 제목/설명은 유지하되 OG 이미지로 보강 const url = (nitter && nitter.url) || extractFirstUrl(tweet.text);
return nitter if (url) {
? { ...nitter, image: og.image || null, description: nitter.description || og.description } try {
: og; const og = await fetchOgCard(url);
if (og && og.image) {
return nitter
? { ...nitter, image: og.image, description: nitter.description || og.description }
: og;
}
// OG 이미지가 없고 Nitter 카드도 없으면 OG 카드라도 반환
if (og && !nitter) return og;
} catch {
// noop
} }
} catch {
// noop
} }
} }
return nitter; return nitter;