diff options
-rw-r--r-- | Presence/XMPP.hs | 68 |
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 | |||
75 | import Data.List (find) | 75 | import Data.List (find) |
76 | import qualified Text.Show.ByteString as L | 76 | import qualified Text.Show.ByteString as L |
77 | import NestingXML | 77 | import NestingXML |
78 | import Data.Set as Set (Set) | ||
78 | import qualified Data.Set as Set | 79 | import qualified Data.Set as Set |
79 | import qualified Data.Map as Map | 80 | import qualified Data.Map as Map |
80 | import GHC.Conc | 81 | import 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 | |||
541 | handlePeerPresence (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) | ||
549 | handlePeerPresence (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 | |||
575 | matchAttribMaybe 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 | ||
580 | matchAttribMaybe name Nothing attrs | ||
581 | | find ( (==name) . fst) attrs==Nothing | ||
582 | = True | ||
583 | |||
584 | presenceTypeOffline = Just "unavailable" | ||
585 | presenceTypeOnline = Nothing | ||
586 | |||
587 | isPresence (EventBeginElement name attrs) testType | ||
588 | | name=="{jabber:server}presence" | ||
589 | && matchAttribMaybe "type" testType attrs | ||
590 | = True | ||
591 | isPresenceOf _ _ = False | ||
592 | |||
539 | fromPeer :: (MonadThrow m,MonadIO m, XMPPSession session) => | 593 | fromPeer :: (MonadThrow m,MonadIO m, XMPPSession session) => |
540 | session -> Sink XML.Event m () | 594 | (session, TVar (Set JID)) -> Sink XML.Event m () |
541 | fromPeer session = doNestingXML $ do | 595 | fromPeer 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 | ||