Skip to content
Merged
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension

Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
Original file line number Diff line number Diff line change
Expand Up @@ -153,7 +153,7 @@ async def process_activity(
self._conversation_lock.release()

activity.timestamp = activity.timestamp or datetime.utcnow()
await self.run_pipeline(TurnContext(self, activity), logic)
await self.run_pipeline(self.create_turn_context(activity), logic)

async def send_activities(
self, context, activities: List[Activity]
Expand Down Expand Up @@ -227,7 +227,7 @@ async def create_conversation(
members_removed=[],
conversation=ConversationAccount(id=str(uuid.uuid4())),
)
context = TurnContext(self, update)
context = self.create_turn_context(update)
return await callback(context)

async def receive_activity(self, activity):
Expand All @@ -252,7 +252,7 @@ async def receive_activity(self, activity):
request.id = str(self._next_id)

# Create context object and run middleware.
context = TurnContext(self, request)
context = self.create_turn_context(request)
return await self.run_pipeline(context, self.logic)

def get_next_activity(self) -> Activity:
Expand Down Expand Up @@ -534,6 +534,9 @@ async def exchange_token_from_credentials(

return None

def create_turn_context(self, activity: Activity) -> TurnContext:
return TurnContext(self, activity)


class TestFlow:
__test__ = False
Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -4,7 +4,9 @@
from typing import Awaitable, Callable

from botbuilder.schema import Activity, ActivityTypes
from botframework.connector.auth import ClaimsIdentity, SkillValidation

from .bot_adapter import BotAdapter
from .middleware_set import Middleware
from .turn_context import TurnContext

Expand Down Expand Up @@ -82,9 +84,12 @@ async def aux():
def stop_interval():
timer.set_clear_timer()

# if it's a message, start sending typing activities until the
# bot logic is done.
if context.activity.type == ActivityTypes.message:
# Start a timer to periodically send the typing activity
# (bots running as skills should not send typing activity)
if (
context.activity.type == ActivityTypes.message
and not ShowTypingMiddleware._is_skill_bot(context)
):
start_interval(context, self._delay, self._period)

# call the bot logic
Expand All @@ -93,3 +98,10 @@ def stop_interval():
stop_interval()

return result

@staticmethod
def _is_skill_bot(context: TurnContext) -> bool:
claims_identity = context.turn_state.get(BotAdapter.BOT_IDENTITY_KEY)
return isinstance(
claims_identity, ClaimsIdentity
) and SkillValidation.is_skill_claim(claims_identity.claims)
35 changes: 33 additions & 2 deletions libraries/botbuilder-core/tests/test_show_typing_middleware.py
Original file line number Diff line number Diff line change
@@ -1,11 +1,31 @@
# Copyright (c) Microsoft Corporation. All rights reserved.
# Licensed under the MIT License.
import asyncio
from uuid import uuid4
import aiounittest

from botbuilder.core import ShowTypingMiddleware
from botbuilder.core import ShowTypingMiddleware, TurnContext
from botbuilder.core.adapters import TestAdapter
from botbuilder.schema import ActivityTypes
from botbuilder.schema import Activity, ActivityTypes
from botframework.connector.auth import AuthenticationConstants, ClaimsIdentity


class SkillTestAdapter(TestAdapter):
def create_turn_context(self, activity: Activity) -> TurnContext:
turn_context = super().create_turn_context(activity)

claims_identity = ClaimsIdentity(
claims={
AuthenticationConstants.VERSION_CLAIM: "2.0",
AuthenticationConstants.AUDIENCE_CLAIM: str(uuid4()),
AuthenticationConstants.AUTHORIZED_PARTY: str(uuid4()),
},
is_authenticated=True,
)

turn_context.turn_state[self.BOT_IDENTITY_KEY] = claims_identity

return turn_context


class TestShowTypingMiddleware(aiounittest.AsyncTestCase):
Expand Down Expand Up @@ -65,3 +85,14 @@ def assert_is_message(activity, description): # pylint: disable=unused-argument

step1 = await adapter.send("foo")
await step1.assert_reply(assert_is_message)

async def test_not_send_not_send_typing_indicator_when_bot_running_as_skill(self):
async def aux(context):
await asyncio.sleep(1)
await context.send_activity(f"echo:{context.activity.text}")

skill_adapter = SkillTestAdapter(aux)
skill_adapter.use(ShowTypingMiddleware(0.001, 1))

step1 = await skill_adapter.send("foo")
await step1.assert_reply("echo:foo")