your personal website on atproto - mirror
blento.app
1import { query, getRequestEvent } from '$app/server';
2import { env } from '$env/dynamic/private';
3import { createCache } from '$lib/cache';
4
5const LASTFM_API_URL = 'https://ws.audioscrobbler.com/2.0/';
6
7const CACHE_TTL: Record<string, number> = {
8 'user.getRecentTracks': 15 * 60,
9 'user.getTopTracks': 60 * 60,
10 'user.getTopAlbums': 60 * 60,
11 'user.getInfo': 12 * 60 * 60
12};
13
14export const fetchLastFM = query(
15 'unchecked',
16 async ({
17 method,
18 user,
19 period = '7day',
20 limit = '50'
21 }: {
22 method: string;
23 user: string;
24 period?: string;
25 limit?: string;
26 }) => {
27 const apiKey = env?.LASTFM_API_KEY;
28 if (!apiKey) return undefined;
29
30 const { platform } = getRequestEvent();
31 const cache = createCache(platform);
32
33 const cacheKey = `${method}:${user}:${period}:${limit}`;
34 const cached = await cache?.get('lastfm', cacheKey);
35 if (cached) return JSON.parse(cached);
36
37 const params = new URLSearchParams({
38 method,
39 user,
40 api_key: apiKey,
41 format: 'json',
42 limit
43 });
44
45 if (method === 'user.getTopTracks' || method === 'user.getTopAlbums') {
46 params.set('period', period);
47 }
48
49 const response = await fetch(`${LASTFM_API_URL}?${params}`);
50 if (!response.ok) return undefined;
51
52 const data = await response.json();
53 if (data.error) return undefined;
54
55 const ttl = CACHE_TTL[method] || 60 * 60;
56 await cache?.put('lastfm', cacheKey, JSON.stringify(data), ttl);
57 return data;
58 }
59);