-- | Various utilities to tweet using the twitter api -- -- Make sure you have a file credentials file (default the executable looks for is `.cred`) with the following info: -- -- @ -- -- api-key: API_KEY -- -- api-sec: API_SECRE -- -- tok: OAUTH_TOKEN -- -- tok-sec: TOKEN_SECRET -- -- @ module Web.Tweet ( -- * Functions to tweet basicTweet , thread , reply -- * Data type for a tweet , module Web.Tweet.Types -- * Various API calls , module Web.Tweet.API , module Web.Tweet.API.Internal -- * Functions to sign API requests , signRequest , oAuthMem , credentialMem -- * Functions to generate a URL string from a `Tweet` , urlString -- * Timeline filters , filterReplies , filterRTs , filterQuotes -- * Helper function to print a bird , bird ) where import Control.Lens import Control.Monad import Data.Default import Data.List.Split (chunksOf) import Data.Maybe import Web.Tweet.API import Web.Tweet.API.Internal import Web.Tweet.Sign import Web.Tweet.Types import Web.Tweet.Utils import Web.Tweet.Utils.API -- | Tweet a string given a path to credentials; return the id of the status. -- -- > basicTweet "On the airplane." ".cred" basicTweet :: String -> FilePath -> IO Int basicTweet contents = tweetData (mkTweet contents) -- | thread tweets together nicely. Takes a string, a list of handles to reply to, plus the ID of the status you're replying to. -- If you need to thread tweets without replying, pass a `Nothing` as the third argument. -- -- > thread "Hi I'm back in New York!" ["friend1","friend2"] Nothing 1 ".cred" thread :: String -> [String] -> Maybe Int -> Int -> FilePath -> IO () thread contents hs idNum num filepath = do let handleStr = concatMap ((++) " " . (++) "@") hs let content = take num . chunksOf (280-length handleStr) $ contents case idNum of (Just _) -> thread' content hs idNum filepath Nothing -> case content of [] -> pure () [x] -> void $ basicTweet x filepath y@(_:_) -> thread' y hs (Just 0) filepath -- | Helper function to make `thread` easier to write. thread' :: [String] -> [String] -> Maybe Int -> FilePath -> IO () thread' content hs idNum filepath = do let f str i = tweetData Tweet { _status = str, _handles = hs, _replyID = if i == 0 then Nothing else Just i } filepath let initial = f (head content) lastTweet <- foldr ((>=>) . f) initial content $ fromMaybe 0 idNum deleteTweet (fromIntegral lastTweet) filepath -- | Reply with a single tweet. Works the same as `thread` but doesn't take the fourth argument. -- -- > reply "Idk what that means" ["friend1"] (Just 189943500) ".cred" reply :: String -> [String] -> Maybe Int -> FilePath -> IO () reply contents hs idNum = thread contents hs idNum 1 -- | Make a `Tweet` with only the contents. mkTweet :: String -> Tweet mkTweet contents = over status (const contents) def