Mercurial > libervia-backend
comparison libervia/backend/plugins/plugin_xep_0092.py @ 4071:4b842c1fb686
refactoring: renamed `sat` package to `libervia.backend`
author | Goffi <goffi@goffi.org> |
---|---|
date | Fri, 02 Jun 2023 11:49:51 +0200 |
parents | sat/plugins/plugin_xep_0092.py@e75827204fe0 |
children |
comparison
equal
deleted
inserted
replaced
4070:d10748475025 | 4071:4b842c1fb686 |
---|---|
1 #!/usr/bin/env python3 | |
2 | |
3 | |
4 # SàT plugin for Software Version (XEP-0092) | |
5 # Copyright (C) 2009-2021 Jérôme Poisson (goffi@goffi.org) | |
6 | |
7 # This program is free software: you can redistribute it and/or modify | |
8 # it under the terms of the GNU Affero General Public License as published by | |
9 # the Free Software Foundation, either version 3 of the License, or | |
10 # (at your option) any later version. | |
11 | |
12 # This program is distributed in the hope that it will be useful, | |
13 # but WITHOUT ANY WARRANTY; without even the implied warranty of | |
14 # MERCHANTABILITY or FITNESS FOR A PARTICULAR PURPOSE. See the | |
15 # GNU Affero General Public License for more details. | |
16 | |
17 # You should have received a copy of the GNU Affero General Public License | |
18 # along with this program. If not, see <http://www.gnu.org/licenses/>. | |
19 | |
20 from typing import Tuple | |
21 | |
22 from twisted.internet import defer, reactor | |
23 from twisted.words.protocols.jabber import jid | |
24 from wokkel import compat | |
25 | |
26 from libervia.backend.core import exceptions | |
27 from libervia.backend.core.constants import Const as C | |
28 from libervia.backend.core.core_types import SatXMPPEntity | |
29 from libervia.backend.core.i18n import _ | |
30 from libervia.backend.core.log import getLogger | |
31 | |
32 log = getLogger(__name__) | |
33 | |
34 NS_VERSION = "jabber:iq:version" | |
35 TIMEOUT = 10 | |
36 | |
37 PLUGIN_INFO = { | |
38 C.PI_NAME: "Software Version Plugin", | |
39 C.PI_IMPORT_NAME: "XEP-0092", | |
40 C.PI_TYPE: "XEP", | |
41 C.PI_PROTOCOLS: ["XEP-0092"], | |
42 C.PI_DEPENDENCIES: [], | |
43 C.PI_RECOMMENDATIONS: [C.TEXT_CMDS], | |
44 C.PI_MAIN: "XEP_0092", | |
45 C.PI_HANDLER: "no", # version is already handler in core.xmpp module | |
46 C.PI_DESCRIPTION: _("""Implementation of Software Version"""), | |
47 } | |
48 | |
49 | |
50 class XEP_0092(object): | |
51 def __init__(self, host): | |
52 log.info(_("Plugin XEP_0092 initialization")) | |
53 self.host = host | |
54 host.bridge.add_method( | |
55 "software_version_get", | |
56 ".plugin", | |
57 in_sign="ss", | |
58 out_sign="(sss)", | |
59 method=self._get_version, | |
60 async_=True, | |
61 ) | |
62 try: | |
63 self.host.plugins[C.TEXT_CMDS].add_who_is_cb(self._whois, 50) | |
64 except KeyError: | |
65 log.info(_("Text commands not available")) | |
66 | |
67 def _get_version(self, entity_jid_s, profile_key): | |
68 def prepare_for_bridge(data): | |
69 name, version, os = data | |
70 return (name or "", version or "", os or "") | |
71 | |
72 client = self.host.get_client(profile_key) | |
73 d = self.version_get(client, jid.JID(entity_jid_s)) | |
74 d.addCallback(prepare_for_bridge) | |
75 return d | |
76 | |
77 def version_get( | |
78 self, | |
79 client: SatXMPPEntity, | |
80 jid_: jid.JID, | |
81 ) -> Tuple[str, str, str]: | |
82 """Ask version of the client that jid_ is running | |
83 | |
84 @param jid_: jid from who we want to know client's version | |
85 @return: a defered which fire a tuple with the following data (None if not available): | |
86 - name: Natural language name of the software | |
87 - version: specific version of the software | |
88 - os: operating system of the queried entity | |
89 """ | |
90 | |
91 def do_version_get(__): | |
92 iq_elt = compat.IQ(client.xmlstream, "get") | |
93 iq_elt["to"] = jid_.full() | |
94 iq_elt.addElement("query", NS_VERSION) | |
95 d = iq_elt.send() | |
96 d.addCallback(self._got_version) | |
97 return d | |
98 | |
99 d = self.host.check_feature(client, NS_VERSION, jid_) | |
100 d.addCallback(do_version_get) | |
101 reactor.callLater( | |
102 TIMEOUT, d.cancel | |
103 ) # XXX: timeout needed because some clients don't answer the IQ | |
104 return d | |
105 | |
106 def _got_version(self, iq_elt): | |
107 try: | |
108 query_elt = next(iq_elt.elements(NS_VERSION, "query")) | |
109 except StopIteration: | |
110 raise exceptions.DataError | |
111 ret = [] | |
112 for name in ("name", "version", "os"): | |
113 try: | |
114 data_elt = next(query_elt.elements(NS_VERSION, name)) | |
115 ret.append(str(data_elt)) | |
116 except StopIteration: | |
117 ret.append(None) | |
118 | |
119 return tuple(ret) | |
120 | |
121 def _whois(self, client, whois_msg, mess_data, target_jid): | |
122 """Add software/OS information to whois""" | |
123 | |
124 def version_cb(version_data): | |
125 name, version, os = version_data | |
126 if name: | |
127 whois_msg.append(_("Client name: %s") % name) | |
128 if version: | |
129 whois_msg.append(_("Client version: %s") % version) | |
130 if os: | |
131 whois_msg.append(_("Operating system: %s") % os) | |
132 | |
133 def version_eb(failure): | |
134 failure.trap(exceptions.FeatureNotFound, defer.CancelledError) | |
135 if failure.check(failure, exceptions.FeatureNotFound): | |
136 whois_msg.append(_("Software version not available")) | |
137 else: | |
138 whois_msg.append(_("Client software version request timeout")) | |
139 | |
140 d = self.version_get(client, target_jid) | |
141 d.addCallbacks(version_cb, version_eb) | |
142 return d |