Skip to content
This repository was archived by the owner on Jan 5, 2026. It is now read-only.

Commit 76176da

Browse files
authored
Mentions support in TurnContext (#291)
* Mention support and get_reply_conversation_reference added to TurnContext
1 parent 8ce8c17 commit 76176da

File tree

2 files changed

+81
-2
lines changed

2 files changed

+81
-2
lines changed

libraries/botbuilder-core/botbuilder/core/turn_context.py

Lines changed: 43 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -1,9 +1,10 @@
11
# Copyright (c) Microsoft Corporation. All rights reserved.
22
# Licensed under the MIT License.
33

4+
import re
45
from copy import copy
56
from typing import List, Callable, Union, Dict
6-
from botbuilder.schema import Activity, ConversationReference, ResourceResponse
7+
from botbuilder.schema import Activity, ConversationReference, Mention, ResourceResponse
78

89

910
class TurnContext:
@@ -290,3 +291,44 @@ def apply_conversation_reference(
290291
activity.reply_to_id = reference.activity_id
291292

292293
return activity
294+
295+
@staticmethod
296+
def get_reply_conversation_reference(
297+
activity: Activity, reply: ResourceResponse
298+
) -> ConversationReference:
299+
reference: ConversationReference = TurnContext.get_conversation_reference(
300+
activity
301+
)
302+
303+
# Update the reference with the new outgoing Activity's id.
304+
reference.activity_id = reply.id
305+
306+
return reference
307+
308+
@staticmethod
309+
def remove_recipient_mention(activity: Activity) -> str:
310+
return TurnContext.remove_mention_text(activity, activity.recipient.id)
311+
312+
@staticmethod
313+
def remove_mention_text(activity: Activity, identifier: str) -> str:
314+
mentions = TurnContext.get_mentions(activity)
315+
for mention in mentions:
316+
if mention.mentioned.id == identifier:
317+
mention_name_match = re.match(
318+
r"<at(.*)>(.*?)<\/at>", mention.text, re.IGNORECASE
319+
)
320+
if mention_name_match:
321+
activity.text = re.sub(
322+
mention_name_match.groups()[1], "", activity.text
323+
)
324+
activity.text = re.sub(r"<at><\/at>", "", activity.text)
325+
return activity.text
326+
327+
@staticmethod
328+
def get_mentions(activity: Activity) -> List[Mention]:
329+
result: List[Mention] = []
330+
if activity.entities is not None:
331+
for entity in activity.entities:
332+
if entity.type.lower() == "mention":
333+
result.append(entity)
334+
return result

libraries/botbuilder-core/tests/test_turn_context.py

Lines changed: 38 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -6,8 +6,9 @@
66
from botbuilder.schema import (
77
Activity,
88
ChannelAccount,
9-
ResourceResponse,
109
ConversationAccount,
10+
Mention,
11+
ResourceResponse,
1112
)
1213
from botbuilder.core import BotAdapter, TurnContext
1314

@@ -261,3 +262,39 @@ def test_apply_conversation_reference_when_is_incoming_is_true_should_not_prepar
261262
assert reply.conversation == ACTIVITY.conversation
262263
assert reply.service_url == ACTIVITY.service_url
263264
assert reply.channel_id == ACTIVITY.channel_id
265+
266+
async def test_should_get_conversation_reference_using_get_reply_conversation_reference(
267+
self
268+
):
269+
context = TurnContext(SimpleAdapter(), ACTIVITY)
270+
reply = await context.send_activity("test")
271+
272+
assert reply.id, "reply has an id"
273+
274+
reference = TurnContext.get_reply_conversation_reference(
275+
context.activity, reply
276+
)
277+
278+
assert reference.activity_id, "reference has an activity id"
279+
assert (
280+
reference.activity_id == reply.id
281+
), "reference id matches outgoing reply id"
282+
283+
def test_should_remove_at_mention_from_activity(self):
284+
activity = Activity(
285+
type="message",
286+
text="<at>TestOAuth619</at> test activity",
287+
recipient=ChannelAccount(id="TestOAuth619"),
288+
entities=[
289+
Mention(
290+
type="mention",
291+
text="<at>TestOAuth619</at>",
292+
mentioned=ChannelAccount(name="Bot", id="TestOAuth619"),
293+
)
294+
],
295+
)
296+
297+
text = TurnContext.remove_recipient_mention(activity)
298+
299+
assert text, " test activity"
300+
assert activity.text, " test activity"

0 commit comments

Comments
 (0)