Repository: zulip/zulip

Issue:
message embeds: Fix nonstandard update_message event for message embeds
In `do_update_embedded_data`, we generate a variant `update_message` event, which has not been properly maintained and doesn't actually match the normal format.  I fixed one issue in 00fd9afad5147beb373caf3410ddc34b0c68a83f; but we should figure out how to make this event actually match the format of a normal `update_message` event, and then update the `GET /events` documentation with clear advice on handling it.  

I'd like us to move that event to be more clearly match the format of normal `update_message` events, with perhaps some clear marker for these variant events.

@amanagr @showell I'd be interested in your thoughts on this.


Discussion:
Hello @zulip/server-api members, this issue was labeled with the "area: api" label, so you may want to check it out!

<!-- areaLabelAddition -->
So, If I understand correctly, this event doesn't belong in the edit history but is an `update_message` event. If there are other events like these we can definitely club them and create a new event for them. 

This is also related to a case with topic edits for messages, where only one messages among all those that are moved receives an "EDITED" tag. I remember you telling me mark all of them as "Edited" which I wasn't so sure about. Sorry, this got lost in one of my WIPs.

We can create a "silently_update_message" event which is tracked by frontend too and no "Edited" label appears. 
@zulipbot claim
Hello @MSurfer20, you claimed this issue to work on it, but this issue and any referenced pull requests haven't been updated for 10 days. Are you still working on this issue?

If so, please update this issue by leaving a comment on this issue to let me know that you're still working on it. Otherwise, I'll automatically remove you from this issue in 4 days.

If you've decided to work on something else, simply comment `@zulipbot abandon` so that someone else can claim it and continue from where you left off.

Thank you for your valuable contributions to Zulip!

<!-- inactiveWarning -->
@zulipbot claim
@MSurfer20 this would be a great issue for you to pick up again now that you have more experience.
@zulipbot claim
@MSurfer20 are you still planning to work this?
Hey @shanukun ! I'm still working on this(couldn't get the chance to make a PR due to a busy week; will open one soon)

Resolving patch:
diff --git a/zerver/tornado/event_queue.py b/zerver/tornado/event_queue.py
--- a/zerver/tornado/event_queue.py
+++ b/zerver/tornado/event_queue.py
@@ -1129,50 +1129,62 @@ def process_message_update_event(
     stream_name = event_template.get("stream_name")
     message_id = event_template["message_id"]
 
+    # TODO/compatibility: Modern `update_message` events contain the
+    # rendering_only key, which indicates whether the update is a link
+    # preview rendering update (not a human action). However, because
+    # events may be in the notify_tornado queue at the time we
+    # upgrade, we need the below logic to compute rendering_only based
+    # on the `user_id` key not being present in legacy events that
+    # would have had rendering_only set. Remove this check when one
+    # can no longer directly update from 4.x to main.
+    if "rendering_only" in event_template:
+        rendering_only_update = event_template["rendering_only"]
+    else:
+        rendering_only_update = "user_id" not in event_template
+
     for user_data in users:
         user_profile_id = user_data["id"]
 
-        if "user_id" in event_template:
-            # The user we'll get here will be the sender if the message's
-            # content was edited, and the editor for topic edits. That's
-            # the correct "acting_user" for both cases.
-            acting_user_id = event_template["user_id"]
-        else:
-            # Events without a `user_id` field come from the do_update_embedded_data
-            # code path, and represent just rendering previews; there should be no
-            # real content changes.
-            # It doesn't really matter what we set `acting_user_id` in this case,
-            # because we know this event isn't meant to send notifications.
-            acting_user_id = user_profile_id
-
         user_event = dict(event_template)  # shallow copy, but deep enough for our needs
         for key in user_data.keys():
             if key != "id":
                 user_event[key] = user_data[key]
 
-        flags: Collection[str] = user_event["flags"]
-        user_notifications_data = UserMessageNotificationsData.from_user_id_sets(
-            user_id=user_profile_id,
-            flags=flags,
-            private_message=(stream_name is None),
-            online_push_user_ids=online_push_user_ids,
-            pm_mention_push_disabled_user_ids=pm_mention_push_disabled_user_ids,
-            pm_mention_email_disabled_user_ids=pm_mention_email_disabled_user_ids,
-            stream_push_user_ids=stream_push_user_ids,
-            stream_email_user_ids=stream_email_user_ids,
-            wildcard_mention_user_ids=wildcard_mention_user_ids,
-            muted_sender_user_ids=muted_sender_user_ids,
-            all_bot_user_ids=all_bot_user_ids,
-        )
+        # Events where `rendering_only_update` is True come from the
+        # do_update_embedded_data code path, and represent rendering
+        # previews; there should be no real content changes.
+        # Therefore, we know only events where `rendering_only_update`
+        # is False possibly send notifications.
+        if not rendering_only_update:
 
-        maybe_enqueue_notifications_for_message_update(
-            user_notifications_data=user_notifications_data,
-            message_id=message_id,
-            acting_user_id=acting_user_id,
-            private_message=(stream_name is None),
-            presence_idle=(user_profile_id in presence_idle_user_ids),
-            prior_mentioned=(user_profile_id in prior_mention_user_ids),
-        )
+            # The user we'll get here will be the sender if the message's
+            # content was edited, and the editor for topic edits. That's
+            # the correct "acting_user" for both cases.
+            acting_user_id = event_template["user_id"]
+
+            flags: Collection[str] = user_event["flags"]
+            user_notifications_data = UserMessageNotificationsData.from_user_id_sets(
+                user_id=user_profile_id,
+                flags=flags,
+                private_message=(stream_name is None),
+                online_push_user_ids=online_push_user_ids,
+                pm_mention_push_disabled_user_ids=pm_mention_push_disabled_user_ids,
+                pm_mention_email_disabled_user_ids=pm_mention_email_disabled_user_ids,
+                stream_push_user_ids=stream_push_user_ids,
+                stream_email_user_ids=stream_email_user_ids,
+                wildcard_mention_user_ids=wildcard_mention_user_ids,
+                muted_sender_user_ids=muted_sender_user_ids,
+                all_bot_user_ids=all_bot_user_ids,
+            )
+
+            maybe_enqueue_notifications_for_message_update(
+                user_notifications_data=user_notifications_data,
+                message_id=message_id,
+                acting_user_id=acting_user_id,
+                private_message=(stream_name is None),
+                presence_idle=(user_profile_id in presence_idle_user_ids),
+                prior_mentioned=(user_profile_id in prior_mention_user_ids),
+            )
 
         for client in get_client_descriptors_for_user(user_profile_id):
             if client.accepts_event(user_event):


Test patch: