We are currently solving the following issue within our repository. Here is the issue text:
--- BEGIN ISSUE ---
[PORT] Updated MicrosoftGovernmentAppCredentials to support Skills in Azure Gov
> Port this change from botbuilder-dotnet/master branch:
https://github.com/microsoft/botbuilder-dotnet/pull/3353

Fixes https://github.com/microsoft/botbuilder-dotnet/issues/3233

Added constructor to MicrosoftGovernmentAppCredentials that takes OAuthScope to support skills in gov.
Updated BotFrameworkHttpClient and BotFrameworkAdapter to pass the OAuthScope to MicrosoftGovernmentAppCredentials
Added SimpleBotToBot functional test for testing.
Added Microsoft.Bot.Framework.Skills.sln to load skills test projects.


# Changed projects
* Microsoft.Bot.Builder
* Microsoft.Bot.Connector
* integration
* Microsoft.Bot.Connector.Tests

[Skills]




--- END ISSUE ---

Below are some code segments, each from a relevant file. One or more of these files may contain bugs.
--- BEGIN FILES ---
Path: `libraries/botframework-connector/botframework/connector/auth/microsoft_government_app_credentials.py`
Content:
```
1 # Copyright (c) Microsoft Corporation. All rights reserved.
2 # Licensed under the MIT License.
3 
4 from botframework.connector.auth import MicrosoftAppCredentials, GovernmentConstants
5 
6 
7 class MicrosoftGovernmentAppCredentials(MicrosoftAppCredentials):
8     """
9     MicrosoftGovernmentAppCredentials auth implementation.
10     """
11 
12     def __init__(
13         self,
14         app_id: str,
15         app_password: str,
16         channel_auth_tenant: str = None,
17         scope: str = GovernmentConstants.TO_CHANNEL_FROM_BOT_OAUTH_SCOPE,
18     ):
19         super().__init__(app_id, app_password, channel_auth_tenant, scope)
20         self.oauth_endpoint = GovernmentConstants.TO_CHANNEL_FROM_BOT_LOGIN_URL
21 
22     @staticmethod
23     def empty():
24         return MicrosoftGovernmentAppCredentials("", "")
25
```

Path: `libraries/botbuilder-integration-aiohttp/botbuilder/integration/aiohttp/bot_framework_http_client.py`
Content:
```
1 # Copyright (c) Microsoft Corporation. All rights reserved.
2 # Licensed under the MIT License.
3 # pylint: disable=no-member
4 
5 import json
6 from typing import Dict
7 from logging import Logger
8 
9 import aiohttp
10 from botbuilder.core import InvokeResponse
11 from botbuilder.core.skills import BotFrameworkClient
12 from botbuilder.schema import (
13     Activity,
14     ExpectedReplies,
15     ConversationReference,
16     ConversationAccount,
17 )
18 from botframework.connector.auth import (
19     ChannelProvider,
20     CredentialProvider,
21     GovernmentConstants,
22     MicrosoftAppCredentials,
23 )
24 
25 
26 class BotFrameworkHttpClient(BotFrameworkClient):
27 
28     """
29     A skill host adapter implements API to forward activity to a skill and
30     implements routing ChannelAPI calls from the Skill up through the bot/adapter.
31     """
32 
33     INVOKE_ACTIVITY_NAME = "SkillEvents.ChannelApiInvoke"
34     _BOT_IDENTITY_KEY = "BotIdentity"
35     _APP_CREDENTIALS_CACHE: Dict[str, MicrosoftAppCredentials] = {}
36 
37     def __init__(
38         self,
39         credential_provider: CredentialProvider,
40         channel_provider: ChannelProvider = None,
41         logger: Logger = None,
42     ):
43         if not credential_provider:
44             raise TypeError("credential_provider can't be None")
45 
46         self._credential_provider = credential_provider
47         self._channel_provider = channel_provider
48         self._logger = logger
49         self._session = aiohttp.ClientSession()
50 
51     async def post_activity(
52         self,
53         from_bot_id: str,
54         to_bot_id: str,
55         to_url: str,
56         service_url: str,
57         conversation_id: str,
58         activity: Activity,
59     ) -> InvokeResponse:
60         app_credentials = await self._get_app_credentials(from_bot_id, to_bot_id)
61 
62         if not app_credentials:
63             raise KeyError("Unable to get appCredentials to connect to the skill")
64 
65         # Get token for the skill call
66         token = (
67             app_credentials.get_access_token()
68             if app_credentials.microsoft_app_id
69             else None
70         )
71 
72         # Capture current activity settings before changing them.
73         # TODO: DO we need to set the activity ID? (events that are created manually don't have it).
74         original_conversation_id = activity.conversation.id
75         original_service_url = activity.service_url
76         original_caller_id = activity.caller_id
77         original_relates_to = activity.relates_to
78 
79         try:
80             # TODO: The relato has to be ported to the adapter in the new integration library when
81             #  resolving conflicts in merge
82             activity.relates_to = ConversationReference(
83                 service_url=activity.service_url,
84                 activity_id=activity.id,
85                 channel_id=activity.channel_id,
86                 conversation=ConversationAccount(
87                     id=activity.conversation.id,
88                     name=activity.conversation.name,
89                     conversation_type=activity.conversation.conversation_type,
90                     aad_object_id=activity.conversation.aad_object_id,
91                     is_group=activity.conversation.is_group,
92                     role=activity.conversation.role,
93                     tenant_id=activity.conversation.tenant_id,
94                     properties=activity.conversation.properties,
95                 ),
96                 bot=None,
97             )
98             activity.conversation.id = conversation_id
99             activity.service_url = service_url
100             activity.caller_id = f"urn:botframework:aadappid:{from_bot_id}"
101 
102             headers_dict = {
103                 "Content-type": "application/json; charset=utf-8",
104             }
105             if token:
106                 headers_dict.update(
107                     {"Authorization": f"Bearer {token}",}
108                 )
109 
110             json_content = json.dumps(activity.serialize())
111             resp = await self._session.post(
112                 to_url, data=json_content.encode("utf-8"), headers=headers_dict,
113             )
114             resp.raise_for_status()
115             data = (await resp.read()).decode()
116             content = json.loads(data) if data else None
117 
118             return InvokeResponse(status=resp.status, body=content)
119 
120         finally:
121             # Restore activity properties.
122             activity.conversation.id = original_conversation_id
123             activity.service_url = original_service_url
124             activity.caller_id = original_caller_id
125             activity.relates_to = original_relates_to
126 
127     async def post_buffered_activity(
128         self,
129         from_bot_id: str,
130         to_bot_id: str,
131         to_url: str,
132         service_url: str,
133         conversation_id: str,
134         activity: Activity,
135     ) -> [Activity]:
136         """
137         Helper method to return a list of activities when an Activity is being
138         sent with DeliveryMode == expectReplies.
139         """
140         response = await self.post_activity(
141             from_bot_id, to_bot_id, to_url, service_url, conversation_id, activity
142         )
143         if not response or (response.status / 100) != 2:
144             return []
145         return ExpectedReplies().deserialize(response.body).activities
146 
147     async def _get_app_credentials(
148         self, app_id: str, oauth_scope: str
149     ) -> MicrosoftAppCredentials:
150         if not app_id:
151             return MicrosoftAppCredentials(None, None)
152 
153         cache_key = f"{app_id}{oauth_scope}"
154         app_credentials = BotFrameworkHttpClient._APP_CREDENTIALS_CACHE.get(cache_key)
155 
156         if app_credentials:
157             return app_credentials
158 
159         app_password = await self._credential_provider.get_app_password(app_id)
160         app_credentials = MicrosoftAppCredentials(
161             app_id, app_password, oauth_scope=oauth_scope
162         )
163         if self._channel_provider and self._channel_provider.is_government():
164             app_credentials.oauth_endpoint = (
165                 GovernmentConstants.TO_CHANNEL_FROM_BOT_LOGIN_URL
166             )
167             app_credentials.oauth_scope = (
168                 GovernmentConstants.TO_CHANNEL_FROM_BOT_OAUTH_SCOPE
169             )
170 
171         BotFrameworkHttpClient._APP_CREDENTIALS_CACHE[cache_key] = app_credentials
172         return app_credentials
173
```
--- END FILES ---

Please first localize the bug based on the issue statement, and then generate a patch according to the `git diff` format fenced by three backticks.

Here is an example:

```diff
diff --git a/examples/server_async.py b/examples/server_async.py
--- a/examples/server_async.py
+++ b/examples/server_async.py
@@ -313,4 +313,4 @@
 
 
 if __name__ == "__main__":
-    asyncio.run(run_async_server("."), debug=True)
+    asyncio.run(run_async_server(), debug=True)
diff --git a/examples/server_sync.py b/examples/server_sync.py
--- a/examples/server_sync.py
+++ b/examples/server_sync.py
@@ -313,5 +313,5 @@
 
 
 if __name__ == "__main__":
-    server = run_sync_server(".")
+    server = run_sync_server()
     server.shutdown()

```

diff --git a/libraries/botbuilder-integration-aiohttp/botbuilder/integration/aiohttp/bot_framework_http_client.py b/libraries/botbuilder-integration-aiohttp/botbuilder/integration/aiohttp/bot_framework_http_client.py
--- a/libraries/botbuilder-integration-aiohttp/botbuilder/integration/aiohttp/bot_framework_http_client.py
+++ b/libraries/botbuilder-integration-aiohttp/botbuilder/integration/aiohttp/bot_framework_http_client.py
@@ -18,8 +18,9 @@
 from botframework.connector.auth import (
     ChannelProvider,
     CredentialProvider,
-    GovernmentConstants,
     MicrosoftAppCredentials,
+    AppCredentials,
+    MicrosoftGovernmentAppCredentials,
 )
 
 
@@ -146,27 +147,26 @@
 
     async def _get_app_credentials(
         self, app_id: str, oauth_scope: str
-    ) -> MicrosoftAppCredentials:
+    ) -> AppCredentials:
         if not app_id:
-            return MicrosoftAppCredentials(None, None)
+            return MicrosoftAppCredentials.empty()
 
+        # in the cache?
         cache_key = f"{app_id}{oauth_scope}"
         app_credentials = BotFrameworkHttpClient._APP_CREDENTIALS_CACHE.get(cache_key)
-
         if app_credentials:
             return app_credentials
 
+        # create a new AppCredentials
         app_password = await self._credential_provider.get_app_password(app_id)
-        app_credentials = MicrosoftAppCredentials(
-            app_id, app_password, oauth_scope=oauth_scope
+
+        app_credentials = (
+            MicrosoftGovernmentAppCredentials(app_id, app_password, scope=oauth_scope)
+            if self._credential_provider and self._channel_provider.is_government()
+            else MicrosoftAppCredentials(app_id, app_password, oauth_scope=oauth_scope)
         )
-        if self._channel_provider and self._channel_provider.is_government():
-            app_credentials.oauth_endpoint = (
-                GovernmentConstants.TO_CHANNEL_FROM_BOT_LOGIN_URL
-            )
-            app_credentials.oauth_scope = (
-                GovernmentConstants.TO_CHANNEL_FROM_BOT_OAUTH_SCOPE
-            )
 
+        # put it in the cache
         BotFrameworkHttpClient._APP_CREDENTIALS_CACHE[cache_key] = app_credentials
+
         return app_credentials
diff --git a/libraries/botframework-connector/botframework/connector/auth/microsoft_government_app_credentials.py b/libraries/botframework-connector/botframework/connector/auth/microsoft_government_app_credentials.py
--- a/libraries/botframework-connector/botframework/connector/auth/microsoft_government_app_credentials.py
+++ b/libraries/botframework-connector/botframework/connector/auth/microsoft_government_app_credentials.py
@@ -14,10 +14,13 @@
         app_id: str,
         app_password: str,
         channel_auth_tenant: str = None,
-        scope: str = GovernmentConstants.TO_CHANNEL_FROM_BOT_OAUTH_SCOPE,
+        scope: str = None,
     ):
         super().__init__(app_id, app_password, channel_auth_tenant, scope)
         self.oauth_endpoint = GovernmentConstants.TO_CHANNEL_FROM_BOT_LOGIN_URL
+        self.oauth_scope = (
+            scope if scope else GovernmentConstants.TO_CHANNEL_FROM_BOT_OAUTH_SCOPE
+        )
 
     @staticmethod
     def empty():

{"golden_diff": "diff --git a/libraries/botbuilder-integration-aiohttp/botbuilder/integration/aiohttp/bot_framework_http_client.py b/libraries/botbuilder-integration-aiohttp/botbuilder/integration/aiohttp/bot_framework_http_client.py\n--- a/libraries/botbuilder-integration-aiohttp/botbuilder/integration/aiohttp/bot_framework_http_client.py\n+++ b/libraries/botbuilder-integration-aiohttp/botbuilder/integration/aiohttp/bot_framework_http_client.py\n@@ -18,8 +18,9 @@\n from botframework.connector.auth import (\n     ChannelProvider,\n     CredentialProvider,\n-    GovernmentConstants,\n     MicrosoftAppCredentials,\n+    AppCredentials,\n+    MicrosoftGovernmentAppCredentials,\n )\n \n \n@@ -146,27 +147,26 @@\n \n     async def _get_app_credentials(\n         self, app_id: str, oauth_scope: str\n-    ) -> MicrosoftAppCredentials:\n+    ) -> AppCredentials:\n         if not app_id:\n-            return MicrosoftAppCredentials(None, None)\n+            return MicrosoftAppCredentials.empty()\n \n+        # in the cache?\n         cache_key = f\"{app_id}{oauth_scope}\"\n         app_credentials = BotFrameworkHttpClient._APP_CREDENTIALS_CACHE.get(cache_key)\n-\n         if app_credentials:\n             return app_credentials\n \n+        # create a new AppCredentials\n         app_password = await self._credential_provider.get_app_password(app_id)\n-        app_credentials = MicrosoftAppCredentials(\n-            app_id, app_password, oauth_scope=oauth_scope\n+\n+        app_credentials = (\n+            MicrosoftGovernmentAppCredentials(app_id, app_password, scope=oauth_scope)\n+            if self._credential_provider and self._channel_provider.is_government()\n+            else MicrosoftAppCredentials(app_id, app_password, oauth_scope=oauth_scope)\n         )\n-        if self._channel_provider and self._channel_provider.is_government():\n-            app_credentials.oauth_endpoint = (\n-                GovernmentConstants.TO_CHANNEL_FROM_BOT_LOGIN_URL\n-            )\n-            app_credentials.oauth_scope = (\n-                GovernmentConstants.TO_CHANNEL_FROM_BOT_OAUTH_SCOPE\n-            )\n \n+        # put it in the cache\n         BotFrameworkHttpClient._APP_CREDENTIALS_CACHE[cache_key] = app_credentials\n+\n         return app_credentials\ndiff --git a/libraries/botframework-connector/botframework/connector/auth/microsoft_government_app_credentials.py b/libraries/botframework-connector/botframework/connector/auth/microsoft_government_app_credentials.py\n--- a/libraries/botframework-connector/botframework/connector/auth/microsoft_government_app_credentials.py\n+++ b/libraries/botframework-connector/botframework/connector/auth/microsoft_government_app_credentials.py\n@@ -14,10 +14,13 @@\n         app_id: str,\r\n         app_password: str,\r\n         channel_auth_tenant: str = None,\r\n-        scope: str = GovernmentConstants.TO_CHANNEL_FROM_BOT_OAUTH_SCOPE,\r\n+        scope: str = None,\r\n     ):\r\n         super().__init__(app_id, app_password, channel_auth_tenant, scope)\r\n         self.oauth_endpoint = GovernmentConstants.TO_CHANNEL_FROM_BOT_LOGIN_URL\r\n+        self.oauth_scope = (\r\n+            scope if scope else GovernmentConstants.TO_CHANNEL_FROM_BOT_OAUTH_SCOPE\r\n+        )\r\n \r\n     @staticmethod\r\n     def empty():\n", "issue": "[PORT] Updated MicrosoftGovernmentAppCredentials to support Skills in Azure Gov\n> Port this change from botbuilder-dotnet/master branch:\nhttps://github.com/microsoft/botbuilder-dotnet/pull/3353\n\nFixes https://github.com/microsoft/botbuilder-dotnet/issues/3233\r\n\r\nAdded constructor to MicrosoftGovernmentAppCredentials that takes OAuthScope to support skills in gov.\r\nUpdated BotFrameworkHttpClient and BotFrameworkAdapter to pass the OAuthScope to MicrosoftGovernmentAppCredentials\r\nAdded SimpleBotToBot functional test for testing.\r\nAdded Microsoft.Bot.Framework.Skills.sln to load skills test projects.\n\n\r\n# Changed projects\r\n* Microsoft.Bot.Builder\r\n* Microsoft.Bot.Connector\r\n* integration\r\n* Microsoft.Bot.Connector.Tests\r\n\r\n[Skills]\r\n\r\n\n\n", "before_files": [{"content": "# Copyright (c) Microsoft Corporation. All rights reserved.\r\n# Licensed under the MIT License.\r\n\r\nfrom botframework.connector.auth import MicrosoftAppCredentials, GovernmentConstants\r\n\r\n\r\nclass MicrosoftGovernmentAppCredentials(MicrosoftAppCredentials):\r\n    \"\"\"\r\n    MicrosoftGovernmentAppCredentials auth implementation.\r\n    \"\"\"\r\n\r\n    def __init__(\r\n        self,\r\n        app_id: str,\r\n        app_password: str,\r\n        channel_auth_tenant: str = None,\r\n        scope: str = GovernmentConstants.TO_CHANNEL_FROM_BOT_OAUTH_SCOPE,\r\n    ):\r\n        super().__init__(app_id, app_password, channel_auth_tenant, scope)\r\n        self.oauth_endpoint = GovernmentConstants.TO_CHANNEL_FROM_BOT_LOGIN_URL\r\n\r\n    @staticmethod\r\n    def empty():\r\n        return MicrosoftGovernmentAppCredentials(\"\", \"\")\r\n", "path": "libraries/botframework-connector/botframework/connector/auth/microsoft_government_app_credentials.py"}, {"content": "# Copyright (c) Microsoft Corporation. All rights reserved.\n# Licensed under the MIT License.\n# pylint: disable=no-member\n\nimport json\nfrom typing import Dict\nfrom logging import Logger\n\nimport aiohttp\nfrom botbuilder.core import InvokeResponse\nfrom botbuilder.core.skills import BotFrameworkClient\nfrom botbuilder.schema import (\n    Activity,\n    ExpectedReplies,\n    ConversationReference,\n    ConversationAccount,\n)\nfrom botframework.connector.auth import (\n    ChannelProvider,\n    CredentialProvider,\n    GovernmentConstants,\n    MicrosoftAppCredentials,\n)\n\n\nclass BotFrameworkHttpClient(BotFrameworkClient):\n\n    \"\"\"\n    A skill host adapter implements API to forward activity to a skill and\n    implements routing ChannelAPI calls from the Skill up through the bot/adapter.\n    \"\"\"\n\n    INVOKE_ACTIVITY_NAME = \"SkillEvents.ChannelApiInvoke\"\n    _BOT_IDENTITY_KEY = \"BotIdentity\"\n    _APP_CREDENTIALS_CACHE: Dict[str, MicrosoftAppCredentials] = {}\n\n    def __init__(\n        self,\n        credential_provider: CredentialProvider,\n        channel_provider: ChannelProvider = None,\n        logger: Logger = None,\n    ):\n        if not credential_provider:\n            raise TypeError(\"credential_provider can't be None\")\n\n        self._credential_provider = credential_provider\n        self._channel_provider = channel_provider\n        self._logger = logger\n        self._session = aiohttp.ClientSession()\n\n    async def post_activity(\n        self,\n        from_bot_id: str,\n        to_bot_id: str,\n        to_url: str,\n        service_url: str,\n        conversation_id: str,\n        activity: Activity,\n    ) -> InvokeResponse:\n        app_credentials = await self._get_app_credentials(from_bot_id, to_bot_id)\n\n        if not app_credentials:\n            raise KeyError(\"Unable to get appCredentials to connect to the skill\")\n\n        # Get token for the skill call\n        token = (\n            app_credentials.get_access_token()\n            if app_credentials.microsoft_app_id\n            else None\n        )\n\n        # Capture current activity settings before changing them.\n        # TODO: DO we need to set the activity ID? (events that are created manually don't have it).\n        original_conversation_id = activity.conversation.id\n        original_service_url = activity.service_url\n        original_caller_id = activity.caller_id\n        original_relates_to = activity.relates_to\n\n        try:\n            # TODO: The relato has to be ported to the adapter in the new integration library when\n            #  resolving conflicts in merge\n            activity.relates_to = ConversationReference(\n                service_url=activity.service_url,\n                activity_id=activity.id,\n                channel_id=activity.channel_id,\n                conversation=ConversationAccount(\n                    id=activity.conversation.id,\n                    name=activity.conversation.name,\n                    conversation_type=activity.conversation.conversation_type,\n                    aad_object_id=activity.conversation.aad_object_id,\n                    is_group=activity.conversation.is_group,\n                    role=activity.conversation.role,\n                    tenant_id=activity.conversation.tenant_id,\n                    properties=activity.conversation.properties,\n                ),\n                bot=None,\n            )\n            activity.conversation.id = conversation_id\n            activity.service_url = service_url\n            activity.caller_id = f\"urn:botframework:aadappid:{from_bot_id}\"\n\n            headers_dict = {\n                \"Content-type\": \"application/json; charset=utf-8\",\n            }\n            if token:\n                headers_dict.update(\n                    {\"Authorization\": f\"Bearer {token}\",}\n                )\n\n            json_content = json.dumps(activity.serialize())\n            resp = await self._session.post(\n                to_url, data=json_content.encode(\"utf-8\"), headers=headers_dict,\n            )\n            resp.raise_for_status()\n            data = (await resp.read()).decode()\n            content = json.loads(data) if data else None\n\n            return InvokeResponse(status=resp.status, body=content)\n\n        finally:\n            # Restore activity properties.\n            activity.conversation.id = original_conversation_id\n            activity.service_url = original_service_url\n            activity.caller_id = original_caller_id\n            activity.relates_to = original_relates_to\n\n    async def post_buffered_activity(\n        self,\n        from_bot_id: str,\n        to_bot_id: str,\n        to_url: str,\n        service_url: str,\n        conversation_id: str,\n        activity: Activity,\n    ) -> [Activity]:\n        \"\"\"\n        Helper method to return a list of activities when an Activity is being\n        sent with DeliveryMode == expectReplies.\n        \"\"\"\n        response = await self.post_activity(\n            from_bot_id, to_bot_id, to_url, service_url, conversation_id, activity\n        )\n        if not response or (response.status / 100) != 2:\n            return []\n        return ExpectedReplies().deserialize(response.body).activities\n\n    async def _get_app_credentials(\n        self, app_id: str, oauth_scope: str\n    ) -> MicrosoftAppCredentials:\n        if not app_id:\n            return MicrosoftAppCredentials(None, None)\n\n        cache_key = f\"{app_id}{oauth_scope}\"\n        app_credentials = BotFrameworkHttpClient._APP_CREDENTIALS_CACHE.get(cache_key)\n\n        if app_credentials:\n            return app_credentials\n\n        app_password = await self._credential_provider.get_app_password(app_id)\n        app_credentials = MicrosoftAppCredentials(\n            app_id, app_password, oauth_scope=oauth_scope\n        )\n        if self._channel_provider and self._channel_provider.is_government():\n            app_credentials.oauth_endpoint = (\n                GovernmentConstants.TO_CHANNEL_FROM_BOT_LOGIN_URL\n            )\n            app_credentials.oauth_scope = (\n                GovernmentConstants.TO_CHANNEL_FROM_BOT_OAUTH_SCOPE\n            )\n\n        BotFrameworkHttpClient._APP_CREDENTIALS_CACHE[cache_key] = app_credentials\n        return app_credentials\n", "path": "libraries/botbuilder-integration-aiohttp/botbuilder/integration/aiohttp/bot_framework_http_client.py"}], "after_files": [{"content": "# Copyright (c) Microsoft Corporation. All rights reserved.\r\n# Licensed under the MIT License.\r\n\r\nfrom botframework.connector.auth import MicrosoftAppCredentials, GovernmentConstants\r\n\r\n\r\nclass MicrosoftGovernmentAppCredentials(MicrosoftAppCredentials):\r\n    \"\"\"\r\n    MicrosoftGovernmentAppCredentials auth implementation.\r\n    \"\"\"\r\n\r\n    def __init__(\r\n        self,\r\n        app_id: str,\r\n        app_password: str,\r\n        channel_auth_tenant: str = None,\r\n        scope: str = None,\r\n    ):\r\n        super().__init__(app_id, app_password, channel_auth_tenant, scope)\r\n        self.oauth_endpoint = GovernmentConstants.TO_CHANNEL_FROM_BOT_LOGIN_URL\r\n        self.oauth_scope = (\r\n            scope if scope else GovernmentConstants.TO_CHANNEL_FROM_BOT_OAUTH_SCOPE\r\n        )\r\n\r\n    @staticmethod\r\n    def empty():\r\n        return MicrosoftGovernmentAppCredentials(\"\", \"\")\r\n", "path": "libraries/botframework-connector/botframework/connector/auth/microsoft_government_app_credentials.py"}, {"content": "# Copyright (c) Microsoft Corporation. All rights reserved.\n# Licensed under the MIT License.\n# pylint: disable=no-member\n\nimport json\nfrom typing import Dict\nfrom logging import Logger\n\nimport aiohttp\nfrom botbuilder.core import InvokeResponse\nfrom botbuilder.core.skills import BotFrameworkClient\nfrom botbuilder.schema import (\n    Activity,\n    ExpectedReplies,\n    ConversationReference,\n    ConversationAccount,\n)\nfrom botframework.connector.auth import (\n    ChannelProvider,\n    CredentialProvider,\n    MicrosoftAppCredentials,\n    AppCredentials,\n    MicrosoftGovernmentAppCredentials,\n)\n\n\nclass BotFrameworkHttpClient(BotFrameworkClient):\n\n    \"\"\"\n    A skill host adapter implements API to forward activity to a skill and\n    implements routing ChannelAPI calls from the Skill up through the bot/adapter.\n    \"\"\"\n\n    INVOKE_ACTIVITY_NAME = \"SkillEvents.ChannelApiInvoke\"\n    _BOT_IDENTITY_KEY = \"BotIdentity\"\n    _APP_CREDENTIALS_CACHE: Dict[str, MicrosoftAppCredentials] = {}\n\n    def __init__(\n        self,\n        credential_provider: CredentialProvider,\n        channel_provider: ChannelProvider = None,\n        logger: Logger = None,\n    ):\n        if not credential_provider:\n            raise TypeError(\"credential_provider can't be None\")\n\n        self._credential_provider = credential_provider\n        self._channel_provider = channel_provider\n        self._logger = logger\n        self._session = aiohttp.ClientSession()\n\n    async def post_activity(\n        self,\n        from_bot_id: str,\n        to_bot_id: str,\n        to_url: str,\n        service_url: str,\n        conversation_id: str,\n        activity: Activity,\n    ) -> InvokeResponse:\n        app_credentials = await self._get_app_credentials(from_bot_id, to_bot_id)\n\n        if not app_credentials:\n            raise KeyError(\"Unable to get appCredentials to connect to the skill\")\n\n        # Get token for the skill call\n        token = (\n            app_credentials.get_access_token()\n            if app_credentials.microsoft_app_id\n            else None\n        )\n\n        # Capture current activity settings before changing them.\n        # TODO: DO we need to set the activity ID? (events that are created manually don't have it).\n        original_conversation_id = activity.conversation.id\n        original_service_url = activity.service_url\n        original_caller_id = activity.caller_id\n        original_relates_to = activity.relates_to\n\n        try:\n            # TODO: The relato has to be ported to the adapter in the new integration library when\n            #  resolving conflicts in merge\n            activity.relates_to = ConversationReference(\n                service_url=activity.service_url,\n                activity_id=activity.id,\n                channel_id=activity.channel_id,\n                conversation=ConversationAccount(\n                    id=activity.conversation.id,\n                    name=activity.conversation.name,\n                    conversation_type=activity.conversation.conversation_type,\n                    aad_object_id=activity.conversation.aad_object_id,\n                    is_group=activity.conversation.is_group,\n                    role=activity.conversation.role,\n                    tenant_id=activity.conversation.tenant_id,\n                    properties=activity.conversation.properties,\n                ),\n                bot=None,\n            )\n            activity.conversation.id = conversation_id\n            activity.service_url = service_url\n            activity.caller_id = f\"urn:botframework:aadappid:{from_bot_id}\"\n\n            headers_dict = {\n                \"Content-type\": \"application/json; charset=utf-8\",\n            }\n            if token:\n                headers_dict.update(\n                    {\"Authorization\": f\"Bearer {token}\",}\n                )\n\n            json_content = json.dumps(activity.serialize())\n            resp = await self._session.post(\n                to_url, data=json_content.encode(\"utf-8\"), headers=headers_dict,\n            )\n            resp.raise_for_status()\n            data = (await resp.read()).decode()\n            content = json.loads(data) if data else None\n\n            return InvokeResponse(status=resp.status, body=content)\n\n        finally:\n            # Restore activity properties.\n            activity.conversation.id = original_conversation_id\n            activity.service_url = original_service_url\n            activity.caller_id = original_caller_id\n            activity.relates_to = original_relates_to\n\n    async def post_buffered_activity(\n        self,\n        from_bot_id: str,\n        to_bot_id: str,\n        to_url: str,\n        service_url: str,\n        conversation_id: str,\n        activity: Activity,\n    ) -> [Activity]:\n        \"\"\"\n        Helper method to return a list of activities when an Activity is being\n        sent with DeliveryMode == expectReplies.\n        \"\"\"\n        response = await self.post_activity(\n            from_bot_id, to_bot_id, to_url, service_url, conversation_id, activity\n        )\n        if not response or (response.status / 100) != 2:\n            return []\n        return ExpectedReplies().deserialize(response.body).activities\n\n    async def _get_app_credentials(\n        self, app_id: str, oauth_scope: str\n    ) -> AppCredentials:\n        if not app_id:\n            return MicrosoftAppCredentials.empty()\n\n        # in the cache?\n        cache_key = f\"{app_id}{oauth_scope}\"\n        app_credentials = BotFrameworkHttpClient._APP_CREDENTIALS_CACHE.get(cache_key)\n        if app_credentials:\n            return app_credentials\n\n        # create a new AppCredentials\n        app_password = await self._credential_provider.get_app_password(app_id)\n\n        app_credentials = (\n            MicrosoftGovernmentAppCredentials(app_id, app_password, scope=oauth_scope)\n            if self._credential_provider and self._channel_provider.is_government()\n            else MicrosoftAppCredentials(app_id, app_password, oauth_scope=oauth_scope)\n        )\n\n        # put it in the cache\n        BotFrameworkHttpClient._APP_CREDENTIALS_CACHE[cache_key] = app_credentials\n\n        return app_credentials\n", "path": "libraries/botbuilder-integration-aiohttp/botbuilder/integration/aiohttp/bot_framework_http_client.py"}]}