This commit is contained in:
75
src/routes/projects/spotify-beatmap-finder/+page.server.ts
Normal file
75
src/routes/projects/spotify-beatmap-finder/+page.server.ts
Normal file
@@ -0,0 +1,75 @@
|
||||
import type { Actions } from './$types';
|
||||
import { fail } from '@sveltejs/kit';
|
||||
import { parseSpotifyInput } from '$lib/map-finder/input';
|
||||
import type { TrackMatchResult } from '$lib/map-finder/types';
|
||||
import { getSpotifyMetadata } from '$lib/server/spotify';
|
||||
import { getOsuMaps, MATCH_CONCURRENCY } from '$lib/server/osu';
|
||||
import { ApiError, publicError, logApiError, mapConcurrent } from '$lib/server/finder-http';
|
||||
import { acquireSearch } from '$lib/server/finder-limit';
|
||||
export const actions: Actions = {
|
||||
default: async ({ request, fetch, getClientAddress }) => {
|
||||
const data = await request.formData();
|
||||
const value = data.get('query');
|
||||
const query = typeof value === 'string' ? value.trim().slice(0, 501) : '';
|
||||
let input;
|
||||
try {
|
||||
input = parseSpotifyInput(query);
|
||||
} catch (error) {
|
||||
return fail(400, { query, error: (error as Error).message });
|
||||
}
|
||||
if (input.kind === 'unsupported')
|
||||
return fail(400, {
|
||||
query,
|
||||
error: `Unsupported Spotify resource: ${input.resource}. Use a track, playlist, or album.`
|
||||
});
|
||||
let address: string;
|
||||
try {
|
||||
address = getClientAddress();
|
||||
} catch {
|
||||
address = 'shared-unknown';
|
||||
}
|
||||
const release = acquireSearch(
|
||||
address,
|
||||
input.kind === 'playlist' || input.kind === 'album' ? 6 : 1
|
||||
);
|
||||
if (!release)
|
||||
return fail(429, {
|
||||
query,
|
||||
error:
|
||||
'Site search limit reached. Wait up to 10 minutes, and finish any pending search before trying again.'
|
||||
});
|
||||
try {
|
||||
const metadata = await getSpotifyMetadata(fetch, input);
|
||||
const results = await mapConcurrent(
|
||||
metadata.tracks,
|
||||
MATCH_CONCURRENCY,
|
||||
async (track): Promise<TrackMatchResult> => {
|
||||
try {
|
||||
const matches = await getOsuMaps(fetch, track);
|
||||
return {
|
||||
track,
|
||||
matches,
|
||||
status: matches.some((m) => m.confidence !== 'low') ? 'matched' : 'no_match'
|
||||
};
|
||||
} catch (error) {
|
||||
logApiError(error);
|
||||
return { track, matches: [], status: 'error', error: publicError(error) };
|
||||
}
|
||||
}
|
||||
);
|
||||
return { query, results, collection: metadata.collection, truncated: metadata.truncated };
|
||||
} catch (error) {
|
||||
logApiError(error);
|
||||
return fail(
|
||||
error instanceof ApiError && error.status === 429
|
||||
? 429
|
||||
: error instanceof ApiError && [403, 404].includes(error.status)
|
||||
? 404
|
||||
: 502,
|
||||
{ query, error: publicError(error) }
|
||||
);
|
||||
} finally {
|
||||
release();
|
||||
}
|
||||
}
|
||||
};
|
||||
Reference in New Issue
Block a user