From cd0969f997a0d736468e83cde72168b5fc9aa153 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?F=C3=A9lix=20Mielcarek?= Date: Tue, 14 May 2024 14:46:47 +0200 Subject: [PATCH] Handling refresh tokens --- .gitignore | 3 +- script/big-brother.js | 122 +++++++++++++++++++++++++++--------------- web/src/app.js | 23 +++----- 3 files changed, 88 insertions(+), 60 deletions(-) diff --git a/.gitignore b/.gitignore index cc2465c..6ab53a5 100644 --- a/.gitignore +++ b/.gitignore @@ -130,4 +130,5 @@ dist .pnp.* # Specific to Gold Digger -spotify_access_token \ No newline at end of file +spotify_access_token +.vscode/ \ No newline at end of file diff --git a/script/big-brother.js b/script/big-brother.js index 2b9fae3..14cfb01 100644 --- a/script/big-brother.js +++ b/script/big-brother.js @@ -6,17 +6,19 @@ const { Client } = require('pg'); //#region CONSTANTS const spotifyRequestsLimit = 50; const thresholdLove = 0.6; +const clientId = process.env.CLIENT_ID; +const clientSecret = process.env.CLIENT_SECRET; const client = new Client({ user: process.env.DB_USER, host: 'localhost', database: 'bigbrother', password: process.env.DB_PASSWORD, port: 5432 - }); +}); //#endregion //#region STRUCTURE -var albumDataStructure = { +let albumDataStructure = { savedTracks: [], totalTracks: 0, name: "", @@ -31,7 +33,7 @@ async function getSavedTracks(accessToken, albums, href=`https://api.spotify.com response.data.items.forEach(t => { if(t.track.album.total_tracks > 1) { if(!albums[t.track.album.id]) { - var albumData = Object.create(albumDataStructure); + let albumData = Object.create(albumDataStructure); albumData.savedTracks = []; albumData.totalTracks = t.track.album.total_tracks; albums[t.track.album.id] = albumData; @@ -55,17 +57,17 @@ async function addAlbums(accessToken, idsString) { } async function tresholdAlgorithm(albums, accessToken) { - var lovedAlbum = [] + let lovedAlbum = [] for(let album in albums) { if(albums[album].savedTracks.length >= albums[album].totalTracks * thresholdLove) { lovedAlbum.push(album); } } - var idsString = ""; - var idsList = []; - var idsCounter = 0; - for(var album of lovedAlbum ) { + let idsString = ""; + let idsList = []; + let idsCounter = 0; + for(let album of lovedAlbum ) { idsList.push(album); idsString = idsString.concat(album,','); idsCounter = idsCounter+1; @@ -93,17 +95,17 @@ async function checkAlbums(accessToken, idsString, idsList, albums) { try { const response = await axios.get(`https://api.spotify.com/v1/me/albums/contains?ids=${idsString}`, { headers: { 'Authorization': 'Bearer ' + accessToken, } }); - var idsToDelete = ""; - var idsCounter = 0; - for(var i in response.data) { + let idsToDelete = ""; + let idsCounter = 0; + for(let i in response.data) { if(response.data[i]) { - for(var track of albums[idsList[i]].savedTracks) { + for(let track of albums[idsList[i]].savedTracks) { idsToDelete = idsToDelete.concat(track, ','); idsCounter = idsCounter+1; if(idsCounter == 50) { await removeTracks(accessToken, idsToDelete); - var idsToDelete = ""; - var idsCounter = 0; + let idsToDelete = ""; + let idsCounter = 0; } } } @@ -114,11 +116,11 @@ async function checkAlbums(accessToken, idsString, idsList, albums) { } async function removeTracksAlgorithm(albums, accessToken) { - var idsString = ""; - var idsList = []; - var idsCounter = 0; + let idsString = ""; + let idsList = []; + let idsCounter = 0; - for(var album in albums) { + for(let album in albums) { idsList.push(album); idsString = idsString.concat(album,','); idsCounter = idsCounter+1; @@ -153,34 +155,66 @@ function stepBeggining(step) { //#endregion //#region MAIN +async function mainAlgorithm(accessToken) { + let albums = {}; + + const step1 = "Get liked tracks"; + const step2 = "Apply treshold algorithm"; + const step3 = "Remove saved tracks from saved albums"; + try { + stepBeggining(step1); + await getSavedTracks(accessToken, albums); + stepSuccess(step1); + + stepBeggining(step2); + await tresholdAlgorithm(albums, accessToken); + stepSuccess(step2); + + stepBeggining(step3); + await removeTracksAlgorithm(albums, accessToken); + stepSuccess(step3); + } catch (error) { } +} + async function main() { + await client.connect(); + try { - await client.connect(); - const query = 'SELECT accesstoken FROM public.users'; - const result = await client.query(query); - - result.rows.forEach(async (row) => { - var albums = {}; - var accessToken = row.accesstoken - - const step1 = "Get liked tracks"; - const step2 = "Apply treshold algorithm"; - const step3 = "Remove saved tracks from saved albums"; - try { - stepBeggining(step1); - await getSavedTracks(accessToken, albums); - stepSuccess(step1); - - stepBeggining(step2); - await tresholdAlgorithm(albums, accessToken); - stepSuccess(step2); - - stepBeggining(step3); - await removeTracksAlgorithm(albums, accessToken); - stepSuccess(step3); - } catch (error) { } - }); - } catch (error) { console.error('Error executing query:', error) } finally { await client.end() } + const selectQuery = 'SELECT * FROM public.users'; + const selectResult = await client.query(selectQuery); + + for(let row of selectResult.rows) { + const spotifyId = row.spotifyid; + const refreshToken = row.refreshtoken; + + let authOptions = { + url: 'https://accounts.spotify.com/api/token', + method: 'post', + data: { + refresh_token: refreshToken, + grant_type: 'refresh_token', + }, + headers: { + 'content-type': 'application/x-www-form-urlencoded', + 'Authorization': 'Basic ' + (new Buffer.from(clientId + ':' + clientSecret).toString('base64')) + }, + json: true + }; + + const response = await axios(authOptions); + const newAccessToken = response.data.access_token; + const newRefreshToken = response.data.refresh_token; + + const updateQuery = ` + UPDATE public.users + SET accesstoken = $2, refreshtoken = $3 + WHERE spotifyid = $1; + `; + await client.query(updateQuery, [spotifyId, newAccessToken, newRefreshToken]) + + await mainAlgorithm(newAccessToken); + } + } catch (error) { console.error('Error executing select query:', error) } finally { await client.end() } } //#endregion diff --git a/web/src/app.js b/web/src/app.js index 8444e0c..8efba1a 100644 --- a/web/src/app.js +++ b/web/src/app.js @@ -4,13 +4,11 @@ const express = require('express') const cookieParser = require('cookie-parser'); const axios = require('axios'); const queryString = require('querystring'); -const fs = require('node:fs'); const pg = require('pg'); //#endregion //#region CONSTANTS const staticDir = path.join(__dirname, '../public'); -const commonDir = path.join(__dirname, '../../common'); const port = 3000 const clientId = process.env.CLIENT_ID; const clientSecret = process.env.CLIENT_SECRET; @@ -99,34 +97,29 @@ app.get('/callback', (req, res) => { axios(authOptions) .then(async response => { - /*fs.writeFile(commonDir + '/spotify_access_token', response.data.access_token, err => { - if (err) { - console.error(err); - } else { - console.log("Spotify access token recovered.") - } - });*/ - const accessToken = response.data.access_token + const refreshToken = response.data.refresh_token try { const response = await axios.get(`https://api.spotify.com/v1/me`, { headers: { 'Authorization': 'Bearer ' + accessToken, } }); const data = { SpotifyId: response.data.id, - AccessToken: accessToken + AccessToken: accessToken, + RefreshToken: refreshToken }; await client.connect() const sqlQuery = ` - INSERT INTO public.users (spotifyid,accesstoken) - VALUES ($1,$2) + INSERT INTO public.users (spotifyid,accesstoken,refreshtoken) + VALUES ($1,$2,$3) ON CONFLICT (spotifyid) DO UPDATE SET - accesstoken = EXCLUDED.accesstoken + accesstoken = EXCLUDED.accesstoken, + refreshtoken = EXCLUDED.refreshtoken `; - client.query(sqlQuery, [data.SpotifyId, data.AccessToken], (err, res) => { + client.query(sqlQuery, [data.SpotifyId, data.AccessToken, data.RefreshToken], (err, res) => { if (err) { console.error('Error executing query', err); return;