I. Background
In the past, whenever I wanted to find out when video games are releasing, I would have to consult a giant list of all release dates in a laundry list format (ex. 1, ex. 2). In an ideal world, it would be cool to have an app, something like Google Calendar, that could give me all of the games coming out in a given month, in a user friendly, digestible format.
I’ve been researching various API to see if there are open source API for video game data and after some digging around, I happened upon the IGDB API. They have pretty good documentation for getting up and running and have generous open source access.
II. Approach
As far as I can tell from the documentation, it’s not possible to request games releasing on a particular date, as the release_dates endpoint can only return a single game reference ID, so my approach is to request games with a version releasing in x month, and then transform + filter as needed to group together games based on release date.
The IGDB API has a pretty standard request flow — register your app (through Twitch), authenticate with a client id + client secret, then use the access token on subsequent requests — so it was fairly quick to get going. At first, I started playing around with the API in Postman to get a feel for the nuts and bolts of syntax. Once I had a sense of that, I played around with executing requests in a .py file, but I ran into some some trouble making requests (which were thankfully solved by using the python wrapper).
For my experiment, I do the following:
- send an authentication request (w/ client id and client secret)
- (use the access token in the response to make subsequent requests)
- request data for games releasing in a given month
- parse through the data in the response, transforming the data in the process
- write the output to a .txt file (in prod, would write to a db)
My general thinking is that, when the application handles this data on the front end, games would be displayed based on when they release (think something like the Mac Calendar app or Google Calendar).
III. API Transformation
My goal thus far has been to transform the API response grouping together games by release date. A example request + response I’ve gotten from this API looks like this:
Request URL:
POST https://api.igdb.com/v4/games/
Query:
fields name, release_dates.human, release_dates.date, release_dates.game.platforms.name;
where release_dates.date >= 1641016800;
limit 5;
Response (as an array of game objects):
[
{
"id": 52,
"name": "The Elder Scrolls: Arena",
"release_dates": [
{
"id": 97271,
"date": 764553600,
"game": {
"id": 52,
"platforms": [
{
"id": 6,
"name": "PC (Microsoft Windows)"
},
{
"id": 13,
"name": "DOS"
}
]
},
"human": "Mar 25, 1994"
},
]
},
]
The API response has games info with the ability to also query for release dates, which come as an array of individual platforms. My goal was to group the responses by date, similar to the below:
[
{
"date": "May 12, 2023",
"games": [
{
"name": "Zelda: Tears of the Kingdom",
"platforms": [
"Nintendo Switch",
]
},
{
"name": "The Tower Between Us",
"platforms": [
"PC (Microsoft Windows)"
]
},
],
},
{
"date": "May 24, 2023",
"games": [
{
"name": "Sunshine Shuffle",
"platforms": [
"PC",
"Nintendo Switch",
]
},
],
},
]
Parsing through the API response was tedious (and in this first iteration likely quite inefficient), but after lots of trial and error, I was able to transform the data into a readable and reliable format.
To execute the program through the command line, I can pass in a year and a month (similar to what I imagine on a typical client request), and can get back a list of games that are releasing in that target month!
I won’t go into the individual logic (some comments in the implementation), but below is the gist of the approach:
from igdb.wrapper import IGDBWrapper
import json, os, sys
month_dict = {'1' : 'Jan', '2' : 'Feb', '3' : 'Mar', '4' : 'Apr', '5' : 'May', '6' : 'Jun', '7' : 'Jul', '8' : 'Aug', '9' : 'Sep', '10' : 'Oct', '11' : 'Nov', '12' : 'Dec'}
def get_games_by_month(year, month):
wrapper = IGDBWrapper(
str(os.getenv('IGDB_CLIENT_ID'),
str(os.getenv('IGDB_AUTH_TOKEN')
)
api_request = wrapper.api_request(
'games',
'fields name, release_dates.date,
release_dates.human, release_dates.platform.name;' +
'where release_dates.y = ' + year +
'& release_dates.m = ' + month + ';
limit 500;'
).decode('utf-8')
response_data = json.loads(api_request)
date_map = []
# transform API response
for res in response_data:
game_release_dates = res['release_dates']
for platform_release in game_release_dates:
human_date = platform_release['human']
platform = platform_release['platform']['name']
selected_date = {}
## see if date already exists in date_map
for date_object in date_map:
if date_object['date'] == human_date:
selected_date = date_object
continue
## if date is present, update games and platforms
if bool(selected_date):
games_list = selected_date['games']
containsGame = False
## update platforms for games in the games_list
for game in games_list:
if game['name'] == res['name']:
game['platforms'].append(platform)
containsGame = True
continue
## add game for selected date if not added yet
if not containsGame:
games_list.append({
'name': res['name'],
'platforms' : [platform]
})
## add date to date_map if it doesn't exist in list
elif human_date[-4:] == year and
human_date[:3] == month_dict[month]:
entry = {}
entry['date'] = human_date
entry['games'] = [{
'name': res['name'],
'platforms' :[platform]
}]
date_map.append(entry)
# sort all of the dates
date_map.sort(key=lambda data: data['date'])
# dump everything into a file
json_dump = json.dumps(date_map, indent=4)
filename = "releases_" + year + "_" + month + ".txt"
f = open(filename, "w")
f.write(json_dump)
f.close()
IV. Considerations
Because game release dates are fairly static (there aren’t hundreds of games releasing every month and release dates aren’t updated often), I’m not too worried about the performance of this method. I imagine that most of these release dates could live in a database with a separate service listening for updates to release dates periodically.
Flow
Each time a user makes a request on the front end, the app first checks the database for information corresponding to that month. If it exists, return the requested info. If it doesn’t exist in the database (i.e. a query for that month has never been requested before), make a request to the IGDB API, perform some transformation, return the data to the client, and separately make sure to store that info in the database.
V. Next Steps
Now that I have something working locally, I think my next step is to look for an open source calendar component I can play around with. I’d love to open up localhost, have the calendar display the current month, with the games list populated as expected. I have a lot of ideas for potential features of this app (so maybe I should create a project board in Trello or something), but for now, I’m just focused on my next step.
Thanks for reading.