Search code examples
javascriptnode.jsfrontendbackendchess

chess.com API does'nt bring back some requests


So im very new to fullstack and been working on a little vanilla js project to make a website that calls a server I run that calls chess.com api, for example retrieving all elo ratings is:

https://api.chess.com/pub/player/${username}/stats

So I made a backend call in node-js:

const fetch = require('node-fetch');

exports.getChessManStats = () => {
   return (req, res) => {
    res.set('Access-Control-Allow-Origin', '*');
    const username = req.param('username');
    console.log(req.param('username'));
    fetch(`https://api.chess.com/pub/player/${username}/stats`)
    .then(res2 => res2.json() )
    .then(chessManData => {
        res.json({  
            daily: chessManData.chess_daily.last.rating,
            rapid: chessManData.chess_rapid.last.rating,
            blitz: chessManData.chess_blitz.last.rating,
            bullet: chessManData.chess_bullet.last.rating,
        })
    })
    .catch(err => console.log(err));
   } 
};

the code then runs with express on the main.js with:

const app = express();
app.get('/getRating',chessManController.getChessManStats()); 

obviously later down the line I called app.listen(3000) .

So then at the frontend I made a button that calls this function :

const makeUserStats = () => {
const username = document.getElementById('username').value;//id=username is type input
document.getElementById('rating').innerHTML = `Searching`; //making the rating div into 'searching'
console.log(`http://localhost:3000/getRating?username=${username}`)//just seeing the sting I send
fetch(`http://localhost:3000/getRating?username=${username}`)
.then(rating => {
    document.getElementsByClassName('statButton').disabled = true;//disabling buttons until the data arrives
    console.log('got json');
    return rating.json();
})
.catch(err => console.log(err))//looking for errors
.then((userRating => {
    window.userRating = userRating;//saving the stats globaly to use in other buttons
    window.user = username;
}))
.then(() => {
    document.getElementsByClassName('statButton').disabled = false;//enabling the buttons again
    document.getElementById('rating').innerHTML = `${window.user} rating is:`; 
})
}

and now when I press the button it works with some usernames and with some dont. YoniRamot (mine) works, hikaru (pro player) works, atomicstew (friend) doesnt work, idobl (friend) doesnt work. and the wierd part is it does'nt catch any errors, just waiting for answer that it never gets. but if you go the the api they all exist:

https://api.chess.com/pub/player/yoniramot/stats -- mine

https://api.chess.com/pub/player/hikaru/stats --proplayer

https://api.chess.com/pub/player/atomicstew/stats --friend

https://api.chess.com/pub/player/idobl/stats --friend

the console of the backend shows:

atomicstew
TypeError: Cannot read property 'last' of undefined
    at C:\Users\Yonatan\Desktop\coding\training\intermediateChess\backend\controllers\chessStats.js:12:45
    at processTicksAndRejections (internal/process/task_queues.js:93:5)

meaning that the backend gets the username but does'nt find it in the api for some reason.

please help my mind is blowing at this point.

-edit 1-

So I added a console log before sending the res with the data, and it printed:

atomicstew
{
  chess_rapid: {
    last: { rating: 1228, date: 1612114999, rd: 28 },
    best: {
      rating: 1265,
      date: 1611786478,
      game: 'https://www.chess.com/live/game/6380128206'
    },
    record: { win: 233, loss: 202, draw: 19 }
  },
  chess_blitz: {
    last: { rating: 902, date: 1611928398, rd: 50 },
    best: {
      rating: 1010,
      date: 1609882454,
      game: 'https://www.chess.com/live/game/6297568401'
    },
    record: { win: 26, loss: 24, draw: 4 }
  },
  fide: 0,
  tactics: {
    highest: { rating: 1659, date: 1609635730 },
    lowest: { rating: 387, date: 1608148134 }
  },
  lessons: {},
  puzzle_rush: {}
}
TypeError: Cannot read property 'last' of undefined
    at C:\Users\Yonatan\Desktop\coding\training\intermediateChess\backend\controllers\chessStats.js:13:45
    at processTicksAndRejections (internal/process/task_queues.js:93:5)

and the references I am calling are right there, so I am still stuck.

-edit 2-

I noe realized that if a player didnt play a certain game mode than the api doesnt hold that values. any ideas how to save the data as 0 or null if there is no data neatly?


Solution

  • Issue is in following block of code where you are trying to access last field on different properties in response:

    res.json({  
          daily: chessManData.chess_daily.last.rating,
          rapid: chessManData.chess_rapid.last.rating,
          blitz: chessManData.chess_blitz.last.rating,
          bullet: chessManData.chess_bullet.last.rating,
    })
    
    

    I had quick look at response for following API and it does not have chess_daily and chess_bullet properties.

    https://api.chess.com/pub/player/atomicstew/stats

    Since you are trying to access chessManData.chess_daily.last.rating and chess_daily is not present in chessManData, you are getting exception for .last.

    In order to fix it, you can replace above block by following:

    res.json({  
         daily: chessManData.chess_daily && chessManData.chess_daily.last ? chessManData.chess_daily.last.rating : null, // replace null with appropriate default value for rating
         rapid: chessManData.chess_rapid && chessManData.chess_rapid.last ? chessManData.chess_rapid.last.rating : null,
         blitz: chessManData.chess_blitz && chessManData.chess_blitz.last ? chessManData.chess_blitz.last.rating : null,
         bullet: chessManData.chess_bullet && chessManData.chess_bullet.last ? chessManData.chess_bullet.last.rating : null,
    })