Mercurial > libervia-backend
view libervia/backend/plugins/plugin_xep_0092.py @ 4127:5fc26a6ef113
frontends (tools) new `aio` module for tools regarding asyncio:
A first method lets run an async method from blocking code.
rel 424
author | Goffi <goffi@goffi.org> |
---|---|
date | Tue, 03 Oct 2023 16:27:51 +0200 |
parents | 4b842c1fb686 |
children |
line wrap: on
line source
#!/usr/bin/env python3 # SàT plugin for Software Version (XEP-0092) # Copyright (C) 2009-2021 Jérôme Poisson (goffi@goffi.org) # This program is free software: you can redistribute it and/or modify # it under the terms of the GNU Affero General Public License as published by # the Free Software Foundation, either version 3 of the License, or # (at your option) any later version. # This program is distributed in the hope that it will be useful, # but WITHOUT ANY WARRANTY; without even the implied warranty of # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the # GNU Affero General Public License for more details. # You should have received a copy of the GNU Affero General Public License # along with this program. If not, see <http://www.gnu.org/licenses/>. from typing import Tuple from twisted.internet import defer, reactor from twisted.words.protocols.jabber import jid from wokkel import compat from libervia.backend.core import exceptions from libervia.backend.core.constants import Const as C from libervia.backend.core.core_types import SatXMPPEntity from libervia.backend.core.i18n import _ from libervia.backend.core.log import getLogger log = getLogger(__name__) NS_VERSION = "jabber:iq:version" TIMEOUT = 10 PLUGIN_INFO = { C.PI_NAME: "Software Version Plugin", C.PI_IMPORT_NAME: "XEP-0092", C.PI_TYPE: "XEP", C.PI_PROTOCOLS: ["XEP-0092"], C.PI_DEPENDENCIES: [], C.PI_RECOMMENDATIONS: [C.TEXT_CMDS], C.PI_MAIN: "XEP_0092", C.PI_HANDLER: "no", # version is already handler in core.xmpp module C.PI_DESCRIPTION: _("""Implementation of Software Version"""), } class XEP_0092(object): def __init__(self, host): log.info(_("Plugin XEP_0092 initialization")) self.host = host host.bridge.add_method( "software_version_get", ".plugin", in_sign="ss", out_sign="(sss)", method=self._get_version, async_=True, ) try: self.host.plugins[C.TEXT_CMDS].add_who_is_cb(self._whois, 50) except KeyError: log.info(_("Text commands not available")) def _get_version(self, entity_jid_s, profile_key): def prepare_for_bridge(data): name, version, os = data return (name or "", version or "", os or "") client = self.host.get_client(profile_key) d = self.version_get(client, jid.JID(entity_jid_s)) d.addCallback(prepare_for_bridge) return d def version_get( self, client: SatXMPPEntity, jid_: jid.JID, ) -> Tuple[str, str, str]: """Ask version of the client that jid_ is running @param jid_: jid from who we want to know client's version @return: a defered which fire a tuple with the following data (None if not available): - name: Natural language name of the software - version: specific version of the software - os: operating system of the queried entity """ def do_version_get(__): iq_elt = compat.IQ(client.xmlstream, "get") iq_elt["to"] = jid_.full() iq_elt.addElement("query", NS_VERSION) d = iq_elt.send() d.addCallback(self._got_version) return d d = self.host.check_feature(client, NS_VERSION, jid_) d.addCallback(do_version_get) reactor.callLater( TIMEOUT, d.cancel ) # XXX: timeout needed because some clients don't answer the IQ return d def _got_version(self, iq_elt): try: query_elt = next(iq_elt.elements(NS_VERSION, "query")) except StopIteration: raise exceptions.DataError ret = [] for name in ("name", "version", "os"): try: data_elt = next(query_elt.elements(NS_VERSION, name)) ret.append(str(data_elt)) except StopIteration: ret.append(None) return tuple(ret) def _whois(self, client, whois_msg, mess_data, target_jid): """Add software/OS information to whois""" def version_cb(version_data): name, version, os = version_data if name: whois_msg.append(_("Client name: %s") % name) if version: whois_msg.append(_("Client version: %s") % version) if os: whois_msg.append(_("Operating system: %s") % os) def version_eb(failure): failure.trap(exceptions.FeatureNotFound, defer.CancelledError) if failure.check(failure, exceptions.FeatureNotFound): whois_msg.append(_("Software version not available")) else: whois_msg.append(_("Client software version request timeout")) d = self.version_get(client, target_jid) d.addCallbacks(version_cb, version_eb) return d