@@ -8,54 +8,16 @@ const IS_LIVE_RE = /"isLive"\s*:\s*true/;
88
99type CacheEntry = {
1010 isLive : boolean ;
11- playableInEmbed : boolean ;
1211 videoId : string | null ;
1312 checkedAt : number ;
1413} ;
1514
1615const 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