Writing an Alfred extension with Ruby
Another month another side project.
TL;DR - I created an Alfred extension in Ruby, it’s easy you can fork my base to create your own.
If you just want the Spotify finder extension download it
I love Alfred,
It’s a great tool - I use it for tons of different stuff: Running programs, controlling my music, basic math and as a file manager. A couple of months back we wrote a small extension at work that talks to Flobot our bot that manages the TVs in the dev rooms so you can command it from Alfred. It was a nice experience but I didn’t get the chance to do anything else since then.
Yesterday someone approached me at work and asked me if there’s a way to control the Spotify player from Alfred. I showed him the extension that’s hosted on the Alfred site. He thanked me, but then asked if theres a way to actually play a specific song - I liked that idea and couldn’t find any extension that does, So I wrote one.
I knew that what I wanted to build was a simple extension that receives a track name in the Alfred query and just plays or queues it into your Spotify app, simple.
` play [track name] `
I started by checking the Spotify API and quickly found that they have a really nice API for searching for tracks and that it responds with something called a Spotify URI which is a unique identifier for a track, album or artist ALA spotify:track:6ZWn1MVUaBH2HNQobhMYeE
I went on to see what ways I have to control the Spotify player, I found that it supports some very basic commands in AppleScript and that one of those commands is a play command that receives a spotify URL and plays it.
There was also something called Libspotify but it was a lot more complex to set up and wouldn’t be relavent in an Alfred extension.
So after testing both API’s seperatly I started working on integrating them. I checked if there was an easy way to send a http request from the AppleScript so I could just query Spotify from the same script that controls the player I couldn’t find an easy way to so I decided to try and write the script in Ruby.
I wrote a small Ruby script that takes a search query as the program argument, send a http request to the Spotify API and parses the first track URL from it. I then found the supported command to run an AppleScript from the command line and using Tempfiles integrated both parts.
I now had a script that searched for a query, got the URI, created a temporary AppleScript that when run using the
osascript command plays the track that was found.
The only thing left was to package it into an Alfred extension.
I wanted my extension installation to be as simple as possible, Alfred extension are always really easy double-click installs and I didn’t want the fact that I used Ruby to make it any worse.
I found a cool extension that also ran Ruby - the conversion extension script and decided I liked the way they got around this issue - They created a temporary ruby file with the contents of the script, ran it and then removed it.
So I started working on a shell script that unloads my script into a tmp ruby file, runs it and deletes it.
To make that shell script I wrote a third ruby script
wrap.rb that will help me in development - what it does is take a ruby script and create a shell script from that that when run reopens the ruby file and etc.
I started writing code that read a Ruby script and tries to compress it into a single line without quotes until I figured out I’m heading towards the wrong solution.
I found that I can use a HEREDOC to write a multiline string into a file in the shell :)
> cat FILENAME <<EOF this is SPARTA! EOF
So my wrapper script is real simple, it just reads the content of the original script
run.rb and wraps it in 5 lines of shell that create a tmp file, dump the content into the tmp file, run it using
/usr/bin/env ruby $filename and then delete it - that’s it.
To “build” the extension all I have to do is run the
wrap.rb file it converts the
run.rb file into an
extension.sh file which I use to create an Alfred extension.
The only caveat is that I assume Ruby installed on the system which is builtin in the latest OSXs and I don’t rely on installed gems.
The script is easily replaceable and I can use this system to write more Ruby Alfred extension - and you can to. Just check out the GitHub repo.
You can download the extension or
Read the Readme and fork the code on GitHub
You should follow me on twitter @YonBergman and subscribe to my RSS
PS. 10 Bonus points if you checked what song I embeded earlier when talking about the Spotify API