Coverage for slidge/core/dispatcher/muc/misc.py: 95%
65 statements
« prev ^ index » next coverage.py v7.6.1, created at 2024-11-07 05:11 +0000
« prev ^ index » next coverage.py v7.6.1, created at 2024-11-07 05:11 +0000
1import logging
3from slixmpp import JID, CoroutineCallback, Iq, Message, Presence, StanzaPath
4from slixmpp.exceptions import XMPPError
6from ..util import DispatcherMixin, exceptions_to_xmpp_errors
9class MucMiscMixin(DispatcherMixin):
10 def __init__(self, xmpp):
11 super().__init__(xmpp)
12 xmpp.register_handler(
13 CoroutineCallback(
14 "ibr_remove", StanzaPath("/iq/register"), self.on_ibr_remove
15 )
16 )
18 xmpp.add_event_handler("groupchat_join", self.on_groupchat_join)
19 xmpp.add_event_handler(
20 "groupchat_direct_invite", self.on_groupchat_direct_invite
21 )
22 xmpp.add_event_handler("groupchat_subject", self.on_groupchat_subject)
23 xmpp.add_event_handler("groupchat_message_error", self.__on_group_chat_error)
25 async def __on_group_chat_error(self, msg: Message):
26 condition = msg["error"].get_condition()
27 if condition not in KICKABLE_ERRORS:
28 return
30 try:
31 muc = await self.get_muc_from_stanza(msg)
32 except XMPPError as e:
33 log.debug("Not removing resource", exc_info=e)
34 return
35 mfrom = msg.get_from()
36 resource = mfrom.resource
37 try:
38 muc.remove_user_resource(resource)
39 except KeyError:
40 # this actually happens quite frequently on for both beagle and monal
41 # (not sure why?), but is of no consequence
42 log.debug("%s was not in the resources of %s", resource, muc)
43 else:
44 log.info(
45 "Removed %s from the resources of %s because of error", resource, muc
46 )
48 @exceptions_to_xmpp_errors
49 async def on_ibr_remove(self, iq: Iq):
50 if iq.get_to() == self.xmpp.boundjid.bare:
51 return
53 if iq["type"] == "set" and iq["register"]["remove"]:
54 muc = await self.get_muc_from_stanza(iq)
55 await muc.session.on_leave_group(muc.legacy_id)
56 iq.reply().send()
57 await muc.session.bookmarks.remove(
58 muc, "You left this chat from an XMPP client."
59 )
60 return
62 raise XMPPError("feature-not-implemented")
64 @exceptions_to_xmpp_errors
65 async def on_groupchat_join(self, p: Presence):
66 if not self.xmpp.GROUPS:
67 raise XMPPError(
68 "feature-not-implemented",
69 "This gateway does not implement multi-user chats.",
70 )
71 muc = await self.get_muc_from_stanza(p)
72 await muc.join(p)
74 @exceptions_to_xmpp_errors
75 async def on_groupchat_direct_invite(self, msg: Message):
76 invite = msg["groupchat_invite"]
77 jid = JID(invite["jid"])
79 if jid.domain != self.xmpp.boundjid.bare:
80 raise XMPPError(
81 "bad-request",
82 "Legacy contacts can only be invited to legacy groups, not standard XMPP MUCs.",
83 )
85 if invite["password"]:
86 raise XMPPError(
87 "bad-request", "Password-protected groups are not supported"
88 )
90 session = await self._get_session(msg, logged=True)
91 contact = await session.contacts.by_jid(msg.get_to())
92 muc = await session.bookmarks.by_jid(jid)
94 await session.on_invitation(contact, muc, invite["reason"] or None)
96 @exceptions_to_xmpp_errors
97 async def on_groupchat_subject(self, msg: Message):
98 muc = await self.get_muc_from_stanza(msg)
99 if not muc.HAS_SUBJECT:
100 raise XMPPError(
101 "bad-request",
102 "There are no room subject in here. "
103 "Use the room configuration to update its name or description",
104 )
105 await muc.on_set_subject(msg["subject"])
108KICKABLE_ERRORS = {
109 "gone",
110 "internal-server-error",
111 "item-not-found",
112 "jid-malformed",
113 "recipient-unavailable",
114 "redirect",
115 "remote-server-not-found",
116 "remote-server-timeout",
117 "service-unavailable",
118 "malformed error",
119}
121log = logging.getLogger(__name__)