module Blaaargh.Internal.Types
( module Blaaargh.Internal.Exception
, Post(..)
, getPostTime
, ContentMap
, ContentItem(..)
, BlaaarghState(..)
, BlaaarghMonad(..)
, BlaaarghHandler
, liftB
, runBlaaarghHandler
, addExtraTemplateArguments
)
where
import Control.Monad.State
import qualified Data.ByteString.Char8 as B
import qualified Data.ByteString.Lazy.Char8 as L
import Data.ByteString.Char8 (ByteString)
import qualified Data.Map as Map
import Data.Map (Map)
import Data.Maybe
import Data.Time.LocalTime
import Happstack.Server
import qualified Text.Atom.Feed as Atom
import qualified Text.Atom.Feed.Export as Atom
import Text.StringTemplate
import Text.StringTemplate.Classes
import qualified Text.XML.Light.Output as XML
import Blaaargh.Internal.Exception
import Blaaargh.Internal.Time
import Blaaargh.Internal.Util.ExcludeList
import Blaaargh.Internal.Util.Templates
newtype Post = Post { unPost :: Atom.Entry }
deriving (Show)
getPostTime :: Post -> ZonedTime
getPostTime (Post p) = parseAtomTime $ fromMaybe upd pub
where
pub = Atom.entryPublished p
upd = Atom.entryUpdated p
instance ToSElem Atom.EntryContent where
toSElem (Atom.TextContent s) = toSElem s
toSElem (Atom.HTMLContent s) = toSElem s
toSElem _ = toSElem (""::String)
instance ToSElem Atom.TextContent where
toSElem (Atom.TextString s) = toSElem s
toSElem (Atom.HTMLString s) = toSElem s
toSElem _ = toSElem (""::String)
instance ToSElem Atom.Person where
toSElem (Atom.Person name _ email _) = toSElem $ name ++ em
where
em = maybe "" (\e -> " <" ++ e ++ ">") email
instance ToSElem Post where
toSElem post@(Post p) = SM $ Map.fromList attrs
where
url = Atom.entryId p
body = fromMaybe (Atom.TextContent "") $ Atom.entryContent p
summary = fromMaybe (Atom.HTMLString "") $ Atom.entrySummary p
attrs = [ ("id", toSElem url)
, ("date", toSElem $ friendlyTime $ getPostTime post)
, ("url", toSElem url)
, ("title", toSElem $ Atom.entryTitle p)
, ("content", toSElem body)
, ("summary", toSElem summary)
, ("authors", toSElemList $ Atom.entryAuthors p) ]
instance ToMessage Atom.Feed where
toContentType _ = "application/atom+xml"
toMessage f = L.pack $ XML.showElement $ Atom.xmlFeed f
type ContentMap = Map ByteString ContentItem
data ContentItem =
ContentPost Post
| ContentDirectory ByteString ContentMap
| ContentStatic FilePath
deriving (Show)
data BlaaarghState = BlaaarghState
{ blaaarghPath :: FilePath
, blaaarghSiteURL :: String
, blaaarghBaseURL :: String
, blaaarghPostMap :: ContentMap
, blaaarghTemplates :: TemplateDirectory
, blaaarghFeedInfo :: Atom.Feed
, blaaarghFeedExcludes :: ExcludeList
, blaaarghExtraTmpl :: Template -> Template
}
newtype BlaaarghMonad a =
BlaaarghMonad { unBlaaarghMonad :: StateT BlaaarghState IO a }
deriving (Monad, MonadIO, MonadState BlaaarghState)
type BlaaarghHandler = ServerPartT BlaaarghMonad Response
liftB :: ServerPartT IO a -> ServerPartT BlaaarghMonad a
liftB = mapServerPartT liftIO
runBlaaarghHandler ::
BlaaarghState
-> ServerPartT BlaaarghMonad a
-> ServerPartT IO a
runBlaaarghHandler s = mapServerPartT $ \m -> do
(a,_) <- runStateT (unBlaaarghMonad m) s
return a
addExtraTemplateArguments :: ToSElem a =>
[(String,a)]
-> BlaaarghMonad ()
addExtraTemplateArguments args = do
modify $ \t ->
t { blaaarghExtraTmpl = foldl f (blaaarghExtraTmpl t) args }
where
f :: ToSElem a => (Template -> Template) -> (String, a) -> (Template -> Template)
f xtmpl (k,v) = (setAttribute k v) . xtmpl