{-# LANGUAGE GeneralizedNewtypeDeriving #-} {-# LANGUAGE MultiParamTypeClasses #-} {-# LANGUAGE OverloadedStrings #-} {-# LANGUAGE TemplateHaskell #-} {-# LANGUAGE TypeFamilies #-} module Main where import Control.Lens import Control.Monad.Except import Control.Monad.Reader import Data.Machine import Data.Maybe import qualified Data.Text.Lazy.Encoding as TLE import qualified Data.Text.Lazy.IO as TLIO import Network.Mail.Newsletter.Class import Network.Mail.Newsletter.Web import Network.Mail.Mime import Network.URI import qualified Network.Wai.Handler.Warp as Warp import Servant import Text.Printf import qualified Web.ClientSession as CS newtype NewsM a = NewsM { runNewsT :: ReaderT NewsData Handler a } deriving (Functor, Applicative, Monad, MonadReader NewsData, MonadIO, MonadError ServantErr) data NewsData = NewsData { _ndTemplates :: NlTemplates NewsM , _ndClientSessKey :: CS.Key , _ndPort :: Int , _ndInMemDedup :: InMemoryDedup , _ndTimeouts :: NewsletterTimeouts , _ndAllowedOrigins :: [URIAuth] } makeLenses ''NewsData instance HasAllowedOrigins NewsData where allowedOrigins = ndAllowedOrigins instance HasNewsletterTimeouts NewsData where newsletterTimeouts = ndTimeouts instance HasNlTemplates NewsData NewsM where nlTemplates = ndTemplates instance HasClientSessionKey NewsData where clientSessionKey = ndClientSessKey instance DedupSubscriptions NewsM where recentlySubscribed = genericInMemRecentlySubscribed instance HasApiRoot NewsM where type ApiRoot NewsM = NewsletterAPI apiRoot = pure newsletterApi apiBase = (fromJust . parseAbsoluteURI . ((<>) "http://127.0.0.1:8080/") . show) <$> view ndPort instance HasInMemoryDedup NewsData where inMemoryDedup = ndInMemDedup instance Newsletter NewsM where subscribe = autoM $ \sub -> liftIO $ printf "Subscribing %s\n" (show sub) unsubscribe = autoM $ \unsub -> liftIO $ printf "Unsubscribing %s\n" (show unsub) subscribers = source [] sendEmail mkEmail = liftIO $ renderMail' (mkEmail "newsletter@example.org") >>= TLIO.putStrLn . TLE.decodeUtf8 sendSubscribe _ mkEmail = liftIO $ renderMail' (mkEmail "newsletter@example.org") >>= TLIO.putStrLn . TLE.decodeUtf8 nt :: NewsData -> NewsM a -> Handler a nt s x = runReaderT (runNewsT x) s app :: NewsData -> Application app s = serve newsletterApi $ hoistServer newsletterApi (nt s) serveNewsletter main :: IO () main = do (_, k) <- CS.randomKey let port = 8080 p <- newInMemDedup (fromInteger $ 24*60*60) let s = NewsData defTemplates k port p (NewsletterTimeouts 5 1) [URIAuth "" "127.0.0.1" (show port)] Warp.run port $ app $ s