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) | ||
