feat: align Spotify widget with centered content and clean diagnostic code

This commit is contained in:
ssbg04 committed 2026-07-07 21:53:05 +08:00
1 parent 70b627a2e4
commit 880483d448
3 files changed
+89 -56

No files matched your search

+50
View File
@@ -0,0 +1,50 @@
const client_id = "ee972078e4f747f59dce341b0a493986";
const client_secret = "c068836397cb4b22840ae4e6249aa3d0";
const redirect_uri = "https://sisibigi.vercel.app/callback";
const code = process.argv[2];
if (!code) {
console.error("\x1b[31mError: Please provide your Spotify authorization code as an argument.\x1b[0m");
console.log("\nUsage:\n node scripts/get-refresh-token.js <YOUR_AUTH_CODE>");
console.log("\nTo get a fresh code, visit:\n https://accounts.spotify.com/authorize?client_id=ee972078e4f747f59dce341b0a493986&response_type=code&redirect_uri=https://sisibigi.vercel.app/callback&scope=user-read-currently-playing%20user-read-playback-state\n");
process.exit(1);
}
const basic = Buffer.from(`${client_id}:${client_secret}`).toString('base64');
const TOKEN_ENDPOINT = `https://accounts.spotify.com/api/token`;
console.log("Trading authorization code for Spotify tokens...");
fetch(TOKEN_ENDPOINT, {
method: 'POST',
headers: {
Authorization: `Basic ${basic}`,
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({
grant_type: 'authorization_code',
code: code.trim(),
redirect_uri,
}),
})
.then(async (response) => {
const text = await response.text();
if (!response.ok) {
console.error(`\x1b[31mSpotify Token Exchange Failed (${response.status}):\x1b[0m`, text);
process.exit(1);
}
const data = JSON.parse(text);
console.log("\n\x1b[32m✔ Success! Here are your tokens:\x1b[0m");
console.log("\n----------------------------------------");
console.log(`\x1b[36mAccess Token (Expires in 1 hour):\x1b[0m\n${data.access_token}\n`);
console.log(`\x1b[36mRefresh Token (Save this!):\x1b[0m\n${data.refresh_token}`);
console.log("----------------------------------------");
console.log("\n\x1b[33mInstructions:\x1b[0m");
console.log("1. Copy the Refresh Token (starts with AQ... or different).");
console.log("2. Paste it into your .env file as: SPOTIFY_REFRESH_TOKEN=...");
console.log("3. Add it to your Vercel Project environment variables and trigger a redeploy.\n");
})
.catch((err) => {
console.error("\x1b[31mRequest Error:\x1b[0m", err);
});
+12 -8
View File
@@ -99,14 +99,16 @@ export default function SpotifyWidget() {
}, [isPlaying, isApiActive]);
return (
<motion.div
className="fixed top-[74px] sm:top-[88px] left-6 sm:left-8 z-40 select-none cursor-pointer flex items-center pointer-events-auto"
onMouseEnter={() => setIsHovered(true)}
onMouseLeave={() => setIsHovered(false)}
initial={{ opacity: 0, y: -20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ type: "spring", stiffness: 260, damping: 25, delay: 0.8 }}
>
<div className="fixed top-[82px] sm:top-[98px] left-0 w-full z-40 pointer-events-none flex justify-start">
<div className="max-w-7xl mx-auto px-6 sm:px-8 lg:px-12 w-full flex justify-start">
<motion.div
className="select-none cursor-pointer flex items-center pointer-events-auto"
onMouseEnter={() => setIsHovered(true)}
onMouseLeave={() => setIsHovered(false)}
initial={{ opacity: 0, y: -20 }}
animate={{ opacity: 1, y: 0 }}
transition={{ type: "spring", stiffness: 260, damping: 25, delay: 0.8 }}
>
<motion.div
layout
className="glass-card border border-white/20 bg-white/5 backdrop-blur-xl rounded-full p-2 flex items-center gap-3 shadow-lg shadow-black/10 overflow-hidden"
@@ -203,5 +205,7 @@ export default function SpotifyWidget() {
</div>
</motion.div>
</motion.div>
</div>
</div>
);
}
+27 -48
View File
@@ -5,15 +5,6 @@ const client_id = import.meta.env.SPOTIFY_CLIENT_ID || process.env.SPOTIFY_CLIEN
const client_secret = import.meta.env.SPOTIFY_CLIENT_SECRET || process.env.SPOTIFY_CLIENT_SECRET || '';
const refresh_token = import.meta.env.SPOTIFY_REFRESH_TOKEN || process.env.SPOTIFY_REFRESH_TOKEN || '';
console.log('Spotify Config Diagnostic:', {
clientIdPresent: !!client_id,
clientIdLength: client_id.length,
clientSecretPresent: !!client_secret,
clientSecretLength: client_secret.length,
refreshTokenPresent: !!refresh_token,
refreshTokenLength: refresh_token.length,
});
const basic = Buffer.from(`${client_id}:${client_secret}`).toString('base64');
const NOW_PLAYING_ENDPOINT = `https://api.spotify.com/v1/me/player/currently-playing`;
const TOKEN_ENDPOINT = `https://accounts.spotify.com/api/token`;
@@ -21,56 +12,44 @@ const TOKEN_ENDPOINT = `https://accounts.spotify.com/api/token`;
// Helper to retrieve a fresh Spotify access token using the refresh token
async function getAccessToken() {
if (!client_id || !client_secret || !refresh_token) {
throw new Error('Spotify API keys are missing in env.');
console.error('Spotify API keys are missing in env.');
return null;
}
const response = await fetch(TOKEN_ENDPOINT, {
method: 'POST',
headers: {
Authorization: `Basic ${basic}`,
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({
grant_type: 'refresh_token',
refresh_token,
}),
});
try {
const response = await fetch(TOKEN_ENDPOINT, {
method: 'POST',
headers: {
Authorization: `Basic ${basic}`,
'Content-Type': 'application/x-www-form-urlencoded',
},
body: new URLSearchParams({
grant_type: 'refresh_token',
refresh_token,
}),
});
if (!response.ok) {
const errText = await response.text();
throw new Error(`Spotify token error: ${response.status} - ${errText}`);
if (!response.ok) {
const errText = await response.text();
console.error('Failed to fetch Spotify access token:', response.status, errText);
return null;
}
const data = await response.json();
return data.access_token;
} catch (error) {
console.error('Error fetching Spotify access token:', error);
return null;
}
const data = await response.json();
return data.access_token;
}
// Server-side GET API handler
export const GET: APIRoute = async () => {
let token = null;
let tokenError = null;
try {
token = await getAccessToken();
} catch (error: any) {
tokenError = error.message || String(error);
}
const token = await getAccessToken();
if (!token) {
return new Response(
JSON.stringify({
isPlaying: false,
message: 'Spotify integration not configured or credentials missing.',
debug: {
clientIdPresent: !!client_id,
clientIdLength: client_id.length,
clientSecretPresent: !!client_secret,
clientSecretLength: client_secret.length,
refreshTokenPresent: !!refresh_token,
refreshTokenLength: refresh_token.length,
tokenError
}
}),
JSON.stringify({ isPlaying: false, message: 'Spotify integration not configured or credentials missing.' }),
{
status: 200,
headers: {