summaryrefslogtreecommitdiff
path: root/Presence/XMPP.hs
diff options
context:
space:
mode:
Diffstat (limited to 'Presence/XMPP.hs')
-rw-r--r--Presence/XMPP.hs68
1 files changed, 66 insertions, 2 deletions
diff --git a/Presence/XMPP.hs b/Presence/XMPP.hs
index 70f2905a..4c8beec4 100644
--- a/Presence/XMPP.hs
+++ b/Presence/XMPP.hs
@@ -75,6 +75,7 @@ import Data.Conduit.Blaze
75import Data.List (find) 75import Data.List (find)
76import qualified Text.Show.ByteString as L 76import qualified Text.Show.ByteString as L
77import NestingXML 77import NestingXML
78import Data.Set as Set (Set)
78import qualified Data.Set as Set 79import qualified Data.Set as Set
79import qualified Data.Map as Map 80import qualified Data.Map as Map
80import GHC.Conc 81import GHC.Conc
@@ -528,7 +529,7 @@ handlePeer st src snk = do
528 jids <- newTVarIO Set.empty 529 jids <- newTVarIO Set.empty
529 session <- newSession session_factory sock 530 session <- newSession session_factory sock
530 531
531 finally ( src $= parseBytes def $$ fromPeer session ) 532 finally ( src $= parseBytes def $$ fromPeer (session,jids) )
532 $ do 533 $ do
533 L.putStrLn $ "(P) disconnected " <++> name 534 L.putStrLn $ "(P) disconnected " <++> name
534 js <- fmap Set.toList (readTVarIO jids) 535 js <- fmap Set.toList (readTVarIO jids)
@@ -536,8 +537,61 @@ handlePeer st src snk = do
536 forM_ js $ announcePresence session . offline 537 forM_ js $ announcePresence session . offline
537 closeSession session 538 closeSession session
538 539
540
541handlePeerPresence (session,jids) stanza False = do
542 -- Offline
543 withJust (lookupAttrib "from" (tagAttrs stanza)) $ \jid -> do
544 peer_jid <- liftIO $ parseAddressJID (L.fromChunks [S.encodeUtf8 jid])
545 liftIO . atomically $ do
546 jids_ <- readTVar jids
547 writeTVar jids (Set.delete peer_jid jids_)
548 liftIO $ announcePresence session (Presence peer_jid Offline)
549handlePeerPresence (session,jids) stanza True = do
550 -- online (Available or Away)
551 let log = liftIO . L.putStrLn . ("(P) " <++>)
552 withJust (lookupAttrib "from" (tagAttrs stanza)) $ \jid -> do
553 pjid <- liftIO $ parseAddressJID (L.fromChunks [S.encodeUtf8 jid])
554 -- stat <- show element content
555 let parseChildren stat = do
556 child <- nextElement
557 case child of
558 Just tag | tagName tag=="{jabber:server}show"
559 -> fmap toStat (lift content)
560 Just tag | otherwise -> parseChildren stat
561 Nothing -> return stat
562 toStat "away" = Away
563 toStat "xa" = Away -- TODO: xa
564 toStat "dnd" = Away -- TODO: dnd
565 toStat "chat" = Available
566
567 stat' <- parseChildren Available
568
569 liftIO . atomically $ do
570 jids_ <- readTVar jids
571 writeTVar jids (Set.insert pjid jids_)
572 liftIO $ announcePresence session (Presence pjid stat')
573 log $ bshow (Presence pjid stat')
574
575matchAttribMaybe name (Just value) attrs =
576 case find ( (==name) . fst) attrs of
577 Just (_,[ContentText x]) | x==value -> True
578 Just (_,[ContentEntity x]) | x==value -> True
579 _ -> False
580matchAttribMaybe name Nothing attrs
581 | find ( (==name) . fst) attrs==Nothing
582 = True
583
584presenceTypeOffline = Just "unavailable"
585presenceTypeOnline = Nothing
586
587isPresence (EventBeginElement name attrs) testType
588 | name=="{jabber:server}presence"
589 && matchAttribMaybe "type" testType attrs
590 = True
591isPresenceOf _ _ = False
592
539fromPeer :: (MonadThrow m,MonadIO m, XMPPSession session) => 593fromPeer :: (MonadThrow m,MonadIO m, XMPPSession session) =>
540 session -> Sink XML.Event m () 594 (session, TVar (Set JID)) -> Sink XML.Event m ()
541fromPeer session = doNestingXML $ do 595fromPeer session = doNestingXML $ do
542 let log = liftIO . L.putStrLn . ("(P) " <++>) 596 let log = liftIO . L.putStrLn . ("(P) " <++>)
543 withXML $ \begindoc -> do 597 withXML $ \begindoc -> do
@@ -552,6 +606,16 @@ fromPeer session = doNestingXML $ do
552 whenJust nextElement $ \stanza -> do 606 whenJust nextElement $ \stanza -> do
553 stanza_lvl <- nesting 607 stanza_lvl <- nesting
554 608
609 let unhandledStanza = do
610 mb <- lift . runMaybeT $ gatherElement stanza Seq.empty
611 withJust mb $ \xs -> prettyPrint "P: " (toList xs)
612 case () of
613 _ | stanza `isPresenceOf` presenceTypeOnline
614 -> handlePeerPresence session stanza True
615 _ | stanza `isPresenceOf` presenceTypeOffline
616 -> handlePeerPresence session stanza False
617 _ -> unhandledStanza
618
555 awaitCloser stanza_lvl 619 awaitCloser stanza_lvl
556 loop 620 loop
557 621