0

I have a issue. I'm doing a project with React. My project is simply for listening to music on Spotify. It is necessary to train the code of the room entered from the home page to the url extension that I will use for Spotify. The api link I use for Spotify uses node.js, so it allows file reading, but I want it to write the code of the room I clicked in React at that time into that txt file. How can I do that?

My only wish is to save the room.id variable in the homepage file into the txt file in another way. Example of homepage.js

      <Heading as="h1" mb={6}>
            Rooms
            </Heading>
            <Divider orientation="horizontal" />
           {rooms.map((room)=> (
              <ListItem>
              <ListItemText primary={room.roomName} secondary={room.roomInfo}/>
             
               {/* <Link to={`/room/${room.id}`}></Link> */}
            
                <Link to={`/room/${room.id}`}>
                <Button>
                Join Room
                
                </Button>
                </Link>
                
              </ListItem>))}

Example of Spotify redirect code..

/**
 * This is an example of a basic node.js script that performs
 * the Authorization Code oAuth2 flow to authenticate against
 * the Spotify Accounts.
 *
 * For more information, read
 * https://developer.spotify.com/web-api/authorization-guide/#authorization_code_flow
 */

 var express = require('express'); // Express web server framework
 var request = require('request'); // "Request" library
 var cors = require('cors');
 var querystring = require('querystring');
 var cookieParser = require('cookie-parser');


 
 /**
  * Generates a random string containing numbers and letters
  * @param  {number} length The length of the string
  * @return {string} The generated string
  */
 var generateRandomString = function(length) {
   var text = '';
   var possible = 'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789';
 
   for (var i = 0; i < length; i++) {
     text += possible.charAt(Math.floor(Math.random() * possible.length));
   }
   return text;
 };
 
 var stateKey = 'spotify_auth_state';
 
 var app = express();
 
 app.use(express.static(__dirname + '/public'))
    .use(cors())
    .use(cookieParser());
 
 app.get('/login', function(req, res) {
 
   var state = generateRandomString(16);
   res.cookie(stateKey, state);  
   // your application requests authorization
   var scope = 'user-read-private user-read-email user-read-playback-state user-modify-playback-state user-read-currently-playing';
   res.redirect('https://accounts.spotify.com/authorize?' +
     querystring.stringify({
       response_type: 'code',
       client_id: client_id,
       scope: scope,
       redirect_uri: redirect_uri,
       state: state
     }));
 });
 
 app.get('/callback', function(req, res) {
 
   // your application requests refresh and access tokens
   // after checking the state parameter
 
  
   var code = req.query.code || null;
   var state = req.query.state || null;
   var storedState = req.cookies ? req.cookies[stateKey] : null;
 
   if (state === null || state !== storedState) {
     res.redirect('/#' +
       querystring.stringify({
         error: 'state_mismatch'
       }));
   } else {
     res.clearCookie(stateKey);
     var authOptions = {
       url: 'https://accounts.spotify.com/api/token',
       form: {
         code: code,
         redirect_uri: redirect_uri,
         grant_type: 'authorization_code'
       },
       headers: {
         'Authorization': 'Basic ' + (new Buffer(client_id + ':' + client_secret).toString('base64'))
       },
       json: true
     };
 
     request.post(authOptions, function(error, response, body) {
       if (!error && response.statusCode === 200) {
 
         var access_token = body.access_token,
             refresh_token = body.refresh_token;
 
         var options = {
           url: 'https://api.spotify.com/v1/me',
           headers: { 'Authorization': 'Bearer ' + access_token },
           json: true
         };
 
         // use the access token to access the Spotify Web API
         request.get(options, function(error, response, body) {
           console.log(body);
         });
         var fs = require('fs');
         var roomCodeTxt = fs.readFileSync('roomCodeText.txt', 'utf-8');
        
 
         // we can also pass the token to the browser to make requests from there
         res.redirect(`http://localhost:3000/room/${roomCodeTxt}\#`  +
           querystring.stringify({
             access_token: access_token,
             refresh_token: refresh_token
           }));
       } else {
         res.redirect('/#' +
           querystring.stringify({
             error: 'invalid_token'
           }));
       }
     });
   }
 });
 
 app.get('/refresh_token', function(req, res) {
 
   // requesting access token from refresh token
   var refresh_token = req.query.refresh_token;
   var authOptions = {
     url: 'https://accounts.spotify.com/api/token',
     headers: { 'Authorization': 'Basic ' + (new Buffer(client_id + ':' + client_secret).toString('base64')) },
     form: {
       grant_type: 'refresh_token',
       refresh_token: refresh_token
     },
     json: true
   };
 
   request.post(authOptions, function(error, response, body) {
     if (!error && response.statusCode === 200) {
       var access_token = body.access_token;
       res.send({
         'access_token': access_token
       });
     }
   });
 });
 
 console.log('Listening on 8888');
 app.listen(8888);
 
Mert Özler
  • 113
  • 5

1 Answers1

1

You can write to a file in node also. See fs.writeFileSync (because this is a server, fs.writeFile or fs.promises.writeFile would help with performance, but for something this little, it shouldn't really matter).

The basic idea is in node, when the user clicks your button, you'll send a request to your server to write a file. Something roughly like this:

// Using the native fetch API
const joinRoom = roomId => {
  return fetch('/write/to/file/endpoint', {
    body: JSON.stringify({ roomId: roomId }),
    // This header lets the server know that what you're sending is JSON
    headers: { 'Content-Type': 'application/json' },
    method: 'POST'
  })
}

// With axios (Added this example in reponse to the O.P.'s comment)
const joinRoom = roomId => {
  // Axios will add the Content-Type: application/json header by default
  return axios.post('/write/to/file/endpoint', { roomId: roomId })
}

...

<button onClick={() => joinRoom(room.id)}>Join Room</button

In your server, you just need to handle requests to this new endpoint and call fs.writeFileSync('roomCodeText.txt', roomId, 'utf-8'). The specific details for how this works depends on how you're handling requests (in vanilla node? With the express library?) You can refer to this stackoverflow question on how to retrieve a POST body in node. There's answers for both express and node. The specific answer I linked to explains how to do it with vanilla node. It assumed that url-encoded data was send in the POST body. We're sending JSON in the above example, so you just need to take that code snippet and replace qs.parse(body) with JSON.parse(body).

Scotty Jamison
  • 10,498
  • 2
  • 24
  • 30
  • Although you answered very well, I guess I could not understand how I could solve it. So I want to ask a few questions and explain exactly what I intend to do. First of all, I want to write the room.id variable into roomCodeTxt.txt, which is in another file where homepage.js does not exist. – Mert Özler May 10 '21 at 14:31
  • This was the only method I could find (I'm new to coding) as I intend this for routing here. So I just learned that I have the possibility to do this with axios. If I am sending room.id to node.js which I use for spotify with the method you suggest, how can I access it from within the node.js I use for spotify? – Mert Özler May 10 '21 at 14:31
  • 1
    I updated my answer in response to your concerns. (I also am now sending the parameter in the POST body instead of in the URL, as that's a more normal thing to do). I'm not really sure I understand your worry about roomCodeTxt.txt being in a different file from your script - it'll always be in a different file, and you choose which file to write to by providing a path to fs.writeFileSync(). – Scotty Jamison May 10 '21 at 15:24
  • I finally understood what he intended to do, my method offers me a very simple and non-functional solution, but I still could not figure out how to use the solution you suggested to me on the node.js side. That's why I added all the code I made an API connection with Spotify. I know what to do on React side, but how can I assign the room.id data I sent here to the roomCodetxt variable in Node.js? – Mert Özler May 10 '21 at 15:31
  • What I intended by writing to the file was actually nothing more than passing the data to the node.js side as you suggested to me. Therefore, with the solution method you suggested to me, I learned the method of transferring data directly, without having to write to the file. But this time, I don't know how to get and use this data by node.js. – Mert Özler May 10 '21 at 15:34
  • Ah, thanks for posting more code. I can see now that you are using the express library. The way you get the POST body in express (according to that link I shared) is to add `app.use(express.json());`, then wherever you choose to receive the request, do `req.body.roomId` to retrieve and use the roomId. So, it might be something like this: `app.use(express.json()); app.post('/the/endpoint/', (req, res) => { console.log(req.body.roomId) });` – Scotty Jamison May 10 '21 at 15:41
  • I got very close ... But when I do what they say on the node.js side, it becomes 'undefined'. So I might be having a problem migrating to node.js via react. homepage.js and app.js run in different folders and ports. While working with port 3000, which I call Login with Spotify, the port 8888 where I perform api operations on spotify. The reason it is undefinied indicates that the data could not be retrieved, so not being able to transfer the data here is a much more important problem. endpointe I wrote that; 'https: localhost: 8888 / callback' do you think this is true? – Mert Özler May 10 '21 at 16:01
  • Change it to `app.post` - in this example, we're doing a POST request, not a GET request. GET is generally used to retrieve a resource. POST is generally used to do some action on the server. You can't send a request body with a GET request, so none of the above advice would work. – Scotty Jamison May 10 '21 at 16:05
  • Let us [continue this discussion in chat](https://chat.stackoverflow.com/rooms/232174/discussion-between-scotty-jamison-and-mert-ozler). – Scotty Jamison May 10 '21 at 16:26