tweet-hs 0.5.1.0 → 0.5.1.2
raw patch · 7 files changed
+194/−93 lines, 7 filesdep ~tweet-hs
Dependency ranges changed: tweet-hs
Files
- src/Web/Tweet.hs +1/−1
- src/Web/Tweet/API.hs +24/−17
- src/Web/Tweet/Exec.hs +98/−57
- src/Web/Tweet/Parser.hs +14/−8
- src/Web/Tweet/Types.hs +1/−1
- src/Web/Tweet/Utils.hs +54/−7
- tweet-hs.cabal +2/−2
src/Web/Tweet.hs view
@@ -67,7 +67,7 @@ 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) last <- foldr ((>=>) . f) initial (content) $ fromMaybe 0 idNum- deleteTweet last filepath+ deleteTweet (fromIntegral last) filepath -- | Reply with a single tweet. Works the same as `thread` but doesn't take the fourth argument. --
src/Web/Tweet/API.hs view
@@ -63,7 +63,6 @@ -- | Show the most successful tweets by a given user, given their screen name. showBest :: String -> Bool -> FilePath -> IO String showBest screenName color filepath = showTweets color . pure . (take 13 . hits) <$> getAll screenName Nothing filepath --- (fmap (take 13 . hits)) <$> getProfile screenName 3200 filepath -- | Display user timeline showTimeline :: Int -> Bool -> FilePath -> IO String@@ -87,31 +86,39 @@ where requestString = "?count=" ++ (show count) -- | Delete a tweet given its id-deleteTweet :: Int -> FilePath -> IO ()+deleteTweet :: Integer -> FilePath -> IO () deleteTweet = (fmap void) . deleteTweetRaw -- | Favorite a tweet given its id-favoriteTweet :: Int -> FilePath -> IO ()+favoriteTweet :: Integer -> FilePath -> IO () favoriteTweet = (fmap void) . favoriteTweetRaw -- | Unfavorite a tweet given its id-unfavoriteTweet :: Int -> FilePath -> IO ()+unfavoriteTweet :: Integer -> FilePath -> IO () unfavoriteTweet = (fmap void) . unfavoriteTweetRaw -- | Unretweet a tweet given its id-unretweetTweet :: Int -> FilePath -> IO ()+unretweetTweet :: Integer -> FilePath -> IO () unretweetTweet = (fmap void) . unretweetTweetRaw +-- | Unfollow a user given their screen name+unfollow :: String -> FilePath -> IO ()+unfollow = (fmap void) . unfollowUserRaw++-- | Follow a user given their screen name+follow :: String -> FilePath -> IO ()+follow = (fmap void) . followUserRaw+ -- | Retweet a tweet given its id-retweetTweet :: Int -> FilePath -> IO ()+retweetTweet :: Integer -> FilePath -> IO () retweetTweet = (fmap void) . retweetTweetRaw -- | Favorite a tweet given its id; return bytestring response-favoriteTweetRaw :: Int -> FilePath -> IO BSL.ByteString-favoriteTweetRaw id = postRequest ("https://api.twitter.com/1.1/favorites/destroy/" ++ (show id) ++ ".json")+favoriteTweetRaw :: Integer -> FilePath -> IO BSL.ByteString+favoriteTweetRaw id = postRequest ("https://api.twitter.com/1.1/favorites/create.json?id=" ++ (show id)) -- | Retweet a tweet given its id; return bytestring response-retweetTweetRaw :: Int -> FilePath -> IO BSL.ByteString+retweetTweetRaw :: Integer -> FilePath -> IO BSL.ByteString retweetTweetRaw id = postRequest ("https://api.twitter.com/1.1/statuses/retweet/" ++ (show id) ++ ".json") -- | Send a DM given text, screen name of recipient.@@ -119,21 +126,21 @@ where encoded = strEncode $ txt -- | Follow a user given their screen name-followUser :: String -> FilePath -> IO BSL.ByteString-followUser screenName = postRequest("https://api.twitter.com/1.1/friendships/create.json?screen_name=" ++ screenName)+followUserRaw :: String -> FilePath -> IO BSL.ByteString+followUserRaw screenName = postRequest("https://api.twitter.com/1.1/friendships/create.json?screen_name=" ++ screenName) -- | Follow a user given their screen name-unfollowUser :: String -> FilePath -> IO BSL.ByteString-unfollowUser screenName = postRequest("https://api.twitter.com/1.1/friendships/destroy.json?screen_name=" ++ screenName)+unfollowUserRaw :: String -> FilePath -> IO BSL.ByteString+unfollowUserRaw screenName = postRequest("https://api.twitter.com/1.1/friendships/destroy.json?screen_name=" ++ screenName) -- | Unretweet a tweet given its id; return bytestring response-unretweetTweetRaw :: Int -> FilePath -> IO BSL.ByteString+unretweetTweetRaw :: Integer -> FilePath -> IO BSL.ByteString unretweetTweetRaw id = postRequest ("https://api.twitter.com/1.1/statuses/unretweet/" ++ (show id) ++ ".json") -- | Favorite a tweet given its id; return bytestring response-unfavoriteTweetRaw :: Int -> FilePath -> IO BSL.ByteString-unfavoriteTweetRaw id = postRequest ("https://api.twitter.com/1.1/favorites/destroy/" ++ (show id) ++ ".json")+unfavoriteTweetRaw :: Integer -> FilePath -> IO BSL.ByteString+unfavoriteTweetRaw id = postRequest ("https://api.twitter.com/1.1/favorites/destroy.json?id=" ++ (show id)) -- | Delete a tweet given its id; return bytestring response-deleteTweetRaw :: Int -> FilePath -> IO BSL.ByteString+deleteTweetRaw :: Integer -> FilePath -> IO BSL.ByteString deleteTweetRaw id = postRequest ("https://api.twitter.com/1.1/statuses/destroy/" ++ (show id) ++ ".json")
src/Web/Tweet/Exec.hs view
@@ -6,6 +6,7 @@ import Web.Tweet import Options.Applicative import qualified Data.ByteString.Char8 as BS+import qualified Data.ByteString.Lazy.Char8 as BSL import Control.Monad import Data.Foldable (fold) import Data.List hiding (delete)@@ -16,6 +17,7 @@ data Program = Program { subcommand :: Command , cred :: Maybe FilePath } -- | Data type for a command+-- TODO add boolean option to show ids alongside tweets data Command = Timeline { count :: Maybe Int , color :: Bool } | SendInput { tweetInputs :: Maybe Int, replyId :: Maybe String, replyHandles :: Maybe [String] } | Profile { count :: Maybe Int , color :: Bool , screenName :: String }@@ -23,6 +25,13 @@ | Send { tweets :: Maybe Int , replyId :: Maybe String , replyHandles :: Maybe [String] , userInput :: String } | Sort { color :: Bool , screenName :: String } | Delete { twId :: Integer }+ | Fav { twId :: Integer }+ | Unfav { twId :: Integer }+ | Retweet { twId :: Integer }+ | Unretweet { twId :: Integer }+ | Follow { screenName :: String }+ | Unfollow { screenName :: String }+ | Dump { screenName :: String } -- | query twitter to post stdin with no fancy options fromStdIn :: Int -> FilePath -> IO ()@@ -49,58 +58,48 @@ -- | Executes program given parsed `Program` select :: Program -> IO ()-select (Program (Send (Just n) Nothing Nothing input) Nothing) = fromCLI input n =<< (++ "/.cred") <$> getHomeDirectory-select (Program (Send Nothing Nothing Nothing input) Nothing) = fromCLI input 15 =<< (++ "/.cred") <$> getHomeDirectory-select (Program (Send (Just n) Nothing Nothing input) (Just file)) = fromCLI input n file-select (Program (Send Nothing Nothing Nothing input) (Just file)) = fromCLI input 15 file-select (Program (Send (Just n) (Just id) (Just handles) input) Nothing) = thread input handles (read id) n =<< (++ "/.cred") <$> getHomeDirectory-select (Program (Send (Just n) (Just id) (Just handles) input) (Just file)) = thread input handles (pure . read $ id) n file-select (Program (Send Nothing (Just id) (Just handles) input) (Just file)) = thread input handles (pure . read $ id) 15 file-select (Program (Send (Just n) (Just id) Nothing input) Nothing) = (thread input [] (pure . read $ id) n) =<< (++ "/.cred") <$> getHomeDirectory-select (Program (Send Nothing (Just id) Nothing input) Nothing) = thread input [] (pure . read $ id) 15 =<< (++ "/.cred") <$> getHomeDirectory-select (Program (Send Nothing (Just id) (Just handles) input) Nothing) = thread input handles (pure . read $ id) 15 =<< (++ "/.cred") <$> getHomeDirectory-select (Program (Send (Just n) (Just id) Nothing input) (Just file)) = thread input [] (pure . read $ id) n file-select (Program (Send (Just n) Nothing (Just handles) input) (Just file)) = thread input handles Nothing n file-select (Program (SendInput (Just n) Nothing Nothing) Nothing) = fromStdIn n =<< (++ "/.cred") <$> getHomeDirectory-select (Program (SendInput Nothing Nothing Nothing) Nothing) = fromStdIn 15 =<< (++ "/.cred") <$> getHomeDirectory-select (Program (SendInput (Just n) Nothing Nothing) (Just file)) = fromStdIn n file-select (Program (SendInput Nothing Nothing Nothing) (Just file) ) = fromStdIn 15 file-select (Program (SendInput (Just n) (Just id) (Just handles)) Nothing) = threadStdIn handles (read id) n =<< (++ "/.cred") <$> getHomeDirectory-select (Program (SendInput (Just n) (Just id) (Just handles)) (Just file)) = threadStdIn handles (pure . read $ id) n file-select (Program (SendInput Nothing (Just id) (Just handles)) (Just file)) = threadStdIn handles (pure . read $ id) 15 file-select (Program (SendInput (Just n) (Just id) Nothing) Nothing) = threadStdIn [] (pure . read $ id) n =<< (++ "/.cred") <$> getHomeDirectory-select (Program (SendInput Nothing (Just id) Nothing) Nothing) = threadStdIn [] (pure . read $ id) 15 =<< (++ "/.cred") <$> getHomeDirectory-select (Program (SendInput Nothing (Just id) (Just handles)) Nothing) = threadStdIn handles (pure . read $ id) 15 =<< (++ "/.cred") <$> getHomeDirectory-select (Program (SendInput (Just n) (Just id) Nothing) (Just file)) = threadStdIn [] (pure . read $ id) n file-select (Program (SendInput (Just n) Nothing (Just handles)) (Just file)) = threadStdIn handles Nothing n file-select (Program (Timeline Nothing False) Nothing) = putStrLn =<< showTimeline 8 False =<< (++ "/.cred") <$> getHomeDirectory-select (Program (Timeline Nothing False) (Just file)) = putStrLn =<< showTimeline 8 False file-select (Program (Timeline (Just n) False) (Just file)) = putStrLn =<< showTimeline 8 False file-select (Program (Timeline (Just n) False) Nothing) = putStrLn =<< showTimeline 8 False =<< (++ "/.cred") <$> getHomeDirectory-select (Program (Timeline Nothing True) Nothing) = putStrLn =<< showTimeline 8 True =<< (++ "/.cred") <$> getHomeDirectory-select (Program (Timeline Nothing True) (Just file)) = putStrLn =<< showTimeline 8 True file-select (Program (Timeline (Just n) True) (Just file)) = putStrLn =<< showTimeline 8 True file-select (Program (Timeline (Just n) True) Nothing) = putStrLn =<< showTimeline 8 True =<< (++ "/.cred") <$> getHomeDirectory-select (Program (Profile (Just n) True name) (Just file)) = putStrLn =<< showProfile name n True file-select (Program (Profile Nothing True name) (Just file)) = putStrLn =<< showProfile name 12 True file-select (Program (Profile (Just n) True name) Nothing) = putStrLn =<< showProfile name n True =<< (++ "/.cred") <$> getHomeDirectory-select (Program (Profile Nothing True name) Nothing) = putStrLn =<< showProfile name 12 True =<< (++ "/.cred") <$> getHomeDirectory-select (Program (Profile (Just n) False name) (Just file)) = putStrLn =<< showProfile name n False file-select (Program (Profile Nothing False name) (Just file)) = putStrLn =<< showProfile name 12 False file-select (Program (Profile (Just n) False name) Nothing) = putStrLn =<< showProfile name n False =<< (++ "/.cred") <$> getHomeDirectory-select (Program (Profile Nothing False name) Nothing) = putStrLn =<< showProfile name 12 False =<< (++ "/.cred") <$> getHomeDirectory-select (Program (Sort True name) (Just file)) = putStrLn =<< showBest name True file-select (Program (Sort True name) Nothing) = putStrLn =<< showBest name True =<< (++ "/.cred") <$> getHomeDirectory-select (Program (Sort False name) (Just file)) = putStrLn =<< showBest name False file-select (Program (Sort False name) Nothing) = putStrLn =<< showBest name False =<< (++ "/.cred") <$> getHomeDirectory-select (Program (Markov name) Nothing) = do- raw <- getMarkov name Nothing =<< (++ "/.cred") <$> getHomeDirectory- writeFile (name ++ ".txt") (unlines raw)- putStrLn $ "Written output to: " ++ name ++ ".txt"-select (Program (Markov name) (Just file)) = do+select (Program com maybeFile) = case maybeFile of+ (Just file) -> selectCommand com file+ _ -> selectCommand com =<< (++ "/.cred") <$> getHomeDirectory++-- | Executes subcommand given subcommand + filepath to configuration file+selectCommand :: Command -> FilePath -> IO ()+selectCommand (Send maybeNum Nothing Nothing input) file = fromCLI input (maybe 15 id maybeNum) file+selectCommand (Send maybeNum (Just replyId) Nothing input) file = thread input [] (pure . read $ replyId) (maybe 15 id maybeNum) file+selectCommand (Send maybeNum Nothing (Just handles) input) file = thread input handles Nothing (maybe 15 id maybeNum) file+selectCommand (SendInput maybeNum Nothing Nothing) file = fromStdIn (maybe 15 id maybeNum) file+selectCommand (SendInput maybeNum (Just replyId) (Just handles)) file = threadStdIn handles (pure . read $ replyId) (maybe 15 id maybeNum) file+selectCommand (SendInput maybeNum (Just replyId) Nothing) file = threadStdIn [] (pure . read $ replyId) (maybe 15 id maybeNum) file+selectCommand (SendInput maybeNum Nothing (Just handles)) file = threadStdIn handles Nothing (maybe 15 id maybeNum) file+selectCommand (Timeline maybeNum color) file = putStrLn =<< showTimeline (maybe 11 id maybeNum) color file+selectCommand (Profile maybeNum color name) file = putStrLn =<< showProfile name (maybe 11 id maybeNum) color file+selectCommand (Sort color name) file = putStrLn =<< showBest name color file+selectCommand (Markov name) file = do raw <- getMarkov name Nothing file writeFile (name ++ ".txt") (unlines raw) putStrLn $ "Written output to: " ++ name ++ ".txt"+selectCommand (Delete n) file = do+ deleteTweet n file+ putStrLn "...tweet deleted successfully!"+selectCommand (Fav n) file = do+ favoriteTweet n file+ putStrLn "...tweet favorited successfully!"+selectCommand (Unfav n) file = do+ unfavoriteTweet n file+ putStrLn "...tweet unfavorited successfully!"+selectCommand (Retweet n) file = do+ retweetTweet n file+ putStrLn "...tweet retweeted successfully!"+selectCommand (Unretweet n) file = do+ unretweetTweet n file+ putStrLn "...tweet retweeted successfully!"+selectCommand (Follow screenName) file = do+ follow screenName file+ putStrLn ("..." ++ screenName ++ " followed successfully!")+selectCommand (Unfollow screenName) file = do+ unfollow screenName file+ putStrLn ("..." ++ screenName ++ " unfollowed successfully!")+selectCommand (Dump screenName) file = BSL.putStrLn =<< (getProfileRaw screenName 3200 file Nothing) -- | Parser to return a program datatype program :: Parser Program@@ -112,7 +111,14 @@ <> 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 "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 "dump" (info dump (progDesc "Dump tweets (for debugging)")))) <*> (optional $ strOption (long "cred" <> short 'c'@@ -134,17 +140,51 @@ -- | Parser for the raw subcommand markov :: Parser Command-markov = Markov- <$> argument str- (metavar "SCREEN_NAME"- <> help "Screen name of user whose tweets you want in bulk.")+markov = Markov <$> user -- | Parser for the raw subcommand+fol :: Parser Command+fol = Follow <$> user++-- | Parser for the raw subcommand+dump :: Parser Command+dump = Dump <$> user++-- | Parser for the raw subcommand+unfol :: Parser Command+unfol = Unfollow <$> 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- <$> read <$> (argument str+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 to delete"))+ <> help "ID of tweet")) -- | Parser for the user subcommand profile :: Parser Command@@ -162,6 +202,7 @@ (metavar "SCREEN_NAME" <> help "Screen name of user you want to view.") +-- | Parse best tweets best :: Parser Command best = Sort <$> switch
src/Web/Tweet/Parser.hs view
@@ -9,6 +9,8 @@ import Data.Monoid import Data.Maybe import Control.Monad+--+import System.IO.Unsafe -- | Parse some number of tweets parseTweet :: Parser Timeline@@ -29,16 +31,20 @@ faves <- read <$> filterStr "favorite_count" pure (TweetEntity text name screenName id Nothing rts faves) "true" -> do- idQuoted <- read <$> filterStr "id"- textQuoted <- filterStr "text"- skipMentions- nameQuoted <- filterStr "name"- screenNameQuoted <- filterStr "screen_name"- rtsQuoted <- read <$> filterStr "retweet_count"- favesQuoted <- read <$> filterStr "favorite_count"+ quoted <- parseQuoted rts <- read <$> filterStr "retweet_count" faves <- read <$> filterStr "favorite_count"- pure $ TweetEntity text name screenName id (Just (TweetEntity textQuoted nameQuoted screenNameQuoted idQuoted Nothing rtsQuoted favesQuoted)) rts faves+ pure $ TweetEntity text name screenName id quoted rts faves+++parseQuoted :: Parser (Maybe TweetEntity)+parseQuoted = do+ optional (string ",\"quoted_status_id" >> filterStr "quoted_status_id_str") -- FIXME it's skipping too many? No prob is when two in a row twitter just dives in to RTs ALSO something wonky with it flipping rts/faves?+ contents <- optional $ string "\",\"quoted_status"+ case contents of+ (Just contents) -> pure <$> getData+ _ -> pure Nothing+ -- | Skip a set of square brackets [] skipInsideBrackets :: Parser ()
src/Web/Tweet/Types.hs view
@@ -26,7 +26,7 @@ , _quoted :: Maybe TweetEntity , _retweets :: Int , _favorites :: Int- } deriving (Generic, Default)+ } deriving (Generic, Default, Eq) -- | Stores data like (name, text, favoriteCount, retweetCount) type Timeline = [TweetEntity]
src/Web/Tweet/Utils.hs view
@@ -4,7 +4,6 @@ import qualified Data.ByteString.Char8 as BS import Data.Char import Data.List-import Data.Monoid import Web.Tweet.Types import Control.Lens.Tuple import Control.Lens hiding (noneOf)@@ -16,26 +15,74 @@ -- | filter out retweets, and sort by most successful. hits :: Timeline -> Timeline-hits = sortTweets . filterRTs+hits = sortTweets . filterRTs -- | Filter out retweets filterRTs :: Timeline -> Timeline filterRTs = filter ((/="RT @") . take 4 . (view text)) +-- | Filter out quotes+filterQuotes :: Timeline -> Timeline+filterQuotes = filter ((==Nothing) . (view quoted))+ -- | Get a list of tweets from a response, returning author, favorites, retweets, and content. getTweets :: String -> Either (ParseError Char Dec) Timeline getTweets = parse parseTweet "" -- | Display Timeline without color displayTimeline :: Timeline -> String-displayTimeline ((TweetEntity content user _ _ Nothing fave rts):rest) = (user <> ":\n " <> (fixNewline content)) <> "\n " <> "♥ " <> (show fave) <> " ♺ " <> (show rts) <> "\n\n" <> (displayTimeline rest) -displayTimeline ((TweetEntity content user _ _ (Just quoted) fave rts):rest) = (user <> ":\n " <> (fixNewline content)) <> "\n " <> "♥ " <> (show fave) <> " ♺ " <> (show rts) <> "\n " <> (_name quoted) <> ": " <> (_text quoted) <> "\n\n" <> (displayTimeline rest) +displayTimeline ((TweetEntity content user _ _ Nothing rts fave):rest) = concat [user+ ,":\n " + ,fixNewline content + ,"\n " + ,"♥ " + ,show fave + ," ♺ " + ,show rts + ,"\n\n" + ,displayTimeline rest]+displayTimeline ((TweetEntity content user _ _ (Just quoted) rts fave):rest) = concat [user + , ":\n " + , fixNewline content + , "\n " + , "♥ " + , show fave + , " ♺ " + , show rts + , "\n " + , _name quoted + , ": " + , _text quoted + , "\n\n" + , displayTimeline rest] displayTimeline [] = [] -- | Display Timeline in color displayTimelineColor :: Timeline -> String-displayTimelineColor ((TweetEntity content user _ _ Nothing fave rts):rest) = ((toYellow user) <> ":\n " <> (fixNewline content)) <> "\n " <> (toRed "♥ ") <> (show fave) <> (toGreen " ♺ ") <> (show rts) <> "\n\n" <> (displayTimelineColor rest) -displayTimelineColor ((TweetEntity content user _ _ (Just quoted) fave rts):rest) = ((toYellow user) <> ":\n " <> (fixNewline content)) <> "\n " <> (toRed "♥ ") <> (show fave) <> (toGreen " ♺ ") <> (show rts) <> "\n " <> (toYellow $ _name quoted) <> ": " <> (_text quoted) <> "\n\n" <> (displayTimelineColor rest) +displayTimelineColor ((TweetEntity content user _ _ Nothing rts fave):rest) = concat [toYellow user + , ":\n " + , fixNewline content+ , "\n " + , toRed "♥ " + , show fave + , toGreen " ♺ " + , show rts + , "\n\n" + , displayTimelineColor rest]+displayTimelineColor ((TweetEntity content user _ _ (Just quoted) rts fave):rest) = concat [toYellow user + , ":\n " + , fixNewline content + , "\n " + , toRed "♥ " + , show fave + , toGreen " ♺ " + , show rts + , "\n " + , toYellow $ _name quoted + , ": " + , _text quoted + , "\n\n" + , displayTimelineColor rest] displayTimelineColor [] = [] -- | When displaying, newlines should include indentation.@@ -45,7 +92,7 @@ -- | sort tweets by most successful sortTweets :: Timeline -> Timeline sortTweets = sortBy compareTweet- where compareTweet (TweetEntity _ _ _ _ _ f1 r1) (TweetEntity _ _ _ _ _ f2 r2) = compare (2*r2 + f2) (2*r1 + f1)+ where compareTweet (TweetEntity _ _ _ _ _ r1 f1) (TweetEntity _ _ _ _ _ r2 f2) = compare (2*r2 + f2) (2*r1 + f1) -- | helper function to get the key as read from a file keyLinePie :: String -> String
tweet-hs.cabal view
@@ -1,5 +1,5 @@ name: tweet-hs-version: 0.5.1.0+version: 0.5.1.2 cabal-version: >=1.10 build-type: Simple license: BSD3@@ -69,7 +69,7 @@ main-is: Main.hs build-depends: base >=4.9.1.0 && <4.10,- tweet-hs >=0.5.1.0 && <0.6+ tweet-hs >=0.5.1.2 && <0.6 default-language: Haskell2010 hs-source-dirs: app