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 +1/−0
- bench/Bench.hs +8/−8
- src/Web/Tweet.hs +5/−5
- src/Web/Tweet/API.hs +51/−51
- src/Web/Tweet/API/Internal.hs +6/−6
- src/Web/Tweet/Exec.hs +20/−20
- src/Web/Tweet/Utils.hs +11/−11
- src/Web/Tweet/Utils/API.hs +3/−3
- test/Spec.hs +8/−8
- tweet-hs.cabal +4/−5
README.md view
@@ -1,5 +1,6 @@ # Command Line Interface Tweeter +[](https://ci.appveyor.com/project/vmchale/command-line-tweeter) [](https://travis-ci.org/vmchale/command-line-tweeter) 
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