packages feed

hlongurl-0.9.1: Hlongurl.hs

import Data.List.Replace (replace, substAllM)
import Network.Curl.Easy (curl_global_init, initialize)
import Network.LongURL (CurlInstance(..), domains, longURL, supportedSites)

import Control.Applicative ((<$>), (<*>))
import Data.ByteString.Lazy.Char8 (ByteString, pack, splitWith, unpack)
import qualified Data.ByteString.Lazy.Char8 as B
import Data.List (intercalate)
import Text.Regex.Base.Context ()
import Text.Regex.Base.RegexLike (getAllMatches, makeRegexM, match)
import Text.Regex.Posix.ByteString.Lazy (Regex)
import Text.Regex.Posix.String ()

-- FIXME: Make this lazy again
bsLines :: ByteString -> [ByteString]
bsLines = postProcess . splitWith (== '\n')
    where
      postProcess []           = []
      postProcess result
        | B.null (last result) = init result
        | otherwise            = result

-- | Split input into lines, in order to do incremental processing, and to try to limit memory usage
mapMLines_ :: Monad m => (ByteString -> m ()) -> ByteString -> m ()
mapMLines_ f = mapM_ f . bsLines

main :: IO ()
main = do
  curl_global_init 2  -- Initialise just win32sock (if applicable)
  curl' <- initialize
  let ci = CurlInstance { curl = curl', userAgent = "hlongurl 0.9.1; Haskell" }
  supportedDomains <- (domains =<<) <$> supportedSites ci
  urlRegex <- (makeRegexM
               $ "http://(" ++ intercalate "|" (replace "." "\\." <$> supportedDomains)
                    ++ ")/([-a-zA-Z0-9_\\'/\\\\\\+&%\\$#\\=~])*") :: IO Regex
  let substURLs :: ByteString -> IO ()
      substURLs =
         (B.putStrLn =<<)
         . (substAllM (((pack . show) <$>) . longURL ci . unpack)
                          <*> getAllMatches . match urlRegex)
  mapMLines_ substURLs =<< B.getContents