]> gitweb.michael.orlitzky.com - dead/halcyon.git/blob - src/Twitter/Http.hs
Add a farewell TODO list.
[dead/halcyon.git] / src / Twitter / Http.hs
1 module Twitter.Http (
2 get_user_new_statuses,
3 get_user_timeline,
4 http_get )
5 where
6
7 import qualified Data.ByteString.Lazy as B ( ByteString )
8 import qualified Data.ByteString.Char8 as BC ( pack )
9 import Network.Connection ( TLSSettings(..) )
10 import Network.HTTP.Client (
11 ManagerSettings,
12 httpLbs,
13 newManager,
14 parseUrl,
15 responseBody )
16 import Network.HTTP.Client.TLS ( mkManagerSettings )
17 import Web.Authenticate.OAuth (
18 OAuth(..),
19 Credential,
20 newCredential,
21 newOAuth,
22 signOAuth )
23
24 import Configuration ( Cfg(..) )
25
26
27 -- | The API URL of username's timeline.
28 --
29 -- See,
30 --
31 -- <https://dev.twitter.com/docs/api/1.1/get/statuses/user_timeline>
32 --
33 user_timeline_url :: String -> String
34 user_timeline_url username =
35 concat [ "https://api.twitter.com/",
36 "1.1/",
37 "statuses/",
38 "user_timeline.json?",
39 "screen_name=",
40 username,
41 "&include_rts=true&",
42 "count=10" ]
43
44
45 -- | Given username's last status id, constructs the API URL for
46 -- username's new statuses. Essentially, 'user_timeline_url' with a
47 -- \"since_id\" parameter tacked on.
48 --
49 -- Examples:
50 --
51 -- >>> user_new_statuses_url "someuser" 8675309
52 -- "https://api.twitter.com/1.1/statuses/user_timeline.json?screen_name=someuser&include_rts=true&count=10&since_id=8675309"
53 --
54 user_new_statuses_url :: String -> Integer -> String
55 user_new_statuses_url username last_status_id =
56 url ++ "&since_id=" ++ since_id
57 where
58 url = user_timeline_url username
59 since_id = show last_status_id
60
61
62 -- | Return's username's timeline.
63 --
64 get_user_timeline :: Cfg -> String -> IO B.ByteString
65 get_user_timeline cfg username = do
66 let uri = user_timeline_url username
67 http_get cfg uri
68
69
70 -- | Returns the JSON representing all of username's statuses that are
71 -- newer than @last_status_id@.
72 --
73 get_user_new_statuses :: Cfg -> String -> Integer -> IO B.ByteString
74 get_user_new_statuses cfg username last_status_id = do
75 let uri = user_new_statuses_url username last_status_id
76 http_get cfg uri
77
78
79 -- | The default 'tlsManagerSettings' attempts to verify the
80 -- certificate that we get from the server, but it's quite pointless
81 -- for our purposes.
82 --
83 -- The default 'tlsManagerSettings' is constructed is like,
84 --
85 -- tlsManagerSettings = mkManagerSettings def Nothing
86 --
87 -- and the 'def' passes in a 'TLSSettings' from
88 -- \"Network.Connection\". By constructing our own 'TLSSettings', we
89 -- can disable the certificate validation.
90 --
91 novalidate_tls_manager_settings :: ManagerSettings
92 novalidate_tls_manager_settings =
93 mkManagerSettings mytls Nothing
94 where
95 -- The first field is "disable validation"
96 mytls = TLSSettingsSimple True False False
97
98
99 -- | Retrieve a URL, or crash. The request is signed using all of the
100 -- OAuth junk contained in the configuration.
101 --
102 http_get :: Cfg -> String -> IO B.ByteString
103 http_get cfg url = do
104 manager <- newManager novalidate_tls_manager_settings
105 request <- parseUrl url
106 signed_request <- signOAuth oauth credential request
107 response <- httpLbs signed_request manager
108 return $ responseBody response
109
110 where
111 consumer_key' = BC.pack (consumer_key cfg)
112 consumer_secret' = BC.pack (consumer_secret cfg)
113 access_token' = BC.pack (access_token cfg)
114 access_secret' = BC.pack (access_secret cfg)
115
116 oauth :: OAuth
117 oauth = newOAuth {
118 oauthConsumerKey = consumer_key',
119 oauthConsumerSecret = consumer_secret' }
120
121 credential :: Credential
122 credential = newCredential access_token' access_secret'