diff options
author | Gregor Kleen <aethoago@141.li> | 2017-02-15 15:10:51 +0100 |
---|---|---|
committer | Gregor Kleen <aethoago@141.li> | 2017-02-15 15:10:51 +0100 |
commit | ee09f262f9b8c7c6a4042071cdfff3e22adbef86 (patch) | |
tree | baeb1d9ee726881d25e0762c21f750850efb37f2 /lib/Postdelay/Scan.hs | |
parent | 8a24b41b333bce25e698d2e4b87f4b4f6548772c (diff) | |
download | postdelay-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.hs | 39 |
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 | ||
3 | module Postdelay.Scan | 3 | module Postdelay.Scan |
4 | ( scan | 4 | ( scan |
@@ -7,20 +7,18 @@ module Postdelay.Scan | |||
7 | ) where | 7 | ) where |
8 | 8 | ||
9 | import Postdelay.Types | 9 | import Postdelay.Types |
10 | import Postdelay.Utils | ||
11 | import Postdelay.TimeSpec | 10 | import Postdelay.TimeSpec |
12 | 11 | ||
13 | import Control.Monad | 12 | import Control.Monad |
14 | import Control.Monad.IO.Class | 13 | import Control.Monad.IO.Class |
15 | import Control.Monad.Except | 14 | import Control.Monad.Catch |
16 | import Control.Monad.Reader | 15 | import Control.Monad.Reader |
17 | import Control.Monad.List | 16 | import Control.Monad.List |
18 | import Control.Exception.Base | 17 | import Control.Exception.Base |
18 | import Control.Lens | ||
19 | 19 | ||
20 | import Text.Parsec.Char | 20 | import qualified Text.Parsec as P |
21 | import Text.Parsec.Prim | 21 | import Text.Megaparsec |
22 | import Text.Parsec.Combinator | ||
23 | import Text.Parsec.Error (ParseError(..)) | ||
24 | import Text.ParserCombinators.Parsec.Rfc2822 | 22 | import Text.ParserCombinators.Parsec.Rfc2822 |
25 | import Codec.MIME.Decode (decodeWords) | 23 | import Codec.MIME.Decode (decodeWords) |
26 | 24 | ||
@@ -40,17 +38,20 @@ import System.Time (CalendarTime(..)) | |||
40 | 38 | ||
41 | import Debug.Trace | 39 | import Debug.Trace |
42 | 40 | ||
41 | instance Exception P.ParseError | ||
43 | 42 | ||
44 | scan :: (MonadIO m, MonadError ParseError m) => String -> m (Maybe Delay) | ||
45 | scan = fmap getOption . extractDelay <=< either throwError return . parse message "" | ||
46 | 43 | ||
47 | extractDelay :: forall m. (MonadIO m, MonadError ParseError m) => Message -> m (Option Delay) | 44 | scan :: (MonadIO m, MonadThrow m) => String -> m (Maybe Delay) |
45 | scan = fmap getOption . extractDelay <=< either throwM return . P.parse message "" | ||
46 | |||
47 | extractDelay :: forall m. (MonadIO m, MonadThrow m) => Message -> m (Option Delay) | ||
48 | extractDelay (Message headers _) = do | 48 | extractDelay (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 | |||
76 | localT :: Either TimeZone TZ -> Iso' UTCTime LocalTime | ||
77 | localT (Left tz) = iso (utcToLocalTime tz) (localTimeToUTC tz) | ||
78 | localT (Right tz) = iso (utcToLocalTimeTZ tz) (localTimeToUTCTZ tz) | ||