diff --git a/src/app/utils/videoEmbed.test.ts b/src/app/utils/videoEmbed.test.ts index 2ead5a849..b8a5986fd 100644 --- a/src/app/utils/videoEmbed.test.ts +++ b/src/app/utils/videoEmbed.test.ts @@ -89,7 +89,7 @@ test('tiktokIdFromOembed + player url', () => { assert.equal(tiktokIdFromOembed({ embed_product_id: '7659555276823006478' }), '7659555276823006478'); assert.equal(tiktokIdFromOembed({ html: '
' }), '123456'); assert.equal(tiktokIdFromOembed({}), null); - assert.ok(tiktokPlayerEmbedUrl('999').startsWith('https://www.tiktok.com/player/v1/999?autoplay=1')); + assert.equal(tiktokPlayerEmbedUrl('999'), 'https://www.tiktok.com/player/v1/999?autoplay=1&rel=0'); }); test('Dailymotion + Streamable', () => { @@ -132,9 +132,11 @@ test('Spotify target + height', () => { assert.equal(spotifyEmbedHeight('album'), 352); }); -test('SoundCloud track detection', () => { +test('SoundCloud track detection (+ on. short link)', () => { assert.equal(isSoundCloudTrack('https://soundcloud.com/artist/some-track'), true); assert.equal(isSoundCloudTrack('https://soundcloud.com/artist'), false); // bare profile + assert.equal(isSoundCloudTrack('https://on.soundcloud.com/abc123'), true); // share short link + assert.equal(parseMediaEmbed('https://on.soundcloud.com/abc123', 'h')?.provider, 'soundcloud'); }); test('buildVideoEmbedUrl: cookie-less YouTube + Vimeo', () => { @@ -218,6 +220,8 @@ test('Reddit post embed → redditmedia', () => { ); assert.equal(getRedditPostEmbed('https://old.reddit.com/r/aww/comments/xyz/'), 'https://embed.reddit.com/r/aww/comments/xyz/?ref_source=embed&ref=share&embed=true&theme=dark'); assert.equal(getRedditPostEmbed('https://www.reddit.com/r/aww/'), null); // subreddit, not a post + // redd.it short link → comments-only embed (no subreddit in the redirect) + assert.equal(getRedditPostEmbed('https://redd.it/1abc23'), 'https://embed.reddit.com/comments/1abc23/?ref_source=embed&ref=share&embed=true&theme=dark'); }); test('parseMediaEmbed: Instagram/Reddit → rich, Tidal → audio', () => { diff --git a/src/app/utils/videoEmbed.ts b/src/app/utils/videoEmbed.ts index 5912f840e..9fd81e7bc 100644 --- a/src/app/utils/videoEmbed.ts +++ b/src/app/utils/videoEmbed.ts @@ -163,12 +163,10 @@ export function extractEmbedHeight(data: unknown): number | undefined { } export function tiktokPlayerEmbedUrl(id: string): string { - // Pure 9:16 video player. NOTE: music_info/description are intentionally OFF — - // they switch TikTok to a wide "video + info panel" layout that leaves empty - // space beside the video in a portrait box. - return `https://www.tiktok.com/player/v1/${encodeURIComponent( - id, - )}?autoplay=1&controls=1&progress_bar=1&play_button=1&volume_control=1&fullscreen_button=1&rel=0`; + // Pure 9:16 video player. music_info/description default OFF (they'd switch + // TikTok to a wide "video + info panel" layout); controls/progress/play/volume/ + // fullscreen buttons all default ON, so only autoplay + rel are load-bearing. + return `https://www.tiktok.com/player/v1/${encodeURIComponent(id)}?autoplay=1&rel=0`; } // --- Dailymotion ---------------------------------------------------------- @@ -249,7 +247,10 @@ export function getSpotifyEmbedTarget(url: string): { type: SpotifyType; id: str export function isSoundCloudTrack(url: string): boolean { try { const { hostname, pathname } = new URL(url); - if (hostname.replace(/^www\./, '') !== 'soundcloud.com') return false; + const h = hostname.replace(/^www\./, ''); + // on.soundcloud.com/ is a share short link — the widget follows it. + if (h === 'on.soundcloud.com') return pathname.replace(/^\/+|\/+$/g, '').length > 0; + if (h !== 'soundcloud.com') return false; // // — at least two segments, not a bare profile const parts = pathname.replace(/^\/+|\/+$/g, '').split('/').filter(Boolean); return parts.length >= 2; @@ -346,15 +347,22 @@ export function getInstagramEmbed(url: string): string | null { // --- Reddit (post embed via redditmedia — bypasses the homeserver's blocked // preview fetch, which Reddit serves a bot-check "please wait" page to) --- +const REDDIT_EMBED_QS = '?ref_source=embed&ref=share&embed=true&theme=dark'; + export function getRedditPostEmbed(url: string): string | null { try { const u = new URL(url); const h = u.hostname.replace(/^(www|old|new|np|i)\./, ''); + // redd.it/ short link → reddit.com/comments/ (no subreddit needed). + if (h === 'redd.it') { + const id = u.pathname.replace(/^\/+|\/+$/g, '').split('/')[0]; + return id ? `https://embed.reddit.com/comments/${id}/${REDDIT_EMBED_QS}` : null; + } if (h !== 'reddit.com') return null; const m = u.pathname.match(/^\/r\/([A-Za-z0-9_]+)\/comments\/([A-Za-z0-9]+)/); if (!m) return null; // embed.reddit.com is the current host (www.redditmedia.com now 301s here). - return `https://embed.reddit.com/r/${m[1]}/comments/${m[2]}/?ref_source=embed&ref=share&embed=true&theme=dark`; + return `https://embed.reddit.com/r/${m[1]}/comments/${m[2]}/${REDDIT_EMBED_QS}`; } catch { return null; }