-
Notifications
You must be signed in to change notification settings - Fork 3
Expand file tree
/
Copy pathMain.hs
More file actions
167 lines (152 loc) · 6.59 KB
/
Main.hs
File metadata and controls
167 lines (152 loc) · 6.59 KB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
141
142
143
144
145
146
147
148
149
150
151
152
153
154
155
156
157
158
159
160
161
162
163
164
165
166
167
{-
Author: Pranav Vishnu Ramabhadran
-}
{-# LANGUAGE OverloadedStrings, DeriveGeneric #-}
import Data.ByteString (ByteString)
import Data.ByteString.Char8 (pack)
import Network.HTTP.Conduit
import Web.Authenticate.OAuth
import Data.Aeson
import Data.Time.Clock (UTCTime)
import Data.Text (Text)
import GHC.Generics
import Control.Concurrent.Timer.Lifted
import Control.Concurrent.Suspend.Lifted
import qualified Responses as R
-- ||| Private Keys and Credentials
myoauth :: OAuth
myoauth =
newOAuth { oauthServerName = "api.twitter.com"
, oauthConsumerKey = "your consumer key here"
, oauthConsumerSecret = "your consumer secret here"
}
mycred :: Credential
mycred = newCredential "your access token here"
"your access token secret here"
-- ||| Functions that interact with the Twitter API
-- | This function reads a timeline JSON and parse it using the 'Tweet' type.
timeline :: String -- ^ Screen name of the user
-> IO (Either String [R.Tweet]) -- ^ If there is any error parsing the JSON data, it
-- will return 'Left String', where the 'String'
-- contains the error information.
timeline name = do
-- Firstly, we create a HTTP request with method GET.
req <- parseUrl $ "https://api.twitter.com/1.1/statuses/user_timeline.json?screen_name=" ++ name
-- Using a HTTP manager, we authenticate the request and send it to get a response.
res <- withManager $ \m -> do
-- OAuth Authentication. 'signOAuth' modifies the HTTP header adding the
-- appropriate authentication.
signedreq <- signOAuth myoauth mycred req
-- Send request.
httpLbs signedreq m
-- Decode the response body.
return $ eitherDecode $ responseBody res
-- | This function takes a string to tweet out and sends a POST reqeuest to do so.
tweet :: String -- ^ String to tweet out
-> IO (Either String R.Tweet) -- ^ If there is any error parsing the JSON data, it
-- will return 'Left String', where the 'String'
-- contains the error information.
tweet text = do
-- Firstly, we create a HTTP request with method POST
req1 <- parseUrl $ "https://api.twitter.com/1.1/statuses/update.json"
let req = urlEncodedBody [("status", pack text)] req1 -- We need to use ByteStrings here
-- Using a HTTP manager, we authenticate the request and send it to get a response.
res <- withManager $ \m -> do
-- OAuth Authentication. 'signOAuth' modifies the HTTP header adding the
-- appropriate authentication.
signedreq <- signOAuth myoauth mycred req
-- Send request.
httpLbs signedreq m
-- Decode the response body.
return $ eitherDecode $ responseBody res
-- | This function reads the mentions JSON and parses it using the 'Tweet' type.
mentions :: String -- ^ ID of the most recent mention we've responded to
-> IO (Either String [R.Tweet]) -- ^ If there is any error parsing the JSON data, it
-- will return 'Left String', where the 'String'
-- contains the error information.
mentions sid = do
-- Firstly, we create a HTTP request with method GET.
req <- parseUrl $ "https://api.twitter.com/1.1/statuses/mentions_timeline.json?since_id=" ++ sid
-- Using a HTTP manager, we authenticate the request and send it to get a response.
res <- withManager $ \m -> do
-- OAuth Authentication. 'signOAuth' modifies the HTTP header adding the
-- appropriate authentication.
signedreq <- signOAuth myoauth mycred req
-- Send request.
httpLbs signedreq m
-- Decode the response body.
return $ eitherDecode $ responseBody res
-- | This function only returns mentions that we haven't yet looked at.
runMentions :: String -- ^ ID of the most recent mention we've responded to
-> IO() -- ^ Runs the code to check our file whether we've
-- already seen something of greater ID and finally,
-- stores the latest ID in our current query.
runMentions sid = do
-- First we read our file to find the most recent ID we have stored
old <- readFile "latest.txt"
-- First check whether we have any data stored in our local file
if (length old > 0)
then do
-- If this ID is greater than the input then use it, else use inputted ID
let d1 = read old :: Float
let d2 = read sid :: Float
if (d1 > d2)
then do
-- Get the list of mentions
ets <- mentions old
case ets of
Left err -> print err
Right ts -> do
let len = length ts
if (len > 0)
then do
-- If we have any new mentions, store the ID of the latest one
let top = head ts
writeFile "latest.txt" (show (R.id top))
mapM_ genResponse $ take 5 ts
else do
mapM_ genResponse $ take 1 ts
else do
-- Get the list of mentions
ets <- mentions sid
case ets of
Left err -> print err
Right ts -> do
let len = length ts
if (len > 0)
then do
-- If we have any new mentions, store the ID of the latest one
let top = head ts
writeFile "latest.txt" (show (R.id top))
mapM_ genResponse $ take 5 ts
else do
mapM_ genResponse $ take 1 ts
else do
-- Get the list of mentions
ets <- mentions sid
case ets of
Left err -> print err
Right ts -> do
let len = length ts
if (len > 0)
then do
-- If we have any new mentions, store the ID of the latest one
let top = head ts
writeFile "latest.txt" (show (R.id top))
mapM_ genResponse $ take 5 ts
else do
mapM_ genResponse $ take 1 ts
-- | Takes a tweet, finds the response and tweets it out.
genResponse :: R.Tweet -> IO (Either String R.Tweet)
genResponse twt = do
res <- R.respond twt
tweet res
-- | The actual work done by the main function.
runMain :: IO ()
runMain = do
runMentions "1"
-- | The main function. This just sets up a Timer.
main :: IO (Timer IO)
main = do
-- Starts a timer that runs realMain every 10 minutes
repeatedTimer runMain (mDelay 10)