{-# LANGUAGE LambdaCase #-} {-# LANGUAGE NoMonomorphismRestriction #-} module XMPPToTox ( module XMPPToTox , CryptoMessage(..) , MessageID(..) ) where import Control.Applicative import Control.Monad import Control.Monad.Catch import Data.Conduit import Data.Function import Data.Monoid import Data.Text (Text) import Data.Text.Encoding as T import Data.XML.Types as XML import Network.Tox.Crypto.Transport (CryptoMessage (..), MessageID (..)) import Text.XML.Stream.Parse as XML -- Debugging. Not real Tox message. funnyMessage :: MonadThrow m => Text -> ConduitM i CryptoMessage m () funnyMessage txt = yield $ UpToN Padding (T.encodeUtf8 txt) sendMsg :: MonadThrow m => Text -> ConduitM i CryptoMessage m () sendMsg txt = do yield $ UpToN MESSAGE (T.encodeUtf8 txt) yield $ TwoByte TYPING 0 -- Message send implies not typing. eom :: MonadThrow m => ConduitM Event o m () eom = many_ ignoreAnyTreeContent msgToTox :: MonadThrow m => ConduitM Event CryptoMessage m (Maybe ()) msgToTox = tag' "{jabber:server}message" (requireAttr "type" >>= \case "chat" -> ignoreAttrs _ -> empty) $ \_ -> many_ $ choose [ tagIgnoreAttrs "{jabber:server}body" $ do content >>= sendMsg eom , tagIgnoreAttrs "{http://jabber.org/protocol/chatstates}composing" $ do yield $ TwoByte TYPING 1 eom , tagIgnoreAttrs "{http://jabber.org/protocol/chatstates}active" $ do yield $ TwoByte TYPING 0 eom , tagIgnoreAttrs "{http://jabber.org/protocol/chatstates}paused" $ do yield $ TwoByte TYPING 0 eom , ignoreAnyTreeContent ] unknownToTox :: MonadThrow m => ConduitM Event CryptoMessage m (Maybe ()) unknownToTox = tag anyName (\n -> ignoreAttrs >> return n) $ \n -> do funnyMessage $ nameLocalName n eom xmppToTox :: MonadThrow m => Conduit XML.Event m CryptoMessage xmppToTox = do eventBeginDocument <- await streamTag <- await fix $ \loop -> do got <- choose [ msgToTox , unknownToTox ] forM_ got $ \_ -> loop