summaryrefslogtreecommitdiffhomepage
path: root/libs/apprise/plugins/NotifyXMPP/SliXmppAdapter.py
diff options
context:
space:
mode:
authormorpheus65535 <[email protected]>2021-12-01 21:19:18 -0500
committermorpheus65535 <[email protected]>2021-12-01 21:19:18 -0500
commitd51dc68ebb3910ca09bb40c33814d43b93d916b8 (patch)
tree569807abb70b41eb98dded56c17bd504e793da5b /libs/apprise/plugins/NotifyXMPP/SliXmppAdapter.py
parent402c82d84f7bd51353348bea7d1a876ad9ecc5b1 (diff)
downloadbazarr-d51dc68ebb3910ca09bb40c33814d43b93d916b8.tar.gz
bazarr-d51dc68ebb3910ca09bb40c33814d43b93d916b8.zip
Updated Apprise notification module to the latest providers.v1.0.2-beta.2
Diffstat (limited to 'libs/apprise/plugins/NotifyXMPP/SliXmppAdapter.py')
-rw-r--r--libs/apprise/plugins/NotifyXMPP/SliXmppAdapter.py203
1 files changed, 203 insertions, 0 deletions
diff --git a/libs/apprise/plugins/NotifyXMPP/SliXmppAdapter.py b/libs/apprise/plugins/NotifyXMPP/SliXmppAdapter.py
new file mode 100644
index 000000000..9450e70d7
--- /dev/null
+++ b/libs/apprise/plugins/NotifyXMPP/SliXmppAdapter.py
@@ -0,0 +1,203 @@
+# -*- coding: utf-8 -*-
+
+import ssl
+from os.path import isfile
+import logging
+
+
+# Default our global support flag
+SLIXMPP_SUPPORT_AVAILABLE = False
+
+try:
+ # Import slixmpp if available
+ import slixmpp
+ import asyncio
+
+ SLIXMPP_SUPPORT_AVAILABLE = True
+
+except ImportError:
+ # No problem; we just simply can't support this plugin because we're
+ # either using Linux, or simply do not have slixmpp installed.
+ pass
+
+
+class SliXmppAdapter(object):
+ """
+ Wrapper to slixmpp
+
+ """
+
+ # Reference to XMPP client.
+ xmpp = None
+
+ # Whether everything succeeded
+ success = False
+
+ # The default protocol
+ protocol = 'xmpp'
+
+ # The default secure protocol
+ secure_protocol = 'xmpps'
+
+ # Taken from https://golang.org/src/crypto/x509/root_linux.go
+ CA_CERTIFICATE_FILE_LOCATIONS = [
+ # Debian/Ubuntu/Gentoo etc.
+ "/etc/ssl/certs/ca-certificates.crt",
+ # Fedora/RHEL 6
+ "/etc/pki/tls/certs/ca-bundle.crt",
+ # OpenSUSE
+ "/etc/ssl/ca-bundle.pem",
+ # OpenELEC
+ "/etc/pki/tls/cacert.pem",
+ # CentOS/RHEL 7
+ "/etc/pki/ca-trust/extracted/pem/tls-ca-bundle.pem",
+ ]
+
+ # This entry is a bit hacky, but it allows us to unit-test this library
+ # in an environment that simply doesn't have the slixmpp package
+ # available to us.
+ #
+ # If anyone is seeing this had knows a better way of testing this
+ # outside of what is defined in test/test_xmpp_plugin.py, please
+ # let me know! :)
+ _enabled = SLIXMPP_SUPPORT_AVAILABLE
+
+ def __init__(self, host=None, port=None, secure=False,
+ verify_certificate=True, xep=None, jid=None, password=None,
+ body=None, subject=None, targets=None, before_message=None,
+ logger=None):
+ """
+ Initialize our SliXmppAdapter object
+ """
+
+ self.host = host
+ self.port = port
+ self.secure = secure
+ self.verify_certificate = verify_certificate
+
+ self.xep = xep
+ self.jid = jid
+ self.password = password
+
+ self.body = body
+ self.subject = subject
+ self.targets = targets
+ self.before_message = before_message
+
+ self.logger = logger or logging.getLogger(__name__)
+
+ # Use the Apprise log handlers for configuring the slixmpp logger.
+ apprise_logger = logging.getLogger('apprise')
+ sli_logger = logging.getLogger('slixmpp')
+ for handler in apprise_logger.handlers:
+ sli_logger.addHandler(handler)
+ sli_logger.setLevel(apprise_logger.level)
+
+ if not self.load():
+ raise ValueError("Invalid XMPP Configuration")
+
+ def load(self):
+
+ try:
+ asyncio.get_event_loop()
+
+ except RuntimeError:
+ # slixmpp can not handle not having an event_loop
+ # see: https://lab.louiz.org/poezio/slixmpp/-/issues/3456
+ # This is a work-around to this problem
+ asyncio.set_event_loop(asyncio.new_event_loop())
+
+ # Prepare our object
+ self.xmpp = slixmpp.ClientXMPP(self.jid, self.password)
+
+ # Register our session
+ self.xmpp.add_event_handler("session_start", self.session_start)
+
+ for xep in self.xep:
+ # Load xep entries
+ try:
+ self.xmpp.register_plugin('xep_{0:04d}'.format(xep))
+
+ except slixmpp.plugins.base.PluginNotFound:
+ self.logger.warning(
+ 'Could not register plugin {}'.format(
+ 'xep_{0:04d}'.format(xep)))
+ return False
+
+ if self.secure:
+ # Don't even try to use the outdated ssl.PROTOCOL_SSLx
+ self.xmpp.ssl_version = ssl.PROTOCOL_TLSv1
+
+ # If the python version supports it, use highest TLS version
+ # automatically
+ if hasattr(ssl, "PROTOCOL_TLS"):
+ # Use the best version of TLS available to us
+ self.xmpp.ssl_version = ssl.PROTOCOL_TLS
+
+ self.xmpp.ca_certs = None
+ if self.verify_certificate:
+ # Set the ca_certs variable for certificate verification
+ self.xmpp.ca_certs = next(
+ (cert for cert in self.CA_CERTIFICATE_FILE_LOCATIONS
+ if isfile(cert)), None)
+
+ if self.xmpp.ca_certs is None:
+ self.logger.warning(
+ 'XMPP Secure comunication can not be verified; '
+ 'no local CA certificate file')
+ return False
+
+ # If the user specified a port, skip SRV resolving, otherwise it is a
+ # lot easier to let slixmpp handle DNS instead of the user.
+ self.override_connection = \
+ None if not self.port else (self.host, self.port)
+
+ # We're good
+ return True
+
+ def process(self):
+ """
+ Thread that handles the server/client i/o
+
+ """
+
+ # Instruct slixmpp to connect to the XMPP service.
+ if not self.xmpp.connect(
+ self.override_connection, use_ssl=self.secure):
+ return False
+
+ # Run the asyncio event loop, and return once disconnected,
+ # for any reason.
+ self.xmpp.process(forever=False)
+
+ return self.success
+
+ def session_start(self, *args, **kwargs):
+ """
+ Session Manager
+ """
+
+ targets = list(self.targets)
+ if not targets:
+ # We always default to notifying ourselves
+ targets.append(self.jid)
+
+ while len(targets) > 0:
+
+ # Get next target (via JID)
+ target = targets.pop(0)
+
+ # Invoke "before_message" event hook.
+ self.before_message()
+
+ # The message we wish to send, and the JID that will receive it.
+ self.xmpp.send_message(
+ mto=target, msubject=self.subject,
+ mbody=self.body, mtype='chat')
+
+ # Using wait=True ensures that the send queue will be
+ # emptied before ending the session.
+ self.xmpp.disconnect(wait=True)
+
+ # Toggle our success flag
+ self.success = True