X-Git-Url: http://gitweb.michael.orlitzky.com/?p=dead%2Fhalcyon.git;a=blobdiff_plain;f=src%2FTwitter%2FHttp.hs;h=eec7ab7187c56145ea5cce09603056e659b6c3c2;hp=d7135cec3b058b4c93093fafd572612625354666;hb=1b72ed45ef890ed1329a32457b4d7f3a7fb37788;hpb=69b8af30f49aaad0f5c051998d2556b9ec291df7 diff --git a/src/Twitter/Http.hs b/src/Twitter/Http.hs index d7135ce..eec7ab7 100644 --- a/src/Twitter/Http.hs +++ b/src/Twitter/Http.hs @@ -1,56 +1,95 @@ -module Twitter.Http +module Twitter.Http ( + get_user_new_statuses, + get_user_timeline, + http_get ) where -import Network.Curl -import System.IO (hPutStrLn, stderr) +import qualified Data.ByteString.Lazy as B ( ByteString ) +import qualified Data.ByteString.Char8 as BC ( pack ) +import Network.HTTP.Client ( + httpLbs, + newManager, + parseUrl, + responseBody ) +import Network.HTTP.Client.TLS ( tlsManagerSettings ) +import Web.Authenticate.OAuth ( + OAuth(..), + Credential, + newCredential, + newOAuth, + signOAuth ) --- |The API URL of username's timeline. +import Configuration ( Cfg(..) ) + + +-- | The API URL of username's timeline. -- -- See, -- --- +-- -- user_timeline_url :: String -> String user_timeline_url username = - concat [ "http://api.twitter.com/1/statuses/user_timeline.xml", - "?screen_name=" ++ username, - "&include_rts=true", - "&count=10" ] - --- |Given username's last status id, constructs the API URL for --- username's new statuses. Essentially, 'user_timeline_url' with a --- "since_id" parameter tacked on. + concat [ "https://api.twitter.com/", + "1.1/", + "statuses/", + "user_timeline.json?", + "screen_name=", + username, + "&include_rts=true&", + "count=10" ] + + +-- | Given username's last status id, constructs the API URL for +-- username's new statuses. Essentially, 'user_timeline_url' with a +-- \"since_id\" parameter tacked on. +-- user_new_statuses_url :: String -> Integer -> String user_new_statuses_url username last_status_id = - concat [ user_timeline_url username, - "&since_id=" ++ (show last_status_id) ] - - --- |Return's username's timeline, or 'Nothing' if there was an error. -get_user_timeline :: String -> IO (Maybe String) -get_user_timeline username = do - let uri = (user_timeline_url username) - timeline <- (http_get uri) - return timeline - - --- Returns the XML representing all of username's statuses that are --- newer than last_status_id. -get_user_new_statuses :: String -> Integer -> IO (Maybe String) -get_user_new_statuses username last_status_id = do - let uri = (user_new_statuses_url username last_status_id) - new_statuses <- (http_get uri) - return new_statuses - - --- |Uses the CURL API to retrieve uri. Returns 'Nothing' if there was --- an error. -http_get :: String -> IO (Maybe String) -http_get uri = withCurlDo $ do - resp <- curlGetString uri [CurlTimeout 45] - - case resp of - (CurlOK, body) -> return (Just body) - (code, _) -> do - hPutStrLn stderr ("HTTP Error: " ++ (show code)) - return Nothing + url ++ "&since_id=" ++ since_id + where + url = user_timeline_url username + since_id = show last_status_id + + +-- | Return's username's timeline. +-- +get_user_timeline :: Cfg -> String -> IO B.ByteString +get_user_timeline cfg username = do + let uri = user_timeline_url username + http_get cfg uri + + +-- | Returns the JSON representing all of username's statuses that are +-- newer than @last_status_id@. +-- +get_user_new_statuses :: Cfg -> String -> Integer -> IO B.ByteString +get_user_new_statuses cfg username last_status_id = do + let uri = user_new_statuses_url username last_status_id + http_get cfg uri + + +-- | Retrieve a URL, or crash. The request is signed using all of the +-- OAuth junk contained in the configuration. +-- +http_get :: Cfg -> String -> IO B.ByteString +http_get cfg url = do + manager <- newManager tlsManagerSettings + request <- parseUrl url + signed_request <- signOAuth oauth credential request + response <- httpLbs signed_request manager + return $ responseBody response + + where + consumer_key' = BC.pack (consumer_key cfg) + consumer_secret' = BC.pack (consumer_secret cfg) + access_token' = BC.pack (access_token cfg) + access_secret' = BC.pack (access_secret cfg) + + oauth :: OAuth + oauth = newOAuth { + oauthConsumerKey = consumer_key', + oauthConsumerSecret = consumer_secret' } + + credential :: Credential + credential = newCredential access_token' access_secret'