summaryrefslogtreecommitdiff
path: root/ToxToXMPP.hs
diff options
context:
space:
mode:
Diffstat (limited to 'ToxToXMPP.hs')
-rw-r--r--ToxToXMPP.hs94
1 files changed, 81 insertions, 13 deletions
diff --git a/ToxToXMPP.hs b/ToxToXMPP.hs
index 8b2544d7..7208a1d1 100644
--- a/ToxToXMPP.hs
+++ b/ToxToXMPP.hs
@@ -5,26 +5,41 @@
5{-# LANGUAGE ViewPatterns #-} 5{-# LANGUAGE ViewPatterns #-}
6module ToxToXMPP where 6module ToxToXMPP where
7 7
8import Control.Monad
8import Crypto.Tox 9import Crypto.Tox
9import Data.Conduit as C 10import Data.Conduit as C
10import qualified Data.Conduit.List as CL 11import qualified Data.Conduit.List as CL
12import Data.Function
11import Data.Monoid 13import Data.Monoid
12import qualified Data.Text as T 14import qualified Data.Text as T
13 ;import Data.Text (Text) 15 ;import Data.Text (Text)
14import Data.Word
15import Data.Text.Encoding as T 16import Data.Text.Encoding as T
17import Data.Word
16import Data.XML.Types as XML 18import Data.XML.Types as XML
17import EventUtil 19import EventUtil
18import Network.Address 20import Network.Address
19import Network.Tox.Crypto.Transport as Tox 21import Network.Tox.Crypto.Transport as Tox hiding (UserStatus (..))
20import Network.Tox.NodeId 22import Network.Tox.NodeId
21import Util (unsplitJID) 23import Util (unsplitJID)
22import XMPPServer as XMPP 24import XMPPServer as XMPP
23 25
26available :: StanzaType
27available = PresenceStatus { presenceShow = Available
28 , presencePriority = Nothing
29 , presenceStatus = []
30 , presenceWhiteList = []
31 }
32
24xmppHostname :: PublicKey -> Text 33xmppHostname :: PublicKey -> Text
25xmppHostname k = T.pack $ show (key2id k) ++ ".tox" 34xmppHostname k = T.pack $ show (key2id k) ++ ".tox"
26 35
27toxToXmpp :: Monad m => SockAddr -> PublicKey -> Text -> Conduit Tox.CryptoMessage m XML.Event 36toxUserStatus :: Word8 -> JabberShow
37toxUserStatus 0 = Available
38toxUserStatus 1 = Away
39toxUserStatus 2 = DoNotDisturb
40toxUserStatus _ = Away -- Default, shouldn't occur.
41
42toxToXmpp :: Monad m => SockAddr -> PublicKey -> Text -> ConduitM Tox.CryptoMessage XML.Event m ()
28toxToXmpp laddr me theirhost = do 43toxToXmpp laddr me theirhost = do
29 CL.sourceList $ XMPP.greet' "jabber:server" theirhost 44 CL.sourceList $ XMPP.greet' "jabber:server" theirhost
30 let me_u = Nothing 45 let me_u = Nothing
@@ -35,29 +50,82 @@ toxToXmpp laddr me theirhost = do
35 -- /to/ should match local address of this node. 50 -- /to/ should match local address of this node.
36 , me_h 51 , me_h
37 , Nothing)) 52 , Nothing))
38 awaitForever $ \case 53 let
54 statelessMessages = \case
39 55
40 UpToN { msgID = MESSAGE 56 UpToN MESSAGE bs ->
41 , msgBytes = bs }
42 -> do
43 xmppInstantMessage "jabber:server" im_from im_to [] (T.decodeUtf8 bs) 57 xmppInstantMessage "jabber:server" im_from im_to [] (T.decodeUtf8 bs)
44 58
45 TwoByte TYPING st -> xmppTyping "jabber:server" im_from im_to st 59 TwoByte TYPING st -> xmppTyping "jabber:server" im_from im_to st
46 60
61 UpToN NICKNAME bs ->
62 xmppInstantMessage "jabber:server" im_from im_to
63 [ attr "style" "font-weight:bold; color:red" ]
64 ("NICKNAME(todo) " <> T.decodeUtf8 bs)
65
47 toxmsg | msgID toxmsg == PacketRequest -> return () 66 toxmsg | msgID toxmsg == PacketRequest -> return ()
48 67
49 toxmsg -> do 68 toxmsg -> do
50 xmppInstantMessage "jabber:server" 69 xmppInstantMessage "jabber:server" im_from im_to
51 im_from
52 im_to -- /to/ should match local address of this node.
53 [ attr "style" "font-weight:bold; color:red" ] 70 [ attr "style" "font-weight:bold; color:red" ]
54 (T.pack $ show $ msgID toxmsg) 71 (T.pack $ "Unhandled message: " ++ show (msgID toxmsg))
72
73 flip fix available $ \loop status -> do
74 let go (TwoByte USERSTATUS st) = do
75 let status' = status { presenceShow = toxUserStatus st }
76 xmppPresence "jabber:server" im_from status'
77 loop status'
78
79 go (UpToN STATUSMESSAGE bs) = do
80 let status' = status { presenceStatus = [("",T.decodeUtf8 bs)] }
81 xmppPresence "jabber:server" im_from status'
82 loop status'
83
84 go (OneByte ONLINE) = do
85 xmppPresence "jabber:server" im_from status
86 loop status
87
88 go x = do
89 statelessMessages x
90 loop status
91 await >>= mapM_ go
92
93xmppPresence :: Monad m => Text -> Maybe Text -> StanzaType -> ConduitM i XML.Event m ()
94xmppPresence namespace mjid p = do
95 let ns n = n { nameNamespace = Just namespace }
96 setFrom = maybe id
97 (\jid -> (attr "from" jid :) )
98 mjid
99 typ Offline = [attr "type" "unavailable"]
100 typ _ = []
101 shw ExtendedAway = ["xa"]
102 shw Chatty = ["chat"]
103 shw Away = ["away"]
104 shw DoNotDisturb = ["dnd"]
105 shw _ = []
106 jabberShow stat =
107 [ EventBeginElement "{jabber:client}show" []
108 , EventContent (ContentText stat)
109 , EventEndElement "{jabber:client}show" ]
110 C.yield $ EventBeginElement (ns "presence") (setFrom $ typ $ presenceShow p)
111 mapM_ C.yield $ shw (presenceShow p) >>= jabberShow
112 forM_ (presencePriority p) $ \prio -> do
113 C.yield $ EventBeginElement (ns "priority") []
114 C.yield $ EventContent $ ContentText (T.pack $ show prio)
115 C.yield $ EventEndElement (ns "priority")
116 forM_ (presenceStatus p) $ \(lang,txt) -> do
117 let atts | T.null lang = []
118 | otherwise = [ ("xml:lang", [ContentText lang]) ]
119 C.yield $ EventBeginElement (ns "status") atts
120 C.yield $ EventContent $ ContentText txt
121 C.yield $ EventEndElement (ns "status")
122 C.yield $ EventEndElement (ns "presence")
55 123
56xmppTyping :: Monad m => Text 124xmppTyping :: Monad m => Text
57 -> Maybe Text 125 -> Maybe Text
58 -> Maybe Text 126 -> Maybe Text
59 -> Word8 127 -> Word8
60 -> ConduitM i Event m () 128 -> ConduitM i XML.Event m ()
61xmppTyping namespace mfrom mto x = 129xmppTyping namespace mfrom mto x =
62 let ns n = n { nameNamespace = Just namespace } 130 let ns n = n { nameNamespace = Just namespace }
63 st = case x of 131 st = case x of
@@ -80,7 +148,7 @@ xmppInstantMessage :: Monad m => Text
80 -> Maybe Text 148 -> Maybe Text
81 -> [(Name, [Content])] 149 -> [(Name, [Content])]
82 -> Text 150 -> Text
83 -> ConduitM i Event m () 151 -> ConduitM i XML.Event m ()
84xmppInstantMessage namespace mfrom mto style text = do 152xmppInstantMessage namespace mfrom mto style text = do
85 let ns n = n { nameNamespace = Just namespace } 153 let ns n = n { nameNamespace = Just namespace }
86 C.yield $ EventBeginElement (ns "message") 154 C.yield $ EventBeginElement (ns "message")