addressbook/src/Control/Addressbook/Streaming.hs

53 lines
1.3 KiB
Haskell
Raw Normal View History

2020-12-10 23:08:03 +02:00
module Control.Addressbook.Streaming where
import qualified Data.Text as T
import Conduit
import qualified Data.Conduit.Binary as CB
import qualified Data.Conduit.Combinators as C
2020-12-11 17:55:35 +02:00
import qualified Data.Conduit.List as CL
2020-12-10 23:08:03 +02:00
import qualified Data.Conduit.Text as CT
import Data.Email
import Data.Email.Header
2020-12-10 23:20:38 +02:00
(Header(..))
2020-12-10 23:08:03 +02:00
import System.IO
(stdin)
2020-12-10 23:20:38 +02:00
import qualified Data.Foldable as F
2020-12-11 17:55:35 +02:00
import qualified Data.Trie as Trie
import Data.Maybe
(fromMaybe)
import System.Environment
(lookupEnv)
import System.FilePath
((</>))
2020-12-10 23:20:38 +02:00
2020-12-10 23:13:23 +02:00
combine :: (MonadUnliftIO m, MonadResource m, MonadThrow m, MonadIO m) => ConduitM FilePath Header m ()
2020-12-10 23:08:03 +02:00
combine = await >>= \case
Nothing -> pure ()
Just path -> (CB.sourceFile path .| parseEmail) >> combine
run :: IO ()
run = do
2020-12-11 17:55:35 +02:00
datDir <- fromMaybe "./" <$> lookupEnv "HOME"
runResourceT $ do
x <- runConduit stream
runConduit (CL.sourceList (Trie.keys x) .| C.map (<> "\n") .| CB.sinkFileCautious (datDir </> ".addressbook.dat"))
2020-12-10 23:20:38 +02:00
where
separate = \case
From x -> [x]
To xs -> F.toList xs
stream =
CB.sourceHandle stdin
.| CT.decode CT.utf8
.| CT.lines
.| C.map T.unpack
.| combine
.| C.concatMap separate
2020-12-11 17:55:35 +02:00
.| CT.encode CT.utf8
.| C.foldMap (`Trie.singleton` ())