comparison sat/plugins/plugin_xep_0033.py @ 2624:56f94936df1e

code style reformatting using black
author Goffi <goffi@goffi.org>
date Wed, 27 Jun 2018 20:14:46 +0200
parents 26edcf3a30eb
children 378188abe941
comparison
equal deleted inserted replaced
2623:49533de4540b 2624:56f94936df1e
18 # along with this program. If not, see <http://www.gnu.org/licenses/>. 18 # along with this program. If not, see <http://www.gnu.org/licenses/>.
19 19
20 from sat.core.i18n import _ 20 from sat.core.i18n import _
21 from sat.core.constants import Const as C 21 from sat.core.constants import Const as C
22 from sat.core.log import getLogger 22 from sat.core.log import getLogger
23
23 log = getLogger(__name__) 24 log = getLogger(__name__)
24 from sat.core import exceptions 25 from sat.core import exceptions
25 from wokkel import disco, iwokkel 26 from wokkel import disco, iwokkel
26 from zope.interface import implements 27 from zope.interface import implements
27 from twisted.words.protocols.jabber.jid import JID 28 from twisted.words.protocols.jabber.jid import JID
28 from twisted.python import failure 29 from twisted.python import failure
29 import copy 30 import copy
31
30 try: 32 try:
31 from twisted.words.protocols.xmlstream import XMPPHandler 33 from twisted.words.protocols.xmlstream import XMPPHandler
32 except ImportError: 34 except ImportError:
33 from wokkel.subprotocols import XMPPHandler 35 from wokkel.subprotocols import XMPPHandler
34 from twisted.words.xish import domish 36 from twisted.words.xish import domish
59 C.PI_TYPE: "XEP", 61 C.PI_TYPE: "XEP",
60 C.PI_PROTOCOLS: ["XEP-0033"], 62 C.PI_PROTOCOLS: ["XEP-0033"],
61 C.PI_DEPENDENCIES: [], 63 C.PI_DEPENDENCIES: [],
62 C.PI_MAIN: "XEP_0033", 64 C.PI_MAIN: "XEP_0033",
63 C.PI_HANDLER: "yes", 65 C.PI_HANDLER: "yes",
64 C.PI_DESCRIPTION: _("""Implementation of Extended Stanza Addressing""") 66 C.PI_DESCRIPTION: _("""Implementation of Extended Stanza Addressing"""),
65 } 67 }
66 68
67 69
68 class XEP_0033(object): 70 class XEP_0033(object):
69 """ 71 """
70 Implementation for XEP 0033 72 Implementation for XEP 0033
71 """ 73 """
74
72 def __init__(self, host): 75 def __init__(self, host):
73 log.info(_("Extended Stanza Addressing plugin initialization")) 76 log.info(_("Extended Stanza Addressing plugin initialization"))
74 self.host = host 77 self.host = host
75 self.internal_data = {} 78 self.internal_data = {}
76 host.trigger.add("sendMessage", self.sendMessageTrigger, trigger.TriggerManager.MIN_PRIORITY) 79 host.trigger.add(
80 "sendMessage", self.sendMessageTrigger, trigger.TriggerManager.MIN_PRIORITY
81 )
77 host.trigger.add("MessageReceived", self.messageReceivedTrigger) 82 host.trigger.add("MessageReceived", self.messageReceivedTrigger)
78 83
79 def sendMessageTrigger(self, client, mess_data, pre_xml_treatments, post_xml_treatments): 84 def sendMessageTrigger(
85 self, client, mess_data, pre_xml_treatments, post_xml_treatments
86 ):
80 """Process the XEP-0033 related data to be sent""" 87 """Process the XEP-0033 related data to be sent"""
81 profile = client.profile 88 profile = client.profile
82 89
83 def treatment(mess_data): 90 def treatment(mess_data):
84 if not 'address' in mess_data['extra']: 91 if not "address" in mess_data["extra"]:
85 return mess_data 92 return mess_data
86 93
87 def discoCallback(entities): 94 def discoCallback(entities):
88 if not entities: 95 if not entities:
89 log.warning(_("XEP-0033 is being used but the server doesn't support it!")) 96 log.warning(
90 raise failure.Failure(exceptions.CancelError(u'Cancelled by XEP-0033')) 97 _("XEP-0033 is being used but the server doesn't support it!")
98 )
99 raise failure.Failure(
100 exceptions.CancelError(u"Cancelled by XEP-0033")
101 )
91 if mess_data["to"] not in entities: 102 if mess_data["to"] not in entities:
92 expected = _(' or ').join([entity.userhost() for entity in entities]) 103 expected = _(" or ").join([entity.userhost() for entity in entities])
93 log.warning(_(u"Stanzas using XEP-0033 should be addressed to %(expected)s, not %(current)s!") % {'expected': expected, 'current': mess_data["to"]}) 104 log.warning(
94 log.warning(_(u"TODO: addressing has been fixed by the backend... fix it in the frontend!")) 105 _(
106 u"Stanzas using XEP-0033 should be addressed to %(expected)s, not %(current)s!"
107 )
108 % {"expected": expected, "current": mess_data["to"]}
109 )
110 log.warning(
111 _(
112 u"TODO: addressing has been fixed by the backend... fix it in the frontend!"
113 )
114 )
95 mess_data["to"] = list(entities)[0].userhostJID() 115 mess_data["to"] = list(entities)[0].userhostJID()
96 element = mess_data['xml'].addElement('addresses', NS_ADDRESS) 116 element = mess_data["xml"].addElement("addresses", NS_ADDRESS)
97 entries = [entry.split(':') for entry in mess_data['extra']['address'].split('\n') if entry != ''] 117 entries = [
118 entry.split(":")
119 for entry in mess_data["extra"]["address"].split("\n")
120 if entry != ""
121 ]
98 for type_, jid_ in entries: 122 for type_, jid_ in entries:
99 element.addChild(domish.Element((None, 'address'), None, {'type': type_, 'jid': jid_})) 123 element.addChild(
124 domish.Element(
125 (None, "address"), None, {"type": type_, "jid": jid_}
126 )
127 )
100 # when the prosody plugin is completed, we can immediately return mess_data from here 128 # when the prosody plugin is completed, we can immediately return mess_data from here
101 self.sendAndStoreMessage(mess_data, entries, profile) 129 self.sendAndStoreMessage(mess_data, entries, profile)
102 log.debug("XEP-0033 took over") 130 log.debug("XEP-0033 took over")
103 raise failure.Failure(exceptions.CancelError(u'Cancelled by XEP-0033')) 131 raise failure.Failure(exceptions.CancelError(u"Cancelled by XEP-0033"))
132
104 d = self.host.findFeaturesSet(client, [NS_ADDRESS]) 133 d = self.host.findFeaturesSet(client, [NS_ADDRESS])
105 d.addCallbacks(discoCallback, lambda dummy: discoCallback(None)) 134 d.addCallbacks(discoCallback, lambda dummy: discoCallback(None))
106 return d 135 return d
107 136
108 post_xml_treatments.addCallback(treatment) 137 post_xml_treatments.addCallback(treatment)
120 - fix Prosody plugin to check if target server support the feature 149 - fix Prosody plugin to check if target server support the feature
121 - redesign the database to save only one entry to the database 150 - redesign the database to save only one entry to the database
122 - change the messageNew signal to eventually pass more than one recipient 151 - change the messageNew signal to eventually pass more than one recipient
123 """ 152 """
124 client = self.host.getClient(profile) 153 client = self.host.getClient(profile)
154
125 def send(mess_data, skip_send=False): 155 def send(mess_data, skip_send=False):
126 d = defer.Deferred() 156 d = defer.Deferred()
127 if not skip_send: 157 if not skip_send:
128 d.addCallback(client.sendMessageData) 158 d.addCallback(client.sendMessageData)
129 d.addCallback(client.messageAddToHistory) 159 d.addCallback(client.messageAddToHistory)
131 d.addErrback(lambda failure: failure.trap(exceptions.CancelError)) 161 d.addErrback(lambda failure: failure.trap(exceptions.CancelError))
132 return d.callback(mess_data) 162 return d.callback(mess_data)
133 163
134 def discoCallback(entities, to_jid_s): 164 def discoCallback(entities, to_jid_s):
135 history_data = copy.deepcopy(mess_data) 165 history_data = copy.deepcopy(mess_data)
136 history_data['to'] = JID(to_jid_s) 166 history_data["to"] = JID(to_jid_s)
137 history_data['xml']['to'] = to_jid_s 167 history_data["xml"]["to"] = to_jid_s
138 if entities: 168 if entities:
139 if entities not in self.internal_data[timestamp]: 169 if entities not in self.internal_data[timestamp]:
140 sent_data = copy.deepcopy(mess_data) 170 sent_data = copy.deepcopy(mess_data)
141 sent_data['to'] = JID(JID(to_jid_s).host) 171 sent_data["to"] = JID(JID(to_jid_s).host)
142 sent_data['xml']['to'] = JID(to_jid_s).host 172 sent_data["xml"]["to"] = JID(to_jid_s).host
143 send(sent_data) 173 send(sent_data)
144 self.internal_data[timestamp].append(entities) 174 self.internal_data[timestamp].append(entities)
145 # we still need to fill the history and signal the echo... 175 # we still need to fill the history and signal the echo...
146 send(history_data, skip_send=True) 176 send(history_data, skip_send=True)
147 else: 177 else:
154 timestamp = time() 184 timestamp = time()
155 self.internal_data[timestamp] = [] 185 self.internal_data[timestamp] = []
156 defer_list = [] 186 defer_list = []
157 for type_, jid_ in entries: 187 for type_, jid_ in entries:
158 d = defer.Deferred() 188 d = defer.Deferred()
159 d.addCallback(self.host.findFeaturesSet, client=client, jid_=JID(JID(jid_).host)) 189 d.addCallback(
160 d.addCallbacks(discoCallback, errback, callbackArgs=[jid_], errbackArgs=[jid_]) 190 self.host.findFeaturesSet, client=client, jid_=JID(JID(jid_).host)
191 )
192 d.addCallbacks(
193 discoCallback, errback, callbackArgs=[jid_], errbackArgs=[jid_]
194 )
161 d.callback([NS_ADDRESS]) 195 d.callback([NS_ADDRESS])
162 defer_list.append(d) 196 defer_list.append(d)
163 d = defer.Deferred().addCallback(lambda dummy: self.internal_data.pop(timestamp)) 197 d = defer.Deferred().addCallback(lambda dummy: self.internal_data.pop(timestamp))
164 defer.DeferredList(defer_list).chainDeferred(d) 198 defer.DeferredList(defer_list).chainDeferred(d)
165 199
166 def messageReceivedTrigger(self, client, message, post_treat): 200 def messageReceivedTrigger(self, client, message, post_treat):
167 """In order to save the addressing information in the history""" 201 """In order to save the addressing information in the history"""
202
168 def post_treat_addr(data, addresses): 203 def post_treat_addr(data, addresses):
169 data['extra']['addresses'] = "" 204 data["extra"]["addresses"] = ""
170 for address in addresses: 205 for address in addresses:
171 # Depending how message has been constructed, we could get here 206 # Depending how message has been constructed, we could get here
172 # some noise like "\n " instead of an address element. 207 # some noise like "\n " instead of an address element.
173 if isinstance(address, domish.Element): 208 if isinstance(address, domish.Element):
174 data['extra']['addresses'] += '%s:%s\n' % (address['type'], address['jid']) 209 data["extra"]["addresses"] += "%s:%s\n" % (
210 address["type"],
211 address["jid"],
212 )
175 return data 213 return data
176 214
177 try: 215 try:
178 addresses = message.elements(NS_ADDRESS, 'addresses').next() 216 addresses = message.elements(NS_ADDRESS, "addresses").next()
179 except StopIteration: 217 except StopIteration:
180 pass # no addresses 218 pass # no addresses
181 else: 219 else:
182 post_treat.addCallback(post_treat_addr, addresses.children) 220 post_treat.addCallback(post_treat_addr, addresses.children)
183 return True 221 return True
192 def __init__(self, plugin_parent, profile): 230 def __init__(self, plugin_parent, profile):
193 self.plugin_parent = plugin_parent 231 self.plugin_parent = plugin_parent
194 self.host = plugin_parent.host 232 self.host = plugin_parent.host
195 self.profile = profile 233 self.profile = profile
196 234
197 def getDiscoInfo(self, requestor, target, nodeIdentifier=''): 235 def getDiscoInfo(self, requestor, target, nodeIdentifier=""):
198 return [disco.DiscoFeature(NS_ADDRESS)] 236 return [disco.DiscoFeature(NS_ADDRESS)]
199 237
200 def getDiscoItems(self, requestor, target, nodeIdentifier=''): 238 def getDiscoItems(self, requestor, target, nodeIdentifier=""):
201 return [] 239 return []