async def post_activity( self, from_bot_id: str, to_bot_id: str, to_url: str, service_url: str, conversation_id: str, activity: Activity, ) -> InvokeResponse: app_credentials = await self._get_app_credentials( from_bot_id, to_bot_id) if not app_credentials: raise KeyError( "Unable to get appCredentials to connect to the skill") # Get token for the skill call token = (app_credentials.get_access_token() if app_credentials.microsoft_app_id else None) # Capture current activity settings before changing them. # TODO: DO we need to set the activity ID? (events that are created manually don't have it). original_conversation_id = activity.conversation.id original_service_url = activity.service_url original_caller_id = activity.caller_id try: activity.conversation.id = conversation_id activity.service_url = service_url activity.caller_id = from_bot_id headers_dict = { "Content-type": "application/json; charset=utf-8", } if token: headers_dict.update({ "Authorization": f"Bearer {token}", }) json_content = json.dumps(activity.serialize()) resp = await self._session.post( to_url, data=json_content.encode("utf-8"), headers=headers_dict, ) resp.raise_for_status() data = (await resp.read()).decode() content = json.loads(data) if data else None if content: return InvokeResponse(status=resp.status, body=content) finally: # Restore activity properties. activity.conversation.id = original_conversation_id activity.service_url = original_service_url activity.caller_id = original_caller_id
async def post_activity( self, from_bot_id: str, to_bot_id: str, to_url: str, service_url: str, conversation_id: str, activity: Activity, ) -> InvokeResponse: app_credentials = await self._get_app_credentials( from_bot_id, to_bot_id) if not app_credentials: raise KeyError( "Unable to get appCredentials to connect to the skill") # Get token for the skill call token = (app_credentials.get_access_token() if app_credentials.microsoft_app_id else None) # Capture current activity settings before changing them. # TODO: DO we need to set the activity ID? (events that are created manually don't have it). original_conversation_id = activity.conversation.id original_service_url = activity.service_url original_caller_id = activity.caller_id original_relates_to = activity.relates_to try: # TODO: The relato has to be ported to the adapter in the new integration library when # resolving conflicts in merge activity.relates_to = ConversationReference( service_url=activity.service_url, activity_id=activity.id, channel_id=activity.channel_id, conversation=ConversationAccount( id=activity.conversation.id, name=activity.conversation.name, conversation_type=activity.conversation.conversation_type, aad_object_id=activity.conversation.aad_object_id, is_group=activity.conversation.is_group, role=activity.conversation.role, tenant_id=activity.conversation.tenant_id, properties=activity.conversation.properties, ), bot=None, ) activity.conversation.id = conversation_id activity.service_url = service_url activity.caller_id = f"urn:botframework:aadappid:{from_bot_id}" headers_dict = { "Content-type": "application/json; charset=utf-8", } if token: headers_dict.update({ "Authorization": f"Bearer {token}", }) json_content = json.dumps(activity.serialize()) resp = await self._session.post( to_url, data=json_content.encode("utf-8"), headers=headers_dict, ) resp.raise_for_status() data = (await resp.read()).decode() content = json.loads(data) if data else None return InvokeResponse(status=resp.status, body=content) finally: # Restore activity properties. activity.conversation.id = original_conversation_id activity.service_url = original_service_url activity.caller_id = original_caller_id activity.relates_to = original_relates_to
async def process_activity( self, auth_header_or_authenticate_request_result: Union[ str, AuthenticateRequestResult ], activity: Activity, logic: Callable[[TurnContext], Awaitable], ): """ Creates a turn context and runs the middleware pipeline for an incoming activity. :param auth_header: The HTTP authentication header of the request :type auth_header: :class:`typing.Union[typing.str, AuthenticateRequestResult]` :param activity: The incoming activity :type activity: :class:`Activity` :param logic: The logic to execute at the end of the adapter's middleware pipeline. :type logic: :class:`typing.Callable` :return: A task that represents the work queued to execute. .. remarks:: This class processes an activity received by the bots web server. This includes any messages sent from a user and is the method that drives what's often referred to as the bots *reactive messaging* flow. Call this method to reactively send a message to a conversation. If the task completes successfully, then an :class:`InvokeResponse` is returned; otherwise. `null` is returned. """ # Authenticate the inbound request, extracting parameters and create a ConnectorFactory for creating a # Connector for outbound requests. authenticate_request_result = ( await self.bot_framework_authentication.authenticate_request( activity, auth_header_or_authenticate_request_result ) if isinstance(auth_header_or_authenticate_request_result, str) else auth_header_or_authenticate_request_result ) # Set the caller_id on the activity activity.caller_id = authenticate_request_result.caller_id # Create the connector client to use for outbound requests. connector_client = ( await authenticate_request_result.connector_factory.create( activity.service_url, authenticate_request_result.audience ) if authenticate_request_result.connector_factory else None ) if not connector_client: raise Error("Unable to extract ConnectorClient from turn context.") # Create a UserTokenClient instance for the application to use. # (For example, it would be used in a sign-in prompt.) user_token_client = await self.bot_framework_authentication.create_user_token_client( authenticate_request_result.claims_identity ) # Create a turn context and run the pipeline. context = self._create_turn_context( activity, authenticate_request_result.claims_identity, authenticate_request_result.audience, connector_client, user_token_client, logic, authenticate_request_result.connector_factory, ) # Run the pipeline await self.run_pipeline(context, logic) # If there are any results they will have been left on the TurnContext. return self._process_turn_results(context)