module Network.XMPP.Monad where import Control.Applicative((<$>)) import Control.Monad.Trans import Control.Monad.Trans.State import Data.Conduit import Data.Conduit.Text as CT import Data.Conduit.Binary as CB import Data.Conduit.List as CL import Data.XML.Types import Data.Default import Data.Text import Network.XMPP.Types import Network.XMPP.Marshal import System.IO import Text.XML.Stream.Elements import Text.XML.Stream.Render as XR import Text.XML.Stream.Parse type XMPPMonad a = StateT XMPPState (ResourceT IO) a data XMPPState = XMPPState { sConSrc :: BufferedSource IO Event , sConSink :: Sink Event IO () , sConHandle :: Maybe Handle , sFeatures :: ServerFeatures , sHaveTLS :: Bool , sHostname :: Text , sUsername :: Text , sResource :: Maybe Text } data ServerFeatures = SF { stls :: Bool , stlsRequired :: Bool , saslMechanisms :: [Text] , other :: [Element] } deriving Show instance Default ServerFeatures where def = SF { stls = False , stlsRequired = False , saslMechanisms = [] , other = [] } pushE :: Element -> XMPPMonad () pushE x = do sink <- gets sConSink lift $ CL.sourceList (elementToEvents x) $$ sink push :: Stanza -> XMPPMonad () push = pushE . stanzaToElement pushOpen :: Element -> XMPPMonad () pushOpen x = do sink <- gets sConSink lift $ CL.sourceList (elementToEvents' x) $$ sink pulls :: Sink Event IO a -> XMPPMonad a pulls snk = do source <- gets sConSrc lift $ source $$ snk pullE :: XMPPMonad Element pullE = do source <- gets sConSrc pulls elementFromEvents pull :: XMPPMonad Stanza pull = elementToStanza <$> pullE xmppFromHandle handle hostname username resource f = runResourceT $ do liftIO $ hSetBuffering handle NoBuffering src <- bufferSource $ CB.sourceHandle handle $= CT.decode CT.utf8 $= parseText def let st = XMPPState src (XR.renderBytes def =$ CB.sinkHandle handle) (Just handle) def False hostname username resource runStateT f st