packages feed

adblock2privoxy-1.2.4: src/Main.hs

module Main where
import InputParser
import ElementBlocker
import UrlBlocker
import Text.ParserCombinators.Parsec hiding (Line, many, optional)
import Task
import Control.Applicative hiding (many)
import SourceInfo
import System.Console.GetOpt
import System.Environment
import Templates
import Data.Time.Clock 
import Network.HTTP.Conduit
import Network.URI
import Data.Text.Lazy.Encoding
import Data.Text.Lazy (unpack)
import Network.Socket
import System.FilePath
import Paths_adblock2privoxy (version)
import Data.Version (showVersion)

data Options = Options
     { _showVersion :: Bool
     , _privoxyDir  :: FilePath
     , _webDir      :: FilePath
     , _taskFile    :: FilePath
     , _forced    :: Bool
     } deriving Show

options :: [OptDescr (Options -> Options)]
options =
     [ Option "v" ["version"]
         (NoArg (\ opts -> opts { _showVersion = True }))
         "show version number"
     , Option "p"   ["privoxyDir"]
         (ReqArg (\ f opts -> opts { _privoxyDir = f })
                 "PATH")
         "privoxy config output path (required)"
     , Option "w"   ["webDir"]
         (ReqArg (\ f opts -> opts { _webDir = f })
                 "PATH")
         "css files output path (optional, privoxyDir is used by default)"
     , Option "t"   ["taskFile"]
         (ReqArg (\ f opts -> opts { _taskFile = f })
                 "PATH")
         "path to task file containing urls to process"
     , Option "f" ["forced"]
         (NoArg (\ opts -> opts { _forced = True }))
         "run even if no sources are expired"
     ]

parseOptions :: [String] -> IO (Options, [String])
parseOptions argv =
   case getOpt Permute options argv of
      (opts,nonOpts,[]  ) -> 
                case foldl (flip id) (Options False "" "" "" False) opts of
                        Options False "" _ _ _ -> writeError "Privoxy dir is not specified.\n"
                        opts'@Options{_showVersion = True} -> return (opts', nonOpts)
                        opts' -> return (setDefaults opts', nonOpts)
      (_,_,errs) -> writeError $ concat errs
   where
        setDefaults opts@(Options _ privoxyDir "" _ _) = setDefaults opts{ _webDir = privoxyDir }
        setDefaults opts@(Options _ privoxyDir _ "" _) = setDefaults opts{ _taskFile = privoxyDir </> "ab2p.task" }
        setDefaults opts = opts  
  
writeError :: String -> IO a
writeError msg = ioError $ userError $ msg ++ usageInfo header options
        where         
        header = "Usage: adblock2privoxy [OPTION...] [URL...]"

getResponse :: String -> IO String
getResponse url = withSocketsDo $ unpack . decodeUtf8 <$> simpleHttp url

processSources :: String -> String -> String -> [SourceInfo]-> IO ()
processSources privoxyDir webDir taskFile sources = do 
        (parsed, sourceInfo) <- unzip <$> mapM parseSource sources   
        let parsed' = concat parsed 
            infoText = showInfos  sourceInfo               
        writeTask taskFile infoText parsed'
        elemBlock webDir infoText parsed'
        urlBlock privoxyDir infoText parsed'
        writeTemplateFiles privoxyDir
        where 
        parseSource sourceInfo = do
            let 
                url = _url sourceInfo
                loader = if isURI url then getResponse else readFile
            putStrLn $ "parse " ++ url
            text <- loader url
            now <- getCurrentTime
            case parse adblockFile url text of
                Right parsed -> 
                        let sourceInfo' = updateInfo now parsed sourceInfo 
                            url' = _url sourceInfo'
                        in if url == url'     
                           then return (parsed, sourceInfo')
                           else parseSource sourceInfo'
                Left msg -> return ([], sourceInfo) <$ putStrLn $ show msg
        
main::IO()
main =  do 
        now <- getCurrentTime
        args <- getArgs
        (Options printVersion privoxyDir webDir taskFile forced, urls) <- parseOptions args
        let acton
                | printVersion = putStrLn $ "adblock2privoxy version " ++ (showVersion version)
                | not . null $ urls 
                   =    processSources privoxyDir webDir taskFile (makeInfo <$> urls)
                | not . null $ taskFile 
                   = do task <- readTask taskFile
                        let sources = logInfo task                        
                        if forced || or (infoExpired now <$> sources)                                
                                then processSources privoxyDir webDir taskFile sources
                                else putStrLn "all sources are up to date"
                | otherwise = writeError "no input specified"
        acton
        now' <- getCurrentTime
        putStrLn $ concat ["done in ", show $ diffUTCTime now' now, " seconds"]