summaryrefslogtreecommitdiff
path: root/XMPPToTox.hs
blob: 7ca4330e4ade614d01d97b270a4b087ba84537cb (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
{-# 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 = yield $ UpToN MESSAGE (T.encodeUtf8 txt)


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}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