Kyouka commited on
Commit
ba606d9
·
verified ·
1 Parent(s): 4b3aeaa

Update index.js

Browse files
Files changed (1) hide show
  1. index.js +66 -177
index.js CHANGED
@@ -105,151 +105,8 @@ app.get('/proxy', async (req, res) => {
105
  }
106
  });
107
 
108
- // 1. Root route - redirect ke Spotify login
109
- app.get('/spotify', (req, res) => {
110
- const FRONTEND_URI = getFrontendUri(req);
111
- const REDIRECT_URI = `${FRONTEND_URI}/callback`;
112
-
113
- const scopes = [
114
- 'user-read-recently-played',
115
- 'user-read-playback-state',
116
- 'user-read-private',
117
- 'user-read-email'
118
- ];
119
-
120
- const queryParams = querystring.stringify({
121
- response_type: 'code',
122
- client_id: CLIENT_ID,
123
- scope: scopes.join(' '),
124
- redirect_uri: REDIRECT_URI,
125
- show_dialog: false,
126
- });
127
-
128
- res.redirect(`https://accounts.spotify.com/authorize?${queryParams}`);
129
- });
130
-
131
- // 2. Callback route
132
- app.get('/callback', async (req, res) => {
133
- const FRONTEND_URI = getFrontendUri(req);
134
- const REDIRECT_URI = `${FRONTEND_URI}/callback`;
135
-
136
- const { code, error } = req.query;
137
-
138
- if (error) {
139
- console.error('Spotify Auth Error:', error);
140
- return res.redirect(`${FRONTEND_URI}/error?message=${encodeURIComponent(error)}`);
141
- }
142
-
143
- try {
144
- // Get tokens
145
- const authResponse = await axios.post('https://accounts.spotify.com/api/token',
146
- querystring.stringify({
147
- grant_type: 'authorization_code',
148
- code,
149
- redirect_uri: REDIRECT_URI,
150
- }), {
151
- headers: {
152
- 'Content-Type': 'application/x-www-form-urlencoded',
153
- 'Authorization': 'Basic ' + Buffer.from(`${CLIENT_ID}:${CLIENT_SECRET}`).toString('base64'),
154
- },
155
- });
156
-
157
- const { access_token, refresh_token, expires_in } = authResponse.data;
158
-
159
- // Get user data to store in session
160
- const userData = await getUserData(access_token);
161
-
162
- // Store tokens and user data in cookies
163
- res.cookie('spotify_access', access_token, {
164
- httpOnly: true,
165
- secure: process.env.NODE_ENV === 'production',
166
- maxAge: expires_in * 1000
167
- });
168
-
169
- res.cookie('spotify_refresh', refresh_token, {
170
- httpOnly: true,
171
- secure: process.env.NODE_ENV === 'production'
172
- });
173
-
174
- res.cookie('spotify_user', JSON.stringify({
175
- id: userData.id,
176
- country: userData.country,
177
- display_name: userData.display_name
178
- }), {
179
- secure: process.env.NODE_ENV === 'production'
180
- });
181
-
182
- // Redirect to recently played with user ID
183
- res.redirect(`${FRONTEND_URI}/api/recently-played/json?user=${userData.id}`);
184
- } catch (err) {
185
- console.error('Callback Error:', err);
186
- res.redirect(`${FRONTEND_URI}/error?message=${encodeURIComponent('Authentication failed')}`);
187
- }
188
- });
189
-
190
- // 3. Recently Played JSON endpoint with market from user country
191
- app.get('/api/recently-played/json', async (req, res) => {
192
- const FRONTEND_URI = getFrontendUri(req);
193
- const accessToken = req.cookies.spotify_access;
194
- const userData = req.cookies.spotify_user ? JSON.parse(req.cookies.spotify_user) : null;
195
-
196
- if (!accessToken || !userData) {
197
- return res.redirect('/');
198
- }
199
-
200
- try {
201
- const limit = parseInt(req.query.limit) || 20;
202
- const params = { limit };
203
-
204
- // Add market parameter from user's country if available
205
- if (userData.country) {
206
- params.market = userData.country;
207
- }
208
-
209
- const response = await axios.get('https://api.spotify.com/v1/me/player/recently-played', {
210
- params,
211
- headers: { 'Authorization': `Bearer ${accessToken}` },
212
- });
213
-
214
- const tracks = response.data.items.map(item => ({
215
- played_at: item.played_at,
216
- track: {
217
- id: item.track.id,
218
- name: item.track.name,
219
- artists: item.track.artists.map(a => ({ id: a.id, name: a.name })),
220
- album: {
221
- id: item.track.album.id,
222
- name: item.track.album.name,
223
- images: item.track.album.images,
224
- release_date: item.track.album.release_date
225
- },
226
- duration_ms: item.track.duration_ms,
227
- preview_url: item.track.preview_url
228
- }
229
- }));
230
 
231
- res.json({
232
- status: 'success',
233
- user: {
234
- id: userData.id,
235
- display_name: userData.display_name,
236
- country: userData.country
237
- },
238
- data: tracks,
239
- count: tracks.length
240
- });
241
- } catch (error) {
242
- if (error.response?.status === 401) {
243
- return res.redirect('/');
244
- }
245
- res.status(500).json({
246
- error: 'Failed to fetch recently played tracks',
247
- details: error.response?.data || error.message
248
- });
249
- }
250
- });
251
 
252
- // 4. Current Playback State endpoint
253
  async function refreshAccessToken(refreshToken) {
254
  const response = await axios.post('https://accounts.spotify.com/api/token',
255
  querystring.stringify({
@@ -264,6 +121,7 @@ async function refreshAccessToken(refreshToken) {
264
  return response.data;
265
  }
266
 
 
267
  app.get('/api/current-playback', async (req, res) => {
268
  try {
269
  const userId = req.query.user;
@@ -373,50 +231,81 @@ app.get('/api/current-playback', async (req, res) => {
373
  }
374
  });
375
 
376
- // 5. User Profile endpoint
377
- app.get('/api/user-profile', async (req, res) => {
378
- const accessToken = req.cookies.spotify_access;
379
- const userData = req.cookies.spotify_user ? JSON.parse(req.cookies.spotify_user) : null;
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
380
 
381
- if (!accessToken || !userData) {
382
- return res.status(401).json({ error: 'Not authenticated' });
383
  }
384
 
385
  try {
386
- const response = await axios.get('https://api.spotify.com/v1/me', {
387
- headers: { 'Authorization': `Bearer ${accessToken}` },
388
- });
 
 
 
 
 
 
 
 
 
389
 
390
- const profileData = {
391
- id: response.data.id,
392
- display_name: response.data.display_name,
393
- email: response.data.email,
394
- country: response.data.country,
395
- followers: response.data.followers.total,
396
- product: response.data.product,
397
- images: response.data.images
 
 
 
 
 
 
 
 
398
  };
399
 
400
- res.json({
401
- status: 'success',
402
- data: profileData
403
- });
404
- } catch (error) {
405
- if (error.response?.status === 401) {
406
- return res.status(401).json({ error: 'Session expired' });
407
- }
408
- res.status(500).json({
409
- error: 'Failed to fetch user profile',
410
- details: error.response?.data || error.message
411
- });
412
  }
413
  });
414
 
415
- // Error handler
416
- app.use((err, req, res, next) => {
417
- console.error('Server Error:', err);
418
- res.status(500).json({ error: 'Internal server error' });
419
- });
420
 
421
  app.get('/pages', async (req, res) => {
422
  const targetUrl = req.query.url;
 
105
  }
106
  });
107
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
108
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
 
109
 
 
110
  async function refreshAccessToken(refreshToken) {
111
  const response = await axios.post('https://accounts.spotify.com/api/token',
112
  querystring.stringify({
 
121
  return response.data;
122
  }
123
 
124
+ // 1. Current Playback Endpoint with User ID
125
  app.get('/api/current-playback', async (req, res) => {
126
  try {
127
  const userId = req.query.user;
 
231
  }
232
  });
233
 
234
+ // 2. Login Endpoint
235
+ app.get('/spotify', (req, res) => {
236
+ const FRONTEND_URI = getFrontendUri(req);
237
+ const REDIRECT_URI = `${FRONTEND_URI}/callback`;
238
+
239
+ const scopes = [
240
+ 'user-read-playback-state',
241
+ 'user-read-currently-playing',
242
+ 'user-read-private',
243
+ 'user-read-email'
244
+ ];
245
+
246
+ const queryParams = querystring.stringify({
247
+ response_type: 'code',
248
+ client_id: CLIENT_ID,
249
+ scope: scopes.join(' '),
250
+ redirect_uri: REDIRECT_URI,
251
+ show_dialog: true,
252
+ });
253
+
254
+ res.redirect(`https://accounts.spotify.com/authorize?${queryParams}`);
255
+ });
256
+
257
+ // 3. Callback Endpoint
258
+ app.get('/callback', async (req, res) => {
259
+ const FRONTEND_URI = getFrontendUri(req);
260
+ const REDIRECT_URI = `${FRONTEND_URI}/callback`;
261
+
262
+ const { code, error } = req.query;
263
 
264
+ if (error) {
265
+ return res.redirect(`${FRONTEND_URI}/error?message=${encodeURIComponent(error)}`);
266
  }
267
 
268
  try {
269
+ // Get tokens
270
+ const authResponse = await axios.post('https://accounts.spotify.com/api/token',
271
+ querystring.stringify({
272
+ grant_type: 'authorization_code',
273
+ code,
274
+ redirect_uri: REDIRECT_URI,
275
+ }), {
276
+ headers: {
277
+ 'Content-Type': 'application/x-www-form-urlencoded',
278
+ 'Authorization': 'Basic ' + Buffer.from(`${CLIENT_ID}:${CLIENT_SECRET}`).toString('base64'),
279
+ },
280
+ });
281
 
282
+ const { access_token, refresh_token, expires_in } = authResponse.data;
283
+
284
+ // Get user data
285
+ const userResponse = await axios.get('https://api.spotify.com/v1/me', {
286
+ headers: { 'Authorization': `Bearer ${access_token}` },
287
+ });
288
+
289
+ // Store user session
290
+ const userId = userResponse.data.id;
291
+ userSessions[userId] = {
292
+ accessToken: access_token,
293
+ refreshToken: refresh_token,
294
+ expiresAt: Date.now() + expires_in * 1000,
295
+ display_name: userResponse.data.display_name,
296
+ country: userResponse.data.country,
297
+ email: userResponse.data.email
298
  };
299
 
300
+ // Redirect to current playback with user ID
301
+ res.redirect(`${FRONTEND_URI}/api/current-playback?user=${userId}`);
302
+
303
+ } catch (err) {
304
+ console.error('Callback error:', err);
305
+ res.redirect(`${FRONTEND_URI}/error?message=${encodeURIComponent('Authentication failed')}`);
 
 
 
 
 
 
306
  }
307
  });
308
 
 
 
 
 
 
309
 
310
  app.get('/pages', async (req, res) => {
311
  const targetUrl = req.query.url;