Aurora SpotiRip desktop and web app
- Spotify playlist, library, album and artist browsing with in-app playback - Song, playlist and album downloads via spotdl with YouTube and Bandcamp fallbacks - Electron desktop app (castLabs Widevine) with a permanent sidebar layout - Linux and Windows packaging scripts
This commit is contained in:
@@ -0,0 +1,57 @@
|
||||
import superjson from "superjson";
|
||||
import { schema, type OutputType } from "./lyrics_POST.schema";
|
||||
|
||||
type LrclibResult = {
|
||||
plainLyrics?: string | null;
|
||||
syncedLyrics?: string | null;
|
||||
instrumental?: boolean;
|
||||
};
|
||||
|
||||
function delay(ms: number) {
|
||||
return new Promise((resolve) => setTimeout(resolve, ms));
|
||||
}
|
||||
|
||||
export async function handle(request: Request) {
|
||||
try {
|
||||
const input = schema.parse(superjson.parse(await request.text()));
|
||||
const params = new URLSearchParams({
|
||||
artist_name: input.artist,
|
||||
track_name: input.title,
|
||||
});
|
||||
if (input.album) params.set("album_name", input.album);
|
||||
if (input.durationMs) {
|
||||
params.set("duration", String(Math.round(input.durationMs / 1000)));
|
||||
}
|
||||
let response: Response | undefined;
|
||||
for (let attempt = 0; attempt < 2; attempt += 1) {
|
||||
response = await fetch(`https://lrclib.net/api/get?${params.toString()}`, {
|
||||
headers: { "User-Agent": "Aurora-SpotiRip/1.0" },
|
||||
});
|
||||
if (response.status !== 429 || attempt > 0) break;
|
||||
const retryAfter = Number(response.headers.get("retry-after") || 1);
|
||||
await delay(Math.min(5000, Math.max(500, retryAfter * 1000)));
|
||||
}
|
||||
if (!response) {
|
||||
throw new Error("Lyrics service did not respond.");
|
||||
}
|
||||
if (response.status === 404) {
|
||||
return new Response(superjson.stringify({} satisfies OutputType));
|
||||
}
|
||||
if (!response.ok) {
|
||||
return new Response(
|
||||
superjson.stringify({ error: `Lyrics service returned HTTP ${response.status}.` }),
|
||||
{ status: 502 },
|
||||
);
|
||||
}
|
||||
const result = (await response.json()) as LrclibResult;
|
||||
const output: OutputType = {
|
||||
plain: result.plainLyrics || undefined,
|
||||
synced: result.syncedLyrics || undefined,
|
||||
instrumental: Boolean(result.instrumental),
|
||||
};
|
||||
return new Response(superjson.stringify(output));
|
||||
} catch (error) {
|
||||
const message = error instanceof Error ? error.message : "Unable to load lyrics.";
|
||||
return new Response(superjson.stringify({ error: message }), { status: 400 });
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user