Repository: microsoft/botbuilder-python

Issue:
Remove Mention Support
**Describe the solution you'd like**
Add Remove Mention support as JS and C#.  See ActivityExtensions for a reference of Mention related methods.  To remove mentions from Activity.Text, see ActivityExtensions.RemoveMentionText and ActivityExtensions.RemoveRecipientMention.  Note that in JS it is TurnContext.removeMentionText.

**Describe alternatives you've considered**
None

**Additional context**
I have implemented SkypeMentionNormalizeMiddleware on all platforms to correct Skype mentions.  The user could still make use of this middleware, but would have to manually remove the mention from Activity.Text to have the same functionality as the other platforms.

[enhancement]



Discussion:

Resolving patch:
diff --git a/libraries/botbuilder-core/botbuilder/core/turn_context.py b/libraries/botbuilder-core/botbuilder/core/turn_context.py
--- a/libraries/botbuilder-core/botbuilder/core/turn_context.py
+++ b/libraries/botbuilder-core/botbuilder/core/turn_context.py
@@ -1,9 +1,10 @@
 # Copyright (c) Microsoft Corporation. All rights reserved.
 # Licensed under the MIT License.
 
+import re
 from copy import copy
 from typing import List, Callable, Union, Dict
-from botbuilder.schema import Activity, ConversationReference, ResourceResponse
+from botbuilder.schema import Activity, ConversationReference, Mention, ResourceResponse
 
 
 class TurnContext:
@@ -290,3 +291,44 @@ def apply_conversation_reference(
                 activity.reply_to_id = reference.activity_id
 
         return activity
+
+    @staticmethod
+    def get_reply_conversation_reference(
+        activity: Activity, reply: ResourceResponse
+    ) -> ConversationReference:
+        reference: ConversationReference = TurnContext.get_conversation_reference(
+            activity
+        )
+
+        # Update the reference with the new outgoing Activity's id.
+        reference.activity_id = reply.id
+
+        return reference
+
+    @staticmethod
+    def remove_recipient_mention(activity: Activity) -> str:
+        return TurnContext.remove_mention_text(activity, activity.recipient.id)
+
+    @staticmethod
+    def remove_mention_text(activity: Activity, identifier: str) -> str:
+        mentions = TurnContext.get_mentions(activity)
+        for mention in mentions:
+            if mention.mentioned.id == identifier:
+                mention_name_match = re.match(
+                    r"<at(.*)>(.*?)<\/at>", mention.text, re.IGNORECASE
+                )
+                if mention_name_match:
+                    activity.text = re.sub(
+                        mention_name_match.groups()[1], "", activity.text
+                    )
+                    activity.text = re.sub(r"<at><\/at>", "", activity.text)
+        return activity.text
+
+    @staticmethod
+    def get_mentions(activity: Activity) -> List[Mention]:
+        result: List[Mention] = []
+        if activity.entities is not None:
+            for entity in activity.entities:
+                if entity.type.lower() == "mention":
+                    result.append(entity)
+        return result


Test patch:
diff --git a/libraries/botbuilder-core/tests/test_turn_context.py b/libraries/botbuilder-core/tests/test_turn_context.py
--- a/libraries/botbuilder-core/tests/test_turn_context.py
+++ b/libraries/botbuilder-core/tests/test_turn_context.py
@@ -6,8 +6,9 @@
 from botbuilder.schema import (
     Activity,
     ChannelAccount,
-    ResourceResponse,
     ConversationAccount,
+    Mention,
+    ResourceResponse,
 )
 from botbuilder.core import BotAdapter, TurnContext
 
@@ -261,3 +262,39 @@ def test_apply_conversation_reference_when_is_incoming_is_true_should_not_prepar
         assert reply.conversation == ACTIVITY.conversation
         assert reply.service_url == ACTIVITY.service_url
         assert reply.channel_id == ACTIVITY.channel_id
+
+    async def test_should_get_conversation_reference_using_get_reply_conversation_reference(
+        self
+    ):
+        context = TurnContext(SimpleAdapter(), ACTIVITY)
+        reply = await context.send_activity("test")
+
+        assert reply.id, "reply has an id"
+
+        reference = TurnContext.get_reply_conversation_reference(
+            context.activity, reply
+        )
+
+        assert reference.activity_id, "reference has an activity id"
+        assert (
+            reference.activity_id == reply.id
+        ), "reference id matches outgoing reply id"
+
+    def test_should_remove_at_mention_from_activity(self):
+        activity = Activity(
+            type="message",
+            text="<at>TestOAuth619</at> test activity",
+            recipient=ChannelAccount(id="TestOAuth619"),
+            entities=[
+                Mention(
+                    type="mention",
+                    text="<at>TestOAuth619</at>",
+                    mentioned=ChannelAccount(name="Bot", id="TestOAuth619"),
+                )
+            ],
+        )
+
+        text = TurnContext.remove_recipient_mention(activity)
+
+        assert text, " test activity"
+        assert activity.text, " test activity"