Skip to content

Commit 1223a43

Browse files
Merge pull request #49 from Juliusolsson05/fix/drop-embed-gate
fix: drop embed detection gate and trust canonical videoId
2 parents 59e14a1 + ce6e8e6 commit 1223a43

1 file changed

Lines changed: 9 additions & 51 deletions

File tree

  • src/app/api/v1/perspectives/live-status

src/app/api/v1/perspectives/live-status/route.ts

Lines changed: 9 additions & 51 deletions
Original file line numberDiff line numberDiff line change
@@ -8,54 +8,16 @@ const IS_LIVE_RE = /"isLive"\s*:\s*true/;
88

99
type CacheEntry = {
1010
isLive: boolean;
11-
playableInEmbed: boolean;
1211
videoId: string | null;
1312
checkedAt: number;
1413
};
1514

1615
const cache = new Map<string, CacheEntry>();
1716

18-
async function isEmbeddableVideo(videoId: string) {
19-
const oembedUrl = `https://www.youtube.com/oembed?url=https://www.youtube.com/watch?v=${videoId}&format=json`;
20-
21-
try {
22-
const res = await fetch(oembedUrl, {
23-
headers: { 'User-Agent': 'Mozilla/5.0' },
24-
signal: AbortSignal.timeout(8000),
25-
});
26-
27-
return res.ok;
28-
} catch {
29-
return false;
30-
}
31-
}
32-
33-
async function parseLivePlayback(html: string) {
34-
const canonicalVideoId = html.match(CANONICAL_VIDEO_RE)?.[1] ?? null;
35-
36-
if (!canonicalVideoId) {
37-
return {
38-
playableInEmbed: false,
39-
videoId: null,
40-
};
41-
}
42-
43-
const playableInEmbed = await isEmbeddableVideo(canonicalVideoId);
44-
45-
return {
46-
playableInEmbed,
47-
videoId: playableInEmbed ? canonicalVideoId : null,
48-
};
49-
}
50-
51-
async function checkLiveStatus(handle: string): Promise<{ isLive: boolean; playableInEmbed: boolean; videoId: string | null }> {
17+
async function checkLiveStatus(handle: string): Promise<{ isLive: boolean; videoId: string | null }> {
5218
const cached = cache.get(handle);
5319
if (cached && Date.now() - cached.checkedAt < CACHE_TTL * 1000) {
54-
return {
55-
isLive: cached.isLive,
56-
playableInEmbed: cached.playableInEmbed,
57-
videoId: cached.videoId,
58-
};
20+
return { isLive: cached.isLive, videoId: cached.videoId };
5921
}
6022

6123
try {
@@ -65,17 +27,13 @@ async function checkLiveStatus(handle: string): Promise<{ isLive: boolean; playa
6527
});
6628
const html = await res.text();
6729
const isLive = IS_LIVE_RE.test(html);
68-
const playback = isLive
69-
? await parseLivePlayback(html)
70-
: { playableInEmbed: false, videoId: null };
71-
const playableInEmbed = playback.playableInEmbed;
72-
const videoId = playback.videoId;
30+
const videoId = isLive ? (html.match(CANONICAL_VIDEO_RE)?.[1] ?? null) : null;
7331

74-
cache.set(handle, { isLive, playableInEmbed, videoId, checkedAt: Date.now() });
75-
return { isLive, playableInEmbed, videoId };
32+
cache.set(handle, { isLive, videoId, checkedAt: Date.now() });
33+
return { isLive, videoId };
7634
} catch {
77-
cache.set(handle, { isLive: false, playableInEmbed: false, videoId: null, checkedAt: Date.now() });
78-
return { isLive: false, playableInEmbed: false, videoId: null };
35+
cache.set(handle, { isLive: false, videoId: null, checkedAt: Date.now() });
36+
return { isLive: false, videoId: null };
7937
}
8038
}
8139

@@ -85,10 +43,10 @@ export async function GET(req: NextRequest) {
8543
return err('INVALID_PARAMS', 'handle query param required (e.g. ?handle=@SkyNews)');
8644
}
8745

88-
const { isLive, playableInEmbed, videoId } = await checkLiveStatus(handle);
46+
const { isLive, videoId } = await checkLiveStatus(handle);
8947

9048
return ok(
91-
{ handle, isLive, playableInEmbed, videoId, ttl: CACHE_TTL },
49+
{ handle, isLive, playableInEmbed: isLive && Boolean(videoId), videoId, ttl: CACHE_TTL },
9250
{
9351
headers: {
9452
'Cache-Control': `public, s-maxage=${CACHE_TTL}, stale-while-revalidate=${CACHE_TTL}`,

0 commit comments

Comments
 (0)