+19
-32
src/lib/lastfm.ts
+19
-32
src/lib/lastfm.ts
···
9
9
name: string;
10
10
artist: string;
11
11
album: string;
12
-
image: string | null;
12
+
images: {
13
+
mb: string | null;
14
+
yt: string | null;
15
+
};
13
16
link: string | null;
14
17
when: number;
15
18
status: 'playing' | 'played';
···
27
30
};
28
31
29
32
const getTrackCoverArt = (releaseMbId: string | null | undefined, originUrl: string | null | undefined) => {
30
-
if (releaseMbId) return `https://coverartarchive.org/release/${releaseMbId}/front-250`;
31
-
32
-
if (!originUrl) return null;
33
-
let videoId: string | null = null;
33
+
let mb: string | null = null;
34
+
let yt: string | null = null;
35
+
36
+
if (releaseMbId) mb = `https://coverartarchive.org/release/${releaseMbId}/front-250`;
34
37
35
38
try {
36
-
if (originUrl.includes('youtube.com') || originUrl.includes('music.youtube.com')) {
37
-
videoId = new URL(originUrl).searchParams.get('v');
38
-
} else if (originUrl.includes('youtu.be')) {
39
-
videoId = originUrl.split('youtu.be/')[1]?.split('?')[0];
39
+
if (originUrl) {
40
+
let videoId: string | null = null;
41
+
if (originUrl.includes('youtube.com') || originUrl.includes('music.youtube.com')) {
42
+
videoId = new URL(originUrl).searchParams.get('v');
43
+
} else if (originUrl.includes('youtu.be')) {
44
+
videoId = originUrl.split('youtu.be/')[1]?.split('?')[0];
45
+
}
46
+
if (videoId) yt = `https://img.youtube.com/vi/${videoId}/mqdefault.jpg`;
40
47
}
41
48
} catch {
42
-
return null;
43
49
}
44
50
45
-
if (!videoId) return null;
46
-
return `https://img.youtube.com/vi/${videoId}/mqdefault.jpg`;
51
+
return { mb, yt };
47
52
};
48
53
49
54
const joinArtists = (artists: any[]) => {
···
66
71
if (statusData.value?.item) {
67
72
track = statusData.value.item;
68
73
if (track.playedTime) when = new Date(track.playedTime).getTime();
69
-
status = 'playing';
74
+
status = (Date.now() / 1000) >= track.expiry ? 'played' : 'playing';
70
75
}
71
76
}
72
77
} catch (err) {
73
78
console.log('could not fetch teal status:', err);
74
79
}
75
80
76
-
if (!track) {
77
-
try {
78
-
const playRes = await fetch(
79
-
`${PDS}/xrpc/com.atproto.repo.listRecords?repo=${DID}&collection=fm.teal.alpha.feed.play&limit=1`
80
-
);
81
-
if (playRes.ok) {
82
-
const playData = await playRes.json();
83
-
if (playData.records.length > 0) {
84
-
track = playData.records[0].value;
85
-
if (track.playedTime) when = new Date(track.playedTime).getTime();
86
-
status = 'played';
87
-
}
88
-
}
89
-
} catch (err) {
90
-
console.log('could not fetch teal history:', err);
91
-
}
92
-
}
93
-
94
81
if (!track) return;
95
82
96
83
const data: LastTrack = {
97
84
name: track.trackName,
98
85
artist: joinArtists(track.artists) ?? 'Unknown Artist',
99
86
album: track.releaseName ?? 'Unknown Album',
100
-
image: getTrackCoverArt(track.releaseMbId, track.originUrl),
87
+
images: getTrackCoverArt(track.releaseMbId, track.originUrl),
101
88
link: track.originUrl ?? null,
102
89
when: when,
103
90
status: status
+19
-15
src/routes/(site)/+page.svelte
+19
-15
src/routes/(site)/+page.svelte
···
153
153
</div>
154
154
{/if}
155
155
{#if data.lastTrack}
156
+
{@const images = data.lastTrack.images}
157
+
{@const initialUrl = images.mb ?? images.yt}
156
158
<div class="flex flex-row gap-0.5 m-1.5 border-4 border-double bg-ralsei-black">
157
159
<!-- svelte-ignore a11y_missing_attribute -->
158
-
{#if data.lastTrack.image}
159
-
<img
160
-
class="border-4 w-[4.5rem] h-[4.5rem] object-cover"
161
-
style="border-style: none double none none;"
162
-
src={data.lastTrack.image}
163
-
title={data.lastTrack.album}
164
-
/>
165
-
{:else}
166
-
<img
167
-
class="border-4 w-[4.5rem] h-[4.5rem] p-2"
168
-
style="border-style: none double none none; image-rendering: pixelated;"
169
-
src="/icons/cd_audio.webp"
170
-
title={data.lastTrack.album}
171
-
/>
172
-
{/if}
160
+
<img
161
+
class="border-4 w-[4.5rem] h-[4.5rem] {initialUrl ? 'object-cover' : 'p-2'}"
162
+
style="border-style: none double none none; {initialUrl ? '' : 'image-rendering: pixelated;'}"
163
+
src={initialUrl ?? '/icons/cd_audio.webp'}
164
+
title={data.lastTrack.album}
165
+
onerror={(e) => {
166
+
const img = e.currentTarget as HTMLImageElement;
167
+
if (images.mb && img.src === images.mb && images.yt)
168
+
img.src = images.yt;
169
+
else {
170
+
img.src = '/icons/cd_audio.webp';
171
+
img.classList.remove('object-cover');
172
+
img.classList.add('p-2');
173
+
img.style.imageRendering = 'pixelated';
174
+
}
175
+
}}
176
+
/>
173
177
<div class="flex flex-col max-w-[60ch] p-2">
174
178
<p
175
179
class="text-shadow-green text-ralsei-green-light text-sm text-ellipsis text-nowrap overflow-hidden max-w-[50ch]"