Browse Source

add onPresenceChange method

onPresenceChange is called when the presence status of a peer changes,
i.e. it goes online or offline or the IM presence is changed
master
Philipp Balzarek 11 years ago
parent
commit
5c8040b80c
  1. 2
      source/Network/Xmpp/Concurrent.hs
  2. 2
      source/Network/Xmpp/Concurrent/Types.hs
  3. 4
      source/Network/Xmpp/IM/Presence.hs
  4. 30
      source/Network/Xmpp/IM/PresenceTracker.hs
  5. 2
      source/Network/Xmpp/IM/PresenceTracker/Types.hs

2
source/Network/Xmpp/Concurrent.hs

@ -175,7 +175,7 @@ newSession stream config realm mbSasl = runErrorT $ do
then [handleRoster boundJid ros out] then [handleRoster boundJid ros out]
else [] else []
let presenceH = if (enablePresenceTracking config) let presenceH = if (enablePresenceTracking config)
then [handlePresence peers out] then [handlePresence (onPresenceChange config) peers out]
else [] else []
(sStanza, ps) <- initPlugins out $ plugins config (sStanza, ps) <- initPlugins out $ plugins config
let stanzaHandler = runHandlers $ List.concat let stanzaHandler = runHandlers $ List.concat

2
source/Network/Xmpp/Concurrent/Types.hs

@ -87,6 +87,7 @@ data SessionConfiguration = SessionConfiguration
, enableRoster :: Bool , enableRoster :: Bool
-- | Track incomming presence stancas. -- | Track incomming presence stancas.
, enablePresenceTracking :: Bool , enablePresenceTracking :: Bool
, onPresenceChange :: Maybe (PeerStatus -> PeerStatus -> IO ())
} }
instance Default SessionConfiguration where instance Default SessionConfiguration where
@ -101,6 +102,7 @@ instance Default SessionConfiguration where
, plugins = [] , plugins = []
, enableRoster = True , enableRoster = True
, enablePresenceTracking = True , enablePresenceTracking = True
, onPresenceChange = Nothing
} }
-- | Handlers to be run when the Xmpp session ends and when the Xmpp connection is -- | Handlers to be run when the Xmpp session ends and when the Xmpp connection is

4
source/Network/Xmpp/IM/Presence.hs

@ -13,12 +13,12 @@ import Network.Xmpp.Types
data ShowStatus = StatusAway data ShowStatus = StatusAway
| StatusChat | StatusChat
| StatusDnd | StatusDnd
| StatusXa deriving (Read, Show) | StatusXa deriving (Read, Show, Eq)
data IMPresence = IMP { showStatus :: Maybe ShowStatus data IMPresence = IMP { showStatus :: Maybe ShowStatus
, status :: Maybe Text , status :: Maybe Text
, priority :: Maybe Int , priority :: Maybe Int
} deriving Show } deriving (Show, Eq)
imPresence :: IMPresence imPresence :: IMPresence
imPresence = IMP { showStatus = Nothing imPresence = IMP { showStatus = Nothing

30
source/Network/Xmpp/IM/PresenceTracker.hs

@ -2,8 +2,10 @@
module Network.Xmpp.IM.PresenceTracker where module Network.Xmpp.IM.PresenceTracker where
import Control.Applicative import Control.Applicative
import Control.Concurrent
import Control.Concurrent.STM import Control.Concurrent.STM
import Data.Foldable import Control.Monad
import qualified Data.Foldable as Foldable
import Data.Map.Strict (Map) import Data.Map.Strict (Map)
import qualified Data.Map.Strict as Map import qualified Data.Map.Strict as Map
import Data.Maybe import Data.Maybe
@ -57,21 +59,31 @@ peerMapPeerAvailable :: Jid -> Peers -> Bool
peerMapPeerAvailable j | isFull j = not . nullOf (peerStatusL j . _PeerAvailable) peerMapPeerAvailable j | isFull j = not . nullOf (peerStatusL j . _PeerAvailable)
| otherwise = not . nullOf (_peers . at j . _Just) | otherwise = not . nullOf (_peers . at j . _Just)
handlePresence :: TVar Peers -> StanzaHandler handlePresence :: Maybe (PeerStatus -> PeerStatus -> IO ())
handlePresence peers _ st _ = do -> TVar Peers
-> StanzaHandler
handlePresence onChange peers _ st _ = do
let mbPr = do let mbPr = do
pr <- st ^? _Presence -- Only act on presence stanzas pr <- st ^? _Presence -- Only act on presence stanzas
fr <- pr ^? from . _Just . _isFull -- Only act on full JIDs fr <- pr ^? from . _Just . _isFull -- Only act on full JIDs
return (pr, fr) return (pr, fr)
forM_ mbPr $ \(pr, fr) -> Foldable.forM_ mbPr $ \(pr, fr) ->
case presenceType pr of case presenceType pr of
Available -> atomically . modifyTVar peers Available -> setStatus fr (PeerAvailable (getIMPresence pr))
$ set (peerStatusL fr) Unavailable -> setStatus fr PeerUnavailable
(PeerAvailable (getIMPresence pr))
Unavailable -> atomically . modifyTVar peers
$ set (peerStatusL fr) PeerUnavailable
_ -> return () _ -> return ()
return [(st, [])] return [(st, [])]
where
setStatus fr newStatus = do
os <- atomically $ do
ps <- readTVar peers
let oldStatus = ps ^. peerStatusL fr
writeTVar peers $ ps & set (peerStatusL fr) newStatus
return oldStatus
unless (os == newStatus) $ case onChange of
Nothing -> return ()
Just oc -> void . forkIO $ oc os newStatus
return ()
-- | Check whether a given jid is available -- | Check whether a given jid is available
isPeerAvailable :: Jid -> Session -> STM Bool isPeerAvailable :: Jid -> Session -> STM Bool

2
source/Network/Xmpp/IM/PresenceTracker/Types.hs

@ -17,4 +17,4 @@ newtype Peers = Peers { unPeers :: Map Jid (Map Jid (Maybe IMPresence))}
data PeerStatus = PeerAvailable (Maybe IMPresence) data PeerStatus = PeerAvailable (Maybe IMPresence)
| PeerUnavailable | PeerUnavailable
deriving (Show) deriving (Show, Eq)

Loading…
Cancel
Save