diff --git a/__tests__/lib/string.test.ts b/__tests__/lib/string.test.ts index 0c441ccdc2..8d999ba7af 100644 --- a/__tests__/lib/string.test.ts +++ b/__tests__/lib/string.test.ts @@ -8,7 +8,7 @@ import { parseStarterPackUri, } from '#/lib/strings/starter-pack' import {messages} from '#/locale/locales/en/messages' -import {klipyStaticUrl} from '#/state/queries/klipy' +import {klipyUrlToBskyGifUrl} from '#/state/queries/klipy' import {tenorUrlToBskyGifUrl} from '#/state/queries/tenor' import {cleanError} from '../../src/lib/strings/errors' import {createFullHandle, makeValidHandle} from '../../src/lib/strings/handles' @@ -858,7 +858,7 @@ describe('parseEmbedPlayerFromUrl', () => { source: 'klipy', isGif: true, hideDetails: true, - playerUri: 'https://static.klipy.com/ii/abc123/73/ac/someFile.gif', + playerUri: 'https://t.gifs.bsky.app/ii/abc123/73/ac/someFile.gif', dimensions: { width: 300, height: 200, @@ -1073,13 +1073,30 @@ describe('tenorUrlToBskyGifUrl', () => { ) }) -describe('klipyStaticUrl', () => { - it('returns the URL as-is for valid KLIPY static URLs', () => { - const input = 'https://static.klipy.com/ii/abc123/73/ac/someFile.gif' - expect(klipyStaticUrl(input)).toEqual(input) +describe('klipyUrlToBskyGifUrl', () => { + const inputs = [ + 'https://static.klipy.com/ii/abc123/73/ac/someFile.gif', + 'https://static.klipy.com/ii/abc123/73/ac/someFile.gif?hh=200&ww=300', + ] + + it.each(inputs)( + 'returns url with t.gifs.bsky.app as hostname for input url', + input => { + const out = klipyUrlToBskyGifUrl(input) + expect(out.startsWith('https://t.gifs.bsky.app/')).toEqual(true) + }, + ) + + it('preserves the path and query params when rewriting', () => { + const out = klipyUrlToBskyGifUrl( + 'https://static.klipy.com/ii/abc123/73/ac/someFile.gif?hh=200&ww=300', + ) + expect(out).toEqual( + 'https://t.gifs.bsky.app/ii/abc123/73/ac/someFile.gif?hh=200&ww=300', + ) }) it('returns empty string for invalid URLs', () => { - expect(klipyStaticUrl('not-a-url')).toEqual('') + expect(klipyUrlToBskyGifUrl('not-a-url')).toEqual('') }) }) diff --git a/src/lib/strings/embed-player.ts b/src/lib/strings/embed-player.ts index bbd4c11305..96978550b4 100644 --- a/src/lib/strings/embed-player.ts +++ b/src/lib/strings/embed-player.ts @@ -683,8 +683,10 @@ export function parseKlipyGif(urlp: URL): return {success: false} } - // Use the base URL without dimension params as the player URI + // Use the base URL without dimension params as the player URI, + // routed through the bsky proxy (t.gifs.bsky.app) — matching Tenor. const playerUrl = new URL(urlp.href) + playerUrl.hostname = 't.gifs.bsky.app' playerUrl.searchParams.delete('hh') playerUrl.searchParams.delete('ww') diff --git a/src/state/queries/klipy.ts b/src/state/queries/klipy.ts index 59e80bc0f8..4b646fb405 100644 --- a/src/state/queries/klipy.ts +++ b/src/state/queries/klipy.ts @@ -90,16 +90,17 @@ function createKlipyApi( } /** - * Returns the static URL for a KLIPY GIF preview image. - * KLIPY images are served directly from their CDN (static.klipy.com), - * unlike Tenor which routes through t.gifs.bsky.app. + * Rewrites a KLIPY static CDN URL through the bsky proxy + * (t.gifs.bsky.app), matching the behavior of `tenorUrlToBskyGifUrl`. */ -export function klipyStaticUrl(gifUrl: string) { +export function klipyUrlToBskyGifUrl(klipyUrl: string) { + let url try { - new URL(gifUrl) - return gifUrl + url = new URL(klipyUrl) } catch (e) { - logger.debug('invalid url passed to klipyStaticUrl()') + logger.debug('invalid url passed to klipyUrlToBskyGifUrl()') return '' } + url.hostname = 't.gifs.bsky.app' + return url.href } diff --git a/src/state/queries/tenor.ts b/src/state/queries/tenor.ts index 3adc9139c8..310fa308b8 100644 --- a/src/state/queries/tenor.ts +++ b/src/state/queries/tenor.ts @@ -105,14 +105,18 @@ export function tenorUrlToBskyGifUrl(tenorUrl: string) { /** * Returns the appropriate URL for a GIF preview image. - * Rewrites Tenor URLs through the bsky proxy (t.gifs.bsky.app); - * KLIPY URLs pass through directly to their CDN. + * Both Tenor (media.tenor.com) and KLIPY (static.klipy.com) URLs are + * rewritten through the bsky proxy at t.gifs.bsky.app. */ export function gifPreviewUrl(gifUrl: string) { try { const url = new URL(gifUrl) - if (url.hostname === 'media.tenor.com') { - return tenorUrlToBskyGifUrl(gifUrl) + if ( + url.hostname === 'media.tenor.com' || + url.hostname === 'static.klipy.com' + ) { + url.hostname = 't.gifs.bsky.app' + return url.href } return gifUrl } catch (e) {