your personal website on atproto - mirror blento.app
at fix-cached-posts 107 lines 3.3 kB view raw
1import { user, listRecords, getCDNImageBlobUrl } from '$lib/atproto'; 2import type { CardDefinition } from '../../types'; 3import LivestreamCard from './LivestreamCard.svelte'; 4import LivestreamEmbedCard from './LivestreamEmbedCard.svelte'; 5 6export const LivestreamCardDefitition = { 7 type: 'latestLivestream', 8 contentComponent: LivestreamCard, 9 createNew: (card) => { 10 card.w = 4; 11 card.h = 4; 12 card.mobileH = 8; 13 card.mobileW = 8; 14 15 card.cardType = 'latestLivestream'; 16 }, 17 loadData: async (items, { did }) => { 18 const records = await listRecords({ did, collection: 'place.stream.livestream', limit: 3 }); 19 20 let latestLivestream: 21 | { 22 createdAt: string; 23 title: string; 24 thumb?: string; 25 href: string; 26 online?: boolean; 27 } 28 | undefined; 29 30 if (records?.length) { 31 const latest = JSON.parse(JSON.stringify(records?.[0])); 32 33 latestLivestream = { 34 createdAt: latest.value.createdAt, 35 title: latest.value?.title as string, 36 thumb: latest.value?.thumb?.ref?.$link 37 ? getCDNImageBlobUrl({ blob: latest.value.thumb, did }) 38 : undefined, 39 href: latest.value?.canonicalUrl || latest.value.url, 40 online: undefined 41 }; 42 } 43 44 if (latestLivestream) { 45 try { 46 const segmentsResponse = await fetch( 47 'https://stream.place/xrpc/place.stream.live.getSegments?userDID=' + 48 encodeURIComponent(did) 49 ); 50 const segments = await segmentsResponse.json(); 51 52 const lastSegment = segments.segments[0]; 53 const startTime = new Date(lastSegment.record.startTime).getTime(); 54 55 const FIVE_MINUTES = 5 * 60 * 1000; 56 const now = Date.now(); 57 58 latestLivestream.online = now - startTime <= FIVE_MINUTES; 59 } catch (error) { 60 console.error(error); 61 } 62 } 63 64 return latestLivestream; 65 }, 66 67 onUrlHandler: (url, item) => { 68 if (url === 'https://stream.place/' + user.profile?.handle) { 69 item.w = 4; 70 item.h = 4; 71 item.mobileH = 8; 72 item.mobileW = 8; 73 item.cardData.href = 'https://stream.place/' + user.profile?.handle; 74 return item; 75 } 76 }, 77 78 canChange: (item) => item.cardData.href === 'https://stream.place/' + user.profile?.handle, 79 80 urlHandlerPriority: 5, 81 82 name: 'Latest Livestream (stream.place)', 83 keywords: ['stream', 'live', 'broadcast', 'video'], 84 groups: ['Media'], 85 icon: `<svg xmlns="http://www.w3.org/2000/svg" fill="none" viewBox="0 0 24 24" stroke-width="2" stroke="currentColor" class="size-4"><path stroke-linecap="round" stroke-linejoin="round" d="m15.75 10.5 4.72-4.72a.75.75 0 0 1 1.28.53v11.38a.75.75 0 0 1-1.28.53l-4.72-4.72M4.5 18.75h9a2.25 2.25 0 0 0 2.25-2.25v-9a2.25 2.25 0 0 0-2.25-2.25h-9A2.25 2.25 0 0 0 2.25 7.5v9a2.25 2.25 0 0 0 2.25 2.25Z" /></svg>` 86} as CardDefinition & { type: 'latestLivestream' }; 87 88export const LivestreamEmbedCardDefitition = { 89 type: 'livestreamEmbed', 90 contentComponent: LivestreamEmbedCard, 91 createNew: (card) => { 92 card.w = 4; 93 card.h = 2; 94 card.mobileW = 8; 95 card.mobileH = 4; 96 97 card.cardData = { 98 href: 'https://stream.place/' + user.profile?.handle, 99 embed: 'https://stream.place/embed/' + user.profile?.handle 100 }; 101 } 102 // canChange: (item) => item.cardData.href === 'https://stream.place/' + client.profile?.handle, 103 104 // change: (item) => { 105 // item.cardData.embed = 'https://stream.place/embed/' + client.profile?.handle; 106 // }, 107} as CardDefinition & { type: 'livestreamEmbed' };