XEP-0045: return occupants and history when join is complete

This commit is contained in:
mathieui 2022-02-27 18:11:10 +01:00
parent 815b7d5af7
commit 06172ea896

View File

@ -56,6 +56,7 @@ from slixmpp.types import (
PresenceArgs, PresenceArgs,
) )
JoinResult = Tuple[Presence, Message, List[Presence], List[Message]]
log = logging.getLogger(__name__) log = logging.getLogger(__name__)
@ -71,7 +72,7 @@ class XEP_0045(BasePlugin):
name = 'xep_0045' name = 'xep_0045'
description = 'XEP-0045: Multi-User Chat' description = 'XEP-0045: Multi-User Chat'
dependencies = {'xep_0030', 'xep_0004'} dependencies = {'xep_0030', 'xep_0004', 'xep_0203'}
stanza = stanza stanza = stanza
rooms: Dict[JID, Dict[str, MucRoomItem]] rooms: Dict[JID, Dict[str, MucRoomItem]]
@ -254,7 +255,7 @@ class XEP_0045(BasePlugin):
if msg['body'] or msg['thread']: if msg['body'] or msg['thread']:
return return
self.xmpp.event('groupchat_subject', msg) self.xmpp.event('groupchat_subject', msg)
self.xmpp.event('muc::%s::groupchat_subject' % msg['from'].bare) self.xmpp.event('muc::%s::groupchat_subject' % msg['from'].bare, msg)
async def join_muc_wait(self, room: JID, nick: str, *, async def join_muc_wait(self, room: JID, nick: str, *,
password: Optional[str] = None, password: Optional[str] = None,
@ -263,7 +264,7 @@ class XEP_0045(BasePlugin):
seconds: Optional[int] = None, seconds: Optional[int] = None,
since: Optional[datetime] = None, since: Optional[datetime] = None,
presence_options: Optional[PresenceArgs] = None, presence_options: Optional[PresenceArgs] = None,
timeout: Optional[int] = None) -> Tuple[Presence, Message]: timeout: Optional[int] = None) -> JoinResult:
""" """
Try to join a MUC and block until we are joined or get an error. Try to join a MUC and block until we are joined or get an error.
@ -283,7 +284,8 @@ class XEP_0045(BasePlugin):
presence error. presence error.
:raises: An asyncio.TimeoutError if there is neither success nor :raises: An asyncio.TimeoutError if there is neither success nor
presence error when the timeout is reached. presence error when the timeout is reached.
:return: Our own presence and the subject :return: A tuple containing our own presence, the subject, a list
of occupants and a list of history messages.
""" """
if presence_options is None: if presence_options is None:
presence_options = {} presence_options = {}
@ -306,14 +308,36 @@ class XEP_0045(BasePlugin):
self.rooms[room] = {} self.rooms[room] = {}
self.our_nicks[room] = nick self.our_nicks[room] = nick
stanza.send() stanza.send()
return await self._await_join(room, timeout)
async def _await_join(self, room: JID, timeout: Optional[int] = None) -> JoinResult:
"""Do the heavy lifting for awaiting a MUC join
A muc join, once the join stanza is sent, is:
occupant presences self-presence room history room subject
"""
presence_done: asyncio.Future = asyncio.Future() presence_done: asyncio.Future = asyncio.Future()
topic_received: asyncio.Future = asyncio.Future() topic_received: asyncio.Future = asyncio.Future()
context0 = self.xmpp.event_handler("muc::%s::groupchat_subject" % room, topic_received.set_result) history_buffer: List[Message] = []
context1 = self.xmpp.event_handler("muc::%s::self-presence" % room, presence_done.set_result) occupant_buffer: List[Presence] = []
context2 = self.xmpp.event_handler("muc::%s::presence-error" % room, presence_done.set_result)
with context0: def add_message(msg: Message):
with context1, context2: delay = msg.get_plugin('delay', check=True)
print(delay)
if delay is not None and delay['from'] == room:
history_buffer.append(msg)
def add_occupant(pres: Presence):
occupant_buffer.append(pres)
catch_occupants = self.xmpp.event_handler("muc::%s::got_online" % room, add_occupant)
catch_history = self.xmpp.event_handler("muc::%s::message" % room, add_message)
subject_handler = self.xmpp.event_handler("muc::%s::groupchat_subject" % room, topic_received.set_result)
self_presence = self.xmpp.event_handler("muc::%s::self-presence" % room, presence_done.set_result)
presence_error = self.xmpp.event_handler("muc::%s::presence-error" % room, presence_done.set_result)
with subject_handler, catch_history, catch_occupants:
with self_presence, presence_error:
done, pending = await asyncio.wait( done, pending = await asyncio.wait(
[presence_done], [presence_done],
timeout=timeout, timeout=timeout,
@ -332,7 +356,7 @@ class XEP_0045(BasePlugin):
subject: Message = topic_received.result() subject: Message = topic_received.result()
# update known nick in case it has changed # update known nick in case it has changed
self.our_nicks[room] = pres['from'].resource self.our_nicks[room] = pres['from'].resource
return (pres, subject) return (pres, subject, occupant_buffer, history_buffer)
def join_muc(self, room: JID, nick: str, maxhistory="0", password='', def join_muc(self, room: JID, nick: str, maxhistory="0", password='',
pstatus='', pshow='', pfrom='') -> asyncio.Future: pstatus='', pshow='', pfrom='') -> asyncio.Future: