Get The Latest NBA News Sent to Your Phone via SMS

July 21, 2022
Written by
Reviewed by
Paul Kamp
Twilion

F5 Your Phone to Get the Latest NBA News

In light of June 30th, 2022, the date when NBA teams can begin negotiations with free agents, now is an exciting time to be a basketball fan. We’ve already seen so much breaking news like Kevin Durant and Kyrie Irving demanding trades, the Timberwolves giving away the farm for Rudy Golbert, and surely much more to come.

I know many fans who are F5ing their news feeds on their computers, so wouldn’t it be fun to do from your phone too? In this post, I’ll teach you how to write a Python application that texts you NBA news.

Prerequisites

Before getting started, it’s important to have the following before moving on:

Background

Unfortunately, there is no official API provided by the NBA. Furthermore, ESPN has retired their public API as developers can no longer generate an API key. But fear not, developers are crafty people, and there’s a solution!

If you do some Google searching, you’ll see many independent third-party developers who have created their own (unofficial) NBA APIs as a workaround. But for this application, I’m going to be using an API from a company, called SportsDataIO, which aggregates a bunch of sports data (not just NBA news) and allows developers to reach it via API calls.

Architecture of an SMS NBA News App

For context, this blog post is structured as follows:

  1. Set Up: Set up our local development environment
  2. NBA News API: Get NBA news data from the SportsDataIO API
  3. Make an Outbound SMS: Send a text message (containing NBA news)
  4. Make an Inbound SMS: Send a text message (containing NBA news) when the application is triggered

Set Up

mkdir nba_app

For us to get NBA data, we need to register for a free account with SportsDataIO. After that, we’ll need an API key to authenticate our application with SportsDataIO. You can find this in your Account settings under Subscriptions. Copy your API key and don’t share it with anyone!

SportsDataIO API Key

Let’s create a file called .env to store our API key in environment variables

Within that file, we’ll create an environment variable called SPORTSDATA_API_KEY. Replace PASTE_YOUR_API_KEY_HERE with the API key that you copied earlier.

SPORTSDATA_API_KEY=PASTE_YOUR_API_KEY_HERE

Since we’ll also be working with our Twilio account, we’ll need to modify this file even more. Log into your Twilio console, then scroll down to find your Account SID and Auth Token. Add two additional lines to the .env file, but change the values to equal your unique Account SID and Auth Token.

TWILIO_ACCOUNT_SID=PASTE_YOUR_ACCOUNT_SID_HERE
TWILIO_AUTH_TOKEN=PASTE_YOUR_AUTH_TOKEN_HERE

If you’re pushing these to a Git repository, please make sure to add the .env file to your .gitignore so that these credentials are secured.

 

NBA News API

Create a file called nba_news.py: this is where we will call the SportsDataIO NBA news API.

import requests
import os
from dotenv import load_dotenv

load_dotenv()

url = f'https://api.sportsdata.io/v3/nba/scores/json/News'

params = {
	'key': os.getenv('SPORTSDATA_API_KEY')
}

def get_news():
	response = requests.get(url, params=params)
	return response.json()

You’ll be able to see the response in JSON or in a browser by hitting the /News endpoint and appending your API key as a query string. That may look like this:

https://api.sportsdata.io/v3/nba/scores/json/News?key={YOUR_API_KEY}

NBA News JSON Response

If you format the JSON response, you’ll see a key called “Categories”. According to the SportsDataIO data dictionary at the time I wrote this post, potential return values are: Top Headlines, Breaking News, Injury, Sit/Start, Waiver Wire, Risers, Fallers, Lineups, Transactions, Free Agents, Prospects/Rookies, Game Recap, Matchup Outlook.

import requests
import os

from datetime import date
from dotenv import load_dotenv
from twilio.rest import Client

load_dotenv()

today = date.today()


# we are hitting 2 endpoints which returns news for today & news for all days
url_news_today = f'https://api.sportsdata.io/v3/nba/scores/json/NewsByDate/{today}'
url_news_all = f'https://api.sportsdata.io/v3/nba/scores/json/News'


# we stored our API key in the .env file and are accessing it here, then storing them as parameters for our HTTP request
params = {
	'key': os.getenv('SPORTSDATA_API_KEY')
}


# we are creating a function to either get the news for today or getting all news
def get_news(date=None):
	if date == 'today':
		response = requests.get(url_news_today, params=params)
	else:
		response = requests.get(url_news_all, params=params)
	return response.json()


# we are looping through the JSON response and seeing if ‘Top-Headlines’ are in the Category key.
def check_transactions(response, target_category):
	for news in response:
		if target_category in news['Categories']:
			return True
	return False


# we return a string output that contains the title and date of a ‘Top-Headlines’ news
def print_transactions(response, target_category):
	output = ''
	for news in response:
		if target_category in news['Categories']:
			output += f"Title: {news['Title']}\n"
			output += f"Date: {news['TimeAgo']}\n"
			output += '----------------------------------------\n'
	return output


# we take in user input. if the user enters F5, we will get news from today only. if the user enters anything else, we will get news from all days.
def get_transactions(date=None):
	target_category = 'Top-Headlines'

	if date and 'f5' in date.lower():
		response = get_news('today')
		if not check_transactions(response, target_category):
			return('No transactions today, keep F5ing')
	else:
		response = get_news()
	return print_transactions(response, target_category)

We can test out the code by calling get_transactions().

For example, add the following to the end of the file:

if __name__ == '__main__':
	print(get_transactions())

You can also test it by entering an argument containing the text ‘F5’. This will give you news for the current day. But if there isn’t any news, you’ll get a message saying that you should keep F5ing.

Make an Outbound SMS

We’ve successfully returned the data that we need, now it’s time to test it out with an outbound SMS. Think of outbound as sending a text message "OUT" to someone’s phone number. So, we are trying to send OUT NBA news via a text message.

 

Within the same file, let’s create a new function called send_text() to send a text message to a phone number of your choice from your Twilio phone number. Just remember to replace 'ENTER_YOUR_TWILIO_NUMBER' with your Twilio number (found in the Console), and 'ENTER_THE_NUMBER_YOURE_TEXTING_TO' with the phone number you’re wanting to text. 

def send_text(option=None):
	account_sid = os.getenv('TWILIO_ACCOUNT_SID')
	auth_token = os.getenv('TWILIO_AUTH_TOKEN')
	client = Client(account_sid, auth_token)

	message = client.messages.create(
		body=get_transactions(option),
		from_='ENTER_YOUR_TWILIO_NUMBER',
		to='ENTER_THE_NUMBER_YOURE_TEXTING_TO'
	)
	print(message.body)

In the code above, notice that the body of our message is a function call that returns NBA news.

 

Below that function, call it, e.g., send_text() and optionally enter in a string argument such as 'give me news'. Remember, that if the argument contains ‘F5’, we get news for today (anything else will return all news).

python nba_news.py

If you entered your own phone number in the “to” parameter, a text message should be sent to your phone!

Make an Inbound SMS

If there was NBA news in our response, we should have successfully sent an SMS containing Top Headlines around the league. Now we’re going to create part of our application for an Inbound SMS. Think of inbound as an inbound SMS triggering your application. In this case, we will be sending a text to a Twilio phone number (our trigger), then having it respond by sending a reply containing news.

 

Create a new file (in the same directory) called app.py. Using Flask, a web framework for Python, we will create an app that runs on a local server. Copy the following code into app.py: 

from flask import Flask, request
from twilio.twiml.messaging_response import MessagingResponse


# we need to access the code we wrote earlier in this file
from nba_news import get_transactions

app = Flask(__name__)

@app.route("/nba", methods=['GET', 'POST'])
def incoming_sms():
    # take in user input, which is contents of a text message that a user sends
    user_input = request.values.get('Body', None)
    # call our function to get nba news and return it as a string 
    transactions = get_transactions(user_input)

    resp = MessagingResponse()
    # send a message that contains the string content
    resp.message(transactions)

    return str(resp)

if __name__ == "__main__":
    app.run(host='localhost', debug=True, port=8080)

Your application should be running on http://localhost:8080. Output will look similar to this:

 * Serving Flask app 'app' (lazy loading)
 * Environment: production
   WARNING: This is a development server. Do not use it in a production deployment.
   Use a production WSGI server instead.
 * Debug mode: on
 * Running on http://localhost:8080 (Press CTRL+C to quit)
 * Restarting with stat
 * Debugger is active!
 * Debugger PIN: 199-776-319

As of now, our application is only running on a server within your computer. But we need a public facing URL (not http://localhost) to configure a Webhook so Twilio can find it. By using a tool, called ngrok, we will “put localhost on the Internet” so we can configure our webhook.

ngrok http 8080

This will create a “tunnel” from the public Internet into port 8080 in our local machine, where the Flask app is listening for requests. You should see output similar to this:

ngrok interface in the console

Take note of the line that says “Forwarding”. In the image above, it shows:
https://5bad813c2718.ngrok.io -> http://localhost:8080

This means that our local application is running publicly on https://5bad813c2718.ngrok.io/nba

Within the Console, enter in the ngrok URL as a Webhook when “A Message Comes In”.

Setting up the webhook URL within the Twilio Console

Please be aware that unless you have an paid account, each time you run the ngrok command a new URL will be generated, so be sure to make the changes within the Twilio console.

Since our application and ngrok are running, we can send a text message to our Twilio phone number and it will respond back with NBA news!

List of recent NBA Headlines

If you text “F5” and no news has happened that day, you’ll receive a message like this:

What you receive if no news happens for the day

 

What if you don’t like basketball but want news for other sports?

Since we are using the SportsDataIO API, they provide developers with endpoints for multiple sports. If you aren’t interested in NBA news, check out the other sports from their API docs.

 

Furthermore, if you want to do something with player statistics, team standings, schedules, fantasy stats, and much more, just take a look at what SportsDataIO offers.

 

Show Me What You Build

Now that you can F5 from your phone, you won’t miss out on any Top Headlines in the NBA world. So keep, F5ing until the season starts on October 19, 2022.

 

Thanks so much for reading! If you found this tutorial helpful, have any questions, or want to show me what you’ve built, let me know online. And if you want to learn more about me, check out my intro blog post.

Picture of Me with my job title: developer evangelist

Anthony Dellavecchia is a Developer Evangelist at Twilio who writes code on stage in front of a crowd. He is an experienced software developer who teaches thousands of people how to change the world with code. His goal is to help you build deep experiences and connections with technology so that they stick with you forever.

Check him out online @anthonyjdella