{-# LANGUAGE ScopedTypeVariables #-} -- | Response module {-# OPTIONS_HADDOCK hide #-} module Network.Lastfm.Internal ( ResponseType(..) , callAPI, callAPIsigned, xml, json, (#) , module Network.Lastfm ) where import Control.Applicative ((<$>)) import Control.Arrow ((&&&), second) import Data.Function (on) import Data.List (sortBy) import Codec.Binary.UTF8.String (encodeString) import Data.ByteString.Lazy.Char8 (ByteString) import qualified Data.ByteString.Lazy.Char8 as BS import Data.Digest.Pure.MD5 (md5) import Data.URLEncoded (urlEncode, export) import Network.Curl import Network.Lastfm import Network.Lastfm.Error import Network.Lastfm.TH -- Send POST query to Lastfm API callAPI ∷ ResponseType → [(String, String)] → Lastfm Response callAPI t = query (parseError t) . insertType t . map (second encodeString) -- Send signed POST query to Lastfm API callAPIsigned ∷ ResponseType → Secret → [(String, String)] → Lastfm Response callAPIsigned t (Secret s) xs = query (parseError t) zs where ys = map (second encodeString) . filter (not . null . snd) $ xs zs = insertType t $ ("api_sig", sign ys) : ys sign ∷ [(String, String)] → String sign = show . md5 . BS.pack . (++ s) . concatMap (uncurry (++)) . sortBy (compare `on` fst) -- Insert desired response type into query insertType ∷ ResponseType → [(String, String)] → [(String, String)] insertType XML = id insertType JSON = (("format", "json") :) -- Try to find error message in Lastfm response parseError ∷ ResponseType → ByteString → Maybe LastfmError parseError XML = xmlError parseError JSON = jsonError query ∷ (ByteString → Maybe LastfmError) → [(String, String)] → IO (Either LastfmError Response) query γ xs = do (status, body) ← (respCurlCode &&& respBody) <$> curlResponse xs return $ case status of CurlOK → case γ body of Nothing → Right body Just n → Left n s → Left $ CurlError s curlResponse ∷ [(String, String)] → IO (CurlResponse_ [(String, String)] ByteString) curlResponse xs = withCurlDo $ curlGetResponse_ "http://ws.audioscrobbler.com/2.0/?" [ CurlPostFields . map (export . urlEncode) $ xs , CurlFailOnError False , CurlUserAgent "Mozilla/5.0 (X11; Linux x86_64; rv:10.0) Gecko/20100101 Firefox/10.0 Iceweasel/10.0" , CurlConnectTimeout 10 ] -- Construct query parameter (#) ∷ Argument a ⇒ a → (String, String) (#) x = (key x, value x)