A small mashup of Upcoming and Last.fm, in Haskell

I wanted to play around with the recent XML and Curl libraries that were recently released by Galois, so I decided to write a mashup of Upcoming and Last.fm. In order for this code to run, you’ll also need to install the csv package for this.

The code is relatively straightforward: fetch the top artists for a given username, parse that csv-file, read the events in The Netherlands for every artist, and output every event. It works on the command line. Save this code as Upcoming.hs, then do runhaskell Upcoming.hs chrisflip, and replace chrisflip by your own last.fm username.

Enjoy!

module Main where
 
import Network.Curl
import Text.CSV
import Network.CGI (urlEncode)
import Text.XML.Light
import Data.Maybe (fromMaybe, fromJust)
import Control.Monad
import System.Environment (getArgs)
 
-- The top artists of last.fm
url u = "http://ws.audioscrobbler.com/1.0/user/" ++ u ++ "/topartists.txt"
 
-- Upcomings's country_id for The Netherlands 
country_id = "9"
upcoming_url artist =  "http://upcoming.yahooapis.com/services/rest/?api_key=" 
                    ++ apikey ++ "&method=event.search&search_text=" 
                    ++ urlEncode artist ++ "&country_id=" ++ country_id
apikey = "ee395ae6dd"
 
main = do
  [username] <- getArgs
  text <- unsafeCurlGetString (url username)
  let (Right a') = parseCSV (url username) text
      artists = getArtists a'
  mapM_ getEvents artists
 
-- The artist is always in the 3rd column of the csv-file
getArtists = map (!! 2) . filter (\x -> length x == 3)
 
getEvents artist = unsafeCurlGetString (upcoming_url artist) >>= processArtist artist
 
processArtist artist contents = do
  let eventEls = elChildren $ fromJust $ parseXMLDoc contents
  when (length eventEls > 0) $ do
    putStrLn artist
    putStrLn (replicate (length artist) '-')
    mapM_ processEvent eventEls
    putStrLn ""
 
processEvent evt = putStrLn $ title ++ " @ " ++ location ++ " [" ++ date ++ "]"
 where [title, location, date] = map fa ["name", "venue_name", "start_date"]
       fa n = fromJust $ findAttr (unqual n) evt
 
unsafeCurlGetString url = curlGetString url [] >>= return . snd

About this entry