Repository: zulip/zulip

Issue:
Link to moved message
As [suggested on CZO](https://chat.zulip.org/#narrow/stream/137-feedback/topic/Moving.20message.20link.20to.20message.28s.29.3F/near/1519423), when Notification Bot sends a noitce about a single moved message to the stream that it was moved to, it would be helpful to link to the new location of the message:

> `"[A message](new message URL) was moved here from..."`

(Currently there is no link on "A message".)


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

<!-- areaLabelAddition -->

@zulipbot claim
Hey, can i work on this issue?
@KousikRoy-EC I’m working 
> @KousikRoy-EC I’m working

How to download and run the code? Can you help?


Resolving patch:
diff --git a/zerver/actions/message_edit.py b/zerver/actions/message_edit.py
--- a/zerver/actions/message_edit.py
+++ b/zerver/actions/message_edit.py
@@ -50,6 +50,7 @@
     update_messages_for_topic_edit,
 )
 from zerver.lib.types import EditHistoryEvent
+from zerver.lib.url_encoding import near_stream_message_url
 from zerver.lib.user_message import UserMessageLite, bulk_insert_ums
 from zerver.lib.user_topics import get_users_with_user_topic_visibility_policy
 from zerver.lib.widget import is_widget_message
@@ -187,6 +188,7 @@ def maybe_send_resolve_topic_notifications(
 
 
 def send_message_moved_breadcrumbs(
+    target_message: Message,
     user_profile: UserProfile,
     old_stream: Stream,
     old_topic: str,
@@ -207,6 +209,13 @@ def send_message_moved_breadcrumbs(
     user_mention = silent_mention_syntax_for_user(user_profile)
     old_topic_link = f"#**{old_stream.name}>{old_topic}**"
     new_topic_link = f"#**{new_stream.name}>{new_topic}**"
+    message = {
+        "id": target_message.id,
+        "stream_id": new_stream.id,
+        "display_recipient": new_stream.name,
+        "topic": new_topic,
+    }
+    moved_message_link = near_stream_message_url(target_message.realm, message)
 
     if new_thread_notification_string is not None:
         with override_language(new_stream.realm.default_language):
@@ -215,6 +224,7 @@ def send_message_moved_breadcrumbs(
                 new_stream,
                 new_topic,
                 new_thread_notification_string.format(
+                    message_link=moved_message_link,
                     old_location=old_topic_link,
                     user=user_mention,
                     changed_messages_count=changed_messages_count,
@@ -925,7 +935,7 @@ def user_info(um: UserMessage) -> Dict[str, Any]:
             else:
                 if changed_messages_count == 1:
                     new_thread_notification_string = gettext_lazy(
-                        "A message was moved here from {old_location} by {user}."
+                        "[A message]({message_link}) was moved here from {old_location} by {user}."
                     )
                 else:
                     new_thread_notification_string = gettext_lazy(
@@ -933,6 +943,7 @@ def user_info(um: UserMessage) -> Dict[str, Any]:
                     )
 
         send_message_moved_breadcrumbs(
+            target_message,
             user_profile,
             stream_being_edited,
             orig_topic_name,


Test patch:
diff --git a/zerver/tests/test_message_edit.py b/zerver/tests/test_message_edit.py
--- a/zerver/tests/test_message_edit.py
+++ b/zerver/tests/test_message_edit.py
@@ -21,6 +21,7 @@
 from zerver.lib.test_classes import ZulipTestCase, get_topic_messages
 from zerver.lib.test_helpers import cache_tries_captured, queries_captured
 from zerver.lib.topic import RESOLVED_TOPIC_PREFIX, TOPIC_NAME
+from zerver.lib.url_encoding import near_stream_message_url
 from zerver.lib.user_topics import (
     get_users_with_user_topic_visibility_policy,
     set_topic_visibility_policy,
@@ -2322,11 +2323,18 @@ def test_move_message_to_stream_change_one(self) -> None:
         )
 
         messages = get_topic_messages(user_profile, new_stream, "test")
+        message = {
+            "id": msg_id_later,
+            "stream_id": new_stream.id,
+            "display_recipient": new_stream.name,
+            "topic": "test",
+        }
+        moved_message_link = near_stream_message_url(messages[1].realm, message)
         self.assert_length(messages, 2)
         self.assertEqual(messages[0].id, msg_id_later)
         self.assertEqual(
             messages[1].content,
-            f"A message was moved here from #**test move stream>test** by @_**Iago|{user_profile.id}**.",
+            f"[A message]({moved_message_link}) was moved here from #**test move stream>test** by @_**Iago|{user_profile.id}**.",
         )
 
     def test_move_message_to_preexisting_topic_change_one(self) -> None:
@@ -2360,11 +2368,18 @@ def test_move_message_to_preexisting_topic_change_one(self) -> None:
         )
 
         messages = get_topic_messages(user_profile, new_stream, "test")
+        message = {
+            "id": msg_id_later,
+            "stream_id": new_stream.id,
+            "display_recipient": new_stream.name,
+            "topic": "test",
+        }
+        moved_message_link = near_stream_message_url(messages[2].realm, message)
         self.assert_length(messages, 3)
         self.assertEqual(messages[0].id, msg_id_later)
         self.assertEqual(
             messages[2].content,
-            f"A message was moved here from #**test move stream>test** by @_**Iago|{user_profile.id}**.",
+            f"[A message]({moved_message_link}) was moved here from #**test move stream>test** by @_**Iago|{user_profile.id}**.",
         )
 
     def test_move_message_to_stream_change_all(self) -> None:
@@ -3130,11 +3145,18 @@ def test_notify_new_topics_after_message_move(self) -> None:
         self.assertEqual(messages[1].content, "Third")
 
         messages = get_topic_messages(user_profile, stream, "edited")
+        message = {
+            "id": msg_id,
+            "stream_id": stream.id,
+            "display_recipient": stream.name,
+            "topic": "edited",
+        }
+        moved_message_link = near_stream_message_url(messages[1].realm, message)
         self.assert_length(messages, 2)
         self.assertEqual(messages[0].content, "First")
         self.assertEqual(
             messages[1].content,
-            f"A message was moved here from #**public stream>test** by @_**Iago|{user_profile.id}**.",
+            f"[A message]({moved_message_link}) was moved here from #**public stream>test** by @_**Iago|{user_profile.id}**.",
         )
 
     def test_notify_old_topics_after_message_move(self) -> None:
@@ -3206,11 +3228,18 @@ def test_notify_both_topics_after_message_move(self) -> None:
         )
 
         messages = get_topic_messages(user_profile, stream, "edited")
+        message = {
+            "id": msg_id,
+            "stream_id": stream.id,
+            "display_recipient": stream.name,
+            "topic": "edited",
+        }
+        moved_message_link = near_stream_message_url(messages[0].realm, message)
         self.assert_length(messages, 2)
         self.assertEqual(messages[0].content, "First")
         self.assertEqual(
             messages[1].content,
-            f"A message was moved here from #**public stream>test** by @_**Iago|{user_profile.id}**.",
+            f"[A message]({moved_message_link}) was moved here from #**public stream>test** by @_**Iago|{user_profile.id}**.",
         )
 
     def test_notify_no_topic_after_message_move(self) -> None: