tweet-hs 1.0.1.35 → 1.0.1.36
raw patch · 11 files changed
+465/−464 lines, 11 filesdep +microlensdep −lensdep ~base
Dependencies added: microlens
Dependencies removed: lens
Dependency ranges changed: base
Files
- app/Main.hs +317/−2
- cabal.project.local +3/−3
- src/Web/Tweet.hs +1/−1
- src/Web/Tweet/API.hs +2/−1
- src/Web/Tweet/Exec.hs +0/−325
- src/Web/Tweet/Parser.hs +2/−3
- src/Web/Tweet/Types.hs +1/−1
- src/Web/Tweet/Utils.hs +1/−1
- src/Web/Tweet/Utils/API.hs +1/−9
- test/Spec.hs +0/−2
- tweet-hs.cabal +137/−116
app/Main.hs view
@@ -1,6 +1,321 @@ module Main where -import Web.Tweet.Exec+import qualified Data.ByteString.Lazy.Char8 as BSL+import Data.Maybe+import Data.Version+import Options.Applicative+import Paths_tweet_hs+import System.Directory+import Web.Tweet +-- | Data type for our program: one optional path to a credential file, (optionally) the number of tweetInputs to make, the id of the status you're replying to, and a list of users you wish to mention.+data Program = Program { subcommand :: Command , cred :: Maybe FilePath , color :: Bool }++-- | Data type for a command+-- TODO add boolean option to show ids alongside tweets+data Command = Timeline { count :: Maybe Int }+ | SendInput { tweetInputs :: Maybe Int, replyId :: Maybe String, replyh :: Maybe [String] }+ | Profile { count :: Maybe Int , screenName'' :: Maybe String, withReplies :: Bool, withRetweets :: Bool }+ | Mentions { count :: Maybe Int }+ | Markov { screenName' :: String }+ | Send { tweets :: Maybe Int , replyId :: Maybe String , replyh :: Maybe [String] , userInput :: String }+ | Sort { screenName' :: String , count :: Maybe Int , includeReplies :: Bool }+ | Delete { twId :: Integer }+ | Fav { twId :: Integer }+ | Unfav { twId :: Integer }+ | Retweet { twId :: Integer }+ | Unretweet { twId :: Integer }+ | List { count :: Maybe Int , screenName' :: String }+ | Follow { screenName' :: String }+ | Unfollow { screenName' :: String }+ | Block { screenName' :: String }+ | Unblock { screenName' :: String }+ | Mute { screenName' :: String }+ | Unmute { screenName' :: String }+ | Dump { screenName' :: String }++-- | query twitter to post stdin with no fancy options+fromStdIn :: Int -> FilePath -> IO ()+fromStdIn = threadStdIn [] Nothing++-- | Tweet string given to us, as parsed from the command line+fromCLI :: String -> Int -> FilePath -> IO ()+fromCLI s = thread s [] Nothing++-- | Threaded tweetInputs from stdIn+threadStdIn :: [String] -> Maybe Int -> Int -> FilePath -> IO ()+threadStdIn hs idNum num filepath = do+ contents <- getContents+ thread contents hs idNum num filepath++-- | Executes parser main :: IO ()-main = exec+main = putStrLn bird >> execParser opts >>= select+ where+ versionInfo = infoOption ("tweet-hs version: " ++ showVersion version) (short 'v' <> long "version" <> help "Show version")+ opts = info (helper <*> versionInfo <*> program)+ (fullDesc+ <> progDesc "Tweet and view tweets"+ <> header "clit - a Command Line Interface Tweeter")++-- | Executes program given parsed `Program`+select :: Program -> IO ()+select (Program com maybeFile c) = case maybeFile of+ (Just file) -> selectCommand com (not c) file+ _ -> selectCommand com (not c) =<< (++ "/.cred.toml") <$> getHomeDirectory++-- | Executes subcommand given subcommand + filepath to configuration file+selectCommand :: Command -> Bool -> FilePath -> IO ()+selectCommand (Send maybeNum Nothing Nothing input) _ file = fromCLI input (fromMaybe 15 maybeNum) file+selectCommand (Send maybeNum (Just rId) Nothing input) _ file = thread input [] (pure . read $ rId) (fromMaybe 15 maybeNum) file+selectCommand (Send maybeNum Nothing (Just h) input) _ file = thread input h Nothing (fromMaybe 15 maybeNum) file+selectCommand (Send maybeNum (Just rId) (Just h) input) _ file = thread input h (pure . read $ rId) (fromMaybe 15 maybeNum) file+selectCommand (SendInput maybeNum Nothing Nothing) _ file = fromStdIn (fromMaybe 15 maybeNum) file+selectCommand (SendInput maybeNum (Just rId) (Just h)) _ file = threadStdIn h (pure . read $ rId) (fromMaybe 15 maybeNum) file+selectCommand (SendInput maybeNum (Just rId) Nothing) _ file = threadStdIn [] (pure . read $ rId) (fromMaybe 15 maybeNum) file+selectCommand (SendInput maybeNum Nothing (Just h)) _ file = threadStdIn h Nothing (fromMaybe 15 maybeNum) file+selectCommand (Timeline maybeNum) c file = putStrLn =<< showTimeline (fromMaybe 11 maybeNum) c file+selectCommand (Mentions maybeNum) c file = putStrLn =<< showTweets c <$> mentions (fromMaybe 11 maybeNum) file+selectCommand (Profile maybeNum n False False) c file = putStrLn =<< showProfile (fromMaybe mempty n) (fromMaybe 11 maybeNum) c file+selectCommand (Profile maybeNum n True False) c file = putStrLn =<< showFilteredTL [filterReplies] (fromMaybe mempty n) (fromMaybe 11 maybeNum) c file+selectCommand (Profile maybeNum n False True) c file = putStrLn =<< showFilteredTL [filterRTs] (fromMaybe mempty n) (fromMaybe 11 maybeNum) c file+selectCommand (Profile maybeNum n True True) c file = putStrLn =<< showFilteredTL [filterReplies, filterRTs] (fromMaybe mempty n) (fromMaybe 11 maybeNum) c file+selectCommand (Sort n maybeNum False) c file = putStrLn =<< showBest' n (fromMaybe 11 maybeNum) c file+selectCommand (Sort n maybeNum True) c file = putStrLn =<< showBest n (fromMaybe 11 maybeNum) c file+selectCommand (List maybeNum n) c file = putStrLn =<< showFavorites (fromMaybe 11 maybeNum) n c file+selectCommand (Markov n) _ file = do+ raw <- getMarkov n Nothing file+ appendFile (n ++ ".txt") (unlines raw)+ putStrLn $ "Written output to: " ++ n ++ ".txt"+selectCommand (Delete n) c file = do+ putStrLn "Deleted:\n"+ putStrLn =<< showTweets c <$> deleteTweetResponse n file+selectCommand (Fav n) c file = do+ putStrLn "Favorited:\n"+ putStrLn =<< showTweets c <$> favoriteTweetResponse n file+selectCommand (Unfav n) c file = do+ putStrLn "Unfavorited:\n"+ putStrLn =<< showTweets c <$> unfavoriteTweetResponse n file+selectCommand (Retweet n) c file = do+ putStrLn "Retweeted:\n"+ putStrLn =<< showTweets c <$> retweetTweetResponse n file+selectCommand (Unretweet n) c file = do+ putStrLn "Unretweeted:\n"+ putStrLn =<< showTweets c <$> unretweetTweetResponse n file+selectCommand (Follow sn) _ file = do+ follow sn file+ putStrLn ("..." ++ sn ++ " followed successfully!")+selectCommand (Unfollow sn) _ file = do+ unfollow sn file+ putStrLn ("..." ++ sn ++ " unfollowed successfully!")+selectCommand (Block sn) _ file = do+ block sn file+ putStrLn ("..." ++ sn ++ " blocked successfully")+selectCommand (Unblock sn) _ file = do+ unblock sn file+ putStrLn ("..." ++ sn ++ " unblocked successfully")+selectCommand (Mute sn) _ file = do+ mute sn file+ putStrLn ("..." ++ sn ++ " muted successfully")+selectCommand (Unmute sn) _ file = do+ unmute sn file+ putStrLn ("..." ++ sn ++ " unmuted successfully")+selectCommand (Dump sn) _ file = BSL.putStrLn =<< getProfileRaw sn 3200 file Nothing++-- | Parser to return a program datatype+program :: Parser Program+program = Program+ <$> 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"))+ <> command "user" (info profile (progDesc "Get a user's profile"))+ <> command "markov" (info markov (progDesc "Grab tweets en masse."))+ <> command "hits" (info best (progDesc "View a user's top tweets."))+ <> command "del" (info delete (progDesc "Delete a tweet.")) -- TODO delete/favorite in bunches!+ <> command "fav" (info fav (progDesc "Favorite a tweet"))+ <> command "ufav" (info unfav (progDesc "Unfavorite a tweet"))+ <> command "urt" (info unrt (progDesc "Un-retweet a tweet"))+ <> command "rt" (info rt (progDesc "Retweet a tweet"))+ <> command "follow" (info fol (progDesc "Follow a user"))+ <> command "unfollow" (info unfol (progDesc "Unfollow a user"))+ <> command "list" (info list (progDesc "List a user's favorites"))+ <> command "dump" (info dump (progDesc "Dump tweets (for debugging)"))+ <> command "block" (info blockParser (progDesc "Block a user"))+ <> 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+ (long "cred"+ <> short 'c'+ <> metavar "CREDENTIALS"+ <> completer (bashCompleter "file -X '!*.toml' -o plusdirs")+ <> help "path to credentials"))+ <*> switch+ (long "color"+ <> short 'l'+ <> help "Turn off colorized terminal output.")++-- | Parser for the view subcommand+timeline :: Parser Command+timeline = Timeline+ <$> optional (read <$> strOption+ (long "count"+ <> short 'n'+ <> metavar "NUM"+ <> help "number of tweetInputs to fetch, default 5"))++-- | Parser for the markov subcommand+markov :: Parser Command+markov = Markov <$> user++-- | Parser for the follow subcommand+fol :: Parser Command+fol = Follow <$> user++-- | Parser for the block subcommand+blockParser :: Parser Command+blockParser = Block <$> user++-- | Parser for the unblock subcommand+unblockParser :: Parser Command+unblockParser = Unblock <$> user++-- | Parser for the dump subcommand+dump :: Parser Command+dump = Dump <$> user++-- | Parser for the unfollow subcommand+unfol :: Parser Command+unfol = Unfollow <$> user++-- | Parser for the list subcommand+list :: Parser Command+list = List+ <$> optional (read <$> strOption+ (long "count"+ <> short 'n'+ <> metavar "NUM"+ <> help "Number of tweetInputs to fetch, default 12"))+ <*> user++-- | Parser for the unfollow subcommand+muteParser :: Parser Command+muteParser = Mute <$> user++-- | Parser for the unfollow subcommand+unmuteParser :: Parser Command+unmuteParser = Unmute <$> user++-- | Parse a user screen name+user :: Parser String+user = argument str+ (metavar "SCREEN_NAME"+ <> help "Screen name of user.")++-- | Parser for the del subcommand+delete :: Parser Command+delete = Delete <$> getInt++-- | Parser for the fav subcommand+fav :: Parser Command+fav = Fav <$> getInt++-- | Parser for the fav subcommand+unfav :: Parser Command+unfav = Unfav <$> getInt++-- | Parser for the fav subcommand+unrt :: Parser Command+unrt = Unretweet <$> getInt++-- | Parser for the fav subcommand+rt :: Parser Command+rt = Retweet <$> getInt++-- | Parser for the del subcommand+getInt :: Parser Integer+getInt = read <$> argument str+ (metavar "TWEET_ID"+ <> help "ID of tweet")++-- | Parser for the user subcommand+profile :: Parser Command+profile = Profile+ <$> optional (read <$> strOption+ (long "count"+ <> short 'n'+ <> metavar "NUM"+ <> help "Number of tweetInputs to fetch, default 12"))+ <*> optional user+ <*> switch (+ long "no-replies"+ <> short 'r'+ <> help "Don't display replies.")+ <*> switch (+ long "no-retweets"+ <> short 't'+ <> help "Don't display retweets.")++-- | Parser for the mention subcommand+mentionsParser :: Parser Command+mentionsParser = Mentions+ <$> optional (read <$> strOption+ (long "count"+ <> short 'n'+ <> metavar "NUM"+ <> help "Number of tweetInputs to fetch, default 12"))++-- | Parse best tweets+best :: Parser Command+best = Sort+ <$> argument str+ (metavar "SCREEN_NAME"+ <> help "Screen name of user you want to view.")+ <*> optional (read <$> strOption+ (long "count"+ <> short 'n'+ <> metavar "NUM"+ <> help "Number of tweetInputs to fetch, default 12"))+ <*> switch+ (long "replies"+ <> short 'r'+ <> help "Include replies in your all-time hits")++-- | Parser for the send subcommand+tweet :: Parser Command+tweet = Send+ <$> optional (read <$> strOption+ (long "tweets"+ <> short 't'+ <> metavar "NUM"+ <> help "Number of tweetInputs in a row, default 15"))+ <*> 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+ (long "handle"+ <> short 'h'+ <> metavar "HANDLE1"+ <> 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+ (long "tweets"+ <> short 't'+ <> metavar "NUM"+ <> help "Number of tweets in a row, default 15"))+ <*> 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+ (metavar "HANDLE1"+ <> help "h to include in replies"))
cabal.project.local view
@@ -1,5 +1,5 @@-with-compiler: ghc-8.2.2+constraints: tweet-hs +development optimization: 2+tests: True+benchmarks: True documentation: True-haddock-hoogle: True-haddock-internal: True
src/Web/Tweet.hs view
@@ -39,11 +39,11 @@ , bird ) where -import Control.Lens import Control.Monad import Data.Default import Data.List.Split (chunksOf) import Data.Maybe+import Lens.Micro import Web.Tweet.API import Web.Tweet.API.Internal import Web.Tweet.Sign
src/Web/Tweet/API.hs view
@@ -4,11 +4,12 @@ module Web.Tweet.API where import Control.Composition-import Control.Lens import Control.Monad import qualified Data.ByteString.Lazy.Char8 as BSL import Data.Maybe (isJust) import Data.Void+import Lens.Micro+import Lens.Micro.Extras import Text.Megaparsec.Error import Web.Tweet.Types import Web.Tweet.Utils
− src/Web/Tweet/Exec.hs
@@ -1,325 +0,0 @@--- | Provides IO action that parses command line options and tweetInputs from stdin-module Web.Tweet.Exec ( exec- , Program (..)- , Command (..)) where--import qualified Data.ByteString.Lazy.Char8 as BSL-import Data.Maybe-import Data.Monoid-import Data.Version-import Options.Applicative-import Paths_tweet_hs-import System.Directory-import Web.Tweet---- | Data type for our program: one optional path to a credential file, (optionally) the number of tweetInputs to make, the id of the status you're replying to, and a list of users you wish to mention.-data Program = Program { subcommand :: Command , cred :: Maybe FilePath , color :: Bool }---- | Data type for a command--- TODO add boolean option to show ids alongside tweets-data Command = Timeline { count :: Maybe Int }- | SendInput { tweetInputs :: Maybe Int, replyId :: Maybe String, replyh :: Maybe [String] }- | Profile { count :: Maybe Int , screenName'' :: Maybe String, withReplies :: Bool, withRetweets :: Bool }- | Mentions { count :: Maybe Int }- | Markov { screenName' :: String }- | Send { tweets :: Maybe Int , replyId :: Maybe String , replyh :: Maybe [String] , userInput :: String }- | Sort { screenName' :: String , count :: Maybe Int , includeReplies :: Bool }- | Delete { twId :: Integer }- | Fav { twId :: Integer }- | Unfav { twId :: Integer }- | Retweet { twId :: Integer }- | Unretweet { twId :: Integer }- | List { count :: Maybe Int , screenName' :: String }- | Follow { screenName' :: String }- | Unfollow { screenName' :: String }- | Block { screenName' :: String }- | Unblock { screenName' :: String }- | Mute { screenName' :: String }- | Unmute { screenName' :: String }- | Dump { screenName' :: String }---- | query twitter to post stdin with no fancy options-fromStdIn :: Int -> FilePath -> IO ()-fromStdIn = threadStdIn [] Nothing---- | Tweet string given to us, as parsed from the command line-fromCLI :: String -> Int -> FilePath -> IO ()-fromCLI s = thread s [] Nothing---- | Threaded tweetInputs from stdIn-threadStdIn :: [String] -> Maybe Int -> Int -> FilePath -> IO ()-threadStdIn hs idNum num filepath = do- contents <- getContents- thread contents hs idNum num filepath---- | Executes parser-exec :: IO ()-exec = putStrLn bird >> execParser opts >>= select- where- versionInfo = infoOption ("tweet-hs version: " ++ showVersion version) (short 'v' <> long "version" <> help "Show version")- opts = info (helper <*> versionInfo <*> program)- (fullDesc- <> progDesc "Tweet and view tweets"- <> header "clit - a Command Line Interface Tweeter")---- | Executes program given parsed `Program`-select :: Program -> IO ()-select (Program com maybeFile c) = case maybeFile of- (Just file) -> selectCommand com (not c) file- _ -> selectCommand com (not c) =<< (++ "/.cred.toml") <$> getHomeDirectory---- | Executes subcommand given subcommand + filepath to configuration file-selectCommand :: Command -> Bool -> FilePath -> IO ()-selectCommand (Send maybeNum Nothing Nothing input) _ file = fromCLI input (fromMaybe 15 maybeNum) file-selectCommand (Send maybeNum (Just rId) Nothing input) _ file = thread input [] (pure . read $ rId) (fromMaybe 15 maybeNum) file-selectCommand (Send maybeNum Nothing (Just h) input) _ file = thread input h Nothing (fromMaybe 15 maybeNum) file-selectCommand (Send maybeNum (Just rId) (Just h) input) _ file = thread input h (pure . read $ rId) (fromMaybe 15 maybeNum) file-selectCommand (SendInput maybeNum Nothing Nothing) _ file = fromStdIn (fromMaybe 15 maybeNum) file-selectCommand (SendInput maybeNum (Just rId) (Just h)) _ file = threadStdIn h (pure . read $ rId) (fromMaybe 15 maybeNum) file-selectCommand (SendInput maybeNum (Just rId) Nothing) _ file = threadStdIn [] (pure . read $ rId) (fromMaybe 15 maybeNum) file-selectCommand (SendInput maybeNum Nothing (Just h)) _ file = threadStdIn h Nothing (fromMaybe 15 maybeNum) file-selectCommand (Timeline maybeNum) c file = putStrLn =<< showTimeline (fromMaybe 11 maybeNum) c file-selectCommand (Mentions maybeNum) c file = putStrLn =<< showTweets c <$> mentions (fromMaybe 11 maybeNum) file-selectCommand (Profile maybeNum n False False) c file = putStrLn =<< showProfile (fromMaybe mempty n) (fromMaybe 11 maybeNum) c file-selectCommand (Profile maybeNum n True False) c file = putStrLn =<< showFilteredTL [filterReplies] (fromMaybe mempty n) (fromMaybe 11 maybeNum) c file-selectCommand (Profile maybeNum n False True) c file = putStrLn =<< showFilteredTL [filterRTs] (fromMaybe mempty n) (fromMaybe 11 maybeNum) c file-selectCommand (Profile maybeNum n True True) c file = putStrLn =<< showFilteredTL [filterReplies, filterRTs] (fromMaybe mempty n) (fromMaybe 11 maybeNum) c file-selectCommand (Sort n maybeNum False) c file = putStrLn =<< showBest' n (fromMaybe 11 maybeNum) c file-selectCommand (Sort n maybeNum True) c file = putStrLn =<< showBest n (fromMaybe 11 maybeNum) c file-selectCommand (List maybeNum n) c file = putStrLn =<< showFavorites (fromMaybe 11 maybeNum) n c file-selectCommand (Markov n) _ file = do- raw <- getMarkov n Nothing file- appendFile (n ++ ".txt") (unlines raw)- putStrLn $ "Written output to: " ++ n ++ ".txt"-selectCommand (Delete n) c file = do- putStrLn "Deleted:\n"- putStrLn =<< showTweets c <$> deleteTweetResponse n file-selectCommand (Fav n) c file = do- putStrLn "Favorited:\n"- putStrLn =<< showTweets c <$> favoriteTweetResponse n file-selectCommand (Unfav n) c file = do- putStrLn "Unfavorited:\n"- putStrLn =<< showTweets c <$> unfavoriteTweetResponse n file-selectCommand (Retweet n) c file = do- putStrLn "Retweeted:\n"- putStrLn =<< showTweets c <$> retweetTweetResponse n file-selectCommand (Unretweet n) c file = do- putStrLn "Unretweeted:\n"- putStrLn =<< showTweets c <$> unretweetTweetResponse n file-selectCommand (Follow sn) _ file = do- follow sn file- putStrLn ("..." ++ sn ++ " followed successfully!")-selectCommand (Unfollow sn) _ file = do- unfollow sn file- putStrLn ("..." ++ sn ++ " unfollowed successfully!")-selectCommand (Block sn) _ file = do- block sn file- putStrLn ("..." ++ sn ++ " blocked successfully")-selectCommand (Unblock sn) _ file = do- unblock sn file- putStrLn ("..." ++ sn ++ " unblocked successfully")-selectCommand (Mute sn) _ file = do- mute sn file- putStrLn ("..." ++ sn ++ " muted successfully")-selectCommand (Unmute sn) _ file = do- unmute sn file- putStrLn ("..." ++ sn ++ " unmuted successfully")-selectCommand (Dump sn) _ file = BSL.putStrLn =<< getProfileRaw sn 3200 file Nothing---- | Parser to return a program datatype-program :: Parser Program-program = Program- <$> 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"))- <> command "user" (info profile (progDesc "Get a user's profile"))- <> command "markov" (info markov (progDesc "Grab tweets en masse."))- <> command "hits" (info best (progDesc "View a user's top tweets."))- <> command "del" (info delete (progDesc "Delete a tweet.")) -- TODO delete/favorite in bunches!- <> command "fav" (info fav (progDesc "Favorite a tweet"))- <> command "ufav" (info unfav (progDesc "Unfavorite a tweet"))- <> command "urt" (info unrt (progDesc "Un-retweet a tweet"))- <> command "rt" (info rt (progDesc "Retweet a tweet"))- <> command "follow" (info fol (progDesc "Follow a user"))- <> command "unfollow" (info unfol (progDesc "Unfollow a user"))- <> command "list" (info list (progDesc "List a user's favorites"))- <> command "dump" (info dump (progDesc "Dump tweets (for debugging)"))- <> command "block" (info blockParser (progDesc "Block a user"))- <> 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- (long "cred"- <> short 'c'- <> metavar "CREDENTIALS"- <> completer (bashCompleter "file -X '!*.toml' -o plusdirs")- <> help "path to credentials"))- <*> switch- (long "color"- <> short 'l'- <> help "Turn off colorized terminal output.")---- | Parser for the view subcommand-timeline :: Parser Command-timeline = Timeline- <$> optional (read <$> strOption- (long "count"- <> short 'n'- <> metavar "NUM"- <> help "number of tweetInputs to fetch, default 5"))---- | Parser for the markov subcommand-markov :: Parser Command-markov = Markov <$> user---- | Parser for the follow subcommand-fol :: Parser Command-fol = Follow <$> user---- | Parser for the block subcommand-blockParser :: Parser Command-blockParser = Block <$> user---- | Parser for the unblock subcommand-unblockParser :: Parser Command-unblockParser = Unblock <$> user---- | Parser for the dump subcommand-dump :: Parser Command-dump = Dump <$> user---- | Parser for the unfollow subcommand-unfol :: Parser Command-unfol = Unfollow <$> user---- | Parser for the list subcommand-list :: Parser Command-list = List- <$> optional (read <$> strOption- (long "count"- <> short 'n'- <> metavar "NUM"- <> help "Number of tweetInputs to fetch, default 12"))- <*> user---- | Parser for the unfollow subcommand-muteParser :: Parser Command-muteParser = Mute <$> user---- | Parser for the unfollow subcommand-unmuteParser :: Parser Command-unmuteParser = Unmute <$> user---- | Parse a user screen name-user :: Parser String-user = argument str- (metavar "SCREEN_NAME"- <> help "Screen name of user.")---- | Parser for the del subcommand-delete :: Parser Command-delete = Delete <$> getInt---- | Parser for the fav subcommand-fav :: Parser Command-fav = Fav <$> getInt---- | Parser for the fav subcommand-unfav :: Parser Command-unfav = Unfav <$> getInt---- | Parser for the fav subcommand-unrt :: Parser Command-unrt = Unretweet <$> getInt---- | Parser for the fav subcommand-rt :: Parser Command-rt = Retweet <$> getInt---- | Parser for the del subcommand-getInt :: Parser Integer-getInt = read <$> argument str- (metavar "TWEET_ID"- <> help "ID of tweet")---- | Parser for the user subcommand-profile :: Parser Command-profile = Profile- <$> optional (read <$> strOption- (long "count"- <> short 'n'- <> metavar "NUM"- <> help "Number of tweetInputs to fetch, default 12"))- <*> optional user- <*> switch (- long "no-replies"- <> short 'r'- <> help "Don't display replies.")- <*> switch (- long "no-retweets"- <> short 't'- <> help "Don't display retweets.")---- | Parser for the mention subcommand-mentionsParser :: Parser Command-mentionsParser = Mentions- <$> optional (read <$> strOption- (long "count"- <> short 'n'- <> metavar "NUM"- <> help "Number of tweetInputs to fetch, default 12"))---- | Parse best tweets-best :: Parser Command-best = Sort- <$> argument str- (metavar "SCREEN_NAME"- <> help "Screen name of user you want to view.")- <*> optional (read <$> strOption- (long "count"- <> short 'n'- <> metavar "NUM"- <> help "Number of tweetInputs to fetch, default 12"))- <*> switch- (long "replies"- <> short 'r'- <> help "Include replies in your all-time hits")---- | Parser for the send subcommand-tweet :: Parser Command-tweet = Send- <$> optional (read <$> strOption- (long "tweets"- <> short 't'- <> metavar "NUM"- <> help "Number of tweetInputs in a row, default 15"))- <*> 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- (long "handle"- <> short 'h'- <> metavar "HANDLE1"- <> 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- (long "tweets"- <> short 't'- <> metavar "NUM"- <> help "Number of tweets in a row, default 15"))- <*> 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- (metavar "HANDLE1"- <> help "h to include in replies"))
src/Web/Tweet/Parser.hs view
@@ -1,5 +1,6 @@ {-# OPTIONS_GHC -fno-warn-unused-do-bind #-} {-# LANGUAGE OverloadedStrings #-}+ -- | Module containing parsers for tweet and response data. module Web.Tweet.Parser ( parseTweet , getData ) where@@ -10,7 +11,6 @@ import Text.Megaparsec.Byte.Lexer as L import Text.Megaparsec import Web.Tweet.Types-import Data.Monoid import qualified Data.Map as M import qualified Data.Text as T import qualified Data.Text.Encoding as TE@@ -97,8 +97,7 @@ string $ "\"" <> str <> "\":" open <- optional $ char '\"' let forbidden = if isJust open then ("\\\"" :: String) else ("\\\"," :: String)- want <- many $ parseHTMLChar <|> noneOf forbidden <|> specialChar '\"' <|> specialChar '/' <|> newlineChar <|> emojiChar <|> unicodeChar -- TODO modify parsec to make this parallel?- pure want+ many $ parseHTMLChar <|> noneOf forbidden <|> specialChar '\"' <|> specialChar '/' <|> newlineChar <|> emojiChar <|> unicodeChar -- TODO modify parsec to make this parallel? -- | Parse a newline newlineChar :: Parser Char
src/Web/Tweet/Types.hs view
@@ -4,9 +4,9 @@ -- | Exports the `Tweet` type, a datatype for building tweets easily module Web.Tweet.Types where -import Control.Lens import Data.Default import GHC.Generics+import Lens.Micro import Web.Authenticate.OAuth -- | Data type for our request: consists of the status text, whether to trium u information in the response, the handles to mention, and optionally the id of the status to reply to.
src/Web/Tweet/Utils.hs view
@@ -15,12 +15,12 @@ ) where import Control.Composition-import Control.Lens import qualified Data.ByteString as BS2 import qualified Data.ByteString.Char8 as BS import Data.List import Data.List.Extra import Data.Void+import Lens.Micro.Extras import Text.Megaparsec import Web.Tweet.Parser import Web.Tweet.Parser.FastParser hiding (text)
src/Web/Tweet/Utils/API.hs view
@@ -54,14 +54,6 @@ 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`.-{-responseInt :: Request -> Manager -> IO Int-responseInt request manager = do- response <- httpLbs request manager- let code = statusCode $ responseStatus response- putStrLn $ if (code == 200) then "POST succesful!" else "failed :(\n error code: " ++ (show code)- return $ (read . (takeWhile (/=',')) . (drop 52)) (BSL.unpack $ responseBody response)-} -- TODO use the more general parser- -- | Convert a tweet to a percent-encoded url for querying an API urlString :: Tweet -> String urlString tweet = concat [ "?status="@@ -77,7 +69,7 @@ strEncode :: String -> String strEncode = BS.unpack . paramEncode . encodeUtf8 . T.pack --- | Percent-encode the status update so it's fit for a URL and UTF-encode it as well.+-- | Percent-encode the status update so it's fit for a URL. tweetEncode :: Tweet -> BS.ByteString tweetEncode tweet = paramEncode . encodeUtf8 $ handleStr `T.append` content where content = T.pack . _status $ tweet
test/Spec.hs view
@@ -1,7 +1,5 @@ {-# LANGUAGE OverloadedStrings #-} --- import qualified Data.ByteString as BS-import Data.Monoid import System.Environment import Test.Hspec import Web.Tweet.Parser.FastParser
tweet-hs.cabal view
@@ -1,127 +1,148 @@-name: tweet-hs-version: 1.0.1.35-synopsis: Command-line tool for twitter-description: a Command Line Interface Tweeter-homepage: https://github.com/vmchale/command-line-tweeter#readme-license: BSD3-license-file: LICENSE-author: Vanessa McHale-maintainer: vanessa.mchale@reconfigure.io-copyright: 2016, 2017 Vanessa McHale-category: Web-build-type: Simple-stability: stable-extra-source-files: README.md, cabal.project.local, bash/mkCompletions, test/data-cabal-version: >=1.10+cabal-version: >=1.10+name: tweet-hs+version: 1.0.1.36+license: BSD3+license-file: LICENSE+copyright: 2016, 2017 Vanessa McHale+maintainer: vanessa.mchale@reconfigure.io+author: Vanessa McHale+stability: stable+homepage: https://github.com/vmchale/command-line-tweeter#readme+synopsis: Command-line tool for twitter+description:+ a Command Line Interface Tweeter+category: Web+build-type: Simple+extra-source-files:+ README.md+ cabal.project.local+ bash/mkCompletions+ test/data -Flag llvm-fast {- Description: Enable build with llvm backend- Default: False-}+source-repository head+ type: git+ location: https://hub.darcs.net/vmchale/tweet-hs -Flag library {- Description: Don't build an executable- Default: False-}+flag llvm-fast+ description:+ Enable build with llvm backend+ default: False -Flag development {- Description: Enable -Werror- Default: False- Manual: True-}+flag library+ description:+ Don't build an executable+ default: False -Flag parallel-gc {- Description: Use parallel garbage collector- Default: False-}+flag development+ description:+ Enable -Werror+ default: False+ manual: True +flag parallel-gc+ description:+ Use parallel garbage collector+ default: False+ library- hs-source-dirs: src- exposed-modules: Web.Tweet- , Web.Tweet.Exec- , Web.Tweet.Parser.FastParser- , Web.Tweet.Parser- , Web.Tweet.Sign- , Web.Tweet.API- , 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- , Paths_tweet_hs- build-depends: base >= 4.9 && < 5- , http-client-tls- , http-client- , http-types- , authenticate-oauth- , megaparsec >= 6.0- , bytestring- , split- , optparse-applicative - , lens- , unordered-containers- , htoml-megaparsec- , data-default- , text- , containers- , ansi-wl-pprint- , directory- , composition-prelude- , extra- , aeson- default-language: Haskell2010- default-extensions: LambdaCase- if flag(development)- ghc-options: -Werror- ghc-options: -Wall -Wincomplete-uni-patterns -Wincomplete-record-updates+ exposed-modules:+ Web.Tweet+ Web.Tweet.Parser.FastParser+ Web.Tweet.Parser+ Web.Tweet.Sign+ Web.Tweet.API+ Web.Tweet.Utils+ hs-source-dirs: src+ other-modules:+ Web.Tweet.Types+ Web.Tweet.Utils.Colors+ Web.Tweet.API.Internal+ Web.Tweet.Utils.API+ default-language: Haskell2010+ default-extensions: LambdaCase+ ghc-options: -Wall -Wincomplete-uni-patterns+ -Wincomplete-record-updates+ build-depends:+ base >=4.11 && <5,+ http-client-tls -any,+ http-client -any,+ http-types -any,+ authenticate-oauth -any,+ megaparsec >=6.0,+ bytestring -any,+ split -any,+ microlens -any,+ unordered-containers -any,+ htoml-megaparsec -any,+ data-default -any,+ text -any,+ containers -any,+ ansi-wl-pprint -any,+ composition-prelude -any,+ extra -any,+ aeson -any+ + if flag(development)+ ghc-options: -Werror executable tweet- if flag(library)- Buildable: False- else- Buildable: True- hs-source-dirs: app- main-is: Main.hs- if flag(llvm-fast)- ghc-options: -fllvm -optlo-O3 -O3- if flag(parallel-gc)- ghc-options: -rtsopts -with-rtsopts=-N- if flag(development)- ghc-options: -Werror- ghc-options: -Wall -Wincomplete-uni-patterns -Wincomplete-record-updates- build-depends: base- , tweet-hs - default-language: Haskell2010--benchmark tweeths-bench- type: exitcode-stdio-1.0- hs-source-dirs: bench- main-is: Bench.hs- build-depends: base- , criterion- , tweet-hs- , bytestring- , megaparsec- if flag(llvm-fast)- ghc-options: -fllvm -optlo-O3 -O3- if flag(development)- ghc-options: -Werror- ghc-options: -Wall -Wincomplete-uni-patterns -Wincomplete-record-updates- default-language: Haskell2010+ main-is: Main.hs+ hs-source-dirs: app+ other-modules:+ Paths_tweet_hs+ default-language: Haskell2010+ ghc-options: -Wall -Wincomplete-uni-patterns+ -Wincomplete-record-updates+ build-depends:+ base -any,+ tweet-hs -any,+ optparse-applicative -any,+ directory -any,+ bytestring -any+ + if flag(library)+ buildable: False+ + if flag(llvm-fast)+ ghc-options: -fllvm -optlo-O3 -O3+ + if flag(parallel-gc)+ ghc-options: -rtsopts -with-rtsopts=-N+ + if flag(development)+ ghc-options: -Werror test-suite tweeths-test- type: exitcode-stdio-1.0- hs-source-dirs: test- main-is: Spec.hs- build-depends: base- , tweet-hs- , hspec- if flag(development)- ghc-options: -Werror- ghc-options: -threaded -rtsopts -with-rtsopts=-N -Wall -Wincomplete-uni-patterns -Wincomplete-record-updates- default-language: Haskell2010+ type: exitcode-stdio-1.0+ main-is: Spec.hs+ hs-source-dirs: test+ default-language: Haskell2010+ ghc-options: -threaded -rtsopts -with-rtsopts=-N -Wall+ -Wincomplete-uni-patterns -Wincomplete-record-updates+ build-depends:+ base -any,+ tweet-hs -any,+ hspec -any+ + if flag(development)+ ghc-options: -Werror -source-repository head- type: git- location: https://hub.darcs.net/vmchale/tweet-hs+benchmark tweeths-bench+ type: exitcode-stdio-1.0+ main-is: Bench.hs+ hs-source-dirs: bench+ default-language: Haskell2010+ ghc-options: -Wall -Wincomplete-uni-patterns+ -Wincomplete-record-updates+ build-depends:+ base -any,+ criterion -any,+ tweet-hs -any,+ bytestring -any,+ megaparsec -any+ + if flag(llvm-fast)+ ghc-options: -fllvm -optlo-O3 -O3+ + if flag(development)+ ghc-options: -Werror