summaryrefslogtreecommitdiff
path: root/lib/Postdelay/Scan.hs
diff options
context:
space:
mode:
authorGregor Kleen <aethoago@141.li>2017-02-15 15:10:51 +0100
committerGregor Kleen <aethoago@141.li>2017-02-15 15:10:51 +0100
commitee09f262f9b8c7c6a4042071cdfff3e22adbef86 (patch)
treebaeb1d9ee726881d25e0762c21f750850efb37f2 /lib/Postdelay/Scan.hs
parent8a24b41b333bce25e698d2e4b87f4b4f6548772c (diff)
downloadpostdelay-ee09f262f9b8c7c6a4042071cdfff3e22adbef86.tar
postdelay-ee09f262f9b8c7c6a4042071cdfff3e22adbef86.tar.gz
postdelay-ee09f262f9b8c7c6a4042071cdfff3e22adbef86.tar.bz2
postdelay-ee09f262f9b8c7c6a4042071cdfff3e22adbef86.tar.xz
postdelay-ee09f262f9b8c7c6a4042071cdfff3e22adbef86.zip
Establish framework
Diffstat (limited to 'lib/Postdelay/Scan.hs')
-rw-r--r--lib/Postdelay/Scan.hs39
1 files changed, 22 insertions, 17 deletions
diff --git a/lib/Postdelay/Scan.hs b/lib/Postdelay/Scan.hs
index 2f0a78a..888a237 100644
--- a/lib/Postdelay/Scan.hs
+++ b/lib/Postdelay/Scan.hs
@@ -1,4 +1,4 @@
1{-# LANGUAGE OverloadedStrings, ScopedTypeVariables, FlexibleContexts, RecordWildCards, ViewPatterns, TupleSections #-} 1{-# LANGUAGE OverloadedStrings, ScopedTypeVariables, FlexibleContexts, RecordWildCards, ViewPatterns, TupleSections, RankNTypes #-}
2 2
3module Postdelay.Scan 3module Postdelay.Scan
4 ( scan 4 ( scan
@@ -7,20 +7,18 @@ module Postdelay.Scan
7 ) where 7 ) where
8 8
9import Postdelay.Types 9import Postdelay.Types
10import Postdelay.Utils
11import Postdelay.TimeSpec 10import Postdelay.TimeSpec
12 11
13import Control.Monad 12import Control.Monad
14import Control.Monad.IO.Class 13import Control.Monad.IO.Class
15import Control.Monad.Except 14import Control.Monad.Catch
16import Control.Monad.Reader 15import Control.Monad.Reader
17import Control.Monad.List 16import Control.Monad.List
18import Control.Exception.Base 17import Control.Exception.Base
18import Control.Lens
19 19
20import Text.Parsec.Char 20import qualified Text.Parsec as P
21import Text.Parsec.Prim 21import Text.Megaparsec
22import Text.Parsec.Combinator
23import Text.Parsec.Error (ParseError(..))
24import Text.ParserCombinators.Parsec.Rfc2822 22import Text.ParserCombinators.Parsec.Rfc2822
25import Codec.MIME.Decode (decodeWords) 23import Codec.MIME.Decode (decodeWords)
26 24
@@ -40,17 +38,20 @@ import System.Time (CalendarTime(..))
40 38
41import Debug.Trace 39import Debug.Trace
42 40
41instance Exception P.ParseError
43 42
44scan :: (MonadIO m, MonadError ParseError m) => String -> m (Maybe Delay)
45scan = fmap getOption . extractDelay <=< either throwError return . parse message ""
46 43
47extractDelay :: forall m. (MonadIO m, MonadError ParseError m) => Message -> m (Option Delay) 44scan :: (MonadIO m, MonadThrow m) => String -> m (Maybe Delay)
45scan = fmap getOption . extractDelay <=< either throwM return . P.parse message ""
46
47extractDelay :: forall m. (MonadIO m, MonadThrow m) => Message -> m (Option Delay)
48extractDelay (Message headers _) = do 48extractDelay (Message headers _) = do
49 zones <- zoneHeaders 49 tz <- foldr' (flip (<>)) (Left dateTz) <$> zoneHeaders
50 let (baseTime, dateTz) = maximumBy (comparing fst) dateHeaders 50 let apply f = Until (baseTime & localT tz %~ appEndo f)
51 tz = foldr' (flip (<>)) (Left dateTz) zones 51 fmap apply . foldMap pure <$> mapM parseDelay delayHeaders
52 foldMap pure <$> mapM (flip runReaderT TimeCtx{..} . parseDelay) delayHeaders
53 where 52 where
53 (baseTime, dateTz) = maximumBy (comparing fst) dateHeaders
54
54 delayHeaders :: [Field] 55 delayHeaders :: [Field]
55 delayHeaders = do 56 delayHeaders = do
56 (OptionalField field content) <- headers 57 (OptionalField field content) <- headers
@@ -67,7 +68,11 @@ extractDelay (Message headers _) = do
67 zoneHeaders = runListT $ do 68 zoneHeaders = runListT $ do
68 (OptionalField field content) <- ListT $ return headers 69 (OptionalField field content) <- ListT $ return headers
69 guard $ CI.mk field == "X-Timezone" 70 guard $ CI.mk field == "X-Timezone"
70 Right r <- runParserT (spaces *> pTimeZone <* spaces <* eof) () field content 71 Right r <- runParserT (spaceConsumer *> lexeme pTimeZone <* eof) field content
71 return r 72 return r
72 parseDelay :: Field -> ReaderT TimeCtx m Delay 73 parseDelay :: Field -> m (Endo LocalTime)
73 parseDelay (OptionalField field content) = either throwError return =<< runParserT (Until <$> pTimeSpec) () field content 74 parseDelay (OptionalField field content) = either throwM return =<< runParserT (spaceConsumer *> lexeme pTimeSpec <* eof) field content
75
76localT :: Either TimeZone TZ -> Iso' UTCTime LocalTime
77localT (Left tz) = iso (utcToLocalTime tz) (localTimeToUTC tz)
78localT (Right tz) = iso (utcToLocalTimeTZ tz) (localTimeToUTCTZ tz)