Steamy Screenshots
My latest project is Steamy Screenshots (view source). It’s an app I made to extract colors from the screenshots people share on Steam. There’s no real usefulness to it, it was just a fun thing to do. You can look up a particular Steam user and view their newest fifty screenshots, or look at the newest screenshots shared for a particular game.
There are a few components to this app, and it’s more complicated than just JavaScript and HTML because, while Steam has a web API, it has no way of getting a given user or app’s screenshots. I had to build a web scraper to get images off of Steam’s community web site and turn those into an RSS feed or a JSON file, then serve those up for consumption by the Steamy Screenshots app.
- Sinatra API that uses Mechanize to:
- Scrape a Steam user’s screenshots page and produce an RSS feed;
- Scrape a Steam game’s screenshots page and produce JSON;
- Scrape an individual Steam screenshot details page and produce JSON with details about the game.
- Steamy Screenshots’ own Sinatra API that:
- Provides a JSON endpoint for getting a list of friends for a given Steam user;
- Caches the giant list of all Steam apps (games, their DLC, etc.) and serves it up as JSON;
- Serves up a lunr.js index of the Steam apps as JSON;
- Provides an endpoint for getting an image hosted elsewhere via its URL, to get around CORS.
- Steamy Screenshots’ JavaScript front end:
- Look up a Steam user by their name and see their latest screenshots;
- List a given user’s Steam friends so you can browse their screenshots;
- Search for a Steam game and see its latest screenshots that the community has shared;
- Get a palette of five colors for each screenshot.
I generate an RSS feed of a Steam user’s screenshots so I can consume that feed on If This Then That and have it post my screenshots to my Tumblr. That was the original impetus for the whole project: I wrote the web scraper Sinatra app so I could get an RSS feed of my own screenshots so they could auto-post to my Tumblr via IFTTT. Then I wanted to make something that built off of that RSS feed, and Steamy Screenshots was born.
For actually pulling colors out of a screenshot, I used lukasklein’s itunes-colors JavaScript implementation of Panic’s iTunes cover art Xcode project. The JavaScript uses an HTML5 canvas
to load the image, which fails when CORS headers are not set on the image host and the host is different from the host where you’re using the JavaScript. Hence the need for a server-side endpoint that pulls down a given image and serves it up from the same host as the JavaScript.
One thing I did differently with Steamy Screenshots than what I normally do with single-page JavaScript applications is I didn’t use any JavaScript framework. No AngularJS, no React, not even Backbone.js. I even wrote raw JavaScript instead of CoffeeScript. I did use jQuery for DOM manipulation. It was a new experience having to figure out how to detect changes to the hash component of the URL and hook that up to actually do anything. I’m so used to using a JavaScript framework that includes such niceties.
Once I get the colors, I use jQuery to grab parts of the page like the links, the header, and the body, then apply text and background colors. I also show little color swatches that, when clicked, use ZeroClipboard to copy the hex color code. I’m a big fan of COLOURlovers myself, so Steamy Screenshots provides a link to make a color palette consisting of the extracted colors. The itunes-colors JavaScript only extracts four colors while a COLOURlovers palette can have five colors, so I generate the fifth color using TinyColor based on one of the extracted colors.
To get the screenshots for a Steam game, I need to know its ID on Steam. To get that, I use lunr.js to let the user search the big JSON file of Steam apps that my app serves up. That’s what translates a user’s query of “oblivion” into a list of relevant Steam apps; when the user chooses the one titled “The Elder Scrolls IV: Oblivion”, I turn that into app ID 22330 and can then get the screenshots off of its Steam community page. I added a couple of scripts to my package.json for updating both the list of apps as well as the lunr.js index, using lunr-index-build for index generation.
I missed using a JavaScript framework when it came to code organization. All the JavaScript is in one big file, which of course turned into a mangle of jQuery callbacks. I didn’t use any JavaScript “classes” for code organization—the functions are just defined out in front of God and everybody. It’s not tested either. Basically, this app is not one I would show off as an example of my cleanest code. If I get a wild hair at some point, I’ll probably go back and refactor the thing to use a framework, split the code into different files, and switch to CoffeeScript.