feat: align Spotify widget with centered content and clean diagnostic code
This commit is contained in:
1 parent
70b627a2e4
commit
880483d448
3 files changed
+89
-56
No files matched your search
@@ -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);
|
||||
});
|
||||
@@ -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>
|
||||
);
|
||||
}
|
||||
@@ -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: {
|
||||
|
||||
Reference in new issue
Block a user