Goodbye Fantasy Bots

After two years I decided to shutter the Fantasy Bots project. Thank you to all my beta testers who provided feedback along this journey. After starting a new job this spring the project was no longer a priority for me. It was humming along for a while but recently Yahoo! made some changes that prevented users from logging into the site. With fantasy baseball coming to an end, I decided this was as good of time as any to pull the plug.

The Coffee Machine Has WIFI Part II

After taking some time off from this experiment, some co-workers brought it back up and pushed me to keep trying. My prior attempt at finding a user manual failed so this time I took detailed pictures of the inside components and tried to find further information on how it works. Also with this further investigation I noticed a compact flash card inserted at the bottom of the main circuit board.

The first thing I did was research any model numbers found inside the unit. One of the identifiers on the main board led me to a user manual that also had information on the application that runs everything. Inside this manual was the default password for logging into the admin panel, could it be that easy… yes, yes it was. After digging around in the settings I found where to connect the machine to our WIFI, which means all my effort looking on the network last time was for nothing.

After further noodling with the admin side of the software, I turned to the compact flash card. The card was unreadable on OSX and Windows but after connecting it to a Linux virtual machine I was able to copy over all the contents. In an effort to keep myself from being the most hated person in the office by breaking the coffee machine, I ordered an identical compact flash card to experiment on.

In a perfect world, I would have been able to create an image of the CF card that could both be used for imaging the new card and also loading in a VM to test modifications on. Unfortunately, I was never able to get the machine to boot from this card. I believe there is something I missed in order to make it a bootable card. A co-worker mentioned some software that would clone the card but I never made it that far.

During a casual conversation about this I mention my fear of breaking the machine because of how much usage I saw in the log files. This sparked the interest of Ryan who took the logs files and created an API that could query the data. The idea is to create some sort of data visualization about coffee drinkers in the office. There is also the idea floating around to combine the coffee machine data with data from the bathroom door sensor that Alex installed. Please feel free to send us title suggestions for this combined data viz.

Getting Started With the Yahoo! Fantasy Sports API

When I first started building my fantasybots.com service, there were many hurdles I ran across while learning to work with the Yahoo! Sports API. First off, the documentation is horrible and has actually gotten worse over the years. Also, it appears community relations with independent developers were abandoned back in 2010. The following are some tips on getting setup using Node and Express.

Setting up Yahoo! app

Go to https://developer.yahoo.com/apps/create/ and create an app. The callback domain says optional but will need to be set for the way we will be doing authentication. This callback domain needs to be a domain you control and can be used for both development and production. Under API Permissions check the Fantasy Sports box and then click the create app button. This will give you the two OAuth keys needed for the next section.

Communicating with the API

While you could setup your own OAuth, I went with a library that took care of most of that along with making the API easier to work with. There are a few out there but I went with fantasy-sports. The documentation on GitHub is straight forward with plenty of code examples.

This library is setup for using the token stored in a browser cookie but I have had no problems storing the token on the back-end for automated request when the user is not on the site.

The API allows you to request JSON but it is very apparent that XML is the primary format. The returned JSON is very messy and overly complicated. Also, if you ever need to POST back to the API it only accepts XML.

Local development

Unfortunately, Yahoo! doesn’t allow you to set the callback domain to a localhost address, but it does allow you to use any subdomain of the url set. In order to have a development workflow that did not require pushing changes to a staging server, what I did was use ngrok. This is an amazing service that I use almost every day at home and work. If you pay for the service, they will allow you to setup your custom domain to tunnel traffic to your localhost environment https://ngrok.com/docs#custom-domains. Once all that is setup then local development is a breeze.

The Data

Be careful when working with the JSON returned from the API. It appears to just be a conversion of XML:

  players: {
    0: {
        player: [
                    player_key: "346.p.8851"
                }, {
                    player_id: "8851"
                }, {
                    name: {
                        full: "Devin Mesoraco",
                        first: "Devin",
                        last: "Mesoraco",
                        ascii_first: "Devin",
                        ascii_last: "Mesoraco"
                }, {
                    status: "DL"
                }, {
                    on_disabled_list: "1"
                }, {
                    editorial_player_key: "mlb.p.8851"
                }, {
                    editorial_team_key: "mlb.t.17"
                }, {
                    editorial_team_full_name: "Cincinnati Reds"
                }, {
                    editorial_team_abbr: "Cin"
                }, {
                    uniform_number: "39"
                }, {
                    display_position: "C"
                }, {
                    headshot: {
                        url: "http://l.yimg.com/iu/api/res/1.2/6lZ3W5sQgW6GvYDqstn64Q--/YXBwaWQ9c2hhcmVkO2NoPTIzMzY7Y3I9MTtjdz0xNzkwO2R4PTg1NztkeT0wO2ZpPXVsY3JvcDtoPTYwO3E9MTAwO3c9NDY-/https://s.yimg.com/xe/i/us/sp/v/mlb_cutout/players_l/20150406/8851.png",
                        size: "small"
                    image_url: "http://l.yimg.com/iu/api/res/1.2/6lZ3W5sQgW6GvYDqstn64Q--/YXBwaWQ9c2hhcmVkO2NoPTIzMzY7Y3I9MTtjdz0xNzkwO2R4PTg1NztkeT0wO2ZpPXVsY3JvcDtoPTYwO3E9MTAwO3c9NDY-/https://s.yimg.com/xe/i/us/sp/v/mlb_cutout/players_l/20150406/8851.png"
                }, {
                    is_undroppable: "0"
                }, {
                    position_type: "B"
                }, {
                    eligible_positions: [{
                        position: "C"
                    }, {
                        position: "Util"
                    }, {
                        position: "DL"

Here is where a library like lodash will come in handy. Also, a huge mistake I did was assume that an object in an array would always be in the same position. For example, { display_position: "C" } in the above JSON is at players['0'].player[0][10], however, if that player was no on the “DL” then the { status: "DL" } is left out and display_position then becomes players['0'].player[0][9]. So what you have to do is either loop through the player[0] array or use lodash to find the object by property.

There are many things I have encountered in my two years of working with this API. Feel free to reach out if you have any questions.

The Coffee Machine Has WIFI?

One day a new shiny office coffee machine showed up. Unlike the previous one, this machine had a large touchscreen instead of buttons. Of course, the first time I try to use it it locks up and says “trash full.” After tracking down the office manager, I watched her open the front, press a small button on the inside, enable the settings screen and that is when I saw a small WIFI icon in the bottom corner. This was the first time I thought about messing with it, but I didn’t have the time or any specific reason.

Fast forward a few months and I run into this wonderful article about automation and I now have a reason. How sweet would it be to initiate a cup of coffee from my desk then have it ready after walking across the office and up the stairs. However, our machine does not provide the cup. That means I either have to tackle anyone who tries to get in my way to chat or I have it wait after brewing and program a button to dispense. But that’s a problem that can be worried about once the experiment is successful.

After discussing this with a coworker, I decided to try and find the machine on our local network. Keep in mind I’m not a network guy and have never done anything like this before, but they make it look like so much fun on TV. He pointed me to a tool called NMAP and I started learning how to use it. In the meantime, he simply walked upstairs, opened the machine’s settings, and tried to find the IP address that way. Unfortunately, that section of the menu was password protected.

I decided to keep working on the network side and ran a scan of every IP in the network. A small part of me was afraid of receiving a call from the IT department, but I guess that didn’t trigger any warnings. The results were a very large list of ip addresses and open ports. I was able to filter out most results by eliminating any machine with anti-virus software. Anything with http/https was checked out in a browser and anything with ssh was inspected through the terminal. While I was unsuccessful in actually finding or gaining access to the coffee machine, I did find my way into a few printers and the smart TV.

The next step was to do a little research. Soon I realized trying to find user manuals was as sketchy as looking for random hardware drivers. I managed to find some promotional pdf’s and a few distributors of the machine but have yet to find any sort of service or user material. A few things that caught my eye were add on items to the product. The manufacture offers a paid service to remotely monitor your machine. Also, a credit card processor is an optional item. One would hope that these services have even the most basic of security. Perhaps thinking this wanna be hacker has any chance at cracking the machine is a bit of a stretch. Looks like this experiment will have to come down to good ol’ social engineering.

To be continued…

That New Blog Smell

It’s been a few years and this blog has become stagnant. Over that time I have worked on some interesting projects both at work and on the side and decided it’s time to share some of those stories. So just like most developers out there, the first thing I did instead of actually writing was rebuild the blog onto a new platform. If you build it, the words will come.

After a few times of the old WordPress site going down because of MySQL issues, I knew I wanted to rebuild it in something more stable. Static sites have become popular recently and I can see why. They offer performance and stability; just not a user friendly CMS for writers. However, as a developer, there are many options geared towards our crowd. I chose to use Octopress from a colleague recommendation. It runs on Jekyll which we have used many times around the office for small websites. I had a feeling using Jekyll for it’s intended purpose was going to be a lot smoother, especially with a framework like Octopress to bundle commonly used modifications. And I must say, so far I am very pleased.