Personal Site
1---
2import { SPOTIFY_CLIENT_SECRET } from "astro:env/server";
3import { SPOTIFY_CLIENT_ID, SPOTIFY_REDIRECT_URI } from "astro:env/server";
4import fs from "node:fs/promises";
5
6// make a 404 if accidentally left in prod
7if (import.meta.env.PROD) return Astro.redirect("/404", 404);
8
9const userAuthCode = Astro.url.searchParams.get("code") ?? undefined;
10
11if (userAuthCode) {
12 fetch("https://accounts.spotify.com/api/token", {
13 method: "post",
14
15 headers: {
16 "content-type": "application/x-www-form-urlencoded",
17 Authorization:
18 "Basic " +
19 Buffer.from(SPOTIFY_CLIENT_ID + ":" + SPOTIFY_CLIENT_SECRET).toString(
20 "base64",
21 ),
22 },
23
24 body: new URLSearchParams({
25 code: userAuthCode,
26 redirect_uri: SPOTIFY_REDIRECT_URI,
27 grant_type: "authorization_code",
28 }).toString(),
29 })
30 .then((res) => res.json())
31 .then((token) => token.refresh_token)
32 .then((token) =>
33 fs.writeFile("./.refreshToken", String(token), {
34 encoding: "utf-8",
35 }),
36 )
37 .catch((err) => console.error(err));
38}
39
40const href = `https://accounts.spotify.com/authorize?response_type=code&client_id=${SPOTIFY_CLIENT_ID}&scope=user-read-currently-playing user-top-read&redirect_uri=${SPOTIFY_REDIRECT_URI}`;
41---
42
43<p>
44 This endpoint is avaliable at /callback when the _ is removed from the start
45 of the filename.
46</p>
47
48<p>This endpoint is to gain the first access token and refresh token.</p>
49
50<p>
51 Opening the endpoint with no query parameters will provide a link to authorize
52 the configured application
53</p>
54
55<p>
56 This should redirect back here where it gains an access token and shows a
57 sucess method
58</p>
59
60<p>The refresh token is automatically stored for later requests.</p>
61
62<p>
63 <a {href}>Get Authorized</a>
64</p>
65
66<p>
67 <!-- {
68 userAuthCode &&
69 (userAccessToken ? (
70 <>
71 Authenticated Successfully!
72 <code>{userAccessToken}</code>
73 </>
74 ) : (
75 <>Authentication Failed or was already used</>
76 ))
77 } -->
78</p>
79
80<style>
81 p,
82 code {
83 max-width: 40ch;
84 }
85
86 code {
87 word-wrap: break-word;
88 }
89</style>