import Control.Monad (forever, when)
import Data.Aeson (decode)
import Data.List ((\\))
import Control.Monad (forever, when)
import Data.Aeson (decode)
import Data.List ((\\))
import Data.Time.LocalTime (TimeZone, getCurrentTimeZone)
import System.Exit (ExitCode(..), exitWith)
import System.IO (hPutStrLn, stderr)
import CommandLine
import Data.Time.LocalTime (TimeZone, getCurrentTimeZone)
import System.Exit (ExitCode(..), exitWith)
import System.IO (hPutStrLn, stderr)
import CommandLine
-import Configuration (Cfg(..))
-import ExitCodes
-import Mail
+import Configuration (Cfg(..), default_config, merge_optional)
+import ExitCodes (exit_no_usernames)
+import qualified OptionalConfiguration as OC
+import Mail (
+ Message(..),
+ default_headers,
+ print_sendmail_result,
+ rfc822_now,
+ sendmail
+ )
- good_statuses = case (ignore_retweets cfg) of
- True -> good_statuses' \\ retweets
- False -> good_statuses'
+ good_statuses = if (ignore_retweets cfg)
+ then good_statuses' \\ retweets
+ else good_statuses'
recurse :: Cfg -> String -> Integer -> (Maybe Message) -> IO ()
recurse cfg username latest_status_id maybe_message = do
thread_sleep (heartbeat cfg)
recurse :: Cfg -> String -> Integer -> (Maybe Message) -> IO ()
recurse cfg username latest_status_id maybe_message = do
thread_sleep (heartbeat cfg)
-- | Try continually to download username's timeline, and determine the
-- latest status id to be posted once we have done so.
-- | Try continually to download username's timeline, and determine the
-- latest status id to be posted once we have done so.
-get_latest_status_id :: Int -> String -> IO Integer
-get_latest_status_id delay username = do
- timeline <- get_user_timeline username
+get_latest_status_id :: Cfg -> String -> IO Integer
+get_latest_status_id cfg username = do
+ let delay = heartbeat cfg
+ timeline <- get_user_timeline cfg username
-- If the HTTP part barfs, try again after a while.
putStrLn ("Couldn't retrieve " ++ username ++ "'s timeline. Retrying...")
thread_sleep delay
-- If the HTTP part barfs, try again after a while.
putStrLn ("Couldn't retrieve " ++ username ++ "'s timeline. Retrying...")
thread_sleep delay
- -- If there were errors parsing the command-line options,
- -- print them and exit.
- when (not (null errors)) $ do
- hPutStrLn stderr (concat errors)
- putStrLn help_text
- exitWith (ExitFailure exit_args_parse_failed)
+ -- Merge the config file options with the command-line ones,
+ -- prefering the command-line ones.
+ let opt_config = rc_cfg <> cmd_cfg
- -- Next, check to see if the 'help' option was passed to the
- -- program. If it was, display the help, and exit successfully.
- help <- help_set
- when (help) $ do
- putStrLn help_text
- exitWith ExitSuccess
+ -- Finally, update a default config with any options that have been
+ -- set in either the config file or on the command-line.
+ let cfg = merge_optional default_config opt_config
- -- Get the list of usernames.
- usernames <- parse_usernames
+ when (null $ usernames cfg) $ do
+ hPutStrLn stderr "ERROR: no usernames supplied."
+ _ <- show_help
+ exitWith (ExitFailure exit_no_usernames)
-- If we have both a "To" and "From" address, we'll create a
-- message object to be passed to all of our threads.
let message = construct_message cfg
-- Execute run_twat on each username in a new thread.
let run_twat_curried = run_twat cfg message
-- If we have both a "To" and "From" address, we'll create a
-- message object to be passed to all of our threads.
let message = construct_message cfg
-- Execute run_twat on each username in a new thread.
let run_twat_curried = run_twat cfg message
-- This thread (the one executing main) doesn't do anything,
-- but when it terminates, so do all the threads we forked.
-- As a result, we need to keep this thread on life support.
-- This thread (the one executing main) doesn't do anything,
-- but when it terminates, so do all the threads we forked.
-- As a result, we need to keep this thread on life support.