summaryrefslogtreecommitdiff
path: root/XMPPToTox.hs
diff options
context:
space:
mode:
Diffstat (limited to 'XMPPToTox.hs')
-rw-r--r--XMPPToTox.hs53
1 files changed, 52 insertions, 1 deletions
diff --git a/XMPPToTox.hs b/XMPPToTox.hs
index ae9a774b..f0505ac7 100644
--- a/XMPPToTox.hs
+++ b/XMPPToTox.hs
@@ -14,10 +14,13 @@ import Data.Function
14import Data.Monoid 14import Data.Monoid
15import Data.Text (Text) 15import Data.Text (Text)
16import Data.Text.Encoding as T 16import Data.Text.Encoding as T
17import Data.Word
17import Data.XML.Types as XML 18import Data.XML.Types as XML
18import Network.Tox.Crypto.Transport (CryptoMessage (..), MessageID (..)) 19import Network.Tox.Crypto.Transport (CryptoMessage (..), MessageID (..))
19import Text.XML.Stream.Parse as XML 20import Text.XML.Stream.Parse as XML
20 21
22import XMPPServer (JabberShow(..))
23
21-- Debugging. Not real Tox message. 24-- Debugging. Not real Tox message.
22funnyMessage :: MonadThrow m => Text -> ConduitM i CryptoMessage m () 25funnyMessage :: MonadThrow m => Text -> ConduitM i CryptoMessage m ()
23funnyMessage txt = yield $ UpToN Padding (T.encodeUtf8 txt) 26funnyMessage txt = yield $ UpToN Padding (T.encodeUtf8 txt)
@@ -53,6 +56,53 @@ msgToTox = tag' "{jabber:server}message"
53 , ignoreAnyTreeContent 56 , ignoreAnyTreeContent
54 ] 57 ]
55 58
59readJabberShow :: Text -> JabberShow
60readJabberShow "xa" = ExtendedAway
61readJabberShow "chat" = Chatty
62readJabberShow "away" = Away
63readJabberShow "dnd" = DoNotDisturb
64readJabberShow _ = Available
65
66-- | Convert XMPP "show" field to Tox USERSTATUS.
67jabberUserStatus :: JabberShow -> Word8
68jabberUserStatus Available = 0
69jabberUserStatus Chatty = 0
70jabberUserStatus Away = 1
71jabberUserStatus ExtendedAway = 1
72jabberUserStatus Offline = 1
73jabberUserStatus DoNotDisturb = 2
74
75
76requireMissing :: XML.Name -> AttrParser ()
77requireMissing nm = force ("Unexpected "++show (XML.nameLocalName nm)++" attribute.") $ do
78 m <- attr nm
79 case m of
80 Nothing -> return $ Just ()
81 Just _ -> return Nothing
82
83presenceToTox :: MonadThrow m =>
84 ConduitM Event CryptoMessage m (Maybe ())
85presenceToTox = tag' "{jabber:server}presence"
86 (requireMissing "type" >> ignoreAttrs)
87 $ \_ -> do
88 xs <- XML.many $ choose
89 [ tagIgnoreAttrs "{jabber:server}show"
90 $ do shw <- readJabberShow <$> content
91 yield $ TwoByte USERSTATUS $ jabberUserStatus shw
92 eom
93 return USERSTATUS
94 , tagIgnoreAttrs "{jabber:server}status"
95 -- TODO: The <status> tag may occur multiple times for different "xml:lang" values.
96 $ do txt <- content
97 yield $ UpToN STATUSMESSAGE $ T.encodeUtf8 txt
98 eom
99 return STATUSMESSAGE
100 , fmap (const Padding) <$> ignoreAnyTreeContent -- Ignore the priority tag and anything else.
101 ]
102 when (not $ USERSTATUS `elem` xs) $ do
103 -- Missing <show> element means Available.
104 yield $ TwoByte USERSTATUS $ jabberUserStatus Available
105
56unknownToTox :: MonadThrow m => 106unknownToTox :: MonadThrow m =>
57 ConduitM Event CryptoMessage m (Maybe ()) 107 ConduitM Event CryptoMessage m (Maybe ())
58unknownToTox = tag anyName (\n -> ignoreAttrs >> return n) $ \n -> do 108unknownToTox = tag anyName (\n -> ignoreAttrs >> return n) $ \n -> do
@@ -60,13 +110,14 @@ unknownToTox = tag anyName (\n -> ignoreAttrs >> return n) $ \n -> do
60 eom 110 eom
61 111
62 112
63xmppToTox :: MonadThrow m => Conduit XML.Event m CryptoMessage 113xmppToTox :: MonadThrow m => ConduitM XML.Event CryptoMessage m ()
64xmppToTox = do 114xmppToTox = do
65 eventBeginDocument <- await 115 eventBeginDocument <- await
66 streamTag <- await 116 streamTag <- await
67 fix $ \loop -> do 117 fix $ \loop -> do
68 got <- choose 118 got <- choose
69 [ msgToTox 119 [ msgToTox
120 , presenceToTox
70 , unknownToTox 121 , unknownToTox
71 ] 122 ]
72 forM_ got $ \_ -> loop 123 forM_ got $ \_ -> loop