Coverage for slidge/slixfix/xep_0100/gateway.py: 64%
64 statements
« prev ^ index » next coverage.py v7.8.0, created at 2025-05-04 08:17 +0000
« prev ^ index » next coverage.py v7.8.0, created at 2025-05-04 08:17 +0000
1import logging
2import warnings
4from slixmpp import JID, Iq, Message, Presence, register_stanza_plugin
5from slixmpp.exceptions import XMPPError
6from slixmpp.plugins.base import BasePlugin
8from slidge.core import config
10from . import stanza
12log = logging.getLogger(__name__)
15class XEP_0100(BasePlugin):
16 name = "xep_0100"
17 description = "XEP-0100: Gateway interaction (slidge)"
18 dependencies = {
19 "xep_0030", # Service discovery
20 "xep_0077", # In band registration
21 "xep_0356", # Privileged entities
22 }
24 default_config = {
25 "component_name": "SliXMPP gateway",
26 "type": "xmpp",
27 "needs_registration": True,
28 }
30 def plugin_init(self) -> None:
31 if not self.xmpp.is_component:
32 log.error("Only components can be gateways, aborting plugin load")
33 return
35 self.xmpp["xep_0030"].add_identity(
36 name=self.component_name, category="gateway", itype=self.type
37 )
39 # Without that BaseXMPP sends unsub/unavailable on sub requests, and we don't want that
40 self.xmpp.client_roster.auto_authorize = False
41 self.xmpp.client_roster.auto_subscribe = False
43 self.xmpp.add_event_handler("user_register", self.on_user_register)
44 self.xmpp.add_event_handler("user_unregister", self.on_user_unregister)
45 self.xmpp.add_event_handler(
46 "presence_unsubscribe", self.on_presence_unsubscribe
47 )
49 self.xmpp.add_event_handler("message", self.on_message)
51 register_stanza_plugin(Iq, stanza.Gateway)
53 def plugin_end(self) -> None:
54 if not self.xmpp.is_component:
55 self.xmpp.remove_event_handler("user_register", self.on_user_register)
56 self.xmpp.remove_event_handler("user_unregister", self.on_user_unregister)
57 self.xmpp.remove_event_handler(
58 "presence_unsubscribe", self.on_presence_unsubscribe
59 )
61 self.xmpp.remove_event_handler("message", self.on_message)
63 async def get_user(self, stanza):
64 return await self.xmpp["xep_0077"].api["user_get"](None, None, None, stanza)
66 async def on_user_unregister(self, iq: Iq) -> None:
67 self.xmpp.send_presence(pto=iq.get_from().bare, ptype="unavailable")
68 self.xmpp.send_presence(pto=iq.get_from().bare, ptype="unsubscribe")
69 self.xmpp.send_presence(pto=iq.get_from().bare, ptype="unsubscribed")
71 async def on_user_register(self, iq: Iq) -> None:
72 self.xmpp.client_roster[iq.get_from()].load()
73 await self.add_component_to_roster(jid=iq.get_from())
75 async def add_component_to_roster(self, jid: JID) -> None:
76 items = {
77 self.xmpp.boundjid.bare: {
78 "name": self.component_name,
79 "subscription": "both",
80 "groups": ["Slidge"],
81 }
82 }
83 try:
84 await self._set_roster(jid, items)
85 except PermissionError:
86 from slidge import __version__
88 warnings.warn(
89 "Slidge does not have the privilege to manage rosters. See "
90 f"https://slidge.im/docs/slidge/{__version__}/admin/privilege.html"
91 )
92 self.xmpp.send_presence(ptype="subscribe", pto=jid.bare)
94 async def _set_roster(self, jid, items) -> None:
95 await self.xmpp["xep_0356"].set_roster(jid=jid.bare, roster_items=items)
97 def on_presence_unsubscribe(self, p: Presence) -> None:
98 if p.get_to() == self.xmpp.boundjid.bare:
99 log.debug("REMOVE: Our roster: %s", self.xmpp.client_roster)
100 self.xmpp["xep_0077"].api["user_remove"](None, None, p["from"], p)
101 self.xmpp.event("user_unregister", p)
103 async def on_message(self, msg: Message):
104 if msg["type"] == "groupchat":
105 return # groupchat messages are out of scope of XEP-0100
107 if msg["to"] == self.xmpp.boundjid.bare:
108 # It may be useful to exchange direct messages with the component
109 self.xmpp.event("gateway_message", msg)
110 return
112 if self.needs_registration and await self.get_user(msg) is None:
113 raise XMPPError(
114 "registration-required", text="You are not registered to this gateway"
115 )
117 self.xmpp.event("legacy_message", msg)