Public
Script
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
import { getSpotifyAccessToken } from "https://esm.town/v/dthyresson/getSpotifyAccessToken";
import { blob } from "https://esm.town/v/std/blob";
import { email } from "https://esm.town/v/std/email";
import { kebabCase } from "npm:lodash-es";
const SPOTIFY_TRACK_KEY_PREFIX = "spotify_track";
type SpotifyTrackUrlFormat = "web" | "app";
export type SpotifyTrackUrlOptions = {
format?: SpotifyTrackUrlFormat;
};
export function buildSpotifyTrackKey(artist: string, title: string) {
const key = `${SPOTIFY_TRACK_KEY_PREFIX}_artist:${kebabCase(artist)}_title:${kebabCase(title)}`.toLowerCase();
console.debug("buildSpotifyTrackKey", artist, title, key);
return key;
}
export function spotifyTrackUrl(track, format: SpotifyTrackUrlFormat) {
if (!track) return;
if (format === "app") {
return spotifyTrackAppLink(track);
}
const url = `https://open.spotify.com/track/${track.id}`;
// console.log("spotifyTrackUrl", url);
return url;
}
export function spotifyTrackAppLink(track) {
if (!track) return;
const url = `spotify://track/${track.id}`;
// console.log("spotifyTrackAppLink", url);
return url;
}
async function cacheTrack(spotifyTrackKey: string, track: any) {
console.debug(`Caching track ${spotifyTrackKey}`);
await blob.setJSON(spotifyTrackKey, track);
if (track.id) {
const artist = track.artists[0].name;
const title = track.name;
const key = buildSpotifyTrackKey(artist, title);
console.debug(`Caching track ${key}`);
await blob.setJSON(key, track);
await blob.setJSON(`${SPOTIFY_TRACK_KEY_PREFIX}_id:${track.id}`, track);
}
}
export async function getSpotifyTrackUrl(artist: string, title: string, options?: SpotifyTrackUrlOptions) {
const format = options?.format || "web";
const spotifyTrackKey = buildSpotifyTrackKey(artist, title);
const cachedTrack = await blob.getJSON(spotifyTrackKey);
if (cachedTrack) {
console.debug(`Found track in cache for ${spotifyTrackKey}`);
const result = { trackUrl: spotifyTrackUrl(cachedTrack, format), ...cachedTrack };
// console.debug(result);
return result;
}
const accessToken = await getSpotifyAccessToken();
const query = `track:${title} artist:${artist}`;
const encodedQuery = encodeURIComponent(query);
// Search for the track
const response = await fetch(`https://api.spotify.com/v1/search?q=${query}&type=track`, {
headers: {
"Authorization": `Bearer ${accessToken.access_token}`,
},
});
if (response.ok) {
const searchData = await response.json();
const track = searchData.tracks.items[0];
if (track) {
await cacheTrack(spotifyTrackKey, track);
}
const trackUrl = spotifyTrackUrl(track, format);
if (!trackUrl) {
const text = `Missing track id: ${artist} ${title}`;
console.error(text);
await email({ subject: "Error in getSpotifyTrackUrl", text });
return;
}
const result = { trackUrl, ...track };
// console.debug(result);
return result;
}
Val Town is a social website to write and deploy JavaScript.
Build APIs and schedule functions from your browser.
Comments
Nobody has commented on this val yet: be the first!
July 29, 2024