Final commit
This commit is contained in:
parent
91fffb3294
commit
c35e0716af
372 changed files with 16591 additions and 1 deletions
15
backend/routes/get-new-suggest.ts
Normal file
15
backend/routes/get-new-suggest.ts
Normal file
|
@ -0,0 +1,15 @@
|
|||
import { searchSpotifyTracks } from "../spotify-api.ts";
|
||||
import { GetNewSuggestInput, GetNewSuggestOutput } from "../types/api.ts";
|
||||
import { generateVibes } from "../ai-suggestion.ts";
|
||||
|
||||
export async function getNewSuggestion(
|
||||
params: GetNewSuggestInput,
|
||||
): Promise<GetNewSuggestOutput> {
|
||||
const ai_suggestion = await generateVibes(params);
|
||||
|
||||
const suggestionResults = await searchSpotifyTracks(
|
||||
ai_suggestion.songs,
|
||||
);
|
||||
|
||||
return { songs: suggestionResults };
|
||||
}
|
18
backend/routes/get-song.ts
Normal file
18
backend/routes/get-song.ts
Normal file
|
@ -0,0 +1,18 @@
|
|||
import { generateSongs } from "../ai-selector.ts";
|
||||
import { searchSpotifyTracks } from "../spotify-api.ts";
|
||||
import { GetSongsTextOutput, GetSongsTextParams } from "../types/api.ts";
|
||||
|
||||
export async function getSong(
|
||||
params: GetSongsTextParams,
|
||||
): Promise<GetSongsTextOutput> {
|
||||
const ai_response = await generateSongs(params.prompt, params.rules);
|
||||
if (ai_response.type == "error") {
|
||||
return ai_response;
|
||||
}
|
||||
|
||||
const spotifyResults = await searchSpotifyTracks(
|
||||
ai_response.songs,
|
||||
);
|
||||
|
||||
return { type: "success", songs: spotifyResults };
|
||||
}
|
87
backend/routes/get-track.ts
Normal file
87
backend/routes/get-track.ts
Normal file
|
@ -0,0 +1,87 @@
|
|||
import { SpotifyTrack } from "../types/spotify.ts";
|
||||
import { getSpotifyAccessToken } from "../spotify-api.ts";
|
||||
import { assert } from "jsr:@std/assert/assert";
|
||||
|
||||
// Simple in-memory cache for track objects by ID
|
||||
const trackCache = new Map<string, SpotifyTrack>();
|
||||
|
||||
/**
|
||||
* Inner function that performs the actual API call without retries.
|
||||
*/
|
||||
async function fetchSpotifyTrackById(trackId: string): Promise<SpotifyTrack> {
|
||||
const accessToken = await getSpotifyAccessToken();
|
||||
const url = `https://api.spotify.com/v1/tracks/${trackId}?market=US`;
|
||||
|
||||
const response = await fetch(url, {
|
||||
headers: {
|
||||
"Authorization": `Bearer ${accessToken}`,
|
||||
},
|
||||
});
|
||||
|
||||
if (!response.ok) {
|
||||
throw new Error(
|
||||
`Failed to fetch track: ${response.status} ${await response.text()}`,
|
||||
);
|
||||
}
|
||||
|
||||
const track: SpotifyTrack = await response.json();
|
||||
|
||||
// Cache the result
|
||||
trackCache.set(trackId, track);
|
||||
|
||||
return track;
|
||||
}
|
||||
|
||||
/**
|
||||
* Fetches a Spotify track by its ID, with caching.
|
||||
* Returns the full SpotifyTrack object.
|
||||
*/
|
||||
export async function getSpotifyTrackById(
|
||||
trackId: string,
|
||||
): Promise<SpotifyTrack> {
|
||||
// Check cache first
|
||||
if (trackCache.has(trackId)) {
|
||||
return trackCache.get(trackId)!;
|
||||
}
|
||||
|
||||
const maxRetries = 10;
|
||||
let lastError: Error;
|
||||
|
||||
for (let attempt = 1; attempt <= maxRetries; attempt++) {
|
||||
try {
|
||||
return await fetchSpotifyTrackById(trackId);
|
||||
} catch (error) {
|
||||
lastError = error as Error;
|
||||
if (attempt === maxRetries) {
|
||||
throw Error(`Attempt ${attempt}: ${lastError}`);
|
||||
}
|
||||
// Optional: add delay between retries
|
||||
await new Promise((resolve) => setTimeout(resolve, 1000 * attempt));
|
||||
}
|
||||
}
|
||||
|
||||
throw lastError!;
|
||||
}
|
||||
|
||||
Deno.test("getSpotifyTrackById basic", async () => {
|
||||
// Example: Blinding Lights by The Weeknd
|
||||
const trackId = "2EqlS6tkEnglzr7tkKAAYD";
|
||||
|
||||
// First call (should fetch from API)
|
||||
const track1 = await getSpotifyTrackById(trackId);
|
||||
assert(track1.id === trackId);
|
||||
assert(typeof track1.name === "string");
|
||||
assert(Array.isArray(track1.artists));
|
||||
|
||||
// Second call (should hit cache)
|
||||
const start = performance.now();
|
||||
const track2 = await getSpotifyTrackById(trackId);
|
||||
const elapsed = performance.now() - start;
|
||||
|
||||
console.log(track2);
|
||||
console.log("Second call elapsed:", elapsed, "ms");
|
||||
assert(track2.id === trackId);
|
||||
assert(typeof track2.name === "string");
|
||||
assert(Array.isArray(track2.artists));
|
||||
assert(elapsed < 10, `Second call took too long: ${elapsed}ms`);
|
||||
});
|
9
backend/routes/get-video.ts
Normal file
9
backend/routes/get-video.ts
Normal file
|
@ -0,0 +1,9 @@
|
|||
import { GetYoutubeInput, GetYoutubeOutput } from "../types/api.ts";
|
||||
import { searchYTVideo } from "../youtube-api.ts";
|
||||
|
||||
export async function getVids(
|
||||
params: GetYoutubeInput,
|
||||
): Promise<GetYoutubeOutput> {
|
||||
const videoId = await searchYTVideo(params);
|
||||
return { videoId };
|
||||
}
|
Loading…
Add table
Add a link
Reference in a new issue