comparison sat/core/xmpp.py @ 3795:967a8e109cda

core (xmpp): adapt message workflow to components: message workflow were not used for components so far. This patch activate it, normalise namespace to the client one to simplify parsing, and use SatXMPPComponent.sendHistory and SatXMPPComponent.receiveHistory to indicate if a component should store sent and received message in database (they both default to False). OTR plugin is deactivated for components. rel 367
author Goffi <goffi@goffi.org>
date Fri, 17 Jun 2022 14:15:23 +0200
parents efc34a89e70b
children 8289ac1b34f4
comparison
equal deleted inserted replaced
3794:a58715ffa445 3795:967a8e109cda
21 from functools import partial 21 from functools import partial
22 import mimetypes 22 import mimetypes
23 from pathlib import Path 23 from pathlib import Path
24 import sys 24 import sys
25 import time 25 import time
26 from typing import Tuple 26 from typing import Tuple, Optional
27 from urllib.parse import unquote, urlparse 27 from urllib.parse import unquote, urlparse
28 import uuid 28 import uuid
29 29
30 import shortuuid 30 import shortuuid
31 from twisted.internet import defer, error as internet_error 31 from twisted.internet import defer, error as internet_error
970 970
971 trigger_suffix = ( 971 trigger_suffix = (
972 "Component" 972 "Component"
973 ) # used for to distinguish some trigger points set in SatXMPPEntity 973 ) # used for to distinguish some trigger points set in SatXMPPEntity
974 is_component = True 974 is_component = True
975 sendHistory = ( 975 # XXX: set to True from entry plugin to keep messages in history for sent messages
976 False 976 sendHistory = False
977 ) # XXX: set to True from entry plugin to keep messages in history for received 977 # XXX: same as sendHistory but for received messaged
978 # messages 978 receiveHistory = False
979 979
980 def __init__(self, host_app, profile, component_jid, password, host=None, port=None, 980 def __init__(self, host_app, profile, component_jid, password, host=None, port=None,
981 max_retries=C.XMPP_MAX_RETRIES): 981 max_retries=C.XMPP_MAX_RETRIES):
982 self.started = time.time() 982 self.started = time.time()
983 if port is None: 983 if port is None:
1013 return jid.JID(self.jid.host.split(".", 1)[-1]) 1013 return jid.JID(self.jid.host.split(".", 1)[-1])
1014 1014
1015 @property 1015 @property
1016 def is_admin(self) -> bool: 1016 def is_admin(self) -> bool:
1017 return False 1017 return False
1018
1019 def _createSubProtocols(self):
1020 self.messageProt = SatMessageProtocol(self.host_app)
1021 self.messageProt.setHandlerParent(self)
1018 1022
1019 def _buildDependencies(self, current, plugins, required=True): 1023 def _buildDependencies(self, current, plugins, required=True):
1020 """build recursively dependencies needed for a plugin 1024 """build recursively dependencies needed for a plugin
1021 1025
1022 this method build list of plugin needed for a component and raises 1026 this method build list of plugin needed for a component and raises
1149 1153
1150 @property 1154 @property
1151 def client(self): 1155 def client(self):
1152 return self.parent 1156 return self.parent
1153 1157
1158 def normalizeNS(self, elt: domish.Element, namespace: Optional[str]) -> None:
1159 if elt.uri == namespace:
1160 elt.defaultUri = elt.uri = C.NS_CLIENT
1161 for child in elt.elements():
1162 self.normalizeNS(child, namespace)
1163
1154 def parseMessage(self, message_elt): 1164 def parseMessage(self, message_elt):
1155 """Parse a message XML and return message_data 1165 """Parse a message XML and return message_data
1156 1166
1157 @param message_elt(domish.Element): raw <message> xml 1167 @param message_elt(domish.Element): raw <message> xml
1158 @param client(SatXMPPClient, None): client to map message id to uid 1168 @param client(SatXMPPClient, None): client to map message id to uid
1163 log.warning(_( 1173 log.warning(_(
1164 "parseMessage used with a non <message/> stanza, ignoring: {xml}" 1174 "parseMessage used with a non <message/> stanza, ignoring: {xml}"
1165 .format(xml=message_elt.toXml()))) 1175 .format(xml=message_elt.toXml())))
1166 return {} 1176 return {}
1167 1177
1168 if message_elt.uri is None: 1178 if message_elt.uri == None:
1169 # wokkel element parsing strip out root namespace 1179 # xmlns may be None when wokkel element parsing strip out root namespace
1170 message_elt.defaultUri = message_elt.uri = C.NS_CLIENT 1180 self.normalizeNS(message_elt, None)
1171 for c in message_elt.elements():
1172 if c.uri is None:
1173 c.uri = C.NS_CLIENT
1174 elif message_elt.uri != C.NS_CLIENT: 1181 elif message_elt.uri != C.NS_CLIENT:
1175 log.warning(_( 1182 log.warning(_(
1176 "received <message> with a wrong namespace: {xml}" 1183 "received <message> with a wrong namespace: {xml}"
1177 .format(xml=message_elt.toXml()))) 1184 .format(xml=message_elt.toXml())))
1178 1185
1247 if not cont: 1254 if not cont:
1248 return 1255 return
1249 data = self.parseMessage(message_elt) 1256 data = self.parseMessage(message_elt)
1250 post_treat.addCallback(self.completeAttachments) 1257 post_treat.addCallback(self.completeAttachments)
1251 post_treat.addCallback(self.skipEmptyMessage) 1258 post_treat.addCallback(self.skipEmptyMessage)
1252 post_treat.addCallback( 1259 if not client.is_component or client.receiveHistory:
1253 lambda ret: defer.ensureDeferred(self.addToHistory(ret)) 1260 post_treat.addCallback(
1254 ) 1261 lambda ret: defer.ensureDeferred(self.addToHistory(ret))
1255 post_treat.addCallback(self.bridgeSignal, data) 1262 )
1263 if not client.is_component:
1264 post_treat.addCallback(self.bridgeSignal, data)
1256 post_treat.addErrback(self.cancelErrorTrap) 1265 post_treat.addErrback(self.cancelErrorTrap)
1257 post_treat.callback(data) 1266 post_treat.callback(data)
1258 1267
1259 def onMessage(self, message_elt): 1268 def onMessage(self, message_elt):
1260 # TODO: handle threads 1269 # TODO: handle threads
1261 message_elt._received_timestamp = time.time() 1270 message_elt._received_timestamp = time.time()
1262 client = self.parent 1271 client = self.parent
1263 if not "from" in message_elt.attributes: 1272 if not "from" in message_elt.attributes:
1264 message_elt["from"] = client.jid.host 1273 message_elt["from"] = client.jid.host
1265 log.debug(_("got message from: {from_}").format(from_=message_elt["from"])) 1274 log.debug(_("got message from: {from_}").format(from_=message_elt["from"]))
1275 if self.client.is_component and message_elt.uri == component.NS_COMPONENT_ACCEPT:
1276 # we use client namespace all the time to simplify parsing
1277 self.normalizeNS(message_elt, component.NS_COMPONENT_ACCEPT)
1266 1278
1267 # plugin can add their treatments to this deferred 1279 # plugin can add their treatments to this deferred
1268 post_treat = defer.Deferred() 1280 post_treat = defer.Deferred()
1269 1281
1270 d = self.host.trigger.asyncPoint( 1282 d = self.host.trigger.asyncPoint(