Skip to content
This repository has been archived by the owner on Jan 14, 2024. It is now read-only.

Commit

Permalink
presence: support actual emission of directed presences
Browse files Browse the repository at this point in the history
  • Loading branch information
horazont committed Dec 15, 2018
1 parent e1ed15e commit 4de61e3
Show file tree
Hide file tree
Showing 2 changed files with 440 additions and 16 deletions.
72 changes: 56 additions & 16 deletions aioxmpp/presence/service.py
Original file line number Diff line number Diff line change
Expand Up @@ -269,10 +269,18 @@ class DirectedPresenceHandle:
.. automethod:: send_presence
"""

def __init__(self, service: "PresenceServer", peer: aioxmpp.JID):
def __init__(self, service: "PresenceServer", peer: aioxmpp.JID,
muted: bool = False):
super().__init__()
self._address = peer
self._service = service
self._muted = muted
self._presence_filter = None
self._unsubscribed = False

def _require_subscribed(self):
if self._unsubscribed:
raise RuntimeError("directed presence relationship is unsubscribed")

@property
def address(self) -> aioxmpp.JID:
Expand Down Expand Up @@ -302,6 +310,7 @@ def muted(self) -> bool:
This attribute is read-only. It must be modified through
:meth:`set_muted`.
"""
return self._muted

@property
def presence_filter(self):
Expand All @@ -322,12 +331,13 @@ def presence_filter(self):
modifications from leaking into other presence relationships; making a
copy inside the callback is not required or recommended.
"""
return self._presence_filter

@presence_filter.setter
def presence_filter(self, new_callback):
pass
self._presence_filter = new_callback

def set_muted(self, muted, *, send_update_now=True):
def set_muted(self, muted: bool, *, send_update_now: bool = True):
"""
Change the :attr:`muted` state of the relationship.
Expand All @@ -351,6 +361,14 @@ def set_muted(self, muted, *, send_update_now=True):
If `send_update_now` is :data:`True`, the current presence is sent to
the peer immediately.
"""
self._require_subscribed()

muted = bool(muted)
if muted == self._muted:
return

self._muted = muted
self._service._emit_presence_directed(self)

def unsubscribe(self):
"""
Expand All @@ -375,25 +393,24 @@ def unsubscribe(self):
This operation is idempotent.
"""
if self._unsubscribed:
return

self._service._unsubscribe_peer_directed(self)
self._unsubscribed = True

def send_presence(self, stanza: aioxmpp.Presence):
def resend_presence(self):
"""
Send a presence stanza to the peer.
Resend the current presence to the directed peer.
:param stanza: The stanza to send.
:type stanza: :class:`aioxmpp.Presence`
:raises RuntimeError: if the presence relationship has been destroyed
with :meth:`unsubscribe`
The type of the presence `stanza` must be either
:attr:`aioxmpp.PresenceType.AVAILABLE` or
:attr:`aioxmpp.PresenceType.UNAVAILABLE`.
The :meth:`presence_filter` is not invoked on this `stanza`; it is
assumed that the owner of the relationship takes care of setting the
`stanza` up in the way it is needed.
This forces a presence send, even if the relationship is muted. The
:attr:`presence_filter` is invoked as normal.
"""
self._require_subscribed()
self._service._emit_presence_directed(self)


class PresenceServer(aioxmpp.service.Service):
Expand Down Expand Up @@ -583,6 +600,15 @@ def set_presence(self, state, status={}, priority=0):
self.on_presence_changed()
return self.resend_presence()

def _emit_presence_directed(self, session):
st = self.make_stanza()
st.to = session.address
if session.presence_filter is not None:
st = session.presence_filter(st)
if st is None:
return
self.client.enqueue(st)

def resend_presence(self):
"""
Re-send the currently configured presence.
Expand All @@ -599,8 +625,18 @@ def resend_presence(self):
any of the parameters changed.
"""

if self.client.established:
return self.client.enqueue(self.make_stanza())
if not self.client.established:
return

main_token = self.client.enqueue(self.make_stanza())

for sessions in self._directed_sessions.values():
for session in sessions.values():
if session.muted:
continue
self._emit_presence_directed(session)

return main_token

def subscribe_peer_directed(self,
peer: aioxmpp.JID,
Expand Down Expand Up @@ -658,8 +694,12 @@ def subscribe_peer_directed(self,
result = sessions[peer.resource] = DirectedPresenceHandle(
self,
peer,
muted=muted,
)

if not muted:
self._emit_presence_directed(result)

return result

def _unsubscribe_peer_directed(self, handle: DirectedPresenceHandle):
Expand Down
Loading

0 comments on commit 4de61e3

Please sign in to comment.