module Web.Last.Parsing where import qualified Web.Last.Types as Types import Prelude hiding ((.),id) import Control.Applicative import Text.JSON.Combinators token :: JSValTo Types.Token token = objOf $ ll "token" strJS topTracks :: JSValTo Types.TopTracks topTracks = objOf $ inObj "toptracks" $ return Types.TopTracks <*> ll "country" strJS <*> llArr "track" (ranked track) topArtists :: JSValTo Types.TopArtists topArtists = objOf $ inObj "topartists" $ return Types.TopArtists <*> ll "country" strJS <*> llArr "artist" (ranked artist) ranked :: JSValTo a -> JSValTo (Types.Ranked a) ranked pa = objOf (Types.Ranked <$> ll "rank" strJS) <*> pa track :: JSValTo Types.Track track = objOf $ return Types.Track <*> ll "name" strJS <*> ll "playcount" strJS <*> ll "mbid" strJS <*> ll "url" strJS <*> ll "streamable" streamProp <*> ll "artist" artist <*> llArr "image" image streamProp :: JSValTo Types.StreamProp streamProp = objOf $ return Types.StreamProp <*> ll "#text" strJS <*> ll "fulltrack" strJS artist :: JSValTo Types.Artist artist = objOf $ return Types.Artist <*> ll "name" strJS <*> ll "mbid" strJS <*> ll "url" strJS image :: JSValTo Types.Image image = objOf $ return Types.Image <*> ll "#text" strJS <*> ll "size" strJS events :: JSValTo Types.Events events = objOf $ inObj "events" $ return Types.Events <*> ll "location" strJS <*> llArr "event" event <*> do page <- ll "page" strJS total <- ll "totalpages" strJS return ((read page :: Int) < (read total :: Int)) event :: JSValTo Types.Event event = objOf $ return Types.Event <*> ll "id" strJS <*> ll "title" strJS <*> ll "artists" (objOf (ll "headliner" strJS)) <*> ll "artists" (objOf (llArr "artist" strJS)) <*> ll "venue" venue <*> ll "startDate" strJS <*> optional (ll "startTime" strJS) <*> ll "description" strJS <*> llArr "image" image <*> ll "attendance" strJS <*> ll "reviews" strJS <*> ll "tag" strJS <*> ll "url" strJS venue :: JSValTo Types.Venue venue = objOf $ return Types.Venue <*> ll "name" strJS <*> ll "location" location <*> ll "url" strJS location :: JSValTo Types.Location location = objOf $ return Types.Location <*> ll "geo:point" geoPoint <*> ll "country" strJS <*> ll "city" strJS <*> ll "street" strJS <*> ll "postalcode" strJS <*> ll "timezone" strJS geoPoint :: JSValTo Types.GeoPoint geoPoint = objOf $ return Types.GeoPoint <*> ll "geo:lat" strJS <*> ll "geo:long" strJS album :: JSValTo Types.Album album = objOf $ return Types.Album <*> ll "name" strJS <*> ll "artist" strJS <*> ll "id" strJS <*> ll "mbid" strJS <*> ll "url" strJS <*> ll "releasedate" strJS <*> llArr "image" image <*> ll "listeners" strJS <*> ll "playcount" strJS <*> ll "toptags" strJS <*> ll "wiki" albumWiki albumWiki :: JSValTo Types.AlbumWiki albumWiki = objOf $ return Types.AlbumWiki <*> ll "published" strJS <*> ll "summary" strJS <*> ll "content" strJS -- Album search doesnt work because the results returned contain much less info than the previous album openSearch :: Search a => JSValTo a -> JSValTo (Types.OpenSearch a) openSearch pa = objOf $ inObj "results" $ return Types.OpenSearch <*> ll "opensearch:Query" query <*> ll "opensearch:totalResult" strJS <*> ll "opensearch:startIndex" strJS <*> ll "opensearch:itemsPerPage" strJS <*> matchs pa query :: JSValTo Types.Query query = objOf $ return Types.Query <*> ll "#text" strJS <*> ll "role" strJS <*> ll "searchTerms" strJS <*> ll "startPage" strJS class Search a where matchs :: JSValTo a -> JSObjTo [a] instance Search Types.Album where matchs pa = ll "albummatches" $ objOf $ llArr "album" pa lastFMError :: JSValTo Types.LastFMError lastFMError = objOf $ return Types.LastFMError <*> ll "error" strJS <*> ll "message" strJS