Files
website/src/routes/api/spotify/connect/+server.ts
Stan Runge b757269151
All checks were successful
Deploy production / deploy (push) Successful in 2m37s
music: self-hosted scrobbler (Spotify poller, Last.fm + streaming-history importers, /trackers/music, homepage listening card)
- music schema: artists/albums/tracks (+album art), plays with source + dedupe, now_playing,
  spotify_auth, import_state; plays_deduped view hides Last.fm scrobbles Spotify also has
- in-app Spotify poller (60s, leased) started from hooks init; no new role or env needed
- /api/spotify/connect + callback (owner only), /trackers/music public stats
- scripts: music-poll, music-import-lastfm (resumable), music-import-history
- deploy/music-collector: optional host timer with its own role
2026-10-24 15:57:40 +00:00

30 lines
1.1 KiB
TypeScript

import { SPOTIFY_CLIENT_ID } from '$app/env/private';
import { error, redirect } from '@sveltejs/kit';
import { requireOwner } from '#lib/server/owner.js';
import {
authorizeUrl,
CALLBACK_PATH,
publicOrigin,
STATE_COOKIE
} from '#lib/server/music/oauth.js';
import type { RequestHandler } from './$types';
// Owner only: start the Spotify Authorization Code flow for the listening tracker.
export const GET: RequestHandler = (event) => {
requireOwner(event);
const { url, cookies } = event;
// The state cookie must be set on the host Spotify redirects back to.
if (url.hostname === 'www.stanrunge.dev')
redirect(302, 'https://stanrunge.dev/api/spotify/connect');
if (!SPOTIFY_CLIENT_ID) error(503, 'Spotify is not configured on this server.');
const state = Buffer.from(crypto.getRandomValues(new Uint8Array(32))).toString('base64url');
cookies.set(STATE_COOKIE, state, {
path: '/api/spotify',
httpOnly: true,
secure: true,
sameSite: 'lax',
maxAge: 600
});
redirect(302, authorizeUrl(SPOTIFY_CLIENT_ID, `${publicOrigin(url)}${CALLBACK_PATH}`, state));
};