8000 Added DeliveryMode bufferedReplies · guptarohan41/botbuilder-python@6ba3cf5 · GitHub
[go: up one dir, main page]

Skip to content

Commit 6ba3cf5

Browse files
committed
Added DeliveryMode bufferedReplies
1 parent 5ed1497 commit 6ba3cf5

File tree

4 files changed

+119
-7
lines changed

4 files changed

+119
-7
lines changed

libraries/botbuilder-core/botbuilder/core/bot_framework_adapter.py

Lines changed: 3 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -39,6 +39,7 @@
3939
ConversationReference,
4040
TokenResponse,
4141
ResourceResponse,
42+
DeliveryModes,
4243
)
4344

4445
from . import __version__
@@ -455,6 +456,8 @@ async def process_activity_with_identity(
455456
if invoke_response is None:
456457
return InvokeResponse(status=501)
457458
return invoke_response.value
459+
if context.activity.delivery_mode == DeliveryModes.buffered_replies:
460+
return InvokeResponse(status=200, body=context.buffered_replies)
458461

459462
return None
460463

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

Lines changed: 18 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -12,6 +12,7 @@
1212
InputHints,
1313
Mention,
1414
ResourceResponse,
15+
DeliveryModes,
1516
)
1617
from .re_escape import escape
1718

@@ -50,6 +51,9 @@ def __init__(self, adapter_or_context, request: Activity = None):
5051

5152
self._turn_state = {}
5253

54+
# A list of activities to send when `context.Activity.DeliveryMode == 'bufferedReplies'`
55+
self.bu 8000 ffered_replies = []
56+
5357
@property
5458
def turn_state(self) -> Dict[str, object]:
5559
return self._turn_state
@@ -190,7 +194,21 @@ def activity_validator(activity: Activity) -> Activity:
190194
for act in activities
191195
]
192196

197+
# send activities through adapter
193198
async def logic():
199+
nonlocal sent_non_trace_activity
200+
201+
if self.activity.delivery_mode == DeliveryModes.buffered_replies:
202+
responses = []
203+
for activity in output:
204+
self.buffered_replies.append(activity)
205+
responses.append(ResourceResponse())
206+
207+
if sent_non_trace_activity:
208+
self.responded = True
209+
210+
return responses
211+
194212
responses = await self.adapter.send_activities(self, output)
195213
if sent_non_trace_activity:
196214
self.responded = True

libraries/botbuilder-core/tests/test_bot_framework_adapter.py

Lines changed: 97 additions & 7 deletions
Original file line numberDiff line numberDiff line change
@@ -19,6 +19,7 @@
1919
ConversationReference,
2020
ConversationResourceResponse,
2121
ChannelAccount,
22+
DeliveryModes,
2223
)
2324
from botframework.connector.aio import ConnectorClient
2425
from botframework.connector.auth import (
@@ -58,6 +59,7 @@ def __init__(self, settings=None):
5859
self.fail_operation = False
5960
self.expect_auth_header = ""
6061
self.new_service_url = None
62+
self.connector_client_mock = None
6163

6264
def aux_test_authenticate_request(self, request: Activity, auth_header: str):
6365
return super()._authenticate_request(request, auth_header)
@@ -102,7 +104,10 @@ def _get_or_create_connector_client(
102104
self.tester.assertIsNotNone(
103105
service_url, "create_connector_client() not passed service_url."
104106
)
105-
connector_client_mock = Mock()
107+
108+
if self.connector_client_mock:
109+
return self.connector_client_mock
110+
self.connector_client_mock = Mock()
106111

107112
async def mock_reply_to_activity(conversation_id, activity_id, activity):
108113
nonlocal self
@@ -160,23 +165,23 @@ async def mock_create_conversation(parameters):
160165
)
161166
return response
162167

163-
connector_client_mock.conversations.reply_to_activity.side_effect = (
168+
self.connector_client_mock.conversations.reply_to_activity.side_effect = (
164169
mock_reply_to_activity
165170
)
166-
connector_client_mock.conversations.send_to_conversation.side_effect = (
171+
self.connector_client_mock.conversations.send_to_conversation.side_effect = (
167172
mock_send_to_conversation
168173
)
169-
connector_client_mock.conversations.update_activity.side_effect = (
174+
self.connector_client_mock.conversations.update_activity.side_effect = (
170175
mock_update_activity
171176
)
172-
connector_client_mock.conversations.delete_activity.side_effect = (
177+
self.connector_client_mock.conversations.delete_activity.side_effect = (
173178
mock_delete_activity
174179
)
175-
connector_client_mock.conversations.create_conversation.side_effect = (
180+
self.connector_client_mock.conversations.create_conversation.side_effect = (
176181
mock_create_conversation
177182
)
178183

179-
return connector_client_mock
184+
return self.connector_client_mock
180185

181186

182187
async def process_activity(
@@ -572,3 +577,88 @@ async def callback(context: TurnContext):
572577
await adapter.continue_conversation(
573578
refs, callback, claims_identity=skills_identity, audience=skill_2_app_id
574579
)
580+
581+
async def test_delivery_mode_buffered_replies(self):
582+
mock_credential_provider = unittest.mock.create_autospec(CredentialProvider)
583+
584+
settings = BotFrameworkAdapterSettings(
585+
app_id="bot_id", credential_provider=mock_credential_provider
586+
)
587+
adapter = AdapterUnderTest(settings)
588+
589+
async def callback(context: TurnContext):
590+
await context.send_activity("activity 1")
591+
await context.send_activity("activity 2")
592+
await context.send_activity("activity 3")
593+
594+
inbound_activity = Activity(
595+
type=ActivityTypes.message,
596+
channel_id="emulator",
597+
service_url="http://tempuri.org/whatever",
598+
delivery_mode=DeliveryModes.buffered_replies,
599+
text="hello world",
600+
)
601+
602+
identity = ClaimsIdentity(
603+
claims={
604+
AuthenticationConstants.AUDIENCE_CLAIM: "bot_id",
605+
AuthenticationConstants.APP_ID_CLAIM: "bot_id",
606+
AuthenticationConstants.VERSION_CLAIM: "1.0",
607+
},
608+
is_authenticated=True,
609+
)
610+
611+
invoke_response = await adapter.process_activity_with_identity(
612+
inbound_activity, identity, callback
613+
)
614+
assert invoke_response
615+
assert invoke_response.status == 200
616+
activities = invoke_response.body
617+
assert len(activities) == 3
618+
assert activities[0].text == "activity 1"
619+
assert activities[1].text == "activity 2"
620+
assert activities[2].text == "activity 3"
621+
assert (
622+
adapter.connector_client_mock.conversations.send_to_conversation.call_count
623+
== 0
624+
)
625+
626+
async def test_delivery_mode_normal(self):
627+
mock_credential_provider = unittest.mock.create_autospec(CredentialProvider)
628+
629+
settings = BotFrameworkAdapterSettings(
630+
app_id="bot_id", credential_provider=mock_credential_provider
631+
)
632+
adapter = AdapterUnderTest(settings)
633+
634+
async def callback(context: TurnContext):
635+
await context.send_activity("activity 1")
636+
await context.send_activity("activity 2")
637+
await context.send_activity("activity 3")
638+
639+
inbound_activity = Activity(
640+
type=ActivityTypes.message,
641+
channel_id="emulator",
642+
service_url="http://tempuri.org/whatever",
643+
delivery_mode=DeliveryModes.normal,
644+
text="hello world",
645+
conversation=ConversationAccount(id="conversationId"),
646+
)
647+
648+
identity = ClaimsIdentity(
649+
claims={
650+
AuthenticationConstants.AUDIENCE_CLAIM: "bot_id",
651+
AuthenticationConstants.APP_ID_CLAIM: "bot_id",
652+
AuthenticationConstants.VERSION_CLAIM: "1.0",
653+
},
654+
is_authenticated=True,
655+
)
656+
657+
invoke_response = await adapter.process_activity_with_identity(
658+
inbound_activity, identity, callback
659+
)
660+
assert not invoke_response
661+
assert (
662+
adapter.connector_client_mock.conversations.send_to_conversation.call_count
663+
== 3
664+
)

libraries/botbuilder-schema/botbuilder/schema/_connector_client_enums.py

Lines changed: 1 addition & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -99,6 +99,7 @@ class DeliveryModes(str, Enum):
9999

100100
normal = "normal"
101101
notification = "notification"
102+
buffered_replies = "bufferedReplies"
102103

103104

104105
class ContactRelationUpdateActionTypes(str, Enum):

0 commit comments

Comments
 (0)
0