diff --git a/docs/package-lock.json b/docs/package-lock.json index 7e795330..ece246b9 100644 --- a/docs/package-lock.json +++ b/docs/package-lock.json @@ -8,7 +8,7 @@ "name": "fxembed-docs", "version": "1.0.0", "dependencies": { - "@astrojs/starlight": "^0.42.1", + "@astrojs/starlight": "^0.42.2", "astro": "^7.3.3", "starlight-openapi": "^0.26.2" } @@ -293,9 +293,9 @@ } }, "node_modules/@astrojs/starlight": { - "version": "0.42.1", - "resolved": "https://registry.npmjs.org/@astrojs/starlight/-/starlight-0.42.1.tgz", - "integrity": "sha512-ABS/A0IfbJeMbuhCKVkrAcO3EWxhpeLveFuL28+7+BQje7ZHa9OXZbUoiLXdYUhH7XFaiAQjAg44RiF2uuZPJw==", + "version": "0.42.2", + "resolved": "https://registry.npmjs.org/@astrojs/starlight/-/starlight-0.42.2.tgz", + "integrity": "sha512-rDAgv3QCJOo0F4EoWeuFG31OdhQOrcipATl9+gCkOqpQiO7u7FR8uVam+HHNJO8Sl21TOAQKUSUEvCXv8jEgJA==", "license": "MIT", "dependencies": { "@astrojs/markdown-satteri": "^0.4.0", diff --git a/docs/package.json b/docs/package.json index 8cda4fc3..dd772a16 100644 --- a/docs/package.json +++ b/docs/package.json @@ -14,7 +14,7 @@ "sanitize-openapi": "node scripts/extract-openapi.mjs --sanitize" }, "dependencies": { - "@astrojs/starlight": "^0.42.1", + "@astrojs/starlight": "^0.42.2", "astro": "^7.3.3", "starlight-openapi": "^0.26.2" } diff --git a/package-lock.json b/package-lock.json index 217b5206..2b58de50 100644 --- a/package-lock.json +++ b/package-lock.json @@ -22,10 +22,10 @@ "zod": "^4.6.5" }, "devDependencies": { - "@aws-sdk/client-s3": "^3.1135.0", - "@aws-sdk/s3-request-presigner": "^3.1135.0", + "@aws-sdk/client-s3": "^3.1136.0", + "@aws-sdk/s3-request-presigner": "^3.1136.0", "@cloudflare/vitest-pool-workers": "^0.22.0", - "@cloudflare/workers-types": "^5.20260915.1", + "@cloudflare/workers-types": "^5.20260919.1", "@eslint/js": "^10.0.1", "@microsoft/eslint-formatter-sarif": "^3.1.0", "@sentry/esbuild-plugin": "^5.4.0", @@ -38,13 +38,13 @@ "eslint-plugin-optimize-regex": "^1.2.1", "eslint-plugin-prettier": "^5.5.6", "globals": "^17.12.0", - "prettier": "^3.9.7", + "prettier": "^3.9.8", "ts-loader": "^9.6.2", "tsx": "^4.23.13", "typescript": "^6.0.3", "typescript-eslint": "^8.70.0", "vitest": "^4.1.11", - "wrangler": "^4.131.2" + "wrangler": "^4.135.0" } }, "node_modules/@asteasolutions/zod-to-openapi": { @@ -77,9 +77,9 @@ } }, "node_modules/@aws-sdk/client-s3": { - "version": "3.1135.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.1135.0.tgz", - "integrity": "sha512-/1CVA0M+TaEOzgM02DUST1NzQTjbY8OumDKPETjzo4owypkZZMxu1ADecFbzeG73hje/XLNAJfGepQ3a40CGnw==", + "version": "3.1136.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/client-s3/-/client-s3-3.1136.0.tgz", + "integrity": "sha512-1FUvu6nuUi3y9VjQAYootkfWKQqZ8aT8wZoV5I0bpeMkGVgntYpJ11xLicGotGE6E1qtLXB+GdOJM9B+OQYWDA==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -314,9 +314,9 @@ } }, "node_modules/@aws-sdk/s3-request-presigner": { - "version": "3.1135.0", - "resolved": "https://registry.npmjs.org/@aws-sdk/s3-request-presigner/-/s3-request-presigner-3.1135.0.tgz", - "integrity": "sha512-e8fkfFrsROsL2xa4X2Elui7SApBSb+vsJ0XlVdifv7MPOuwPzQ0oQsC1/BQxT1/Hx3IuOVdT0EF9dU87aKse8A==", + "version": "3.1136.0", + "resolved": "https://registry.npmjs.org/@aws-sdk/s3-request-presigner/-/s3-request-presigner-3.1136.0.tgz", + "integrity": "sha512-SYH0+Eg8+4Tb03s3rfpNVtWEtgqmSf9LCieuCam/hk9bTib72uTjVz5dENCIkRkw3baq1QsePmjiN7IRyqHcnQ==", "dev": true, "license": "Apache-2.0", "dependencies": { @@ -881,9 +881,9 @@ } }, "node_modules/@cloudflare/workers-types": { - "version": "5.20260915.1", - "resolved": "https://registry.npmjs.org/@cloudflare/workers-types/-/workers-types-5.20260915.1.tgz", - "integrity": "sha512-3Lw2wkyVcEDdD0W6rNBmannaAkUsWGsO5TjbyHflWIDlhxtFRDFnxqHoDlg4YiVxinsIcBl1j9jW1kdruUhZpg==", + "version": "5.20260919.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workers-types/-/workers-types-5.20260919.1.tgz", + "integrity": "sha512-xUdKJoTHhNcXwnBrfrM1STkzm3oSUc9cRVzP8fO5NyJZ/UtnDnWZHDk9z8IkTnbC2WRWFAS87HICmqZhbHDvQw==", "dev": true, "license": "MIT OR Apache-2.0" }, @@ -3347,9 +3347,9 @@ "license": "MIT" }, "node_modules/@types/node": { - "version": "26.6.1", - "resolved": "https://registry.npmjs.org/@types/node/-/node-26.6.1.tgz", - "integrity": "sha512-VqGJBMCtdhqkBUCcBLvywI0NJ+KLuVzgNnlBUNFOQjqVxzo2lxLUNg1DSey8+u2u6ktswSAxg+s68QLzWHNOuA==", + "version": "26.6.2", + "resolved": "https://registry.npmjs.org/@types/node/-/node-26.6.2.tgz", + "integrity": "sha512-X1P21scMv4zGKLYqjdGjaKa7COa0RKVYYZZN/NfvLQ1JegxFhdhpZG/Lyn8AXx6CDUavKAd11v6BvfpkDByK8g==", "dev": true, "license": "MIT", "peer": true, @@ -6336,9 +6336,9 @@ } }, "node_modules/prettier": { - "version": "3.9.7", - "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.9.7.tgz", - "integrity": "sha512-T3mF5P7HFzZVLDQuCUNtJj6WK1pcpLMweMNUVwGb01bLNkH9AkKxtZvmInw8K6bnn2O3d6/5RHl6zSHiBAD0Og==", + "version": "3.9.8", + "resolved": "https://registry.npmjs.org/prettier/-/prettier-3.9.8.tgz", + "integrity": "sha512-WRFq3Wn3WId7LLROfMLdH7xaFr2jR62wU8nLO6rQUOLOxNZUviyJQs1M0iIhLexSFy+L+w0ch66wtoO2jRjG0A==", "dev": true, "license": "MIT", "bin": { @@ -7541,9 +7541,9 @@ } }, "node_modules/wrangler": { - "version": "4.131.2", - "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-4.131.2.tgz", - "integrity": "sha512-jmkGE7monbPKyYQr1FPQN+SARVhddqw2fhXOmTKCw4lroqlFGSS6rit/RTvPi/qzNLKrXxkS8DhWXasJnStplg==", + "version": "4.135.0", + "resolved": "https://registry.npmjs.org/wrangler/-/wrangler-4.135.0.tgz", + "integrity": "sha512-WrNBQSfIG6YcILJcodYr5ty8vgkzGsV8YX+kfd+uZ5/Bd8cUW0GnUIRKAVfn5kYKqh1m/BPcji9h1d7mE8euFw==", "dev": true, "license": "MIT OR Apache-2.0", "dependencies": { @@ -7551,10 +7551,10 @@ "@cloudflare/unenv-preset": "2.16.1", "blake3-wasm": "2.1.5", "esbuild": "0.28.1", - "miniflare": "5.20260911.1-alpha", + "miniflare": "5.20260918.0-alpha", "path-to-regexp": "6.3.0", "unenv": "2.0.0-rc.24", - "workerd": "1.20260911.1" + "workerd": "1.20260918.1" }, "bin": { "cf-wrangler": "bin/cf-wrangler.js", @@ -7568,7 +7568,7 @@ "fsevents": "2.3.3" }, "peerDependencies": { - "@cloudflare/workers-types": "^5.20260911.1" + "@cloudflare/workers-types": "^5.20260918.1" }, "peerDependenciesMeta": { "@cloudflare/workers-types": { @@ -7577,9 +7577,9 @@ } }, "node_modules/wrangler/node_modules/@cloudflare/workerd-darwin-64": { - "version": "1.20260911.1", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20260911.1.tgz", - "integrity": "sha512-785eaY1bkR1cm4Z/PCUeteZYmTMe6lre2zz63/GdGGimsoMsKxgl4brFPRukim8iv28EyD1XoCB/VPYF20BERA==", + "version": "1.20260918.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-64/-/workerd-darwin-64-1.20260918.1.tgz", + "integrity": "sha512-H5Em6Wd0jjxaloYh2rp+WLBl2eWbkk7nSP1svGt6K1RSv/rNVqmKdpjZPJTBSavOmeYGa88qvtOWwS+33OHTqQ==", "cpu": [ "x64" ], @@ -7594,9 +7594,9 @@ } }, "node_modules/wrangler/node_modules/@cloudflare/workerd-darwin-arm64": { - "version": "1.20260911.1", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20260911.1.tgz", - "integrity": "sha512-WU4bFqEN0H7ndGWxoedegv95DmNVBtv0ncXcHG9nYFTUI78sxEb0qoT3U6Ga4hyBkzsJFBX/zvVBIGX3qKldGA==", + "version": "1.20260918.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-darwin-arm64/-/workerd-darwin-arm64-1.20260918.1.tgz", + "integrity": "sha512-CR9JRZEQo93fNgBVF4Df2H2/VYO4n7rxSseSwCVv3bJQEb0huADUSCj2FK4ipxar8ToOEB4wawyw0vJo5U/rQQ==", "cpu": [ "arm64" ], @@ -7611,9 +7611,9 @@ } }, "node_modules/wrangler/node_modules/@cloudflare/workerd-linux-64": { - "version": "1.20260911.1", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20260911.1.tgz", - "integrity": "sha512-0Y2gy62oxQxWa38qinSPE6zNL5+JmumJtDY9AWW1HB8KHuATxN71o5MGzmVFfB8PwZsiHfUd2Sv7O22krCOrhw==", + "version": "1.20260918.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-64/-/workerd-linux-64-1.20260918.1.tgz", + "integrity": "sha512-UQ2nnY3qpXLzQ80frmWO+8HvtqyWaQILe8QYZwpemdjT+sqwCz4Dz+0/WVkFco0v/04kIIqikVeLTY/7gEhmkw==", "cpu": [ "x64" ], @@ -7628,9 +7628,9 @@ } }, "node_modules/wrangler/node_modules/@cloudflare/workerd-linux-arm64": { - "version": "1.20260911.1", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20260911.1.tgz", - "integrity": "sha512-kttNPnx1r2lCqFUoMH62z7CqGV+j4QBbw5fdtaz4pzOrzBv0AWkNATt7onFUe+SwP8zhcepMtbm2F4kKzTf6VA==", + "version": "1.20260918.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-linux-arm64/-/workerd-linux-arm64-1.20260918.1.tgz", + "integrity": "sha512-4rib51MaLNWweUIUxM/Xj558M5QmyZoBSf0ffv+lYah5VTrvwnez3XGxX72pElnBKHROvAPOi5msQ5Ts8JSI0A==", "cpu": [ "arm64" ], @@ -7645,9 +7645,9 @@ } }, "node_modules/wrangler/node_modules/@cloudflare/workerd-windows-64": { - "version": "1.20260911.1", - "resolved": "https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20260911.1.tgz", - "integrity": "sha512-5iO/YfoBDOgO3CrHdkiiVP8SL3O2jC+c6Ux3d378TSPKLhU5+CgHjtE/ZSodWQrzr4FzFRqdW8S7n5nbyD1MHQ==", + "version": "1.20260918.1", + "resolved": "https://registry.npmjs.org/@cloudflare/workerd-windows-64/-/workerd-windows-64-1.20260918.1.tgz", + "integrity": "sha512-sATrMx5ShYYgmgUGrcTmvsFSJBFuN95NEkX3xwb1qk8w1A6h5N11sea7yN2IeibwPyPmXKjWNjXOno0hZAM71Q==", "cpu": [ "x64" ], @@ -8227,16 +8227,16 @@ } }, "node_modules/wrangler/node_modules/miniflare": { - "version": "5.20260911.1-alpha", - "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-5.20260911.1-alpha.tgz", - "integrity": "sha512-7IDj9monoYcCPrS8HfcTt90T3pDwKGvNEAR1Y061KbJhBd5JkStOwOpHMUDFBo9PEbjWVDxPICAnXGNNV2LNfQ==", + "version": "5.20260918.0-alpha", + "resolved": "https://registry.npmjs.org/miniflare/-/miniflare-5.20260918.0-alpha.tgz", + "integrity": "sha512-vyIes7yW/OTzHtz4GhcBCTohZfqk2eQNiIkngZ07VRA5Qu24aNgW/TrFwlPkMLMjWDQ8R4JJBBHR/KX+liSDtg==", "dev": true, "license": "MIT", "dependencies": { "@cspotcode/source-map-support": "0.8.1", "sharp": "0.35.4", "undici": "7.29.0", - "workerd": "1.20260911.1", + "workerd": "1.20260918.1", "ws": "8.21.0", "youch": "4.1.0-beta.10" }, @@ -8308,9 +8308,9 @@ } }, "node_modules/wrangler/node_modules/workerd": { - "version": "1.20260911.1", - "resolved": "https://registry.npmjs.org/workerd/-/workerd-1.20260911.1.tgz", - "integrity": "sha512-vRr8QdBxueQOZJO1hRCI73EZlix87IAyBAcSyI3rA1VB+6oxjw3oaqzYnIV8C4IOPtUgihbdMAgzkb5GM4V7DQ==", + "version": "1.20260918.1", + "resolved": "https://registry.npmjs.org/workerd/-/workerd-1.20260918.1.tgz", + "integrity": "sha512-NsjfQlBNQ0iEniv/STOy4zbp8s5k60PzL1Ter02Eg44arbDhHtf6UOs03E31XDRmmBFxSIkAZuCyld3RKH1wqA==", "dev": true, "hasInstallScript": true, "license": "Apache-2.0", @@ -8321,11 +8321,11 @@ "node": ">=16" }, "optionalDependencies": { - "@cloudflare/workerd-darwin-64": "1.20260911.1", - "@cloudflare/workerd-darwin-arm64": "1.20260911.1", - "@cloudflare/workerd-linux-64": "1.20260911.1", - "@cloudflare/workerd-linux-arm64": "1.20260911.1", - "@cloudflare/workerd-windows-64": "1.20260911.1" + "@cloudflare/workerd-darwin-64": "1.20260918.1", + "@cloudflare/workerd-darwin-arm64": "1.20260918.1", + "@cloudflare/workerd-linux-64": "1.20260918.1", + "@cloudflare/workerd-linux-arm64": "1.20260918.1", + "@cloudflare/workerd-windows-64": "1.20260918.1" } }, "node_modules/wrappy": { @@ -8435,15 +8435,15 @@ "zod": "^4.6.5" }, "devDependencies": { - "@types/node": "^24.13.5", + "@types/node": "^24.13.6", "typescript": "^6.0.3", "vitest": "^4.1.11" } }, "packages/atmosphere/node_modules/@types/node": { - "version": "24.13.5", - "resolved": "https://registry.npmjs.org/@types/node/-/node-24.13.5.tgz", - "integrity": "sha512-TXyindR+lBr22aJIdMQzCFHPHR6cR4js838mRDCSz5hOKWZvZwsXSSiXDmjRj4iJmgl+sR9O+1mkoVBSMadNug==", + "version": "24.13.6", + "resolved": "https://registry.npmjs.org/@types/node/-/node-24.13.6.tgz", + "integrity": "sha512-SGrw/h3KPFshy3OE6ZL53LMBG5vGQQ8/gIpiqz/kRZhPJ7HgwCEs8LBuNtWLa8dvGZVpSF7+Bf+c11HUrCb/yg==", "dev": true, "license": "MIT", "dependencies": { diff --git a/package.json b/package.json index 8869962d..c5b118d3 100644 --- a/package.json +++ b/package.json @@ -33,10 +33,10 @@ "author": "dangered wolf", "license": "MIT", "devDependencies": { - "@aws-sdk/client-s3": "^3.1135.0", - "@aws-sdk/s3-request-presigner": "^3.1135.0", + "@aws-sdk/client-s3": "^3.1136.0", + "@aws-sdk/s3-request-presigner": "^3.1136.0", "@cloudflare/vitest-pool-workers": "^0.22.0", - "@cloudflare/workers-types": "^5.20260915.1", + "@cloudflare/workers-types": "^5.20260919.1", "@eslint/js": "^10.0.1", "@microsoft/eslint-formatter-sarif": "^3.1.0", "@sentry/esbuild-plugin": "^5.4.0", @@ -49,13 +49,13 @@ "eslint-plugin-optimize-regex": "^1.2.1", "eslint-plugin-prettier": "^5.5.6", "globals": "^17.12.0", - "prettier": "^3.9.7", + "prettier": "^3.9.8", "ts-loader": "^9.6.2", "tsx": "^4.23.13", "typescript": "^6.0.3", "typescript-eslint": "^8.70.0", "vitest": "^4.1.11", - "wrangler": "^4.131.2" + "wrangler": "^4.135.0" }, "dependencies": { "@fxembed/atmosphere": "*", diff --git a/packages/atmosphere/package.json b/packages/atmosphere/package.json index f1dd4b8e..b3c3db3e 100644 --- a/packages/atmosphere/package.json +++ b/packages/atmosphere/package.json @@ -110,7 +110,7 @@ }, "license": "MIT", "devDependencies": { - "@types/node": "^24.13.5", + "@types/node": "^24.13.6", "typescript": "^6.0.3", "vitest": "^4.1.11" }, diff --git a/src/embed/status.ts b/src/embed/status.ts index 0de0a45d..12f68fc7 100644 --- a/src/embed/status.ts +++ b/src/embed/status.ts @@ -31,6 +31,26 @@ import { constructInstagramPost } from '@fxembed/atmosphere/providers/instagram/ import { InputFlags } from '../types/types'; import { formatRuntime } from '../helpers/runtime'; +/** + * Telegram's link preview plays videos inside an embed container. Instagram + * files fail there, so Telegram user agents get the video file directly. + * Image posts, other networks, and other clients stay on the embed pipeline. + * Explicit API, text-only, gallery, and instant-view requests are unchanged. + */ +const useDirectMediaForTelegramInstagramVideo = ( + isTelegram: boolean, + provider: DataProvider, + flags: InputFlags, + hasVideo: boolean +): boolean => + isTelegram && + provider === DataProvider.Instagram && + hasVideo && + !flags.api && + !flags.textOnly && + !flags.gallery && + !flags.forceInstantView; + /** * Check if the tweet text is essentially just an article URL with no meaningful additional content. * Returns true if we should use the article as the main preview. @@ -345,6 +365,24 @@ export const handleStatus = async ( } } + /* Temporary: Instagram videos + Telegram skip the embed container. */ + if ( + useDirectMediaForTelegramInstagramVideo( + isTelegram, + provider, + flags, + (status.media?.videos?.length ?? 0) > 0 + ) + ) { + const videos = status.media?.videos ?? []; + const indexed = mediaNumber ? status.media?.all?.[mediaNumber - 1] : undefined; + const selected = indexed?.type === 'video' ? indexed : videos[0]; + if (selected?.url) { + console.log('Telegram Instagram video direct media', selected.url); + return c.redirect(selected.url, 302); + } + } + /* User requested gallery view, but this isn't a status with media */ if (flags.gallery && (status.media?.all?.length ?? 0) < 1) { flags.gallery = false; diff --git a/test/instagram.telegramDirect.test.ts b/test/instagram.telegramDirect.test.ts new file mode 100644 index 00000000..fa7912a4 --- /dev/null +++ b/test/instagram.telegramDirect.test.ts @@ -0,0 +1,159 @@ +import { afterEach, expect, test, vi } from 'vitest'; +import { app } from '../src/worker'; +import { botHeaders } from './helpers/data'; +import harness from './helpers/harness'; + +const telegramHeaders = { 'User-Agent': 'TelegramBot (like TwitterBot)' }; +const VIDEO_URL = 'https://cdn.example/reel.mp4'; +const IMAGE_URL = 'https://cdn.example/photo.jpg'; + +const author = { + pk: '1', + username: 'iguser', + full_name: 'IG User', + profile_pic_url: 'https://cdn.example/avatar.jpg' +}; + +const posts: Record> = { + VidTest01: { + code: 'VidTest01', + pk: '1', + media_type: 2, + taken_at: 1700000000, + caption: { text: 'a reel' }, + user: author, + original_width: 720, + original_height: 1280, + video_duration: 5, + video_versions: [{ url: VIDEO_URL, type: 101, width: 720, height: 1280 }], + image_versions2: { + candidates: [{ url: 'https://cdn.example/thumb.jpg', width: 720, height: 1280 }] + } + }, + ImgTest01: { + code: 'ImgTest01', + pk: '2', + media_type: 1, + taken_at: 1700000000, + caption: { text: 'a photo' }, + user: author, + image_versions2: { + candidates: [{ url: IMAGE_URL, width: 1080, height: 1080 }] + } + } +}; + +function webInfoHtml(item: Record): string { + return ``; +} + +function installInstagramFetch() { + vi.stubGlobal('fetch', async (input: RequestInfo | URL) => { + const raw = typeof input === 'string' ? input : input instanceof URL ? input.href : input.url; + const url = new URL(raw); + if (url.hostname !== 'www.instagram.com') { + return new Response('not found', { status: 404 }); + } + const shortcode = url.pathname.split('/').filter(Boolean).pop(); + const item = shortcode ? posts[shortcode] : undefined; + if (!item) { + return new Response('', { status: 200 }); + } + return new Response(webInfoHtml(item), { + status: 200, + headers: { 'content-type': 'text/html' } + }); + }); +} + +afterEach(() => { + vi.unstubAllGlobals(); +}); + +test('Telegram receives direct media for an Instagram video', async () => { + installInstagramFetch(); + const res = await app.request( + new Request('https://67instagram.com/reel/VidTest01', { + method: 'GET', + headers: telegramHeaders + }), + undefined, + harness + ); + + expect(res.status).toBe(302); + expect(res.headers.get('location')).toBe(VIDEO_URL); +}); + +test('Discord keeps the embed pipeline for an Instagram video', async () => { + installInstagramFetch(); + const res = await app.request( + new Request('https://67instagram.com/p/VidTest01', { + method: 'GET', + headers: botHeaders + }), + undefined, + harness + ); + + expect(res.status).toBe(200); + const html = await res.text(); + expect(html).toContain('application/activity+json'); + expect(html).not.toContain(`content="${VIDEO_URL}"`); + expect(res.headers.get('location')).toBeNull(); +}); + +test('Other non-Telegram clients keep the Instagram video embed', async () => { + installInstagramFetch(); + const res = await app.request( + new Request('https://67instagram.com/reel/VidTest01', { + method: 'GET', + headers: { 'User-Agent': 'WhatsApp/2.0' } + }), + undefined, + harness + ); + + expect(res.status).toBe(200); + const html = await res.text(); + expect(html).toContain('og:video'); + expect(html).toContain(VIDEO_URL); + expect(html).toContain('twitter:card" content="player"'); +}); + +test('Telegram keeps the embed pipeline for an Instagram image', async () => { + installInstagramFetch(); + const res = await app.request( + new Request('https://67instagram.com/p/ImgTest01', { + method: 'GET', + headers: telegramHeaders + }), + undefined, + harness + ); + + expect(res.status).toBe(200); + const html = await res.text(); + expect(html).toContain('og:image'); + expect(html).toContain(IMAGE_URL); + expect(res.headers.get('location')).toBeNull(); +}); + +test('Telegram keeps the embed pipeline for a non-Instagram video', async () => { + const res = await app.request( + new Request('https://fxtwitter.com/DivineDropbear/status/1841206275088290279', { + method: 'GET', + headers: telegramHeaders + }), + undefined, + harness + ); + + expect(res.status).toBe(200); + const html = await res.text(); + expect(html).toContain('twitter:card" content="player"'); + expect(html).not.toContain('