data endpoint for entity 90008 (aka. a website)
at svelte 4.4 kB view raw
1import { updateLastPosts } from '$lib/bluesky'; 2import { getLastTrack, updateNowPlayingTrack } from '$lib/lastfm'; 3import { steamReadLastGame, steamUpdateNowPlaying } from '$lib/steam'; 4import { updateCommits } from '$lib/activity'; 5import { ToadScheduler, SimpleIntervalJob, Task, AsyncTask } from 'toad-scheduler'; 6import { 7 incrementFakeVisitCount, 8 incrementLegitVisitCount, 9 pushMetric, 10 sendAllMetrics 11} from '$lib/metrics'; 12import { 13 addLastVisitor, 14 decrementVisitCount, 15 incrementVisitCount, 16 notifyDarkVisitors, 17 removeLastVisitor 18} from '$lib/visits'; 19import { testUa } from '$lib/robots'; 20import { error, type Handle } from '@sveltejs/kit'; 21import { _fetchEntries } from './routes/(site)/guestbook/+page.server'; 22import { sequence } from '@sveltejs/kit/hooks'; 23 24const updateNowPlaying = async () => { 25 try { 26 await Promise.all([steamUpdateNowPlaying(), updateNowPlayingTrack()]); 27 } catch (err) { 28 console.log(`error while updating: ${err}`); 29 } 30}; 31const refreshContent = async () => { 32 try { 33 await Promise.all([updateLastPosts(), _fetchEntries(), updateCommits(), sendAllMetrics()]); 34 } catch (err) { 35 console.log(`error while updating: ${err}`); 36 } 37}; 38 39await Promise.all([updateNowPlaying(), refreshContent()]); 40 41const scheduler = new ToadScheduler(); 42scheduler.addSimpleIntervalJob( 43 new SimpleIntervalJob( 44 { seconds: 5 }, 45 new AsyncTask('updateNowPlaying task', updateNowPlaying, (err) => 46 console.log(`error while updateNowPlaying: ${err}`) 47 ) 48 ) 49); 50scheduler.addSimpleIntervalJob( 51 new SimpleIntervalJob( 52 { seconds: 30 }, 53 new AsyncTask('refreshContent task', refreshContent, (err) => 54 console.log(`error while refreshContent: ${err}`) 55 ) 56 ) 57); 58 59const corsHandler = (allowedOrigins = ['*']) => { 60 return async ({ event, resolve }: Parameters<Handle>[0]) => { 61 const origin = event.request.headers.get('origin'); 62 63 const corsHeaders: Record<string, string> = { 64 'Access-Control-Allow-Methods': 'GET, POST, PUT, DELETE, PATCH, OPTIONS', 65 'Access-Control-Allow-Headers': 'Content-Type, Authorization', 66 }; 67 68 if (allowedOrigins.includes('*')) 69 corsHeaders['Access-Control-Allow-Origin'] = '*'; 70 else if (origin && allowedOrigins.includes(origin)) { 71 corsHeaders['Access-Control-Allow-Origin'] = origin; 72 corsHeaders['Access-Control-Allow-Credentials'] = 'true'; 73 } 74 75 if (event.request.method === 'OPTIONS') 76 return new Response(null, { headers: corsHeaders }); 77 78 const response = await resolve(event); 79 80 Object.entries(corsHeaders).forEach(([key, value]) => { 81 response.headers.set(key, value); 82 }); 83 84 return response; 85 }; 86} 87 88const handler = async ({ event, resolve }: Parameters<Handle>[0]) => { 89 notifyDarkVisitors(event.url, event.request); // no await so it doesnt block 90 91 const isPrefetch = () => { 92 return ( 93 event.request.headers.get('Sec-Purpose')?.includes('prefetch') || 94 event.request.headers.get('Purpose')?.includes('prefetch') || 95 event.request.headers.get('x-purpose')?.includes('preview') || 96 event.request.headers.get('x-moz')?.includes('prefetch') 97 ); 98 }; 99 const isApi = () => { 100 return event.url.pathname.startsWith('/_api'); 101 }; 102 const isRss = () => { 103 return event.url.pathname.endsWith('/_rss'); 104 }; 105 106 // block any requests if the user agent is disallowed by our robots txt 107 const isFakeVisit = 108 (await testUa(event.url.toString(), event.request.headers.get('user-agent') ?? '')) === false; 109 if (isFakeVisit) { 110 pushMetric({ gazesys_visit_fake_total: await incrementFakeVisitCount() }); 111 throw error(403, 'get a better user agent silly'); 112 } 113 114 // only push metric if legit page visit (still want rss to count here though) 115 const isPageVisit = !isApi() && !isPrefetch(); 116 if (isPageVisit) pushMetric({ gazesys_visit_real_total: await incrementLegitVisitCount() }); 117 118 // only add visitors if its a "legit" page visit 119 let id = null; 120 let valid = false; 121 if (isPageVisit && !isRss()) { 122 id = addLastVisitor(event.request, event.cookies); 123 valid = await incrementVisitCount(event.request, event.cookies); 124 } 125 126 // actually resolve event 127 const resp = await resolve(event); 128 // remove visitors if it was a 404 129 if (resp.status === 404) { 130 if (id !== null) removeLastVisitor(id); 131 if (valid) decrementVisitCount(); 132 } 133 134 return resp; 135}; 136 137const allowedOrigins = [ 138 "https://gaze.systems", 139 "https://ptr.pet", 140 "https://poor.dog", 141]; 142export const handle = sequence(corsHandler(allowedOrigins), handler);