Personal Site
0
fork

Configure Feed

Select the types of activity you want to include in your feed.

at master 69 lines 2.3 kB view raw
1import { sdk } from "/components/home/playing/spotify"; 2import type { nowPlaying } from "/components/home/playing/spotify/client"; 3 4export const prerender = false; 5 6export async function GET() { 7 const update = async (): Promise<string> => { 8 // extract a subset to reduce size for client 9 // not huge savings but tesco yk 10 // + reduces chance of leaking extra data to client 11 const playing = await sdk.player.getCurrentlyPlayingTrack().then( 12 (playing) => 13 // minimise body to make faster and streamline download 14 (!!playing && "album" in playing.item 15 ? { 16 id: playing.item.id, 17 name: playing.item.name, 18 href: playing.item.external_urls.spotify, 19 album: playing.item.album.name, 20 art: playing.item.album.images[0].url, 21 artists: playing.item.artists.map((artist) => ({ 22 name: artist.name, 23 href: artist.external_urls.spotify, 24 })), 25 } 26 : null) satisfies nowPlaying, 27 ); 28 29 // SSE syntax: https://developer.mozilla.org/en-US/docs/Web/API/Server-sent_events/Using_server-sent_events#event_stream_format 30 return `event: playing\ndata: ${JSON.stringify(playing)}\n\n`; 31 }; 32 33 const abort = new AbortController(); 34 35 return new Response( 36 new ReadableStream({ 37 async start(controller) { 38 while (!abort.signal.aborted) { 39 // dont block loop if spotify API is slow/etc 40 update() 41 // dont write if aborted as it can cause errors 42 .then((val) => 43 !abort.signal.aborted ? controller.enqueue(val) : undefined, 44 ) 45 .catch((err) => { 46 console.error("/now-playing-sse", "GOT ERROR:", err); 47 }); 48 await new Promise((res, rej) => { 49 setTimeout(res, 20 * 1000); 50 abort.signal.addEventListener("abort", rej); 51 }); 52 } 53 }, 54 55 async cancel() { 56 abort.abort(); 57 }, 58 }), 59 { 60 // Set the headers for Server-Sent Events (SSE) 61 headers: { 62 Connection: "keep-alive", 63 "Content-Encoding": "none", 64 "Cache-Control": "no-cache, no-transform", 65 "Content-Type": "text/event-stream; charset=utf-8", 66 }, 67 }, 68 ); 69}