plugin XEP-0424: fix ID used and recipients

This commit is contained in:
Goffi 2023-12-13 22:00:25 +01:00
commit b571b0d6e2

View file

@ -43,6 +43,7 @@ PLUGIN_INFO = {
C.PI_MODES: C.PLUG_MODE_BOTH,
C.PI_PROTOCOLS: ["XEP-0424"],
C.PI_DEPENDENCIES: ["XEP-0334", "XEP-0428"],
C.PI_RECOMMENDATIONS: ["XEP-0045"],
C.PI_MAIN: "XEP_0424",
C.PI_HANDLER: "yes",
C.PI_DESCRIPTION: _("""Implementation Message Retraction"""),
@ -67,12 +68,12 @@ PARAMS = """
class XEP_0424:
def __init__(self, host):
log.info(f"plugin {PLUGIN_INFO[C.PI_NAME]!r} initialization")
self.host = host
host.memory.update_params(PARAMS)
self._h = host.plugins["XEP-0334"]
self._m = host.plugins.get("XEP-0045")
host.register_namespace("message-retract", NS_MESSAGE_RETRACT)
host.trigger.add("message_received", self._message_received_trigger, 100)
host.bridge.add_method(
@ -89,66 +90,65 @@ class XEP_0424:
def _retract(self, message_id: str, profile: str) -> None:
client = self.host.get_client(profile)
return defer.ensureDeferred(
self.retract(client, message_id)
)
return defer.ensureDeferred(self.retract(client, message_id))
def retract_by_origin_id(
self,
client: SatXMPPEntity,
peer_jid: jid.JID,
origin_id: str
def send_retract(
self, client: SatXMPPEntity, peer_jid: jid.JID, retract_id: str, history: History
) -> None:
"""Send a message retraction using origin-id
[retract] should be prefered: internal ID should be used as it is independant of
XEPs changes. However, in some case messages may not be stored in database
(notably for some components), and then this method can be used
@param origin_id: origin-id as specified in XEP-0359
@param retract_id: ID (origin or stanza according to XEP-0359) of message to
retract
@param history: history instance of the message to retract
"""
message_elt = domish.Element((None, "message"))
message_elt["from"] = client.jid.full()
message_elt["to"] = peer_jid.full()
message_elt["type"] = history.type
retract_elt = message_elt.addElement((NS_MESSAGE_RETRACT, "retract"))
retract_elt["id"] = origin_id
retract_elt["id"] = retract_id
self.host.plugins["XEP-0428"].add_fallback_elt(
message_elt,
"[A message retraction has been requested, but your client doesn't support "
"it]"
"it]",
)
self._h.add_hint_elements(message_elt, [self._h.HINT_STORE])
client.send(message_elt)
async def retract_by_history(
self,
client: SatXMPPEntity,
history: History
) -> None:
async def retract_by_history(self, client: SatXMPPEntity, history: History) -> None:
"""Send a message retraction using History instance
This method is to use instead of [retract] when the history instance is already
retrieved. Note that the instance must have messages and subjets loaded
@param history: history instance of the message to retract
"""
try:
origin_id = history.origin_id
except KeyError:
raise exceptions.FeatureNotFound(
f"message to retract doesn't have the necessary origin-id, the sending "
"client is probably not supporting message retraction."
)
if history.type == C.MESS_TYPE_GROUPCHAT:
is_group_chat = True
peer_jid = jid.JID(history.source)
retract_id = history.stanza_id
else:
if history.type == C.MESS_TYPE_GROUPCHAT:
is_group_chat = True
is_group_chat = False
peer_jid = jid.JID(history.dest)
if self._m is not None and self._m.is_joined_room(client, peer_jid):
# it's actually a private MUC message, we need the full JID.
peer_jid = history.dest_jid
else:
is_group_chat = False
peer_jid = jid.JID(history.dest)
self.retract_by_origin_id(client, peer_jid, origin_id)
if not is_group_chat:
# retraction will happen when <retract> message will be received in the
# chat.
await self.retract_db_history(client, history)
retract_id = history.origin_id
if not retract_id:
raise exceptions.FeatureNotFound(
"Message to retract doesn't have the necessary ID, the sending client is "
"probably not supporting message retraction."
)
self.send_retract(client, peer_jid, retract_id, history)
if not is_group_chat:
# retraction will happen when <retract> message will be received in the
# chat.
await self.retract_db_history(client, history)
async def retract(
self,
@ -165,8 +165,11 @@ class XEP_0424:
if not message_id:
raise ValueError("message_id can't be empty")
history = await self.host.memory.storage.get(
client, History, History.uid, message_id,
joined_loads=[History.messages, History.subjects, History.thread]
client,
History,
History.uid,
message_id,
joined_loads=[History.messages, History.subjects, History.thread],
)
if history is None:
raise exceptions.NotFound(
@ -186,14 +189,14 @@ class XEP_0424:
keep_history = await self.host.memory.param_get_a_async(
NAME, CATEGORY, profile_key=client.profile
)
old_version: Dict[str, Any] = {
"timestamp": time.time()
}
old_version: Dict[str, Any] = {"timestamp": time.time()}
if keep_history:
old_version.update({
"messages": [m.serialise() for m in history.messages],
"subjects": [s.serialise() for s in history.subjects],
})
old_version.update(
{
"messages": [m.serialise() for m in history.messages],
"subjects": [s.serialise() for s in history.subjects],
}
)
history.extra.setdefault("old_versions", []).append(old_version)
@ -219,7 +222,7 @@ class XEP_0424:
self,
client: SatXMPPEntity,
message_elt: domish.Element,
post_treat: defer.Deferred
post_treat: defer.Deferred,
) -> bool:
retract_elt = next(message_elt.elements(NS_MESSAGE_RETRACT, "retract"), None)
if not retract_elt:
@ -230,17 +233,23 @@ class XEP_0424:
else:
col_id = History.origin_id
history = await self.host.memory.storage.get(
client, History, col_id, retract_elt["id"],
joined_loads=[History.messages, History.subjects, History.thread]
client,
History,
col_id,
retract_elt["id"],
joined_loads=[History.messages, History.subjects, History.thread],
)
except KeyError:
log.warning(f"invalid retract element, missing id: {retract_elt.toXml()}")
return False
from_jid = jid.JID(message_elt["from"])
if (
history is not None
and history.source_jid.userhostJID() != from_jid.userhostJID()
if history is not None and (
(history.type == C.MESS_TYPE_GROUPCHAT and history.source_jid != from_jid)
or (
history.type != C.MESS_TYPE_GROUPCHAT
and history.source_jid.userhostJID() != from_jid.userhostJID()
)
):
log.warning(
f"Received message retraction from {from_jid.full()}, but the message to "
@ -257,9 +266,7 @@ class XEP_0424:
if history is None:
# we check history after the trigger because we may be in a component which
# doesn't store messages in database.
log.warning(
f"No message found with given origin-id: {message_elt.toXml()}"
)
log.warning(f"No message found with given id: {message_elt.toXml()}")
return False
log.info(f"[{client.profile}] retracting message {history.uid!r}")
await self.retract_db_history(client, history)
@ -268,7 +275,6 @@ class XEP_0424:
@implementer(disco.IDisco)
class XEP_0424_handler(xmlstream.XMPPHandler):
def getDiscoInfo(self, __, target, nodeIdentifier=""):
return [disco.DiscoFeature(NS_MESSAGE_RETRACT)]