packages feed

tweet-hs 1.0.1.9 → 1.0.1.21

raw patch · 10 files changed

+117/−117 lines, 10 filesdep +htoml-megaparsecdep −QuickCheckdep −htomlPVP: major bump suggested

API removals or changes: PVP suggests a major version bump

Dependencies added: htoml-megaparsec

Dependencies removed: QuickCheck, htoml

API changes (from Hackage documentation)

+ Web.Tweet.Utils: bird :: String
+ Web.Tweet.Utils: displayTimeline :: Timeline -> String
+ Web.Tweet.Utils: displayTimelineColor :: Timeline -> String
+ Web.Tweet.Utils: filterQuotes :: Timeline -> Timeline
+ Web.Tweet.Utils: filterRTs :: Timeline -> Timeline
+ Web.Tweet.Utils: filterReplies :: Timeline -> Timeline
+ Web.Tweet.Utils: getConfigData :: FilePath -> IO [(ByteString, ByteString)]
+ Web.Tweet.Utils: getTweets :: ByteString -> Either (ParseError Char Void) Timeline
+ Web.Tweet.Utils: getTweetsFast :: ByteString -> Either String Timeline
+ Web.Tweet.Utils: hits :: Timeline -> Timeline
+ Web.Tweet.Utils: hits' :: Timeline -> Timeline
+ Web.Tweet.Utils: lineByKey :: ByteString -> [(ByteString, ByteString)] -> ByteString
- Web.Tweet.API: sendDMRaw :: String -> [Char] -> FilePath -> IO ByteString
+ Web.Tweet.API: sendDMRaw :: String -> String -> FilePath -> IO ByteString

Files

README.md view
@@ -1,5 +1,6 @@ # Command Line Interface Tweeter +[![Windows build status](https://ci.appveyor.com/api/projects/status/github/vmchale/command-line-tweeter?svg=true)](https://ci.appveyor.com/project/vmchale/command-line-tweeter) [![Build Status](https://travis-ci.org/vmchale/command-line-tweeter.svg?branch=master)](https://travis-ci.org/vmchale/command-line-tweeter)  ![Displaying a user timeline in a terminal.](https://raw.githubusercontent.com/vmchale/command-line-tweeter/master/screenshot.png)
bench/Bench.hs view
@@ -13,15 +13,15 @@ setupEnv' = readFile "test/data"  main :: IO ()-main = do+main =     defaultMain [-                env setupEnv $ \ ~file ->-                bgroup "aeson parser"-                      [ bench "226" $ whnf fast file ]-                , env setupEnv' $ \ ~file ->-                  bgroup "handrolled parser"-                      [ bench "226" $ whnf (parse parseTweet) file ]-                ]+            env setupEnv $ \ file ->+            bgroup "aeson parser"+                  [ bench "226" $ whnf fast file ]+            , env setupEnv' $ \ file ->+              bgroup "handrolled parser"+                  [ bench "226" $ whnf (parse parseTweet) file ]+            ]     where         fast = fmap (fmap fromFast) . fastParse 
src/Web/Tweet.hs view
@@ -63,8 +63,8 @@ -- > 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 (140-(length handleStr))) $ contents+    let handleStr = concatMap ((++) " " . (++) "@") hs+    let content = take num . chunksOf (140-length handleStr) $ contents     case idNum of         (Just _) -> thread' content hs idNum filepath         Nothing -> case content of@@ -75,9 +75,9 @@ -- | 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 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+    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.@@ -88,4 +88,4 @@  -- | Make a `Tweet` with only the contents. mkTweet :: String -> Tweet-mkTweet contents = over (status) (const (contents)) def+mkTweet contents = over status (const contents) def
src/Web/Tweet/API.hs view
@@ -15,14 +15,14 @@  -- | Get tweets (text only) for some user getMarkov :: String -> Maybe Int -> FilePath -> IO [String]-getMarkov = (fmap (map (view text))) .** getAll+getMarkov = fmap (map (view text)) .** getAll  -- | Get all tweets by some user getAll :: String -> Maybe Int -> FilePath -> IO Timeline getAll sn maxId filepath = do     tweets <- either (error "Parse tweets failed") id <$> getProfileMax sn 200 filepath maxId     let lastId = _tweetId . last $ tweets-    if (Just lastId) == maxId then+    if Just lastId == maxId then         pure []     else         do@@ -36,7 +36,7 @@     let requestString = urlString tweet     bytes <- postRequestMem ("https://api.twitter.com/1.1/statuses/update.json" ++ requestString) config     putStrLn $ displayTimelineColor . either (error "failed to parse tweet") id . getTweets . BSL.toStrict $ bytes-    pure . (view tweetId) . head . either (error "failed to parse tweet") id . getTweets . BSL.toStrict $ bytes+    pure . view tweetId . head . either (error "failed to parse tweet") id . getTweets . BSL.toStrict $ bytes  -- | tweet, given a `Tweet` and path to credentials. Return id of posted tweet. tweetData :: Tweet -> FilePath -> IO Int@@ -44,7 +44,7 @@     let requestString = urlString tweet     bytes <- postRequest ("https://api.twitter.com/1.1/statuses/update.json" ++ requestString) filepath -- FIXME fix the coloration     putStrLn $ displayTimelineColor . either (error "failed to parse tweet") id . getTweets . BSL.toStrict $ bytes-    pure . (view tweetId) . head . either (error "failed to parse tweet") id . getTweets . BSL.toStrict $ bytes+    pure . view tweetId . head . either (error "failed to parse tweet") id . getTweets . BSL.toStrict $ bytes  -- | Gets user profile with max_id set. getProfileMax :: String -> Int -> FilePath -> Maybe Int -> IO (Either (ParseError Char Void) Timeline)@@ -58,15 +58,15 @@ getProfileRaw :: String -> Int -> FilePath -> Maybe Int -> IO BSL.ByteString getProfileRaw sn count filepath maxId = getRequest ("https://api.twitter.com/1.1/statuses/user_timeline.json" ++ requestString) filepath     where requestString = case maxId of {-        (Just i) -> "?screen_name=" ++ sn ++ "&count=" ++ (show count) ++ "&max_id=" ++ (show i) ;-        Nothing -> "?screen_name=" ++ sn ++ "&count=" ++ (show count) }+        (Just i) -> "?screen_name=" ++ sn ++ "&count=" ++ show count ++ "&max_id=" ++ show i ;+        Nothing -> "?screen_name=" ++ sn ++ "&count=" ++ show count }  -- | Gets user profile with max_id set getProfileRawMem :: String -> Int -> Config -> Maybe Int -> IO BSL.ByteString getProfileRawMem sn count config maxId = getRequestMem ("https://api.twitter.com/1.1/statuses/user_timeline.json" ++ requestString) config     where requestString = case maxId of {-        (Just i) -> "?screen_name=" ++ sn ++ "&count=" ++ (show count) ++ "&max_id=" ++ (show i) ;-        Nothing -> "?screen_name=" ++ sn ++ "&count=" ++ (show count) }+        (Just i) -> "?screen_name=" ++ sn ++ "&count=" ++ show count ++ "&max_id=" ++ show i ;+        Nothing -> "?screen_name=" ++ sn ++ "&count=" ++ show count }  -- | Get mentions and parse response as a list of tweets mentions :: Int -> FilePath -> IO (Either (ParseError Char Void) Timeline)@@ -79,12 +79,12 @@ -- | Gets mentions mentionsRaw :: Int -> FilePath -> IO BSL.ByteString mentionsRaw count = getRequest ("https://api.twitter.com/1.1/statuses/mentions_timeline.json" ++ requestString)-    where requestString = "?count=" ++ (show count)+    where requestString = "?count=" ++ show count  -- | Gets mentions mentionsRawMem :: Int -> Config -> IO BSL.ByteString mentionsRawMem count = getRequestMem ("https://api.twitter.com/1.1/statuses/mentions_timeline.json" ++ requestString)-    where requestString = "?count=" ++ (show count)+    where requestString = "?count=" ++ show count  -- | Get user profile given screen name and how many tweets to return getProfile :: String -> Int -> FilePath -> IO (Either (ParseError Char Void) Timeline)@@ -92,19 +92,19 @@  -- | Mute a user given their screen name mute :: String -> FilePath -> IO ()-mute = (fmap void) . muteUserRaw+mute = fmap void . muteUserRaw  -- | Mute a user given their screen name muteMem :: String -> Config -> IO ()-muteMem = (fmap void) . muteUserRawMem+muteMem = fmap void . muteUserRawMem  -- | Unmute a user given their screen name unmute :: String -> FilePath -> IO ()-unmute = (fmap void) . unmuteUserRaw+unmute = fmap void . unmuteUserRaw  -- | Unmute a user given their screen name unmuteMem :: String -> Config -> IO ()-unmuteMem = (fmap void) . unmuteUserRawMem+unmuteMem = fmap void . unmuteUserRawMem  -- | Mute a user given their screen name muteUserRaw :: String -> FilePath -> IO BSL.ByteString@@ -125,37 +125,37 @@ -- | Get user's DMs. getDMsRaw :: Show p => p -> FilePath -> IO BSL.ByteString getDMsRaw count = getRequest ("https://api.twitter.com/1.1/direct_messages.json" ++ requestString)-    where requestString = "?count=" ++ (show count)+    where requestString = "?count=" ++ show count  -- | Get a user's favorites getFavorites :: Int -> String -> FilePath -> IO (Either (ParseError Char Void) Timeline)-getFavorites count = fmap (fmap (take count)) . (fmap (getTweets . BSL.toStrict)) .* favoriteTweetListRaw+getFavorites count = fmap (fmap (take count) . getTweets . BSL.toStrict) .* favoriteTweetListRaw  -- | Get a timeline getTimeline :: Int -> FilePath -> IO (Either (ParseError Char Void) Timeline)-getTimeline = (fmap (getTweets . BSL.toStrict)) .* getTimelineRaw+getTimeline = fmap (getTweets . BSL.toStrict) .* getTimelineRaw  -- | Get a timeline getTimelineMem :: Int -> Config -> IO (Either (ParseError Char Void) Timeline)-getTimelineMem = (fmap (getTweets . BSL.toStrict)) .* getTimelineRawMem+getTimelineMem = fmap (getTweets . BSL.toStrict) .* getTimelineRawMem  -- | Get a user's timeline and return response as a bytestring getTimelineRaw :: Int -> FilePath -> IO BSL.ByteString getTimelineRaw count = getRequest ("https://api.twitter.com/1.1/statuses/home_timeline.json" ++ requestString)-    where requestString = "?count=" ++ (show count)+    where requestString = "?count=" ++ show count  -- | Get a user's timeline and return response as a bytestring getTimelineRawMem :: Int -> Config -> IO BSL.ByteString getTimelineRawMem count = getRequestMem ("https://api.twitter.com/1.1/statuses/home_timeline.json" ++ requestString)-    where requestString = "?count=" ++ (show count)+    where requestString = "?count=" ++ show count  -- | Delete a tweet given its id deleteTweet :: Integer -> FilePath -> IO ()-deleteTweet = (fmap void) . deleteTweetRaw+deleteTweet = fmap void . deleteTweetRaw  -- | Delete a tweet given its id deleteTweetMem :: Integer -> Config -> IO ()-deleteTweetMem = (fmap void) . deleteTweetRawMem+deleteTweetMem = fmap void . deleteTweetRawMem  -- | Get response, i.e. the tweet deleted deleteTweetResponse :: Integer -> FilePath -> IO (Either (ParseError Char Void) Timeline)@@ -167,11 +167,11 @@  -- | Favorite a tweet given its id favoriteTweet :: Integer -> FilePath -> IO ()-favoriteTweet = (fmap void) . favoriteTweetRaw+favoriteTweet = fmap void . favoriteTweetRaw  -- | Favorite a tweet given its id favoriteTweetMem :: Integer -> Config -> IO ()-favoriteTweetMem = (fmap void) . favoriteTweetRawMem+favoriteTweetMem = fmap void . favoriteTweetRawMem  -- | Favorite a tweet and returned the (parsed) response favoriteTweetList :: String -> FilePath -> IO (Either (ParseError Char Void) Timeline)@@ -187,11 +187,11 @@  -- | Unfavorite a tweet given its id unfavoriteTweet :: Integer -> FilePath -> IO ()-unfavoriteTweet = (fmap void) . unfavoriteTweetRaw+unfavoriteTweet = fmap void . unfavoriteTweetRaw  -- | Unfavorite a tweet given its id unfavoriteTweetMem :: Integer -> Config -> IO ()-unfavoriteTweetMem = (fmap void) . unfavoriteTweetRawMem+unfavoriteTweetMem = fmap void . unfavoriteTweetRawMem  -- | Unfavorite a tweet and returned the (parsed) response unfavoriteTweetResponse :: Integer -> FilePath -> IO (Either (ParseError Char Void) Timeline)@@ -203,11 +203,11 @@  -- | Unretweet a tweet given its id unretweetTweet :: Integer -> FilePath -> IO ()-unretweetTweet = (fmap void) . unretweetTweetRaw+unretweetTweet = fmap void . unretweetTweetRaw  -- | Unretweet a tweet given its id unretweetTweetMem :: Integer -> Config -> IO ()-unretweetTweetMem = (fmap void) . unretweetTweetRawMem+unretweetTweetMem = fmap void . unretweetTweetRawMem  -- | Unretweet a tweet and returned the (parsed) response unretweetTweetResponse :: Integer -> FilePath -> IO (Either (ParseError Char Void) Timeline)@@ -219,43 +219,43 @@  -- | Unfollow a user given their screen name unfollow :: String -> FilePath -> IO ()-unfollow = (fmap void) . unfollowUserRaw+unfollow = fmap void . unfollowUserRaw  -- | Unfollow a user given their screen name unfollowMem :: String -> Config -> IO ()-unfollowMem = (fmap void) . unfollowUserRawMem+unfollowMem = fmap void . unfollowUserRawMem  -- | Follow a user given their screen name follow :: String -> FilePath -> IO ()-follow = (fmap void) . followUserRaw+follow = fmap void . followUserRaw  -- | Follow a user given their screen name followMem :: String -> Config -> IO ()-followMem = (fmap void) . followUserRawMem+followMem = fmap void . followUserRawMem  -- | Block a user given their screen name block :: String -> FilePath -> IO ()-block = (fmap void) . blockUserRaw+block = fmap void . blockUserRaw  -- | Block a user given their screen name blockMem :: String -> Config -> IO ()-blockMem = (fmap void) . blockUserRawMem+blockMem = fmap void . blockUserRawMem  -- | Unblock a user given their screen name unblock :: String -> FilePath -> IO ()-unblock = (fmap void) . unblockUserRaw+unblock = fmap void . unblockUserRaw  -- | Unblock a user given their screen name unblockMem :: String -> Config -> IO ()-unblockMem = (fmap void) . unblockUserRawMem+unblockMem = fmap void . unblockUserRawMem  -- | Retweet a tweet given its id retweetTweet :: Integer -> FilePath -> IO ()-retweetTweet = (fmap void) . retweetTweetRaw+retweetTweet = fmap void . retweetTweetRaw  -- | Retweet a tweet given its id retweetTweetMem :: Integer -> Config -> IO ()-retweetTweetMem = (fmap void) . retweetTweetRawMem+retweetTweetMem = fmap void . retweetTweetRawMem  -- | Retweet a tweet and returned the (parsed) response retweetTweetResponse :: Integer -> FilePath -> IO (Either (ParseError Char Void) Timeline)@@ -275,32 +275,32 @@  -- | Favorite a tweet given its id; return bytestring response favoriteTweetRaw :: Integer -> FilePath -> IO BSL.ByteString-favoriteTweetRaw idNum = postRequest ("https://api.twitter.com/1.1/favorites/create.json?id=" ++ (show idNum))+favoriteTweetRaw idNum = postRequest ("https://api.twitter.com/1.1/favorites/create.json?id=" ++ show idNum)  -- | Favorite a tweet given its idNum; return bytestring response favoriteTweetRawMem :: Integer -> Config -> IO BSL.ByteString-favoriteTweetRawMem idNum = postRequestMem ("https://api.twitter.com/1.1/favorites/create.json?id=" ++ (show idNum))+favoriteTweetRawMem idNum = postRequestMem ("https://api.twitter.com/1.1/favorites/create.json?id=" ++ show idNum)  -- | Retweet a tweet given its idNum; return bytestring response retweetTweetRaw :: Integer -> FilePath -> IO BSL.ByteString-retweetTweetRaw idNum = postRequest ("https://api.twitter.com/1.1/statuses/retweet/" ++ (show idNum) ++ ".json")+retweetTweetRaw idNum = postRequest ("https://api.twitter.com/1.1/statuses/retweet/" ++ show idNum ++ ".json")  -- | Retweet a tweet given its idNum; return bytestring response retweetTweetRawMem :: Integer -> Config -> IO BSL.ByteString-retweetTweetRawMem idNum = postRequestMem ("https://api.twitter.com/1.1/statuses/retweet/" ++ (show idNum) ++ ".json")+retweetTweetRawMem idNum = postRequestMem ("https://api.twitter.com/1.1/statuses/retweet/" ++ show idNum ++ ".json")  -- | Send a DM given text, screen name of recipient.-sendDMRaw :: String -> [Char] -> FilePath -> IO BSL.ByteString+sendDMRaw :: String -> String -> FilePath -> IO BSL.ByteString sendDMRaw txt sn = postRequest ("https://api.twitter.com/1.1/direct_messages/new.json?text=" ++ encoded ++ "&screen_name" ++ sn ++ ".json")     where encoded = strEncode txt  -- | Get DMs, return bytestring of response getDMs :: Int -> FilePath -> IO BSL.ByteString-getDMs count = getRequest ("https://dev.twitter.com/rest/reference/get/direct_messages.json?count=" ++ (show count))+getDMs count = getRequest ("https://dev.twitter.com/rest/reference/get/direct_messages.json?count=" ++ show count)  -- | Get DMs, return bytestring of response getDMMem :: Int -> Config -> IO BSL.ByteString-getDMMem count = getRequestMem ("https://dev.twitter.com/rest/reference/get/direct_messages.json?count=" ++ (show count))+getDMMem count = getRequestMem ("https://dev.twitter.com/rest/reference/get/direct_messages.json?count=" ++ show count)  -- | Follow a user given their screen name followUserRaw :: String -> FilePath -> IO BSL.ByteString@@ -336,24 +336,24 @@  -- | Unretweet a tweet given its id; return bytestring response unretweetTweetRaw :: Integer -> FilePath -> IO BSL.ByteString-unretweetTweetRaw idNum = postRequest ("https://api.twitter.com/1.1/statuses/unretweet/" ++ (show idNum) ++ ".json")+unretweetTweetRaw idNum = postRequest ("https://api.twitter.com/1.1/statuses/unretweet/" ++ show idNum ++ ".json")  -- | Unretweet a tweet given its idNum; return bytestring response unretweetTweetRawMem :: Integer -> Config -> IO BSL.ByteString-unretweetTweetRawMem idNum = postRequestMem ("https://api.twitter.com/1.1/statuses/unretweet/" ++ (show idNum) ++ ".json")+unretweetTweetRawMem idNum = postRequestMem ("https://api.twitter.com/1.1/statuses/unretweet/" ++ show idNum ++ ".json")  -- | Unfavorite a tweet given its idNum; return bytestring response unfavoriteTweetRaw :: Integer -> FilePath -> IO BSL.ByteString-unfavoriteTweetRaw idNum = postRequest ("https://api.twitter.com/1.1/favorites/destroy.json?id=" ++ (show idNum))+unfavoriteTweetRaw idNum = postRequest ("https://api.twitter.com/1.1/favorites/destroy.json?id=" ++ show idNum)  -- | Unfavorite a tweet given its idNum; return bytestring response unfavoriteTweetRawMem :: Integer -> Config -> IO BSL.ByteString-unfavoriteTweetRawMem idNum = postRequestMem ("https://api.twitter.com/1.1/favorites/destroy.json?id=" ++ (show idNum))+unfavoriteTweetRawMem idNum = postRequestMem ("https://api.twitter.com/1.1/favorites/destroy.json?id=" ++ show idNum)  -- | Delete a tweet given its idNum; return bytestring response deleteTweetRaw :: Integer -> FilePath -> IO BSL.ByteString-deleteTweetRaw idNum = postRequest ("https://api.twitter.com/1.1/statuses/destroy/" ++ (show idNum) ++ ".json")+deleteTweetRaw idNum = postRequest ("https://api.twitter.com/1.1/statuses/destroy/" ++ show idNum ++ ".json")  -- | Delete a tweet given its idNum; return bytestring response deleteTweetRawMem :: Integer -> Config -> IO BSL.ByteString-deleteTweetRawMem idNum = postRequestMem ("https://api.twitter.com/1.1/statuses/destroy/" ++ (show idNum) ++ ".json")+deleteTweetRawMem idNum = postRequestMem ("https://api.twitter.com/1.1/statuses/destroy/" ++ show idNum ++ ".json")
src/Web/Tweet/API/Internal.hs view
@@ -16,23 +16,23 @@  -- | Show the most successful tweets by a given user, given their screen name. showBest :: String -> Int -> Bool -> FilePath -> IO String-showBest sn n color = fmap (showTweets color . pure . (take n . hits)) . getAll sn Nothing+showBest sn n color = fmap (showTweets color . pure . take n . hits) . getAll sn Nothing  -- | Show the most successful tweets by a given user, given their screen name. Additionally filter out replies. showBest' :: String -> Int -> Bool -> FilePath -> IO String-showBest' sn n color = fmap (showTweets color . pure . (take n . hits')) . getAll sn Nothing+showBest' sn n color = fmap (showTweets color . pure . take n . hits') . getAll sn Nothing  -- | Display user timeline showTimeline :: Int -> Bool -> FilePath -> IO String-showTimeline count color = (fmap (showTweets color)) . getTimeline count+showTimeline count color = fmap (showTweets color) . getTimeline count  showFilteredTL :: [Filter] -> String -> Int -> Bool -> FilePath -> IO String-showFilteredTL filters sn count color = (fmap (showTweets color . fmap (foldr (.) id filters))) . getProfile sn count+showFilteredTL filters sn count color = fmap (showTweets color . fmap (foldr (.) id filters)) . getProfile sn count  -- | Display user timeline in color, as appropriate showTweets :: Bool -> Either (ParseError Char Void) Timeline -> String-showTweets color = (either show id) . (fmap (if color then displayTimelineColor else displayTimeline))+showTweets color = either show id . fmap (if color then displayTimelineColor else displayTimeline)  -- | Display a user's favorites showFavorites :: Int -> String -> Bool -> FilePath -> IO String-showFavorites count sn color = (fmap (showTweets color)) . getFavorites count sn+showFavorites count sn color = fmap (showTweets color) . getFavorites count sn
src/Web/Tweet/Exec.hs view
@@ -124,12 +124,12 @@ selectCommand (Unmute sn) _ file = do     unmute sn file     putStrLn ("..." ++ sn ++ " unmuted successfully")-selectCommand (Dump sn) _ file = BSL.putStrLn =<< (getProfileRaw sn 3200 file Nothing)+selectCommand (Dump sn) _ file = BSL.putStrLn =<< getProfileRaw sn 3200 file Nothing  -- | Parser to return a program datatype program :: Parser Program program = Program-    <$> (hsubparser+    <$> hsubparser         (command "send" (info tweet (progDesc "Send a tweet from the command-line"))         <> command "input" (info tweetInput (progDesc "Send a tweet from stdIn"))         <> command "view" (info timeline (progDesc "Get your timeline"))@@ -149,8 +149,8 @@         <> command "unblock" (info unblockParser (progDesc "Unblock a user"))         <> command "mute" (info muteParser (progDesc "Mute a user"))         <> command "unmute" (info unmuteParser (progDesc "Unmute a user"))-        <> command "mentions" (info mentionsParser (progDesc "Fetch mentions"))))-    <*> (optional $ strOption+        <> command "mentions" (info mentionsParser (progDesc "Fetch mentions")))+    <*> optional (strOption         (long "cred"         <> short 'c'         <> metavar "CREDENTIALS"@@ -164,7 +164,7 @@ -- | Parser for the view subcommand timeline :: Parser Command timeline = Timeline-    <$> (optional $ read <$> strOption+    <$> optional (read <$> strOption         (long "count"         <> short 'n'         <> metavar "NUM"@@ -197,7 +197,7 @@ -- | Parser for the list subcommand list :: Parser Command list = List-    <$> (optional $ read <$> strOption+    <$> optional (read <$> strOption         (long "count"         <> short 'n'         <> metavar "NUM"@@ -240,14 +240,14 @@  -- | Parser for the del subcommand getInt :: Parser Integer-getInt = read <$> (argument str+getInt = read <$> argument str     (metavar "TWEET_ID"-    <> help "ID of tweet"))+    <> help "ID of tweet")  -- | Parser for the user subcommand profile :: Parser Command profile = Profile-    <$> (optional $ read <$> strOption+    <$> optional (read <$> strOption         (long "count"         <> short 'n'         <> metavar "NUM"@@ -265,7 +265,7 @@ -- | Parser for the mention subcommand mentionsParser :: Parser Command mentionsParser = Mentions-    <$> (optional $ read <$> strOption+    <$> optional (read <$> strOption         (long "count"         <> short 'n'         <> metavar "NUM"@@ -277,7 +277,7 @@     <$> argument str         (metavar "SCREEN_NAME"         <> help "Screen name of user you want to view.")-    <*> (optional $ read <$> strOption+    <*> optional (read <$> strOption         (long "count"         <> short 'n'         <> metavar "NUM"@@ -290,36 +290,36 @@ -- | Parser for the send subcommand tweet :: Parser Command tweet = Send-    <$> (optional $ read <$> strOption+    <$> optional (read <$> strOption         (long "tweets"         <> short 't'         <> metavar "NUM"         <> help "Number of tweetInputs in a row, default 15"))-    <*> (optional $ strOption+    <*> optional (strOption         (long "reply"         <> short 'r'         <> help "id of status to reply to - be sure to include their handle, e.g. @my_build_errors"))-    <*> (optional (some $ strOption+    <*> optional (some $ strOption         (long "handle"         <> short 'h'         <> metavar "HANDLE1"-        <> help "h to include in replies")))-    <*> (unwords <$> (some $ argument str+        <> help "h to include in replies"))+    <*> (unwords <$> some (argument str         (metavar "TEXT"         <> help "text of tweet to be sent")))  -- | Parser for the input command tweetInput :: Parser Command tweetInput = SendInput-    <$> (optional $ read <$> strOption+    <$> optional (read <$> strOption         (long "tweets"         <> short 't'         <> metavar "NUM"         <> help "Number of tweets in a row, default 15"))-    <*> (optional $ strOption+    <*> optional (strOption         (long "reply"         <> short 'r'         <> help "id of status to reply to - be sure to include their handle, e.g. @my_build_errors"))-    <*> (optional (some $ argument str+    <*> optional (some $ argument str         (metavar "HANDLE1"-        <> help "h to include in replies")))+        <> help "h to include in replies"))
src/Web/Tweet/Utils.hs view
@@ -37,15 +37,15 @@  -- | Filter out retweets filterRTs :: Timeline -> Timeline-filterRTs = filter ((/="RT @") . take 4 . (view text))+filterRTs = filter ((/="RT @") . take 4 . view text)  -- | Filter out replies filterReplies :: Timeline -> Timeline-filterReplies = filter ((/="@") . take 1 . (view text))+filterReplies = filter ((/="@") . take 1 . view text)  -- | Filter out quotes filterQuotes :: Timeline -> Timeline-filterQuotes = filter ((==Nothing) . (view quoted))+filterQuotes = filter ((==Nothing) . view quoted)  -- | Get a list of tweets from a response, returning author, favorites, retweets, and content. getTweets :: BS2.ByteString -> Either (ParseError Char Void) Timeline@@ -58,7 +58,7 @@  -- | Display Timeline without color displayTimeline :: Timeline -> String-displayTimeline ((TweetEntity content u sn idTweet _ Nothing rts fave):rest) = concat [u+displayTimeline (TweetEntity content u sn idTweet _ Nothing rts fave:rest) = concat [u     , " ("     , sn     , ")"@@ -75,7 +75,7 @@     , show idTweet     ,"\n\n"     ,displayTimeline rest]-displayTimeline ((TweetEntity content u sn idTweet _ (Just q) rts fave):rest) = concat [u+displayTimeline (TweetEntity content u sn idTweet _ (Just q) rts fave:rest) = concat [u     , " ("     , sn     , ")"@@ -100,11 +100,11 @@ displayTimeline [] = []  bird :: String-bird = toPlainBlue $ "🐦\n"+bird = toPlainBlue "🐦\n"  -- | Display Timeline in color displayTimelineColor :: Timeline -> String-displayTimelineColor ((TweetEntity content u sn idTweet _ Nothing rts fave):rest) = concat [toYellow u+displayTimelineColor (TweetEntity content u sn idTweet _ Nothing rts fave:rest) = concat [toYellow u     , " ("     , sn     , ")"@@ -120,7 +120,7 @@     , toBlue (show idTweet)     , "\n\n"     , displayTimelineColor rest]-displayTimelineColor ((TweetEntity content u sn idTweet _ (Just q) rts fave):rest) = concat [toYellow u+displayTimelineColor (TweetEntity content u sn idTweet _ (Just q) rts fave:rest) = concat [toYellow u     , " ("     , sn     , ")"@@ -164,11 +164,11 @@  -- | Filter a line of a file for only the actual data and no descriptors filterLine :: String -> String-filterLine = reverse . (takeWhile (not . (`elem` (" :" :: String)))) . reverse+filterLine = reverse . takeWhile (not . (`elem` (" :" :: String))) . reverse  -- | Get pairs of "key" to search for and actual values getConfigData :: FilePath -> IO [(BS.ByteString, BS.ByteString)] getConfigData filepath = zip <$> keys <*> content-    where content = (map (BS.pack . filterLine)) . lines <$> file-          keys    = (map (BS.pack . keyLinePie)) . lines <$> file+    where content = map (BS.pack . filterLine) . lines <$> file+          keys    = map (BS.pack . keyLinePie) . lines <$> file           file    = readFile filepath
src/Web/Tweet/Utils/API.hs view
@@ -51,7 +51,7 @@ responseBS request manager = do     response <- httpLbs request manager     let code = statusCode $ responseStatus response-    putStr $ if (code == 200) then "" else "failed :(\n error code: " ++ (show code) ++ "\n"+    putStr $ if code == 200 then "" else "failed :(\n error code: " ++ show code ++ "\n"     pure . responseBody $ response  -- | print output of a request and return status id as an `Int`.@@ -68,7 +68,7 @@                          , BS.unpack (tweetEncode tweet)                          , "&trim_user="                          , map toLower (show trim)-                         , (if isJust (_replyID tweet) then "&in_reply_to_status_id=" else "")+                         , if isJust (_replyID tweet) then "&in_reply_to_status_id=" else ""                          , reply ]     where trim  = False           reply = fromMaybe "" (show <$> _replyID tweet)@@ -81,5 +81,5 @@ tweetEncode :: Tweet -> BS.ByteString tweetEncode tweet = paramEncode . encodeUtf8 $ handleStr `T.append` content     where content   = T.pack . _status $ tweet-          handleStr = T.pack $ concatMap ((++ " ") . ((++) "@")) hs+          handleStr = T.pack $ concatMap ((++ " ") . (++) "@") hs           hs        = _handles tweet
test/Spec.hs view
@@ -8,12 +8,12 @@ import           Web.Tweet.Sign  main :: IO ()-main = hspec $ do+main = hspec $     describe "fastParse" $ do-        -- file <- runIO $ BS.readFile "test/data"-        config <- runIO $ (<> "/.cred") <$> getEnv "HOME"-        configToml <- runIO $ (<> "/.cred.toml") <$> getEnv "HOME"-        parallel $ it "parses sample tweets wrong" $ do-            fastParse "" `shouldBe` Left "Error in $: not enough input"-        parallel $ it "parses a config file the same way with the toml parser" $-            ((==) <$> mkConfigToml configToml <*> mkConfig config) >>= (`shouldBe` True)+    -- file <- runIO $ BS.readFile "test/data"+    config <- runIO $ (<> "/.cred") <$> getEnv "HOME"+    configToml <- runIO $ (<> "/.cred.toml") <$> getEnv "HOME"+    parallel $ it "parses sample tweets wrong" $+        fastParse "" `shouldBe` Left "Error in $: not enough input"+    parallel $ it "parses a config file the same way with the toml parser" $+        ((==) <$> mkConfigToml configToml <*> mkConfig config) >>= (`shouldBe` True)
tweet-hs.cabal view
@@ -1,5 +1,5 @@ name:                tweet-hs-version:             1.0.1.9+version:             1.0.1.21 synopsis:            Command-line tool for twitter description:         a Command Line Interface Tweeter homepage:            https://github.com/vmchale/command-line-tweeter#readme@@ -43,8 +43,9 @@                      , Web.Tweet.Parser                      , Web.Tweet.Sign                      , Web.Tweet.API-  other-modules:       Web.Tweet.Types                      , Web.Tweet.Utils+                     -- FIXME move to other-modules!!+  other-modules:       Web.Tweet.Types                      , Web.Tweet.Utils.Colors                      , Web.Tweet.API.Internal                      , Web.Tweet.Utils.API@@ -60,7 +61,7 @@                      , optparse-applicative                       , lens                      , unordered-containers-                     , htoml+                     , htoml-megaparsec                      , data-default                      , text                      , containers@@ -116,8 +117,6 @@   build-depends:       base                      , tweet-hs                      , hspec-                     , QuickCheck-                     , bytestring   if flag(development)     ghc-options:       -Werror   ghc-options:         -threaded -rtsopts -with-rtsopts=-N -Wall -Wincomplete-uni-patterns -Wincomplete-record-updates