Final commit

This commit is contained in:
Giovanni 2025-08-02 13:28:10 +02:00
parent 91fffb3294
commit c35e0716af
372 changed files with 16591 additions and 1 deletions

View 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 };
}

View 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 };
}

View 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`);
});

View 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 };
}