packages feed

imm-0.5.0.0: Imm/Boot.hs

{-# LANGUAGE TupleSections #-}
module Imm.Boot (imm, ConfigFeed) where

-- {{{ Imports
import qualified Imm.Core as Core
import Imm.Config
import Imm.Dyre as Dyre
import Imm.Options (CliOptions)
import qualified Imm.Options as Options
import Imm.Util

import Control.Conditional
import Control.Lens hiding ((??))

import Data.Default
import Data.Either
import Data.Maybe

import Network.URI as N

import System.Directory
import System.Exit
-- }}}

type ConfigFeed = (Config -> Config, String)

-- | Main function to call in the configuration file.
imm :: [ConfigFeed] -> IO ()
imm feedsFromConfig = do
    options <- Options.get

    when (view Options.help options) $ putStrLn Options.usage >> exitSuccess

    Dyre.wrap realMain options (options, feedsFromConfig)


validateFeeds :: [ConfigFeed] -> [URI] -> ([String], Core.FeedList)
validateFeeds feedsFromConfig feedsFromOptions = (errors ++ errors', null feedsFromOptions ? feedsOK ?? feedsOK')
  where
    validateFromConfig (x, u) = maybe (Left ("Invalid feed URI: " ++ u)) (Right . (x,)) $ N.parseURI u
    validateFromOptions uri   = maybe (Left ("URI from commandline option has no configuration entry: " ++ show uri)) Right . listToMaybe . (filter ((== uri) . snd)) $ feedsOK
    (errors,  feedsOK)        = partitionEithers $ map validateFromConfig  feedsFromConfig
    (errors', feedsOK')       = partitionEithers $ map validateFromOptions feedsFromOptions


realMain :: (CliOptions, [ConfigFeed]) -> IO ()
realMain (options, feedsFromConfig) = do
    let (errors, feedsOK) = validateFeeds feedsFromConfig (view Options.feedList options)
    when (not $ null errors) . putStrLn $ unlines errors

    when (null feedsOK) $ putStrLn "Nothing to process. Exiting..." >> exitFailure
    -- when (view Options.verbose options) . putStrLn . unlines $ map (show . snd) feedsOK

    home <- getHomeDirectory >/> "feeds"
    let config = set maildir home def
    dispatch feedsOK config options


dispatch :: Core.FeedList -> Config -> CliOptions -> IO ()
dispatch feeds config options
    | options^.Options.check               = Core.check options feeds
    | options^.Options.list                = Core.list options feeds
    | options^.Options.markAsRead          = Core.markAsRead options feeds
    | options^.Options.markAsUnread        = Core.markAsUnread options feeds
    | options^.Options.update              = Core.update options feeds
    | isJust (options^.Options.importOPML) = Core.importOPML
    | otherwise                            = putStrLn Options.usage