Monitor chess progress using Twilio Serverless and SMS

January 25, 2021
Written by
Reviewed by
Diane Phan
Twilion

header img chess

After the Queen's Gambit came out, I, alongside many, began playing a lot of chess and completing chess puzzles. This tutorial will go over how to build a chess progress monitor using the chess.com API, Twilio Functions, and the Twilio Serverless Toolkit. Text a chess.com username to +14243260196 (for example below, mine is lizziepika) to see it in action.

SMS example

Prerequisites

  1. A Twilio account - sign up for a free one here and receive an extra $10 if you upgrade through this link
  2. A Twilio phone number with SMS capabilities - configure one here
  3. Postman (you could alternatively make cURL requests from the command line)
  4. Node.js installed - download it here

Make a chess.com API Request  

cute Disney man chess gif

Chess.com provides a nice read-only published data API which makes available public data from the site, such as player data, game data, and club or tournament information.

You can look over different API endpoints offered. To get someone's profile information, the URL would look like https://api.chess.com/pub/player/{insert-chess.com-username}. Open Postman and paste that URL (replacing it with a chess.com username--if you need one, you can use lizziepika) into the URL bar.

Click Send to hit it with a GET request to see the following data returned:

JSON in postman
{
    "avatar": "https://images.chesscomfiles.com/uploads/v1/user/100737392.a1fb42ec.200x200o.30a48f2c7424.jpeg",
    "player_id": 100737392,
    "@id": "https://api.chess.com/pub/player/lizziepika",
    "url": "https://www.chess.com/member/lizziepika",
    "name": "Lizzie Bird",
    "username": "lizziepika",
    "followers": 11,
    "country": "https://api.chess.com/pub/country/US",
    "last_online": 1611167412,
    "joined": 1606775497,
    "status": "basic",
    "is_streamer": false
}

To get a player's current games, the URL would be: https://api.chess.com/pub/player/{insert-chess.com-username}/games. As a big sports fan, I personally am a sucker for statistics. The URL to retrieve the stats would look like https://api.chess.com/pub/player/${insert-username}/stats and return data as shown below:

JSON stats in Postman
{
    "chess_daily": {
        "last": {
            "rating": 1109,
            "date": 1610664629,
            "rd": 181
        },
        "best": {
            "rating": 1109,
            "date": 1610664629,
            "game": "https://www.chess.com/game/daily/297257528"
        },
        "record": {
            "win": 3,
            "loss": 1,
            "draw": 0,
            "time_per_move": 17091,
            "timeout_percent": 20
        }
    },
    "chess_rapid": {
        "last": {
            "rating": 654,
            "date": 1611119635,
            "rd": 29
        },
        "best": {
            "rating": 710,
            "date": 1610599582,
            "game": "https://www.chess.com/live/game/6230163156"
        },
        "record": {
            "win": 136,
            "loss": 114,
            "draw": 23
        }
    },
    "fide": 0,
    "tactics": {
        "highest": {
            "rating": 742,
            "date": 1610692192
        },
        "lowest": {
            "rating": 409,
            "date": 1607080346
        }
    },
    "lessons": {},
    "puzzle_rush": {}
}

You can see more chess.com API endpoints here.

Get Started with the Twilio Serverless Toolkit

The Serverless Toolkit is CLI tooling that helps you develop locally and deploy to Twilio Runtime. The best way to work with the Serverless Toolkit is through the Twilio CLI. If you don't have the Twilio CLI installed yet, run the following commands on the command line to install it and the Serverless Toolkit:

npm install twilio-cli -g
twilio login
twilio plugins:install @twilio-labs/plugin-serverless

Afterwards, create your new project and install our lone requirement got to make HTTP requests in Node.js by running:

twilio serverless:init chess-api
cd chess-api
npm install got

Make a Twilio Function with JavaScript

Use cd to change into the functions directory and make a new file called chess-open-to-other-usernames.js containing the following code:

const got = require('got');
exports.handler = async function(context, event, callback) {
  const twiml = new Twilio.twiml.MessagingResponse();
  const message = twiml.message(); 
  const username = event.Body.toLowerCase().trim();
  let stats_url, profile_url, stats_resp, profile_resp, prof_data, data, chess_rapid;
  try {
    stats_url = `https://api.chess.com/pub/player/${username}/stats`;
    profile_url = `https://api.chess.com/pub/player/${username}`;
    profile_resp = await got(profile_url);
    stats_resp = await got(stats_url);
    prof_data = JSON.parse(profile_resp.body);
    data = JSON.parse(stats_resp.body);
    chess_rapid = data.chess_rapid;
  }
  catch (e) {
    message.body('User does not exist on chess.com');
    callback(null, twiml);
  }
  const avatar_url = prof_data.avatar;
  const rapid_record = chess_rapid.record;
  const win = rapid_record.win;
  const loss = rapid_record.loss;
  const draw = rapid_record.draw;
  const rapid_best = chess_rapid.best;
  const rapid_best_rating = rapid_best.rating;
  const rapid_last = chess_rapid.last.rating;
  const unix_timestamp = rapid_best.date;
  let date = new Date(unix_timestamp * 1000);
  date = date.toDateString(); // outputs to "Thu May 28 2015 format"
  message.body(`${username}'s rapid record: ${win} wins, ${loss} losses, ${draw} draws. Current rapid rating: ${rapid_last}, best rapid rating: ${rapid_best_rating} from ${date}`);
  message.media(avatar_url);
  callback(null, twiml);
};

This code imports got, makes a Twilio Messaging Response object, creates a variable username from the inbound text message users will text in and variables for the stats and profile endpoints of the chess.com API, parses the responses from the endpoints (like we saw using Postman above), and finally parses the responses to handle data from rapid chess games.

We use a try..catch block to check that the user (and link we are making a HTTP request to) exist, and if not, a message is returned saying so. Else, we parse the rapid chess record for information such as wins, losses, draws, best rating, and the time of the best rating which is formatted with toDateString(). We return a text message containing that data as well as the account's avatar image.

You can view the complete app on GitHub here.

Configure the Function with a Twilio Phone Number

To open up our app to the web with a public-facing URL, go back to the chess-api root directory and run twilio serverless:deploy. You should see this at the bottom of your terminal:

Function URLs in terminal

Grab the Function URL corresponding to your app (the one that ends with  /chess-open-to-other-usernames) and configure a Twilio phone number with it as shown below: select the Twilio number you just purchased in your Twilio phone numbers console and scroll down to the Messaging section. Paste the link in the text field for A MESSAGE COMES IN webhook making sure that it's set to HTTP POST.

Configure phone number for messaging in console

When you click Save at the bottom, the new Twilio Functions UI will update the Webhook to the Function like so:

new Function with service and environment in Messaging section of console

The Service is the Serverless project name, environment provides no other options, and Function Path is the file name. Now take out your phone and text a chess.com username to your Twilio number.Share the Twilio number and instructions with friends so they can stay up-to-date on your progress!

What's Next for Twilio Serverless, APIs, and Chess?

Gaston chess gif

Twilio's Serverless Toolkit makes it possible to deploy web apps quickly, and Runtime seamlessly handles servers for you. Let me know online what you're building with Serverless, or if you want to start a chess game!