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):