diff --git a/sdk/communication/azure-communication-messages/MANIFEST.in b/sdk/communication/azure-communication-messages/MANIFEST.in index 0808b8a6a118..ba2a01329f05 100644 --- a/sdk/communication/azure-communication-messages/MANIFEST.in +++ b/sdk/communication/azure-communication-messages/MANIFEST.in @@ -4,4 +4,4 @@ include azure/communication/messages/py.typed recursive-include tests *.py recursive-include samples *.py *.md include azure/__init__.py -include azure/communication/__init__.py \ No newline at end of file +include azure/communication/__init__.py diff --git a/sdk/communication/azure-communication-messages/_meta.json b/sdk/communication/azure-communication-messages/_meta.json new file mode 100644 index 000000000000..f7fc4f1d884e --- /dev/null +++ b/sdk/communication/azure-communication-messages/_meta.json @@ -0,0 +1,6 @@ +{ + "commit": "726419b7eba57b9b5888ca11e055c8f82dcaae58", + "repository_url": "https://github.com/Azure/azure-rest-api-specs", + "typespec_src": "specification/communication/Communication.Messages", + "@azure-tools/typespec-python": "0.44.2" +} \ No newline at end of file diff --git a/sdk/communication/azure-communication-messages/apiview-properties.json b/sdk/communication/azure-communication-messages/apiview-properties.json new file mode 100644 index 000000000000..a1a52abccb09 --- /dev/null +++ b/sdk/communication/azure-communication-messages/apiview-properties.json @@ -0,0 +1,121 @@ +{ + "CrossLanguagePackageId": "Azure.Communication.MessagesService", + "CrossLanguageDefinitionId": { + "azure.communication.messages.models.ActionBindings": "Azure.Communication.MessagesService.ActionBindings", + "azure.communication.messages.models.ActionGroup": "Azure.Communication.MessagesService.ActionGroup", + "azure.communication.messages.models.MessageContent": "Azure.Communication.MessagesService.MessageContent", + "azure.communication.messages.models.ActionGroupContent": "Azure.Communication.MessagesService.ActionGroupContent", + "azure.communication.messages.models.ActionGroupItem": "Azure.Communication.MessagesService.ActionGroupItem", + "azure.communication.messages.models.AddParticipantsOptions": "Azure.Communication.MessagesService.AddParticipantsOptions", + "azure.communication.messages.models.AddParticipantsResult": "Azure.Communication.MessagesService.AddParticipantsResult", + "azure.communication.messages.models.ConversationMessageContent": "Azure.Communication.MessagesService.ConversationMessageContent", + "azure.communication.messages.models.AudioConversationMessageContent": "Azure.Communication.MessagesService.AudioConversationMessageContent", + "azure.communication.messages.models.NotificationContent": "Azure.Communication.MessagesService.NotificationContent", + "azure.communication.messages.models.AudioNotificationContent": "Azure.Communication.MessagesService.AudioNotificationContent", + "azure.communication.messages.models.Contact": "Azure.Communication.MessagesService.Contact", + "azure.communication.messages.models.BotContact": "Azure.Communication.MessagesService.BotContact", + "azure.communication.messages.models.ButtonContent": "Azure.Communication.MessagesService.ButtonContent", + "azure.communication.messages.models.ButtonSetContent": "Azure.Communication.MessagesService.ButtonSetContent", + "azure.communication.messages.models.CommunicationContact": "Azure.Communication.MessagesService.CommunicationContact", + "azure.communication.messages.models.CommunicationConversation": "Azure.Communication.MessagesService.Conversation", + "azure.communication.messages.models.ConversationMessageItem": "Azure.Communication.MessagesService.ConversationMessageItem", + "azure.communication.messages.models.ConversationParticipant": "Azure.Communication.MessagesService.ConversationParticipant", + "azure.communication.messages.models.DocumentConversationMessageContent": "Azure.Communication.MessagesService.DocumentConversationMessageContent", + "azure.communication.messages.models.DocumentMessageContent": "Azure.Communication.MessagesService.DocumentMessageContent", + "azure.communication.messages.models.DocumentNotificationContent": "Azure.Communication.MessagesService.DocumentNotificationContent", + "azure.communication.messages.models.ExternalConversationParticipant": "Azure.Communication.MessagesService.ExternalConversationParticipant", + "azure.communication.messages.models.GetConversationThreadAnalysisResult": "Azure.Communication.MessagesService.GetConversationThreadAnalysisResult", + "azure.communication.messages.models.ImageConversationMessageContent": "Azure.Communication.MessagesService.ImageConversationMessageContent", + "azure.communication.messages.models.ImageMessageContent": "Azure.Communication.MessagesService.ImageMessageContent", + "azure.communication.messages.models.ImageNotificationContent": "Azure.Communication.MessagesService.ImageNotificationContent", + "azure.communication.messages.models.InteractiveMessage": "Azure.Communication.MessagesService.InteractiveMessage", + "azure.communication.messages.models.InteractiveNotificationContent": "Azure.Communication.MessagesService.InteractiveNotificationContent", + "azure.communication.messages.models.InternalConversationParticipant": "Azure.Communication.MessagesService.InternalConversationParticipant", + "azure.communication.messages.models.LinkContent": "Azure.Communication.MessagesService.LinkContent", + "azure.communication.messages.models.MediaNotificationContent": "Azure.Communication.MessagesService.MediaNotificationContent", + "azure.communication.messages.models.Message": "Azure.Communication.MessagesService.Message", + "azure.communication.messages.models.MessageReceipt": "Azure.Communication.MessagesService.MessageReceipt", + "azure.communication.messages.models.MessageTemplate": "Azure.Communication.MessagesService.MessageTemplate", + "azure.communication.messages.models.MessageTemplateBindings": "Azure.Communication.MessagesService.MessageTemplateBindings", + "azure.communication.messages.models.MessageTemplateValue": "Azure.Communication.MessagesService.MessageTemplateValue", + "azure.communication.messages.models.MessageTemplateDocument": "Azure.Communication.MessagesService.MessageTemplateDocument", + "azure.communication.messages.models.MessageTemplateImage": "Azure.Communication.MessagesService.MessageTemplateImage", + "azure.communication.messages.models.MessageTemplateItem": "Azure.Communication.MessagesService.MessageTemplateItem", + "azure.communication.messages.models.MessageTemplateLocation": "Azure.Communication.MessagesService.MessageTemplateLocation", + "azure.communication.messages.models.MessageTemplateQuickAction": "Azure.Communication.MessagesService.MessageTemplateQuickAction", + "azure.communication.messages.models.MessageTemplateText": "Azure.Communication.MessagesService.MessageTemplateText", + "azure.communication.messages.models.MessageTemplateVideo": "Azure.Communication.MessagesService.MessageTemplateVideo", + "azure.communication.messages.models.ReactionNotificationContent": "Azure.Communication.MessagesService.ReactionNotificationContent", + "azure.communication.messages.models.RemoveParticipantsOptions": "Azure.Communication.MessagesService.RemoveParticipantsOptions", + "azure.communication.messages.models.RemoveParticipantsResult": "Azure.Communication.MessagesService.RemoveParticipantsResult", + "azure.communication.messages.models.SendConversationMessageOptions": "Azure.Communication.MessagesService.SendConversationMessageOptions", + "azure.communication.messages.models.SendConversationMessageResult": "Azure.Communication.MessagesService.SendConversationMessageResult", + "azure.communication.messages.models.SendMessageResult": "Azure.Communication.MessagesService.SendMessageResult", + "azure.communication.messages.models.StickerNotificationContent": "Azure.Communication.MessagesService.StickerNotificationContent", + "azure.communication.messages.models.TemplateConversationMessageContent": "Azure.Communication.MessagesService.TemplateConversationMessageContent", + "azure.communication.messages.models.TemplateNotificationContent": "Azure.Communication.MessagesService.TemplateNotificationContent", + "azure.communication.messages.models.TextConversationMessageContent": "Azure.Communication.MessagesService.TextConversationMessageContent", + "azure.communication.messages.models.TextMessageContent": "Azure.Communication.MessagesService.TextMessageContent", + "azure.communication.messages.models.TextNotificationContent": "Azure.Communication.MessagesService.TextNotificationContent", + "azure.communication.messages.models.UpdateParticipantsResult": "Azure.Communication.MessagesService.UpdateParticipantsResult", + "azure.communication.messages.models.VideoConversationMessageContent": "Azure.Communication.MessagesService.VideoConversationMessageContent", + "azure.communication.messages.models.VideoMessageContent": "Azure.Communication.MessagesService.VideoMessageContent", + "azure.communication.messages.models.VideoNotificationContent": "Azure.Communication.MessagesService.VideoNotificationContent", + "azure.communication.messages.models.WhatsAppButtonActionBindings": "Azure.Communication.MessagesService.WhatsAppButtonActionBindings", + "azure.communication.messages.models.WhatsAppContact": "Azure.Communication.MessagesService.WhatsAppContact", + "azure.communication.messages.models.WhatsAppListActionBindings": "Azure.Communication.MessagesService.WhatsAppListActionBindings", + "azure.communication.messages.models.WhatsAppMessageTemplateBindings": "Azure.Communication.MessagesService.WhatsAppMessageTemplateBindings", + "azure.communication.messages.models.WhatsAppMessageTemplateBindingsButton": "Azure.Communication.MessagesService.WhatsAppMessageTemplateBindingsButton", + "azure.communication.messages.models.WhatsAppMessageTemplateBindingsComponent": "Azure.Communication.MessagesService.WhatsAppMessageTemplateBindingsComponent", + "azure.communication.messages.models.WhatsAppMessageTemplateItem": "Azure.Communication.MessagesService.WhatsAppMessageTemplateItem", + "azure.communication.messages.models.WhatsAppUrlActionBindings": "Azure.Communication.MessagesService.WhatsAppUrlActionBindings", + "azure.communication.messages.models.RepeatabilityResult": "Azure.Core.RepeatabilityResult", + "azure.communication.messages.models.CommunicationMessageKind": "Azure.Communication.MessagesService.CommunicationMessageKind", + "azure.communication.messages.models.MessageContentKind": "Azure.Communication.MessagesService.MessageContentKind", + "azure.communication.messages.models.MessageActionBindingKind": "Azure.Communication.MessagesService.MessageActionBindingKind", + "azure.communication.messages.models.MessageTemplateValueKind": "Azure.Communication.MessagesService.MessageTemplateValueKind", + "azure.communication.messages.models.MessageTemplateBindingsKind": "Azure.Communication.MessagesService.MessageTemplateBindingsKind", + "azure.communication.messages.models.WhatsAppMessageButtonSubType": "Azure.Communication.MessagesService.WhatsAppMessageButtonSubType", + "azure.communication.messages.models.MessageTemplateStatus": "Azure.Communication.MessagesService.MessageTemplateStatus", + "azure.communication.messages.models.CommunicationMessagesChannel": "Azure.Communication.MessagesService.CommunicationMessagesChannel", + "azure.communication.messages.models.OutboundDeliveryStrategyKind": "Azure.Communication.MessagesService.OutboundDeliveryStrategyKind", + "azure.communication.messages.models.ParticipantKind": "Azure.Communication.MessagesService.ParticipantKind", + "azure.communication.messages.models.MessagePlatformKind": "Azure.Communication.MessagesService.MessagePlatformKind", + "azure.communication.messages.NotificationMessagesClient.send": "Azure.Communication.MessagesService.NotificationMessagesClient.send", + "azure.communication.messages.aio.NotificationMessagesClient.send": "Azure.Communication.MessagesService.NotificationMessagesClient.send", + "azure.communication.messages.NotificationMessagesClient.download_media": "ClientForAcsMessages.NotificationMessagesClient.downloadMedia", + "azure.communication.messages.aio.NotificationMessagesClient.download_media": "ClientForAcsMessages.NotificationMessagesClient.downloadMedia", + "azure.communication.messages.MessageTemplateClient.list_templates": "Azure.Communication.MessagesService.MessageTemplateClient.listTemplates", + "azure.communication.messages.aio.MessageTemplateClient.list_templates": "Azure.Communication.MessagesService.MessageTemplateClient.listTemplates", + "azure.communication.messages.ConversationAdministrationClient.create_conversation": "Azure.Communication.MessagesService.ConversationAdministrationClient.createConversation", + "azure.communication.messages.aio.ConversationAdministrationClient.create_conversation": "Azure.Communication.MessagesService.ConversationAdministrationClient.createConversation", + "azure.communication.messages.ConversationAdministrationClient.get_conversation": "Azure.Communication.MessagesService.ConversationAdministrationClient.getConversation", + "azure.communication.messages.aio.ConversationAdministrationClient.get_conversation": "Azure.Communication.MessagesService.ConversationAdministrationClient.getConversation", + "azure.communication.messages.ConversationAdministrationClient.delete_conversation": "Azure.Communication.MessagesService.ConversationAdministrationClient.deleteConversation", + "azure.communication.messages.aio.ConversationAdministrationClient.delete_conversation": "Azure.Communication.MessagesService.ConversationAdministrationClient.deleteConversation", + "azure.communication.messages.ConversationAdministrationClient.terminate_conversation": "Azure.Communication.MessagesService.ConversationAdministrationClient.terminateConversation", + "azure.communication.messages.aio.ConversationAdministrationClient.terminate_conversation": "Azure.Communication.MessagesService.ConversationAdministrationClient.terminateConversation", + "azure.communication.messages.ConversationAdministrationClient.list_conversations": "ClientForAcsMessages.ConversationAdministrationClient.listConversations", + "azure.communication.messages.aio.ConversationAdministrationClient.list_conversations": "ClientForAcsMessages.ConversationAdministrationClient.listConversations", + "azure.communication.messages.ConversationAdministrationClient.list_messages": "ClientForAcsMessages.ConversationAdministrationClient.listMessages", + "azure.communication.messages.aio.ConversationAdministrationClient.list_messages": "ClientForAcsMessages.ConversationAdministrationClient.listMessages", + "azure.communication.messages.ConversationAdministrationClient.add_participants": "ClientForAcsMessages.ConversationAdministrationClient.addParticipants", + "azure.communication.messages.aio.ConversationAdministrationClient.add_participants": "ClientForAcsMessages.ConversationAdministrationClient.addParticipants", + "azure.communication.messages.ConversationAdministrationClient.remove_participants": "ClientForAcsMessages.ConversationAdministrationClient.removeParticipants", + "azure.communication.messages.aio.ConversationAdministrationClient.remove_participants": "ClientForAcsMessages.ConversationAdministrationClient.removeParticipants", + "azure.communication.messages.ConversationAdministrationClient.analyze_conversation": "ClientForAcsMessages.ConversationAdministrationClient.analyzeConversation", + "azure.communication.messages.aio.ConversationAdministrationClient.analyze_conversation": "ClientForAcsMessages.ConversationAdministrationClient.analyzeConversation", + "azure.communication.messages.ConversationThreadClient.add_participants": "Azure.Communication.MessagesService.ConversationThreadClient.addParticipants", + "azure.communication.messages.aio.ConversationThreadClient.add_participants": "Azure.Communication.MessagesService.ConversationThreadClient.addParticipants", + "azure.communication.messages.ConversationThreadClient.remove_participants": "Azure.Communication.MessagesService.ConversationThreadClient.removeParticipants", + "azure.communication.messages.aio.ConversationThreadClient.remove_participants": "Azure.Communication.MessagesService.ConversationThreadClient.removeParticipants", + "azure.communication.messages.ConversationThreadClient.list_conversations": "Azure.Communication.MessagesService.ConversationThreadClient.listConversations", + "azure.communication.messages.aio.ConversationThreadClient.list_conversations": "Azure.Communication.MessagesService.ConversationThreadClient.listConversations", + "azure.communication.messages.ConversationThreadClient.list_messages": "Azure.Communication.MessagesService.ConversationThreadClient.listMessages", + "azure.communication.messages.aio.ConversationThreadClient.list_messages": "Azure.Communication.MessagesService.ConversationThreadClient.listMessages", + "azure.communication.messages.ConversationThreadClient.send_message": "Azure.Communication.MessagesService.ConversationThreadClient.sendMessage", + "azure.communication.messages.aio.ConversationThreadClient.send_message": "Azure.Communication.MessagesService.ConversationThreadClient.sendMessage", + "azure.communication.messages.ConversationThreadClient.analyze_conversation": "Azure.Communication.MessagesService.ConversationThreadClient.analyzeConversation", + "azure.communication.messages.aio.ConversationThreadClient.analyze_conversation": "Azure.Communication.MessagesService.ConversationThreadClient.analyzeConversation" + } +} \ No newline at end of file diff --git a/sdk/communication/azure-communication-messages/azure/communication/messages/__init__.py b/sdk/communication/azure-communication-messages/azure/communication/messages/__init__.py index d37d6656e82a..a521cc1084d9 100644 --- a/sdk/communication/azure-communication-messages/azure/communication/messages/__init__.py +++ b/sdk/communication/azure-communication-messages/azure/communication/messages/__init__.py @@ -14,6 +14,8 @@ from ._client import NotificationMessagesClient # type: ignore from ._client import MessageTemplateClient # type: ignore +from ._client import ConversationAdministrationClient # type: ignore +from ._client import ConversationThreadClient # type: ignore from ._version import VERSION __version__ = VERSION @@ -28,6 +30,8 @@ __all__ = [ "NotificationMessagesClient", "MessageTemplateClient", + "ConversationAdministrationClient", + "ConversationThreadClient", ] __all__.extend([p for p in _patch_all if p not in __all__]) # pyright: ignore diff --git a/sdk/communication/azure-communication-messages/azure/communication/messages/_api_versions.py b/sdk/communication/azure-communication-messages/azure/communication/messages/_api_versions.py deleted file mode 100644 index 98685e53479c..000000000000 --- a/sdk/communication/azure-communication-messages/azure/communication/messages/_api_versions.py +++ /dev/null @@ -1,17 +0,0 @@ -# ------------------------------------ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. -# ------------------------------------ - -from enum import Enum -from azure.core import CaseInsensitiveEnumMeta - - -class ApiVersion(str, Enum, metaclass=CaseInsensitiveEnumMeta): - V2023_08_24_PREVIEW = "2023-08-24-preview" - V2024_02_01 = "2024-02-01" - V2024_08_30 = "2024-08-30" - V2025_01_15_PREVIEW = "2025-01-15-preview" - - -DEFAULT_VERSION = ApiVersion.V2025_01_15_preview.value diff --git a/sdk/communication/azure-communication-messages/azure/communication/messages/_client.py b/sdk/communication/azure-communication-messages/azure/communication/messages/_client.py index a32a72ef112a..a3b4a47524ab 100644 --- a/sdk/communication/azure-communication-messages/azure/communication/messages/_client.py +++ b/sdk/communication/azure-communication-messages/azure/communication/messages/_client.py @@ -15,9 +15,19 @@ from azure.core.pipeline import policies from azure.core.rest import HttpRequest, HttpResponse -from ._configuration import MessageTemplateClientConfiguration, NotificationMessagesClientConfiguration -from ._operations import MessageTemplateClientOperationsMixin, NotificationMessagesClientOperationsMixin -from ._serialization import Deserializer, Serializer +from ._configuration import ( + ConversationAdministrationClientConfiguration, + ConversationThreadClientConfiguration, + MessageTemplateClientConfiguration, + NotificationMessagesClientConfiguration, +) +from ._operations import ( + ConversationAdministrationClientOperationsMixin, + ConversationThreadClientOperationsMixin, + MessageTemplateClientOperationsMixin, + NotificationMessagesClientOperationsMixin, +) +from ._utils.serialization import Deserializer, Serializer if TYPE_CHECKING: from azure.core.credentials import TokenCredential @@ -27,14 +37,15 @@ class NotificationMessagesClient(NotificationMessagesClientOperationsMixin): """NotificationMessagesClient. :param endpoint: The communication resource, for example - https://my-resource.communication.azure.com. Required. + `https://my-resource.communication.azure.com `_. + Required. :type endpoint: str :param credential: Credential used to authenticate requests to the service. Is either a token - credential type or a AzureKeyCredential type. Required. + credential type or a key credential type. Required. :type credential: ~azure.core.credentials.TokenCredential or - ~azure.core.credentials.AzureKeyCredential + ~azure.core.credentials.AzureKeyCredential or ~azure.core.credentials.AzureKeyCredential :keyword api_version: The API version to use for this operation. Default value is - "2025-01-15-preview". Note that overriding this default value may result in unsupported + "2025-04-01-preview". Note that overriding this default value may result in unsupported behavior. :paramtype api_version: str """ @@ -42,6 +53,7 @@ class NotificationMessagesClient(NotificationMessagesClientOperationsMixin): def __init__(self, endpoint: str, credential: Union["TokenCredential", AzureKeyCredential], **kwargs: Any) -> None: _endpoint = "{endpoint}" self._config = NotificationMessagesClientConfiguration(endpoint=endpoint, credential=credential, **kwargs) + _policies = kwargs.pop("policies", None) if _policies is None: _policies = [ @@ -106,14 +118,15 @@ class MessageTemplateClient(MessageTemplateClientOperationsMixin): """MessageTemplateClient. :param endpoint: The communication resource, for example - https://my-resource.communication.azure.com. Required. + `https://my-resource.communication.azure.com `_. + Required. :type endpoint: str :param credential: Credential used to authenticate requests to the service. Is either a token - credential type or a AzureKeyCredential type. Required. + credential type or a key credential type. Required. :type credential: ~azure.core.credentials.TokenCredential or - ~azure.core.credentials.AzureKeyCredential + ~azure.core.credentials.AzureKeyCredential or ~azure.core.credentials.AzureKeyCredential :keyword api_version: The API version to use for this operation. Default value is - "2025-01-15-preview". Note that overriding this default value may result in unsupported + "2025-04-01-preview". Note that overriding this default value may result in unsupported behavior. :paramtype api_version: str """ @@ -121,6 +134,169 @@ class MessageTemplateClient(MessageTemplateClientOperationsMixin): def __init__(self, endpoint: str, credential: Union["TokenCredential", AzureKeyCredential], **kwargs: Any) -> None: _endpoint = "{endpoint}" self._config = MessageTemplateClientConfiguration(endpoint=endpoint, credential=credential, **kwargs) + + _policies = kwargs.pop("policies", None) + if _policies is None: + _policies = [ + policies.RequestIdPolicy(**kwargs), + self._config.headers_policy, + self._config.user_agent_policy, + self._config.proxy_policy, + policies.ContentDecodePolicy(**kwargs), + self._config.redirect_policy, + self._config.retry_policy, + self._config.authentication_policy, + self._config.custom_hook_policy, + self._config.logging_policy, + policies.DistributedTracingPolicy(**kwargs), + policies.SensitiveHeaderCleanupPolicy(**kwargs) if self._config.redirect_policy else None, + self._config.http_logging_policy, + ] + self._client: PipelineClient = PipelineClient(base_url=_endpoint, policies=_policies, **kwargs) + + self._serialize = Serializer() + self._deserialize = Deserializer() + self._serialize.client_side_validation = False + + def send_request(self, request: HttpRequest, *, stream: bool = False, **kwargs: Any) -> HttpResponse: + """Runs the network request through the client's chained policies. + + >>> from azure.core.rest import HttpRequest + >>> request = HttpRequest("GET", "https://www.example.org/") + + >>> response = client.send_request(request) + + + For more information on this code flow, see https://aka.ms/azsdk/dpcodegen/python/send_request + + :param request: The network request you want to make. Required. + :type request: ~azure.core.rest.HttpRequest + :keyword bool stream: Whether the response payload will be streamed. Defaults to False. + :return: The response of your network call. Does not do error handling on your response. + :rtype: ~azure.core.rest.HttpResponse + """ + + request_copy = deepcopy(request) + path_format_arguments = { + "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), + } + + request_copy.url = self._client.format_url(request_copy.url, **path_format_arguments) + return self._client.send_request(request_copy, stream=stream, **kwargs) # type: ignore + + def close(self) -> None: + self._client.close() + + def __enter__(self) -> Self: + self._client.__enter__() + return self + + def __exit__(self, *exc_details: Any) -> None: + self._client.__exit__(*exc_details) + + +class ConversationAdministrationClient(ConversationAdministrationClientOperationsMixin): + """ConversationAdministrationClient. + + :param endpoint: The communication resource, for example + `https://my-resource.communication.azure.com `_. + Required. + :type endpoint: str + :param credential: Credential used to authenticate requests to the service. Is either a token + credential type or a key credential type. Required. + :type credential: ~azure.core.credentials.TokenCredential or + ~azure.core.credentials.AzureKeyCredential or ~azure.core.credentials.AzureKeyCredential + :keyword api_version: The API version to use for this operation. Default value is + "2025-04-01-preview". Note that overriding this default value may result in unsupported + behavior. + :paramtype api_version: str + """ + + def __init__(self, endpoint: str, credential: Union["TokenCredential", AzureKeyCredential], **kwargs: Any) -> None: + _endpoint = "{endpoint}" + self._config = ConversationAdministrationClientConfiguration(endpoint=endpoint, credential=credential, **kwargs) + + _policies = kwargs.pop("policies", None) + if _policies is None: + _policies = [ + policies.RequestIdPolicy(**kwargs), + self._config.headers_policy, + self._config.user_agent_policy, + self._config.proxy_policy, + policies.ContentDecodePolicy(**kwargs), + self._config.redirect_policy, + self._config.retry_policy, + self._config.authentication_policy, + self._config.custom_hook_policy, + self._config.logging_policy, + policies.DistributedTracingPolicy(**kwargs), + policies.SensitiveHeaderCleanupPolicy(**kwargs) if self._config.redirect_policy else None, + self._config.http_logging_policy, + ] + self._client: PipelineClient = PipelineClient(base_url=_endpoint, policies=_policies, **kwargs) + + self._serialize = Serializer() + self._deserialize = Deserializer() + self._serialize.client_side_validation = False + + def send_request(self, request: HttpRequest, *, stream: bool = False, **kwargs: Any) -> HttpResponse: + """Runs the network request through the client's chained policies. + + >>> from azure.core.rest import HttpRequest + >>> request = HttpRequest("GET", "https://www.example.org/") + + >>> response = client.send_request(request) + + + For more information on this code flow, see https://aka.ms/azsdk/dpcodegen/python/send_request + + :param request: The network request you want to make. Required. + :type request: ~azure.core.rest.HttpRequest + :keyword bool stream: Whether the response payload will be streamed. Defaults to False. + :return: The response of your network call. Does not do error handling on your response. + :rtype: ~azure.core.rest.HttpResponse + """ + + request_copy = deepcopy(request) + path_format_arguments = { + "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), + } + + request_copy.url = self._client.format_url(request_copy.url, **path_format_arguments) + return self._client.send_request(request_copy, stream=stream, **kwargs) # type: ignore + + def close(self) -> None: + self._client.close() + + def __enter__(self) -> Self: + self._client.__enter__() + return self + + def __exit__(self, *exc_details: Any) -> None: + self._client.__exit__(*exc_details) + + +class ConversationThreadClient(ConversationThreadClientOperationsMixin): + """ConversationThreadClient. + + :param endpoint: The communication resource, for example + `https://my-resource.communication.azure.com `_. + Required. + :type endpoint: str + :param credential: Credential used to authenticate requests to the service. Is either a token + credential type or a key credential type. Required. + :type credential: ~azure.core.credentials.TokenCredential or + ~azure.core.credentials.AzureKeyCredential or ~azure.core.credentials.AzureKeyCredential + :keyword api_version: The API version to use for this operation. Default value is + "2025-04-01-preview". Note that overriding this default value may result in unsupported + behavior. + :paramtype api_version: str + """ + + def __init__(self, endpoint: str, credential: Union["TokenCredential", AzureKeyCredential], **kwargs: Any) -> None: + _endpoint = "{endpoint}" + self._config = ConversationThreadClientConfiguration(endpoint=endpoint, credential=credential, **kwargs) + _policies = kwargs.pop("policies", None) if _policies is None: _policies = [ diff --git a/sdk/communication/azure-communication-messages/azure/communication/messages/_configuration.py b/sdk/communication/azure-communication-messages/azure/communication/messages/_configuration.py index b573ba282c5a..4d0f8c4f9725 100644 --- a/sdk/communication/azure-communication-messages/azure/communication/messages/_configuration.py +++ b/sdk/communication/azure-communication-messages/azure/communication/messages/_configuration.py @@ -24,20 +24,21 @@ class NotificationMessagesClientConfiguration: # pylint: disable=too-many-insta attributes. :param endpoint: The communication resource, for example - https://my-resource.communication.azure.com. Required. + `https://my-resource.communication.azure.com `_. + Required. :type endpoint: str :param credential: Credential used to authenticate requests to the service. Is either a token - credential type or a AzureKeyCredential type. Required. + credential type or a key credential type. Required. :type credential: ~azure.core.credentials.TokenCredential or - ~azure.core.credentials.AzureKeyCredential + ~azure.core.credentials.AzureKeyCredential or ~azure.core.credentials.AzureKeyCredential :keyword api_version: The API version to use for this operation. Default value is - "2025-01-15-preview". Note that overriding this default value may result in unsupported + "2025-04-01-preview". Note that overriding this default value may result in unsupported behavior. :paramtype api_version: str """ def __init__(self, endpoint: str, credential: Union["TokenCredential", AzureKeyCredential], **kwargs: Any) -> None: - api_version: str = kwargs.pop("api_version", "2025-01-15-preview") + api_version: str = kwargs.pop("api_version", "2025-04-01-preview") if endpoint is None: raise ValueError("Parameter 'endpoint' must not be None.") @@ -57,6 +58,8 @@ def _infer_policy(self, **kwargs): return policies.BearerTokenCredentialPolicy(self.credential, *self.credential_scopes, **kwargs) if isinstance(self.credential, AzureKeyCredential): return policies.AzureKeyCredentialPolicy(self.credential, "Authorization", **kwargs) + if isinstance(self.credential, AzureKeyCredential): + return policies.AzureKeyCredentialPolicy(self.credential, "Authorization", prefix="Bearer", **kwargs) raise TypeError(f"Unsupported credential: {self.credential}") def _configure(self, **kwargs: Any) -> None: @@ -80,20 +83,80 @@ class MessageTemplateClientConfiguration: # pylint: disable=too-many-instance-a attributes. :param endpoint: The communication resource, for example - https://my-resource.communication.azure.com. Required. + `https://my-resource.communication.azure.com `_. + Required. + :type endpoint: str + :param credential: Credential used to authenticate requests to the service. Is either a token + credential type or a key credential type. Required. + :type credential: ~azure.core.credentials.TokenCredential or + ~azure.core.credentials.AzureKeyCredential or ~azure.core.credentials.AzureKeyCredential + :keyword api_version: The API version to use for this operation. Default value is + "2025-04-01-preview". Note that overriding this default value may result in unsupported + behavior. + :paramtype api_version: str + """ + + def __init__(self, endpoint: str, credential: Union["TokenCredential", AzureKeyCredential], **kwargs: Any) -> None: + api_version: str = kwargs.pop("api_version", "2025-04-01-preview") + + if endpoint is None: + raise ValueError("Parameter 'endpoint' must not be None.") + if credential is None: + raise ValueError("Parameter 'credential' must not be None.") + + self.endpoint = endpoint + self.credential = credential + self.api_version = api_version + self.credential_scopes = kwargs.pop("credential_scopes", ["https://communication.azure.com/.default"]) + kwargs.setdefault("sdk_moniker", "communication-messages/{}".format(VERSION)) + self.polling_interval = kwargs.get("polling_interval", 30) + self._configure(**kwargs) + + def _infer_policy(self, **kwargs): + if hasattr(self.credential, "get_token"): + return policies.BearerTokenCredentialPolicy(self.credential, *self.credential_scopes, **kwargs) + if isinstance(self.credential, AzureKeyCredential): + return policies.AzureKeyCredentialPolicy(self.credential, "Authorization", **kwargs) + if isinstance(self.credential, AzureKeyCredential): + return policies.AzureKeyCredentialPolicy(self.credential, "Authorization", prefix="Bearer", **kwargs) + raise TypeError(f"Unsupported credential: {self.credential}") + + def _configure(self, **kwargs: Any) -> None: + self.user_agent_policy = kwargs.get("user_agent_policy") or policies.UserAgentPolicy(**kwargs) + self.headers_policy = kwargs.get("headers_policy") or policies.HeadersPolicy(**kwargs) + self.proxy_policy = kwargs.get("proxy_policy") or policies.ProxyPolicy(**kwargs) + self.logging_policy = kwargs.get("logging_policy") or policies.NetworkTraceLoggingPolicy(**kwargs) + self.http_logging_policy = kwargs.get("http_logging_policy") or policies.HttpLoggingPolicy(**kwargs) + self.custom_hook_policy = kwargs.get("custom_hook_policy") or policies.CustomHookPolicy(**kwargs) + self.redirect_policy = kwargs.get("redirect_policy") or policies.RedirectPolicy(**kwargs) + self.retry_policy = kwargs.get("retry_policy") or policies.RetryPolicy(**kwargs) + self.authentication_policy = kwargs.get("authentication_policy") + if self.credential and not self.authentication_policy: + self.authentication_policy = self._infer_policy(**kwargs) + + +class ConversationAdministrationClientConfiguration: # pylint: disable=too-many-instance-attributes,name-too-long + """Configuration for ConversationAdministrationClient. + + Note that all parameters used to create this instance are saved as instance + attributes. + + :param endpoint: The communication resource, for example + `https://my-resource.communication.azure.com `_. + Required. :type endpoint: str :param credential: Credential used to authenticate requests to the service. Is either a token - credential type or a AzureKeyCredential type. Required. + credential type or a key credential type. Required. :type credential: ~azure.core.credentials.TokenCredential or - ~azure.core.credentials.AzureKeyCredential + ~azure.core.credentials.AzureKeyCredential or ~azure.core.credentials.AzureKeyCredential :keyword api_version: The API version to use for this operation. Default value is - "2025-01-15-preview". Note that overriding this default value may result in unsupported + "2025-04-01-preview". Note that overriding this default value may result in unsupported behavior. :paramtype api_version: str """ def __init__(self, endpoint: str, credential: Union["TokenCredential", AzureKeyCredential], **kwargs: Any) -> None: - api_version: str = kwargs.pop("api_version", "2025-01-15-preview") + api_version: str = kwargs.pop("api_version", "2025-04-01-preview") if endpoint is None: raise ValueError("Parameter 'endpoint' must not be None.") @@ -113,6 +176,67 @@ def _infer_policy(self, **kwargs): return policies.BearerTokenCredentialPolicy(self.credential, *self.credential_scopes, **kwargs) if isinstance(self.credential, AzureKeyCredential): return policies.AzureKeyCredentialPolicy(self.credential, "Authorization", **kwargs) + if isinstance(self.credential, AzureKeyCredential): + return policies.AzureKeyCredentialPolicy(self.credential, "Authorization", prefix="Bearer", **kwargs) + raise TypeError(f"Unsupported credential: {self.credential}") + + def _configure(self, **kwargs: Any) -> None: + self.user_agent_policy = kwargs.get("user_agent_policy") or policies.UserAgentPolicy(**kwargs) + self.headers_policy = kwargs.get("headers_policy") or policies.HeadersPolicy(**kwargs) + self.proxy_policy = kwargs.get("proxy_policy") or policies.ProxyPolicy(**kwargs) + self.logging_policy = kwargs.get("logging_policy") or policies.NetworkTraceLoggingPolicy(**kwargs) + self.http_logging_policy = kwargs.get("http_logging_policy") or policies.HttpLoggingPolicy(**kwargs) + self.custom_hook_policy = kwargs.get("custom_hook_policy") or policies.CustomHookPolicy(**kwargs) + self.redirect_policy = kwargs.get("redirect_policy") or policies.RedirectPolicy(**kwargs) + self.retry_policy = kwargs.get("retry_policy") or policies.RetryPolicy(**kwargs) + self.authentication_policy = kwargs.get("authentication_policy") + if self.credential and not self.authentication_policy: + self.authentication_policy = self._infer_policy(**kwargs) + + +class ConversationThreadClientConfiguration: # pylint: disable=too-many-instance-attributes + """Configuration for ConversationThreadClient. + + Note that all parameters used to create this instance are saved as instance + attributes. + + :param endpoint: The communication resource, for example + `https://my-resource.communication.azure.com `_. + Required. + :type endpoint: str + :param credential: Credential used to authenticate requests to the service. Is either a token + credential type or a key credential type. Required. + :type credential: ~azure.core.credentials.TokenCredential or + ~azure.core.credentials.AzureKeyCredential or ~azure.core.credentials.AzureKeyCredential + :keyword api_version: The API version to use for this operation. Default value is + "2025-04-01-preview". Note that overriding this default value may result in unsupported + behavior. + :paramtype api_version: str + """ + + def __init__(self, endpoint: str, credential: Union["TokenCredential", AzureKeyCredential], **kwargs: Any) -> None: + api_version: str = kwargs.pop("api_version", "2025-04-01-preview") + + if endpoint is None: + raise ValueError("Parameter 'endpoint' must not be None.") + if credential is None: + raise ValueError("Parameter 'credential' must not be None.") + + self.endpoint = endpoint + self.credential = credential + self.api_version = api_version + self.credential_scopes = kwargs.pop("credential_scopes", ["https://communication.azure.com/.default"]) + kwargs.setdefault("sdk_moniker", "communication-messages/{}".format(VERSION)) + self.polling_interval = kwargs.get("polling_interval", 30) + self._configure(**kwargs) + + def _infer_policy(self, **kwargs): + if hasattr(self.credential, "get_token"): + return policies.BearerTokenCredentialPolicy(self.credential, *self.credential_scopes, **kwargs) + if isinstance(self.credential, AzureKeyCredential): + return policies.AzureKeyCredentialPolicy(self.credential, "Authorization", **kwargs) + if isinstance(self.credential, AzureKeyCredential): + return policies.AzureKeyCredentialPolicy(self.credential, "Authorization", prefix="Bearer", **kwargs) raise TypeError(f"Unsupported credential: {self.credential}") def _configure(self, **kwargs: Any) -> None: diff --git a/sdk/communication/azure-communication-messages/azure/communication/messages/_operations/__init__.py b/sdk/communication/azure-communication-messages/azure/communication/messages/_operations/__init__.py index 5e78e7b2ee7c..95e745bec65c 100644 --- a/sdk/communication/azure-communication-messages/azure/communication/messages/_operations/__init__.py +++ b/sdk/communication/azure-communication-messages/azure/communication/messages/_operations/__init__.py @@ -14,6 +14,8 @@ from ._operations import NotificationMessagesClientOperationsMixin # type: ignore from ._operations import MessageTemplateClientOperationsMixin # type: ignore +from ._operations import ConversationAdministrationClientOperationsMixin # type: ignore +from ._operations import ConversationThreadClientOperationsMixin # type: ignore from ._patch import __all__ as _patch_all from ._patch import * @@ -22,6 +24,8 @@ __all__ = [ "NotificationMessagesClientOperationsMixin", "MessageTemplateClientOperationsMixin", + "ConversationAdministrationClientOperationsMixin", + "ConversationThreadClientOperationsMixin", ] __all__.extend([p for p in _patch_all if p not in __all__]) # pyright: ignore _patch_sdk() diff --git a/sdk/communication/azure-communication-messages/azure/communication/messages/_operations/_operations.py b/sdk/communication/azure-communication-messages/azure/communication/messages/_operations/_operations.py index b5eedc436115..bb09624d661c 100644 --- a/sdk/communication/azure-communication-messages/azure/communication/messages/_operations/_operations.py +++ b/sdk/communication/azure-communication-messages/azure/communication/messages/_operations/_operations.py @@ -1,3 +1,4 @@ +# pylint: disable=too-many-lines # coding=utf-8 # -------------------------------------------------------------------------- # Copyright (c) Microsoft Corporation. All rights reserved. @@ -5,14 +6,15 @@ # Code generated by Microsoft (R) Python Code Generator. # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- +from collections.abc import MutableMapping import datetime from io import IOBase import json -import sys from typing import Any, Callable, Dict, IO, Iterable, Iterator, List, Optional, TypeVar, Union, overload import urllib.parse import uuid +from azure.core import PipelineClient from azure.core.exceptions import ( ClientAuthenticationError, HttpResponseError, @@ -30,17 +32,21 @@ from azure.core.utils import case_insensitive_dict from .. import models as _models -from .._model_base import SdkJSONEncoder, _deserialize -from .._serialization import Serializer -from .._vendor import MessageTemplateClientMixinABC, NotificationMessagesClientMixinABC - -if sys.version_info >= (3, 9): - from collections.abc import MutableMapping -else: - from typing import MutableMapping # type: ignore -JSON = MutableMapping[str, Any] # pylint: disable=unsubscriptable-object +from .._configuration import ( + ConversationAdministrationClientConfiguration, + ConversationThreadClientConfiguration, + MessageTemplateClientConfiguration, + NotificationMessagesClientConfiguration, +) +from .._utils.model_base import SdkJSONEncoder, _deserialize +from .._utils.serialization import Serializer +from .._utils.utils import ClientMixinABC +from .._validation import api_version_validation + +JSON = MutableMapping[str, Any] T = TypeVar("T") ClsType = Optional[Callable[[PipelineResponse[HttpRequest, HttpResponse], T, Dict[str, Any]], Any]] +_Unset: Any = object() _SERIALIZER = Serializer() _SERIALIZER.client_side_validation = False @@ -51,7 +57,7 @@ def build_notification_messages_send_request(**kwargs: Any) -> HttpRequest: _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) - api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2025-01-15-preview")) + api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2025-04-01-preview")) accept = _headers.pop("Accept", "application/json") # Construct URL @@ -80,7 +86,7 @@ def build_notification_messages_download_media_request( # pylint: disable=name- _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) - api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2025-01-15-preview")) + api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2025-04-01-preview")) accept = _headers.pop("Accept", "application/octet-stream") # Construct URL @@ -101,12 +107,12 @@ def build_notification_messages_download_media_request( # pylint: disable=name- def build_message_template_list_templates_request( # pylint: disable=name-too-long - channel_id: str, *, maxpagesize: Optional[int] = None, **kwargs: Any + channel_id: str, *, max_page_size: Optional[int] = None, **kwargs: Any ) -> HttpRequest: _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) - api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2025-01-15-preview")) + api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2025-04-01-preview")) accept = _headers.pop("Accept", "application/json") # Construct URL @@ -119,8 +125,8 @@ def build_message_template_list_templates_request( # pylint: disable=name-too-l # Construct parameters _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") - if maxpagesize is not None: - _params["maxpagesize"] = _SERIALIZER.query("maxpagesize", maxpagesize, "int") + if max_page_size is not None: + _params["maxPageSize"] = _SERIALIZER.query("max_page_size", max_page_size, "int") # Construct headers _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") @@ -128,65 +134,2026 @@ def build_message_template_list_templates_request( # pylint: disable=name-too-l return HttpRequest(method="GET", url=_url, params=_params, headers=_headers, **kwargs) -class NotificationMessagesClientOperationsMixin(NotificationMessagesClientMixinABC): # pylint: disable=name-too-long +def build_conversation_administration_create_conversation_request( # pylint: disable=name-too-long + **kwargs: Any, +) -> HttpRequest: + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) + _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) - @overload - def send( - self, body: _models.NotificationContent, *, content_type: str = "application/json", **kwargs: Any - ) -> _models.SendMessageResult: - """Sends a notification message from Business to User. + content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) + api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2025-04-01-preview")) + accept = _headers.pop("Accept", "application/json") - :param body: Details of the message to send. Required. - :type body: ~azure.communication.messages.models.NotificationContent - :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. - Default value is "application/json". - :paramtype content_type: str - :return: SendMessageResult. The SendMessageResult is compatible with MutableMapping - :rtype: ~azure.communication.messages.models.SendMessageResult - :raises ~azure.core.exceptions.HttpResponseError: - """ + # Construct URL + _url = "/messages/conversations" - @overload - def send(self, body: JSON, *, content_type: str = "application/json", **kwargs: Any) -> _models.SendMessageResult: - """Sends a notification message from Business to User. + # Construct parameters + _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") - :param body: Details of the message to send. Required. - :type body: JSON - :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. - Default value is "application/json". - :paramtype content_type: str - :return: SendMessageResult. The SendMessageResult is compatible with MutableMapping - :rtype: ~azure.communication.messages.models.SendMessageResult - :raises ~azure.core.exceptions.HttpResponseError: - """ + # Construct headers + if content_type is not None: + _headers["Content-Type"] = _SERIALIZER.header("content_type", content_type, "str") + _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") - @overload - def send( - self, body: IO[bytes], *, content_type: str = "application/json", **kwargs: Any - ) -> _models.SendMessageResult: - """Sends a notification message from Business to User. + return HttpRequest(method="POST", url=_url, params=_params, headers=_headers, **kwargs) - :param body: Details of the message to send. Required. - :type body: IO[bytes] - :keyword content_type: Body Parameter content-type. Content type parameter for binary body. - Default value is "application/json". - :paramtype content_type: str - :return: SendMessageResult. The SendMessageResult is compatible with MutableMapping - :rtype: ~azure.communication.messages.models.SendMessageResult - :raises ~azure.core.exceptions.HttpResponseError: - """ - @distributed_trace - def send( - self, body: Union[_models.NotificationContent, JSON, IO[bytes]], **kwargs: Any - ) -> _models.SendMessageResult: - """Sends a notification message from Business to User. +def build_conversation_administration_get_conversation_request( # pylint: disable=name-too-long + conversation_id: str, **kwargs: Any +) -> HttpRequest: + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) + _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) - :param body: Details of the message to send. Is one of the following types: - NotificationContent, JSON, IO[bytes] Required. - :type body: ~azure.communication.messages.models.NotificationContent or JSON or IO[bytes] - :return: SendMessageResult. The SendMessageResult is compatible with MutableMapping - :rtype: ~azure.communication.messages.models.SendMessageResult + api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2025-04-01-preview")) + accept = _headers.pop("Accept", "application/json") + + # Construct URL + _url = "/messages/conversations/{conversationId}" + path_format_arguments = { + "conversationId": _SERIALIZER.url("conversation_id", conversation_id, "str"), + } + + _url: str = _url.format(**path_format_arguments) # type: ignore + + # Construct parameters + _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") + + # Construct headers + _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") + + return HttpRequest(method="GET", url=_url, params=_params, headers=_headers, **kwargs) + + +def build_conversation_administration_delete_conversation_request( # pylint: disable=name-too-long + conversation_id: str, **kwargs: Any +) -> HttpRequest: + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) + _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) + + api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2025-04-01-preview")) + accept = _headers.pop("Accept", "application/json") + + # Construct URL + _url = "/messages/conversations/{conversationId}" + path_format_arguments = { + "conversationId": _SERIALIZER.url("conversation_id", conversation_id, "str"), + } + + _url: str = _url.format(**path_format_arguments) # type: ignore + + # Construct parameters + _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") + + # Construct headers + if "Repeatability-Request-ID" not in _headers: + _headers["Repeatability-Request-ID"] = str(uuid.uuid4()) + if "Repeatability-First-Sent" not in _headers: + _headers["Repeatability-First-Sent"] = _SERIALIZER.serialize_data( + datetime.datetime.now(datetime.timezone.utc), "rfc-1123" + ) + _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") + + return HttpRequest(method="DELETE", url=_url, params=_params, headers=_headers, **kwargs) + + +def build_conversation_administration_terminate_conversation_request( # pylint: disable=name-too-long + conversation_id: str, **kwargs: Any +) -> HttpRequest: + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) + _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) + + api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2025-04-01-preview")) + accept = _headers.pop("Accept", "application/json") + + # Construct URL + _url = "/messages/conversations/{conversationId}:terminate" + path_format_arguments = { + "conversationId": _SERIALIZER.url("conversation_id", conversation_id, "str"), + } + + _url: str = _url.format(**path_format_arguments) # type: ignore + + # Construct parameters + _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") + + # Construct headers + if "Repeatability-Request-ID" not in _headers: + _headers["Repeatability-Request-ID"] = str(uuid.uuid4()) + if "Repeatability-First-Sent" not in _headers: + _headers["Repeatability-First-Sent"] = _SERIALIZER.serialize_data( + datetime.datetime.now(datetime.timezone.utc), "rfc-1123" + ) + _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") + + return HttpRequest(method="POST", url=_url, params=_params, headers=_headers, **kwargs) + + +def build_conversation_administration_list_conversations_request( # pylint: disable=name-too-long + *, + max_page_size: Optional[int] = None, + participant_id: Optional[str] = None, + channel_id: Optional[str] = None, + **kwargs: Any, +) -> HttpRequest: + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) + _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) + + api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2025-04-01-preview")) + accept = _headers.pop("Accept", "application/json") + + # Construct URL + _url = "/messages/conversations" + + # Construct parameters + _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") + if max_page_size is not None: + _params["maxPageSize"] = _SERIALIZER.query("max_page_size", max_page_size, "int") + if participant_id is not None: + _params["participantId"] = _SERIALIZER.query("participant_id", participant_id, "str") + if channel_id is not None: + _params["channelId"] = _SERIALIZER.query("channel_id", channel_id, "str") + + # Construct headers + _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") + + return HttpRequest(method="GET", url=_url, params=_params, headers=_headers, **kwargs) + + +def build_conversation_administration_list_messages_request( # pylint: disable=name-too-long + conversation_id: str, *, max_page_size: Optional[int] = None, participant_id: Optional[str] = None, **kwargs: Any +) -> HttpRequest: + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) + _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) + + api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2025-04-01-preview")) + accept = _headers.pop("Accept", "application/json") + + # Construct URL + _url = "/messages/conversations/{conversationId}/messages" + path_format_arguments = { + "conversationId": _SERIALIZER.url("conversation_id", conversation_id, "str"), + } + + _url: str = _url.format(**path_format_arguments) # type: ignore + + # Construct parameters + _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") + if max_page_size is not None: + _params["maxPageSize"] = _SERIALIZER.query("max_page_size", max_page_size, "int") + if participant_id is not None: + _params["participantId"] = _SERIALIZER.query("participant_id", participant_id, "str") + + # Construct headers + _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") + + return HttpRequest(method="GET", url=_url, params=_params, headers=_headers, **kwargs) + + +def build_conversation_administration_add_participants_request( # pylint: disable=name-too-long + conversation_id: str, **kwargs: Any +) -> HttpRequest: + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) + _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) + + content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) + api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2025-04-01-preview")) + accept = _headers.pop("Accept", "application/json") + + # Construct URL + _url = "/messages/conversations/{conversationId}/participants:add" + path_format_arguments = { + "conversationId": _SERIALIZER.url("conversation_id", conversation_id, "str"), + } + + _url: str = _url.format(**path_format_arguments) # type: ignore + + # Construct parameters + _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") + + # Construct headers + if "Repeatability-Request-ID" not in _headers: + _headers["Repeatability-Request-ID"] = str(uuid.uuid4()) + if "Repeatability-First-Sent" not in _headers: + _headers["Repeatability-First-Sent"] = _SERIALIZER.serialize_data( + datetime.datetime.now(datetime.timezone.utc), "rfc-1123" + ) + if content_type is not None: + _headers["Content-Type"] = _SERIALIZER.header("content_type", content_type, "str") + _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") + + return HttpRequest(method="POST", url=_url, params=_params, headers=_headers, **kwargs) + + +def build_conversation_administration_remove_participants_request( # pylint: disable=name-too-long + conversation_id: str, **kwargs: Any +) -> HttpRequest: + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) + _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) + + content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) + api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2025-04-01-preview")) + accept = _headers.pop("Accept", "application/json") + + # Construct URL + _url = "/messages/conversations/{conversationId}/participants:remove" + path_format_arguments = { + "conversationId": _SERIALIZER.url("conversation_id", conversation_id, "str"), + } + + _url: str = _url.format(**path_format_arguments) # type: ignore + + # Construct parameters + _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") + + # Construct headers + if "Repeatability-Request-ID" not in _headers: + _headers["Repeatability-Request-ID"] = str(uuid.uuid4()) + if "Repeatability-First-Sent" not in _headers: + _headers["Repeatability-First-Sent"] = _SERIALIZER.serialize_data( + datetime.datetime.now(datetime.timezone.utc), "rfc-1123" + ) + if content_type is not None: + _headers["Content-Type"] = _SERIALIZER.header("content_type", content_type, "str") + _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") + + return HttpRequest(method="POST", url=_url, params=_params, headers=_headers, **kwargs) + + +def build_conversation_administration_analyze_conversation_request( # pylint: disable=name-too-long + conversation_id: str, **kwargs: Any +) -> HttpRequest: + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) + _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) + + api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2025-04-01-preview")) + accept = _headers.pop("Accept", "application/json") + + # Construct URL + _url = "/messages/conversations/{conversationId}:analyze" + path_format_arguments = { + "conversationId": _SERIALIZER.url("conversation_id", conversation_id, "str"), + } + + _url: str = _url.format(**path_format_arguments) # type: ignore + + # Construct parameters + _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") + + # Construct headers + if "Repeatability-Request-ID" not in _headers: + _headers["Repeatability-Request-ID"] = str(uuid.uuid4()) + if "Repeatability-First-Sent" not in _headers: + _headers["Repeatability-First-Sent"] = _SERIALIZER.serialize_data( + datetime.datetime.now(datetime.timezone.utc), "rfc-1123" + ) + _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") + + return HttpRequest(method="POST", url=_url, params=_params, headers=_headers, **kwargs) + + +def build_conversation_thread_add_participants_request( # pylint: disable=name-too-long + conversation_id: str, **kwargs: Any +) -> HttpRequest: + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) + _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) + + content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) + api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2025-04-01-preview")) + accept = _headers.pop("Accept", "application/json") + + # Construct URL + _url = "/messages/conversations/{conversationId}/participants:add" + path_format_arguments = { + "conversationId": _SERIALIZER.url("conversation_id", conversation_id, "str"), + } + + _url: str = _url.format(**path_format_arguments) # type: ignore + + # Construct parameters + _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") + + # Construct headers + if "Repeatability-Request-ID" not in _headers: + _headers["Repeatability-Request-ID"] = str(uuid.uuid4()) + if "Repeatability-First-Sent" not in _headers: + _headers["Repeatability-First-Sent"] = _SERIALIZER.serialize_data( + datetime.datetime.now(datetime.timezone.utc), "rfc-1123" + ) + if content_type is not None: + _headers["Content-Type"] = _SERIALIZER.header("content_type", content_type, "str") + _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") + + return HttpRequest(method="POST", url=_url, params=_params, headers=_headers, **kwargs) + + +def build_conversation_thread_remove_participants_request( # pylint: disable=name-too-long + conversation_id: str, **kwargs: Any +) -> HttpRequest: + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) + _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) + + content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) + api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2025-04-01-preview")) + accept = _headers.pop("Accept", "application/json") + + # Construct URL + _url = "/messages/conversations/{conversationId}/participants:remove" + path_format_arguments = { + "conversationId": _SERIALIZER.url("conversation_id", conversation_id, "str"), + } + + _url: str = _url.format(**path_format_arguments) # type: ignore + + # Construct parameters + _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") + + # Construct headers + if "Repeatability-Request-ID" not in _headers: + _headers["Repeatability-Request-ID"] = str(uuid.uuid4()) + if "Repeatability-First-Sent" not in _headers: + _headers["Repeatability-First-Sent"] = _SERIALIZER.serialize_data( + datetime.datetime.now(datetime.timezone.utc), "rfc-1123" + ) + if content_type is not None: + _headers["Content-Type"] = _SERIALIZER.header("content_type", content_type, "str") + _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") + + return HttpRequest(method="POST", url=_url, params=_params, headers=_headers, **kwargs) + + +def build_conversation_thread_list_conversations_request( # pylint: disable=name-too-long + *, + max_page_size: Optional[int] = None, + participant_id: Optional[str] = None, + channel_id: Optional[str] = None, + **kwargs: Any, +) -> HttpRequest: + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) + _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) + + api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2025-04-01-preview")) + accept = _headers.pop("Accept", "application/json") + + # Construct URL + _url = "/messages/conversations" + + # Construct parameters + _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") + if max_page_size is not None: + _params["maxPageSize"] = _SERIALIZER.query("max_page_size", max_page_size, "int") + if participant_id is not None: + _params["participantId"] = _SERIALIZER.query("participant_id", participant_id, "str") + if channel_id is not None: + _params["channelId"] = _SERIALIZER.query("channel_id", channel_id, "str") + + # Construct headers + _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") + + return HttpRequest(method="GET", url=_url, params=_params, headers=_headers, **kwargs) + + +def build_conversation_thread_list_messages_request( # pylint: disable=name-too-long + conversation_id: str, *, max_page_size: Optional[int] = None, participant_id: Optional[str] = None, **kwargs: Any +) -> HttpRequest: + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) + _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) + + api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2025-04-01-preview")) + accept = _headers.pop("Accept", "application/json") + + # Construct URL + _url = "/messages/conversations/{conversationId}/messages" + path_format_arguments = { + "conversationId": _SERIALIZER.url("conversation_id", conversation_id, "str"), + } + + _url: str = _url.format(**path_format_arguments) # type: ignore + + # Construct parameters + _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") + if max_page_size is not None: + _params["maxPageSize"] = _SERIALIZER.query("max_page_size", max_page_size, "int") + if participant_id is not None: + _params["participantId"] = _SERIALIZER.query("participant_id", participant_id, "str") + + # Construct headers + _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") + + return HttpRequest(method="GET", url=_url, params=_params, headers=_headers, **kwargs) + + +def build_conversation_thread_send_message_request( # pylint: disable=name-too-long + conversation_id: str, **kwargs: Any +) -> HttpRequest: + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) + _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) + + content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) + api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2025-04-01-preview")) + accept = _headers.pop("Accept", "application/json") + + # Construct URL + _url = "/messages/conversations/{conversationId}/messages:send" + path_format_arguments = { + "conversationId": _SERIALIZER.url("conversation_id", conversation_id, "str"), + } + + _url: str = _url.format(**path_format_arguments) # type: ignore + + # Construct parameters + _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") + + # Construct headers + if "Repeatability-Request-ID" not in _headers: + _headers["Repeatability-Request-ID"] = str(uuid.uuid4()) + if "Repeatability-First-Sent" not in _headers: + _headers["Repeatability-First-Sent"] = _SERIALIZER.serialize_data( + datetime.datetime.now(datetime.timezone.utc), "rfc-1123" + ) + if content_type is not None: + _headers["Content-Type"] = _SERIALIZER.header("content_type", content_type, "str") + _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") + + return HttpRequest(method="POST", url=_url, params=_params, headers=_headers, **kwargs) + + +def build_conversation_thread_analyze_conversation_request( # pylint: disable=name-too-long + conversation_id: str, **kwargs: Any +) -> HttpRequest: + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) + _params = case_insensitive_dict(kwargs.pop("params", {}) or {}) + + api_version: str = kwargs.pop("api_version", _params.pop("api-version", "2025-04-01-preview")) + accept = _headers.pop("Accept", "application/json") + + # Construct URL + _url = "/messages/conversations/{conversationId}:analyze" + path_format_arguments = { + "conversationId": _SERIALIZER.url("conversation_id", conversation_id, "str"), + } + + _url: str = _url.format(**path_format_arguments) # type: ignore + + # Construct parameters + _params["api-version"] = _SERIALIZER.query("api_version", api_version, "str") + + # Construct headers + if "Repeatability-Request-ID" not in _headers: + _headers["Repeatability-Request-ID"] = str(uuid.uuid4()) + if "Repeatability-First-Sent" not in _headers: + _headers["Repeatability-First-Sent"] = _SERIALIZER.serialize_data( + datetime.datetime.now(datetime.timezone.utc), "rfc-1123" + ) + _headers["Accept"] = _SERIALIZER.header("accept", accept, "str") + + return HttpRequest(method="POST", url=_url, params=_params, headers=_headers, **kwargs) + + +class NotificationMessagesClientOperationsMixin( # pylint: disable=name-too-long + ClientMixinABC[PipelineClient[HttpRequest, HttpResponse], NotificationMessagesClientConfiguration] +): + + @overload + def send( + self, body: _models.NotificationContent, *, content_type: str = "application/json", **kwargs: Any + ) -> _models.SendMessageResult: + """Sends a notification message from Business to User. + + :param body: Details of the message to send. Required. + :type body: ~azure.communication.messages.models.NotificationContent + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/json". + :paramtype content_type: str + :return: SendMessageResult. The SendMessageResult is compatible with MutableMapping + :rtype: ~azure.communication.messages.models.SendMessageResult + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @overload + def send(self, body: JSON, *, content_type: str = "application/json", **kwargs: Any) -> _models.SendMessageResult: + """Sends a notification message from Business to User. + + :param body: Details of the message to send. Required. + :type body: JSON + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/json". + :paramtype content_type: str + :return: SendMessageResult. The SendMessageResult is compatible with MutableMapping + :rtype: ~azure.communication.messages.models.SendMessageResult + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @overload + def send( + self, body: IO[bytes], *, content_type: str = "application/json", **kwargs: Any + ) -> _models.SendMessageResult: + """Sends a notification message from Business to User. + + :param body: Details of the message to send. Required. + :type body: IO[bytes] + :keyword content_type: Body Parameter content-type. Content type parameter for binary body. + Default value is "application/json". + :paramtype content_type: str + :return: SendMessageResult. The SendMessageResult is compatible with MutableMapping + :rtype: ~azure.communication.messages.models.SendMessageResult + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @distributed_trace + def send( + self, body: Union[_models.NotificationContent, JSON, IO[bytes]], **kwargs: Any + ) -> _models.SendMessageResult: + """Sends a notification message from Business to User. + + :param body: Details of the message to send. Is one of the following types: + NotificationContent, JSON, IO[bytes] Required. + :type body: ~azure.communication.messages.models.NotificationContent or JSON or IO[bytes] + :return: SendMessageResult. The SendMessageResult is compatible with MutableMapping + :rtype: ~azure.communication.messages.models.SendMessageResult + :raises ~azure.core.exceptions.HttpResponseError: + """ + error_map: MutableMapping = { + 401: ClientAuthenticationError, + 404: ResourceNotFoundError, + 409: ResourceExistsError, + 304: ResourceNotModifiedError, + } + error_map.update(kwargs.pop("error_map", {}) or {}) + + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) + _params = kwargs.pop("params", {}) or {} + + content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) + cls: ClsType[_models.SendMessageResult] = kwargs.pop("cls", None) + + content_type = content_type or "application/json" + _content = None + if isinstance(body, (IOBase, bytes)): + _content = body + else: + _content = json.dumps(body, cls=SdkJSONEncoder, exclude_readonly=True) # type: ignore + + _request = build_notification_messages_send_request( + content_type=content_type, + api_version=self._config.api_version, + content=_content, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + + _stream = kwargs.pop("stream", False) + pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + + response = pipeline_response.http_response + + if response.status_code not in [202]: + if _stream: + try: + response.read() # Load the body in memory and close the socket + except (StreamConsumedError, StreamClosedError): + pass + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + response_headers = {} + response_headers["Repeatability-Result"] = self._deserialize( + "str", response.headers.get("Repeatability-Result") + ) + response_headers["x-ms-client-request-id"] = self._deserialize( + "str", response.headers.get("x-ms-client-request-id") + ) + + if _stream: + deserialized = response.iter_bytes() + else: + deserialized = _deserialize(_models.SendMessageResult, response.json()) + + if cls: + return cls(pipeline_response, deserialized, response_headers) # type: ignore + + return deserialized # type: ignore + + @distributed_trace + def download_media(self, id: str, **kwargs: Any) -> Iterator[bytes]: + """Download the Media payload from a User to Business message. + + :param id: The stream ID. Required. + :type id: str + :return: Iterator[bytes] + :rtype: Iterator[bytes] + :raises ~azure.core.exceptions.HttpResponseError: + """ + error_map: MutableMapping = { + 401: ClientAuthenticationError, + 404: ResourceNotFoundError, + 409: ResourceExistsError, + 304: ResourceNotModifiedError, + } + error_map.update(kwargs.pop("error_map", {}) or {}) + + _headers = kwargs.pop("headers", {}) or {} + _params = kwargs.pop("params", {}) or {} + + cls: ClsType[Iterator[bytes]] = kwargs.pop("cls", None) + + _request = build_notification_messages_download_media_request( + id=id, + api_version=self._config.api_version, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + + _stream = kwargs.pop("stream", True) + pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + + response = pipeline_response.http_response + + if response.status_code not in [200]: + if _stream: + try: + response.read() # Load the body in memory and close the socket + except (StreamConsumedError, StreamClosedError): + pass + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + response_headers = {} + response_headers["x-ms-client-request-id"] = self._deserialize( + "str", response.headers.get("x-ms-client-request-id") + ) + response_headers["content-type"] = self._deserialize("str", response.headers.get("content-type")) + + deserialized = response.iter_bytes() + + if cls: + return cls(pipeline_response, deserialized, response_headers) # type: ignore + + return deserialized # type: ignore + + +class MessageTemplateClientOperationsMixin( + ClientMixinABC[PipelineClient[HttpRequest, HttpResponse], MessageTemplateClientConfiguration] +): + + @distributed_trace + def list_templates( + self, channel_id: str, *, max_page_size: Optional[int] = None, **kwargs: Any + ) -> Iterable["_models.MessageTemplateItem"]: + """List all templates for given Azure Communication Services channel. + + :param channel_id: The registration ID of the channel. Required. + :type channel_id: str + :keyword max_page_size: Number of objects to return per page. Default value is None. + :paramtype max_page_size: int + :return: An iterator like instance of MessageTemplateItem + :rtype: ~azure.core.paging.ItemPaged[~azure.communication.messages.models.MessageTemplateItem] + :raises ~azure.core.exceptions.HttpResponseError: + """ + _headers = kwargs.pop("headers", {}) or {} + _params = kwargs.pop("params", {}) or {} + + cls: ClsType[List[_models.MessageTemplateItem]] = kwargs.pop("cls", None) + + error_map: MutableMapping = { + 401: ClientAuthenticationError, + 404: ResourceNotFoundError, + 409: ResourceExistsError, + 304: ResourceNotModifiedError, + } + error_map.update(kwargs.pop("error_map", {}) or {}) + + def prepare_request(next_link=None): + if not next_link: + + _request = build_message_template_list_templates_request( + channel_id=channel_id, + max_page_size=max_page_size, + api_version=self._config.api_version, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url( + "self._config.endpoint", self._config.endpoint, "str", skip_quote=True + ), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + + else: + # make call to next link with the client's api-version + _parsed_next_link = urllib.parse.urlparse(next_link) + _next_request_params = case_insensitive_dict( + { + key: [urllib.parse.quote(v) for v in value] + for key, value in urllib.parse.parse_qs(_parsed_next_link.query).items() + } + ) + _next_request_params["api-version"] = self._config.api_version + _request = HttpRequest( + "GET", urllib.parse.urljoin(next_link, _parsed_next_link.path), params=_next_request_params + ) + path_format_arguments = { + "endpoint": self._serialize.url( + "self._config.endpoint", self._config.endpoint, "str", skip_quote=True + ), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + + return _request + + def extract_data(pipeline_response): + deserialized = pipeline_response.http_response.json() + list_of_elem = _deserialize(List[_models.MessageTemplateItem], deserialized.get("value", [])) + if cls: + list_of_elem = cls(list_of_elem) # type: ignore + return deserialized.get("nextLink") or None, iter(list_of_elem) + + def get_next(next_link=None): + _request = prepare_request(next_link) + + _stream = False + pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + return pipeline_response + + return ItemPaged(get_next, extract_data) + + +class ConversationAdministrationClientOperationsMixin( # pylint: disable=name-too-long + ClientMixinABC[PipelineClient[HttpRequest, HttpResponse], ConversationAdministrationClientConfiguration] +): + + @overload + def create_conversation( + self, + *, + conversation: _models.CommunicationConversation, + content_type: str = "application/json", + initial_message: Optional[_models.Message] = None, + **kwargs: Any, + ) -> _models.CommunicationConversation: + """Creates a new conversation. This is only for create operation. + + :keyword conversation: The conversation details. Required. + :paramtype conversation: ~azure.communication.messages.models.CommunicationConversation + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/json". + :paramtype content_type: str + :keyword initial_message: An initial message within the conversation. Default value is None. + :paramtype initial_message: ~azure.communication.messages.models.Message + :return: CommunicationConversation. The CommunicationConversation is compatible with + MutableMapping + :rtype: ~azure.communication.messages.models.CommunicationConversation + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @overload + def create_conversation( + self, body: JSON, *, content_type: str = "application/json", **kwargs: Any + ) -> _models.CommunicationConversation: + """Creates a new conversation. This is only for create operation. + + :param body: Required. + :type body: JSON + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/json". + :paramtype content_type: str + :return: CommunicationConversation. The CommunicationConversation is compatible with + MutableMapping + :rtype: ~azure.communication.messages.models.CommunicationConversation + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @overload + def create_conversation( + self, body: IO[bytes], *, content_type: str = "application/json", **kwargs: Any + ) -> _models.CommunicationConversation: + """Creates a new conversation. This is only for create operation. + + :param body: Required. + :type body: IO[bytes] + :keyword content_type: Body Parameter content-type. Content type parameter for binary body. + Default value is "application/json". + :paramtype content_type: str + :return: CommunicationConversation. The CommunicationConversation is compatible with + MutableMapping + :rtype: ~azure.communication.messages.models.CommunicationConversation + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @distributed_trace + @api_version_validation( + method_added_on="2025-04-01-preview", + params_added_on={"2025-04-01-preview": ["endpoint", "api_version", "content_type", "accept"]}, + ) + def create_conversation( + self, + body: Union[JSON, IO[bytes]] = _Unset, + *, + conversation: _models.CommunicationConversation = _Unset, + initial_message: Optional[_models.Message] = None, + **kwargs: Any, + ) -> _models.CommunicationConversation: + """Creates a new conversation. This is only for create operation. + + :param body: Is either a JSON type or a IO[bytes] type. Required. + :type body: JSON or IO[bytes] + :keyword conversation: The conversation details. Required. + :paramtype conversation: ~azure.communication.messages.models.CommunicationConversation + :keyword initial_message: An initial message within the conversation. Default value is None. + :paramtype initial_message: ~azure.communication.messages.models.Message + :return: CommunicationConversation. The CommunicationConversation is compatible with + MutableMapping + :rtype: ~azure.communication.messages.models.CommunicationConversation + :raises ~azure.core.exceptions.HttpResponseError: + """ + error_map: MutableMapping = { + 401: ClientAuthenticationError, + 404: ResourceNotFoundError, + 409: ResourceExistsError, + 304: ResourceNotModifiedError, + } + error_map.update(kwargs.pop("error_map", {}) or {}) + + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) + _params = kwargs.pop("params", {}) or {} + + content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) + cls: ClsType[_models.CommunicationConversation] = kwargs.pop("cls", None) + + if body is _Unset: + if conversation is _Unset: + raise TypeError("missing required argument: conversation") + body = {"conversation": conversation, "initialMessage": initial_message} + body = {k: v for k, v in body.items() if v is not None} + content_type = content_type or "application/json" + _content = None + if isinstance(body, (IOBase, bytes)): + _content = body + else: + _content = json.dumps(body, cls=SdkJSONEncoder, exclude_readonly=True) # type: ignore + + _request = build_conversation_administration_create_conversation_request( + content_type=content_type, + api_version=self._config.api_version, + content=_content, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + + _stream = kwargs.pop("stream", False) + pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + + response = pipeline_response.http_response + + if response.status_code not in [201]: + if _stream: + try: + response.read() # Load the body in memory and close the socket + except (StreamConsumedError, StreamClosedError): + pass + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + if _stream: + deserialized = response.iter_bytes() + else: + deserialized = _deserialize(_models.CommunicationConversation, response.json()) + + if cls: + return cls(pipeline_response, deserialized, {}) # type: ignore + + return deserialized # type: ignore + + @distributed_trace + @api_version_validation( + method_added_on="2025-04-01-preview", + params_added_on={ + "2025-04-01-preview": ["endpoint", "api_version", "conversation_id", "client_request_id", "accept"] + }, + ) + def get_conversation(self, conversation_id: str, **kwargs: Any) -> _models.CommunicationConversation: + """Gets the details of a specific conversation. + + :param conversation_id: The conversation ID. Required. + :type conversation_id: str + :return: CommunicationConversation. The CommunicationConversation is compatible with + MutableMapping + :rtype: ~azure.communication.messages.models.CommunicationConversation + :raises ~azure.core.exceptions.HttpResponseError: + """ + error_map: MutableMapping = { + 401: ClientAuthenticationError, + 404: ResourceNotFoundError, + 409: ResourceExistsError, + 304: ResourceNotModifiedError, + } + error_map.update(kwargs.pop("error_map", {}) or {}) + + _headers = kwargs.pop("headers", {}) or {} + _params = kwargs.pop("params", {}) or {} + + cls: ClsType[_models.CommunicationConversation] = kwargs.pop("cls", None) + + _request = build_conversation_administration_get_conversation_request( + conversation_id=conversation_id, + api_version=self._config.api_version, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + + _stream = kwargs.pop("stream", False) + pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + + response = pipeline_response.http_response + + if response.status_code not in [200]: + if _stream: + try: + response.read() # Load the body in memory and close the socket + except (StreamConsumedError, StreamClosedError): + pass + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + response_headers = {} + response_headers["x-ms-client-request-id"] = self._deserialize( + "str", response.headers.get("x-ms-client-request-id") + ) + + if _stream: + deserialized = response.iter_bytes() + else: + deserialized = _deserialize(_models.CommunicationConversation, response.json()) + + if cls: + return cls(pipeline_response, deserialized, response_headers) # type: ignore + + return deserialized # type: ignore + + @distributed_trace + @api_version_validation( + method_added_on="2025-04-01-preview", + params_added_on={ + "2025-04-01-preview": [ + "endpoint", + "api_version", + "conversation_id", + "repeatability_request_id", + "repeatability_first_sent", + "client_request_id", + "accept", + ] + }, + ) + def delete_conversation( # pylint: disable=inconsistent-return-statements + self, conversation_id: str, **kwargs: Any + ) -> None: + """Deletes a specific conversation. + + :param conversation_id: The conversation ID. Required. + :type conversation_id: str + :return: None + :rtype: None + :raises ~azure.core.exceptions.HttpResponseError: + """ + error_map: MutableMapping = { + 401: ClientAuthenticationError, + 404: ResourceNotFoundError, + 409: ResourceExistsError, + 304: ResourceNotModifiedError, + } + error_map.update(kwargs.pop("error_map", {}) or {}) + + _headers = kwargs.pop("headers", {}) or {} + _params = kwargs.pop("params", {}) or {} + + cls: ClsType[None] = kwargs.pop("cls", None) + + _request = build_conversation_administration_delete_conversation_request( + conversation_id=conversation_id, + api_version=self._config.api_version, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + + _stream = False + pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + + response = pipeline_response.http_response + + if response.status_code not in [204]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + response_headers = {} + response_headers["Repeatability-Result"] = self._deserialize( + "str", response.headers.get("Repeatability-Result") + ) + response_headers["x-ms-client-request-id"] = self._deserialize( + "str", response.headers.get("x-ms-client-request-id") + ) + + if cls: + return cls(pipeline_response, None, response_headers) # type: ignore + + @distributed_trace + @api_version_validation( + method_added_on="2025-04-01-preview", + params_added_on={ + "2025-04-01-preview": [ + "endpoint", + "api_version", + "conversation_id", + "repeatability_request_id", + "repeatability_first_sent", + "client_request_id", + "accept", + ] + }, + ) + def terminate_conversation( # pylint: disable=inconsistent-return-statements + self, conversation_id: str, **kwargs: Any + ) -> None: + """Terminates a specific conversation. + + :param conversation_id: The conversation ID. Required. + :type conversation_id: str + :return: None + :rtype: None + :raises ~azure.core.exceptions.HttpResponseError: + """ + error_map: MutableMapping = { + 401: ClientAuthenticationError, + 404: ResourceNotFoundError, + 409: ResourceExistsError, + 304: ResourceNotModifiedError, + } + error_map.update(kwargs.pop("error_map", {}) or {}) + + _headers = kwargs.pop("headers", {}) or {} + _params = kwargs.pop("params", {}) or {} + + cls: ClsType[None] = kwargs.pop("cls", None) + + _request = build_conversation_administration_terminate_conversation_request( + conversation_id=conversation_id, + api_version=self._config.api_version, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + + _stream = False + pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + response_headers = {} + response_headers["Repeatability-Result"] = self._deserialize( + "str", response.headers.get("Repeatability-Result") + ) + response_headers["x-ms-client-request-id"] = self._deserialize( + "str", response.headers.get("x-ms-client-request-id") + ) + + if cls: + return cls(pipeline_response, None, response_headers) # type: ignore + + @distributed_trace + @api_version_validation( + method_added_on="2025-04-01-preview", + params_added_on={ + "2025-04-01-preview": [ + "endpoint", + "api_version", + "max_page_size", + "participant_id", + "channel_id", + "client_request_id", + "accept", + ] + }, + ) + def list_conversations( + self, + *, + max_page_size: Optional[int] = None, + participant_id: Optional[str] = None, + channel_id: Optional[str] = None, + **kwargs: Any, + ) -> Iterable["_models.CommunicationConversation"]: + """Retrieves list of conversations. + + :keyword max_page_size: Number of objects to return per page. Default value is None. + :paramtype max_page_size: int + :keyword participant_id: The participant user ID. Default value is None. + :paramtype participant_id: str + :keyword channel_id: The id of channel. Default value is None. + :paramtype channel_id: str + :return: An iterator like instance of CommunicationConversation + :rtype: + ~azure.core.paging.ItemPaged[~azure.communication.messages.models.CommunicationConversation] + :raises ~azure.core.exceptions.HttpResponseError: + """ + _headers = kwargs.pop("headers", {}) or {} + _params = kwargs.pop("params", {}) or {} + + cls: ClsType[List[_models.CommunicationConversation]] = kwargs.pop("cls", None) + + error_map: MutableMapping = { + 401: ClientAuthenticationError, + 404: ResourceNotFoundError, + 409: ResourceExistsError, + 304: ResourceNotModifiedError, + } + error_map.update(kwargs.pop("error_map", {}) or {}) + + def prepare_request(next_link=None): + if not next_link: + + _request = build_conversation_administration_list_conversations_request( + max_page_size=max_page_size, + participant_id=participant_id, + channel_id=channel_id, + api_version=self._config.api_version, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url( + "self._config.endpoint", self._config.endpoint, "str", skip_quote=True + ), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + + else: + # make call to next link with the client's api-version + _parsed_next_link = urllib.parse.urlparse(next_link) + _next_request_params = case_insensitive_dict( + { + key: [urllib.parse.quote(v) for v in value] + for key, value in urllib.parse.parse_qs(_parsed_next_link.query).items() + } + ) + _next_request_params["api-version"] = self._config.api_version + _request = HttpRequest( + "GET", urllib.parse.urljoin(next_link, _parsed_next_link.path), params=_next_request_params + ) + path_format_arguments = { + "endpoint": self._serialize.url( + "self._config.endpoint", self._config.endpoint, "str", skip_quote=True + ), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + + return _request + + def extract_data(pipeline_response): + deserialized = pipeline_response.http_response.json() + list_of_elem = _deserialize(List[_models.CommunicationConversation], deserialized.get("value", [])) + if cls: + list_of_elem = cls(list_of_elem) # type: ignore + return deserialized.get("nextLink") or None, iter(list_of_elem) + + def get_next(next_link=None): + _request = prepare_request(next_link) + + _stream = False + pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + return pipeline_response + + return ItemPaged(get_next, extract_data) + + @distributed_trace + @api_version_validation( + method_added_on="2025-04-01-preview", + params_added_on={ + "2025-04-01-preview": [ + "endpoint", + "api_version", + "conversation_id", + "max_page_size", + "participant_id", + "client_request_id", + "accept", + ] + }, + ) + def list_messages( + self, + conversation_id: str, + *, + max_page_size: Optional[int] = None, + participant_id: Optional[str] = None, + **kwargs: Any, + ) -> Iterable["_models.ConversationMessageItem"]: + """Retrieves list of conversation messages. + + :param conversation_id: The conversation ID. Required. + :type conversation_id: str + :keyword max_page_size: Number of objects to return per page. Default value is None. + :paramtype max_page_size: int + :keyword participant_id: The participant user ID. Default value is None. + :paramtype participant_id: str + :return: An iterator like instance of ConversationMessageItem + :rtype: + ~azure.core.paging.ItemPaged[~azure.communication.messages.models.ConversationMessageItem] + :raises ~azure.core.exceptions.HttpResponseError: + """ + _headers = kwargs.pop("headers", {}) or {} + _params = kwargs.pop("params", {}) or {} + + cls: ClsType[List[_models.ConversationMessageItem]] = kwargs.pop("cls", None) + + error_map: MutableMapping = { + 401: ClientAuthenticationError, + 404: ResourceNotFoundError, + 409: ResourceExistsError, + 304: ResourceNotModifiedError, + } + error_map.update(kwargs.pop("error_map", {}) or {}) + + def prepare_request(next_link=None): + if not next_link: + + _request = build_conversation_administration_list_messages_request( + conversation_id=conversation_id, + max_page_size=max_page_size, + participant_id=participant_id, + api_version=self._config.api_version, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url( + "self._config.endpoint", self._config.endpoint, "str", skip_quote=True + ), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + + else: + # make call to next link with the client's api-version + _parsed_next_link = urllib.parse.urlparse(next_link) + _next_request_params = case_insensitive_dict( + { + key: [urllib.parse.quote(v) for v in value] + for key, value in urllib.parse.parse_qs(_parsed_next_link.query).items() + } + ) + _next_request_params["api-version"] = self._config.api_version + _request = HttpRequest( + "GET", urllib.parse.urljoin(next_link, _parsed_next_link.path), params=_next_request_params + ) + path_format_arguments = { + "endpoint": self._serialize.url( + "self._config.endpoint", self._config.endpoint, "str", skip_quote=True + ), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + + return _request + + def extract_data(pipeline_response): + deserialized = pipeline_response.http_response.json() + list_of_elem = _deserialize(List[_models.ConversationMessageItem], deserialized.get("value", [])) + if cls: + list_of_elem = cls(list_of_elem) # type: ignore + return deserialized.get("nextLink") or None, iter(list_of_elem) + + def get_next(next_link=None): + _request = prepare_request(next_link) + + _stream = False + pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + return pipeline_response + + return ItemPaged(get_next, extract_data) + + @overload + def add_participants( + self, + conversation_id: str, + options: _models.AddParticipantsOptions, + *, + content_type: str = "application/json", + **kwargs: Any, + ) -> _models.AddParticipantsResult: + """Adds participants to a specific conversation. + + :param conversation_id: The conversation ID. Required. + :type conversation_id: str + :param options: Details of the payload for adding participants to a conversation. Required. + :type options: ~azure.communication.messages.models.AddParticipantsOptions + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/json". + :paramtype content_type: str + :return: AddParticipantsResult. The AddParticipantsResult is compatible with MutableMapping + :rtype: ~azure.communication.messages.models.AddParticipantsResult + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @overload + def add_participants( + self, conversation_id: str, options: JSON, *, content_type: str = "application/json", **kwargs: Any + ) -> _models.AddParticipantsResult: + """Adds participants to a specific conversation. + + :param conversation_id: The conversation ID. Required. + :type conversation_id: str + :param options: Details of the payload for adding participants to a conversation. Required. + :type options: JSON + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/json". + :paramtype content_type: str + :return: AddParticipantsResult. The AddParticipantsResult is compatible with MutableMapping + :rtype: ~azure.communication.messages.models.AddParticipantsResult + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @overload + def add_participants( + self, conversation_id: str, options: IO[bytes], *, content_type: str = "application/json", **kwargs: Any + ) -> _models.AddParticipantsResult: + """Adds participants to a specific conversation. + + :param conversation_id: The conversation ID. Required. + :type conversation_id: str + :param options: Details of the payload for adding participants to a conversation. Required. + :type options: IO[bytes] + :keyword content_type: Body Parameter content-type. Content type parameter for binary body. + Default value is "application/json". + :paramtype content_type: str + :return: AddParticipantsResult. The AddParticipantsResult is compatible with MutableMapping + :rtype: ~azure.communication.messages.models.AddParticipantsResult + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @distributed_trace + @api_version_validation( + method_added_on="2025-04-01-preview", + params_added_on={ + "2025-04-01-preview": [ + "endpoint", + "api_version", + "conversation_id", + "repeatability_request_id", + "repeatability_first_sent", + "client_request_id", + "content_type", + "accept", + ] + }, + ) + def add_participants( + self, conversation_id: str, options: Union[_models.AddParticipantsOptions, JSON, IO[bytes]], **kwargs: Any + ) -> _models.AddParticipantsResult: + """Adds participants to a specific conversation. + + :param conversation_id: The conversation ID. Required. + :type conversation_id: str + :param options: Details of the payload for adding participants to a conversation. Is one of the + following types: AddParticipantsOptions, JSON, IO[bytes] Required. + :type options: ~azure.communication.messages.models.AddParticipantsOptions or JSON or IO[bytes] + :return: AddParticipantsResult. The AddParticipantsResult is compatible with MutableMapping + :rtype: ~azure.communication.messages.models.AddParticipantsResult + :raises ~azure.core.exceptions.HttpResponseError: + """ + error_map: MutableMapping = { + 401: ClientAuthenticationError, + 404: ResourceNotFoundError, + 409: ResourceExistsError, + 304: ResourceNotModifiedError, + } + error_map.update(kwargs.pop("error_map", {}) or {}) + + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) + _params = kwargs.pop("params", {}) or {} + + content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) + cls: ClsType[_models.AddParticipantsResult] = kwargs.pop("cls", None) + + content_type = content_type or "application/json" + _content = None + if isinstance(options, (IOBase, bytes)): + _content = options + else: + _content = json.dumps(options, cls=SdkJSONEncoder, exclude_readonly=True) # type: ignore + + _request = build_conversation_administration_add_participants_request( + conversation_id=conversation_id, + content_type=content_type, + api_version=self._config.api_version, + content=_content, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + + _stream = kwargs.pop("stream", False) + pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + + response = pipeline_response.http_response + + if response.status_code not in [207]: + if _stream: + try: + response.read() # Load the body in memory and close the socket + except (StreamConsumedError, StreamClosedError): + pass + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + response_headers = {} + response_headers["Repeatability-Result"] = self._deserialize( + "str", response.headers.get("Repeatability-Result") + ) + response_headers["x-ms-client-request-id"] = self._deserialize( + "str", response.headers.get("x-ms-client-request-id") + ) + + if _stream: + deserialized = response.iter_bytes() + else: + deserialized = _deserialize(_models.AddParticipantsResult, response.json()) + + if cls: + return cls(pipeline_response, deserialized, response_headers) # type: ignore + + return deserialized # type: ignore + + @overload + def remove_participants( + self, + conversation_id: str, + options: _models.RemoveParticipantsOptions, + *, + content_type: str = "application/json", + **kwargs: Any, + ) -> _models.RemoveParticipantsResult: + """remove a participant from a conversation. + + :param conversation_id: The conversation ID. Required. + :type conversation_id: str + :param options: Details of the request body for removing participants from a conversation. + Required. + :type options: ~azure.communication.messages.models.RemoveParticipantsOptions + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/json". + :paramtype content_type: str + :return: RemoveParticipantsResult. The RemoveParticipantsResult is compatible with + MutableMapping + :rtype: ~azure.communication.messages.models.RemoveParticipantsResult + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @overload + def remove_participants( + self, conversation_id: str, options: JSON, *, content_type: str = "application/json", **kwargs: Any + ) -> _models.RemoveParticipantsResult: + """remove a participant from a conversation. + + :param conversation_id: The conversation ID. Required. + :type conversation_id: str + :param options: Details of the request body for removing participants from a conversation. + Required. + :type options: JSON + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/json". + :paramtype content_type: str + :return: RemoveParticipantsResult. The RemoveParticipantsResult is compatible with + MutableMapping + :rtype: ~azure.communication.messages.models.RemoveParticipantsResult + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @overload + def remove_participants( + self, conversation_id: str, options: IO[bytes], *, content_type: str = "application/json", **kwargs: Any + ) -> _models.RemoveParticipantsResult: + """remove a participant from a conversation. + + :param conversation_id: The conversation ID. Required. + :type conversation_id: str + :param options: Details of the request body for removing participants from a conversation. + Required. + :type options: IO[bytes] + :keyword content_type: Body Parameter content-type. Content type parameter for binary body. + Default value is "application/json". + :paramtype content_type: str + :return: RemoveParticipantsResult. The RemoveParticipantsResult is compatible with + MutableMapping + :rtype: ~azure.communication.messages.models.RemoveParticipantsResult + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @distributed_trace + @api_version_validation( + method_added_on="2025-04-01-preview", + params_added_on={ + "2025-04-01-preview": [ + "endpoint", + "api_version", + "conversation_id", + "repeatability_request_id", + "repeatability_first_sent", + "client_request_id", + "content_type", + "accept", + ] + }, + ) + def remove_participants( + self, conversation_id: str, options: Union[_models.RemoveParticipantsOptions, JSON, IO[bytes]], **kwargs: Any + ) -> _models.RemoveParticipantsResult: + """remove a participant from a conversation. + + :param conversation_id: The conversation ID. Required. + :type conversation_id: str + :param options: Details of the request body for removing participants from a conversation. Is + one of the following types: RemoveParticipantsOptions, JSON, IO[bytes] Required. + :type options: ~azure.communication.messages.models.RemoveParticipantsOptions or JSON or + IO[bytes] + :return: RemoveParticipantsResult. The RemoveParticipantsResult is compatible with + MutableMapping + :rtype: ~azure.communication.messages.models.RemoveParticipantsResult + :raises ~azure.core.exceptions.HttpResponseError: + """ + error_map: MutableMapping = { + 401: ClientAuthenticationError, + 404: ResourceNotFoundError, + 409: ResourceExistsError, + 304: ResourceNotModifiedError, + } + error_map.update(kwargs.pop("error_map", {}) or {}) + + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) + _params = kwargs.pop("params", {}) or {} + + content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) + cls: ClsType[_models.RemoveParticipantsResult] = kwargs.pop("cls", None) + + content_type = content_type or "application/json" + _content = None + if isinstance(options, (IOBase, bytes)): + _content = options + else: + _content = json.dumps(options, cls=SdkJSONEncoder, exclude_readonly=True) # type: ignore + + _request = build_conversation_administration_remove_participants_request( + conversation_id=conversation_id, + content_type=content_type, + api_version=self._config.api_version, + content=_content, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + + _stream = kwargs.pop("stream", False) + pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + + response = pipeline_response.http_response + + if response.status_code not in [207]: + if _stream: + try: + response.read() # Load the body in memory and close the socket + except (StreamConsumedError, StreamClosedError): + pass + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + response_headers = {} + response_headers["Repeatability-Result"] = self._deserialize( + "str", response.headers.get("Repeatability-Result") + ) + response_headers["x-ms-client-request-id"] = self._deserialize( + "str", response.headers.get("x-ms-client-request-id") + ) + + if _stream: + deserialized = response.iter_bytes() + else: + deserialized = _deserialize(_models.RemoveParticipantsResult, response.json()) + + if cls: + return cls(pipeline_response, deserialized, response_headers) # type: ignore + + return deserialized # type: ignore + + @distributed_trace + @api_version_validation( + method_added_on="2025-04-01-preview", + params_added_on={ + "2025-04-01-preview": [ + "endpoint", + "api_version", + "conversation_id", + "repeatability_request_id", + "repeatability_first_sent", + "client_request_id", + "accept", + ] + }, + ) + def analyze_conversation(self, conversation_id: str, **kwargs: Any) -> _models.GetConversationThreadAnalysisResult: + """Get AI Analysis of a conversation. + + :param conversation_id: The conversation ID. Required. + :type conversation_id: str + :return: GetConversationThreadAnalysisResult. The GetConversationThreadAnalysisResult is + compatible with MutableMapping + :rtype: ~azure.communication.messages.models.GetConversationThreadAnalysisResult + :raises ~azure.core.exceptions.HttpResponseError: + """ + error_map: MutableMapping = { + 401: ClientAuthenticationError, + 404: ResourceNotFoundError, + 409: ResourceExistsError, + 304: ResourceNotModifiedError, + } + error_map.update(kwargs.pop("error_map", {}) or {}) + + _headers = kwargs.pop("headers", {}) or {} + _params = kwargs.pop("params", {}) or {} + + cls: ClsType[_models.GetConversationThreadAnalysisResult] = kwargs.pop("cls", None) + + _request = build_conversation_administration_analyze_conversation_request( + conversation_id=conversation_id, + api_version=self._config.api_version, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + + _stream = kwargs.pop("stream", False) + pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + + response = pipeline_response.http_response + + if response.status_code not in [200]: + if _stream: + try: + response.read() # Load the body in memory and close the socket + except (StreamConsumedError, StreamClosedError): + pass + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + response_headers = {} + response_headers["Repeatability-Result"] = self._deserialize( + "str", response.headers.get("Repeatability-Result") + ) + response_headers["x-ms-client-request-id"] = self._deserialize( + "str", response.headers.get("x-ms-client-request-id") + ) + + if _stream: + deserialized = response.iter_bytes() + else: + deserialized = _deserialize(_models.GetConversationThreadAnalysisResult, response.json()) + + if cls: + return cls(pipeline_response, deserialized, response_headers) # type: ignore + + return deserialized # type: ignore + + +class ConversationThreadClientOperationsMixin( + ClientMixinABC[PipelineClient[HttpRequest, HttpResponse], ConversationThreadClientConfiguration] +): + + @overload + def add_participants( + self, + conversation_id: str, + options: _models.AddParticipantsOptions, + *, + content_type: str = "application/json", + **kwargs: Any, + ) -> _models.AddParticipantsResult: + """Adds participants to a specific conversation. + + :param conversation_id: The conversation ID. Required. + :type conversation_id: str + :param options: Details of the payload for adding participants to a conversation. Required. + :type options: ~azure.communication.messages.models.AddParticipantsOptions + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/json". + :paramtype content_type: str + :return: AddParticipantsResult. The AddParticipantsResult is compatible with MutableMapping + :rtype: ~azure.communication.messages.models.AddParticipantsResult + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @overload + def add_participants( + self, conversation_id: str, options: JSON, *, content_type: str = "application/json", **kwargs: Any + ) -> _models.AddParticipantsResult: + """Adds participants to a specific conversation. + + :param conversation_id: The conversation ID. Required. + :type conversation_id: str + :param options: Details of the payload for adding participants to a conversation. Required. + :type options: JSON + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/json". + :paramtype content_type: str + :return: AddParticipantsResult. The AddParticipantsResult is compatible with MutableMapping + :rtype: ~azure.communication.messages.models.AddParticipantsResult + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @overload + def add_participants( + self, conversation_id: str, options: IO[bytes], *, content_type: str = "application/json", **kwargs: Any + ) -> _models.AddParticipantsResult: + """Adds participants to a specific conversation. + + :param conversation_id: The conversation ID. Required. + :type conversation_id: str + :param options: Details of the payload for adding participants to a conversation. Required. + :type options: IO[bytes] + :keyword content_type: Body Parameter content-type. Content type parameter for binary body. + Default value is "application/json". + :paramtype content_type: str + :return: AddParticipantsResult. The AddParticipantsResult is compatible with MutableMapping + :rtype: ~azure.communication.messages.models.AddParticipantsResult + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @distributed_trace + @api_version_validation( + method_added_on="2025-04-01-preview", + params_added_on={ + "2025-04-01-preview": [ + "endpoint", + "api_version", + "conversation_id", + "repeatability_request_id", + "repeatability_first_sent", + "client_request_id", + "content_type", + "accept", + ] + }, + ) + def add_participants( + self, conversation_id: str, options: Union[_models.AddParticipantsOptions, JSON, IO[bytes]], **kwargs: Any + ) -> _models.AddParticipantsResult: + """Adds participants to a specific conversation. + + :param conversation_id: The conversation ID. Required. + :type conversation_id: str + :param options: Details of the payload for adding participants to a conversation. Is one of the + following types: AddParticipantsOptions, JSON, IO[bytes] Required. + :type options: ~azure.communication.messages.models.AddParticipantsOptions or JSON or IO[bytes] + :return: AddParticipantsResult. The AddParticipantsResult is compatible with MutableMapping + :rtype: ~azure.communication.messages.models.AddParticipantsResult + :raises ~azure.core.exceptions.HttpResponseError: + """ + error_map: MutableMapping = { + 401: ClientAuthenticationError, + 404: ResourceNotFoundError, + 409: ResourceExistsError, + 304: ResourceNotModifiedError, + } + error_map.update(kwargs.pop("error_map", {}) or {}) + + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) + _params = kwargs.pop("params", {}) or {} + + content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) + cls: ClsType[_models.AddParticipantsResult] = kwargs.pop("cls", None) + + content_type = content_type or "application/json" + _content = None + if isinstance(options, (IOBase, bytes)): + _content = options + else: + _content = json.dumps(options, cls=SdkJSONEncoder, exclude_readonly=True) # type: ignore + + _request = build_conversation_thread_add_participants_request( + conversation_id=conversation_id, + content_type=content_type, + api_version=self._config.api_version, + content=_content, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + + _stream = kwargs.pop("stream", False) + pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + + response = pipeline_response.http_response + + if response.status_code not in [207]: + if _stream: + try: + response.read() # Load the body in memory and close the socket + except (StreamConsumedError, StreamClosedError): + pass + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + response_headers = {} + response_headers["Repeatability-Result"] = self._deserialize( + "str", response.headers.get("Repeatability-Result") + ) + response_headers["x-ms-client-request-id"] = self._deserialize( + "str", response.headers.get("x-ms-client-request-id") + ) + + if _stream: + deserialized = response.iter_bytes() + else: + deserialized = _deserialize(_models.AddParticipantsResult, response.json()) + + if cls: + return cls(pipeline_response, deserialized, response_headers) # type: ignore + + return deserialized # type: ignore + + @overload + def remove_participants( + self, + conversation_id: str, + options: _models.RemoveParticipantsOptions, + *, + content_type: str = "application/json", + **kwargs: Any, + ) -> _models.RemoveParticipantsResult: + """remove a participant from a conversation. + + :param conversation_id: The conversation ID. Required. + :type conversation_id: str + :param options: Details of the request body for removing participants from a conversation. + Required. + :type options: ~azure.communication.messages.models.RemoveParticipantsOptions + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/json". + :paramtype content_type: str + :return: RemoveParticipantsResult. The RemoveParticipantsResult is compatible with + MutableMapping + :rtype: ~azure.communication.messages.models.RemoveParticipantsResult + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @overload + def remove_participants( + self, conversation_id: str, options: JSON, *, content_type: str = "application/json", **kwargs: Any + ) -> _models.RemoveParticipantsResult: + """remove a participant from a conversation. + + :param conversation_id: The conversation ID. Required. + :type conversation_id: str + :param options: Details of the request body for removing participants from a conversation. + Required. + :type options: JSON + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/json". + :paramtype content_type: str + :return: RemoveParticipantsResult. The RemoveParticipantsResult is compatible with + MutableMapping + :rtype: ~azure.communication.messages.models.RemoveParticipantsResult + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @overload + def remove_participants( + self, conversation_id: str, options: IO[bytes], *, content_type: str = "application/json", **kwargs: Any + ) -> _models.RemoveParticipantsResult: + """remove a participant from a conversation. + + :param conversation_id: The conversation ID. Required. + :type conversation_id: str + :param options: Details of the request body for removing participants from a conversation. + Required. + :type options: IO[bytes] + :keyword content_type: Body Parameter content-type. Content type parameter for binary body. + Default value is "application/json". + :paramtype content_type: str + :return: RemoveParticipantsResult. The RemoveParticipantsResult is compatible with + MutableMapping + :rtype: ~azure.communication.messages.models.RemoveParticipantsResult + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @distributed_trace + @api_version_validation( + method_added_on="2025-04-01-preview", + params_added_on={ + "2025-04-01-preview": [ + "endpoint", + "api_version", + "conversation_id", + "repeatability_request_id", + "repeatability_first_sent", + "client_request_id", + "content_type", + "accept", + ] + }, + ) + def remove_participants( + self, conversation_id: str, options: Union[_models.RemoveParticipantsOptions, JSON, IO[bytes]], **kwargs: Any + ) -> _models.RemoveParticipantsResult: + """remove a participant from a conversation. + + :param conversation_id: The conversation ID. Required. + :type conversation_id: str + :param options: Details of the request body for removing participants from a conversation. Is + one of the following types: RemoveParticipantsOptions, JSON, IO[bytes] Required. + :type options: ~azure.communication.messages.models.RemoveParticipantsOptions or JSON or + IO[bytes] + :return: RemoveParticipantsResult. The RemoveParticipantsResult is compatible with + MutableMapping + :rtype: ~azure.communication.messages.models.RemoveParticipantsResult :raises ~azure.core.exceptions.HttpResponseError: """ error_map: MutableMapping = { @@ -201,16 +2168,17 @@ def send( _params = kwargs.pop("params", {}) or {} content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) - cls: ClsType[_models.SendMessageResult] = kwargs.pop("cls", None) + cls: ClsType[_models.RemoveParticipantsResult] = kwargs.pop("cls", None) content_type = content_type or "application/json" _content = None - if isinstance(body, (IOBase, bytes)): - _content = body + if isinstance(options, (IOBase, bytes)): + _content = options else: - _content = json.dumps(body, cls=SdkJSONEncoder, exclude_readonly=True) # type: ignore + _content = json.dumps(options, cls=SdkJSONEncoder, exclude_readonly=True) # type: ignore - _request = build_notification_messages_send_request( + _request = build_conversation_thread_remove_participants_request( + conversation_id=conversation_id, content_type=content_type, api_version=self._config.api_version, content=_content, @@ -229,7 +2197,7 @@ def send( response = pipeline_response.http_response - if response.status_code not in [202]: + if response.status_code not in [207]: if _stream: try: response.read() # Load the body in memory and close the socket @@ -249,7 +2217,7 @@ def send( if _stream: deserialized = response.iter_bytes() else: - deserialized = _deserialize(_models.SendMessageResult, response.json()) + deserialized = _deserialize(_models.RemoveParticipantsResult, response.json()) if cls: return cls(pipeline_response, deserialized, response_headers) # type: ignore @@ -257,15 +2225,46 @@ def send( return deserialized # type: ignore @distributed_trace - def download_media(self, id: str, **kwargs: Any) -> Iterator[bytes]: - """Download the Media payload from a User to Business message. - - :param id: The stream ID. Required. - :type id: str - :return: Iterator[bytes] - :rtype: Iterator[bytes] + @api_version_validation( + method_added_on="2025-04-01-preview", + params_added_on={ + "2025-04-01-preview": [ + "endpoint", + "api_version", + "max_page_size", + "participant_id", + "channel_id", + "client_request_id", + "accept", + ] + }, + ) + def list_conversations( + self, + *, + max_page_size: Optional[int] = None, + participant_id: Optional[str] = None, + channel_id: Optional[str] = None, + **kwargs: Any, + ) -> Iterable["_models.CommunicationConversation"]: + """Retrieves list of conversations. + + :keyword max_page_size: Number of objects to return per page. Default value is None. + :paramtype max_page_size: int + :keyword participant_id: The participant user ID. Default value is None. + :paramtype participant_id: str + :keyword channel_id: The id of channel. Default value is None. + :paramtype channel_id: str + :return: An iterator like instance of CommunicationConversation + :rtype: + ~azure.core.paging.ItemPaged[~azure.communication.messages.models.CommunicationConversation] :raises ~azure.core.exceptions.HttpResponseError: """ + _headers = kwargs.pop("headers", {}) or {} + _params = kwargs.pop("params", {}) or {} + + cls: ClsType[List[_models.CommunicationConversation]] = kwargs.pop("cls", None) + error_map: MutableMapping = { 401: ClientAuthenticationError, 404: ResourceNotFoundError, @@ -274,69 +2273,110 @@ def download_media(self, id: str, **kwargs: Any) -> Iterator[bytes]: } error_map.update(kwargs.pop("error_map", {}) or {}) - _headers = kwargs.pop("headers", {}) or {} - _params = kwargs.pop("params", {}) or {} - - cls: ClsType[Iterator[bytes]] = kwargs.pop("cls", None) - - _request = build_notification_messages_download_media_request( - id=id, - api_version=self._config.api_version, - headers=_headers, - params=_params, - ) - path_format_arguments = { - "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), - } - _request.url = self._client.format_url(_request.url, **path_format_arguments) + def prepare_request(next_link=None): + if not next_link: - _stream = kwargs.pop("stream", True) - pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access - _request, stream=_stream, **kwargs - ) + _request = build_conversation_thread_list_conversations_request( + max_page_size=max_page_size, + participant_id=participant_id, + channel_id=channel_id, + api_version=self._config.api_version, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url( + "self._config.endpoint", self._config.endpoint, "str", skip_quote=True + ), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) - response = pipeline_response.http_response + else: + # make call to next link with the client's api-version + _parsed_next_link = urllib.parse.urlparse(next_link) + _next_request_params = case_insensitive_dict( + { + key: [urllib.parse.quote(v) for v in value] + for key, value in urllib.parse.parse_qs(_parsed_next_link.query).items() + } + ) + _next_request_params["api-version"] = self._config.api_version + _request = HttpRequest( + "GET", urllib.parse.urljoin(next_link, _parsed_next_link.path), params=_next_request_params + ) + path_format_arguments = { + "endpoint": self._serialize.url( + "self._config.endpoint", self._config.endpoint, "str", skip_quote=True + ), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) - if response.status_code not in [200]: - if _stream: - try: - response.read() # Load the body in memory and close the socket - except (StreamConsumedError, StreamClosedError): - pass - map_error(status_code=response.status_code, response=response, error_map=error_map) - raise HttpResponseError(response=response) + return _request - response_headers = {} - response_headers["x-ms-client-request-id"] = self._deserialize( - "str", response.headers.get("x-ms-client-request-id") - ) - response_headers["content-type"] = self._deserialize("str", response.headers.get("content-type")) + def extract_data(pipeline_response): + deserialized = pipeline_response.http_response.json() + list_of_elem = _deserialize(List[_models.CommunicationConversation], deserialized.get("value", [])) + if cls: + list_of_elem = cls(list_of_elem) # type: ignore + return deserialized.get("nextLink") or None, iter(list_of_elem) - deserialized = response.iter_bytes() + def get_next(next_link=None): + _request = prepare_request(next_link) - if cls: - return cls(pipeline_response, deserialized, response_headers) # type: ignore + _stream = False + pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + response = pipeline_response.http_response - return deserialized # type: ignore + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + return pipeline_response -class MessageTemplateClientOperationsMixin(MessageTemplateClientMixinABC): + return ItemPaged(get_next, extract_data) @distributed_trace - def list_templates(self, channel_id: str, **kwargs: Any) -> Iterable["_models.MessageTemplateItem"]: - """List all templates for given Azure Communication Services channel. - - :param channel_id: The registration ID of the channel. Required. - :type channel_id: str - :return: An iterator like instance of MessageTemplateItem - :rtype: ~azure.core.paging.ItemPaged[~azure.communication.messages.models.MessageTemplateItem] + @api_version_validation( + method_added_on="2025-04-01-preview", + params_added_on={ + "2025-04-01-preview": [ + "endpoint", + "api_version", + "conversation_id", + "max_page_size", + "participant_id", + "client_request_id", + "accept", + ] + }, + ) + def list_messages( + self, + conversation_id: str, + *, + max_page_size: Optional[int] = None, + participant_id: Optional[str] = None, + **kwargs: Any, + ) -> Iterable["_models.ConversationMessageItem"]: + """Retrieves list of conversation messages. + + :param conversation_id: The conversation ID. Required. + :type conversation_id: str + :keyword max_page_size: Number of objects to return per page. Default value is None. + :paramtype max_page_size: int + :keyword participant_id: The participant user ID. Default value is None. + :paramtype participant_id: str + :return: An iterator like instance of ConversationMessageItem + :rtype: + ~azure.core.paging.ItemPaged[~azure.communication.messages.models.ConversationMessageItem] :raises ~azure.core.exceptions.HttpResponseError: """ _headers = kwargs.pop("headers", {}) or {} _params = kwargs.pop("params", {}) or {} - maxpagesize = kwargs.pop("maxpagesize", None) - cls: ClsType[List[_models.MessageTemplateItem]] = kwargs.pop("cls", None) + cls: ClsType[List[_models.ConversationMessageItem]] = kwargs.pop("cls", None) error_map: MutableMapping = { 401: ClientAuthenticationError, @@ -349,9 +2389,10 @@ def list_templates(self, channel_id: str, **kwargs: Any) -> Iterable["_models.Me def prepare_request(next_link=None): if not next_link: - _request = build_message_template_list_templates_request( - channel_id=channel_id, - maxpagesize=maxpagesize, + _request = build_conversation_thread_list_messages_request( + conversation_id=conversation_id, + max_page_size=max_page_size, + participant_id=participant_id, api_version=self._config.api_version, headers=_headers, params=_params, @@ -387,7 +2428,7 @@ def prepare_request(next_link=None): def extract_data(pipeline_response): deserialized = pipeline_response.http_response.json() - list_of_elem = _deserialize(List[_models.MessageTemplateItem], deserialized["value"]) + list_of_elem = _deserialize(List[_models.ConversationMessageItem], deserialized.get("value", [])) if cls: list_of_elem = cls(list_of_elem) # type: ignore return deserialized.get("nextLink") or None, iter(list_of_elem) @@ -408,3 +2449,251 @@ def get_next(next_link=None): return pipeline_response return ItemPaged(get_next, extract_data) + + @overload + def send_message( + self, + conversation_id: str, + options: _models.SendConversationMessageOptions, + *, + content_type: str = "application/json", + **kwargs: Any, + ) -> _models.SendConversationMessageResult: + """Sends a conversation message from Business to User. + + :param conversation_id: The conversation ID. Required. + :type conversation_id: str + :param options: Details of the conversation message to send. Required. + :type options: ~azure.communication.messages.models.SendConversationMessageOptions + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/json". + :paramtype content_type: str + :return: SendConversationMessageResult. The SendConversationMessageResult is compatible with + MutableMapping + :rtype: ~azure.communication.messages.models.SendConversationMessageResult + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @overload + def send_message( + self, conversation_id: str, options: JSON, *, content_type: str = "application/json", **kwargs: Any + ) -> _models.SendConversationMessageResult: + """Sends a conversation message from Business to User. + + :param conversation_id: The conversation ID. Required. + :type conversation_id: str + :param options: Details of the conversation message to send. Required. + :type options: JSON + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/json". + :paramtype content_type: str + :return: SendConversationMessageResult. The SendConversationMessageResult is compatible with + MutableMapping + :rtype: ~azure.communication.messages.models.SendConversationMessageResult + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @overload + def send_message( + self, conversation_id: str, options: IO[bytes], *, content_type: str = "application/json", **kwargs: Any + ) -> _models.SendConversationMessageResult: + """Sends a conversation message from Business to User. + + :param conversation_id: The conversation ID. Required. + :type conversation_id: str + :param options: Details of the conversation message to send. Required. + :type options: IO[bytes] + :keyword content_type: Body Parameter content-type. Content type parameter for binary body. + Default value is "application/json". + :paramtype content_type: str + :return: SendConversationMessageResult. The SendConversationMessageResult is compatible with + MutableMapping + :rtype: ~azure.communication.messages.models.SendConversationMessageResult + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @distributed_trace + @api_version_validation( + method_added_on="2025-04-01-preview", + params_added_on={ + "2025-04-01-preview": [ + "endpoint", + "api_version", + "conversation_id", + "repeatability_request_id", + "repeatability_first_sent", + "client_request_id", + "content_type", + "accept", + ] + }, + ) + def send_message( + self, + conversation_id: str, + options: Union[_models.SendConversationMessageOptions, JSON, IO[bytes]], + **kwargs: Any, + ) -> _models.SendConversationMessageResult: + """Sends a conversation message from Business to User. + + :param conversation_id: The conversation ID. Required. + :type conversation_id: str + :param options: Details of the conversation message to send. Is one of the following types: + SendConversationMessageOptions, JSON, IO[bytes] Required. + :type options: ~azure.communication.messages.models.SendConversationMessageOptions or JSON or + IO[bytes] + :return: SendConversationMessageResult. The SendConversationMessageResult is compatible with + MutableMapping + :rtype: ~azure.communication.messages.models.SendConversationMessageResult + :raises ~azure.core.exceptions.HttpResponseError: + """ + error_map: MutableMapping = { + 401: ClientAuthenticationError, + 404: ResourceNotFoundError, + 409: ResourceExistsError, + 304: ResourceNotModifiedError, + } + error_map.update(kwargs.pop("error_map", {}) or {}) + + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) + _params = kwargs.pop("params", {}) or {} + + content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) + cls: ClsType[_models.SendConversationMessageResult] = kwargs.pop("cls", None) + + content_type = content_type or "application/json" + _content = None + if isinstance(options, (IOBase, bytes)): + _content = options + else: + _content = json.dumps(options, cls=SdkJSONEncoder, exclude_readonly=True) # type: ignore + + _request = build_conversation_thread_send_message_request( + conversation_id=conversation_id, + content_type=content_type, + api_version=self._config.api_version, + content=_content, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + + _stream = kwargs.pop("stream", False) + pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + + response = pipeline_response.http_response + + if response.status_code not in [200]: + if _stream: + try: + response.read() # Load the body in memory and close the socket + except (StreamConsumedError, StreamClosedError): + pass + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + response_headers = {} + response_headers["Repeatability-Result"] = self._deserialize( + "str", response.headers.get("Repeatability-Result") + ) + response_headers["x-ms-client-request-id"] = self._deserialize( + "str", response.headers.get("x-ms-client-request-id") + ) + + if _stream: + deserialized = response.iter_bytes() + else: + deserialized = _deserialize(_models.SendConversationMessageResult, response.json()) + + if cls: + return cls(pipeline_response, deserialized, response_headers) # type: ignore + + return deserialized # type: ignore + + @distributed_trace + @api_version_validation( + method_added_on="2025-04-01-preview", + params_added_on={ + "2025-04-01-preview": [ + "endpoint", + "api_version", + "conversation_id", + "repeatability_request_id", + "repeatability_first_sent", + "client_request_id", + "accept", + ] + }, + ) + def analyze_conversation(self, conversation_id: str, **kwargs: Any) -> _models.GetConversationThreadAnalysisResult: + """Get AI Analysis of a conversation. + + :param conversation_id: The conversation ID. Required. + :type conversation_id: str + :return: GetConversationThreadAnalysisResult. The GetConversationThreadAnalysisResult is + compatible with MutableMapping + :rtype: ~azure.communication.messages.models.GetConversationThreadAnalysisResult + :raises ~azure.core.exceptions.HttpResponseError: + """ + error_map: MutableMapping = { + 401: ClientAuthenticationError, + 404: ResourceNotFoundError, + 409: ResourceExistsError, + 304: ResourceNotModifiedError, + } + error_map.update(kwargs.pop("error_map", {}) or {}) + + _headers = kwargs.pop("headers", {}) or {} + _params = kwargs.pop("params", {}) or {} + + cls: ClsType[_models.GetConversationThreadAnalysisResult] = kwargs.pop("cls", None) + + _request = build_conversation_thread_analyze_conversation_request( + conversation_id=conversation_id, + api_version=self._config.api_version, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + + _stream = kwargs.pop("stream", False) + pipeline_response: PipelineResponse = self._client._pipeline.run( # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + + response = pipeline_response.http_response + + if response.status_code not in [200]: + if _stream: + try: + response.read() # Load the body in memory and close the socket + except (StreamConsumedError, StreamClosedError): + pass + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + response_headers = {} + response_headers["Repeatability-Result"] = self._deserialize( + "str", response.headers.get("Repeatability-Result") + ) + response_headers["x-ms-client-request-id"] = self._deserialize( + "str", response.headers.get("x-ms-client-request-id") + ) + + if _stream: + deserialized = response.iter_bytes() + else: + deserialized = _deserialize(_models.GetConversationThreadAnalysisResult, response.json()) + + if cls: + return cls(pipeline_response, deserialized, response_headers) # type: ignore + + return deserialized # type: ignore diff --git a/sdk/communication/azure-communication-messages/azure/communication/messages/_operations/_patch.py b/sdk/communication/azure-communication-messages/azure/communication/messages/_operations/_patch.py index f7dd32510333..8bcb627aa475 100644 --- a/sdk/communication/azure-communication-messages/azure/communication/messages/_operations/_patch.py +++ b/sdk/communication/azure-communication-messages/azure/communication/messages/_operations/_patch.py @@ -1,7 +1,8 @@ -# ------------------------------------ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. -# ------------------------------------ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# -------------------------------------------------------------------------- """Customize generated code here. Follow our quickstart for examples: https://aka.ms/azsdk/python/dpcodegen/python/customize diff --git a/sdk/communication/azure-communication-messages/azure/communication/messages/_patch.py b/sdk/communication/azure-communication-messages/azure/communication/messages/_patch.py index eb3162ba82cb..8bcb627aa475 100644 --- a/sdk/communication/azure-communication-messages/azure/communication/messages/_patch.py +++ b/sdk/communication/azure-communication-messages/azure/communication/messages/_patch.py @@ -1,137 +1,15 @@ -# ------------------------------------ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. -# ------------------------------------ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# -------------------------------------------------------------------------- """Customize generated code here. Follow our quickstart for examples: https://aka.ms/azsdk/python/dpcodegen/python/customize """ -from typing import List, Any, Union -from urllib.parse import urlparse -from azure.core.credentials import TokenCredential, AzureKeyCredential -from ._shared.utils import parse_connection_str -from ._client import ( - NotificationMessagesClient as NotificationMessagesClientGenerated, - MessageTemplateClient as MessageTemplateClientGenerated, -) -from ._shared.auth_policy_utils import get_authentication_policy -from ._api_versions import DEFAULT_VERSION +from typing import List - -class NotificationMessagesClient(NotificationMessagesClientGenerated): - """A client to interact with the AzureCommunicationService Messaging service. - - This client provides operations to create and update jobs, policies and workers. - - :param str endpoint: - The endpoint of the Azure Communication resource. - :param Union[TokenCredential, AsyncTokenCredential] credential: - The credentials with which to authenticate - - :keyword api_version: Azure Communication Messaging API version. - Default value is "2023-11-01". - Note that overriding this default value may result in unsupported behavior. - """ - - def __init__(self, endpoint: str, credential: Union[TokenCredential, AzureKeyCredential], **kwargs: Any) -> None: - if not credential: - raise ValueError("credential can not be None") - - try: - if not endpoint.lower().startswith("http"): - endpoint = "https://" + endpoint - except AttributeError: - raise ValueError("Host URL must be a string") # pylint:disable=raise-missing-from - - parsed_url = urlparse(endpoint.rstrip("/")) - if not parsed_url.netloc: - raise ValueError("Invalid URL: {}".format(endpoint)) - - self._endpoint = endpoint - self._api_version = kwargs.pop("api_version", DEFAULT_VERSION) - self._authentication_policy = get_authentication_policy(endpoint, credential) - self._credential = credential - super().__init__( - self._endpoint, - self._credential, - authentication_policy=self._authentication_policy, - api_version=self._api_version, - **kwargs - ) - - @classmethod - def from_connection_string(cls, conn_str: str, **kwargs: Any) -> "NotificationMessagesClient": - """Create NotificationMessagesClient from a Connection String. - - :param conn_str: Azure communication service connection string. Required. - :type conn_str: str - :return: instance of NotificationMessagesClient - :rtype: - ~azure.communication.messages.NotificationMessagesClient - """ - endpoint, access_key = parse_connection_str(conn_str) - return cls(endpoint, AzureKeyCredential(access_key), **kwargs) - - -class MessageTemplateClient(MessageTemplateClientGenerated): - """A client to interact with the AzureCommunicationService Messaging service. - - This client provides Advanced Messaging. - - :param str endpoint: - The endpoint of the Azure Communication resource. - :param Union[TokenCredential, AsyncTokenCredential] credential: - The credentials with which to authenticate - - :keyword api_version: Azure Communication Messages API version. Default value is "2024-02-01". - Note that overriding this default value may result in unsupported behavior. - :paramtype api_version: str - """ - - def __init__(self, endpoint: str, credential: Union[TokenCredential, AzureKeyCredential], **kwargs: Any) -> "None": - if not credential: - raise ValueError("credential can not be None") - - try: - if not endpoint.lower().startswith("http"): - endpoint = "https://" + endpoint - except AttributeError: - raise ValueError("Host URL must be a string") # pylint: disable=raise-missing-from - - parsed_url = urlparse(endpoint.rstrip("/")) - if not parsed_url.netloc: - raise ValueError("Invalid URL: {}".format(endpoint)) - - self._endpoint = endpoint - self._api_version = kwargs.pop("api_version", DEFAULT_VERSION) - self._authentication_policy = get_authentication_policy(endpoint, credential) - self._credential = credential - super().__init__( - self._endpoint, - self._credential, - authentication_policy=self._authentication_policy, - api_version=self._api_version, - **kwargs - ) - - @classmethod - def from_connection_string(cls, conn_str: str, **kwargs: Any) -> "MessageTemplateClient": - """Create MessageTemplateClient from a Connection String. - - :param conn_str: Azure communication service connection string. Required. - :type conn_str: str - :return: instance of MessageTemplateClient - :rtype: - ~azure.communication.messages.MessageTemplateClient - """ - endpoint, access_key = parse_connection_str(conn_str) - return cls(endpoint, AzureKeyCredential(access_key), **kwargs) - - -__all__: List[str] = [ - "NotificationMessagesClient", - "MessageTemplateClient", -] # Add all objects you want publicly available to users at this package level +__all__: List[str] = [] # Add all objects you want publicly available to users at this package level def patch_sdk(): diff --git a/sdk/communication/azure-communication-messages/azure/communication/messages/_shared/__init__.py b/sdk/communication/azure-communication-messages/azure/communication/messages/_shared/__init__.py deleted file mode 100644 index 5b396cd202e8..000000000000 --- a/sdk/communication/azure-communication-messages/azure/communication/messages/_shared/__init__.py +++ /dev/null @@ -1,5 +0,0 @@ -# ------------------------------------------------------------------------- -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. See License.txt in the project root for -# license information. -# -------------------------------------------------------------------------- diff --git a/sdk/communication/azure-communication-messages/azure/communication/messages/_shared/auth_policy_utils.py b/sdk/communication/azure-communication-messages/azure/communication/messages/_shared/auth_policy_utils.py deleted file mode 100644 index e0bdebfcc294..000000000000 --- a/sdk/communication/azure-communication-messages/azure/communication/messages/_shared/auth_policy_utils.py +++ /dev/null @@ -1,52 +0,0 @@ -# ------------------------------------------------------------------------ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. See License.txt in the project root for -# license information. -# ------------------------------------------------------------------------- - -from typing import Union -from azure.core.credentials import TokenCredential, AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from azure.core.pipeline.policies import ( - AsyncBearerTokenCredentialPolicy, - BearerTokenCredentialPolicy, -) -from .._shared.policy import HMACCredentialsPolicy - - -def get_authentication_policy( - endpoint: str, - credential: Union[TokenCredential, AsyncTokenCredential, AzureKeyCredential, str], - decode_url: bool = False, - is_async: bool = False, -) -> Union[AsyncBearerTokenCredentialPolicy, BearerTokenCredentialPolicy, HMACCredentialsPolicy]: - """Returns the correct authentication policy based on which credential is being passed. - - :param endpoint: The endpoint to which we are authenticating to. - :type endpoint: str - :param credential: The credential we use to authenticate to the service - :type credential: Union[TokenCredential, AsyncTokenCredential, AzureKeyCredential, str] - :param bool decode_url: `True` if there is a need to decode the url. Default value is `False` - :param bool is_async: For async clients there is a need to decode the url - - :return: Either AsyncBearerTokenCredentialPolicy or BearerTokenCredentialPolicy or HMACCredentialsPolicy - :rtype: ~azure.core.pipeline.policies.AsyncBearerTokenCredentialPolicy or - ~azure.core.pipeline.policies.BearerTokenCredentialPolicy or - ~azure.communication.messages.shared.policy.HMACCredentialsPolicy - """ - - if credential is None: - raise ValueError("Parameter 'credential' must not be None.") - if hasattr(credential, "get_token"): - if is_async: - return AsyncBearerTokenCredentialPolicy( - credential, "https://communication.azure.com//.default" # type: ignore - ) - return BearerTokenCredentialPolicy(credential, "https://communication.azure.com//.default") # type: ignore - if isinstance(credential, (AzureKeyCredential, str)): - return HMACCredentialsPolicy(endpoint, credential, decode_url=decode_url) - - raise TypeError( - f"Unsupported credential: {format(type(credential))}. Use an access token string to use HMACCredentialsPolicy" - "or a token credential from azure.identity" - ) diff --git a/sdk/communication/azure-communication-messages/azure/communication/messages/_shared/models.py b/sdk/communication/azure-communication-messages/azure/communication/messages/_shared/models.py deleted file mode 100644 index 43875e1197e5..000000000000 --- a/sdk/communication/azure-communication-messages/azure/communication/messages/_shared/models.py +++ /dev/null @@ -1,417 +0,0 @@ -# ------------------------------------ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. -# ------------------------------------ -from enum import Enum -import warnings -from typing import Mapping, Optional, Union, Any, cast -from typing_extensions import Literal, TypedDict, Protocol, runtime_checkable - -from azure.core import CaseInsensitiveEnumMeta - - -class DeprecatedEnumMeta(CaseInsensitiveEnumMeta): - - def __getattribute__(cls, item): - if item.upper() == "MICROSOFT_BOT": - warnings.warn( - "MICROSOFT_BOT is deprecated and has been replaced by \ - MICROSOFT_TEAMS_APP identifier.", - DeprecationWarning, - ) - item = "MICROSOFT_TEAMS_APP" - return super().__getattribute__(item) - - -class CommunicationIdentifierKind(str, Enum, metaclass=DeprecatedEnumMeta): - """Communication Identifier Kind. - - For checking yet unknown identifiers it is better to rely on the presence of the `raw_id` property, - as new or existing distinct type identifiers always contain the `raw_id` property. - It is not advisable to rely on the `kind` property with a value `unknown`, - as it could become a new or existing distinct type in the future. - """ - - UNKNOWN = "unknown" - COMMUNICATION_USER = "communication_user" - PHONE_NUMBER = "phone_number" - MICROSOFT_TEAMS_USER = "microsoft_teams_user" - MICROSOFT_TEAMS_APP = "microsoft_teams_app" - - -class CommunicationCloudEnvironment(str, Enum, metaclass=CaseInsensitiveEnumMeta): - """The cloud environment that the identifier belongs to""" - - PUBLIC = "PUBLIC" - DOD = "DOD" - GCCH = "GCCH" - - -@runtime_checkable -class CommunicationIdentifier(Protocol): - """Communication Identifier.""" - - @property - def raw_id(self) -> str: - """The raw ID of the identifier.""" - ... - - @property - def kind(self) -> CommunicationIdentifierKind: - """The type of identifier.""" - ... - - @property - def properties(self) -> Mapping[str, Any]: - """The properties of the identifier.""" - ... - - -PHONE_NUMBER_PREFIX = "4:" -BOT_PREFIX = "28:" -BOT_PUBLIC_CLOUD_PREFIX = "28:orgid:" -BOT_DOD_CLOUD_PREFIX = "28:dod:" -BOT_DOD_CLOUD_GLOBAL_PREFIX = "28:dod-global:" -BOT_GCCH_CLOUD_PREFIX = "28:gcch:" -BOT_GCCH_CLOUD_GLOBAL_PREFIX = "28:gcch-global:" -TEAMS_APP_PUBLIC_CLOUD_PREFIX = "28:orgid:" -TEAMS_APP_DOD_CLOUD_PREFIX = "28:dod:" -TEAMS_APP_GCCH_CLOUD_PREFIX = "28:gcch:" -TEAMS_USER_ANONYMOUS_PREFIX = "8:teamsvisitor:" -TEAMS_USER_PUBLIC_CLOUD_PREFIX = "8:orgid:" -TEAMS_USER_DOD_CLOUD_PREFIX = "8:dod:" -TEAMS_USER_GCCH_CLOUD_PREFIX = "8:gcch:" -ACS_USER_PREFIX = "8:acs:" -ACS_USER_DOD_CLOUD_PREFIX = "8:dod-acs:" -ACS_USER_GCCH_CLOUD_PREFIX = "8:gcch-acs:" -SPOOL_USER_PREFIX = "8:spool:" - - -class CommunicationUserProperties(TypedDict): - """Dictionary of properties for a CommunicationUserIdentifier.""" - - id: str - """ID of the Communication user as returned from Azure Communication Identity.""" - - -class CommunicationUserIdentifier: - """Represents a user in Azure Communication Service.""" - - kind: Literal[CommunicationIdentifierKind.COMMUNICATION_USER] = CommunicationIdentifierKind.COMMUNICATION_USER - """The type of identifier.""" - properties: CommunicationUserProperties - """The properties of the identifier.""" - raw_id: str - """The raw ID of the identifier.""" - - def __init__(self, id: str, **kwargs: Any) -> None: - """ - :param str id: ID of the Communication user as returned from Azure Communication Identity. - :keyword str raw_id: The raw ID of the identifier. If not specified, the 'id' value will be used. - """ - self.properties = CommunicationUserProperties(id=id) - raw_id: Optional[str] = kwargs.get("raw_id") - self.raw_id = raw_id if raw_id is not None else id - - def __eq__(self, other): - try: - if other.raw_id: - return self.raw_id == other.raw_id - return self.raw_id == other.properties["id"] - except Exception: # pylint: disable=broad-except - return False - - -class PhoneNumberProperties(TypedDict): - """Dictionary of properties for a PhoneNumberIdentifier.""" - - value: str - """The phone number in E.164 format.""" - - -class PhoneNumberIdentifier: - """Represents a phone number.""" - - kind: Literal[CommunicationIdentifierKind.PHONE_NUMBER] = CommunicationIdentifierKind.PHONE_NUMBER - """The type of identifier.""" - properties: PhoneNumberProperties - """The properties of the identifier.""" - raw_id: str - """The raw ID of the identifier.""" - - def __init__(self, value: str, **kwargs: Any) -> None: - """ - :param str value: The phone number. - :keyword str raw_id: The raw ID of the identifier. If not specified, this will be constructed from - the 'value' parameter. - """ - self.properties = PhoneNumberProperties(value=value) - raw_id: Optional[str] = kwargs.get("raw_id") - self.raw_id = raw_id if raw_id is not None else self._format_raw_id(self.properties) - - def __eq__(self, other): - try: - if other.raw_id: - return self.raw_id == other.raw_id - return self.raw_id == self._format_raw_id(other.properties) - except Exception: # pylint:disable=broad-except - return False - - def _format_raw_id(self, properties: PhoneNumberProperties) -> str: - # We just assume correct E.164 format here because - # validation should only happen server-side, not client-side. - value = properties["value"] - return f"{PHONE_NUMBER_PREFIX}{value}" - - -class UnknownIdentifier: - """Represents an identifier of an unknown type. - - It will be encountered in communications with endpoints that are not - identifiable by this version of the SDK. - - For checking yet unknown identifiers it is better to rely on the presence of the `raw_id` property, - as new or existing distinct type identifiers always contain the `raw_id` property. - It is not advisable to rely on the `kind` property with a value `unknown`, - as it could become a new or existing distinct type in the future. - """ - - kind: Literal[CommunicationIdentifierKind.UNKNOWN] = CommunicationIdentifierKind.UNKNOWN - """The type of identifier.""" - properties: Mapping[str, Any] - """The properties of the identifier.""" - raw_id: str - """The raw ID of the identifier.""" - - def __init__(self, identifier: str) -> None: - """ - :param str identifier: The ID of the identifier. - """ - self.raw_id = identifier - self.properties = {} - - def __eq__(self, other): - try: - return self.raw_id == other.raw_id - except AttributeError: - return False - - -class MicrosoftTeamsUserProperties(TypedDict): - """Dictionary of properties for a MicrosoftTeamsUserIdentifier.""" - - user_id: str - """The id of the Microsoft Teams user. If the user isn't anonymous, the id is the AAD object id of the user.""" - is_anonymous: bool - """Set this to true if the user is anonymous for example when joining a meeting with a share link.""" - cloud: Union[CommunicationCloudEnvironment, str] - """Cloud environment that this identifier belongs to.""" - - -class MicrosoftTeamsUserIdentifier: - """Represents an identifier for a Microsoft Teams user.""" - - kind: Literal[CommunicationIdentifierKind.MICROSOFT_TEAMS_USER] = CommunicationIdentifierKind.MICROSOFT_TEAMS_USER - """The type of identifier.""" - properties: MicrosoftTeamsUserProperties - """The properties of the identifier.""" - raw_id: str - """The raw ID of the identifier.""" - - def __init__(self, user_id: str, **kwargs: Any) -> None: - """ - :param str user_id: Microsoft Teams user id. - :keyword bool is_anonymous: `True` if the identifier is anonymous. Default value is `False`. - :keyword cloud: Cloud environment that the user belongs to. Default value is `PUBLIC`. - :paramtype cloud: str or ~azure.communication.chat.CommunicationCloudEnvironment - :keyword str raw_id: The raw ID of the identifier. If not specified, this value will be constructed from - the other properties. - """ - self.properties = MicrosoftTeamsUserProperties( - user_id=user_id, - is_anonymous=kwargs.get("is_anonymous", False), - cloud=kwargs.get("cloud") or CommunicationCloudEnvironment.PUBLIC, - ) - raw_id: Optional[str] = kwargs.get("raw_id") - self.raw_id = raw_id if raw_id is not None else self._format_raw_id(self.properties) - - def __eq__(self, other): - try: - if other.raw_id: - return self.raw_id == other.raw_id - return self.raw_id == self._format_raw_id(other.properties) - except Exception: # pylint: disable=broad-except - return False - - def _format_raw_id(self, properties: MicrosoftTeamsUserProperties) -> str: - user_id = properties["user_id"] - if properties["is_anonymous"]: - return f"{TEAMS_USER_ANONYMOUS_PREFIX}{user_id}" - cloud = properties["cloud"] - if cloud == CommunicationCloudEnvironment.DOD: - return f"{TEAMS_USER_DOD_CLOUD_PREFIX}{user_id}" - if cloud == CommunicationCloudEnvironment.GCCH: - return f"{TEAMS_USER_GCCH_CLOUD_PREFIX}{user_id}" - if cloud == CommunicationCloudEnvironment.PUBLIC: - return f"{TEAMS_USER_PUBLIC_CLOUD_PREFIX}{user_id}" - return f"{TEAMS_USER_PUBLIC_CLOUD_PREFIX}{user_id}" - - -class MicrosoftTeamsAppProperties(TypedDict): - """Dictionary of properties for a MicrosoftTeamsAppIdentifier.""" - - app_id: str - """The id of the Microsoft Teams application.""" - cloud: Union[CommunicationCloudEnvironment, str] - """Cloud environment that this identifier belongs to.""" - - -class _botbackcompatdict(dict): - """Backwards compatible properties.""" - - def __getitem__(self, __key: Any) -> Any: - try: - return super().__getitem__(__key) - except KeyError: - if __key == "bot_id": - return super().__getitem__("app_id") - if __key == "is_resource_account_configured": - return True - raise - - -class MicrosoftTeamsAppIdentifier: - """Represents an identifier for a Microsoft Teams application.""" - - kind: Literal[CommunicationIdentifierKind.MICROSOFT_TEAMS_APP] = CommunicationIdentifierKind.MICROSOFT_TEAMS_APP - """The type of identifier.""" - properties: MicrosoftTeamsAppProperties - """The properties of the identifier.""" - raw_id: str - """The raw ID of the identifier.""" - - def __init__(self, app_id: str, **kwargs: Any) -> None: - """ - :param str app_id: Microsoft Teams application id. - :keyword cloud: Cloud environment that the application belongs to. Default value is `PUBLIC`. - :paramtype cloud: str or ~azure.communication.chat.CommunicationCloudEnvironment - :keyword str raw_id: The raw ID of the identifier. If not specified, this value will be constructed - from the other properties. - """ - self.properties = cast( - MicrosoftTeamsAppProperties, - _botbackcompatdict( - app_id=app_id, - cloud=kwargs.get("cloud") or CommunicationCloudEnvironment.PUBLIC, - ), - ) - raw_id: Optional[str] = kwargs.get("raw_id") - self.raw_id = raw_id if raw_id is not None else self._format_raw_id(self.properties) - - def __eq__(self, other): - try: - if other.raw_id: - return self.raw_id == other.raw_id - return self.raw_id == self._format_raw_id(other.properties) - except Exception: # pylint: disable=broad-except - return False - - def _format_raw_id(self, properties: MicrosoftTeamsAppProperties) -> str: - app_id = properties["app_id"] - cloud = properties["cloud"] - if cloud == CommunicationCloudEnvironment.DOD: - return f"{TEAMS_APP_DOD_CLOUD_PREFIX}{app_id}" - if cloud == CommunicationCloudEnvironment.GCCH: - return f"{TEAMS_APP_GCCH_CLOUD_PREFIX}{app_id}" - return f"{TEAMS_APP_PUBLIC_CLOUD_PREFIX}{app_id}" - - -class _MicrosoftBotIdentifier(MicrosoftTeamsAppIdentifier): - """Represents an identifier for a Microsoft bot. - - DEPRECATED. Only used in cases of backwards compatibility. - """ - - def __init__(self, bot_id, **kwargs): - """ - :param str bot_id: Microsoft bot id. - :keyword bool is_resource_account_configured: `False` if the identifier is global. - Default value is `True` for tennantzed bots. - :keyword cloud: Cloud environment that the bot belongs to. Default value is `PUBLIC`. - :paramtype cloud: str or ~azure.communication.chat.CommunicationCloudEnvironment - """ - warnings.warn( - "The MicrosoftBotIdentifier is deprecated and has been replaced by MicrosoftTeamsAppIdentifier.", - DeprecationWarning, - ) - super().__init__(bot_id, **kwargs) - - -def identifier_from_raw_id(raw_id: str) -> CommunicationIdentifier: # pylint: disable=too-many-return-statements - """ - Creates a CommunicationIdentifier from a given raw ID. - - When storing raw IDs use this function to restore the identifier that was encoded in the raw ID. - - :param str raw_id: A raw ID to construct the CommunicationIdentifier from. - :return: The CommunicationIdentifier parsed from the raw_id. - :rtype: CommunicationIdentifier - """ - if raw_id.startswith(PHONE_NUMBER_PREFIX): - return PhoneNumberIdentifier(value=raw_id[len(PHONE_NUMBER_PREFIX) :], raw_id=raw_id) - - segments = raw_id.split(":", maxsplit=2) - if len(segments) < 3: - return UnknownIdentifier(identifier=raw_id) - - prefix = f"{segments[0]}:{segments[1]}:" - suffix = segments[2] - if prefix == TEAMS_USER_ANONYMOUS_PREFIX: - return MicrosoftTeamsUserIdentifier(user_id=suffix, is_anonymous=True, raw_id=raw_id) - if prefix == TEAMS_USER_PUBLIC_CLOUD_PREFIX: - return MicrosoftTeamsUserIdentifier( - user_id=suffix, - is_anonymous=False, - cloud=CommunicationCloudEnvironment.PUBLIC, - raw_id=raw_id, - ) - if prefix == TEAMS_USER_DOD_CLOUD_PREFIX: - return MicrosoftTeamsUserIdentifier( - user_id=suffix, - is_anonymous=False, - cloud=CommunicationCloudEnvironment.DOD, - raw_id=raw_id, - ) - if prefix == TEAMS_USER_GCCH_CLOUD_PREFIX: - return MicrosoftTeamsUserIdentifier( - user_id=suffix, - is_anonymous=False, - cloud=CommunicationCloudEnvironment.GCCH, - raw_id=raw_id, - ) - if prefix == TEAMS_APP_PUBLIC_CLOUD_PREFIX: - return MicrosoftTeamsAppIdentifier( - app_id=suffix, - cloud=CommunicationCloudEnvironment.PUBLIC, - raw_id=raw_id, - ) - if prefix == TEAMS_APP_DOD_CLOUD_PREFIX: - return MicrosoftTeamsAppIdentifier( - app_id=suffix, - cloud=CommunicationCloudEnvironment.DOD, - raw_id=raw_id, - ) - if prefix == TEAMS_APP_GCCH_CLOUD_PREFIX: - return MicrosoftTeamsAppIdentifier( - app_id=suffix, - cloud=CommunicationCloudEnvironment.GCCH, - raw_id=raw_id, - ) - if prefix in [ - ACS_USER_PREFIX, - ACS_USER_DOD_CLOUD_PREFIX, - ACS_USER_GCCH_CLOUD_PREFIX, - SPOOL_USER_PREFIX, - ]: - return CommunicationUserIdentifier(id=raw_id, raw_id=raw_id) - return UnknownIdentifier(identifier=raw_id) diff --git a/sdk/communication/azure-communication-messages/azure/communication/messages/_shared/policy.py b/sdk/communication/azure-communication-messages/azure/communication/messages/_shared/policy.py deleted file mode 100644 index 1843d22e83a2..000000000000 --- a/sdk/communication/azure-communication-messages/azure/communication/messages/_shared/policy.py +++ /dev/null @@ -1,120 +0,0 @@ -# ------------------------------------------------------------------------ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. See License.txt in the project root for -# license information. -# ------------------------------------------------------------------------- - -import hashlib -import urllib -import base64 -import hmac -from urllib.parse import ParseResult, urlparse -from typing import Union -from azure.core.credentials import AzureKeyCredential -from azure.core.pipeline.policies import SansIOHTTPPolicy -from .utils import get_current_utc_time - - -class HMACCredentialsPolicy(SansIOHTTPPolicy): - """Implementation of HMAC authentication policy. - - :param str host: The host of the endpoint url for Azure Communication Service resource - :param access_key: The access key we use to authenticate to the service - :type access_key: str or AzureKeyCredential - :param bool decode_url: `True` if there is a need to decode the url. Default value is `False` - """ - - def __init__( - self, - host: str, - access_key: Union[str, AzureKeyCredential], - decode_url: bool = False, - ) -> None: - super(HMACCredentialsPolicy, self).__init__() - - if host.startswith("https://"): - self._host = host.replace("https://", "") - - if host.startswith("http://"): - self._host = host.replace("http://", "") - - self._access_key = access_key - self._decode_url = decode_url - - def _compute_hmac( - self, value # type: str - ): - if isinstance(self._access_key, AzureKeyCredential): - decoded_secret = base64.b64decode(self._access_key.key) - else: - decoded_secret = base64.b64decode(self._access_key) - - digest = hmac.new(decoded_secret, value.encode("utf-8"), hashlib.sha256).digest() - - return base64.b64encode(digest).decode("utf-8") - - def _sign_request(self, request): - verb = request.http_request.method.upper() - - # Get the path and query from url, which looks like https://host/path/query - parsed_url: ParseResult = urlparse(request.http_request.url) - query_url = parsed_url.path - - if parsed_url.query: - query_url += "?" + parsed_url.query - - # Need URL() to get a correct encoded key value, from "%3A" to ":", when transport is in type AioHttpTransport. - # There's a similar scenario in azure-storage-blob and azure-appconfiguration, the check logic is from there. - try: - from yarl import URL - from azure.core.pipeline.transport import ( # pylint:disable=non-abstract-transport-import - AioHttpTransport, - ) - - if ( - isinstance(request.context.transport, AioHttpTransport) - or isinstance( - getattr(request.context.transport, "_transport", None), - AioHttpTransport, - ) - or isinstance( - getattr( - getattr(request.context.transport, "_transport", None), - "_transport", - None, - ), - AioHttpTransport, - ) - ): - query_url = str(URL(query_url)) - except (ImportError, TypeError): - pass - - if self._decode_url: - query_url = urllib.parse.unquote(query_url) - - signed_headers = "x-ms-date;host;x-ms-content-sha256" - - utc_now = get_current_utc_time() - if request.http_request.body is None: - request.http_request.body = "" - content_digest = hashlib.sha256((request.http_request.body.encode("utf-8"))).digest() - content_hash = base64.b64encode(content_digest).decode("utf-8") - - string_to_sign = verb + "\n" + query_url + "\n" + utc_now + ";" + self._host + ";" + content_hash - - signature = self._compute_hmac(string_to_sign) - - signature_header = { - "x-ms-date": utc_now, - "x-ms-content-sha256": content_hash, - "x-ms-return-client-request-id": "true", - "Authorization": "HMAC-SHA256 SignedHeaders=" + signed_headers + "&Signature=" + signature, - } - - request.http_request.headers.update(signature_header) - - return request - - def on_request(self, request): - self._sign_request(request) diff --git a/sdk/communication/azure-communication-messages/azure/communication/messages/_shared/user_credential.py b/sdk/communication/azure-communication-messages/azure/communication/messages/_shared/user_credential.py deleted file mode 100644 index 54603e7b32ce..000000000000 --- a/sdk/communication/azure-communication-messages/azure/communication/messages/_shared/user_credential.py +++ /dev/null @@ -1,143 +0,0 @@ -# ------------------------------------------------------------------------- -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. See License.txt in the project root for -# license information. -# -------------------------------------------------------------------------- - -from threading import Lock, Condition, Timer, TIMEOUT_MAX, Event -from datetime import timedelta -from typing import Any - -from .utils import get_current_utc_as_int -from .utils import create_access_token - - -class CommunicationTokenCredential(object): - """Credential type used for authenticating to an Azure Communication service. - :param str token: The token used to authenticate to an Azure Communication service. - :keyword token_refresher: The sync token refresher to provide capacity to fetch a fresh token. - The returned token must be valid (expiration date must be in the future). - :paramtype token_refresher: Callable[[], AccessToken] - :keyword bool proactive_refresh: Whether to refresh the token proactively or not. - If the proactive refreshing is enabled ('proactive_refresh' is true), the credential will use - a background thread to attempt to refresh the token within 10 minutes before the cached token expires, - the proactive refresh will request a new token by calling the 'token_refresher' callback. - When 'proactive_refresh' is enabled, the Credential object must be either run within a context manager - or the 'close' method must be called once the object usage has been finished. - :raises: TypeError if paramater 'token' is not a string - :raises: ValueError if the 'proactive_refresh' is enabled without providing the 'token_refresher' callable. - """ - - _ON_DEMAND_REFRESHING_INTERVAL_MINUTES = 2 - _DEFAULT_AUTOREFRESH_INTERVAL_MINUTES = 10 - - def __init__(self, token: str, **kwargs: Any): - if not isinstance(token, str): - raise TypeError("Token must be a string.") - self._token = create_access_token(token) - self._token_refresher = kwargs.pop("token_refresher", None) - self._proactive_refresh = kwargs.pop("proactive_refresh", False) - if self._proactive_refresh and self._token_refresher is None: - raise ValueError("When 'proactive_refresh' is True, 'token_refresher' must not be None.") - self._timer = None - self._lock = Condition(Lock()) - self._some_thread_refreshing = False - self._is_closed = Event() - - def get_token(self, *scopes, **kwargs): # pylint: disable=unused-argument - # type (*str, **Any) -> AccessToken - """The value of the configured token. - :param any scopes: Scopes to be added to the token. - :return: AccessToken - :rtype: ~azure.core.credentials.AccessToken - """ - if self._proactive_refresh and self._is_closed.is_set(): - raise RuntimeError("An instance of CommunicationTokenCredential cannot be reused once it has been closed.") - - if not self._token_refresher or not self._is_token_expiring_soon(self._token): - return self._token - self._update_token_and_reschedule() - return self._token - - def _update_token_and_reschedule(self): - should_this_thread_refresh = False - with self._lock: - while self._is_token_expiring_soon(self._token): - if self._some_thread_refreshing: - if self._is_token_valid(self._token): - return self._token - self._wait_till_lock_owner_finishes_refreshing() - else: - should_this_thread_refresh = True - self._some_thread_refreshing = True - break - - if should_this_thread_refresh: - try: - new_token = self._token_refresher() - if not self._is_token_valid(new_token): - raise ValueError("The token returned from the token_refresher is expired.") - with self._lock: - self._token = new_token - self._some_thread_refreshing = False - self._lock.notify_all() - except: - with self._lock: - self._some_thread_refreshing = False - self._lock.notify_all() - raise - if self._proactive_refresh: - self._schedule_refresh() - return self._token - - def _schedule_refresh(self): - if self._is_closed.is_set(): - return - if self._timer is not None: - self._timer.cancel() - - token_ttl = self._token.expires_on - get_current_utc_as_int() - - if self._is_token_expiring_soon(self._token): - # Schedule the next refresh for when it reaches a certain percentage of the remaining lifetime. - timespan = token_ttl // 2 - else: - # Schedule the next refresh for when it gets in to the soon-to-expire window. - timespan = token_ttl - timedelta(minutes=self._DEFAULT_AUTOREFRESH_INTERVAL_MINUTES).total_seconds() - if timespan <= TIMEOUT_MAX: - self._timer = Timer(timespan, self._update_token_and_reschedule) - self._timer.daemon = True - self._timer.start() - - def _wait_till_lock_owner_finishes_refreshing(self): - self._lock.release() - self._lock.acquire() - - def _is_token_expiring_soon(self, token): - if self._proactive_refresh: - interval = timedelta(minutes=self._DEFAULT_AUTOREFRESH_INTERVAL_MINUTES) - else: - interval = timedelta(minutes=self._ON_DEMAND_REFRESHING_INTERVAL_MINUTES) - return (token.expires_on - get_current_utc_as_int()) < interval.total_seconds() - - @classmethod - def _is_token_valid(cls, token): - return get_current_utc_as_int() < token.expires_on - - def __enter__(self): - if self._proactive_refresh: - if self._is_closed.is_set(): - raise RuntimeError( - "An instance of CommunicationTokenCredential cannot be reused once it has been closed." - ) - self._schedule_refresh() - return self - - def __exit__(self, *args): - self.close() - - def close(self) -> None: - if self._timer is not None: - self._timer.cancel() - self._timer = None - self._is_closed.set() diff --git a/sdk/communication/azure-communication-messages/azure/communication/messages/_shared/user_credential_async.py b/sdk/communication/azure-communication-messages/azure/communication/messages/_shared/user_credential_async.py deleted file mode 100644 index c55896c5b6bb..000000000000 --- a/sdk/communication/azure-communication-messages/azure/communication/messages/_shared/user_credential_async.py +++ /dev/null @@ -1,148 +0,0 @@ -# ------------------------------------------------------------------------- -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. See License.txt in the project root for -# license information. -# -------------------------------------------------------------------------- -# pylint: disable=C4763 -from asyncio import Condition, Lock, Event -from datetime import timedelta -from typing import Any -import sys - -from .utils import get_current_utc_as_int -from .utils import create_access_token -from .utils_async import AsyncTimer - - -class CommunicationTokenCredential(object): - """Credential type used for authenticating to an Azure Communication service. - :param str token: The token used to authenticate to an Azure Communication service. - :keyword token_refresher: The async token refresher to provide capacity to fetch a fresh token. - The returned token must be valid (expiration date must be in the future). - :paramtype token_refresher: Callable[[], Awaitable[AccessToken]] - :keyword bool proactive_refresh: Whether to refresh the token proactively or not. - If the proactive refreshing is enabled ('proactive_refresh' is true), the credential will use - a background thread to attempt to refresh the token within 10 minutes before the cached token expires, - the proactive refresh will request a new token by calling the 'token_refresher' callback. - When 'proactive_refresh is enabled', the Credential object must be either run within a context manager - or the 'close' method must be called once the object usage has been finished. - :raises: TypeError if paramater 'token' is not a string - :raises: ValueError if the 'proactive_refresh' is enabled without providing the 'token_refresher' function. - """ - - _ON_DEMAND_REFRESHING_INTERVAL_MINUTES = 2 - _DEFAULT_AUTOREFRESH_INTERVAL_MINUTES = 10 - - def __init__(self, token: str, **kwargs: Any): - if not isinstance(token, str): - raise TypeError("Token must be a string.") - self._token = create_access_token(token) - self._token_refresher = kwargs.pop("token_refresher", None) - self._proactive_refresh = kwargs.pop("proactive_refresh", False) - if self._proactive_refresh and self._token_refresher is None: - raise ValueError("When 'proactive_refresh' is True, 'token_refresher' must not be None.") - self._timer = None - self._async_mutex = Lock() - if sys.version_info[:3] == (3, 10, 0): - # Workaround for Python 3.10 bug(https://bugs.python.org/issue45416): - getattr(self._async_mutex, "_get_loop", lambda: None)() - self._lock = Condition(self._async_mutex) - self._some_thread_refreshing = False - self._is_closed = Event() - - async def get_token(self, *scopes, **kwargs): # pylint: disable=unused-argument - # type (*str, **Any) -> AccessToken - """The value of the configured token. - :param any scopes: Scopes to be added to the token. - :return: AccessToken - :rtype: ~azure.core.credentials.AccessToken - """ - if self._proactive_refresh and self._is_closed.is_set(): - raise RuntimeError("An instance of CommunicationTokenCredential cannot be reused once it has been closed.") - - if not self._token_refresher or not self._is_token_expiring_soon(self._token): - return self._token - await self._update_token_and_reschedule() - return self._token - - async def _update_token_and_reschedule(self): - should_this_thread_refresh = False - async with self._lock: - while self._is_token_expiring_soon(self._token): - if self._some_thread_refreshing: - if self._is_token_valid(self._token): - return self._token - await self._wait_till_lock_owner_finishes_refreshing() - else: - should_this_thread_refresh = True - self._some_thread_refreshing = True - break - - if should_this_thread_refresh: - try: - new_token = await self._token_refresher() - if not self._is_token_valid(new_token): - raise ValueError("The token returned from the token_refresher is expired.") - async with self._lock: - self._token = new_token - self._some_thread_refreshing = False - self._lock.notify_all() - except: - async with self._lock: - self._some_thread_refreshing = False - self._lock.notify_all() - raise - if self._proactive_refresh: - self._schedule_refresh() - return self._token - - def _schedule_refresh(self): - if self._is_closed.is_set(): - return - if self._timer is not None: - self._timer.cancel() - - token_ttl = self._token.expires_on - get_current_utc_as_int() - - if self._is_token_expiring_soon(self._token): - # Schedule the next refresh for when it reaches a certain percentage of the remaining lifetime. - timespan = token_ttl // 2 - else: - # Schedule the next refresh for when it gets in to the soon-to-expire window. - timespan = token_ttl - timedelta(minutes=self._DEFAULT_AUTOREFRESH_INTERVAL_MINUTES).total_seconds() - - self._timer = AsyncTimer(timespan, self._update_token_and_reschedule) - self._timer.start() - - async def _wait_till_lock_owner_finishes_refreshing(self): - self._lock.release() - await self._lock.acquire() - - def _is_token_expiring_soon(self, token): - if self._proactive_refresh: - interval = timedelta(minutes=self._DEFAULT_AUTOREFRESH_INTERVAL_MINUTES) - else: - interval = timedelta(minutes=self._ON_DEMAND_REFRESHING_INTERVAL_MINUTES) - return (token.expires_on - get_current_utc_as_int()) < interval.total_seconds() - - @classmethod - def _is_token_valid(cls, token): - return get_current_utc_as_int() < token.expires_on - - async def __aenter__(self): - if self._proactive_refresh: - if self._is_closed.is_set(): - raise RuntimeError( - "An instance of CommunicationTokenCredential cannot be reused once it has been closed." - ) - self._schedule_refresh() - return self - - async def __aexit__(self, *args): - await self.close() - - async def close(self) -> None: - if self._timer is not None: - self._timer.cancel() - self._timer = None - self._is_closed.set() diff --git a/sdk/communication/azure-communication-messages/azure/communication/messages/_shared/utils.py b/sdk/communication/azure-communication-messages/azure/communication/messages/_shared/utils.py deleted file mode 100644 index 38a62a49dc3f..000000000000 --- a/sdk/communication/azure-communication-messages/azure/communication/messages/_shared/utils.py +++ /dev/null @@ -1,89 +0,0 @@ -# ------------------------------------------------------------------------ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. See License.txt in the project root for -# license information. -# ------------------------------------------------------------------------- - -import base64 -import json -import calendar -from typing import cast, Tuple, Optional -from datetime import datetime -from azure.core.serialization import TZ_UTC -from azure.core.credentials import AccessToken - - -def _convert_datetime_to_utc_int(input_datetime) -> int: - """ - Converts DateTime in local time to the Epoch in UTC in second. - - :param input_datetime: Input datetime - :type input_datetime: datetime - :return: Integer - :rtype: int - """ - return int(calendar.timegm(input_datetime.utctimetuple())) - - -def parse_connection_str(conn_str: Optional[str]) -> Tuple[str, str]: - if conn_str is None: - raise ValueError("Connection string is undefined.") - endpoint = None - shared_access_key = None - for element in conn_str.split(";"): - key, _, value = element.partition("=") - if key.lower() == "endpoint": - endpoint = value.rstrip("/") - elif key.lower() == "accesskey": - shared_access_key = value - if not all([endpoint, shared_access_key]): - raise ValueError( - "Invalid connection string. You can get the connection string from your resource page in the Azure Portal. " - "The format should be as follows: endpoint=https:///;accesskey=" - ) - left_slash_pos = cast(str, endpoint).find("//") - if left_slash_pos != -1: - host = cast(str, endpoint)[left_slash_pos + 2 :] - else: - host = str(endpoint) - - return host, str(shared_access_key) - - -def get_current_utc_time() -> str: - return str(datetime.now(tz=TZ_UTC).strftime("%a, %d %b %Y %H:%M:%S ")) + "GMT" - - -def get_current_utc_as_int() -> int: - current_utc_datetime = datetime.utcnow() - return _convert_datetime_to_utc_int(current_utc_datetime) - - -def create_access_token(token) -> AccessToken: - """Creates an instance of azure.core.credentials.AccessToken from a - string token. The input string is jwt token in the following form: - .. - This method looks into the token_payload which is a json and extracts the expiry time - for that token and creates a tuple of type azure.core.credentials.AccessToken - (, ) - :param token: User token - :type token: str - :return: Instance of azure.core.credentials.AccessToken - token and expiry date of it - :rtype: ~azure.core.credentials.AccessToken - """ - - token_parse_err_msg = "Token is not formatted correctly" - parts = token.split(".") - - if len(parts) < 3: - raise ValueError(token_parse_err_msg) - - try: - padded_base64_payload = base64.b64decode(parts[1] + "==").decode("ascii") - payload = json.loads(padded_base64_payload) - return AccessToken( - token, - _convert_datetime_to_utc_int(datetime.fromtimestamp(payload["exp"], TZ_UTC)), - ) - except ValueError as val_error: - raise ValueError(token_parse_err_msg) from val_error diff --git a/sdk/communication/azure-communication-messages/azure/communication/messages/_shared/utils_async.py b/sdk/communication/azure-communication-messages/azure/communication/messages/_shared/utils_async.py deleted file mode 100644 index 7402d088a880..000000000000 --- a/sdk/communication/azure-communication-messages/azure/communication/messages/_shared/utils_async.py +++ /dev/null @@ -1,30 +0,0 @@ -# ------------------------------------------------------------------------ -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. See License.txt in the project root for -# license information. -# ------------------------------------------------------------------------- -# pylint: disable=C4763 -from asyncio import sleep, ensure_future - -class AsyncTimer: - """A non-blocking timer, that calls a function after a specified number of seconds: - :param int interval: time interval in seconds - :param callable callback: function to be called after the interval has elapsed - """ - - def __init__(self, interval, callback): - self._interval = interval - self._callback = callback - self._task = None - - def start(self): - self._task = ensure_future(self._job()) - - async def _job(self): - await sleep(self._interval) - await self._callback() - - def cancel(self): - if self._task is not None: - self._task.cancel() - self._task = None diff --git a/sdk/communication/azure-communication-messages/azure/communication/messages/_types.py b/sdk/communication/azure-communication-messages/azure/communication/messages/_utils/__init__.py similarity index 77% rename from sdk/communication/azure-communication-messages/azure/communication/messages/_types.py rename to sdk/communication/azure-communication-messages/azure/communication/messages/_utils/__init__.py index 1fe86657cb0f..8026245c2abc 100644 --- a/sdk/communication/azure-communication-messages/azure/communication/messages/_types.py +++ b/sdk/communication/azure-communication-messages/azure/communication/messages/_utils/__init__.py @@ -1,12 +1,6 @@ -# coding=utf-8 -# pylint: disable=too-many-lines # -------------------------------------------------------------------------- # Copyright (c) Microsoft Corporation. All rights reserved. # Licensed under the MIT License. See License.txt in the project root for license information. # Code generated by Microsoft (R) Python Code Generator. # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- - -from typing import Literal - -RepeatabilityResult = Literal["accepted", "rejected"] diff --git a/sdk/communication/azure-communication-messages/azure/communication/messages/_model_base.py b/sdk/communication/azure-communication-messages/azure/communication/messages/_utils/model_base.py similarity index 94% rename from sdk/communication/azure-communication-messages/azure/communication/messages/_model_base.py rename to sdk/communication/azure-communication-messages/azure/communication/messages/_utils/model_base.py index 7f73b97b23ef..49d5c7259389 100644 --- a/sdk/communication/azure-communication-messages/azure/communication/messages/_model_base.py +++ b/sdk/communication/azure-communication-messages/azure/communication/messages/_utils/model_base.py @@ -2,8 +2,9 @@ # coding=utf-8 # -------------------------------------------------------------------------- # Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. See License.txt in the project root for -# license information. +# Licensed under the MIT License. See License.txt in the project root for license information. +# Code generated by Microsoft (R) Python Code Generator. +# Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- # pylint: disable=protected-access, broad-except @@ -21,6 +22,7 @@ from datetime import datetime, date, time, timedelta, timezone from json import JSONEncoder import xml.etree.ElementTree as ET +from collections.abc import MutableMapping from typing_extensions import Self import isodate from azure.core.exceptions import DeserializationError @@ -28,11 +30,6 @@ from azure.core.pipeline import PipelineResponse from azure.core.serialization import _Null -if sys.version_info >= (3, 9): - from collections.abc import MutableMapping -else: - from typing import MutableMapping - _LOGGER = logging.getLogger(__name__) __all__ = ["SdkJSONEncoder", "Model", "rest_field", "rest_discriminator"] @@ -347,7 +344,7 @@ def _get_model(module_name: str, model_name: str): _UNSET = object() -class _MyMutableMapping(MutableMapping[str, typing.Any]): # pylint: disable=unsubscriptable-object +class _MyMutableMapping(MutableMapping[str, typing.Any]): def __init__(self, data: typing.Dict[str, typing.Any]) -> None: self._data = data @@ -373,50 +370,97 @@ def __ne__(self, other: typing.Any) -> bool: return not self.__eq__(other) def keys(self) -> typing.KeysView[str]: + """ + :returns: a set-like object providing a view on D's keys + :rtype: ~typing.KeysView + """ return self._data.keys() def values(self) -> typing.ValuesView[typing.Any]: + """ + :returns: an object providing a view on D's values + :rtype: ~typing.ValuesView + """ return self._data.values() def items(self) -> typing.ItemsView[str, typing.Any]: + """ + :returns: set-like object providing a view on D's items + :rtype: ~typing.ItemsView + """ return self._data.items() def get(self, key: str, default: typing.Any = None) -> typing.Any: + """ + Get the value for key if key is in the dictionary, else default. + :param str key: The key to look up. + :param any default: The value to return if key is not in the dictionary. Defaults to None + :returns: D[k] if k in D, else d. + :rtype: any + """ try: return self[key] except KeyError: return default @typing.overload - def pop(self, key: str) -> typing.Any: ... + def pop(self, key: str) -> typing.Any: ... # pylint: disable=arguments-differ @typing.overload - def pop(self, key: str, default: _T) -> _T: ... + def pop(self, key: str, default: _T) -> _T: ... # pylint: disable=signature-differs @typing.overload - def pop(self, key: str, default: typing.Any) -> typing.Any: ... + def pop(self, key: str, default: typing.Any) -> typing.Any: ... # pylint: disable=signature-differs def pop(self, key: str, default: typing.Any = _UNSET) -> typing.Any: + """ + Removes specified key and return the corresponding value. + :param str key: The key to pop. + :param any default: The value to return if key is not in the dictionary + :returns: The value corresponding to the key. + :rtype: any + :raises KeyError: If key is not found and default is not given. + """ if default is _UNSET: return self._data.pop(key) return self._data.pop(key, default) def popitem(self) -> typing.Tuple[str, typing.Any]: + """ + Removes and returns some (key, value) pair + :returns: The (key, value) pair. + :rtype: tuple + :raises KeyError: if D is empty. + """ return self._data.popitem() def clear(self) -> None: + """ + Remove all items from D. + """ self._data.clear() - def update(self, *args: typing.Any, **kwargs: typing.Any) -> None: + def update(self, *args: typing.Any, **kwargs: typing.Any) -> None: # pylint: disable=arguments-differ + """ + Updates D from mapping/iterable E and F. + :param any args: Either a mapping object or an iterable of key-value pairs. + """ self._data.update(*args, **kwargs) @typing.overload def setdefault(self, key: str, default: None = None) -> None: ... @typing.overload - def setdefault(self, key: str, default: typing.Any) -> typing.Any: ... + def setdefault(self, key: str, default: typing.Any) -> typing.Any: ... # pylint: disable=signature-differs def setdefault(self, key: str, default: typing.Any = _UNSET) -> typing.Any: + """ + Same as calling D.get(k, d), and setting D[k]=d if k not found + :param str key: The key to look up. + :param any default: The value to set if key is not in the dictionary + :returns: D[k] if k in D, else d. + :rtype: any + """ if default is _UNSET: return self._data.setdefault(key) return self._data.setdefault(key, default) @@ -597,7 +641,7 @@ def __new__(cls, *args: typing.Any, **kwargs: typing.Any) -> Self: cls._attr_to_rest_field: typing.Dict[str, _RestField] = dict(attr_to_rest_field.items()) cls._calculated.add(f"{cls.__module__}.{cls.__qualname__}") - return super().__new__(cls) # pylint: disable=no-value-for-parameter + return super().__new__(cls) def __init_subclass__(cls, discriminator: typing.Optional[str] = None) -> None: for base in cls.__bases__: @@ -633,7 +677,7 @@ def _deserialize(cls, data, exist_discriminators): discriminator_value = data.find(xml_name).text # pyright: ignore else: discriminator_value = data.get(discriminator._rest_name) - mapped_cls = cls.__mapping__.get(discriminator_value, cls) # pyright: ignore + mapped_cls = cls.__mapping__.get(discriminator_value, cls) # pyright: ignore # pylint: disable=no-member return mapped_cls._deserialize(data, exist_discriminators) def as_dict(self, *, exclude_readonly: bool = False) -> typing.Dict[str, typing.Any]: @@ -910,6 +954,19 @@ def _failsafe_deserialize( return None +def _failsafe_deserialize_xml( + deserializer: typing.Any, + value: typing.Any, +) -> typing.Any: + try: + return _deserialize_xml(deserializer, value) + except DeserializationError: + _LOGGER.warning( + "Ran into a deserialization error. Ignoring since this is failsafe deserialization", exc_info=True + ) + return None + + class _RestField: def __init__( self, diff --git a/sdk/communication/azure-communication-messages/azure/communication/messages/_serialization.py b/sdk/communication/azure-communication-messages/azure/communication/messages/_utils/serialization.py similarity index 94% rename from sdk/communication/azure-communication-messages/azure/communication/messages/_serialization.py rename to sdk/communication/azure-communication-messages/azure/communication/messages/_utils/serialization.py index b24ab2885450..eb86ea23c965 100644 --- a/sdk/communication/azure-communication-messages/azure/communication/messages/_serialization.py +++ b/sdk/communication/azure-communication-messages/azure/communication/messages/_utils/serialization.py @@ -1,28 +1,10 @@ -# pylint: disable=too-many-lines +# pylint: disable=line-too-long,useless-suppression,too-many-lines +# coding=utf-8 # -------------------------------------------------------------------------- -# # Copyright (c) Microsoft Corporation. All rights reserved. -# -# The MIT License (MIT) -# -# Permission is hereby granted, free of charge, to any person obtaining a copy -# of this software and associated documentation files (the ""Software""), to -# deal in the Software without restriction, including without limitation the -# rights to use, copy, modify, merge, publish, distribute, sublicense, and/or -# sell copies of the Software, and to permit persons to whom the Software is -# furnished to do so, subject to the following conditions: -# -# The above copyright notice and this permission notice shall be included in -# all copies or substantial portions of the Software. -# -# THE SOFTWARE IS PROVIDED *AS IS*, WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -# IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -# FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -# AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -# LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING -# FROM, OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS -# IN THE SOFTWARE. -# +# Licensed under the MIT License. See License.txt in the project root for license information. +# Code generated by Microsoft (R) Python Code Generator. +# Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- # pyright: reportUnnecessaryTypeIgnoreComment=false @@ -48,9 +30,7 @@ IO, Mapping, Callable, - TypeVar, MutableMapping, - Type, List, ) @@ -61,13 +41,13 @@ import xml.etree.ElementTree as ET import isodate # type: ignore +from typing_extensions import Self from azure.core.exceptions import DeserializationError, SerializationError from azure.core.serialization import NULL as CoreNull _BOM = codecs.BOM_UTF8.decode(encoding="utf-8") -ModelType = TypeVar("ModelType", bound="Model") JSON = MutableMapping[str, Any] @@ -185,73 +165,7 @@ def deserialize_from_http_generics(cls, body_bytes: Optional[Union[AnyStr, IO]], except NameError: _long_type = int - -class UTC(datetime.tzinfo): - """Time Zone info for handling UTC""" - - def utcoffset(self, dt): - """UTF offset for UTC is 0. - - :param datetime.datetime dt: The datetime - :returns: The offset - :rtype: datetime.timedelta - """ - return datetime.timedelta(0) - - def tzname(self, dt): - """Timestamp representation. - - :param datetime.datetime dt: The datetime - :returns: The timestamp representation - :rtype: str - """ - return "Z" - - def dst(self, dt): - """No daylight saving for UTC. - - :param datetime.datetime dt: The datetime - :returns: The daylight saving time - :rtype: datetime.timedelta - """ - return datetime.timedelta(hours=1) - - -try: - from datetime import timezone as _FixedOffset # type: ignore -except ImportError: # Python 2.7 - - class _FixedOffset(datetime.tzinfo): # type: ignore - """Fixed offset in minutes east from UTC. - Copy/pasted from Python doc - :param datetime.timedelta offset: offset in timedelta format - """ - - def __init__(self, offset) -> None: - self.__offset = offset - - def utcoffset(self, dt): - return self.__offset - - def tzname(self, dt): - return str(self.__offset.total_seconds() / 3600) - - def __repr__(self): - return "".format(self.tzname(None)) - - def dst(self, dt): - return datetime.timedelta(0) - - def __getinitargs__(self): - return (self.__offset,) - - -try: - from datetime import timezone - - TZ_UTC = timezone.utc -except ImportError: - TZ_UTC = UTC() # type: ignore +TZ_UTC = datetime.timezone.utc _FLATTEN = re.compile(r"(? ModelType: + def deserialize(cls, data: Any, content_type: Optional[str] = None) -> Self: """Parse a str using the RestAPI syntax and return a model. :param str data: A str using RestAPI structure. JSON by default. :param str content_type: JSON by default, set application/xml if XML. :returns: An instance of this model - :raises: DeserializationError if something went wrong - :rtype: ModelType + :raises DeserializationError: if something went wrong + :rtype: Self """ deserializer = Deserializer(cls._infer_class_models()) return deserializer(cls.__name__, data, content_type=content_type) # type: ignore @classmethod def from_dict( - cls: Type[ModelType], + cls, data: Any, key_extractors: Optional[Callable[[str, Dict[str, Any], Any], Any]] = None, content_type: Optional[str] = None, - ) -> ModelType: + ) -> Self: """Parse a dict using given key extractor return a model. By default consider key @@ -479,8 +393,8 @@ def from_dict( :param function key_extractors: A key extractor function. :param str content_type: JSON by default, set application/xml if XML. :returns: An instance of this model - :raises: DeserializationError if something went wrong - :rtype: ModelType + :raises DeserializationError: if something went wrong + :rtype: Self """ deserializer = Deserializer(cls._infer_class_models()) deserializer.key_extractors = ( # type: ignore @@ -626,7 +540,7 @@ def _serialize( # pylint: disable=too-many-nested-blocks, too-many-branches, to :param object target_obj: The data to be serialized. :param str data_type: The type to be serialized from. :rtype: str, dict - :raises: SerializationError if serialization fails. + :raises SerializationError: if serialization fails. :returns: The serialized data. """ key_transformer = kwargs.get("key_transformer", self.key_transformer) @@ -736,8 +650,8 @@ def body(self, data, data_type, **kwargs): :param object data: The data to be serialized. :param str data_type: The type to be serialized from. :rtype: dict - :raises: SerializationError if serialization fails. - :raises: ValueError if data is None + :raises SerializationError: if serialization fails. + :raises ValueError: if data is None :returns: The serialized request body """ @@ -781,8 +695,8 @@ def url(self, name, data, data_type, **kwargs): :param str data_type: The type to be serialized from. :rtype: str :returns: The serialized URL path - :raises: TypeError if serialization fails. - :raises: ValueError if data is None + :raises TypeError: if serialization fails. + :raises ValueError: if data is None """ try: output = self.serialize_data(data, data_type, **kwargs) @@ -805,8 +719,8 @@ def query(self, name, data, data_type, **kwargs): :param object data: The data to be serialized. :param str data_type: The type to be serialized from. :rtype: str, list - :raises: TypeError if serialization fails. - :raises: ValueError if data is None + :raises TypeError: if serialization fails. + :raises ValueError: if data is None :returns: The serialized query parameter """ try: @@ -835,8 +749,8 @@ def header(self, name, data, data_type, **kwargs): :param object data: The data to be serialized. :param str data_type: The type to be serialized from. :rtype: str - :raises: TypeError if serialization fails. - :raises: ValueError if data is None + :raises TypeError: if serialization fails. + :raises ValueError: if data is None :returns: The serialized header """ try: @@ -855,9 +769,9 @@ def serialize_data(self, data, data_type, **kwargs): :param object data: The data to be serialized. :param str data_type: The type to be serialized from. - :raises: AttributeError if required data is None. - :raises: ValueError if data is None - :raises: SerializationError if serialization fails. + :raises AttributeError: if required data is None. + :raises ValueError: if data is None + :raises SerializationError: if serialization fails. :returns: The serialized data. :rtype: str, int, float, bool, dict, list """ @@ -1192,7 +1106,7 @@ def serialize_rfc(attr, **kwargs): # pylint: disable=unused-argument :param Datetime attr: Object to be serialized. :rtype: str - :raises: TypeError if format invalid. + :raises TypeError: if format invalid. :return: serialized rfc """ try: @@ -1218,7 +1132,7 @@ def serialize_iso(attr, **kwargs): # pylint: disable=unused-argument :param Datetime attr: Object to be serialized. :rtype: str - :raises: SerializationError if format invalid. + :raises SerializationError: if format invalid. :return: serialized iso """ if isinstance(attr, str): @@ -1251,7 +1165,7 @@ def serialize_unix(attr, **kwargs): # pylint: disable=unused-argument :param Datetime attr: Object to be serialized. :rtype: int - :raises: SerializationError if format invalid + :raises SerializationError: if format invalid :return: serialied unix """ if isinstance(attr, int): @@ -1429,7 +1343,7 @@ def xml_key_extractor(attr, attr_desc, data): # pylint: disable=unused-argument # Iter and wrapped, should have found one node only (the wrap one) if len(children) != 1: raise DeserializationError( - "Tried to deserialize an array not wrapped, and found several nodes '{}'. Maybe you should declare this array as wrapped?".format( # pylint: disable=line-too-long + "Tried to deserialize an array not wrapped, and found several nodes '{}'. Maybe you should declare this array as wrapped?".format( xml_name ) ) @@ -1488,7 +1402,7 @@ def __call__(self, target_obj, response_data, content_type=None): :param str target_obj: Target data type to deserialize to. :param requests.Response response_data: REST response object. :param str content_type: Swagger "produces" if available. - :raises: DeserializationError if deserialization fails. + :raises DeserializationError: if deserialization fails. :return: Deserialized object. :rtype: object """ @@ -1502,7 +1416,7 @@ def _deserialize(self, target_obj, data): # pylint: disable=inconsistent-return :param str target_obj: Target data type to deserialize to. :param object data: Object to deserialize. - :raises: DeserializationError if deserialization fails. + :raises DeserializationError: if deserialization fails. :return: Deserialized object. :rtype: object """ @@ -1717,7 +1631,7 @@ def deserialize_data(self, data, data_type): # pylint: disable=too-many-return- :param str data: The response string to be deserialized. :param str data_type: The type to deserialize to. - :raises: DeserializationError if deserialization fails. + :raises DeserializationError: if deserialization fails. :return: Deserialized object. :rtype: object """ @@ -1799,7 +1713,7 @@ def deserialize_object(self, attr, **kwargs): # pylint: disable=too-many-return :param dict attr: Dictionary to be deserialized. :return: Deserialized object. :rtype: dict - :raises: TypeError if non-builtin datatype encountered. + :raises TypeError: if non-builtin datatype encountered. """ if attr is None: return None @@ -1845,7 +1759,7 @@ def deserialize_basic(self, attr, data_type): # pylint: disable=too-many-return :param str data_type: deserialization data type. :return: Deserialized basic type. :rtype: str, int, float or bool - :raises: TypeError if string format is not valid. + :raises TypeError: if string format is not valid. """ # If we're here, data is supposed to be a basic type. # If it's still an XML node, take the text @@ -1936,7 +1850,7 @@ def deserialize_bytearray(attr): :param str attr: response string to be deserialized. :return: Deserialized bytearray :rtype: bytearray - :raises: TypeError if string format invalid. + :raises TypeError: if string format invalid. """ if isinstance(attr, ET.Element): attr = attr.text @@ -1949,7 +1863,7 @@ def deserialize_base64(attr): :param str attr: response string to be deserialized. :return: Deserialized base64 string :rtype: bytearray - :raises: TypeError if string format invalid. + :raises TypeError: if string format invalid. """ if isinstance(attr, ET.Element): attr = attr.text @@ -1964,7 +1878,7 @@ def deserialize_decimal(attr): :param str attr: response string to be deserialized. :return: Deserialized decimal - :raises: DeserializationError if string format invalid. + :raises DeserializationError: if string format invalid. :rtype: decimal """ if isinstance(attr, ET.Element): @@ -1982,7 +1896,7 @@ def deserialize_long(attr): :param str attr: response string to be deserialized. :return: Deserialized int :rtype: long or int - :raises: ValueError if string format invalid. + :raises ValueError: if string format invalid. """ if isinstance(attr, ET.Element): attr = attr.text @@ -1995,7 +1909,7 @@ def deserialize_duration(attr): :param str attr: response string to be deserialized. :return: Deserialized duration :rtype: TimeDelta - :raises: DeserializationError if string format invalid. + :raises DeserializationError: if string format invalid. """ if isinstance(attr, ET.Element): attr = attr.text @@ -2013,7 +1927,7 @@ def deserialize_date(attr): :param str attr: response string to be deserialized. :return: Deserialized date :rtype: Date - :raises: DeserializationError if string format invalid. + :raises DeserializationError: if string format invalid. """ if isinstance(attr, ET.Element): attr = attr.text @@ -2029,7 +1943,7 @@ def deserialize_time(attr): :param str attr: response string to be deserialized. :return: Deserialized time :rtype: datetime.time - :raises: DeserializationError if string format invalid. + :raises DeserializationError: if string format invalid. """ if isinstance(attr, ET.Element): attr = attr.text @@ -2044,14 +1958,14 @@ def deserialize_rfc(attr): :param str attr: response string to be deserialized. :return: Deserialized RFC datetime :rtype: Datetime - :raises: DeserializationError if string format invalid. + :raises DeserializationError: if string format invalid. """ if isinstance(attr, ET.Element): attr = attr.text try: parsed_date = email.utils.parsedate_tz(attr) # type: ignore date_obj = datetime.datetime( - *parsed_date[:6], tzinfo=_FixedOffset(datetime.timedelta(minutes=(parsed_date[9] or 0) / 60)) + *parsed_date[:6], tzinfo=datetime.timezone(datetime.timedelta(minutes=(parsed_date[9] or 0) / 60)) ) if not date_obj.tzinfo: date_obj = date_obj.astimezone(tz=TZ_UTC) @@ -2067,7 +1981,7 @@ def deserialize_iso(attr): :param str attr: response string to be deserialized. :return: Deserialized ISO datetime :rtype: Datetime - :raises: DeserializationError if string format invalid. + :raises DeserializationError: if string format invalid. """ if isinstance(attr, ET.Element): attr = attr.text @@ -2105,7 +2019,7 @@ def deserialize_unix(attr): :param int attr: Object to be serialized. :return: Deserialized datetime :rtype: Datetime - :raises: DeserializationError if format invalid + :raises DeserializationError: if format invalid """ if isinstance(attr, ET.Element): attr = int(attr.text) # type: ignore diff --git a/sdk/communication/azure-communication-messages/azure/communication/messages/_vendor.py b/sdk/communication/azure-communication-messages/azure/communication/messages/_utils/utils.py similarity index 50% rename from sdk/communication/azure-communication-messages/azure/communication/messages/_vendor.py rename to sdk/communication/azure-communication-messages/azure/communication/messages/_utils/utils.py index 877478019c76..35c9c836f85f 100644 --- a/sdk/communication/azure-communication-messages/azure/communication/messages/_vendor.py +++ b/sdk/communication/azure-communication-messages/azure/communication/messages/_utils/utils.py @@ -6,29 +6,20 @@ # -------------------------------------------------------------------------- from abc import ABC -from typing import TYPE_CHECKING - -from ._configuration import MessageTemplateClientConfiguration, NotificationMessagesClientConfiguration +from typing import Generic, TYPE_CHECKING, TypeVar if TYPE_CHECKING: - from azure.core import PipelineClient - - from ._serialization import Deserializer, Serializer - + from .serialization import Deserializer, Serializer -class NotificationMessagesClientMixinABC(ABC): - """DO NOT use this class. It is for internal typing use only.""" - _client: "PipelineClient" - _config: NotificationMessagesClientConfiguration - _serialize: "Serializer" - _deserialize: "Deserializer" +TClient = TypeVar("TClient") +TConfig = TypeVar("TConfig") -class MessageTemplateClientMixinABC(ABC): +class ClientMixinABC(ABC, Generic[TClient, TConfig]): """DO NOT use this class. It is for internal typing use only.""" - _client: "PipelineClient" - _config: MessageTemplateClientConfiguration + _client: TClient + _config: TConfig _serialize: "Serializer" _deserialize: "Deserializer" diff --git a/sdk/communication/azure-communication-messages/azure/communication/messages/_validation.py b/sdk/communication/azure-communication-messages/azure/communication/messages/_validation.py new file mode 100644 index 000000000000..752b2822f9d3 --- /dev/null +++ b/sdk/communication/azure-communication-messages/azure/communication/messages/_validation.py @@ -0,0 +1,50 @@ +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# Code generated by Microsoft (R) Python Code Generator. +# Changes may cause incorrect behavior and will be lost if the code is regenerated. +# -------------------------------------------------------------------------- +import functools + + +def api_version_validation(**kwargs): + params_added_on = kwargs.pop("params_added_on", {}) + method_added_on = kwargs.pop("method_added_on", "") + + def decorator(func): + @functools.wraps(func) + def wrapper(*args, **kwargs): + try: + # this assumes the client has an _api_version attribute + client = args[0] + client_api_version = client._config.api_version # pylint: disable=protected-access + except AttributeError: + return func(*args, **kwargs) + + if method_added_on > client_api_version: + raise ValueError( + f"'{func.__name__}' is not available in API version " + f"{client_api_version}. Pass service API version {method_added_on} or newer to your client." + ) + + unsupported = { + parameter: api_version + for api_version, parameters in params_added_on.items() + for parameter in parameters + if parameter in kwargs and api_version > client_api_version + } + if unsupported: + raise ValueError( + "".join( + [ + f"'{param}' is not available in API version {client_api_version}. " + f"Use service API version {version} or newer.\n" + for param, version in unsupported.items() + ] + ) + ) + return func(*args, **kwargs) + + return wrapper + + return decorator diff --git a/sdk/communication/azure-communication-messages/azure/communication/messages/_version.py b/sdk/communication/azure-communication-messages/azure/communication/messages/_version.py index 5bf479b145f7..0ec13ea52bbf 100644 --- a/sdk/communication/azure-communication-messages/azure/communication/messages/_version.py +++ b/sdk/communication/azure-communication-messages/azure/communication/messages/_version.py @@ -6,4 +6,4 @@ # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- -VERSION = "1.2.0b1" +VERSION = "1.0.0" diff --git a/sdk/communication/azure-communication-messages/azure/communication/messages/aio/__init__.py b/sdk/communication/azure-communication-messages/azure/communication/messages/aio/__init__.py index b23d0eda98d1..cd865eb6f34f 100644 --- a/sdk/communication/azure-communication-messages/azure/communication/messages/aio/__init__.py +++ b/sdk/communication/azure-communication-messages/azure/communication/messages/aio/__init__.py @@ -14,6 +14,8 @@ from ._client import NotificationMessagesClient # type: ignore from ._client import MessageTemplateClient # type: ignore +from ._client import ConversationAdministrationClient # type: ignore +from ._client import ConversationThreadClient # type: ignore try: from ._patch import __all__ as _patch_all @@ -25,6 +27,8 @@ __all__ = [ "NotificationMessagesClient", "MessageTemplateClient", + "ConversationAdministrationClient", + "ConversationThreadClient", ] __all__.extend([p for p in _patch_all if p not in __all__]) # pyright: ignore diff --git a/sdk/communication/azure-communication-messages/azure/communication/messages/aio/_client.py b/sdk/communication/azure-communication-messages/azure/communication/messages/aio/_client.py index 71066f8c89ea..40c77c45d327 100644 --- a/sdk/communication/azure-communication-messages/azure/communication/messages/aio/_client.py +++ b/sdk/communication/azure-communication-messages/azure/communication/messages/aio/_client.py @@ -15,9 +15,19 @@ from azure.core.pipeline import policies from azure.core.rest import AsyncHttpResponse, HttpRequest -from .._serialization import Deserializer, Serializer -from ._configuration import MessageTemplateClientConfiguration, NotificationMessagesClientConfiguration -from ._operations import MessageTemplateClientOperationsMixin, NotificationMessagesClientOperationsMixin +from .._utils.serialization import Deserializer, Serializer +from ._configuration import ( + ConversationAdministrationClientConfiguration, + ConversationThreadClientConfiguration, + MessageTemplateClientConfiguration, + NotificationMessagesClientConfiguration, +) +from ._operations import ( + ConversationAdministrationClientOperationsMixin, + ConversationThreadClientOperationsMixin, + MessageTemplateClientOperationsMixin, + NotificationMessagesClientOperationsMixin, +) if TYPE_CHECKING: from azure.core.credentials_async import AsyncTokenCredential @@ -27,14 +37,15 @@ class NotificationMessagesClient(NotificationMessagesClientOperationsMixin): """NotificationMessagesClient. :param endpoint: The communication resource, for example - https://my-resource.communication.azure.com. Required. + `https://my-resource.communication.azure.com `_. + Required. :type endpoint: str :param credential: Credential used to authenticate requests to the service. Is either a token - credential type or a AzureKeyCredential type. Required. + credential type or a key credential type. Required. :type credential: ~azure.core.credentials_async.AsyncTokenCredential or - ~azure.core.credentials.AzureKeyCredential + ~azure.core.credentials.AzureKeyCredential or ~azure.core.credentials.AzureKeyCredential :keyword api_version: The API version to use for this operation. Default value is - "2025-01-15-preview". Note that overriding this default value may result in unsupported + "2025-04-01-preview". Note that overriding this default value may result in unsupported behavior. :paramtype api_version: str """ @@ -44,6 +55,7 @@ def __init__( ) -> None: _endpoint = "{endpoint}" self._config = NotificationMessagesClientConfiguration(endpoint=endpoint, credential=credential, **kwargs) + _policies = kwargs.pop("policies", None) if _policies is None: _policies = [ @@ -110,14 +122,15 @@ class MessageTemplateClient(MessageTemplateClientOperationsMixin): """MessageTemplateClient. :param endpoint: The communication resource, for example - https://my-resource.communication.azure.com. Required. + `https://my-resource.communication.azure.com `_. + Required. :type endpoint: str :param credential: Credential used to authenticate requests to the service. Is either a token - credential type or a AzureKeyCredential type. Required. + credential type or a key credential type. Required. :type credential: ~azure.core.credentials_async.AsyncTokenCredential or - ~azure.core.credentials.AzureKeyCredential + ~azure.core.credentials.AzureKeyCredential or ~azure.core.credentials.AzureKeyCredential :keyword api_version: The API version to use for this operation. Default value is - "2025-01-15-preview". Note that overriding this default value may result in unsupported + "2025-04-01-preview". Note that overriding this default value may result in unsupported behavior. :paramtype api_version: str """ @@ -127,6 +140,177 @@ def __init__( ) -> None: _endpoint = "{endpoint}" self._config = MessageTemplateClientConfiguration(endpoint=endpoint, credential=credential, **kwargs) + + _policies = kwargs.pop("policies", None) + if _policies is None: + _policies = [ + policies.RequestIdPolicy(**kwargs), + self._config.headers_policy, + self._config.user_agent_policy, + self._config.proxy_policy, + policies.ContentDecodePolicy(**kwargs), + self._config.redirect_policy, + self._config.retry_policy, + self._config.authentication_policy, + self._config.custom_hook_policy, + self._config.logging_policy, + policies.DistributedTracingPolicy(**kwargs), + policies.SensitiveHeaderCleanupPolicy(**kwargs) if self._config.redirect_policy else None, + self._config.http_logging_policy, + ] + self._client: AsyncPipelineClient = AsyncPipelineClient(base_url=_endpoint, policies=_policies, **kwargs) + + self._serialize = Serializer() + self._deserialize = Deserializer() + self._serialize.client_side_validation = False + + def send_request( + self, request: HttpRequest, *, stream: bool = False, **kwargs: Any + ) -> Awaitable[AsyncHttpResponse]: + """Runs the network request through the client's chained policies. + + >>> from azure.core.rest import HttpRequest + >>> request = HttpRequest("GET", "https://www.example.org/") + + >>> response = await client.send_request(request) + + + For more information on this code flow, see https://aka.ms/azsdk/dpcodegen/python/send_request + + :param request: The network request you want to make. Required. + :type request: ~azure.core.rest.HttpRequest + :keyword bool stream: Whether the response payload will be streamed. Defaults to False. + :return: The response of your network call. Does not do error handling on your response. + :rtype: ~azure.core.rest.AsyncHttpResponse + """ + + request_copy = deepcopy(request) + path_format_arguments = { + "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), + } + + request_copy.url = self._client.format_url(request_copy.url, **path_format_arguments) + return self._client.send_request(request_copy, stream=stream, **kwargs) # type: ignore + + async def close(self) -> None: + await self._client.close() + + async def __aenter__(self) -> Self: + await self._client.__aenter__() + return self + + async def __aexit__(self, *exc_details: Any) -> None: + await self._client.__aexit__(*exc_details) + + +class ConversationAdministrationClient(ConversationAdministrationClientOperationsMixin): + """ConversationAdministrationClient. + + :param endpoint: The communication resource, for example + `https://my-resource.communication.azure.com `_. + Required. + :type endpoint: str + :param credential: Credential used to authenticate requests to the service. Is either a token + credential type or a key credential type. Required. + :type credential: ~azure.core.credentials_async.AsyncTokenCredential or + ~azure.core.credentials.AzureKeyCredential or ~azure.core.credentials.AzureKeyCredential + :keyword api_version: The API version to use for this operation. Default value is + "2025-04-01-preview". Note that overriding this default value may result in unsupported + behavior. + :paramtype api_version: str + """ + + def __init__( + self, endpoint: str, credential: Union["AsyncTokenCredential", AzureKeyCredential], **kwargs: Any + ) -> None: + _endpoint = "{endpoint}" + self._config = ConversationAdministrationClientConfiguration(endpoint=endpoint, credential=credential, **kwargs) + + _policies = kwargs.pop("policies", None) + if _policies is None: + _policies = [ + policies.RequestIdPolicy(**kwargs), + self._config.headers_policy, + self._config.user_agent_policy, + self._config.proxy_policy, + policies.ContentDecodePolicy(**kwargs), + self._config.redirect_policy, + self._config.retry_policy, + self._config.authentication_policy, + self._config.custom_hook_policy, + self._config.logging_policy, + policies.DistributedTracingPolicy(**kwargs), + policies.SensitiveHeaderCleanupPolicy(**kwargs) if self._config.redirect_policy else None, + self._config.http_logging_policy, + ] + self._client: AsyncPipelineClient = AsyncPipelineClient(base_url=_endpoint, policies=_policies, **kwargs) + + self._serialize = Serializer() + self._deserialize = Deserializer() + self._serialize.client_side_validation = False + + def send_request( + self, request: HttpRequest, *, stream: bool = False, **kwargs: Any + ) -> Awaitable[AsyncHttpResponse]: + """Runs the network request through the client's chained policies. + + >>> from azure.core.rest import HttpRequest + >>> request = HttpRequest("GET", "https://www.example.org/") + + >>> response = await client.send_request(request) + + + For more information on this code flow, see https://aka.ms/azsdk/dpcodegen/python/send_request + + :param request: The network request you want to make. Required. + :type request: ~azure.core.rest.HttpRequest + :keyword bool stream: Whether the response payload will be streamed. Defaults to False. + :return: The response of your network call. Does not do error handling on your response. + :rtype: ~azure.core.rest.AsyncHttpResponse + """ + + request_copy = deepcopy(request) + path_format_arguments = { + "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), + } + + request_copy.url = self._client.format_url(request_copy.url, **path_format_arguments) + return self._client.send_request(request_copy, stream=stream, **kwargs) # type: ignore + + async def close(self) -> None: + await self._client.close() + + async def __aenter__(self) -> Self: + await self._client.__aenter__() + return self + + async def __aexit__(self, *exc_details: Any) -> None: + await self._client.__aexit__(*exc_details) + + +class ConversationThreadClient(ConversationThreadClientOperationsMixin): + """ConversationThreadClient. + + :param endpoint: The communication resource, for example + `https://my-resource.communication.azure.com `_. + Required. + :type endpoint: str + :param credential: Credential used to authenticate requests to the service. Is either a token + credential type or a key credential type. Required. + :type credential: ~azure.core.credentials_async.AsyncTokenCredential or + ~azure.core.credentials.AzureKeyCredential or ~azure.core.credentials.AzureKeyCredential + :keyword api_version: The API version to use for this operation. Default value is + "2025-04-01-preview". Note that overriding this default value may result in unsupported + behavior. + :paramtype api_version: str + """ + + def __init__( + self, endpoint: str, credential: Union["AsyncTokenCredential", AzureKeyCredential], **kwargs: Any + ) -> None: + _endpoint = "{endpoint}" + self._config = ConversationThreadClientConfiguration(endpoint=endpoint, credential=credential, **kwargs) + _policies = kwargs.pop("policies", None) if _policies is None: _policies = [ diff --git a/sdk/communication/azure-communication-messages/azure/communication/messages/aio/_configuration.py b/sdk/communication/azure-communication-messages/azure/communication/messages/aio/_configuration.py index abd8e1a53b27..1e2018a73051 100644 --- a/sdk/communication/azure-communication-messages/azure/communication/messages/aio/_configuration.py +++ b/sdk/communication/azure-communication-messages/azure/communication/messages/aio/_configuration.py @@ -24,14 +24,15 @@ class NotificationMessagesClientConfiguration: # pylint: disable=too-many-insta attributes. :param endpoint: The communication resource, for example - https://my-resource.communication.azure.com. Required. + `https://my-resource.communication.azure.com `_. + Required. :type endpoint: str :param credential: Credential used to authenticate requests to the service. Is either a token - credential type or a AzureKeyCredential type. Required. + credential type or a key credential type. Required. :type credential: ~azure.core.credentials_async.AsyncTokenCredential or - ~azure.core.credentials.AzureKeyCredential + ~azure.core.credentials.AzureKeyCredential or ~azure.core.credentials.AzureKeyCredential :keyword api_version: The API version to use for this operation. Default value is - "2025-01-15-preview". Note that overriding this default value may result in unsupported + "2025-04-01-preview". Note that overriding this default value may result in unsupported behavior. :paramtype api_version: str """ @@ -39,7 +40,7 @@ class NotificationMessagesClientConfiguration: # pylint: disable=too-many-insta def __init__( self, endpoint: str, credential: Union["AsyncTokenCredential", AzureKeyCredential], **kwargs: Any ) -> None: - api_version: str = kwargs.pop("api_version", "2025-01-15-preview") + api_version: str = kwargs.pop("api_version", "2025-04-01-preview") if endpoint is None: raise ValueError("Parameter 'endpoint' must not be None.") @@ -59,6 +60,8 @@ def _infer_policy(self, **kwargs): return policies.AsyncBearerTokenCredentialPolicy(self.credential, *self.credential_scopes, **kwargs) if isinstance(self.credential, AzureKeyCredential): return policies.AzureKeyCredentialPolicy(self.credential, "Authorization", **kwargs) + if isinstance(self.credential, AzureKeyCredential): + return policies.AzureKeyCredentialPolicy(self.credential, "Authorization", prefix="Bearer", **kwargs) raise TypeError(f"Unsupported credential: {self.credential}") def _configure(self, **kwargs: Any) -> None: @@ -82,14 +85,76 @@ class MessageTemplateClientConfiguration: # pylint: disable=too-many-instance-a attributes. :param endpoint: The communication resource, for example - https://my-resource.communication.azure.com. Required. + `https://my-resource.communication.azure.com `_. + Required. + :type endpoint: str + :param credential: Credential used to authenticate requests to the service. Is either a token + credential type or a key credential type. Required. + :type credential: ~azure.core.credentials_async.AsyncTokenCredential or + ~azure.core.credentials.AzureKeyCredential or ~azure.core.credentials.AzureKeyCredential + :keyword api_version: The API version to use for this operation. Default value is + "2025-04-01-preview". Note that overriding this default value may result in unsupported + behavior. + :paramtype api_version: str + """ + + def __init__( + self, endpoint: str, credential: Union["AsyncTokenCredential", AzureKeyCredential], **kwargs: Any + ) -> None: + api_version: str = kwargs.pop("api_version", "2025-04-01-preview") + + if endpoint is None: + raise ValueError("Parameter 'endpoint' must not be None.") + if credential is None: + raise ValueError("Parameter 'credential' must not be None.") + + self.endpoint = endpoint + self.credential = credential + self.api_version = api_version + self.credential_scopes = kwargs.pop("credential_scopes", ["https://communication.azure.com/.default"]) + kwargs.setdefault("sdk_moniker", "communication-messages/{}".format(VERSION)) + self.polling_interval = kwargs.get("polling_interval", 30) + self._configure(**kwargs) + + def _infer_policy(self, **kwargs): + if hasattr(self.credential, "get_token"): + return policies.AsyncBearerTokenCredentialPolicy(self.credential, *self.credential_scopes, **kwargs) + if isinstance(self.credential, AzureKeyCredential): + return policies.AzureKeyCredentialPolicy(self.credential, "Authorization", **kwargs) + if isinstance(self.credential, AzureKeyCredential): + return policies.AzureKeyCredentialPolicy(self.credential, "Authorization", prefix="Bearer", **kwargs) + raise TypeError(f"Unsupported credential: {self.credential}") + + def _configure(self, **kwargs: Any) -> None: + self.user_agent_policy = kwargs.get("user_agent_policy") or policies.UserAgentPolicy(**kwargs) + self.headers_policy = kwargs.get("headers_policy") or policies.HeadersPolicy(**kwargs) + self.proxy_policy = kwargs.get("proxy_policy") or policies.ProxyPolicy(**kwargs) + self.logging_policy = kwargs.get("logging_policy") or policies.NetworkTraceLoggingPolicy(**kwargs) + self.http_logging_policy = kwargs.get("http_logging_policy") or policies.HttpLoggingPolicy(**kwargs) + self.custom_hook_policy = kwargs.get("custom_hook_policy") or policies.CustomHookPolicy(**kwargs) + self.redirect_policy = kwargs.get("redirect_policy") or policies.AsyncRedirectPolicy(**kwargs) + self.retry_policy = kwargs.get("retry_policy") or policies.AsyncRetryPolicy(**kwargs) + self.authentication_policy = kwargs.get("authentication_policy") + if self.credential and not self.authentication_policy: + self.authentication_policy = self._infer_policy(**kwargs) + + +class ConversationAdministrationClientConfiguration: # pylint: disable=too-many-instance-attributes,name-too-long + """Configuration for ConversationAdministrationClient. + + Note that all parameters used to create this instance are saved as instance + attributes. + + :param endpoint: The communication resource, for example + `https://my-resource.communication.azure.com `_. + Required. :type endpoint: str :param credential: Credential used to authenticate requests to the service. Is either a token - credential type or a AzureKeyCredential type. Required. + credential type or a key credential type. Required. :type credential: ~azure.core.credentials_async.AsyncTokenCredential or - ~azure.core.credentials.AzureKeyCredential + ~azure.core.credentials.AzureKeyCredential or ~azure.core.credentials.AzureKeyCredential :keyword api_version: The API version to use for this operation. Default value is - "2025-01-15-preview". Note that overriding this default value may result in unsupported + "2025-04-01-preview". Note that overriding this default value may result in unsupported behavior. :paramtype api_version: str """ @@ -97,7 +162,7 @@ class MessageTemplateClientConfiguration: # pylint: disable=too-many-instance-a def __init__( self, endpoint: str, credential: Union["AsyncTokenCredential", AzureKeyCredential], **kwargs: Any ) -> None: - api_version: str = kwargs.pop("api_version", "2025-01-15-preview") + api_version: str = kwargs.pop("api_version", "2025-04-01-preview") if endpoint is None: raise ValueError("Parameter 'endpoint' must not be None.") @@ -117,6 +182,69 @@ def _infer_policy(self, **kwargs): return policies.AsyncBearerTokenCredentialPolicy(self.credential, *self.credential_scopes, **kwargs) if isinstance(self.credential, AzureKeyCredential): return policies.AzureKeyCredentialPolicy(self.credential, "Authorization", **kwargs) + if isinstance(self.credential, AzureKeyCredential): + return policies.AzureKeyCredentialPolicy(self.credential, "Authorization", prefix="Bearer", **kwargs) + raise TypeError(f"Unsupported credential: {self.credential}") + + def _configure(self, **kwargs: Any) -> None: + self.user_agent_policy = kwargs.get("user_agent_policy") or policies.UserAgentPolicy(**kwargs) + self.headers_policy = kwargs.get("headers_policy") or policies.HeadersPolicy(**kwargs) + self.proxy_policy = kwargs.get("proxy_policy") or policies.ProxyPolicy(**kwargs) + self.logging_policy = kwargs.get("logging_policy") or policies.NetworkTraceLoggingPolicy(**kwargs) + self.http_logging_policy = kwargs.get("http_logging_policy") or policies.HttpLoggingPolicy(**kwargs) + self.custom_hook_policy = kwargs.get("custom_hook_policy") or policies.CustomHookPolicy(**kwargs) + self.redirect_policy = kwargs.get("redirect_policy") or policies.AsyncRedirectPolicy(**kwargs) + self.retry_policy = kwargs.get("retry_policy") or policies.AsyncRetryPolicy(**kwargs) + self.authentication_policy = kwargs.get("authentication_policy") + if self.credential and not self.authentication_policy: + self.authentication_policy = self._infer_policy(**kwargs) + + +class ConversationThreadClientConfiguration: # pylint: disable=too-many-instance-attributes + """Configuration for ConversationThreadClient. + + Note that all parameters used to create this instance are saved as instance + attributes. + + :param endpoint: The communication resource, for example + `https://my-resource.communication.azure.com `_. + Required. + :type endpoint: str + :param credential: Credential used to authenticate requests to the service. Is either a token + credential type or a key credential type. Required. + :type credential: ~azure.core.credentials_async.AsyncTokenCredential or + ~azure.core.credentials.AzureKeyCredential or ~azure.core.credentials.AzureKeyCredential + :keyword api_version: The API version to use for this operation. Default value is + "2025-04-01-preview". Note that overriding this default value may result in unsupported + behavior. + :paramtype api_version: str + """ + + def __init__( + self, endpoint: str, credential: Union["AsyncTokenCredential", AzureKeyCredential], **kwargs: Any + ) -> None: + api_version: str = kwargs.pop("api_version", "2025-04-01-preview") + + if endpoint is None: + raise ValueError("Parameter 'endpoint' must not be None.") + if credential is None: + raise ValueError("Parameter 'credential' must not be None.") + + self.endpoint = endpoint + self.credential = credential + self.api_version = api_version + self.credential_scopes = kwargs.pop("credential_scopes", ["https://communication.azure.com/.default"]) + kwargs.setdefault("sdk_moniker", "communication-messages/{}".format(VERSION)) + self.polling_interval = kwargs.get("polling_interval", 30) + self._configure(**kwargs) + + def _infer_policy(self, **kwargs): + if hasattr(self.credential, "get_token"): + return policies.AsyncBearerTokenCredentialPolicy(self.credential, *self.credential_scopes, **kwargs) + if isinstance(self.credential, AzureKeyCredential): + return policies.AzureKeyCredentialPolicy(self.credential, "Authorization", **kwargs) + if isinstance(self.credential, AzureKeyCredential): + return policies.AzureKeyCredentialPolicy(self.credential, "Authorization", prefix="Bearer", **kwargs) raise TypeError(f"Unsupported credential: {self.credential}") def _configure(self, **kwargs: Any) -> None: diff --git a/sdk/communication/azure-communication-messages/azure/communication/messages/aio/_operations/__init__.py b/sdk/communication/azure-communication-messages/azure/communication/messages/aio/_operations/__init__.py index 5e78e7b2ee7c..95e745bec65c 100644 --- a/sdk/communication/azure-communication-messages/azure/communication/messages/aio/_operations/__init__.py +++ b/sdk/communication/azure-communication-messages/azure/communication/messages/aio/_operations/__init__.py @@ -14,6 +14,8 @@ from ._operations import NotificationMessagesClientOperationsMixin # type: ignore from ._operations import MessageTemplateClientOperationsMixin # type: ignore +from ._operations import ConversationAdministrationClientOperationsMixin # type: ignore +from ._operations import ConversationThreadClientOperationsMixin # type: ignore from ._patch import __all__ as _patch_all from ._patch import * @@ -22,6 +24,8 @@ __all__ = [ "NotificationMessagesClientOperationsMixin", "MessageTemplateClientOperationsMixin", + "ConversationAdministrationClientOperationsMixin", + "ConversationThreadClientOperationsMixin", ] __all__.extend([p for p in _patch_all if p not in __all__]) # pyright: ignore _patch_sdk() diff --git a/sdk/communication/azure-communication-messages/azure/communication/messages/aio/_operations/_operations.py b/sdk/communication/azure-communication-messages/azure/communication/messages/aio/_operations/_operations.py index 574698b25cdb..206d46a225aa 100644 --- a/sdk/communication/azure-communication-messages/azure/communication/messages/aio/_operations/_operations.py +++ b/sdk/communication/azure-communication-messages/azure/communication/messages/aio/_operations/_operations.py @@ -1,3 +1,4 @@ +# pylint: disable=line-too-long,useless-suppression,too-many-lines # coding=utf-8 # -------------------------------------------------------------------------- # Copyright (c) Microsoft Corporation. All rights reserved. @@ -5,12 +6,13 @@ # Code generated by Microsoft (R) Python Code Generator. # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- +from collections.abc import MutableMapping from io import IOBase import json -import sys from typing import Any, AsyncIterable, AsyncIterator, Callable, Dict, IO, List, Optional, TypeVar, Union, overload import urllib.parse +from azure.core import AsyncPipelineClient from azure.core.async_paging import AsyncItemPaged, AsyncList from azure.core.exceptions import ( ClientAuthenticationError, @@ -29,24 +31,45 @@ from azure.core.utils import case_insensitive_dict from ... import models as _models -from ..._model_base import SdkJSONEncoder, _deserialize from ..._operations._operations import ( + build_conversation_administration_add_participants_request, + build_conversation_administration_analyze_conversation_request, + build_conversation_administration_create_conversation_request, + build_conversation_administration_delete_conversation_request, + build_conversation_administration_get_conversation_request, + build_conversation_administration_list_conversations_request, + build_conversation_administration_list_messages_request, + build_conversation_administration_remove_participants_request, + build_conversation_administration_terminate_conversation_request, + build_conversation_thread_add_participants_request, + build_conversation_thread_analyze_conversation_request, + build_conversation_thread_list_conversations_request, + build_conversation_thread_list_messages_request, + build_conversation_thread_remove_participants_request, + build_conversation_thread_send_message_request, build_message_template_list_templates_request, build_notification_messages_download_media_request, build_notification_messages_send_request, ) -from .._vendor import MessageTemplateClientMixinABC, NotificationMessagesClientMixinABC +from ..._utils.model_base import SdkJSONEncoder, _deserialize +from ..._utils.utils import ClientMixinABC +from ..._validation import api_version_validation +from .._configuration import ( + ConversationAdministrationClientConfiguration, + ConversationThreadClientConfiguration, + MessageTemplateClientConfiguration, + NotificationMessagesClientConfiguration, +) -if sys.version_info >= (3, 9): - from collections.abc import MutableMapping -else: - from typing import MutableMapping # type: ignore -JSON = MutableMapping[str, Any] # pylint: disable=unsubscriptable-object +JSON = MutableMapping[str, Any] T = TypeVar("T") ClsType = Optional[Callable[[PipelineResponse[HttpRequest, AsyncHttpResponse], T, Dict[str, Any]], Any]] +_Unset: Any = object() -class NotificationMessagesClientOperationsMixin(NotificationMessagesClientMixinABC): # pylint: disable=name-too-long +class NotificationMessagesClientOperationsMixin( # pylint: disable=name-too-long + ClientMixinABC[AsyncPipelineClient[HttpRequest, AsyncHttpResponse], NotificationMessagesClientConfiguration] +): @overload async def send( @@ -240,14 +263,20 @@ async def download_media(self, id: str, **kwargs: Any) -> AsyncIterator[bytes]: return deserialized # type: ignore -class MessageTemplateClientOperationsMixin(MessageTemplateClientMixinABC): +class MessageTemplateClientOperationsMixin( + ClientMixinABC[AsyncPipelineClient[HttpRequest, AsyncHttpResponse], MessageTemplateClientConfiguration] +): @distributed_trace - def list_templates(self, channel_id: str, **kwargs: Any) -> AsyncIterable["_models.MessageTemplateItem"]: + def list_templates( + self, channel_id: str, *, max_page_size: Optional[int] = None, **kwargs: Any + ) -> AsyncIterable["_models.MessageTemplateItem"]: """List all templates for given Azure Communication Services channel. :param channel_id: The registration ID of the channel. Required. :type channel_id: str + :keyword max_page_size: Number of objects to return per page. Default value is None. + :paramtype max_page_size: int :return: An iterator like instance of MessageTemplateItem :rtype: ~azure.core.async_paging.AsyncItemPaged[~azure.communication.messages.models.MessageTemplateItem] @@ -256,7 +285,6 @@ def list_templates(self, channel_id: str, **kwargs: Any) -> AsyncIterable["_mode _headers = kwargs.pop("headers", {}) or {} _params = kwargs.pop("params", {}) or {} - maxpagesize = kwargs.pop("maxpagesize", None) cls: ClsType[List[_models.MessageTemplateItem]] = kwargs.pop("cls", None) error_map: MutableMapping = { @@ -272,7 +300,7 @@ def prepare_request(next_link=None): _request = build_message_template_list_templates_request( channel_id=channel_id, - maxpagesize=maxpagesize, + max_page_size=max_page_size, api_version=self._config.api_version, headers=_headers, params=_params, @@ -308,7 +336,7 @@ def prepare_request(next_link=None): async def extract_data(pipeline_response): deserialized = pipeline_response.http_response.json() - list_of_elem = _deserialize(List[_models.MessageTemplateItem], deserialized["value"]) + list_of_elem = _deserialize(List[_models.MessageTemplateItem], deserialized.get("value", [])) if cls: list_of_elem = cls(list_of_elem) # type: ignore return deserialized.get("nextLink") or None, AsyncList(list_of_elem) @@ -329,3 +357,1804 @@ async def get_next(next_link=None): return pipeline_response return AsyncItemPaged(get_next, extract_data) + + +class ConversationAdministrationClientOperationsMixin( # pylint: disable=name-too-long + ClientMixinABC[AsyncPipelineClient[HttpRequest, AsyncHttpResponse], ConversationAdministrationClientConfiguration] +): + + @overload + async def create_conversation( + self, + *, + conversation: _models.CommunicationConversation, + content_type: str = "application/json", + initial_message: Optional[_models.Message] = None, + **kwargs: Any + ) -> _models.CommunicationConversation: + """Creates a new conversation. This is only for create operation. + + :keyword conversation: The conversation details. Required. + :paramtype conversation: ~azure.communication.messages.models.CommunicationConversation + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/json". + :paramtype content_type: str + :keyword initial_message: An initial message within the conversation. Default value is None. + :paramtype initial_message: ~azure.communication.messages.models.Message + :return: CommunicationConversation. The CommunicationConversation is compatible with + MutableMapping + :rtype: ~azure.communication.messages.models.CommunicationConversation + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @overload + async def create_conversation( + self, body: JSON, *, content_type: str = "application/json", **kwargs: Any + ) -> _models.CommunicationConversation: + """Creates a new conversation. This is only for create operation. + + :param body: Required. + :type body: JSON + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/json". + :paramtype content_type: str + :return: CommunicationConversation. The CommunicationConversation is compatible with + MutableMapping + :rtype: ~azure.communication.messages.models.CommunicationConversation + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @overload + async def create_conversation( + self, body: IO[bytes], *, content_type: str = "application/json", **kwargs: Any + ) -> _models.CommunicationConversation: + """Creates a new conversation. This is only for create operation. + + :param body: Required. + :type body: IO[bytes] + :keyword content_type: Body Parameter content-type. Content type parameter for binary body. + Default value is "application/json". + :paramtype content_type: str + :return: CommunicationConversation. The CommunicationConversation is compatible with + MutableMapping + :rtype: ~azure.communication.messages.models.CommunicationConversation + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @distributed_trace_async + @api_version_validation( + method_added_on="2025-04-01-preview", + params_added_on={"2025-04-01-preview": ["endpoint", "api_version", "content_type", "accept"]}, + ) + async def create_conversation( + self, + body: Union[JSON, IO[bytes]] = _Unset, + *, + conversation: _models.CommunicationConversation = _Unset, + initial_message: Optional[_models.Message] = None, + **kwargs: Any + ) -> _models.CommunicationConversation: + """Creates a new conversation. This is only for create operation. + + :param body: Is either a JSON type or a IO[bytes] type. Required. + :type body: JSON or IO[bytes] + :keyword conversation: The conversation details. Required. + :paramtype conversation: ~azure.communication.messages.models.CommunicationConversation + :keyword initial_message: An initial message within the conversation. Default value is None. + :paramtype initial_message: ~azure.communication.messages.models.Message + :return: CommunicationConversation. The CommunicationConversation is compatible with + MutableMapping + :rtype: ~azure.communication.messages.models.CommunicationConversation + :raises ~azure.core.exceptions.HttpResponseError: + """ + error_map: MutableMapping = { + 401: ClientAuthenticationError, + 404: ResourceNotFoundError, + 409: ResourceExistsError, + 304: ResourceNotModifiedError, + } + error_map.update(kwargs.pop("error_map", {}) or {}) + + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) + _params = kwargs.pop("params", {}) or {} + + content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) + cls: ClsType[_models.CommunicationConversation] = kwargs.pop("cls", None) + + if body is _Unset: + if conversation is _Unset: + raise TypeError("missing required argument: conversation") + body = {"conversation": conversation, "initialMessage": initial_message} + body = {k: v for k, v in body.items() if v is not None} + content_type = content_type or "application/json" + _content = None + if isinstance(body, (IOBase, bytes)): + _content = body + else: + _content = json.dumps(body, cls=SdkJSONEncoder, exclude_readonly=True) # type: ignore + + _request = build_conversation_administration_create_conversation_request( + content_type=content_type, + api_version=self._config.api_version, + content=_content, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + + _stream = kwargs.pop("stream", False) + pipeline_response: PipelineResponse = await self._client._pipeline.run( # type: ignore # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + + response = pipeline_response.http_response + + if response.status_code not in [201]: + if _stream: + try: + await response.read() # Load the body in memory and close the socket + except (StreamConsumedError, StreamClosedError): + pass + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + if _stream: + deserialized = response.iter_bytes() + else: + deserialized = _deserialize(_models.CommunicationConversation, response.json()) + + if cls: + return cls(pipeline_response, deserialized, {}) # type: ignore + + return deserialized # type: ignore + + @distributed_trace_async + @api_version_validation( + method_added_on="2025-04-01-preview", + params_added_on={ + "2025-04-01-preview": ["endpoint", "api_version", "conversation_id", "client_request_id", "accept"] + }, + ) + async def get_conversation(self, conversation_id: str, **kwargs: Any) -> _models.CommunicationConversation: + """Gets the details of a specific conversation. + + :param conversation_id: The conversation ID. Required. + :type conversation_id: str + :return: CommunicationConversation. The CommunicationConversation is compatible with + MutableMapping + :rtype: ~azure.communication.messages.models.CommunicationConversation + :raises ~azure.core.exceptions.HttpResponseError: + """ + error_map: MutableMapping = { + 401: ClientAuthenticationError, + 404: ResourceNotFoundError, + 409: ResourceExistsError, + 304: ResourceNotModifiedError, + } + error_map.update(kwargs.pop("error_map", {}) or {}) + + _headers = kwargs.pop("headers", {}) or {} + _params = kwargs.pop("params", {}) or {} + + cls: ClsType[_models.CommunicationConversation] = kwargs.pop("cls", None) + + _request = build_conversation_administration_get_conversation_request( + conversation_id=conversation_id, + api_version=self._config.api_version, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + + _stream = kwargs.pop("stream", False) + pipeline_response: PipelineResponse = await self._client._pipeline.run( # type: ignore # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + + response = pipeline_response.http_response + + if response.status_code not in [200]: + if _stream: + try: + await response.read() # Load the body in memory and close the socket + except (StreamConsumedError, StreamClosedError): + pass + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + response_headers = {} + response_headers["x-ms-client-request-id"] = self._deserialize( + "str", response.headers.get("x-ms-client-request-id") + ) + + if _stream: + deserialized = response.iter_bytes() + else: + deserialized = _deserialize(_models.CommunicationConversation, response.json()) + + if cls: + return cls(pipeline_response, deserialized, response_headers) # type: ignore + + return deserialized # type: ignore + + @distributed_trace_async + @api_version_validation( + method_added_on="2025-04-01-preview", + params_added_on={ + "2025-04-01-preview": [ + "endpoint", + "api_version", + "conversation_id", + "repeatability_request_id", + "repeatability_first_sent", + "client_request_id", + "accept", + ] + }, + ) + async def delete_conversation(self, conversation_id: str, **kwargs: Any) -> None: + """Deletes a specific conversation. + + :param conversation_id: The conversation ID. Required. + :type conversation_id: str + :return: None + :rtype: None + :raises ~azure.core.exceptions.HttpResponseError: + """ + error_map: MutableMapping = { + 401: ClientAuthenticationError, + 404: ResourceNotFoundError, + 409: ResourceExistsError, + 304: ResourceNotModifiedError, + } + error_map.update(kwargs.pop("error_map", {}) or {}) + + _headers = kwargs.pop("headers", {}) or {} + _params = kwargs.pop("params", {}) or {} + + cls: ClsType[None] = kwargs.pop("cls", None) + + _request = build_conversation_administration_delete_conversation_request( + conversation_id=conversation_id, + api_version=self._config.api_version, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + + _stream = False + pipeline_response: PipelineResponse = await self._client._pipeline.run( # type: ignore # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + + response = pipeline_response.http_response + + if response.status_code not in [204]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + response_headers = {} + response_headers["Repeatability-Result"] = self._deserialize( + "str", response.headers.get("Repeatability-Result") + ) + response_headers["x-ms-client-request-id"] = self._deserialize( + "str", response.headers.get("x-ms-client-request-id") + ) + + if cls: + return cls(pipeline_response, None, response_headers) # type: ignore + + @distributed_trace_async + @api_version_validation( + method_added_on="2025-04-01-preview", + params_added_on={ + "2025-04-01-preview": [ + "endpoint", + "api_version", + "conversation_id", + "repeatability_request_id", + "repeatability_first_sent", + "client_request_id", + "accept", + ] + }, + ) + async def terminate_conversation(self, conversation_id: str, **kwargs: Any) -> None: + """Terminates a specific conversation. + + :param conversation_id: The conversation ID. Required. + :type conversation_id: str + :return: None + :rtype: None + :raises ~azure.core.exceptions.HttpResponseError: + """ + error_map: MutableMapping = { + 401: ClientAuthenticationError, + 404: ResourceNotFoundError, + 409: ResourceExistsError, + 304: ResourceNotModifiedError, + } + error_map.update(kwargs.pop("error_map", {}) or {}) + + _headers = kwargs.pop("headers", {}) or {} + _params = kwargs.pop("params", {}) or {} + + cls: ClsType[None] = kwargs.pop("cls", None) + + _request = build_conversation_administration_terminate_conversation_request( + conversation_id=conversation_id, + api_version=self._config.api_version, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + + _stream = False + pipeline_response: PipelineResponse = await self._client._pipeline.run( # type: ignore # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + response_headers = {} + response_headers["Repeatability-Result"] = self._deserialize( + "str", response.headers.get("Repeatability-Result") + ) + response_headers["x-ms-client-request-id"] = self._deserialize( + "str", response.headers.get("x-ms-client-request-id") + ) + + if cls: + return cls(pipeline_response, None, response_headers) # type: ignore + + @distributed_trace + @api_version_validation( + method_added_on="2025-04-01-preview", + params_added_on={ + "2025-04-01-preview": [ + "endpoint", + "api_version", + "max_page_size", + "participant_id", + "channel_id", + "client_request_id", + "accept", + ] + }, + ) + def list_conversations( + self, + *, + max_page_size: Optional[int] = None, + participant_id: Optional[str] = None, + channel_id: Optional[str] = None, + **kwargs: Any + ) -> AsyncIterable["_models.CommunicationConversation"]: + """Retrieves list of conversations. + + :keyword max_page_size: Number of objects to return per page. Default value is None. + :paramtype max_page_size: int + :keyword participant_id: The participant user ID. Default value is None. + :paramtype participant_id: str + :keyword channel_id: The id of channel. Default value is None. + :paramtype channel_id: str + :return: An iterator like instance of CommunicationConversation + :rtype: + ~azure.core.async_paging.AsyncItemPaged[~azure.communication.messages.models.CommunicationConversation] + :raises ~azure.core.exceptions.HttpResponseError: + """ + _headers = kwargs.pop("headers", {}) or {} + _params = kwargs.pop("params", {}) or {} + + cls: ClsType[List[_models.CommunicationConversation]] = kwargs.pop("cls", None) + + error_map: MutableMapping = { + 401: ClientAuthenticationError, + 404: ResourceNotFoundError, + 409: ResourceExistsError, + 304: ResourceNotModifiedError, + } + error_map.update(kwargs.pop("error_map", {}) or {}) + + def prepare_request(next_link=None): + if not next_link: + + _request = build_conversation_administration_list_conversations_request( + max_page_size=max_page_size, + participant_id=participant_id, + channel_id=channel_id, + api_version=self._config.api_version, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url( + "self._config.endpoint", self._config.endpoint, "str", skip_quote=True + ), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + + else: + # make call to next link with the client's api-version + _parsed_next_link = urllib.parse.urlparse(next_link) + _next_request_params = case_insensitive_dict( + { + key: [urllib.parse.quote(v) for v in value] + for key, value in urllib.parse.parse_qs(_parsed_next_link.query).items() + } + ) + _next_request_params["api-version"] = self._config.api_version + _request = HttpRequest( + "GET", urllib.parse.urljoin(next_link, _parsed_next_link.path), params=_next_request_params + ) + path_format_arguments = { + "endpoint": self._serialize.url( + "self._config.endpoint", self._config.endpoint, "str", skip_quote=True + ), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + + return _request + + async def extract_data(pipeline_response): + deserialized = pipeline_response.http_response.json() + list_of_elem = _deserialize(List[_models.CommunicationConversation], deserialized.get("value", [])) + if cls: + list_of_elem = cls(list_of_elem) # type: ignore + return deserialized.get("nextLink") or None, AsyncList(list_of_elem) + + async def get_next(next_link=None): + _request = prepare_request(next_link) + + _stream = False + pipeline_response: PipelineResponse = await self._client._pipeline.run( # type: ignore # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + return pipeline_response + + return AsyncItemPaged(get_next, extract_data) + + @distributed_trace + @api_version_validation( + method_added_on="2025-04-01-preview", + params_added_on={ + "2025-04-01-preview": [ + "endpoint", + "api_version", + "conversation_id", + "max_page_size", + "participant_id", + "client_request_id", + "accept", + ] + }, + ) + def list_messages( + self, + conversation_id: str, + *, + max_page_size: Optional[int] = None, + participant_id: Optional[str] = None, + **kwargs: Any + ) -> AsyncIterable["_models.ConversationMessageItem"]: + """Retrieves list of conversation messages. + + :param conversation_id: The conversation ID. Required. + :type conversation_id: str + :keyword max_page_size: Number of objects to return per page. Default value is None. + :paramtype max_page_size: int + :keyword participant_id: The participant user ID. Default value is None. + :paramtype participant_id: str + :return: An iterator like instance of ConversationMessageItem + :rtype: + ~azure.core.async_paging.AsyncItemPaged[~azure.communication.messages.models.ConversationMessageItem] + :raises ~azure.core.exceptions.HttpResponseError: + """ + _headers = kwargs.pop("headers", {}) or {} + _params = kwargs.pop("params", {}) or {} + + cls: ClsType[List[_models.ConversationMessageItem]] = kwargs.pop("cls", None) + + error_map: MutableMapping = { + 401: ClientAuthenticationError, + 404: ResourceNotFoundError, + 409: ResourceExistsError, + 304: ResourceNotModifiedError, + } + error_map.update(kwargs.pop("error_map", {}) or {}) + + def prepare_request(next_link=None): + if not next_link: + + _request = build_conversation_administration_list_messages_request( + conversation_id=conversation_id, + max_page_size=max_page_size, + participant_id=participant_id, + api_version=self._config.api_version, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url( + "self._config.endpoint", self._config.endpoint, "str", skip_quote=True + ), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + + else: + # make call to next link with the client's api-version + _parsed_next_link = urllib.parse.urlparse(next_link) + _next_request_params = case_insensitive_dict( + { + key: [urllib.parse.quote(v) for v in value] + for key, value in urllib.parse.parse_qs(_parsed_next_link.query).items() + } + ) + _next_request_params["api-version"] = self._config.api_version + _request = HttpRequest( + "GET", urllib.parse.urljoin(next_link, _parsed_next_link.path), params=_next_request_params + ) + path_format_arguments = { + "endpoint": self._serialize.url( + "self._config.endpoint", self._config.endpoint, "str", skip_quote=True + ), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + + return _request + + async def extract_data(pipeline_response): + deserialized = pipeline_response.http_response.json() + list_of_elem = _deserialize(List[_models.ConversationMessageItem], deserialized.get("value", [])) + if cls: + list_of_elem = cls(list_of_elem) # type: ignore + return deserialized.get("nextLink") or None, AsyncList(list_of_elem) + + async def get_next(next_link=None): + _request = prepare_request(next_link) + + _stream = False + pipeline_response: PipelineResponse = await self._client._pipeline.run( # type: ignore # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + return pipeline_response + + return AsyncItemPaged(get_next, extract_data) + + @overload + async def add_participants( + self, + conversation_id: str, + options: _models.AddParticipantsOptions, + *, + content_type: str = "application/json", + **kwargs: Any + ) -> _models.AddParticipantsResult: + """Adds participants to a specific conversation. + + :param conversation_id: The conversation ID. Required. + :type conversation_id: str + :param options: Details of the payload for adding participants to a conversation. Required. + :type options: ~azure.communication.messages.models.AddParticipantsOptions + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/json". + :paramtype content_type: str + :return: AddParticipantsResult. The AddParticipantsResult is compatible with MutableMapping + :rtype: ~azure.communication.messages.models.AddParticipantsResult + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @overload + async def add_participants( + self, conversation_id: str, options: JSON, *, content_type: str = "application/json", **kwargs: Any + ) -> _models.AddParticipantsResult: + """Adds participants to a specific conversation. + + :param conversation_id: The conversation ID. Required. + :type conversation_id: str + :param options: Details of the payload for adding participants to a conversation. Required. + :type options: JSON + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/json". + :paramtype content_type: str + :return: AddParticipantsResult. The AddParticipantsResult is compatible with MutableMapping + :rtype: ~azure.communication.messages.models.AddParticipantsResult + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @overload + async def add_participants( + self, conversation_id: str, options: IO[bytes], *, content_type: str = "application/json", **kwargs: Any + ) -> _models.AddParticipantsResult: + """Adds participants to a specific conversation. + + :param conversation_id: The conversation ID. Required. + :type conversation_id: str + :param options: Details of the payload for adding participants to a conversation. Required. + :type options: IO[bytes] + :keyword content_type: Body Parameter content-type. Content type parameter for binary body. + Default value is "application/json". + :paramtype content_type: str + :return: AddParticipantsResult. The AddParticipantsResult is compatible with MutableMapping + :rtype: ~azure.communication.messages.models.AddParticipantsResult + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @distributed_trace_async + @api_version_validation( + method_added_on="2025-04-01-preview", + params_added_on={ + "2025-04-01-preview": [ + "endpoint", + "api_version", + "conversation_id", + "repeatability_request_id", + "repeatability_first_sent", + "client_request_id", + "content_type", + "accept", + ] + }, + ) + async def add_participants( + self, conversation_id: str, options: Union[_models.AddParticipantsOptions, JSON, IO[bytes]], **kwargs: Any + ) -> _models.AddParticipantsResult: + """Adds participants to a specific conversation. + + :param conversation_id: The conversation ID. Required. + :type conversation_id: str + :param options: Details of the payload for adding participants to a conversation. Is one of the + following types: AddParticipantsOptions, JSON, IO[bytes] Required. + :type options: ~azure.communication.messages.models.AddParticipantsOptions or JSON or IO[bytes] + :return: AddParticipantsResult. The AddParticipantsResult is compatible with MutableMapping + :rtype: ~azure.communication.messages.models.AddParticipantsResult + :raises ~azure.core.exceptions.HttpResponseError: + """ + error_map: MutableMapping = { + 401: ClientAuthenticationError, + 404: ResourceNotFoundError, + 409: ResourceExistsError, + 304: ResourceNotModifiedError, + } + error_map.update(kwargs.pop("error_map", {}) or {}) + + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) + _params = kwargs.pop("params", {}) or {} + + content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) + cls: ClsType[_models.AddParticipantsResult] = kwargs.pop("cls", None) + + content_type = content_type or "application/json" + _content = None + if isinstance(options, (IOBase, bytes)): + _content = options + else: + _content = json.dumps(options, cls=SdkJSONEncoder, exclude_readonly=True) # type: ignore + + _request = build_conversation_administration_add_participants_request( + conversation_id=conversation_id, + content_type=content_type, + api_version=self._config.api_version, + content=_content, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + + _stream = kwargs.pop("stream", False) + pipeline_response: PipelineResponse = await self._client._pipeline.run( # type: ignore # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + + response = pipeline_response.http_response + + if response.status_code not in [207]: + if _stream: + try: + await response.read() # Load the body in memory and close the socket + except (StreamConsumedError, StreamClosedError): + pass + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + response_headers = {} + response_headers["Repeatability-Result"] = self._deserialize( + "str", response.headers.get("Repeatability-Result") + ) + response_headers["x-ms-client-request-id"] = self._deserialize( + "str", response.headers.get("x-ms-client-request-id") + ) + + if _stream: + deserialized = response.iter_bytes() + else: + deserialized = _deserialize(_models.AddParticipantsResult, response.json()) + + if cls: + return cls(pipeline_response, deserialized, response_headers) # type: ignore + + return deserialized # type: ignore + + @overload + async def remove_participants( + self, + conversation_id: str, + options: _models.RemoveParticipantsOptions, + *, + content_type: str = "application/json", + **kwargs: Any + ) -> _models.RemoveParticipantsResult: + """remove a participant from a conversation. + + :param conversation_id: The conversation ID. Required. + :type conversation_id: str + :param options: Details of the request body for removing participants from a conversation. + Required. + :type options: ~azure.communication.messages.models.RemoveParticipantsOptions + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/json". + :paramtype content_type: str + :return: RemoveParticipantsResult. The RemoveParticipantsResult is compatible with + MutableMapping + :rtype: ~azure.communication.messages.models.RemoveParticipantsResult + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @overload + async def remove_participants( + self, conversation_id: str, options: JSON, *, content_type: str = "application/json", **kwargs: Any + ) -> _models.RemoveParticipantsResult: + """remove a participant from a conversation. + + :param conversation_id: The conversation ID. Required. + :type conversation_id: str + :param options: Details of the request body for removing participants from a conversation. + Required. + :type options: JSON + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/json". + :paramtype content_type: str + :return: RemoveParticipantsResult. The RemoveParticipantsResult is compatible with + MutableMapping + :rtype: ~azure.communication.messages.models.RemoveParticipantsResult + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @overload + async def remove_participants( + self, conversation_id: str, options: IO[bytes], *, content_type: str = "application/json", **kwargs: Any + ) -> _models.RemoveParticipantsResult: + """remove a participant from a conversation. + + :param conversation_id: The conversation ID. Required. + :type conversation_id: str + :param options: Details of the request body for removing participants from a conversation. + Required. + :type options: IO[bytes] + :keyword content_type: Body Parameter content-type. Content type parameter for binary body. + Default value is "application/json". + :paramtype content_type: str + :return: RemoveParticipantsResult. The RemoveParticipantsResult is compatible with + MutableMapping + :rtype: ~azure.communication.messages.models.RemoveParticipantsResult + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @distributed_trace_async + @api_version_validation( + method_added_on="2025-04-01-preview", + params_added_on={ + "2025-04-01-preview": [ + "endpoint", + "api_version", + "conversation_id", + "repeatability_request_id", + "repeatability_first_sent", + "client_request_id", + "content_type", + "accept", + ] + }, + ) + async def remove_participants( + self, conversation_id: str, options: Union[_models.RemoveParticipantsOptions, JSON, IO[bytes]], **kwargs: Any + ) -> _models.RemoveParticipantsResult: + """remove a participant from a conversation. + + :param conversation_id: The conversation ID. Required. + :type conversation_id: str + :param options: Details of the request body for removing participants from a conversation. Is + one of the following types: RemoveParticipantsOptions, JSON, IO[bytes] Required. + :type options: ~azure.communication.messages.models.RemoveParticipantsOptions or JSON or + IO[bytes] + :return: RemoveParticipantsResult. The RemoveParticipantsResult is compatible with + MutableMapping + :rtype: ~azure.communication.messages.models.RemoveParticipantsResult + :raises ~azure.core.exceptions.HttpResponseError: + """ + error_map: MutableMapping = { + 401: ClientAuthenticationError, + 404: ResourceNotFoundError, + 409: ResourceExistsError, + 304: ResourceNotModifiedError, + } + error_map.update(kwargs.pop("error_map", {}) or {}) + + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) + _params = kwargs.pop("params", {}) or {} + + content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) + cls: ClsType[_models.RemoveParticipantsResult] = kwargs.pop("cls", None) + + content_type = content_type or "application/json" + _content = None + if isinstance(options, (IOBase, bytes)): + _content = options + else: + _content = json.dumps(options, cls=SdkJSONEncoder, exclude_readonly=True) # type: ignore + + _request = build_conversation_administration_remove_participants_request( + conversation_id=conversation_id, + content_type=content_type, + api_version=self._config.api_version, + content=_content, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + + _stream = kwargs.pop("stream", False) + pipeline_response: PipelineResponse = await self._client._pipeline.run( # type: ignore # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + + response = pipeline_response.http_response + + if response.status_code not in [207]: + if _stream: + try: + await response.read() # Load the body in memory and close the socket + except (StreamConsumedError, StreamClosedError): + pass + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + response_headers = {} + response_headers["Repeatability-Result"] = self._deserialize( + "str", response.headers.get("Repeatability-Result") + ) + response_headers["x-ms-client-request-id"] = self._deserialize( + "str", response.headers.get("x-ms-client-request-id") + ) + + if _stream: + deserialized = response.iter_bytes() + else: + deserialized = _deserialize(_models.RemoveParticipantsResult, response.json()) + + if cls: + return cls(pipeline_response, deserialized, response_headers) # type: ignore + + return deserialized # type: ignore + + @distributed_trace_async + @api_version_validation( + method_added_on="2025-04-01-preview", + params_added_on={ + "2025-04-01-preview": [ + "endpoint", + "api_version", + "conversation_id", + "repeatability_request_id", + "repeatability_first_sent", + "client_request_id", + "accept", + ] + }, + ) + async def analyze_conversation( + self, conversation_id: str, **kwargs: Any + ) -> _models.GetConversationThreadAnalysisResult: + """Get AI Analysis of a conversation. + + :param conversation_id: The conversation ID. Required. + :type conversation_id: str + :return: GetConversationThreadAnalysisResult. The GetConversationThreadAnalysisResult is + compatible with MutableMapping + :rtype: ~azure.communication.messages.models.GetConversationThreadAnalysisResult + :raises ~azure.core.exceptions.HttpResponseError: + """ + error_map: MutableMapping = { + 401: ClientAuthenticationError, + 404: ResourceNotFoundError, + 409: ResourceExistsError, + 304: ResourceNotModifiedError, + } + error_map.update(kwargs.pop("error_map", {}) or {}) + + _headers = kwargs.pop("headers", {}) or {} + _params = kwargs.pop("params", {}) or {} + + cls: ClsType[_models.GetConversationThreadAnalysisResult] = kwargs.pop("cls", None) + + _request = build_conversation_administration_analyze_conversation_request( + conversation_id=conversation_id, + api_version=self._config.api_version, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + + _stream = kwargs.pop("stream", False) + pipeline_response: PipelineResponse = await self._client._pipeline.run( # type: ignore # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + + response = pipeline_response.http_response + + if response.status_code not in [200]: + if _stream: + try: + await response.read() # Load the body in memory and close the socket + except (StreamConsumedError, StreamClosedError): + pass + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + response_headers = {} + response_headers["Repeatability-Result"] = self._deserialize( + "str", response.headers.get("Repeatability-Result") + ) + response_headers["x-ms-client-request-id"] = self._deserialize( + "str", response.headers.get("x-ms-client-request-id") + ) + + if _stream: + deserialized = response.iter_bytes() + else: + deserialized = _deserialize(_models.GetConversationThreadAnalysisResult, response.json()) + + if cls: + return cls(pipeline_response, deserialized, response_headers) # type: ignore + + return deserialized # type: ignore + + +class ConversationThreadClientOperationsMixin( + ClientMixinABC[AsyncPipelineClient[HttpRequest, AsyncHttpResponse], ConversationThreadClientConfiguration] +): + + @overload + async def add_participants( + self, + conversation_id: str, + options: _models.AddParticipantsOptions, + *, + content_type: str = "application/json", + **kwargs: Any + ) -> _models.AddParticipantsResult: + """Adds participants to a specific conversation. + + :param conversation_id: The conversation ID. Required. + :type conversation_id: str + :param options: Details of the payload for adding participants to a conversation. Required. + :type options: ~azure.communication.messages.models.AddParticipantsOptions + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/json". + :paramtype content_type: str + :return: AddParticipantsResult. The AddParticipantsResult is compatible with MutableMapping + :rtype: ~azure.communication.messages.models.AddParticipantsResult + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @overload + async def add_participants( + self, conversation_id: str, options: JSON, *, content_type: str = "application/json", **kwargs: Any + ) -> _models.AddParticipantsResult: + """Adds participants to a specific conversation. + + :param conversation_id: The conversation ID. Required. + :type conversation_id: str + :param options: Details of the payload for adding participants to a conversation. Required. + :type options: JSON + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/json". + :paramtype content_type: str + :return: AddParticipantsResult. The AddParticipantsResult is compatible with MutableMapping + :rtype: ~azure.communication.messages.models.AddParticipantsResult + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @overload + async def add_participants( + self, conversation_id: str, options: IO[bytes], *, content_type: str = "application/json", **kwargs: Any + ) -> _models.AddParticipantsResult: + """Adds participants to a specific conversation. + + :param conversation_id: The conversation ID. Required. + :type conversation_id: str + :param options: Details of the payload for adding participants to a conversation. Required. + :type options: IO[bytes] + :keyword content_type: Body Parameter content-type. Content type parameter for binary body. + Default value is "application/json". + :paramtype content_type: str + :return: AddParticipantsResult. The AddParticipantsResult is compatible with MutableMapping + :rtype: ~azure.communication.messages.models.AddParticipantsResult + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @distributed_trace_async + @api_version_validation( + method_added_on="2025-04-01-preview", + params_added_on={ + "2025-04-01-preview": [ + "endpoint", + "api_version", + "conversation_id", + "repeatability_request_id", + "repeatability_first_sent", + "client_request_id", + "content_type", + "accept", + ] + }, + ) + async def add_participants( + self, conversation_id: str, options: Union[_models.AddParticipantsOptions, JSON, IO[bytes]], **kwargs: Any + ) -> _models.AddParticipantsResult: + """Adds participants to a specific conversation. + + :param conversation_id: The conversation ID. Required. + :type conversation_id: str + :param options: Details of the payload for adding participants to a conversation. Is one of the + following types: AddParticipantsOptions, JSON, IO[bytes] Required. + :type options: ~azure.communication.messages.models.AddParticipantsOptions or JSON or IO[bytes] + :return: AddParticipantsResult. The AddParticipantsResult is compatible with MutableMapping + :rtype: ~azure.communication.messages.models.AddParticipantsResult + :raises ~azure.core.exceptions.HttpResponseError: + """ + error_map: MutableMapping = { + 401: ClientAuthenticationError, + 404: ResourceNotFoundError, + 409: ResourceExistsError, + 304: ResourceNotModifiedError, + } + error_map.update(kwargs.pop("error_map", {}) or {}) + + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) + _params = kwargs.pop("params", {}) or {} + + content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) + cls: ClsType[_models.AddParticipantsResult] = kwargs.pop("cls", None) + + content_type = content_type or "application/json" + _content = None + if isinstance(options, (IOBase, bytes)): + _content = options + else: + _content = json.dumps(options, cls=SdkJSONEncoder, exclude_readonly=True) # type: ignore + + _request = build_conversation_thread_add_participants_request( + conversation_id=conversation_id, + content_type=content_type, + api_version=self._config.api_version, + content=_content, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + + _stream = kwargs.pop("stream", False) + pipeline_response: PipelineResponse = await self._client._pipeline.run( # type: ignore # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + + response = pipeline_response.http_response + + if response.status_code not in [207]: + if _stream: + try: + await response.read() # Load the body in memory and close the socket + except (StreamConsumedError, StreamClosedError): + pass + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + response_headers = {} + response_headers["Repeatability-Result"] = self._deserialize( + "str", response.headers.get("Repeatability-Result") + ) + response_headers["x-ms-client-request-id"] = self._deserialize( + "str", response.headers.get("x-ms-client-request-id") + ) + + if _stream: + deserialized = response.iter_bytes() + else: + deserialized = _deserialize(_models.AddParticipantsResult, response.json()) + + if cls: + return cls(pipeline_response, deserialized, response_headers) # type: ignore + + return deserialized # type: ignore + + @overload + async def remove_participants( + self, + conversation_id: str, + options: _models.RemoveParticipantsOptions, + *, + content_type: str = "application/json", + **kwargs: Any + ) -> _models.RemoveParticipantsResult: + """remove a participant from a conversation. + + :param conversation_id: The conversation ID. Required. + :type conversation_id: str + :param options: Details of the request body for removing participants from a conversation. + Required. + :type options: ~azure.communication.messages.models.RemoveParticipantsOptions + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/json". + :paramtype content_type: str + :return: RemoveParticipantsResult. The RemoveParticipantsResult is compatible with + MutableMapping + :rtype: ~azure.communication.messages.models.RemoveParticipantsResult + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @overload + async def remove_participants( + self, conversation_id: str, options: JSON, *, content_type: str = "application/json", **kwargs: Any + ) -> _models.RemoveParticipantsResult: + """remove a participant from a conversation. + + :param conversation_id: The conversation ID. Required. + :type conversation_id: str + :param options: Details of the request body for removing participants from a conversation. + Required. + :type options: JSON + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/json". + :paramtype content_type: str + :return: RemoveParticipantsResult. The RemoveParticipantsResult is compatible with + MutableMapping + :rtype: ~azure.communication.messages.models.RemoveParticipantsResult + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @overload + async def remove_participants( + self, conversation_id: str, options: IO[bytes], *, content_type: str = "application/json", **kwargs: Any + ) -> _models.RemoveParticipantsResult: + """remove a participant from a conversation. + + :param conversation_id: The conversation ID. Required. + :type conversation_id: str + :param options: Details of the request body for removing participants from a conversation. + Required. + :type options: IO[bytes] + :keyword content_type: Body Parameter content-type. Content type parameter for binary body. + Default value is "application/json". + :paramtype content_type: str + :return: RemoveParticipantsResult. The RemoveParticipantsResult is compatible with + MutableMapping + :rtype: ~azure.communication.messages.models.RemoveParticipantsResult + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @distributed_trace_async + @api_version_validation( + method_added_on="2025-04-01-preview", + params_added_on={ + "2025-04-01-preview": [ + "endpoint", + "api_version", + "conversation_id", + "repeatability_request_id", + "repeatability_first_sent", + "client_request_id", + "content_type", + "accept", + ] + }, + ) + async def remove_participants( + self, conversation_id: str, options: Union[_models.RemoveParticipantsOptions, JSON, IO[bytes]], **kwargs: Any + ) -> _models.RemoveParticipantsResult: + """remove a participant from a conversation. + + :param conversation_id: The conversation ID. Required. + :type conversation_id: str + :param options: Details of the request body for removing participants from a conversation. Is + one of the following types: RemoveParticipantsOptions, JSON, IO[bytes] Required. + :type options: ~azure.communication.messages.models.RemoveParticipantsOptions or JSON or + IO[bytes] + :return: RemoveParticipantsResult. The RemoveParticipantsResult is compatible with + MutableMapping + :rtype: ~azure.communication.messages.models.RemoveParticipantsResult + :raises ~azure.core.exceptions.HttpResponseError: + """ + error_map: MutableMapping = { + 401: ClientAuthenticationError, + 404: ResourceNotFoundError, + 409: ResourceExistsError, + 304: ResourceNotModifiedError, + } + error_map.update(kwargs.pop("error_map", {}) or {}) + + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) + _params = kwargs.pop("params", {}) or {} + + content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) + cls: ClsType[_models.RemoveParticipantsResult] = kwargs.pop("cls", None) + + content_type = content_type or "application/json" + _content = None + if isinstance(options, (IOBase, bytes)): + _content = options + else: + _content = json.dumps(options, cls=SdkJSONEncoder, exclude_readonly=True) # type: ignore + + _request = build_conversation_thread_remove_participants_request( + conversation_id=conversation_id, + content_type=content_type, + api_version=self._config.api_version, + content=_content, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + + _stream = kwargs.pop("stream", False) + pipeline_response: PipelineResponse = await self._client._pipeline.run( # type: ignore # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + + response = pipeline_response.http_response + + if response.status_code not in [207]: + if _stream: + try: + await response.read() # Load the body in memory and close the socket + except (StreamConsumedError, StreamClosedError): + pass + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + response_headers = {} + response_headers["Repeatability-Result"] = self._deserialize( + "str", response.headers.get("Repeatability-Result") + ) + response_headers["x-ms-client-request-id"] = self._deserialize( + "str", response.headers.get("x-ms-client-request-id") + ) + + if _stream: + deserialized = response.iter_bytes() + else: + deserialized = _deserialize(_models.RemoveParticipantsResult, response.json()) + + if cls: + return cls(pipeline_response, deserialized, response_headers) # type: ignore + + return deserialized # type: ignore + + @distributed_trace + @api_version_validation( + method_added_on="2025-04-01-preview", + params_added_on={ + "2025-04-01-preview": [ + "endpoint", + "api_version", + "max_page_size", + "participant_id", + "channel_id", + "client_request_id", + "accept", + ] + }, + ) + def list_conversations( + self, + *, + max_page_size: Optional[int] = None, + participant_id: Optional[str] = None, + channel_id: Optional[str] = None, + **kwargs: Any + ) -> AsyncIterable["_models.CommunicationConversation"]: + """Retrieves list of conversations. + + :keyword max_page_size: Number of objects to return per page. Default value is None. + :paramtype max_page_size: int + :keyword participant_id: The participant user ID. Default value is None. + :paramtype participant_id: str + :keyword channel_id: The id of channel. Default value is None. + :paramtype channel_id: str + :return: An iterator like instance of CommunicationConversation + :rtype: + ~azure.core.async_paging.AsyncItemPaged[~azure.communication.messages.models.CommunicationConversation] + :raises ~azure.core.exceptions.HttpResponseError: + """ + _headers = kwargs.pop("headers", {}) or {} + _params = kwargs.pop("params", {}) or {} + + cls: ClsType[List[_models.CommunicationConversation]] = kwargs.pop("cls", None) + + error_map: MutableMapping = { + 401: ClientAuthenticationError, + 404: ResourceNotFoundError, + 409: ResourceExistsError, + 304: ResourceNotModifiedError, + } + error_map.update(kwargs.pop("error_map", {}) or {}) + + def prepare_request(next_link=None): + if not next_link: + + _request = build_conversation_thread_list_conversations_request( + max_page_size=max_page_size, + participant_id=participant_id, + channel_id=channel_id, + api_version=self._config.api_version, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url( + "self._config.endpoint", self._config.endpoint, "str", skip_quote=True + ), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + + else: + # make call to next link with the client's api-version + _parsed_next_link = urllib.parse.urlparse(next_link) + _next_request_params = case_insensitive_dict( + { + key: [urllib.parse.quote(v) for v in value] + for key, value in urllib.parse.parse_qs(_parsed_next_link.query).items() + } + ) + _next_request_params["api-version"] = self._config.api_version + _request = HttpRequest( + "GET", urllib.parse.urljoin(next_link, _parsed_next_link.path), params=_next_request_params + ) + path_format_arguments = { + "endpoint": self._serialize.url( + "self._config.endpoint", self._config.endpoint, "str", skip_quote=True + ), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + + return _request + + async def extract_data(pipeline_response): + deserialized = pipeline_response.http_response.json() + list_of_elem = _deserialize(List[_models.CommunicationConversation], deserialized.get("value", [])) + if cls: + list_of_elem = cls(list_of_elem) # type: ignore + return deserialized.get("nextLink") or None, AsyncList(list_of_elem) + + async def get_next(next_link=None): + _request = prepare_request(next_link) + + _stream = False + pipeline_response: PipelineResponse = await self._client._pipeline.run( # type: ignore # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + return pipeline_response + + return AsyncItemPaged(get_next, extract_data) + + @distributed_trace + @api_version_validation( + method_added_on="2025-04-01-preview", + params_added_on={ + "2025-04-01-preview": [ + "endpoint", + "api_version", + "conversation_id", + "max_page_size", + "participant_id", + "client_request_id", + "accept", + ] + }, + ) + def list_messages( + self, + conversation_id: str, + *, + max_page_size: Optional[int] = None, + participant_id: Optional[str] = None, + **kwargs: Any + ) -> AsyncIterable["_models.ConversationMessageItem"]: + """Retrieves list of conversation messages. + + :param conversation_id: The conversation ID. Required. + :type conversation_id: str + :keyword max_page_size: Number of objects to return per page. Default value is None. + :paramtype max_page_size: int + :keyword participant_id: The participant user ID. Default value is None. + :paramtype participant_id: str + :return: An iterator like instance of ConversationMessageItem + :rtype: + ~azure.core.async_paging.AsyncItemPaged[~azure.communication.messages.models.ConversationMessageItem] + :raises ~azure.core.exceptions.HttpResponseError: + """ + _headers = kwargs.pop("headers", {}) or {} + _params = kwargs.pop("params", {}) or {} + + cls: ClsType[List[_models.ConversationMessageItem]] = kwargs.pop("cls", None) + + error_map: MutableMapping = { + 401: ClientAuthenticationError, + 404: ResourceNotFoundError, + 409: ResourceExistsError, + 304: ResourceNotModifiedError, + } + error_map.update(kwargs.pop("error_map", {}) or {}) + + def prepare_request(next_link=None): + if not next_link: + + _request = build_conversation_thread_list_messages_request( + conversation_id=conversation_id, + max_page_size=max_page_size, + participant_id=participant_id, + api_version=self._config.api_version, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url( + "self._config.endpoint", self._config.endpoint, "str", skip_quote=True + ), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + + else: + # make call to next link with the client's api-version + _parsed_next_link = urllib.parse.urlparse(next_link) + _next_request_params = case_insensitive_dict( + { + key: [urllib.parse.quote(v) for v in value] + for key, value in urllib.parse.parse_qs(_parsed_next_link.query).items() + } + ) + _next_request_params["api-version"] = self._config.api_version + _request = HttpRequest( + "GET", urllib.parse.urljoin(next_link, _parsed_next_link.path), params=_next_request_params + ) + path_format_arguments = { + "endpoint": self._serialize.url( + "self._config.endpoint", self._config.endpoint, "str", skip_quote=True + ), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + + return _request + + async def extract_data(pipeline_response): + deserialized = pipeline_response.http_response.json() + list_of_elem = _deserialize(List[_models.ConversationMessageItem], deserialized.get("value", [])) + if cls: + list_of_elem = cls(list_of_elem) # type: ignore + return deserialized.get("nextLink") or None, AsyncList(list_of_elem) + + async def get_next(next_link=None): + _request = prepare_request(next_link) + + _stream = False + pipeline_response: PipelineResponse = await self._client._pipeline.run( # type: ignore # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + response = pipeline_response.http_response + + if response.status_code not in [200]: + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + return pipeline_response + + return AsyncItemPaged(get_next, extract_data) + + @overload + async def send_message( + self, + conversation_id: str, + options: _models.SendConversationMessageOptions, + *, + content_type: str = "application/json", + **kwargs: Any + ) -> _models.SendConversationMessageResult: + """Sends a conversation message from Business to User. + + :param conversation_id: The conversation ID. Required. + :type conversation_id: str + :param options: Details of the conversation message to send. Required. + :type options: ~azure.communication.messages.models.SendConversationMessageOptions + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/json". + :paramtype content_type: str + :return: SendConversationMessageResult. The SendConversationMessageResult is compatible with + MutableMapping + :rtype: ~azure.communication.messages.models.SendConversationMessageResult + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @overload + async def send_message( + self, conversation_id: str, options: JSON, *, content_type: str = "application/json", **kwargs: Any + ) -> _models.SendConversationMessageResult: + """Sends a conversation message from Business to User. + + :param conversation_id: The conversation ID. Required. + :type conversation_id: str + :param options: Details of the conversation message to send. Required. + :type options: JSON + :keyword content_type: Body Parameter content-type. Content type parameter for JSON body. + Default value is "application/json". + :paramtype content_type: str + :return: SendConversationMessageResult. The SendConversationMessageResult is compatible with + MutableMapping + :rtype: ~azure.communication.messages.models.SendConversationMessageResult + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @overload + async def send_message( + self, conversation_id: str, options: IO[bytes], *, content_type: str = "application/json", **kwargs: Any + ) -> _models.SendConversationMessageResult: + """Sends a conversation message from Business to User. + + :param conversation_id: The conversation ID. Required. + :type conversation_id: str + :param options: Details of the conversation message to send. Required. + :type options: IO[bytes] + :keyword content_type: Body Parameter content-type. Content type parameter for binary body. + Default value is "application/json". + :paramtype content_type: str + :return: SendConversationMessageResult. The SendConversationMessageResult is compatible with + MutableMapping + :rtype: ~azure.communication.messages.models.SendConversationMessageResult + :raises ~azure.core.exceptions.HttpResponseError: + """ + + @distributed_trace_async + @api_version_validation( + method_added_on="2025-04-01-preview", + params_added_on={ + "2025-04-01-preview": [ + "endpoint", + "api_version", + "conversation_id", + "repeatability_request_id", + "repeatability_first_sent", + "client_request_id", + "content_type", + "accept", + ] + }, + ) + async def send_message( + self, + conversation_id: str, + options: Union[_models.SendConversationMessageOptions, JSON, IO[bytes]], + **kwargs: Any + ) -> _models.SendConversationMessageResult: + """Sends a conversation message from Business to User. + + :param conversation_id: The conversation ID. Required. + :type conversation_id: str + :param options: Details of the conversation message to send. Is one of the following types: + SendConversationMessageOptions, JSON, IO[bytes] Required. + :type options: ~azure.communication.messages.models.SendConversationMessageOptions or JSON or + IO[bytes] + :return: SendConversationMessageResult. The SendConversationMessageResult is compatible with + MutableMapping + :rtype: ~azure.communication.messages.models.SendConversationMessageResult + :raises ~azure.core.exceptions.HttpResponseError: + """ + error_map: MutableMapping = { + 401: ClientAuthenticationError, + 404: ResourceNotFoundError, + 409: ResourceExistsError, + 304: ResourceNotModifiedError, + } + error_map.update(kwargs.pop("error_map", {}) or {}) + + _headers = case_insensitive_dict(kwargs.pop("headers", {}) or {}) + _params = kwargs.pop("params", {}) or {} + + content_type: Optional[str] = kwargs.pop("content_type", _headers.pop("Content-Type", None)) + cls: ClsType[_models.SendConversationMessageResult] = kwargs.pop("cls", None) + + content_type = content_type or "application/json" + _content = None + if isinstance(options, (IOBase, bytes)): + _content = options + else: + _content = json.dumps(options, cls=SdkJSONEncoder, exclude_readonly=True) # type: ignore + + _request = build_conversation_thread_send_message_request( + conversation_id=conversation_id, + content_type=content_type, + api_version=self._config.api_version, + content=_content, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + + _stream = kwargs.pop("stream", False) + pipeline_response: PipelineResponse = await self._client._pipeline.run( # type: ignore # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + + response = pipeline_response.http_response + + if response.status_code not in [200]: + if _stream: + try: + await response.read() # Load the body in memory and close the socket + except (StreamConsumedError, StreamClosedError): + pass + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + response_headers = {} + response_headers["Repeatability-Result"] = self._deserialize( + "str", response.headers.get("Repeatability-Result") + ) + response_headers["x-ms-client-request-id"] = self._deserialize( + "str", response.headers.get("x-ms-client-request-id") + ) + + if _stream: + deserialized = response.iter_bytes() + else: + deserialized = _deserialize(_models.SendConversationMessageResult, response.json()) + + if cls: + return cls(pipeline_response, deserialized, response_headers) # type: ignore + + return deserialized # type: ignore + + @distributed_trace_async + @api_version_validation( + method_added_on="2025-04-01-preview", + params_added_on={ + "2025-04-01-preview": [ + "endpoint", + "api_version", + "conversation_id", + "repeatability_request_id", + "repeatability_first_sent", + "client_request_id", + "accept", + ] + }, + ) + async def analyze_conversation( + self, conversation_id: str, **kwargs: Any + ) -> _models.GetConversationThreadAnalysisResult: + """Get AI Analysis of a conversation. + + :param conversation_id: The conversation ID. Required. + :type conversation_id: str + :return: GetConversationThreadAnalysisResult. The GetConversationThreadAnalysisResult is + compatible with MutableMapping + :rtype: ~azure.communication.messages.models.GetConversationThreadAnalysisResult + :raises ~azure.core.exceptions.HttpResponseError: + """ + error_map: MutableMapping = { + 401: ClientAuthenticationError, + 404: ResourceNotFoundError, + 409: ResourceExistsError, + 304: ResourceNotModifiedError, + } + error_map.update(kwargs.pop("error_map", {}) or {}) + + _headers = kwargs.pop("headers", {}) or {} + _params = kwargs.pop("params", {}) or {} + + cls: ClsType[_models.GetConversationThreadAnalysisResult] = kwargs.pop("cls", None) + + _request = build_conversation_thread_analyze_conversation_request( + conversation_id=conversation_id, + api_version=self._config.api_version, + headers=_headers, + params=_params, + ) + path_format_arguments = { + "endpoint": self._serialize.url("self._config.endpoint", self._config.endpoint, "str", skip_quote=True), + } + _request.url = self._client.format_url(_request.url, **path_format_arguments) + + _stream = kwargs.pop("stream", False) + pipeline_response: PipelineResponse = await self._client._pipeline.run( # type: ignore # pylint: disable=protected-access + _request, stream=_stream, **kwargs + ) + + response = pipeline_response.http_response + + if response.status_code not in [200]: + if _stream: + try: + await response.read() # Load the body in memory and close the socket + except (StreamConsumedError, StreamClosedError): + pass + map_error(status_code=response.status_code, response=response, error_map=error_map) + raise HttpResponseError(response=response) + + response_headers = {} + response_headers["Repeatability-Result"] = self._deserialize( + "str", response.headers.get("Repeatability-Result") + ) + response_headers["x-ms-client-request-id"] = self._deserialize( + "str", response.headers.get("x-ms-client-request-id") + ) + + if _stream: + deserialized = response.iter_bytes() + else: + deserialized = _deserialize(_models.GetConversationThreadAnalysisResult, response.json()) + + if cls: + return cls(pipeline_response, deserialized, response_headers) # type: ignore + + return deserialized # type: ignore diff --git a/sdk/communication/azure-communication-messages/azure/communication/messages/aio/_operations/_patch.py b/sdk/communication/azure-communication-messages/azure/communication/messages/aio/_operations/_patch.py index f7dd32510333..8bcb627aa475 100644 --- a/sdk/communication/azure-communication-messages/azure/communication/messages/aio/_operations/_patch.py +++ b/sdk/communication/azure-communication-messages/azure/communication/messages/aio/_operations/_patch.py @@ -1,7 +1,8 @@ -# ------------------------------------ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. -# ------------------------------------ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# -------------------------------------------------------------------------- """Customize generated code here. Follow our quickstart for examples: https://aka.ms/azsdk/python/dpcodegen/python/customize diff --git a/sdk/communication/azure-communication-messages/azure/communication/messages/aio/_patch.py b/sdk/communication/azure-communication-messages/azure/communication/messages/aio/_patch.py index d69ae3068ceb..8bcb627aa475 100644 --- a/sdk/communication/azure-communication-messages/azure/communication/messages/aio/_patch.py +++ b/sdk/communication/azure-communication-messages/azure/communication/messages/aio/_patch.py @@ -1,144 +1,15 @@ -# ------------------------------------ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. -# ------------------------------------ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# -------------------------------------------------------------------------- """Customize generated code here. Follow our quickstart for examples: https://aka.ms/azsdk/python/dpcodegen/python/customize """ -from typing import ( - List, - Any, - Union, -) -from urllib.parse import urlparse -from azure.core.credentials import AzureKeyCredential -from azure.core.credentials_async import AsyncTokenCredential -from .._shared.utils import parse_connection_str -from ._client import ( - NotificationMessagesClient as NotificationMessagesClientGenerated, - MessageTemplateClient as MessageTemplateClientGenerated, -) -from .._api_versions import DEFAULT_VERSION -from .._shared.auth_policy_utils import get_authentication_policy +from typing import List - -class NotificationMessagesClient(NotificationMessagesClientGenerated): - """A client to interact with the AzureCommunicationService Messaging service. - - This client allows you to send and receive WhatsApp template messages using the - Azure Communication Services Messaging SDK. - - :param str endpoint: - The endpoint of the Azure Communication resource. - :param ~azure.core.credentials.AzureKeyCredential credential: - The credentials with which to authenticate - :keyword api_version: Azure Communication Messaging API version. - Default value is "2024-02-01". - Note that overriding this default value may result in unsupported behavior. - """ - - def __init__( - self, endpoint: str, credential: Union[AsyncTokenCredential, AzureKeyCredential], **kwargs: Any - ) -> None: - if not credential: - raise ValueError("credential can not be None") - - try: - if not endpoint.lower().startswith("http"): - endpoint = "https://" + endpoint - except AttributeError: - raise ValueError("Host URL must be a string") # pylint:disable=raise-missing-from - - parsed_url = urlparse(endpoint.rstrip("/")) - if not parsed_url.netloc: - raise ValueError("Invalid URL: {}".format(endpoint)) - - self._endpoint = endpoint - self._credential = credential - self._authentication_policy = get_authentication_policy(endpoint, credential) - self._api_version = kwargs.pop("api_version", DEFAULT_VERSION) - super().__init__( - self._endpoint, - self._credential, - authentication_policy=self._authentication_policy, - api_version=self._api_version, - **kwargs - ) - - @classmethod - def from_connection_string(cls, conn_str: str, **kwargs: Any) -> "NotificationMessagesClient": - """Create NotificationMessagesClient from a Connection String. - - :param conn_str: Azure Communication Service endpoint. Required. - :type conn_str: str - :return: instance of NotificationMessagesClient. - :rtype: ~azure.communication.message.NotificationMessagesClient - """ - endpoint, access_key = parse_connection_str(conn_str) - return cls(endpoint, AzureKeyCredential(key=access_key), **kwargs) - - -class MessageTemplateClient(MessageTemplateClientGenerated): - """A client to interact with the AzureCommunicationService Messaging service. - - This client allows you to send and receive WhatsApp template - messages using the Azure Communication Services Messaging SDK. - - :param str endpoint: - The endpoint of the Azure Communication resource. - :param ~azure.core.credentials.AzureKeyCredential credential: - The credentials with which to authenticate - :keyword api_version: Azure Communication Messaging API version. Default value is "2024-02-01". - Note that overriding this default value may result in unsupported behavior. - :paramtype api_version: str - """ - - def __init__( - self, endpoint: str, credential: Union[AsyncTokenCredential, AzureKeyCredential], **kwargs: Any - ) -> "None": - if not credential: - raise ValueError("credential can not be None") - - try: - if not endpoint.lower().startswith("http"): - endpoint = "https://" + endpoint - except AttributeError: - raise ValueError("Host URL must be a string") # pylint: disable=raise-missing-from - - parsed_url = urlparse(endpoint.rstrip("/")) - if not parsed_url.netloc: - raise ValueError("Invalid URL: {}".format(endpoint)) - - self._endpoint = endpoint - self._credential = credential - self._authentication_policy = get_authentication_policy(endpoint, credential) - self._api_version = kwargs.pop("api_version", DEFAULT_VERSION) - super().__init__( - self._endpoint, - self._credential, - authentication_policy=self._authentication_policy, - api_version=self._api_version, - **kwargs - ) - - @classmethod - def from_connection_string(cls, conn_str: str, **kwargs: Any) -> "MessageTemplateClient": - """Create MessageTemplateClient from a Connection String. - - :param conn_str: Azure Communication Service endpoint. Required. - :type conn_str: str - :return: instance of MessageTemplateClient. - :rtype: ~azure.communication.message.MessageTemplateClient - """ - endpoint, access_key = parse_connection_str(conn_str) - return cls(endpoint, AzureKeyCredential(access_key), **kwargs) - - -__all__: List[str] = [ - "NotificationMessagesClient", - "MessageTemplateClient", -] # Add all objects you want publicly available to users at this package level +__all__: List[str] = [] # Add all objects you want publicly available to users at this package level def patch_sdk(): diff --git a/sdk/communication/azure-communication-messages/azure/communication/messages/aio/_vendor.py b/sdk/communication/azure-communication-messages/azure/communication/messages/aio/_vendor.py deleted file mode 100644 index 1ef61ca00c30..000000000000 --- a/sdk/communication/azure-communication-messages/azure/communication/messages/aio/_vendor.py +++ /dev/null @@ -1,34 +0,0 @@ -# -------------------------------------------------------------------------- -# Copyright (c) Microsoft Corporation. All rights reserved. -# Licensed under the MIT License. See License.txt in the project root for license information. -# Code generated by Microsoft (R) Python Code Generator. -# Changes may cause incorrect behavior and will be lost if the code is regenerated. -# -------------------------------------------------------------------------- - -from abc import ABC -from typing import TYPE_CHECKING - -from ._configuration import MessageTemplateClientConfiguration, NotificationMessagesClientConfiguration - -if TYPE_CHECKING: - from azure.core import AsyncPipelineClient - - from .._serialization import Deserializer, Serializer - - -class NotificationMessagesClientMixinABC(ABC): - """DO NOT use this class. It is for internal typing use only.""" - - _client: "AsyncPipelineClient" - _config: NotificationMessagesClientConfiguration - _serialize: "Serializer" - _deserialize: "Deserializer" - - -class MessageTemplateClientMixinABC(ABC): - """DO NOT use this class. It is for internal typing use only.""" - - _client: "AsyncPipelineClient" - _config: MessageTemplateClientConfiguration - _serialize: "Serializer" - _deserialize: "Deserializer" diff --git a/sdk/communication/azure-communication-messages/azure/communication/messages/models/__init__.py b/sdk/communication/azure-communication-messages/azure/communication/messages/models/__init__.py index ab0b1a95ee7d..230d082e0058 100644 --- a/sdk/communication/azure-communication-messages/azure/communication/messages/models/__init__.py +++ b/sdk/communication/azure-communication-messages/azure/communication/messages/models/__init__.py @@ -18,17 +18,33 @@ ActionGroup, ActionGroupContent, ActionGroupItem, + AddParticipantsOptions, + AddParticipantsResult, + AudioConversationMessageContent, AudioNotificationContent, + BotContact, ButtonContent, ButtonSetContent, + CommunicationContact, + CommunicationConversation, + Contact, + ConversationMessageContent, + ConversationMessageItem, + ConversationParticipant, + DocumentConversationMessageContent, DocumentMessageContent, DocumentNotificationContent, + ExternalConversationParticipant, + GetConversationThreadAnalysisResult, + ImageConversationMessageContent, ImageMessageContent, ImageNotificationContent, InteractiveMessage, InteractiveNotificationContent, + InternalConversationParticipant, LinkContent, MediaNotificationContent, + Message, MessageContent, MessageReceipt, MessageTemplate, @@ -43,14 +59,23 @@ MessageTemplateVideo, NotificationContent, ReactionNotificationContent, + RemoveParticipantsOptions, + RemoveParticipantsResult, + SendConversationMessageOptions, + SendConversationMessageResult, SendMessageResult, StickerNotificationContent, + TemplateConversationMessageContent, TemplateNotificationContent, + TextConversationMessageContent, TextMessageContent, TextNotificationContent, + UpdateParticipantsResult, + VideoConversationMessageContent, VideoMessageContent, VideoNotificationContent, WhatsAppButtonActionBindings, + WhatsAppContact, WhatsAppListActionBindings, WhatsAppMessageTemplateBindings, WhatsAppMessageTemplateBindingsButton, @@ -64,9 +89,12 @@ CommunicationMessagesChannel, MessageActionBindingKind, MessageContentKind, + MessagePlatformKind, MessageTemplateBindingsKind, MessageTemplateStatus, MessageTemplateValueKind, + OutboundDeliveryStrategyKind, + ParticipantKind, RepeatabilityResult, WhatsAppMessageButtonSubType, ) @@ -79,17 +107,33 @@ "ActionGroup", "ActionGroupContent", "ActionGroupItem", + "AddParticipantsOptions", + "AddParticipantsResult", + "AudioConversationMessageContent", "AudioNotificationContent", + "BotContact", "ButtonContent", "ButtonSetContent", + "CommunicationContact", + "CommunicationConversation", + "Contact", + "ConversationMessageContent", + "ConversationMessageItem", + "ConversationParticipant", + "DocumentConversationMessageContent", "DocumentMessageContent", "DocumentNotificationContent", + "ExternalConversationParticipant", + "GetConversationThreadAnalysisResult", + "ImageConversationMessageContent", "ImageMessageContent", "ImageNotificationContent", "InteractiveMessage", "InteractiveNotificationContent", + "InternalConversationParticipant", "LinkContent", "MediaNotificationContent", + "Message", "MessageContent", "MessageReceipt", "MessageTemplate", @@ -104,14 +148,23 @@ "MessageTemplateVideo", "NotificationContent", "ReactionNotificationContent", + "RemoveParticipantsOptions", + "RemoveParticipantsResult", + "SendConversationMessageOptions", + "SendConversationMessageResult", "SendMessageResult", "StickerNotificationContent", + "TemplateConversationMessageContent", "TemplateNotificationContent", + "TextConversationMessageContent", "TextMessageContent", "TextNotificationContent", + "UpdateParticipantsResult", + "VideoConversationMessageContent", "VideoMessageContent", "VideoNotificationContent", "WhatsAppButtonActionBindings", + "WhatsAppContact", "WhatsAppListActionBindings", "WhatsAppMessageTemplateBindings", "WhatsAppMessageTemplateBindingsButton", @@ -122,9 +175,12 @@ "CommunicationMessagesChannel", "MessageActionBindingKind", "MessageContentKind", + "MessagePlatformKind", "MessageTemplateBindingsKind", "MessageTemplateStatus", "MessageTemplateValueKind", + "OutboundDeliveryStrategyKind", + "ParticipantKind", "RepeatabilityResult", "WhatsAppMessageButtonSubType", ] diff --git a/sdk/communication/azure-communication-messages/azure/communication/messages/models/_enums.py b/sdk/communication/azure-communication-messages/azure/communication/messages/models/_enums.py index 886dcda444f3..cf4a10c1625c 100644 --- a/sdk/communication/azure-communication-messages/azure/communication/messages/models/_enums.py +++ b/sdk/communication/azure-communication-messages/azure/communication/messages/models/_enums.py @@ -39,7 +39,7 @@ class CommunicationMessageKind(str, Enum, metaclass=CaseInsensitiveEnumMeta): class CommunicationMessagesChannel(str, Enum, metaclass=CaseInsensitiveEnumMeta): """The type of the communication messages channel.""" - WHATSAPP = "whatsApp" + WHATS_APP = "whatsApp" """The WhatsApp communication messages channel type.""" @@ -73,10 +73,21 @@ class MessageContentKind(str, Enum, metaclass=CaseInsensitiveEnumMeta): """The Url content type.""" +class MessagePlatformKind(str, Enum, metaclass=CaseInsensitiveEnumMeta): + """Defines the type of message platform.""" + + COMMUNICATION = "communication" + """Azure Communication platform.""" + BOT = "bot" + """Bot platform.""" + WHATS_APP = "whatsApp" + """WhatsApp platform.""" + + class MessageTemplateBindingsKind(str, Enum, metaclass=CaseInsensitiveEnumMeta): """The type of the message template.""" - WHATSAPP = "whatsApp" + WHATS_APP = "whatsApp" """The WhatsApp template type.""" @@ -110,6 +121,26 @@ class MessageTemplateValueKind(str, Enum, metaclass=CaseInsensitiveEnumMeta): """The quick action template parameter type.""" +class OutboundDeliveryStrategyKind(str, Enum, metaclass=CaseInsensitiveEnumMeta): + """The options of the outbound delivery strategy for messages sent by participants in a + conversation. + """ + + INTERNAL_ONLY = "internalOnly" + """Delivery strategy for internal only.""" + ALL_PARTICIPANTS = "allParticipants" + """Delivery strategy for all participants.""" + + +class ParticipantKind(str, Enum, metaclass=CaseInsensitiveEnumMeta): + """The type of a participant in a threaded conversation.""" + + INTERNAL = "internal" + """A participant internal to Azure Communication Services.""" + EXTERNAL = "external" + """A participant on other platforms""" + + class RepeatabilityResult(str, Enum, metaclass=CaseInsensitiveEnumMeta): """Repeatability Result header options.""" diff --git a/sdk/communication/azure-communication-messages/azure/communication/messages/models/_models.py b/sdk/communication/azure-communication-messages/azure/communication/messages/models/_models.py index 1c601a64031b..9ef22c222a1e 100644 --- a/sdk/communication/azure-communication-messages/azure/communication/messages/models/_models.py +++ b/sdk/communication/azure-communication-messages/azure/communication/messages/models/_models.py @@ -1,4 +1,4 @@ -# pylint: disable=too-many-lines +# pylint: disable=line-too-long,useless-suppression,too-many-lines # coding=utf-8 # -------------------------------------------------------------------------- # Copyright (c) Microsoft Corporation. All rights reserved. @@ -8,38 +8,40 @@ # -------------------------------------------------------------------------- # pylint: disable=useless-super-delegation +import datetime from typing import Any, Dict, List, Literal, Mapping, Optional, TYPE_CHECKING, Union, overload -from .. import _model_base -from .._model_base import rest_discriminator, rest_field +from azure.core.exceptions import ODataV4Format + +from .._utils.model_base import Model as _Model, rest_discriminator, rest_field from ._enums import ( CommunicationMessageKind, CommunicationMessagesChannel, MessageActionBindingKind, MessageContentKind, + MessagePlatformKind, MessageTemplateBindingsKind, MessageTemplateValueKind, + ParticipantKind, ) if TYPE_CHECKING: from .. import models as _models -class ActionBindings(_model_base.Model): +class ActionBindings(_Model): """Binding actions to the interactive message. You probably want to use the sub-classes and not this class directly. Known sub-classes are: WhatsAppButtonActionBindings, WhatsAppListActionBindings, WhatsAppUrlActionBindings - All required parameters must be populated in order to send to server. - :ivar kind: Kind of the MessageActionBinding. Required. Known values are: "whatsAppListAction", "whatsAppButtonAction", and "whatsAppUrlAction". :vartype kind: str or ~azure.communication.messages.models.MessageActionBindingKind """ - __mapping__: Dict[str, _model_base.Model] = {} - kind: str = rest_discriminator(name="kind") + __mapping__: Dict[str, _Model] = {} + kind: str = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) """Kind of the MessageActionBinding. Required. Known values are: \"whatsAppListAction\", \"whatsAppButtonAction\", and \"whatsAppUrlAction\".""" @@ -61,20 +63,20 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) -class ActionGroup(_model_base.Model): +class ActionGroup(_Model): """The Action Group content. - All required parameters must be populated in order to send to server. - :ivar title: Title of the ActionGroup. Required. :vartype title: str :ivar items_property: Array of items in ActionGroup. Required. :vartype items_property: list[~azure.communication.messages.models.ActionGroupItem] """ - title: str = rest_field() + title: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) """Title of the ActionGroup. Required.""" - items_property: List["_models.ActionGroupItem"] = rest_field(name="items") + items_property: List["_models.ActionGroupItem"] = rest_field( + name="items", visibility=["read", "create", "update", "delete", "query"] + ) """Array of items in ActionGroup. Required.""" @overload @@ -96,22 +98,20 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) -class MessageContent(_model_base.Model): +class MessageContent(_Model): """The message content object used to create interactive messages components. You probably want to use the sub-classes and not this class directly. Known sub-classes are: ButtonSetContent, DocumentMessageContent, ActionGroupContent, ImageMessageContent, TextMessageContent, LinkContent, VideoMessageContent - All required parameters must be populated in order to send to server. - :ivar kind: Kind of MessageContent. Required. Known values are: "text", "image", "video", "document", "group", "buttonSet", and "url". :vartype kind: str or ~azure.communication.messages.models.MessageContentKind """ - __mapping__: Dict[str, _model_base.Model] = {} - kind: str = rest_discriminator(name="kind") + __mapping__: Dict[str, _Model] = {} + kind: str = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) """Kind of MessageContent. Required. Known values are: \"text\", \"image\", \"video\", \"document\", \"group\", \"buttonSet\", and \"url\".""" @@ -136,8 +136,6 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: class ActionGroupContent(MessageContent, discriminator="group"): """The action content of type ActionGroup. - All required parameters must be populated in order to send to server. - :ivar kind: Message content kind is actionGroup. Required. The ActionSet content type. :vartype kind: str or ~azure.communication.messages.models.GROUP :ivar title: Title of the actionGroup content. Required. @@ -146,11 +144,11 @@ class ActionGroupContent(MessageContent, discriminator="group"): :vartype groups: list[~azure.communication.messages.models.ActionGroup] """ - kind: Literal[MessageContentKind.GROUP] = rest_discriminator(name="kind") # type: ignore + kind: Literal[MessageContentKind.GROUP] = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) # type: ignore """Message content kind is actionGroup. Required. The ActionSet content type.""" - title: str = rest_field() + title: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) """Title of the actionGroup content. Required.""" - groups: List["_models.ActionGroup"] = rest_field() + groups: List["_models.ActionGroup"] = rest_field(visibility=["read", "create", "update", "delete", "query"]) """Set or group of actions. Required.""" @overload @@ -172,11 +170,9 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, kind=MessageContentKind.GROUP, **kwargs) -class ActionGroupItem(_model_base.Model): +class ActionGroupItem(_Model): """The Action group item in the content. - All required parameters must be populated in order to send to server. - :ivar id: Id of the Item. Required. :vartype id: str :ivar title: Title of the Item. Required. @@ -185,11 +181,11 @@ class ActionGroupItem(_model_base.Model): :vartype description: str """ - id: str = rest_field() + id: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) """Id of the Item. Required.""" - title: str = rest_field() + title: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) """Title of the Item. Required.""" - description: str = rest_field() + description: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) """Description of the Item. Required.""" @overload @@ -212,7 +208,140 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) -class NotificationContent(_model_base.Model): +class AddParticipantsOptions(_Model): + """Request payload for adding participants to a conversation. + + :ivar participants: List of participants to add. Required. + :vartype participants: list[~azure.communication.messages.models.ConversationParticipant] + """ + + participants: List["_models.ConversationParticipant"] = rest_field( + visibility=["read", "create", "update", "delete", "query"] + ) + """List of participants to add. Required.""" + + @overload + def __init__( + self, + *, + participants: List["_models.ConversationParticipant"], + ) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: + """ + :param mapping: raw JSON to initialize the model. + :type mapping: Mapping[str, Any] + """ + + def __init__(self, *args: Any, **kwargs: Any) -> None: + super().__init__(*args, **kwargs) + + +class AddParticipantsResult(_Model): + """Response for the add participants operation. + + :ivar invalid_participants: List of Ids with Errors if failed to be added. Required. + :vartype invalid_participants: + list[~azure.communication.messages.models.UpdateParticipantsResult] + """ + + invalid_participants: List["_models.UpdateParticipantsResult"] = rest_field( + name="invalidParticipants", visibility=["read", "create", "update", "delete", "query"] + ) + """List of Ids with Errors if failed to be added. Required.""" + + @overload + def __init__( + self, + *, + invalid_participants: List["_models.UpdateParticipantsResult"], + ) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: + """ + :param mapping: raw JSON to initialize the model. + :type mapping: Mapping[str, Any] + """ + + def __init__(self, *args: Any, **kwargs: Any) -> None: + super().__init__(*args, **kwargs) + + +class ConversationMessageContent(_Model): + """Details of the conversation message content. + + You probably want to use the sub-classes and not this class directly. Known sub-classes are: + AudioConversationMessageContent, DocumentConversationMessageContent, + ImageConversationMessageContent, TemplateConversationMessageContent, + TextConversationMessageContent, VideoConversationMessageContent + + :ivar kind: The type discriminator describing a message type. Required. Known values are: + "text", "image", "image_v0", "document", "video", "audio", "template", "sticker", "reaction", + and "interactive". + :vartype kind: str or ~azure.communication.messages.models.CommunicationMessageKind + """ + + __mapping__: Dict[str, _Model] = {} + kind: str = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) + """The type discriminator describing a message type. Required. Known values are: \"text\", + \"image\", \"image_v0\", \"document\", \"video\", \"audio\", \"template\", \"sticker\", + \"reaction\", and \"interactive\".""" + + @overload + def __init__( + self, + *, + kind: str, + ) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: + """ + :param mapping: raw JSON to initialize the model. + :type mapping: Mapping[str, Any] + """ + + def __init__(self, *args: Any, **kwargs: Any) -> None: + super().__init__(*args, **kwargs) + + +class AudioConversationMessageContent(ConversationMessageContent, discriminator="audio"): + """A request to send an audio conversation message. + + :ivar kind: Message notification type is audio. Required. Audio message type. + :vartype kind: str or ~azure.communication.messages.models.AUDIO + :ivar media_uri: A media url for the file. Required if the type is one of the supported media + types, e.g. image. Required. + :vartype media_uri: str + """ + + kind: Literal[CommunicationMessageKind.AUDIO] = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) # type: ignore + """Message notification type is audio. Required. Audio message type.""" + media_uri: str = rest_field(name="mediaUri", visibility=["read", "create", "update", "delete", "query"]) + """A media url for the file. Required if the type is one of the supported media types, e.g. image. + Required.""" + + @overload + def __init__( + self, + *, + media_uri: str, + ) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: + """ + :param mapping: raw JSON to initialize the model. + :type mapping: Mapping[str, Any] + """ + + def __init__(self, *args: Any, **kwargs: Any) -> None: + super().__init__(*args, kind=CommunicationMessageKind.AUDIO, **kwargs) + + +class NotificationContent(_Model): """Details of the message to send. You probably want to use the sub-classes and not this class directly. Known sub-classes are: @@ -221,26 +350,26 @@ class NotificationContent(_model_base.Model): StickerNotificationContent, TemplateNotificationContent, TextNotificationContent, VideoNotificationContent - All required parameters must be populated in order to send to server. - :ivar channel_registration_id: The Channel Registration ID for the Business Identifier. Required. :vartype channel_registration_id: str :ivar to: The native external platform user identifiers of the recipient. Required. :vartype to: list[str] - :ivar kind: The type discriminator describing a notification type. Required. Known values are: + :ivar kind: The type discriminator describing a message type. Required. Known values are: "text", "image", "image_v0", "document", "video", "audio", "template", "sticker", "reaction", and "interactive". :vartype kind: str or ~azure.communication.messages.models.CommunicationMessageKind """ - __mapping__: Dict[str, _model_base.Model] = {} - channel_registration_id: str = rest_field(name="channelRegistrationId") + __mapping__: Dict[str, _Model] = {} + channel_registration_id: str = rest_field( + name="channelRegistrationId", visibility=["read", "create", "update", "delete", "query"] + ) """The Channel Registration ID for the Business Identifier. Required.""" - to: List[str] = rest_field() + to: List[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) """The native external platform user identifiers of the recipient. Required.""" - kind: str = rest_discriminator(name="kind") - """The type discriminator describing a notification type. Required. Known values are: \"text\", + kind: str = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) + """The type discriminator describing a message type. Required. Known values are: \"text\", \"image\", \"image_v0\", \"document\", \"video\", \"audio\", \"template\", \"sticker\", \"reaction\", and \"interactive\".""" @@ -267,8 +396,6 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: class AudioNotificationContent(NotificationContent, discriminator="audio"): """A request to send an audio notification. - All required parameters must be populated in order to send to server. - :ivar channel_registration_id: The Channel Registration ID for the Business Identifier. Required. :vartype channel_registration_id: str @@ -281,9 +408,9 @@ class AudioNotificationContent(NotificationContent, discriminator="audio"): :vartype media_uri: str """ - kind: Literal[CommunicationMessageKind.AUDIO] = rest_discriminator(name="kind") # type: ignore + kind: Literal[CommunicationMessageKind.AUDIO] = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) # type: ignore """Message notification type is audio. Required. Audio message type.""" - media_uri: str = rest_field(name="mediaUri") + media_uri: str = rest_field(name="mediaUri", visibility=["read", "create", "update", "delete", "query"]) """A media url for the file. Required if the type is one of the supported media types, e.g. image. Required.""" @@ -307,10 +434,82 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, kind=CommunicationMessageKind.AUDIO, **kwargs) -class ButtonContent(_model_base.Model): - """The message content of type Button information. +class Contact(_Model): + """Details of an external platform contact. + + You probably want to use the sub-classes and not this class directly. Known sub-classes are: + BotContact, CommunicationContact, WhatsAppContact + + :ivar id: External platform identifier. Required. + :vartype id: str + :ivar kind: Type of message platform (e.g., WhatsApp). Required. Known values are: + "communication", "bot", and "whatsApp". + :vartype kind: str or ~azure.communication.messages.models.MessagePlatformKind + """ + + __mapping__: Dict[str, _Model] = {} + id: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) + """External platform identifier. Required.""" + kind: str = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) + """Type of message platform (e.g., WhatsApp). Required. Known values are: \"communication\", + \"bot\", and \"whatsApp\".""" + + @overload + def __init__( + self, + *, + id: str, # pylint: disable=redefined-builtin + kind: str, + ) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: + """ + :param mapping: raw JSON to initialize the model. + :type mapping: Mapping[str, Any] + """ + + def __init__(self, *args: Any, **kwargs: Any) -> None: + super().__init__(*args, **kwargs) + + +class BotContact(Contact, discriminator="bot"): + """Bot Contact. + + :ivar id: External platform identifier. Required. + :vartype id: str + :ivar kind: Contact type is bot. Required. Bot platform. + :vartype kind: str or ~azure.communication.messages.models.BOT + :ivar bot_app_id: Bot App Id of the Bot Contact. Required. + :vartype bot_app_id: str + """ + + kind: Literal[MessagePlatformKind.BOT] = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) # type: ignore + """Contact type is bot. Required. Bot platform.""" + bot_app_id: str = rest_field(name="botAppId", visibility=["read", "create", "update", "delete", "query"]) + """Bot App Id of the Bot Contact. Required.""" + + @overload + def __init__( + self, + *, + id: str, # pylint: disable=redefined-builtin + bot_app_id: str, + ) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: + """ + :param mapping: raw JSON to initialize the model. + :type mapping: Mapping[str, Any] + """ + + def __init__(self, *args: Any, **kwargs: Any) -> None: + super().__init__(*args, kind=MessagePlatformKind.BOT, **kwargs) - All required parameters must be populated in order to send to server. + +class ButtonContent(_Model): + """The message content of type Button information. :ivar id: Unique Id of the button content. Required. :vartype id: str @@ -318,9 +517,9 @@ class ButtonContent(_model_base.Model): :vartype title: str """ - id: str = rest_field() + id: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) """Unique Id of the button content. Required.""" - title: str = rest_field() + title: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) """Title of the button content. Required.""" @overload @@ -345,17 +544,15 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: class ButtonSetContent(MessageContent, discriminator="buttonSet"): """The message content of type ButtonSet/ List of buttons information. - All required parameters must be populated in order to send to server. - :ivar kind: Message content kind is Button. Required. The ButtonSet content type. :vartype kind: str or ~azure.communication.messages.models.BUTTON_SET :ivar buttons: Unique Id of the button content. Required. :vartype buttons: list[~azure.communication.messages.models.ButtonContent] """ - kind: Literal[MessageContentKind.BUTTON_SET] = rest_discriminator(name="kind") # type: ignore + kind: Literal[MessageContentKind.BUTTON_SET] = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) # type: ignore """Message content kind is Button. Required. The ButtonSet content type.""" - buttons: List["_models.ButtonContent"] = rest_field() + buttons: List["_models.ButtonContent"] = rest_field(visibility=["read", "create", "update", "delete", "query"]) """Unique Id of the button content. Required.""" @overload @@ -376,20 +573,256 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, kind=MessageContentKind.BUTTON_SET, **kwargs) +class CommunicationContact(Contact, discriminator="communication"): + """Communication Contact. + + :ivar id: External platform identifier. Required. + :vartype id: str + :ivar kind: Contact type is communication. Required. Azure Communication platform. + :vartype kind: str or ~azure.communication.messages.models.COMMUNICATION + """ + + kind: Literal[MessagePlatformKind.COMMUNICATION] = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) # type: ignore + """Contact type is communication. Required. Azure Communication platform.""" + + @overload + def __init__( + self, + *, + id: str, # pylint: disable=redefined-builtin + ) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: + """ + :param mapping: raw JSON to initialize the model. + :type mapping: Mapping[str, Any] + """ + + def __init__(self, *args: Any, **kwargs: Any) -> None: + super().__init__(*args, kind=MessagePlatformKind.COMMUNICATION, **kwargs) + + +class CommunicationConversation(_Model): + """A conversation. + + :ivar id: The conversation ID. Required. + :vartype id: str + :ivar topic: The conversation topic. + :vartype topic: str + :ivar delivery_channel_ids: List of delivery channel IDs. + :vartype delivery_channel_ids: list[str] + :ivar outbound_delivery_strategy: Outbound delivery strategy for the conversation. Known values + are: "internalOnly" and "allParticipants". + :vartype outbound_delivery_strategy: str or + ~azure.communication.messages.models.OutboundDeliveryStrategyKind + :ivar participants: List of participants involved in the conversation. + :vartype participants: list[~azure.communication.messages.models.ConversationParticipant] + """ + + id: str = rest_field(visibility=["read"]) + """The conversation ID. Required.""" + topic: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) + """The conversation topic.""" + delivery_channel_ids: Optional[List[str]] = rest_field( + name="deliveryChannelIds", visibility=["read", "create", "update", "delete", "query"] + ) + """List of delivery channel IDs.""" + outbound_delivery_strategy: Optional[Union[str, "_models.OutboundDeliveryStrategyKind"]] = rest_field( + name="outboundDeliveryStrategy", visibility=["read", "create", "update", "delete", "query"] + ) + """Outbound delivery strategy for the conversation. Known values are: \"internalOnly\" and + \"allParticipants\".""" + participants: Optional[List["_models.ConversationParticipant"]] = rest_field( + visibility=["read", "create", "update", "delete", "query"] + ) + """List of participants involved in the conversation.""" + + @overload + def __init__( + self, + *, + topic: Optional[str] = None, + delivery_channel_ids: Optional[List[str]] = None, + outbound_delivery_strategy: Optional[Union[str, "_models.OutboundDeliveryStrategyKind"]] = None, + participants: Optional[List["_models.ConversationParticipant"]] = None, + ) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: + """ + :param mapping: raw JSON to initialize the model. + :type mapping: Mapping[str, Any] + """ + + def __init__(self, *args: Any, **kwargs: Any) -> None: + super().__init__(*args, **kwargs) + + +class ConversationMessageItem(_Model): + """The conversation message as returned from the service. + + :ivar id: Message ID. Required. + :vartype id: str + :ivar sequence_id: Message sequence ID. + :vartype sequence_id: int + :ivar message: Payload of a threaded conversation message. Required. + :vartype message: ~azure.communication.messages.models.ConversationMessageContent + :ivar sender_display_name: The display name of the message sender. + :vartype sender_display_name: str + :ivar sender_communication_identifier: The communication identifier of the message sender. + Required. + :vartype sender_communication_identifier: str + :ivar created_on: Timestamp when the message is sent. Required. + :vartype created_on: ~datetime.datetime + """ + + id: str = rest_field(visibility=["read"]) + """Message ID. Required.""" + sequence_id: Optional[int] = rest_field( + name="sequenceId", visibility=["read", "create", "update", "delete", "query"] + ) + """Message sequence ID.""" + message: "_models.ConversationMessageContent" = rest_field( + visibility=["read", "create", "update", "delete", "query"] + ) + """Payload of a threaded conversation message. Required.""" + sender_display_name: Optional[str] = rest_field( + name="senderDisplayName", visibility=["read", "create", "update", "delete", "query"] + ) + """The display name of the message sender.""" + sender_communication_identifier: str = rest_field( + name="senderCommunicationIdentifier", visibility=["read", "create", "update", "delete", "query"] + ) + """The communication identifier of the message sender. Required.""" + created_on: datetime.datetime = rest_field( + name="createdOn", visibility=["read", "create", "update", "delete", "query"], format="rfc3339" + ) + """Timestamp when the message is sent. Required.""" + + @overload + def __init__( + self, + *, + message: "_models.ConversationMessageContent", + sender_communication_identifier: str, + created_on: datetime.datetime, + sequence_id: Optional[int] = None, + sender_display_name: Optional[str] = None, + ) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: + """ + :param mapping: raw JSON to initialize the model. + :type mapping: Mapping[str, Any] + """ + + def __init__(self, *args: Any, **kwargs: Any) -> None: + super().__init__(*args, **kwargs) + + +class ConversationParticipant(_Model): + """Advanced Messaging conversation participant. + + You probably want to use the sub-classes and not this class directly. Known sub-classes are: + ExternalConversationParticipant, InternalConversationParticipant + + :ivar id: Participant Identifier. Required. + :vartype id: str + :ivar display_name: Participant display name. + :vartype display_name: str + :ivar kind: The type discriminator describing a participant type. Required. Known values are: + "internal" and "external". + :vartype kind: str or ~azure.communication.messages.models.ParticipantKind + """ + + __mapping__: Dict[str, _Model] = {} + id: str = rest_field(visibility=["read"]) + """Participant Identifier. Required.""" + display_name: Optional[str] = rest_field( + name="displayName", visibility=["read", "create", "update", "delete", "query"] + ) + """Participant display name.""" + kind: str = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) + """The type discriminator describing a participant type. Required. Known values are: \"internal\" + and \"external\".""" + + @overload + def __init__( + self, + *, + kind: str, + display_name: Optional[str] = None, + ) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: + """ + :param mapping: raw JSON to initialize the model. + :type mapping: Mapping[str, Any] + """ + + def __init__(self, *args: Any, **kwargs: Any) -> None: + super().__init__(*args, **kwargs) + + +class DocumentConversationMessageContent(ConversationMessageContent, discriminator="document"): + """A request to send a document conversation message. + + :ivar kind: Message notification type is document. Required. Document message type. + :vartype kind: str or ~azure.communication.messages.models.DOCUMENT + :ivar caption: Optional text content. + :vartype caption: str + :ivar file_name: Optional name for the file. + :vartype file_name: str + :ivar media_uri: A media url for the file. Required if the type is one of the supported media + types, e.g. image. Required. + :vartype media_uri: str + """ + + kind: Literal[CommunicationMessageKind.DOCUMENT] = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) # type: ignore + """Message notification type is document. Required. Document message type.""" + caption: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) + """Optional text content.""" + file_name: Optional[str] = rest_field(name="fileName", visibility=["read", "create", "update", "delete", "query"]) + """Optional name for the file.""" + media_uri: str = rest_field(name="mediaUri", visibility=["read", "create", "update", "delete", "query"]) + """A media url for the file. Required if the type is one of the supported media types, e.g. image. + Required.""" + + @overload + def __init__( + self, + *, + media_uri: str, + caption: Optional[str] = None, + file_name: Optional[str] = None, + ) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: + """ + :param mapping: raw JSON to initialize the model. + :type mapping: Mapping[str, Any] + """ + + def __init__(self, *args: Any, **kwargs: Any) -> None: + super().__init__(*args, kind=CommunicationMessageKind.DOCUMENT, **kwargs) + + class DocumentMessageContent(MessageContent, discriminator="document"): """The message content of type document information. - All required parameters must be populated in order to send to server. - :ivar kind: Message content kind is document. Required. The document content type. :vartype kind: str or ~azure.communication.messages.models.DOCUMENT :ivar media_uri: MediaUri of the media content. Required. :vartype media_uri: str """ - kind: Literal[MessageContentKind.DOCUMENT] = rest_discriminator(name="kind") # type: ignore + kind: Literal[MessageContentKind.DOCUMENT] = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) # type: ignore """Message content kind is document. Required. The document content type.""" - media_uri: str = rest_field(name="mediaUri") + media_uri: str = rest_field(name="mediaUri", visibility=["read", "create", "update", "delete", "query"]) """MediaUri of the media content. Required.""" @overload @@ -413,14 +846,12 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: class DocumentNotificationContent(NotificationContent, discriminator="document"): """A request to send a document notification. - All required parameters must be populated in order to send to server. - :ivar channel_registration_id: The Channel Registration ID for the Business Identifier. Required. :vartype channel_registration_id: str :ivar to: The native external platform user identifiers of the recipient. Required. :vartype to: list[str] - :ivar kind: Message notification type is image. Required. Document message type. + :ivar kind: Message notification type is document. Required. Document message type. :vartype kind: str or ~azure.communication.messages.models.DOCUMENT :ivar caption: Optional text content. :vartype caption: str @@ -431,13 +862,13 @@ class DocumentNotificationContent(NotificationContent, discriminator="document") :vartype media_uri: str """ - kind: Literal[CommunicationMessageKind.DOCUMENT] = rest_discriminator(name="kind") # type: ignore - """Message notification type is image. Required. Document message type.""" - caption: Optional[str] = rest_field() + kind: Literal[CommunicationMessageKind.DOCUMENT] = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) # type: ignore + """Message notification type is document. Required. Document message type.""" + caption: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) """Optional text content.""" - file_name: Optional[str] = rest_field(name="fileName") + file_name: Optional[str] = rest_field(name="fileName", visibility=["read", "create", "update", "delete", "query"]) """Optional name for the file.""" - media_uri: str = rest_field(name="mediaUri") + media_uri: str = rest_field(name="mediaUri", visibility=["read", "create", "update", "delete", "query"]) """A media url for the file. Required if the type is one of the supported media types, e.g. image. Required.""" @@ -463,20 +894,122 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, kind=CommunicationMessageKind.DOCUMENT, **kwargs) +class ExternalConversationParticipant(ConversationParticipant, discriminator="external"): + """External conversation participant. + + :ivar id: Participant Identifier. Required. + :vartype id: str + :ivar display_name: Participant display name. + :vartype display_name: str + :ivar kind: Participant type is external. Required. A participant on other platforms + :vartype kind: str or ~azure.communication.messages.models.EXTERNAL + :ivar contacts: List of external platform identifiers for the participant. Required. + :vartype contacts: list[~azure.communication.messages.models.Contact] + """ + + kind: Literal[ParticipantKind.EXTERNAL] = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) # type: ignore + """Participant type is external. Required. A participant on other platforms""" + contacts: List["_models.Contact"] = rest_field(visibility=["read", "create", "update", "delete", "query"]) + """List of external platform identifiers for the participant. Required.""" + + @overload + def __init__( + self, + *, + contacts: List["_models.Contact"], + display_name: Optional[str] = None, + ) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: + """ + :param mapping: raw JSON to initialize the model. + :type mapping: Mapping[str, Any] + """ + + def __init__(self, *args: Any, **kwargs: Any) -> None: + super().__init__(*args, kind=ParticipantKind.EXTERNAL, **kwargs) + + +class GetConversationThreadAnalysisResult(_Model): + """Result of the get conversation messages AI Analysis operation. + + :ivar summary: The AI summary of the conversation messages. Required. + :vartype summary: str + """ + + summary: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) + """The AI summary of the conversation messages. Required.""" + + @overload + def __init__( + self, + *, + summary: str, + ) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: + """ + :param mapping: raw JSON to initialize the model. + :type mapping: Mapping[str, Any] + """ + + def __init__(self, *args: Any, **kwargs: Any) -> None: + super().__init__(*args, **kwargs) + + +class ImageConversationMessageContent(ConversationMessageContent, discriminator="image"): + """A request to send an image conversation message. + + :ivar kind: Message notification type is image. Required. Image message type. + :vartype kind: str or ~azure.communication.messages.models.IMAGE + :ivar content: Optional text content. + :vartype content: str + :ivar media_uri: A media url for the file. Required if the type is one of the supported media + types, e.g. image. Required. + :vartype media_uri: str + """ + + kind: Literal[CommunicationMessageKind.IMAGE] = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) # type: ignore + """Message notification type is image. Required. Image message type.""" + content: Optional[str] = rest_field(name="caption", visibility=["read", "create", "update", "delete", "query"]) + """Optional text content.""" + media_uri: str = rest_field(name="mediaUri", visibility=["read", "create", "update", "delete", "query"]) + """A media url for the file. Required if the type is one of the supported media types, e.g. image. + Required.""" + + @overload + def __init__( + self, + *, + media_uri: str, + content: Optional[str] = None, + ) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: + """ + :param mapping: raw JSON to initialize the model. + :type mapping: Mapping[str, Any] + """ + + def __init__(self, *args: Any, **kwargs: Any) -> None: + super().__init__(*args, kind=CommunicationMessageKind.IMAGE, **kwargs) + + class ImageMessageContent(MessageContent, discriminator="image"): """The message content of type image information. - All required parameters must be populated in order to send to server. - :ivar kind: Message content kind is image. Required. The image content type. :vartype kind: str or ~azure.communication.messages.models.IMAGE :ivar media_uri: MediaUri of the media content. Required. :vartype media_uri: str """ - kind: Literal[MessageContentKind.IMAGE] = rest_discriminator(name="kind") # type: ignore + kind: Literal[MessageContentKind.IMAGE] = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) # type: ignore """Message content kind is image. Required. The image content type.""" - media_uri: str = rest_field(name="mediaUri") + media_uri: str = rest_field(name="mediaUri", visibility=["read", "create", "update", "delete", "query"]) """MediaUri of the media content. Required.""" @overload @@ -500,8 +1033,6 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: class ImageNotificationContent(NotificationContent, discriminator="image"): """A request to send an image notification. - All required parameters must be populated in order to send to server. - :ivar channel_registration_id: The Channel Registration ID for the Business Identifier. Required. :vartype channel_registration_id: str @@ -516,11 +1047,11 @@ class ImageNotificationContent(NotificationContent, discriminator="image"): :vartype media_uri: str """ - kind: Literal[CommunicationMessageKind.IMAGE] = rest_discriminator(name="kind") # type: ignore + kind: Literal[CommunicationMessageKind.IMAGE] = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) # type: ignore """Message notification type is image. Required. Image message type.""" - content: Optional[str] = rest_field(name="caption") + content: Optional[str] = rest_field(name="caption", visibility=["read", "create", "update", "delete", "query"]) """Optional text content.""" - media_uri: str = rest_field(name="mediaUri") + media_uri: str = rest_field(name="mediaUri", visibility=["read", "create", "update", "delete", "query"]) """A media url for the file. Required if the type is one of the supported media types, e.g. image. Required.""" @@ -545,11 +1076,9 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, kind=CommunicationMessageKind.IMAGE, **kwargs) -class InteractiveMessage(_model_base.Model): +class InteractiveMessage(_Model): """The Interactive message content to which user can read and respond. - All required parameters must be populated in order to send to server. - :ivar header: Gets or Sets Header content. Supports the following types:text, images etc. :vartype header: ~azure.communication.messages.models.MessageContent :ivar body: Gets or Sets Message body content. Emojis, markdown, and links are supported. @@ -562,13 +1091,15 @@ class InteractiveMessage(_model_base.Model): :vartype action: ~azure.communication.messages.models.ActionBindings """ - header: Optional["_models.MessageContent"] = rest_field() + header: Optional["_models.MessageContent"] = rest_field(visibility=["read", "create", "update", "delete", "query"]) """Gets or Sets Header content. Supports the following types:text, images etc.""" - body: "_models.TextMessageContent" = rest_field() + body: "_models.TextMessageContent" = rest_field(visibility=["read", "create", "update", "delete", "query"]) """Gets or Sets Message body content. Emojis, markdown, and links are supported. Required.""" - footer: Optional["_models.TextMessageContent"] = rest_field() + footer: Optional["_models.TextMessageContent"] = rest_field( + visibility=["read", "create", "update", "delete", "query"] + ) """Gets or Sets Message footer content. Emojis, markdown, and links are supported.""" - action: "_models.ActionBindings" = rest_field() + action: "_models.ActionBindings" = rest_field(visibility=["read", "create", "update", "delete", "query"]) """The binding object to get or set Action which describes options user have to respond to message. Required.""" @@ -596,8 +1127,6 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: class InteractiveNotificationContent(NotificationContent, discriminator="interactive"): """A request to send an Interactive message notification. - All required parameters must be populated in order to send to server. - :ivar channel_registration_id: The Channel Registration ID for the Business Identifier. Required. :vartype channel_registration_id: str @@ -610,9 +1139,11 @@ class InteractiveNotificationContent(NotificationContent, discriminator="interac :vartype interactive_message: ~azure.communication.messages.models.InteractiveMessage """ - kind: Literal[CommunicationMessageKind.INTERACTIVE] = rest_discriminator(name="kind") # type: ignore + kind: Literal[CommunicationMessageKind.INTERACTIVE] = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) # type: ignore """Message notification type is Interactive. Required. Interactive Actionable message type.""" - interactive_message: "_models.InteractiveMessage" = rest_field(name="interactiveMessage") + interactive_message: "_models.InteractiveMessage" = rest_field( + name="interactiveMessage", visibility=["read", "create", "update", "delete", "query"] + ) """The interactive message content. Required.""" @overload @@ -635,11 +1166,47 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, kind=CommunicationMessageKind.INTERACTIVE, **kwargs) +class InternalConversationParticipant(ConversationParticipant, discriminator="internal"): + """Internal conversation participant. + + :ivar id: Participant Identifier. Required. + :vartype id: str + :ivar display_name: Participant display name. + :vartype display_name: str + :ivar kind: Participant type is internal. Required. A participant internal to Azure + Communication Services. + :vartype kind: str or ~azure.communication.messages.models.INTERNAL + :ivar contact: The internal platform identifiers for the participant. Required. + :vartype contact: ~azure.communication.messages.models.Contact + """ + + kind: Literal[ParticipantKind.INTERNAL] = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) # type: ignore + """Participant type is internal. Required. A participant internal to Azure Communication Services.""" + contact: "_models.Contact" = rest_field(visibility=["read", "create", "update", "delete", "query"]) + """The internal platform identifiers for the participant. Required.""" + + @overload + def __init__( + self, + *, + contact: "_models.Contact", + display_name: Optional[str] = None, + ) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: + """ + :param mapping: raw JSON to initialize the model. + :type mapping: Mapping[str, Any] + """ + + def __init__(self, *args: Any, **kwargs: Any) -> None: + super().__init__(*args, kind=ParticipantKind.INTERNAL, **kwargs) + + class LinkContent(MessageContent, discriminator="url"): """The message content of type Url information. - All required parameters must be populated in order to send to server. - :ivar kind: Message content kind is url. Required. The Url content type. :vartype kind: str or ~azure.communication.messages.models.URL :ivar title: Title of the url content. Required. @@ -648,11 +1215,11 @@ class LinkContent(MessageContent, discriminator="url"): :vartype url: str """ - kind: Literal[MessageContentKind.URL] = rest_discriminator(name="kind") # type: ignore + kind: Literal[MessageContentKind.URL] = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) # type: ignore """Message content kind is url. Required. The Url content type.""" - title: str = rest_field() + title: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) """Title of the url content. Required.""" - url: str = rest_field() + url: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) """The url in the content. Required.""" @overload @@ -677,8 +1244,6 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: class MediaNotificationContent(NotificationContent, discriminator="image_v0"): """@deprecated A request to send an image notification. - All required parameters must be populated in order to send to server. - :ivar channel_registration_id: The Channel Registration ID for the Business Identifier. Required. :vartype channel_registration_id: str @@ -694,12 +1259,12 @@ class MediaNotificationContent(NotificationContent, discriminator="image_v0"): :vartype media_uri: str """ - kind: Literal[CommunicationMessageKind.IMAGE_V0] = rest_discriminator(name="kind") # type: ignore + kind: Literal[CommunicationMessageKind.IMAGE_V0] = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) # type: ignore """Message notification type is image. Required. Image message type. Legacy image type for ``MediaNotificationContent`` which is being deprecated""" - content: Optional[str] = rest_field() + content: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) """Optional text content.""" - media_uri: str = rest_field(name="mediaUri") + media_uri: str = rest_field(name="mediaUri", visibility=["read", "create", "update", "delete", "query"]) """A media url for the file. Required if the type is one of the supported media types, e.g. image. Required.""" @@ -707,10 +1272,38 @@ class MediaNotificationContent(NotificationContent, discriminator="image_v0"): def __init__( self, *, - channel_registration_id: str, - to: List[str], - media_uri: str, - content: Optional[str] = None, + channel_registration_id: str, + to: List[str], + media_uri: str, + content: Optional[str] = None, + ) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: + """ + :param mapping: raw JSON to initialize the model. + :type mapping: Mapping[str, Any] + """ + + def __init__(self, *args: Any, **kwargs: Any) -> None: + super().__init__(*args, kind=CommunicationMessageKind.IMAGE_V0, **kwargs) + + +class Message(_Model): + """Details of a message. + + :ivar content: Content of the message. Required. + :vartype content: str + """ + + content: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) + """Content of the message. Required.""" + + @overload + def __init__( + self, + *, + content: str, ) -> None: ... @overload @@ -721,22 +1314,21 @@ def __init__(self, mapping: Mapping[str, Any]) -> None: """ def __init__(self, *args: Any, **kwargs: Any) -> None: - super().__init__(*args, kind=CommunicationMessageKind.IMAGE_V0, **kwargs) + super().__init__(*args, **kwargs) -class MessageReceipt(_model_base.Model): +class MessageReceipt(_Model): """Receipt of the sending one message. - :ivar message_id: The message id. Required. :vartype message_id: str :ivar to: The native external platform user identifier of the recipient. Required. :vartype to: str """ - message_id: str = rest_field(name="messageId") + message_id: str = rest_field(name="messageId", visibility=["read", "create", "update", "delete", "query"]) """The message id. Required.""" - to: str = rest_field() + to: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) """The native external platform user identifier of the recipient. Required.""" @overload @@ -758,11 +1350,9 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) -class MessageTemplate(_model_base.Model): +class MessageTemplate(_Model): """The template object used to create templates. - All required parameters must be populated in order to send to server. - :ivar name: Name of the template. Required. :vartype name: str :ivar language: The template's language, in the ISO 639 format, consist of a two-letter @@ -774,14 +1364,18 @@ class MessageTemplate(_model_base.Model): :vartype bindings: ~azure.communication.messages.models.MessageTemplateBindings """ - name: str = rest_field() + name: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) """Name of the template. Required.""" - language: str = rest_field() + language: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) """The template's language, in the ISO 639 format, consist of a two-letter language code followed by an optional two-letter country code, e.g., 'en' or 'en_US'. Required.""" - template_values: Optional[List["_models.MessageTemplateValue"]] = rest_field(name="values") + template_values: Optional[List["_models.MessageTemplateValue"]] = rest_field( + name="values", visibility=["read", "create", "update", "delete", "query"] + ) """The template values.""" - bindings: Optional["_models.MessageTemplateBindings"] = rest_field() + bindings: Optional["_models.MessageTemplateBindings"] = rest_field( + visibility=["read", "create", "update", "delete", "query"] + ) """The binding object to link values to the template specific locations.""" @overload @@ -805,20 +1399,18 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) -class MessageTemplateBindings(_model_base.Model): +class MessageTemplateBindings(_Model): """The binding object to link values to the template specific locations. You probably want to use the sub-classes and not this class directly. Known sub-classes are: WhatsAppMessageTemplateBindings - All required parameters must be populated in order to send to server. - :ivar kind: The type discriminator describing a template bindings type. Required. "whatsApp" :vartype kind: str or ~azure.communication.messages.models.MessageTemplateBindingsKind """ - __mapping__: Dict[str, _model_base.Model] = {} - kind: str = rest_discriminator(name="kind") + __mapping__: Dict[str, _Model] = {} + kind: str = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) """The type discriminator describing a template bindings type. Required. \"whatsApp\"""" @overload @@ -839,15 +1431,13 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) -class MessageTemplateValue(_model_base.Model): +class MessageTemplateValue(_Model): """The class describes a parameter of a template. You probably want to use the sub-classes and not this class directly. Known sub-classes are: MessageTemplateDocument, MessageTemplateImage, MessageTemplateLocation, MessageTemplateQuickAction, MessageTemplateText, MessageTemplateVideo - All required parameters must be populated in order to send to server. - :ivar name: Template binding reference name. Required. :vartype name: str :ivar kind: The type discriminator describing a template parameter type. Required. Known values @@ -855,10 +1445,10 @@ class MessageTemplateValue(_model_base.Model): :vartype kind: str or ~azure.communication.messages.models.MessageTemplateValueKind """ - __mapping__: Dict[str, _model_base.Model] = {} - name: str = rest_field() + __mapping__: Dict[str, _Model] = {} + name: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) """Template binding reference name. Required.""" - kind: str = rest_discriminator(name="kind") + kind: str = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) """The type discriminator describing a template parameter type. Required. Known values are: \"text\", \"image\", \"document\", \"video\", \"location\", and \"quickAction\".""" @@ -884,8 +1474,6 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: class MessageTemplateDocument(MessageTemplateValue, discriminator="document"): """The message template's document value information. - All required parameters must be populated in order to send to server. - :ivar name: Template binding reference name. Required. :vartype name: str :ivar kind: Message parameter type is document. Required. The document template parameter type. @@ -898,13 +1486,13 @@ class MessageTemplateDocument(MessageTemplateValue, discriminator="document"): :vartype file_name: str """ - kind: Literal[MessageTemplateValueKind.DOCUMENT] = rest_discriminator(name="kind") # type: ignore + kind: Literal[MessageTemplateValueKind.DOCUMENT] = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) # type: ignore """Message parameter type is document. Required. The document template parameter type.""" - url: str = rest_field() + url: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) """The (public) URL of the media. Required.""" - caption: Optional[str] = rest_field() + caption: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) """The [optional] caption of the media object.""" - file_name: Optional[str] = rest_field(name="fileName") + file_name: Optional[str] = rest_field(name="fileName", visibility=["read", "create", "update", "delete", "query"]) """The [optional] filename of the media file.""" @overload @@ -931,8 +1519,6 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: class MessageTemplateImage(MessageTemplateValue, discriminator="image"): """The message template's image value information. - All required parameters must be populated in order to send to server. - :ivar name: Template binding reference name. Required. :vartype name: str :ivar kind: Message parameter type is image. Required. The image template parameter type. @@ -945,13 +1531,13 @@ class MessageTemplateImage(MessageTemplateValue, discriminator="image"): :vartype file_name: str """ - kind: Literal[MessageTemplateValueKind.IMAGE] = rest_discriminator(name="kind") # type: ignore + kind: Literal[MessageTemplateValueKind.IMAGE] = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) # type: ignore """Message parameter type is image. Required. The image template parameter type.""" - url: str = rest_field() + url: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) """The (public) URL of the media. Required.""" - caption: Optional[str] = rest_field() + caption: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) """The [optional] caption of the media object.""" - file_name: Optional[str] = rest_field(name="fileName") + file_name: Optional[str] = rest_field(name="fileName", visibility=["read", "create", "update", "delete", "query"]) """The [optional] filename of the media file.""" @overload @@ -975,15 +1561,12 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, kind=MessageTemplateValueKind.IMAGE, **kwargs) -class MessageTemplateItem(_model_base.Model): +class MessageTemplateItem(_Model): """The message template as returned from the service. You probably want to use the sub-classes and not this class directly. Known sub-classes are: WhatsAppMessageTemplateItem - Readonly variables are only populated by the server, and will be ignored when sending a request. - - :ivar name: The template's name. Required. :vartype name: str :ivar language: The template's language, in the ISO 639 format, consist of a two-letter @@ -996,16 +1579,18 @@ class MessageTemplateItem(_model_base.Model): :vartype kind: str or ~azure.communication.messages.models.CommunicationMessagesChannel """ - __mapping__: Dict[str, _model_base.Model] = {} + __mapping__: Dict[str, _Model] = {} name: str = rest_field(visibility=["read"]) """The template's name. Required.""" - language: str = rest_field() + language: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) """The template's language, in the ISO 639 format, consist of a two-letter language code followed by an optional two-letter country code, e.g., 'en' or 'en_US'. Required.""" - status: Union[str, "_models.MessageTemplateStatus"] = rest_field() + status: Union[str, "_models.MessageTemplateStatus"] = rest_field( + visibility=["read", "create", "update", "delete", "query"] + ) """The aggregated template status. Required. Known values are: \"approved\", \"rejected\", \"pending\", and \"paused\".""" - kind: str = rest_discriminator(name="kind") + kind: str = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) """The type discriminator describing a template type. Required. \"whatsApp\"""" @overload @@ -1031,8 +1616,6 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: class MessageTemplateLocation(MessageTemplateValue, discriminator="location"): """The message template's location value information. - All required parameters must be populated in order to send to server. - :ivar name: Template binding reference name. Required. :vartype name: str :ivar kind: Message parameter type is location. Required. The location template parameter type. @@ -1047,15 +1630,17 @@ class MessageTemplateLocation(MessageTemplateValue, discriminator="location"): :vartype longitude: float """ - kind: Literal[MessageTemplateValueKind.LOCATION] = rest_discriminator(name="kind") # type: ignore + kind: Literal[MessageTemplateValueKind.LOCATION] = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) # type: ignore """Message parameter type is location. Required. The location template parameter type.""" - location_name: Optional[str] = rest_field(name="locationName") + location_name: Optional[str] = rest_field( + name="locationName", visibility=["read", "create", "update", "delete", "query"] + ) """The [Optional] name of the location.""" - address: Optional[str] = rest_field() + address: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) """The [Optional] address of the location.""" - latitude: float = rest_field() + latitude: float = rest_field(visibility=["read", "create", "update", "delete", "query"]) """The latitude of the location. Required.""" - longitude: float = rest_field() + longitude: float = rest_field(visibility=["read", "create", "update", "delete", "query"]) """The longitude of the location. Required.""" @overload @@ -1083,8 +1668,6 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: class MessageTemplateQuickAction(MessageTemplateValue, discriminator="quickAction"): """The message template's quick action value information. - All required parameters must be populated in order to send to server. - :ivar name: Template binding reference name. Required. :vartype name: str :ivar kind: Message parameter type is quick action. Required. The quick action template @@ -1096,11 +1679,11 @@ class MessageTemplateQuickAction(MessageTemplateValue, discriminator="quickActio :vartype payload: str """ - kind: Literal[MessageTemplateValueKind.QUICK_ACTION] = rest_discriminator(name="kind") # type: ignore + kind: Literal[MessageTemplateValueKind.QUICK_ACTION] = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) # type: ignore """Message parameter type is quick action. Required. The quick action template parameter type.""" - text: Optional[str] = rest_field() + text: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) """The [Optional] quick action text.""" - payload: Optional[str] = rest_field() + payload: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) """The [Optional] quick action payload.""" @overload @@ -1126,8 +1709,6 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: class MessageTemplateText(MessageTemplateValue, discriminator="text"): """The message template's text value information. - All required parameters must be populated in order to send to server. - :ivar name: Template binding reference name. Required. :vartype name: str :ivar kind: Message parameter type is text. Required. The text template parameter type. @@ -1136,9 +1717,9 @@ class MessageTemplateText(MessageTemplateValue, discriminator="text"): :vartype text: str """ - kind: Literal[MessageTemplateValueKind.TEXT] = rest_discriminator(name="kind") # type: ignore + kind: Literal[MessageTemplateValueKind.TEXT] = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) # type: ignore """Message parameter type is text. Required. The text template parameter type.""" - text: str = rest_field() + text: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) """The text value. Required.""" @overload @@ -1163,8 +1744,6 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: class MessageTemplateVideo(MessageTemplateValue, discriminator="video"): """The message template's video value information. - All required parameters must be populated in order to send to server. - :ivar name: Template binding reference name. Required. :vartype name: str :ivar kind: Message parameter type is video. Required. The video template parameter type. @@ -1177,13 +1756,13 @@ class MessageTemplateVideo(MessageTemplateValue, discriminator="video"): :vartype file_name: str """ - kind: Literal[MessageTemplateValueKind.VIDEO] = rest_discriminator(name="kind") # type: ignore + kind: Literal[MessageTemplateValueKind.VIDEO] = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) # type: ignore """Message parameter type is video. Required. The video template parameter type.""" - url: str = rest_field() + url: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) """The (public) URL of the media. Required.""" - caption: Optional[str] = rest_field() + caption: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) """The [optional] caption of the media object.""" - file_name: Optional[str] = rest_field(name="fileName") + file_name: Optional[str] = rest_field(name="fileName", visibility=["read", "create", "update", "delete", "query"]) """The [optional] filename of the media file.""" @overload @@ -1210,8 +1789,6 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: class ReactionNotificationContent(NotificationContent, discriminator="reaction"): """A request to send a Reaction notification. - All required parameters must be populated in order to send to server. - :ivar channel_registration_id: The Channel Registration ID for the Business Identifier. Required. :vartype channel_registration_id: str @@ -1219,17 +1796,17 @@ class ReactionNotificationContent(NotificationContent, discriminator="reaction") :vartype to: list[str] :ivar kind: Message notification type is reaction. Required. Reaction message type. :vartype kind: str or ~azure.communication.messages.models.REACTION - :ivar emoji: emoji content like uD83D. Required. + :ivar emoji: emoji content like \\uD83D\\uDE00. Required. :vartype emoji: str :ivar message_id: ID of the previous message you want to reply to. Required. :vartype message_id: str """ - kind: Literal[CommunicationMessageKind.REACTION] = rest_discriminator(name="kind") # type: ignore + kind: Literal[CommunicationMessageKind.REACTION] = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) # type: ignore """Message notification type is reaction. Required. Reaction message type.""" - emoji: str = rest_field() - """emoji content like :) Required.""" - message_id: str = rest_field(name="messageId") + emoji: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) + """emoji content like \uD83D\uDE00. Required.""" + message_id: str = rest_field(name="messageId", visibility=["read", "create", "update", "delete", "query"]) """ID of the previous message you want to reply to. Required.""" @overload @@ -1253,15 +1830,145 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, kind=CommunicationMessageKind.REACTION, **kwargs) -class SendMessageResult(_model_base.Model): - """Result of the send message operation. +class RemoveParticipantsOptions(_Model): + """Request payload for removing participants from a conversation. + + :ivar participant_ids: The participant IDs to remove. Required. + :vartype participant_ids: list[str] + """ + + participant_ids: List[str] = rest_field( + name="participantIds", visibility=["read", "create", "update", "delete", "query"] + ) + """The participant IDs to remove. Required.""" + + @overload + def __init__( + self, + *, + participant_ids: List[str], + ) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: + """ + :param mapping: raw JSON to initialize the model. + :type mapping: Mapping[str, Any] + """ + + def __init__(self, *args: Any, **kwargs: Any) -> None: + super().__init__(*args, **kwargs) + + +class RemoveParticipantsResult(_Model): + """Response for the remove participants operation. + + :ivar invalid_participants: List of Ids with Errors if failed to be added. Required. + :vartype invalid_participants: + list[~azure.communication.messages.models.UpdateParticipantsResult] + """ + + invalid_participants: List["_models.UpdateParticipantsResult"] = rest_field( + name="invalidParticipants", visibility=["read", "create", "update", "delete", "query"] + ) + """List of Ids with Errors if failed to be added. Required.""" + + @overload + def __init__( + self, + *, + invalid_participants: List["_models.UpdateParticipantsResult"], + ) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: + """ + :param mapping: raw JSON to initialize the model. + :type mapping: Mapping[str, Any] + """ + + def __init__(self, *args: Any, **kwargs: Any) -> None: + super().__init__(*args, **kwargs) + +class SendConversationMessageOptions(_Model): + """Request payload for sending a conversation message. + + :ivar request: Details of a send conversation message request. Required. + :vartype request: ~azure.communication.messages.models.ConversationMessageContent + :ivar outbound_delivery_strategy: The options of the outbound delivery strategy for messages + sent by participants in a conversation. + Supports internalOnly, allChannels. Known values are: "internalOnly" and "allParticipants". + :vartype outbound_delivery_strategy: str or + ~azure.communication.messages.models.OutboundDeliveryStrategyKind + """ + + request: "_models.ConversationMessageContent" = rest_field( + visibility=["read", "create", "update", "delete", "query"] + ) + """Details of a send conversation message request. Required.""" + outbound_delivery_strategy: Optional[Union[str, "_models.OutboundDeliveryStrategyKind"]] = rest_field( + name="outboundDeliveryStrategy", visibility=["read", "create", "update", "delete", "query"] + ) + """The options of the outbound delivery strategy for messages sent by participants in a + conversation. + Supports internalOnly, allChannels. Known values are: \"internalOnly\" and \"allParticipants\".""" + + @overload + def __init__( + self, + *, + request: "_models.ConversationMessageContent", + outbound_delivery_strategy: Optional[Union[str, "_models.OutboundDeliveryStrategyKind"]] = None, + ) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: + """ + :param mapping: raw JSON to initialize the model. + :type mapping: Mapping[str, Any] + """ + + def __init__(self, *args: Any, **kwargs: Any) -> None: + super().__init__(*args, **kwargs) + + +class SendConversationMessageResult(_Model): + """Result of the send conversation message operation. + + :ivar message_id: A server-generated Advanced Messaging conversation message id. Required. + :vartype message_id: str + """ + + message_id: str = rest_field(name="messageId", visibility=["read", "create", "update", "delete", "query"]) + """A server-generated Advanced Messaging conversation message id. Required.""" + + @overload + def __init__( + self, + *, + message_id: str, + ) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: + """ + :param mapping: raw JSON to initialize the model. + :type mapping: Mapping[str, Any] + """ + + def __init__(self, *args: Any, **kwargs: Any) -> None: + super().__init__(*args, **kwargs) + + +class SendMessageResult(_Model): + """Result of the send message operation. :ivar receipts: Receipts of the send message operation. Required. :vartype receipts: list[~azure.communication.messages.models.MessageReceipt] """ - receipts: List["_models.MessageReceipt"] = rest_field() + receipts: List["_models.MessageReceipt"] = rest_field(visibility=["read", "create", "update", "delete", "query"]) """Receipts of the send message operation. Required.""" @overload @@ -1285,8 +1992,6 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: class StickerNotificationContent(NotificationContent, discriminator="sticker"): """A request to send a Sticker notification. - All required parameters must be populated in order to send to server. - :ivar channel_registration_id: The Channel Registration ID for the Business Identifier. Required. :vartype channel_registration_id: str @@ -1299,9 +2004,9 @@ class StickerNotificationContent(NotificationContent, discriminator="sticker"): :vartype media_uri: str """ - kind: Literal[CommunicationMessageKind.STICKER] = rest_discriminator(name="kind") # type: ignore + kind: Literal[CommunicationMessageKind.STICKER] = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) # type: ignore """Message notification type is sticker. Required. Sticker message type.""" - media_uri: str = rest_field(name="mediaUri") + media_uri: str = rest_field(name="mediaUri", visibility=["read", "create", "update", "delete", "query"]) """A media url for the file. Required if the type is one of the supported media types, e.g. image. Required.""" @@ -1325,11 +2030,41 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, kind=CommunicationMessageKind.STICKER, **kwargs) +class TemplateConversationMessageContent(ConversationMessageContent, discriminator="template"): + """A request to send a template conversation message. + + :ivar kind: Message notification type is template. Required. Template message type. + :vartype kind: str or ~azure.communication.messages.models.TEMPLATE + :ivar template: The template object used to create templates. Required. + :vartype template: ~azure.communication.messages.models.MessageTemplate + """ + + kind: Literal[CommunicationMessageKind.TEMPLATE] = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) # type: ignore + """Message notification type is template. Required. Template message type.""" + template: "_models.MessageTemplate" = rest_field(visibility=["read", "create", "update", "delete", "query"]) + """The template object used to create templates. Required.""" + + @overload + def __init__( + self, + *, + template: "_models.MessageTemplate", + ) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: + """ + :param mapping: raw JSON to initialize the model. + :type mapping: Mapping[str, Any] + """ + + def __init__(self, *args: Any, **kwargs: Any) -> None: + super().__init__(*args, kind=CommunicationMessageKind.TEMPLATE, **kwargs) + + class TemplateNotificationContent(NotificationContent, discriminator="template"): """A request to send a template notification. - All required parameters must be populated in order to send to server. - :ivar channel_registration_id: The Channel Registration ID for the Business Identifier. Required. :vartype channel_registration_id: str @@ -1341,9 +2076,9 @@ class TemplateNotificationContent(NotificationContent, discriminator="template") :vartype template: ~azure.communication.messages.models.MessageTemplate """ - kind: Literal[CommunicationMessageKind.TEMPLATE] = rest_discriminator(name="kind") # type: ignore + kind: Literal[CommunicationMessageKind.TEMPLATE] = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) # type: ignore """Message notification type is template. Required. Template message type.""" - template: "_models.MessageTemplate" = rest_field() + template: "_models.MessageTemplate" = rest_field(visibility=["read", "create", "update", "delete", "query"]) """The template object used to create templates. Required.""" @overload @@ -1366,20 +2101,50 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, kind=CommunicationMessageKind.TEMPLATE, **kwargs) +class TextConversationMessageContent(ConversationMessageContent, discriminator="text"): + """A request to send a text conversation message. + + :ivar kind: Message notification type is text. Required. Text message type. + :vartype kind: str or ~azure.communication.messages.models.TEXT + :ivar content: Message content. Required. + :vartype content: str + """ + + kind: Literal[CommunicationMessageKind.TEXT] = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) # type: ignore + """Message notification type is text. Required. Text message type.""" + content: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) + """Message content. Required.""" + + @overload + def __init__( + self, + *, + content: str, + ) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: + """ + :param mapping: raw JSON to initialize the model. + :type mapping: Mapping[str, Any] + """ + + def __init__(self, *args: Any, **kwargs: Any) -> None: + super().__init__(*args, kind=CommunicationMessageKind.TEXT, **kwargs) + + class TextMessageContent(MessageContent, discriminator="text"): """The message content of type text information. - All required parameters must be populated in order to send to server. - :ivar kind: Message content kind is text. Required. The text content type. :vartype kind: str or ~azure.communication.messages.models.TEXT :ivar text: The text value. Required. :vartype text: str """ - kind: Literal[MessageContentKind.TEXT] = rest_discriminator(name="kind") # type: ignore + kind: Literal[MessageContentKind.TEXT] = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) # type: ignore """Message content kind is text. Required. The text content type.""" - text: str = rest_field() + text: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) """The text value. Required.""" @overload @@ -1403,8 +2168,6 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: class TextNotificationContent(NotificationContent, discriminator="text"): """A request to send a text notification. - All required parameters must be populated in order to send to server. - :ivar channel_registration_id: The Channel Registration ID for the Business Identifier. Required. :vartype channel_registration_id: str @@ -1416,9 +2179,9 @@ class TextNotificationContent(NotificationContent, discriminator="text"): :vartype content: str """ - kind: Literal[CommunicationMessageKind.TEXT] = rest_discriminator(name="kind") # type: ignore + kind: Literal[CommunicationMessageKind.TEXT] = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) # type: ignore """Message notification type is text. Required. Text message type.""" - content: str = rest_field() + content: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) """Message content. Required.""" @overload @@ -1441,20 +2204,90 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, kind=CommunicationMessageKind.TEXT, **kwargs) +class UpdateParticipantsResult(_Model): + """Response for the remove participants operation. + + :ivar id: Participant User Id. Required. + :vartype id: str + :ivar error: Error of the participant operation. + :vartype error: ~azure.core.ODataV4Format + """ + + id: str = rest_field(visibility=["read", "create", "update", "delete", "query"]) + """Participant User Id. Required.""" + error: Optional[ODataV4Format] = rest_field(visibility=["read", "create", "update", "delete", "query"]) + """Error of the participant operation.""" + + @overload + def __init__( + self, + *, + id: str, # pylint: disable=redefined-builtin + error: Optional[ODataV4Format] = None, + ) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: + """ + :param mapping: raw JSON to initialize the model. + :type mapping: Mapping[str, Any] + """ + + def __init__(self, *args: Any, **kwargs: Any) -> None: + super().__init__(*args, **kwargs) + + +class VideoConversationMessageContent(ConversationMessageContent, discriminator="video"): + """A request to send a video conversation message. + + :ivar kind: Message notification type is video. Required. Video message type. + :vartype kind: str or ~azure.communication.messages.models.VIDEO + :ivar caption: Optional text content. + :vartype caption: str + :ivar media_uri: A media url for the file. Required if the type is one of the supported media + types, e.g. image. Required. + :vartype media_uri: str + """ + + kind: Literal[CommunicationMessageKind.VIDEO] = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) # type: ignore + """Message notification type is video. Required. Video message type.""" + caption: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) + """Optional text content.""" + media_uri: str = rest_field(name="mediaUri", visibility=["read", "create", "update", "delete", "query"]) + """A media url for the file. Required if the type is one of the supported media types, e.g. image. + Required.""" + + @overload + def __init__( + self, + *, + media_uri: str, + caption: Optional[str] = None, + ) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: + """ + :param mapping: raw JSON to initialize the model. + :type mapping: Mapping[str, Any] + """ + + def __init__(self, *args: Any, **kwargs: Any) -> None: + super().__init__(*args, kind=CommunicationMessageKind.VIDEO, **kwargs) + + class VideoMessageContent(MessageContent, discriminator="video"): """The message content of type video information. - All required parameters must be populated in order to send to server. - :ivar kind: Message content kind is video. Required. The video content type. :vartype kind: str or ~azure.communication.messages.models.VIDEO :ivar media_uri: MediaUri of the media content. Required. :vartype media_uri: str """ - kind: Literal[MessageContentKind.VIDEO] = rest_discriminator(name="kind") # type: ignore + kind: Literal[MessageContentKind.VIDEO] = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) # type: ignore """Message content kind is video. Required. The video content type.""" - media_uri: str = rest_field(name="mediaUri") + media_uri: str = rest_field(name="mediaUri", visibility=["read", "create", "update", "delete", "query"]) """MediaUri of the media content. Required.""" @overload @@ -1478,14 +2311,12 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: class VideoNotificationContent(NotificationContent, discriminator="video"): """A request to send a video notification. - All required parameters must be populated in order to send to server. - :ivar channel_registration_id: The Channel Registration ID for the Business Identifier. Required. :vartype channel_registration_id: str :ivar to: The native external platform user identifiers of the recipient. Required. :vartype to: list[str] - :ivar kind: Message notification type is image. Required. Video message type. + :ivar kind: Message notification type is video. Required. Video message type. :vartype kind: str or ~azure.communication.messages.models.VIDEO :ivar caption: Optional text content. :vartype caption: str @@ -1494,11 +2325,11 @@ class VideoNotificationContent(NotificationContent, discriminator="video"): :vartype media_uri: str """ - kind: Literal[CommunicationMessageKind.VIDEO] = rest_discriminator(name="kind") # type: ignore - """Message notification type is image. Required. Video message type.""" - caption: Optional[str] = rest_field() + kind: Literal[CommunicationMessageKind.VIDEO] = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) # type: ignore + """Message notification type is video. Required. Video message type.""" + caption: Optional[str] = rest_field(visibility=["read", "create", "update", "delete", "query"]) """Optional text content.""" - media_uri: str = rest_field(name="mediaUri") + media_uri: str = rest_field(name="mediaUri", visibility=["read", "create", "update", "delete", "query"]) """A media url for the file. Required if the type is one of the supported media types, e.g. image. Required.""" @@ -1526,8 +2357,6 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: class WhatsAppButtonActionBindings(ActionBindings, discriminator="whatsAppButtonAction"): """WhatsApp Binding actions to the interactive message. - All required parameters must be populated in order to send to server. - :ivar kind: Message action binding type is WhatsAppButtonAction. Required. The WhatsApp Button action binding kind. :vartype kind: str or ~azure.communication.messages.models.WHATS_APP_BUTTON_ACTION @@ -1535,10 +2364,10 @@ class WhatsAppButtonActionBindings(ActionBindings, discriminator="whatsAppButton :vartype content: ~azure.communication.messages.models.ButtonSetContent """ - kind: Literal[MessageActionBindingKind.WHATS_APP_BUTTON_ACTION] = rest_discriminator(name="kind") # type: ignore + kind: Literal[MessageActionBindingKind.WHATS_APP_BUTTON_ACTION] = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) # type: ignore """Message action binding type is WhatsAppButtonAction. Required. The WhatsApp Button action binding kind.""" - content: "_models.ButtonSetContent" = rest_field() + content: "_models.ButtonSetContent" = rest_field(visibility=["read", "create", "update", "delete", "query"]) """Action content of Interactive message. Required.""" @overload @@ -1559,11 +2388,39 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, kind=MessageActionBindingKind.WHATS_APP_BUTTON_ACTION, **kwargs) +class WhatsAppContact(Contact, discriminator="whatsApp"): + """WhatsApp Contact. + + :ivar id: External platform identifier. Required. + :vartype id: str + :ivar kind: Contact type is whatsApp. Required. WhatsApp platform. + :vartype kind: str or ~azure.communication.messages.models.WHATS_APP + """ + + kind: Literal[MessagePlatformKind.WHATS_APP] = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) # type: ignore + """Contact type is whatsApp. Required. WhatsApp platform.""" + + @overload + def __init__( + self, + *, + id: str, # pylint: disable=redefined-builtin + ) -> None: ... + + @overload + def __init__(self, mapping: Mapping[str, Any]) -> None: + """ + :param mapping: raw JSON to initialize the model. + :type mapping: Mapping[str, Any] + """ + + def __init__(self, *args: Any, **kwargs: Any) -> None: + super().__init__(*args, kind=MessagePlatformKind.WHATS_APP, **kwargs) + + class WhatsAppListActionBindings(ActionBindings, discriminator="whatsAppListAction"): """WhatsApp List Binding actions to the interactive message. - All required parameters must be populated in order to send to server. - :ivar kind: Message action binding type is WhatsAppListAction. Required. The WhatsApp List action binding kind. :vartype kind: str or ~azure.communication.messages.models.WHATS_APP_LIST_ACTION @@ -1571,10 +2428,10 @@ class WhatsAppListActionBindings(ActionBindings, discriminator="whatsAppListActi :vartype content: ~azure.communication.messages.models.ActionGroupContent """ - kind: Literal[MessageActionBindingKind.WHATS_APP_LIST_ACTION] = rest_discriminator(name="kind") # type: ignore + kind: Literal[MessageActionBindingKind.WHATS_APP_LIST_ACTION] = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) # type: ignore """Message action binding type is WhatsAppListAction. Required. The WhatsApp List action binding kind.""" - content: "_models.ActionGroupContent" = rest_field() + content: "_models.ActionGroupContent" = rest_field(visibility=["read", "create", "update", "delete", "query"]) """Action content of Interactive message. Required.""" @overload @@ -1598,10 +2455,8 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: class WhatsAppMessageTemplateBindings(MessageTemplateBindings, discriminator="whatsApp"): """The template bindings for WhatsApp. - All required parameters must be populated in order to send to server. - :ivar kind: MessageTemplateBindings is whatsApp. Required. The WhatsApp template type. - :vartype kind: str or ~azure.communication.messages.models.WHATSAPP + :vartype kind: str or ~azure.communication.messages.models.WHATS_APP :ivar header: The header template bindings. :vartype header: list[~azure.communication.messages.models.WhatsAppMessageTemplateBindingsComponent] @@ -1616,15 +2471,23 @@ class WhatsAppMessageTemplateBindings(MessageTemplateBindings, discriminator="wh list[~azure.communication.messages.models.WhatsAppMessageTemplateBindingsButton] """ - kind: Literal[MessageTemplateBindingsKind.WHATSAPP] = rest_discriminator(name="kind") # type: ignore + kind: Literal[MessageTemplateBindingsKind.WHATS_APP] = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) # type: ignore """MessageTemplateBindings is whatsApp. Required. The WhatsApp template type.""" - header: Optional[List["_models.WhatsAppMessageTemplateBindingsComponent"]] = rest_field() + header: Optional[List["_models.WhatsAppMessageTemplateBindingsComponent"]] = rest_field( + visibility=["read", "create", "update", "delete", "query"] + ) """The header template bindings.""" - body: Optional[List["_models.WhatsAppMessageTemplateBindingsComponent"]] = rest_field() + body: Optional[List["_models.WhatsAppMessageTemplateBindingsComponent"]] = rest_field( + visibility=["read", "create", "update", "delete", "query"] + ) """The body template bindings.""" - footer: Optional[List["_models.WhatsAppMessageTemplateBindingsComponent"]] = rest_field() + footer: Optional[List["_models.WhatsAppMessageTemplateBindingsComponent"]] = rest_field( + visibility=["read", "create", "update", "delete", "query"] + ) """The footer template bindings.""" - buttons: Optional[List["_models.WhatsAppMessageTemplateBindingsButton"]] = rest_field() + buttons: Optional[List["_models.WhatsAppMessageTemplateBindingsButton"]] = rest_field( + visibility=["read", "create", "update", "delete", "query"] + ) """The button template bindings.""" @overload @@ -1645,14 +2508,12 @@ def __init__(self, mapping: Mapping[str, Any]) -> None: """ def __init__(self, *args: Any, **kwargs: Any) -> None: - super().__init__(*args, kind=MessageTemplateBindingsKind.WHATSAPP, **kwargs) + super().__init__(*args, kind=MessageTemplateBindingsKind.WHATS_APP, **kwargs) -class WhatsAppMessageTemplateBindingsButton(_model_base.Model): +class WhatsAppMessageTemplateBindingsButton(_Model): """The template bindings component button for WhatsApp. - All required parameters must be populated in order to send to server. - :ivar sub_type: The WhatsApp button sub type. Required. Known values are: "quickReply" and "url". :vartype sub_type: str or ~azure.communication.messages.models.WhatsAppMessageButtonSubType @@ -1660,9 +2521,11 @@ class WhatsAppMessageTemplateBindingsButton(_model_base.Model): :vartype ref_value: str """ - sub_type: Union[str, "_models.WhatsAppMessageButtonSubType"] = rest_field(name="subType") + sub_type: Union[str, "_models.WhatsAppMessageButtonSubType"] = rest_field( + name="subType", visibility=["read", "create", "update", "delete", "query"] + ) """The WhatsApp button sub type. Required. Known values are: \"quickReply\" and \"url\".""" - ref_value: str = rest_field(name="refValue") + ref_value: str = rest_field(name="refValue", visibility=["read", "create", "update", "delete", "query"]) """The name of the referenced item in the template values. Required.""" @overload @@ -1684,16 +2547,14 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: super().__init__(*args, **kwargs) -class WhatsAppMessageTemplateBindingsComponent(_model_base.Model): +class WhatsAppMessageTemplateBindingsComponent(_Model): """The template bindings component for WhatsApp. - All required parameters must be populated in order to send to server. - :ivar ref_value: The name of the referenced item in the template values. Required. :vartype ref_value: str """ - ref_value: str = rest_field(name="refValue") + ref_value: str = rest_field(name="refValue", visibility=["read", "create", "update", "delete", "query"]) """The name of the referenced item in the template values. Required.""" @overload @@ -1717,9 +2578,6 @@ def __init__(self, *args: Any, **kwargs: Any) -> None: class WhatsAppMessageTemplateItem(MessageTemplateItem, discriminator="whatsApp"): """The WhatsApp-specific template response contract. - Readonly variables are only populated by the server, and will be ignored when sending a request. - - :ivar name: The template's name. Required. :vartype name: str :ivar language: The template's language, in the ISO 639 format, consist of a two-letter @@ -1733,12 +2591,12 @@ class WhatsAppMessageTemplateItem(MessageTemplateItem, discriminator="whatsApp") :vartype content: any :ivar kind: Message template response type is whatsApp. Required. The WhatsApp communication messages channel type. - :vartype kind: str or ~azure.communication.messages.models.WHATSAPP + :vartype kind: str or ~azure.communication.messages.models.WHATS_APP """ - content: Optional[Any] = rest_field() + content: Optional[Any] = rest_field(visibility=["read", "create", "update", "delete", "query"]) """WhatsApp platform's template content. This is the payload returned from WhatsApp API.""" - kind: Literal[CommunicationMessagesChannel.WHATSAPP] = rest_discriminator(name="kind") # type: ignore + kind: Literal[CommunicationMessagesChannel.WHATS_APP] = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) # type: ignore """Message template response type is whatsApp. Required. The WhatsApp communication messages channel type.""" @@ -1759,14 +2617,12 @@ def __init__(self, mapping: Mapping[str, Any]) -> None: """ def __init__(self, *args: Any, **kwargs: Any) -> None: - super().__init__(*args, kind=CommunicationMessagesChannel.WHATSAPP, **kwargs) + super().__init__(*args, kind=CommunicationMessagesChannel.WHATS_APP, **kwargs) class WhatsAppUrlActionBindings(ActionBindings, discriminator="whatsAppUrlAction"): """WhatsApp Binding actions to the interactive message. - All required parameters must be populated in order to send to server. - :ivar kind: Message action binding type is WhatsAppUrlAction. Required. The WhatsApp Url action binding kind. :vartype kind: str or ~azure.communication.messages.models.WHATS_APP_URL_ACTION @@ -1774,10 +2630,10 @@ class WhatsAppUrlActionBindings(ActionBindings, discriminator="whatsAppUrlAction :vartype content: ~azure.communication.messages.models.LinkContent """ - kind: Literal[MessageActionBindingKind.WHATS_APP_URL_ACTION] = rest_discriminator(name="kind") # type: ignore + kind: Literal[MessageActionBindingKind.WHATS_APP_URL_ACTION] = rest_discriminator(name="kind", visibility=["read", "create", "update", "delete", "query"]) # type: ignore """Message action binding type is WhatsAppUrlAction. Required. The WhatsApp Url action binding kind.""" - content: "_models.LinkContent" = rest_field() + content: "_models.LinkContent" = rest_field(visibility=["read", "create", "update", "delete", "query"]) """Action content of Interactive message. Required.""" @overload diff --git a/sdk/communication/azure-communication-messages/azure/communication/messages/models/_patch.py b/sdk/communication/azure-communication-messages/azure/communication/messages/models/_patch.py index f7dd32510333..8bcb627aa475 100644 --- a/sdk/communication/azure-communication-messages/azure/communication/messages/models/_patch.py +++ b/sdk/communication/azure-communication-messages/azure/communication/messages/models/_patch.py @@ -1,7 +1,8 @@ -# ------------------------------------ -# Copyright (c) Microsoft Corporation. -# Licensed under the MIT License. -# ------------------------------------ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# -------------------------------------------------------------------------- """Customize generated code here. Follow our quickstart for examples: https://aka.ms/azsdk/python/dpcodegen/python/customize diff --git a/sdk/communication/azure-communication-messages/generated_samples/conversation_thread_add_participants.py b/sdk/communication/azure-communication-messages/generated_samples/conversation_thread_add_participants.py new file mode 100644 index 000000000000..7b862faccecb --- /dev/null +++ b/sdk/communication/azure-communication-messages/generated_samples/conversation_thread_add_participants.py @@ -0,0 +1,47 @@ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# Code generated by Microsoft (R) Python Code Generator. +# Changes may cause incorrect behavior and will be lost if the code is regenerated. +# -------------------------------------------------------------------------- + +from azure.communication.messages import ConversationAdministrationClient + +""" +# PREREQUISITES + pip install azure-communication-messages +# USAGE + python conversation_thread_add_participants.py +""" + + +def main(): + client = NotificationMessagesClient( + endpoint="https://my-resource.communication.azure.com", + credential="CREDENTIAL", + ) + + response = client.add_participants( + conversation_id="19:34adfa4f-cedf-4dc0-ba29-b6d1a69ab345@thread.v2", + options={ + "participants": [ + { + "contacts": [{"id": "12345678901", "kind": "whatsApp"}], + "displayName": "Customer", + "kind": "external", + }, + { + "contact": {"id": "8:acs:uuid1", "kind": "communication"}, + "displayName": "Support", + "kind": "internal", + }, + ] + }, + ) + print(response) + + +# x-ms-original-file: 2025-04-01-preview/ConversationThread_AddParticipants.json +if __name__ == "__main__": + main() diff --git a/sdk/communication/azure-communication-messages/generated_samples/conversation_thread_analyze_conversation.py b/sdk/communication/azure-communication-messages/generated_samples/conversation_thread_analyze_conversation.py new file mode 100644 index 000000000000..3bd0b707e406 --- /dev/null +++ b/sdk/communication/azure-communication-messages/generated_samples/conversation_thread_analyze_conversation.py @@ -0,0 +1,33 @@ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# Code generated by Microsoft (R) Python Code Generator. +# Changes may cause incorrect behavior and will be lost if the code is regenerated. +# -------------------------------------------------------------------------- + +from azure.communication.messages import ConversationAdministrationClient + +""" +# PREREQUISITES + pip install azure-communication-messages +# USAGE + python conversation_thread_analyze_conversation.py +""" + + +def main(): + client = NotificationMessagesClient( + endpoint="https://my-resource.communication.azure.com", + credential="CREDENTIAL", + ) + + response = client.analyze_conversation( + conversation_id="19:34adfa4f-cedf-4dc0-ba29-b6d1a69ab345@thread.v2", + ) + print(response) + + +# x-ms-original-file: 2025-04-01-preview/ConversationThread_AnalyzeConversation.json +if __name__ == "__main__": + main() diff --git a/sdk/communication/azure-communication-messages/generated_samples/conversation_thread_list_conversations.py b/sdk/communication/azure-communication-messages/generated_samples/conversation_thread_list_conversations.py new file mode 100644 index 000000000000..233de29a9573 --- /dev/null +++ b/sdk/communication/azure-communication-messages/generated_samples/conversation_thread_list_conversations.py @@ -0,0 +1,32 @@ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# Code generated by Microsoft (R) Python Code Generator. +# Changes may cause incorrect behavior and will be lost if the code is regenerated. +# -------------------------------------------------------------------------- + +from azure.communication.messages import ConversationAdministrationClient + +""" +# PREREQUISITES + pip install azure-communication-messages +# USAGE + python conversation_thread_list_conversations.py +""" + + +def main(): + client = NotificationMessagesClient( + endpoint="https://my-resource.communication.azure.com", + credential="CREDENTIAL", + ) + + response = client.list_conversations() + for item in response: + print(item) + + +# x-ms-original-file: 2025-04-01-preview/ConversationThread_ListConversations.json +if __name__ == "__main__": + main() diff --git a/sdk/communication/azure-communication-messages/generated_samples/conversation_thread_list_messages.py b/sdk/communication/azure-communication-messages/generated_samples/conversation_thread_list_messages.py new file mode 100644 index 000000000000..535293249b28 --- /dev/null +++ b/sdk/communication/azure-communication-messages/generated_samples/conversation_thread_list_messages.py @@ -0,0 +1,34 @@ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# Code generated by Microsoft (R) Python Code Generator. +# Changes may cause incorrect behavior and will be lost if the code is regenerated. +# -------------------------------------------------------------------------- + +from azure.communication.messages import ConversationAdministrationClient + +""" +# PREREQUISITES + pip install azure-communication-messages +# USAGE + python conversation_thread_list_messages.py +""" + + +def main(): + client = NotificationMessagesClient( + endpoint="https://my-resource.communication.azure.com", + credential="CREDENTIAL", + ) + + response = client.list_messages( + conversation_id="19:34adfa4f-cedf-4dc0-ba29-b6d1a69ab345@thread.v2", + ) + for item in response: + print(item) + + +# x-ms-original-file: 2025-04-01-preview/ConversationThread_ListMessages.json +if __name__ == "__main__": + main() diff --git a/sdk/communication/azure-communication-messages/generated_samples/conversation_thread_remove_participants.py b/sdk/communication/azure-communication-messages/generated_samples/conversation_thread_remove_participants.py new file mode 100644 index 000000000000..d1d918d15fcc --- /dev/null +++ b/sdk/communication/azure-communication-messages/generated_samples/conversation_thread_remove_participants.py @@ -0,0 +1,34 @@ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# Code generated by Microsoft (R) Python Code Generator. +# Changes may cause incorrect behavior and will be lost if the code is regenerated. +# -------------------------------------------------------------------------- + +from azure.communication.messages import ConversationAdministrationClient + +""" +# PREREQUISITES + pip install azure-communication-messages +# USAGE + python conversation_thread_remove_participants.py +""" + + +def main(): + client = NotificationMessagesClient( + endpoint="https://my-resource.communication.azure.com", + credential="CREDENTIAL", + ) + + response = client.remove_participants( + conversation_id="19:34adfa4f-cedf-4dc0-ba29-b6d1a69ab345@thread.v2", + options={"participantIds": ["8:acs:uuid2"]}, + ) + print(response) + + +# x-ms-original-file: 2025-04-01-preview/ConversationThread_RemoveParticipants.json +if __name__ == "__main__": + main() diff --git a/sdk/communication/azure-communication-messages/generated_samples/stream_get_media.py b/sdk/communication/azure-communication-messages/generated_samples/stream_get_media.py new file mode 100644 index 000000000000..e467e2fb46a1 --- /dev/null +++ b/sdk/communication/azure-communication-messages/generated_samples/stream_get_media.py @@ -0,0 +1,33 @@ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# Code generated by Microsoft (R) Python Code Generator. +# Changes may cause incorrect behavior and will be lost if the code is regenerated. +# -------------------------------------------------------------------------- + +from azure.communication.messages import NotificationMessagesClient + +""" +# PREREQUISITES + pip install azure-communication-messages +# USAGE + python stream_get_media.py +""" + + +def main(): + client = NotificationMessagesClient( + endpoint="https://my-resource.communication.azure.com", + credential="CREDENTIAL", + ) + + response = client.download_media( + id="d19e68ec-bdd6-4a50-8dfb-cbb1642df6ab", + ) + print(response) + + +# x-ms-original-file: 2025-04-01-preview/Stream_GetMedia.json +if __name__ == "__main__": + main() diff --git a/sdk/communication/azure-communication-messages/generated_tests/conftest.py b/sdk/communication/azure-communication-messages/generated_tests/conftest.py new file mode 100644 index 000000000000..eebe08f05035 --- /dev/null +++ b/sdk/communication/azure-communication-messages/generated_tests/conftest.py @@ -0,0 +1,100 @@ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# Code generated by Microsoft (R) Python Code Generator. +# Changes may cause incorrect behavior and will be lost if the code is regenerated. +# -------------------------------------------------------------------------- +import os +import pytest +from dotenv import load_dotenv +from devtools_testutils import ( + test_proxy, + add_general_regex_sanitizer, + add_body_key_sanitizer, + add_header_regex_sanitizer, +) + +load_dotenv() + + +# For security, please avoid record sensitive identity information in recordings +@pytest.fixture(scope="session", autouse=True) +def add_sanitizers(test_proxy): + notificationmessages_subscription_id = os.environ.get( + "NOTIFICATIONMESSAGES_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000" + ) + notificationmessages_tenant_id = os.environ.get( + "NOTIFICATIONMESSAGES_TENANT_ID", "00000000-0000-0000-0000-000000000000" + ) + notificationmessages_client_id = os.environ.get( + "NOTIFICATIONMESSAGES_CLIENT_ID", "00000000-0000-0000-0000-000000000000" + ) + notificationmessages_client_secret = os.environ.get( + "NOTIFICATIONMESSAGES_CLIENT_SECRET", "00000000-0000-0000-0000-000000000000" + ) + add_general_regex_sanitizer( + regex=notificationmessages_subscription_id, value="00000000-0000-0000-0000-000000000000" + ) + add_general_regex_sanitizer(regex=notificationmessages_tenant_id, value="00000000-0000-0000-0000-000000000000") + add_general_regex_sanitizer(regex=notificationmessages_client_id, value="00000000-0000-0000-0000-000000000000") + add_general_regex_sanitizer(regex=notificationmessages_client_secret, value="00000000-0000-0000-0000-000000000000") + + messagetemplate_subscription_id = os.environ.get( + "MESSAGETEMPLATE_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000" + ) + messagetemplate_tenant_id = os.environ.get("MESSAGETEMPLATE_TENANT_ID", "00000000-0000-0000-0000-000000000000") + messagetemplate_client_id = os.environ.get("MESSAGETEMPLATE_CLIENT_ID", "00000000-0000-0000-0000-000000000000") + messagetemplate_client_secret = os.environ.get( + "MESSAGETEMPLATE_CLIENT_SECRET", "00000000-0000-0000-0000-000000000000" + ) + add_general_regex_sanitizer(regex=messagetemplate_subscription_id, value="00000000-0000-0000-0000-000000000000") + add_general_regex_sanitizer(regex=messagetemplate_tenant_id, value="00000000-0000-0000-0000-000000000000") + add_general_regex_sanitizer(regex=messagetemplate_client_id, value="00000000-0000-0000-0000-000000000000") + add_general_regex_sanitizer(regex=messagetemplate_client_secret, value="00000000-0000-0000-0000-000000000000") + + conversationadministration_subscription_id = os.environ.get( + "CONVERSATIONADMINISTRATION_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000" + ) + conversationadministration_tenant_id = os.environ.get( + "CONVERSATIONADMINISTRATION_TENANT_ID", "00000000-0000-0000-0000-000000000000" + ) + conversationadministration_client_id = os.environ.get( + "CONVERSATIONADMINISTRATION_CLIENT_ID", "00000000-0000-0000-0000-000000000000" + ) + conversationadministration_client_secret = os.environ.get( + "CONVERSATIONADMINISTRATION_CLIENT_SECRET", "00000000-0000-0000-0000-000000000000" + ) + add_general_regex_sanitizer( + regex=conversationadministration_subscription_id, value="00000000-0000-0000-0000-000000000000" + ) + add_general_regex_sanitizer( + regex=conversationadministration_tenant_id, value="00000000-0000-0000-0000-000000000000" + ) + add_general_regex_sanitizer( + regex=conversationadministration_client_id, value="00000000-0000-0000-0000-000000000000" + ) + add_general_regex_sanitizer( + regex=conversationadministration_client_secret, value="00000000-0000-0000-0000-000000000000" + ) + + conversationthread_subscription_id = os.environ.get( + "CONVERSATIONTHREAD_SUBSCRIPTION_ID", "00000000-0000-0000-0000-000000000000" + ) + conversationthread_tenant_id = os.environ.get( + "CONVERSATIONTHREAD_TENANT_ID", "00000000-0000-0000-0000-000000000000" + ) + conversationthread_client_id = os.environ.get( + "CONVERSATIONTHREAD_CLIENT_ID", "00000000-0000-0000-0000-000000000000" + ) + conversationthread_client_secret = os.environ.get( + "CONVERSATIONTHREAD_CLIENT_SECRET", "00000000-0000-0000-0000-000000000000" + ) + add_general_regex_sanitizer(regex=conversationthread_subscription_id, value="00000000-0000-0000-0000-000000000000") + add_general_regex_sanitizer(regex=conversationthread_tenant_id, value="00000000-0000-0000-0000-000000000000") + add_general_regex_sanitizer(regex=conversationthread_client_id, value="00000000-0000-0000-0000-000000000000") + add_general_regex_sanitizer(regex=conversationthread_client_secret, value="00000000-0000-0000-0000-000000000000") + + add_header_regex_sanitizer(key="Set-Cookie", value="[set-cookie;]") + add_header_regex_sanitizer(key="Cookie", value="cookie;") + add_body_key_sanitizer(json_path="$..access_token", value="access_token") diff --git a/sdk/communication/azure-communication-messages/generated_tests/test_conversation_administration.py b/sdk/communication/azure-communication-messages/generated_tests/test_conversation_administration.py new file mode 100644 index 000000000000..ef8fd2ffc0c5 --- /dev/null +++ b/sdk/communication/azure-communication-messages/generated_tests/test_conversation_administration.py @@ -0,0 +1,128 @@ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# Code generated by Microsoft (R) Python Code Generator. +# Changes may cause incorrect behavior and will be lost if the code is regenerated. +# -------------------------------------------------------------------------- +import pytest +from devtools_testutils import recorded_by_proxy +from testpreparer import ConversationAdministrationClientTestBase, ConversationAdministrationPreparer + + +@pytest.mark.skip("you may need to update the auto-generated test case before run it") +class TestConversationAdministration(ConversationAdministrationClientTestBase): + @ConversationAdministrationPreparer() + @recorded_by_proxy + def test_create_conversation(self, conversationadministration_endpoint): + client = self.create_client(endpoint=conversationadministration_endpoint) + response = client.create_conversation( + body={ + "conversation": { + "id": "str", + "deliveryChannelIds": ["str"], + "outboundDeliveryStrategy": "str", + "participants": ["conversation_participant"], + "topic": "str", + }, + "initialMessage": {"content": "str"}, + }, + conversation={ + "id": "str", + "deliveryChannelIds": ["str"], + "outboundDeliveryStrategy": "str", + "participants": ["conversation_participant"], + "topic": "str", + }, + ) + + # please add some check logic here by yourself + # ... + + @ConversationAdministrationPreparer() + @recorded_by_proxy + def test_get_conversation(self, conversationadministration_endpoint): + client = self.create_client(endpoint=conversationadministration_endpoint) + response = client.get_conversation( + conversation_id="str", + ) + + # please add some check logic here by yourself + # ... + + @ConversationAdministrationPreparer() + @recorded_by_proxy + def test_delete_conversation(self, conversationadministration_endpoint): + client = self.create_client(endpoint=conversationadministration_endpoint) + response = client.delete_conversation( + conversation_id="str", + ) + + # please add some check logic here by yourself + # ... + + @ConversationAdministrationPreparer() + @recorded_by_proxy + def test_terminate_conversation(self, conversationadministration_endpoint): + client = self.create_client(endpoint=conversationadministration_endpoint) + response = client.terminate_conversation( + conversation_id="str", + ) + + # please add some check logic here by yourself + # ... + + @ConversationAdministrationPreparer() + @recorded_by_proxy + def test_list_conversations(self, conversationadministration_endpoint): + client = self.create_client(endpoint=conversationadministration_endpoint) + response = client.list_conversations() + result = [r for r in response] + # please add some check logic here by yourself + # ... + + @ConversationAdministrationPreparer() + @recorded_by_proxy + def test_list_messages(self, conversationadministration_endpoint): + client = self.create_client(endpoint=conversationadministration_endpoint) + response = client.list_messages( + conversation_id="str", + ) + result = [r for r in response] + # please add some check logic here by yourself + # ... + + @ConversationAdministrationPreparer() + @recorded_by_proxy + def test_add_participants(self, conversationadministration_endpoint): + client = self.create_client(endpoint=conversationadministration_endpoint) + response = client.add_participants( + conversation_id="str", + options={"participants": ["conversation_participant"]}, + ) + + # please add some check logic here by yourself + # ... + + @ConversationAdministrationPreparer() + @recorded_by_proxy + def test_remove_participants(self, conversationadministration_endpoint): + client = self.create_client(endpoint=conversationadministration_endpoint) + response = client.remove_participants( + conversation_id="str", + options={"participantIds": ["str"]}, + ) + + # please add some check logic here by yourself + # ... + + @ConversationAdministrationPreparer() + @recorded_by_proxy + def test_analyze_conversation(self, conversationadministration_endpoint): + client = self.create_client(endpoint=conversationadministration_endpoint) + response = client.analyze_conversation( + conversation_id="str", + ) + + # please add some check logic here by yourself + # ... diff --git a/sdk/communication/azure-communication-messages/generated_tests/test_conversation_administration_async.py b/sdk/communication/azure-communication-messages/generated_tests/test_conversation_administration_async.py new file mode 100644 index 000000000000..4e43f2d9e5fb --- /dev/null +++ b/sdk/communication/azure-communication-messages/generated_tests/test_conversation_administration_async.py @@ -0,0 +1,129 @@ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# Code generated by Microsoft (R) Python Code Generator. +# Changes may cause incorrect behavior and will be lost if the code is regenerated. +# -------------------------------------------------------------------------- +import pytest +from devtools_testutils.aio import recorded_by_proxy_async +from testpreparer import ConversationAdministrationPreparer +from testpreparer_async import ConversationAdministrationClientTestBaseAsync + + +@pytest.mark.skip("you may need to update the auto-generated test case before run it") +class TestConversationAdministrationAsync(ConversationAdministrationClientTestBaseAsync): + @ConversationAdministrationPreparer() + @recorded_by_proxy_async + async def test_create_conversation(self, conversationadministration_endpoint): + client = self.create_async_client(endpoint=conversationadministration_endpoint) + response = await client.create_conversation( + body={ + "conversation": { + "id": "str", + "deliveryChannelIds": ["str"], + "outboundDeliveryStrategy": "str", + "participants": ["conversation_participant"], + "topic": "str", + }, + "initialMessage": {"content": "str"}, + }, + conversation={ + "id": "str", + "deliveryChannelIds": ["str"], + "outboundDeliveryStrategy": "str", + "participants": ["conversation_participant"], + "topic": "str", + }, + ) + + # please add some check logic here by yourself + # ... + + @ConversationAdministrationPreparer() + @recorded_by_proxy_async + async def test_get_conversation(self, conversationadministration_endpoint): + client = self.create_async_client(endpoint=conversationadministration_endpoint) + response = await client.get_conversation( + conversation_id="str", + ) + + # please add some check logic here by yourself + # ... + + @ConversationAdministrationPreparer() + @recorded_by_proxy_async + async def test_delete_conversation(self, conversationadministration_endpoint): + client = self.create_async_client(endpoint=conversationadministration_endpoint) + response = await client.delete_conversation( + conversation_id="str", + ) + + # please add some check logic here by yourself + # ... + + @ConversationAdministrationPreparer() + @recorded_by_proxy_async + async def test_terminate_conversation(self, conversationadministration_endpoint): + client = self.create_async_client(endpoint=conversationadministration_endpoint) + response = await client.terminate_conversation( + conversation_id="str", + ) + + # please add some check logic here by yourself + # ... + + @ConversationAdministrationPreparer() + @recorded_by_proxy_async + async def test_list_conversations(self, conversationadministration_endpoint): + client = self.create_async_client(endpoint=conversationadministration_endpoint) + response = client.list_conversations() + result = [r async for r in response] + # please add some check logic here by yourself + # ... + + @ConversationAdministrationPreparer() + @recorded_by_proxy_async + async def test_list_messages(self, conversationadministration_endpoint): + client = self.create_async_client(endpoint=conversationadministration_endpoint) + response = client.list_messages( + conversation_id="str", + ) + result = [r async for r in response] + # please add some check logic here by yourself + # ... + + @ConversationAdministrationPreparer() + @recorded_by_proxy_async + async def test_add_participants(self, conversationadministration_endpoint): + client = self.create_async_client(endpoint=conversationadministration_endpoint) + response = await client.add_participants( + conversation_id="str", + options={"participants": ["conversation_participant"]}, + ) + + # please add some check logic here by yourself + # ... + + @ConversationAdministrationPreparer() + @recorded_by_proxy_async + async def test_remove_participants(self, conversationadministration_endpoint): + client = self.create_async_client(endpoint=conversationadministration_endpoint) + response = await client.remove_participants( + conversation_id="str", + options={"participantIds": ["str"]}, + ) + + # please add some check logic here by yourself + # ... + + @ConversationAdministrationPreparer() + @recorded_by_proxy_async + async def test_analyze_conversation(self, conversationadministration_endpoint): + client = self.create_async_client(endpoint=conversationadministration_endpoint) + response = await client.analyze_conversation( + conversation_id="str", + ) + + # please add some check logic here by yourself + # ... diff --git a/sdk/communication/azure-communication-messages/generated_tests/test_conversation_thread.py b/sdk/communication/azure-communication-messages/generated_tests/test_conversation_thread.py new file mode 100644 index 000000000000..126a4dffa898 --- /dev/null +++ b/sdk/communication/azure-communication-messages/generated_tests/test_conversation_thread.py @@ -0,0 +1,80 @@ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# Code generated by Microsoft (R) Python Code Generator. +# Changes may cause incorrect behavior and will be lost if the code is regenerated. +# -------------------------------------------------------------------------- +import pytest +from devtools_testutils import recorded_by_proxy +from testpreparer import ConversationThreadClientTestBase, ConversationThreadPreparer + + +@pytest.mark.skip("you may need to update the auto-generated test case before run it") +class TestConversationThread(ConversationThreadClientTestBase): + @ConversationThreadPreparer() + @recorded_by_proxy + def test_add_participants(self, conversationthread_endpoint): + client = self.create_client(endpoint=conversationthread_endpoint) + response = client.add_participants( + conversation_id="str", + options={"participants": ["conversation_participant"]}, + ) + + # please add some check logic here by yourself + # ... + + @ConversationThreadPreparer() + @recorded_by_proxy + def test_remove_participants(self, conversationthread_endpoint): + client = self.create_client(endpoint=conversationthread_endpoint) + response = client.remove_participants( + conversation_id="str", + options={"participantIds": ["str"]}, + ) + + # please add some check logic here by yourself + # ... + + @ConversationThreadPreparer() + @recorded_by_proxy + def test_list_conversations(self, conversationthread_endpoint): + client = self.create_client(endpoint=conversationthread_endpoint) + response = client.list_conversations() + result = [r for r in response] + # please add some check logic here by yourself + # ... + + @ConversationThreadPreparer() + @recorded_by_proxy + def test_list_messages(self, conversationthread_endpoint): + client = self.create_client(endpoint=conversationthread_endpoint) + response = client.list_messages( + conversation_id="str", + ) + result = [r for r in response] + # please add some check logic here by yourself + # ... + + @ConversationThreadPreparer() + @recorded_by_proxy + def test_send_message(self, conversationthread_endpoint): + client = self.create_client(endpoint=conversationthread_endpoint) + response = client.send_message( + conversation_id="str", + options={"request": "conversation_message_content", "outboundDeliveryStrategy": "str"}, + ) + + # please add some check logic here by yourself + # ... + + @ConversationThreadPreparer() + @recorded_by_proxy + def test_analyze_conversation(self, conversationthread_endpoint): + client = self.create_client(endpoint=conversationthread_endpoint) + response = client.analyze_conversation( + conversation_id="str", + ) + + # please add some check logic here by yourself + # ... diff --git a/sdk/communication/azure-communication-messages/generated_tests/test_conversation_thread_async.py b/sdk/communication/azure-communication-messages/generated_tests/test_conversation_thread_async.py new file mode 100644 index 000000000000..24c90de5ec55 --- /dev/null +++ b/sdk/communication/azure-communication-messages/generated_tests/test_conversation_thread_async.py @@ -0,0 +1,81 @@ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# Code generated by Microsoft (R) Python Code Generator. +# Changes may cause incorrect behavior and will be lost if the code is regenerated. +# -------------------------------------------------------------------------- +import pytest +from devtools_testutils.aio import recorded_by_proxy_async +from testpreparer import ConversationThreadPreparer +from testpreparer_async import ConversationThreadClientTestBaseAsync + + +@pytest.mark.skip("you may need to update the auto-generated test case before run it") +class TestConversationThreadAsync(ConversationThreadClientTestBaseAsync): + @ConversationThreadPreparer() + @recorded_by_proxy_async + async def test_add_participants(self, conversationthread_endpoint): + client = self.create_async_client(endpoint=conversationthread_endpoint) + response = await client.add_participants( + conversation_id="str", + options={"participants": ["conversation_participant"]}, + ) + + # please add some check logic here by yourself + # ... + + @ConversationThreadPreparer() + @recorded_by_proxy_async + async def test_remove_participants(self, conversationthread_endpoint): + client = self.create_async_client(endpoint=conversationthread_endpoint) + response = await client.remove_participants( + conversation_id="str", + options={"participantIds": ["str"]}, + ) + + # please add some check logic here by yourself + # ... + + @ConversationThreadPreparer() + @recorded_by_proxy_async + async def test_list_conversations(self, conversationthread_endpoint): + client = self.create_async_client(endpoint=conversationthread_endpoint) + response = client.list_conversations() + result = [r async for r in response] + # please add some check logic here by yourself + # ... + + @ConversationThreadPreparer() + @recorded_by_proxy_async + async def test_list_messages(self, conversationthread_endpoint): + client = self.create_async_client(endpoint=conversationthread_endpoint) + response = client.list_messages( + conversation_id="str", + ) + result = [r async for r in response] + # please add some check logic here by yourself + # ... + + @ConversationThreadPreparer() + @recorded_by_proxy_async + async def test_send_message(self, conversationthread_endpoint): + client = self.create_async_client(endpoint=conversationthread_endpoint) + response = await client.send_message( + conversation_id="str", + options={"request": "conversation_message_content", "outboundDeliveryStrategy": "str"}, + ) + + # please add some check logic here by yourself + # ... + + @ConversationThreadPreparer() + @recorded_by_proxy_async + async def test_analyze_conversation(self, conversationthread_endpoint): + client = self.create_async_client(endpoint=conversationthread_endpoint) + response = await client.analyze_conversation( + conversation_id="str", + ) + + # please add some check logic here by yourself + # ... diff --git a/sdk/communication/azure-communication-messages/generated_tests/test_message_template.py b/sdk/communication/azure-communication-messages/generated_tests/test_message_template.py new file mode 100644 index 000000000000..dabf704a6444 --- /dev/null +++ b/sdk/communication/azure-communication-messages/generated_tests/test_message_template.py @@ -0,0 +1,24 @@ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# Code generated by Microsoft (R) Python Code Generator. +# Changes may cause incorrect behavior and will be lost if the code is regenerated. +# -------------------------------------------------------------------------- +import pytest +from devtools_testutils import recorded_by_proxy +from testpreparer import MessageTemplateClientTestBase, MessageTemplatePreparer + + +@pytest.mark.skip("you may need to update the auto-generated test case before run it") +class TestMessageTemplate(MessageTemplateClientTestBase): + @MessageTemplatePreparer() + @recorded_by_proxy + def test_list_templates(self, messagetemplate_endpoint): + client = self.create_client(endpoint=messagetemplate_endpoint) + response = client.list_templates( + channel_id="str", + ) + result = [r for r in response] + # please add some check logic here by yourself + # ... diff --git a/sdk/communication/azure-communication-messages/generated_tests/test_message_template_async.py b/sdk/communication/azure-communication-messages/generated_tests/test_message_template_async.py new file mode 100644 index 000000000000..17dc315792dd --- /dev/null +++ b/sdk/communication/azure-communication-messages/generated_tests/test_message_template_async.py @@ -0,0 +1,25 @@ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# Code generated by Microsoft (R) Python Code Generator. +# Changes may cause incorrect behavior and will be lost if the code is regenerated. +# -------------------------------------------------------------------------- +import pytest +from devtools_testutils.aio import recorded_by_proxy_async +from testpreparer import MessageTemplatePreparer +from testpreparer_async import MessageTemplateClientTestBaseAsync + + +@pytest.mark.skip("you may need to update the auto-generated test case before run it") +class TestMessageTemplateAsync(MessageTemplateClientTestBaseAsync): + @MessageTemplatePreparer() + @recorded_by_proxy_async + async def test_list_templates(self, messagetemplate_endpoint): + client = self.create_async_client(endpoint=messagetemplate_endpoint) + response = client.list_templates( + channel_id="str", + ) + result = [r async for r in response] + # please add some check logic here by yourself + # ... diff --git a/sdk/communication/azure-communication-messages/generated_tests/test_notification_messages.py b/sdk/communication/azure-communication-messages/generated_tests/test_notification_messages.py new file mode 100644 index 000000000000..23071ca986e6 --- /dev/null +++ b/sdk/communication/azure-communication-messages/generated_tests/test_notification_messages.py @@ -0,0 +1,35 @@ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# Code generated by Microsoft (R) Python Code Generator. +# Changes may cause incorrect behavior and will be lost if the code is regenerated. +# -------------------------------------------------------------------------- +import pytest +from devtools_testutils import recorded_by_proxy +from testpreparer import NotificationMessagesClientTestBase, NotificationMessagesPreparer + + +@pytest.mark.skip("you may need to update the auto-generated test case before run it") +class TestNotificationMessages(NotificationMessagesClientTestBase): + @NotificationMessagesPreparer() + @recorded_by_proxy + def test_send(self, notificationmessages_endpoint): + client = self.create_client(endpoint=notificationmessages_endpoint) + response = client.send( + body={"channelRegistrationId": "str", "kind": "audio", "mediaUri": "str", "to": ["str"]}, + ) + + # please add some check logic here by yourself + # ... + + @NotificationMessagesPreparer() + @recorded_by_proxy + def test_download_media(self, notificationmessages_endpoint): + client = self.create_client(endpoint=notificationmessages_endpoint) + response = client.download_media( + id="str", + ) + + # please add some check logic here by yourself + # ... diff --git a/sdk/communication/azure-communication-messages/generated_tests/test_notification_messages_async.py b/sdk/communication/azure-communication-messages/generated_tests/test_notification_messages_async.py new file mode 100644 index 000000000000..27188dc4eb4d --- /dev/null +++ b/sdk/communication/azure-communication-messages/generated_tests/test_notification_messages_async.py @@ -0,0 +1,36 @@ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# Code generated by Microsoft (R) Python Code Generator. +# Changes may cause incorrect behavior and will be lost if the code is regenerated. +# -------------------------------------------------------------------------- +import pytest +from devtools_testutils.aio import recorded_by_proxy_async +from testpreparer import NotificationMessagesPreparer +from testpreparer_async import NotificationMessagesClientTestBaseAsync + + +@pytest.mark.skip("you may need to update the auto-generated test case before run it") +class TestNotificationMessagesAsync(NotificationMessagesClientTestBaseAsync): + @NotificationMessagesPreparer() + @recorded_by_proxy_async + async def test_send(self, notificationmessages_endpoint): + client = self.create_async_client(endpoint=notificationmessages_endpoint) + response = await client.send( + body={"channelRegistrationId": "str", "kind": "audio", "mediaUri": "str", "to": ["str"]}, + ) + + # please add some check logic here by yourself + # ... + + @NotificationMessagesPreparer() + @recorded_by_proxy_async + async def test_download_media(self, notificationmessages_endpoint): + client = self.create_async_client(endpoint=notificationmessages_endpoint) + response = await client.download_media( + id="str", + ) + + # please add some check logic here by yourself + # ... diff --git a/sdk/communication/azure-communication-messages/generated_tests/testpreparer.py b/sdk/communication/azure-communication-messages/generated_tests/testpreparer.py new file mode 100644 index 000000000000..ef0efafa5ea9 --- /dev/null +++ b/sdk/communication/azure-communication-messages/generated_tests/testpreparer.py @@ -0,0 +1,83 @@ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# Code generated by Microsoft (R) Python Code Generator. +# Changes may cause incorrect behavior and will be lost if the code is regenerated. +# -------------------------------------------------------------------------- +from azure.communication.messages import ( + ConversationAdministrationClient, + ConversationThreadClient, + MessageTemplateClient, + NotificationMessagesClient, +) +from devtools_testutils import AzureRecordedTestCase, PowerShellPreparer +import functools + + +class NotificationMessagesClientTestBase(AzureRecordedTestCase): + + def create_client(self, endpoint): + credential = self.get_credential(NotificationMessagesClient) + return self.create_client_from_credential( + NotificationMessagesClient, + credential=credential, + endpoint=endpoint, + ) + + +NotificationMessagesPreparer = functools.partial( + PowerShellPreparer, + "notificationmessages", + notificationmessages_endpoint="https://fake_notificationmessages_endpoint.com", +) + + +class MessageTemplateClientTestBase(AzureRecordedTestCase): + + def create_client(self, endpoint): + credential = self.get_credential(MessageTemplateClient) + return self.create_client_from_credential( + MessageTemplateClient, + credential=credential, + endpoint=endpoint, + ) + + +MessageTemplatePreparer = functools.partial( + PowerShellPreparer, "messagetemplate", messagetemplate_endpoint="https://fake_messagetemplate_endpoint.com" +) + + +class ConversationAdministrationClientTestBase(AzureRecordedTestCase): + + def create_client(self, endpoint): + credential = self.get_credential(ConversationAdministrationClient) + return self.create_client_from_credential( + ConversationAdministrationClient, + credential=credential, + endpoint=endpoint, + ) + + +ConversationAdministrationPreparer = functools.partial( + PowerShellPreparer, + "conversationadministration", + conversationadministration_endpoint="https://fake_conversationadministration_endpoint.com", +) + + +class ConversationThreadClientTestBase(AzureRecordedTestCase): + + def create_client(self, endpoint): + credential = self.get_credential(ConversationThreadClient) + return self.create_client_from_credential( + ConversationThreadClient, + credential=credential, + endpoint=endpoint, + ) + + +ConversationThreadPreparer = functools.partial( + PowerShellPreparer, "conversationthread", conversationthread_endpoint="https://fake_conversationthread_endpoint.com" +) diff --git a/sdk/communication/azure-communication-messages/generated_tests/testpreparer_async.py b/sdk/communication/azure-communication-messages/generated_tests/testpreparer_async.py new file mode 100644 index 000000000000..a7b1886fac2a --- /dev/null +++ b/sdk/communication/azure-communication-messages/generated_tests/testpreparer_async.py @@ -0,0 +1,58 @@ +# coding=utf-8 +# -------------------------------------------------------------------------- +# Copyright (c) Microsoft Corporation. All rights reserved. +# Licensed under the MIT License. See License.txt in the project root for license information. +# Code generated by Microsoft (R) Python Code Generator. +# Changes may cause incorrect behavior and will be lost if the code is regenerated. +# -------------------------------------------------------------------------- +from azure.communication.messages.aio import ( + ConversationAdministrationClient, + ConversationThreadClient, + MessageTemplateClient, + NotificationMessagesClient, +) +from devtools_testutils import AzureRecordedTestCase + + +class NotificationMessagesClientTestBaseAsync(AzureRecordedTestCase): + + def create_async_client(self, endpoint): + credential = self.get_credential(NotificationMessagesClient, is_async=True) + return self.create_client_from_credential( + NotificationMessagesClient, + credential=credential, + endpoint=endpoint, + ) + + +class MessageTemplateClientTestBaseAsync(AzureRecordedTestCase): + + def create_async_client(self, endpoint): + credential = self.get_credential(MessageTemplateClient, is_async=True) + return self.create_client_from_credential( + MessageTemplateClient, + credential=credential, + endpoint=endpoint, + ) + + +class ConversationAdministrationClientTestBaseAsync(AzureRecordedTestCase): + + def create_async_client(self, endpoint): + credential = self.get_credential(ConversationAdministrationClient, is_async=True) + return self.create_client_from_credential( + ConversationAdministrationClient, + credential=credential, + endpoint=endpoint, + ) + + +class ConversationThreadClientTestBaseAsync(AzureRecordedTestCase): + + def create_async_client(self, endpoint): + credential = self.get_credential(ConversationThreadClient, is_async=True) + return self.create_client_from_credential( + ConversationThreadClient, + credential=credential, + endpoint=endpoint, + ) diff --git a/sdk/communication/azure-communication-messages/samples/download_media.py b/sdk/communication/azure-communication-messages/samples/download_media.py index ad965cfd1039..a67fd9c37280 100644 --- a/sdk/communication/azure-communication-messages/samples/download_media.py +++ b/sdk/communication/azure-communication-messages/samples/download_media.py @@ -1,3 +1,4 @@ +# pylint: disable=line-too-long,useless-suppression # coding: utf-8 # ------------------------------------------------------------------------- diff --git a/sdk/communication/azure-communication-messages/samples/get_templates_list.py b/sdk/communication/azure-communication-messages/samples/get_templates_list.py index 91e6a1c76abc..e05ec4442928 100644 --- a/sdk/communication/azure-communication-messages/samples/get_templates_list.py +++ b/sdk/communication/azure-communication-messages/samples/get_templates_list.py @@ -1,3 +1,4 @@ +# pylint: disable=line-too-long,useless-suppression # coding: utf-8 # ------------------------------------------------------------------------- diff --git a/sdk/communication/azure-communication-messages/samples/get_templates_list_async.py b/sdk/communication/azure-communication-messages/samples/get_templates_list_async.py index 261767c07d80..6c7ccb98af37 100644 --- a/sdk/communication/azure-communication-messages/samples/get_templates_list_async.py +++ b/sdk/communication/azure-communication-messages/samples/get_templates_list_async.py @@ -1,3 +1,4 @@ +# pylint: disable=line-too-long,useless-suppression # coding: utf-8 # ------------------------------------------------------------------------- diff --git a/sdk/communication/azure-communication-messages/samples/send_audio_notification_messages.py b/sdk/communication/azure-communication-messages/samples/send_audio_notification_messages.py index 7c4f11c55082..61bb5ecabc9f 100644 --- a/sdk/communication/azure-communication-messages/samples/send_audio_notification_messages.py +++ b/sdk/communication/azure-communication-messages/samples/send_audio_notification_messages.py @@ -1,3 +1,4 @@ +# pylint: disable=line-too-long,useless-suppression # coding: utf-8 # ------------------------------------------------------------------------- diff --git a/sdk/communication/azure-communication-messages/samples/send_document_notification_messages.py b/sdk/communication/azure-communication-messages/samples/send_document_notification_messages.py index 847a8d2a08fb..80f52de212d3 100644 --- a/sdk/communication/azure-communication-messages/samples/send_document_notification_messages.py +++ b/sdk/communication/azure-communication-messages/samples/send_document_notification_messages.py @@ -1,3 +1,4 @@ +# pylint: disable=line-too-long,useless-suppression # coding: utf-8 # ------------------------------------------------------------------------- diff --git a/sdk/communication/azure-communication-messages/samples/send_image_notification_messages.py b/sdk/communication/azure-communication-messages/samples/send_image_notification_messages.py index dcf813287188..fac960e33c89 100644 --- a/sdk/communication/azure-communication-messages/samples/send_image_notification_messages.py +++ b/sdk/communication/azure-communication-messages/samples/send_image_notification_messages.py @@ -1,3 +1,4 @@ +# pylint: disable=line-too-long,useless-suppression # coding: utf-8 # ------------------------------------------------------------------------- diff --git a/sdk/communication/azure-communication-messages/samples/send_image_notification_messages_async.py b/sdk/communication/azure-communication-messages/samples/send_image_notification_messages_async.py index df8f4a72e18f..ec61fdcd4ddc 100644 --- a/sdk/communication/azure-communication-messages/samples/send_image_notification_messages_async.py +++ b/sdk/communication/azure-communication-messages/samples/send_image_notification_messages_async.py @@ -1,3 +1,4 @@ +# pylint: disable=line-too-long,useless-suppression # coding: utf-8 # ------------------------------------------------------------------------- diff --git a/sdk/communication/azure-communication-messages/samples/send_reaction_notification_messages.py b/sdk/communication/azure-communication-messages/samples/send_reaction_notification_messages.py index 91d49adda406..22ba1751ee91 100644 --- a/sdk/communication/azure-communication-messages/samples/send_reaction_notification_messages.py +++ b/sdk/communication/azure-communication-messages/samples/send_reaction_notification_messages.py @@ -1,3 +1,4 @@ +# pylint: disable=line-too-long,useless-suppression # coding: utf-8 # ------------------------------------------------------------------------- diff --git a/sdk/communication/azure-communication-messages/samples/send_sticker_notification_messages.py b/sdk/communication/azure-communication-messages/samples/send_sticker_notification_messages.py index d72c41bab74e..aac9efdc28ef 100644 --- a/sdk/communication/azure-communication-messages/samples/send_sticker_notification_messages.py +++ b/sdk/communication/azure-communication-messages/samples/send_sticker_notification_messages.py @@ -1,3 +1,4 @@ +# pylint: disable=line-too-long,useless-suppression # coding: utf-8 # ------------------------------------------------------------------------- diff --git a/sdk/communication/azure-communication-messages/samples/send_template_notification_messages.py b/sdk/communication/azure-communication-messages/samples/send_template_notification_messages.py index 8887e73c6744..eb9b990eca97 100644 --- a/sdk/communication/azure-communication-messages/samples/send_template_notification_messages.py +++ b/sdk/communication/azure-communication-messages/samples/send_template_notification_messages.py @@ -1,3 +1,4 @@ +# pylint: disable=line-too-long,useless-suppression # coding: utf-8 # ------------------------------------------------------------------------- diff --git a/sdk/communication/azure-communication-messages/samples/send_template_notification_messages_async.py b/sdk/communication/azure-communication-messages/samples/send_template_notification_messages_async.py index d3d2d4d26874..3ccc0f388875 100644 --- a/sdk/communication/azure-communication-messages/samples/send_template_notification_messages_async.py +++ b/sdk/communication/azure-communication-messages/samples/send_template_notification_messages_async.py @@ -1,3 +1,4 @@ +# pylint: disable=line-too-long,useless-suppression # coding: utf-8 # ------------------------------------------------------------------------- diff --git a/sdk/communication/azure-communication-messages/samples/send_text_notification_messages.py b/sdk/communication/azure-communication-messages/samples/send_text_notification_messages.py index 390ae2f5d28b..051afe425883 100644 --- a/sdk/communication/azure-communication-messages/samples/send_text_notification_messages.py +++ b/sdk/communication/azure-communication-messages/samples/send_text_notification_messages.py @@ -1,3 +1,4 @@ +# pylint: disable=line-too-long,useless-suppression # coding: utf-8 # ------------------------------------------------------------------------- diff --git a/sdk/communication/azure-communication-messages/samples/send_text_notification_messages_async.py b/sdk/communication/azure-communication-messages/samples/send_text_notification_messages_async.py index 5b7cdfe4d88d..fdba46a3cd3a 100644 --- a/sdk/communication/azure-communication-messages/samples/send_text_notification_messages_async.py +++ b/sdk/communication/azure-communication-messages/samples/send_text_notification_messages_async.py @@ -1,3 +1,4 @@ +# pylint: disable=line-too-long,useless-suppression # coding: utf-8 # ------------------------------------------------------------------------- diff --git a/sdk/communication/azure-communication-messages/samples/send_text_notification_messages_with_token_credentials.py b/sdk/communication/azure-communication-messages/samples/send_text_notification_messages_with_token_credentials.py index 55d28e259269..df67174d0299 100644 --- a/sdk/communication/azure-communication-messages/samples/send_text_notification_messages_with_token_credentials.py +++ b/sdk/communication/azure-communication-messages/samples/send_text_notification_messages_with_token_credentials.py @@ -1,3 +1,4 @@ +# pylint: disable=line-too-long,useless-suppression # coding: utf-8 # ------------------------------------------------------------------------- diff --git a/sdk/communication/azure-communication-messages/samples/send_video_notification_messages.py b/sdk/communication/azure-communication-messages/samples/send_video_notification_messages.py index 96d697ac81db..7d1d4ebbf316 100644 --- a/sdk/communication/azure-communication-messages/samples/send_video_notification_messages.py +++ b/sdk/communication/azure-communication-messages/samples/send_video_notification_messages.py @@ -1,3 +1,4 @@ +# pylint: disable=line-too-long,useless-suppression # coding: utf-8 # ------------------------------------------------------------------------- diff --git a/sdk/communication/azure-communication-messages/samples/send_whatsapp_list_notification_messages.py b/sdk/communication/azure-communication-messages/samples/send_whatsapp_list_notification_messages.py index 2407f0d09504..0a6df4e72ec8 100644 --- a/sdk/communication/azure-communication-messages/samples/send_whatsapp_list_notification_messages.py +++ b/sdk/communication/azure-communication-messages/samples/send_whatsapp_list_notification_messages.py @@ -1,3 +1,4 @@ +# pylint: disable=line-too-long,useless-suppression # coding: utf-8 # ------------------------------------------------------------------------- diff --git a/sdk/communication/azure-communication-messages/samples/send_whatsapp_urlbased_notification_messages.py b/sdk/communication/azure-communication-messages/samples/send_whatsapp_urlbased_notification_messages.py index 8af8358be64b..e73227267a05 100644 --- a/sdk/communication/azure-communication-messages/samples/send_whatsapp_urlbased_notification_messages.py +++ b/sdk/communication/azure-communication-messages/samples/send_whatsapp_urlbased_notification_messages.py @@ -1,3 +1,4 @@ +# pylint: disable=line-too-long,useless-suppression # coding: utf-8 # ------------------------------------------------------------------------- diff --git a/sdk/communication/azure-communication-messages/samples/send_whatsappreplybutton_notification_messages.py b/sdk/communication/azure-communication-messages/samples/send_whatsappreplybutton_notification_messages.py index 06634802466a..976bef5a072d 100644 --- a/sdk/communication/azure-communication-messages/samples/send_whatsappreplybutton_notification_messages.py +++ b/sdk/communication/azure-communication-messages/samples/send_whatsappreplybutton_notification_messages.py @@ -1,3 +1,4 @@ +# pylint: disable=line-too-long,useless-suppression # coding: utf-8 # ------------------------------------------------------------------------- diff --git a/sdk/communication/azure-communication-messages/setup.py b/sdk/communication/azure-communication-messages/setup.py index c0d6b48794c6..3feff21e6f6e 100644 --- a/sdk/communication/azure-communication-messages/setup.py +++ b/sdk/communication/azure-communication-messages/setup.py @@ -5,7 +5,7 @@ # Code generated by Microsoft (R) Python Code Generator. # Changes may cause incorrect behavior and will be lost if the code is regenerated. # -------------------------------------------------------------------------- -# coding: utf-8 + import os import re @@ -29,7 +29,7 @@ setup( name=PACKAGE_NAME, version=version, - description="Microsoft {} Client Library for Python".format(PACKAGE_PPRINT_NAME), + description="Microsoft Corporation {} Client Library for Python".format(PACKAGE_PPRINT_NAME), long_description=open("README.md", "r").read(), long_description_content_type="text/markdown", license="MIT License", @@ -42,7 +42,6 @@ "Programming Language :: Python", "Programming Language :: Python :: 3 :: Only", "Programming Language :: Python :: 3", - "Programming Language :: Python :: 3.8", "Programming Language :: Python :: 3.9", "Programming Language :: Python :: 3.10", "Programming Language :: Python :: 3.11", @@ -67,5 +66,5 @@ "azure-core>=1.30.0", "typing-extensions>=4.6.0", ], - python_requires=">=3.8", + python_requires=">=3.9", ) diff --git a/sdk/communication/azure-communication-messages/tests/_shared/communication_service_preparer.py b/sdk/communication/azure-communication-messages/tests/_shared/communication_service_preparer.py index 2502a4713a88..e552ff83a69a 100644 --- a/sdk/communication/azure-communication-messages/tests/_shared/communication_service_preparer.py +++ b/sdk/communication/azure-communication-messages/tests/_shared/communication_service_preparer.py @@ -1,3 +1,4 @@ +# pylint: disable=line-too-long,useless-suppression # ------------------------------------ # Copyright (c) Microsoft Corporation. # Licensed under the MIT License. diff --git a/sdk/communication/azure-communication-messages/tsp-location.yaml b/sdk/communication/azure-communication-messages/tsp-location.yaml index b6a10b5b40ee..62ec1bec6d75 100644 --- a/sdk/communication/azure-communication-messages/tsp-location.yaml +++ b/sdk/communication/azure-communication-messages/tsp-location.yaml @@ -1,4 +1,4 @@ directory: specification/communication/Communication.Messages -commit: 7797d20dce4f18ee2b3709b894f22634d6fb8b1e +commit: 726419b7eba57b9b5888ca11e055c8f82dcaae58 repo: Azure/azure-rest-api-specs -additionalDirectories: [] +additionalDirectories: