plugin XEP-0424: fix ID used and recipients
This commit is contained in:
parent
817d7b6daf
commit
b571b0d6e2
1 changed files with 59 additions and 53 deletions
|
|
@ -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)]
|
||||
|
||||
|
|
|
|||
Loading…
Reference in a new issue