Mercurial > libervia-backend
comparison libervia/backend/plugins/plugin_xep_0045.py @ 4155:453e53dfc50e
plugin XEP-0045: user normal workflow for history + `get_room_user_jid` method:
- workflow is now using the normal messages workflow even for history message: previous
workflow was dedicated to MUC and only adding message to history, resulting in other
plugins being skipped.
- new `get_room_user_jid` helps to retrieve easily the JID currently used in a joined
room.
author | Goffi <goffi@goffi.org> |
---|---|
date | Wed, 22 Nov 2023 15:00:57 +0100 |
parents | d861ad696797 |
children | 6784d07b99c8 |
comparison
equal
deleted
inserted
replaced
4154:85f5e6225aa1 | 4155:453e53dfc50e |
---|---|
173 if stanza_id: | 173 if stanza_id: |
174 data["extra"]["stanza_id"] = stanza_id | 174 data["extra"]["stanza_id"] = stanza_id |
175 | 175 |
176 def message_received_trigger(self, client, message_elt, post_treat): | 176 def message_received_trigger(self, client, message_elt, post_treat): |
177 if message_elt.getAttribute("type") == C.MESS_TYPE_GROUPCHAT: | 177 if message_elt.getAttribute("type") == C.MESS_TYPE_GROUPCHAT: |
178 if message_elt.subject or message_elt.delay: | 178 if message_elt.subject: |
179 return False | 179 return False |
180 from_jid = jid.JID(message_elt['from']) | 180 from_jid = jid.JID(message_elt['from']) |
181 room_jid = from_jid.userhostJID() | 181 room_jid = from_jid.userhostJID() |
182 if room_jid in client._muc_client.joined_rooms: | 182 if room_jid in client._muc_client.joined_rooms: |
183 room = client._muc_client.joined_rooms[room_jid] | 183 room = client._muc_client.joined_rooms[room_jid] |
254 if peer_jid.resource: | 254 if peer_jid.resource: |
255 if not self.is_room(client, peer_jid): | 255 if not self.is_room(client, peer_jid): |
256 return peer_jid.userhostJID() | 256 return peer_jid.userhostJID() |
257 return peer_jid | 257 return peer_jid |
258 | 258 |
259 def get_room_user_jid(self, client: SatXMPPEntity, room_jid: jid.JID) -> jid.JID: | |
260 """Get the nick used in the room | |
261 | |
262 @param room_jid: jid of the room to use | |
263 @return: JID used in room | |
264 | |
265 @raise exceptions.NotFound: this room has not been joined | |
266 @raise exceptions.InternalError: invalid room_jid | |
267 """ | |
268 # FIXME: doesn't check if room is anonymous or not | |
269 # TODO: check if room is (semi)anonymous | |
270 if room_jid.resource: | |
271 raise exceptions.InternalError(f"{room_jid} should not have a ressource.") | |
272 room = self.get_room(client, room_jid) | |
273 return jid.JID(tuple=(room_jid.user, room_jid.host, room.nick)) | |
274 | |
259 def _get_room_joined_args(self, room, profile): | 275 def _get_room_joined_args(self, room, profile): |
260 return [ | 276 return [ |
261 room.roomJID.userhost(), | 277 room.roomJID.userhost(), |
262 XEP_0045._get_occupants(room), | 278 XEP_0045._get_occupants(room), |
263 room.nick, | 279 room.nick, |
1065 try: | 1081 try: |
1066 mam_data = await self._mam.get_archives(client, mam_req, | 1082 mam_data = await self._mam.get_archives(client, mam_req, |
1067 service=room_jid) | 1083 service=room_jid) |
1068 except xmpp_error.StanzaError as e: | 1084 except xmpp_error.StanzaError as e: |
1069 if last_mess and e.condition == 'item-not-found': | 1085 if last_mess and e.condition == 'item-not-found': |
1070 log.info( | 1086 log.warning( |
1071 f"requested item (with id {stanza_id!r}) can't be found in " | 1087 f"requested item (with id {stanza_id!r}) can't be found in " |
1072 f"history of {room_jid}, history has probably been purged on " | 1088 f"history of {room_jid}, history has probably been purged on " |
1073 f"server.") | 1089 f"server.") |
1074 # we get last items like for a new room | 1090 # we get last items like for a new room |
1075 rsm_req = rsm.RSMRequest(max_=50, before='') | 1091 rsm_req = rsm.RSMRequest(max_=50, before='') |
1097 if fwd_message_elt.getAttribute("to"): | 1113 if fwd_message_elt.getAttribute("to"): |
1098 log.warning( | 1114 log.warning( |
1099 'Forwarded message element has a "to" attribute while it is ' | 1115 'Forwarded message element has a "to" attribute while it is ' |
1100 'forbidden by specifications') | 1116 'forbidden by specifications') |
1101 fwd_message_elt["to"] = client.jid.full() | 1117 fwd_message_elt["to"] = client.jid.full() |
1102 try: | 1118 client.messageProt.onMessage(fwd_message_elt) |
1103 mess_data = client.messageProt.parse_message(fwd_message_elt) | |
1104 except Exception as e: | |
1105 log.error( | |
1106 f"Can't parse message, ignoring it: {e}\n" | |
1107 f"{fwd_message_elt.toXml()}" | |
1108 ) | |
1109 continue | |
1110 # we attache parsed message data to element, to avoid parsing | |
1111 # again in _add_to_history | |
1112 fwd_message_elt._mess_data = mess_data | |
1113 # and we inject to MUC workflow | |
1114 client._muc_client._onGroupChat(fwd_message_elt) | 1119 client._muc_client._onGroupChat(fwd_message_elt) |
1115 | 1120 |
1116 if not count: | 1121 if not count: |
1117 log.info(_("No message received while offline in {room_jid}".format( | 1122 log.info(_("No message received while offline in {room_jid}".format( |
1118 room_jid=room_jid))) | 1123 room_jid=room_jid))) |
1350 ## messages ## | 1355 ## messages ## |
1351 | 1356 |
1352 def receivedGroupChat(self, room, user, body): | 1357 def receivedGroupChat(self, room, user, body): |
1353 log.debug('receivedGroupChat: room=%s user=%s body=%s' % (room.roomJID.full(), user, body)) | 1358 log.debug('receivedGroupChat: room=%s user=%s body=%s' % (room.roomJID.full(), user, body)) |
1354 | 1359 |
1355 def _add_to_history(self, __, user, message): | |
1356 try: | |
1357 # message can be already parsed (with MAM), in this case mess_data | |
1358 # it attached to the element | |
1359 mess_data = message.element._mess_data | |
1360 except AttributeError: | |
1361 mess_data = self.client.messageProt.parse_message(message.element) | |
1362 if mess_data['message'] or mess_data['subject']: | |
1363 return defer.ensureDeferred( | |
1364 self.host.memory.add_to_history(self.client, mess_data) | |
1365 ) | |
1366 else: | |
1367 return defer.succeed(None) | |
1368 | |
1369 def _add_to_history_eb(self, failure): | |
1370 failure.trap(exceptions.CancelError) | |
1371 | |
1372 def receivedHistory(self, room, user, message): | |
1373 """Called when history (backlog) message are received | |
1374 | |
1375 we check if message is not already in our history | |
1376 and add it if needed | |
1377 @param room(muc.Room): room instance | |
1378 @param user(muc.User, None): the user that sent the message | |
1379 None if the message come from the room | |
1380 @param message(muc.GroupChat): the parsed message | |
1381 """ | |
1382 if room.state != ROOM_STATE_SELF_PRESENCE: | |
1383 log.warning(_( | |
1384 "received history in unexpected state in room {room} (state: " | |
1385 "{state})").format(room = room.roomJID.userhost(), | |
1386 state = room.state)) | |
1387 if not hasattr(room, "_history_d"): | |
1388 # XXX: this hack is due to buggy behaviour seen in the wild because of the | |
1389 # "mod_delay" prosody module being activated. This module add an | |
1390 # unexpected <delay> elements which break our workflow. | |
1391 log.warning(_("storing the unexpected message anyway, to avoid loss")) | |
1392 # we have to restore URI which are stripped by wokkel parsing | |
1393 for c in message.element.elements(): | |
1394 if c.uri is None: | |
1395 c.uri = C.NS_CLIENT | |
1396 mess_data = self.client.messageProt.parse_message(message.element) | |
1397 message.element._mess_data = mess_data | |
1398 self._add_to_history(None, user, message) | |
1399 if mess_data['message'] or mess_data['subject']: | |
1400 self.host.bridge.message_new( | |
1401 *self.client.message_get_bridge_args(mess_data), | |
1402 profile=self.client.profile | |
1403 ) | |
1404 return | |
1405 room._history_d.addCallback(self._add_to_history, user, message) | |
1406 room._history_d.addErrback(self._add_to_history_eb) | |
1407 | |
1408 ## subject ## | 1360 ## subject ## |
1409 | 1361 |
1410 def groupChatReceived(self, message): | 1362 def groupChatReceived(self, message): |
1411 """ | 1363 """ |
1412 A group chat message has been received from a MUC room. | 1364 A group chat message has been received from a MUC room. |
1425 | 1377 |
1426 if message.subject is not None: | 1378 if message.subject is not None: |
1427 self.receivedSubject(room, user, message.subject) | 1379 self.receivedSubject(room, user, message.subject) |
1428 elif message.delay is None: | 1380 elif message.delay is None: |
1429 self.receivedGroupChat(room, user, message) | 1381 self.receivedGroupChat(room, user, message) |
1430 else: | |
1431 self.receivedHistory(room, user, message) | |
1432 | 1382 |
1433 def subject(self, room, subject): | 1383 def subject(self, room, subject): |
1434 return muc.MUCClientProtocol.subject(self, room, subject) | 1384 return muc.MUCClientProtocol.subject(self, room, subject) |
1435 | 1385 |
1436 def _history_cb(self, __, room): | 1386 def _history_cb(self, __, room): |