Skip to content

Commit

Permalink
Rsarkar/communication chat preview5 (Azure#17325)
Browse files Browse the repository at this point in the history
* Rename user_identifier suffix (Azure#17178)
* make CommunicationUserIdentifierSerializer private
* CommunicationTokenCredential + AccessToken fix
- Initialize CommunicationTokenCredential with token and not with CommunicationTokenRefreshOptions
- Convert AccessToken.expires_on to int as compared to datetime
* add token_refresher to CommunicationTokenCredential
* update docstring
* Identifier fields renaming _ credential import fixes in sample code
* preview5 models generated
- CommunicationError renamed to ChatError
* rename ChatThread to ChatThreadProperties
* get_chat_thread renamed to get_properties
- Rename method
- Move get_properties from ChatClient to ChatThreadClient
- Change method signature - remove parameter thread_id
- Modify unit and e2e tests - move tests from chat_thread_* to chat_thread_client_*
- Update README.md
* Rename ChatThreadInfo to ChatThreadItem
* Remove add_participant
* Rename repeatability_request_id to idempotency_token
* Change send_message return type from str to SendChatMessageResult
* Changes made due to rename of CommunicationError -> ChatError
- Changes made due to flattening of CreateChatThreadResult and AddChatParticipantsResult
* test recording added
* Address PR comments
* pylint fixes
  • Loading branch information
sarkar-rajarshi authored Mar 19, 2021
1 parent ef231f1 commit 388beb9
Show file tree
Hide file tree
Showing 90 changed files with 3,472 additions and 6,566 deletions.
11 changes: 10 additions & 1 deletion sdk/communication/azure-communication-chat/CHANGELOG.md
Original file line number Diff line number Diff line change
@@ -1,7 +1,16 @@
# Release History

## 1.0.0b6 (Unreleased)

### Breaking Changes
- Renamed `ChatThread` to `ChatThreadProperties`.
- Renamed `get_chat_thread` to `get_properties`.
- Moved `get_properties` under `ChatThreadClient`.
- Renamed `ChatThreadInfo` to `ChatThreadItem`.
- Removed `ChatThreadClient.add_participant` method.
- Renamed `repeatability_request_id` to `idempotency_token`.
- Changed return type of `send_message` to `SendChatMessageResult`.
- Replaced `CommunicationError` with `ChatError`.
- Refactored `CommunicationTokenCredential` constructor to accept `token` instead of `CommunicationTokenRefreshOptions`.

## 1.0.0b5 (2021-03-09)
### Breaking Changes
Expand Down
117 changes: 36 additions & 81 deletions sdk/communication/azure-communication-chat/README.md
Original file line number Diff line number Diff line change
Expand Up @@ -44,14 +44,11 @@ it with this token. It is because the initiator of the create request must be in
This will allow you to create, get, list or delete chat threads.

```python
from azure.communication.chat import ChatClient
from azure.communication.identity._shared.user_credential import CommunicationTokenCredential
from azure.communication.identity._shared.user_token_refresh_options import CommunicationTokenRefreshOptions
from azure.communication.chat import ChatClient, CommunicationTokenCredential

# Your unique Azure Communication service endpoint
endpoint = "https://<RESOURCE_NAME>.communcationservices.azure.com"
refresh_options = CommunicationTokenRefreshOptions(token)
chat_client = ChatClient(endpoint, CommunicationTokenCredential(refresh_options))
chat_client = ChatClient(endpoint, CommunicationTokenCredential(token))
```

## Create Chat Thread Client
Expand All @@ -67,15 +64,15 @@ chat_thread_client = chat_client.get_chat_thread_client(create_chat_thread_resul
```

Additionally, the client can also direct so that the request is repeatable; that is, if the client makes the
request multiple times with the same Repeatability-Request-ID and it will get back an appropriate response without
the server executing the request multiple times. The value of the Repeatability-Request-ID is an opaque string
request multiple times with the same Idempotency-Token and it will get back an appropriate response without
the server executing the request multiple times. The value of the Idempotency-Token is an opaque string
representing a client-generated, globally unique for all time, identifier for the request.

```python
create_chat_thread_result = chat_client.create_chat_thread(
topic,
thread_participants=thread_participants,
repeatability_request_id=repeatability_request_id
idempotency_token=idempotency_token
)
chat_thread_client = chat_client.get_chat_thread_client(create_chat_thread_result.chat_thread.id)
```
Expand All @@ -96,11 +93,10 @@ Once you initialized a `ChatClient` class, you can do the following chat operati

## Create, get, update, and delete threads

Perform CRD(Create-Read-Delete) operations on thread participants
Perform CRD(Create-Read-Delete) operations on threads

```Python
create_chat_thread(topic, **kwargs)
get_chat_thread(thread_id, **kwargs)
list_chat_threads(**kwargs)
delete_chat_thread(thread_id, **kwargs)
```
Expand All @@ -115,6 +111,11 @@ Perform Update operation on thread topic
update_topic(topic, **kwargs)
```

## Get Chat thread properties
```python
get_properties(**kwargs)
```

## Send, get, update, and delete messages

Perform CRUD(Create-Read-Update-Delete) operations on messages
Expand All @@ -133,7 +134,6 @@ Perform CRD(Create-Read-Delete) operations on thread participants

```Python
list_participants(**kwargs)
add_participant(thread_participant, **kwargs)
add_participants(thread_participants, **kwargs)
remove_participant(participant_id, **kwargs)
```
Expand Down Expand Up @@ -177,22 +177,22 @@ Use the `create_chat_thread` method to create a chat thread.
<!-- [User Access Tokens](#user-access-tokens) -->
- `display_name`, optional, is the display name for the thread participant.
- `share_history_time`, optional, time from which the chat history is shared with the participant.
- Use `repeatability_request_id`, optional, to specify the unique identifier for the request.
- Use `idempotency_token`, optional, to specify the unique identifier for the request.


`CreateChatThreadResult` is the result returned from creating a thread, you can use it to fetch the `id` of
the chat thread that got created. This `id` can then be used to fetch a `ChatThreadClient` object using
the `get_chat_thread_client` method. `ChatThreadClient` can be used to perform other chat operations to this chat thread.

```Python
# Without repeatability_request_id and thread_participants
# Without idempotency_token and thread_participants
topic = "test topic"
create_chat_thread_result = chat_client.create_chat_thread(topic)
chat_thread_client = chat_client.get_chat_thread_client(create_chat_thread_result.chat_thread.id)
```

```Python
# With repeatability_request_id and thread_participants
# With idempotency_token and thread_participants
from azure.communication.identity import CommunicationIdentityClient
from azure.communication.chat import ChatThreadParticipant
import uuid
Expand All @@ -219,13 +219,13 @@ thread_participants = [ChatThreadParticipant(
share_history_time=datetime.utcnow()
)]

# obtains repeatability_request_id using some customer logic
repeatability_request_id = get_unique_identifier_for_request()
# obtains idempotency_token using some customer logic
idempotency_token = get_unique_identifier_for_request()

create_chat_thread_result = chat_client.create_chat_thread(
topic,
thread_participants=thread_participants,
repeatability_request_id=repeatability_request_id)
idempotency_token=idempotency_token)
thread_id = create_chat_thread_result.chat_thread.id

# fetch ChatThreadClient
Expand All @@ -240,16 +240,17 @@ def decide_to_retry(error, **kwargs):
return True

retry = [thread_participant for thread_participant, error in create_chat_thread_result.errors if decide_to_retry(error)]
chat_thread_client.add_participants(retry)
if len(retry) > 0:
chat_thread_client.add_participants(retry)
```


### Get a thread

Use `get_chat_thread` method retrieves a `ChatThread` from the service; `thread_id` is the unique ID of the thread.
- Use `thread_id`, required, to specify the unique ID of the thread.
Use `get_properties` method retrieves a `ChatThreadProperties` from the service; `thread_id` is the unique ID of the thread.

```Python
chat_thread = chat_client.get_chat_thread(thread_id=thread_id)
chat_thread_properties = chat_thread_client.get_properties()
```

### List chat threads
Expand All @@ -258,7 +259,7 @@ Use `list_chat_threads` method retrieves the list of created chat threads
- Use `results_per_page`, optional, The maximum number of messages to be returned per page.
- Use `start_time`, optional, The start time where the range query.

An iterator of `[ChatThreadInfo]` is the response returned from listing threads
An iterator of `[ChatThreadItem]` is the response returned from listing threads

```python
from datetime import datetime, timedelta
Expand All @@ -267,10 +268,10 @@ import pytz
start_time = datetime.utcnow() - timedelta(days=2)
start_time = start_time.replace(tzinfo=pytz.utc)

chat_thread_infos = chat_client.list_chat_threads(results_per_page=5, start_time=start_time)
for chat_thread_info_page in chat_thread_infos.by_page():
for chat_thread_info in chat_thread_info_page:
print(chat_thread_info)
chat_threads = chat_client.list_chat_threads(results_per_page=5, start_time=start_time)
for chat_thread_item_page in chat_threads.by_page():
for chat_thread_item in chat_thread_item_page:
print("thread id:", chat_thread_item.id)
```

### Update a thread topic
Expand All @@ -279,10 +280,10 @@ Use `update_topic` method to update a thread's properties. `topic` is used to de
- Use `topic` to give thread a new topic;

```python
topic="new topic"
topic = "new topic"
chat_thread_client.update_topic(topic=topic)

chat_thread = chat_client.get_chat_thread(thread_id)
chat_thread = chat_client.get_properties(thread_id)

assert chat_thread.topic == topic
```
Expand Down Expand Up @@ -322,15 +323,17 @@ sender_display_name='sender name'
chat_message_type = ChatMessageType.TEXT

# without specifying sender_display_name and chat_message_type
send_message_result_id = chat_thread_client.send_message(content)
send_message_result = chat_thread_client.send_message(content)
send_message_result_id = send_message_result.id
print("Message sent: id: ", send_message_result_id)

# specifying sender_display_name and chat_message_type
send_message_result_w_type_id = chat_thread_client.send_message(
send_message_result_w_type = chat_thread_client.send_message(
content,
sender_display_name=sender_display_name,
chat_message_type=chat_message_type # equivalent to chat_message_type = 'text'
)
send_message_result_w_type_id = send_message_result_w_type.id
print("Message sent: id: ", send_message_result_w_type_id)
```

Expand Down Expand Up @@ -407,55 +410,6 @@ for chat_thread_participant_page in chat_thread_participants.by_page():
print("ChatThreadParticipant: ", chat_thread_participant)
```

### Add single thread participant
Use `add_participant` method to add a single thread participants to the thread.

- Use `thread_participant`, required, to specify the `ChatThreadParticipant` to be added to the thread;
- `user`, required, it is the `CommunicationUserIdentifier` you created by CommunicationIdentityClient.create_user() from User Access Tokens
<!-- [User Access Tokens](#user-access-tokens) -->
- `display_name`, optional, is the display name for the thread participant.
- `share_history_time`, optional, time from which the chat history is shared with the participant.

When participant is successfully added, no error is thrown. In case of an error encountered while adding participant,
a `RuntimeError` is thrown
```python
from azure.communication.identity import CommunicationIdentityClient
from azure.communication.chat import ChatThreadParticipant
from datetime import datetime

# create an user
identity_client = CommunicationIdentityClient.from_connection_string('<connection_string>')
new_user = identity_client.create_user()

# # conversely, you can also add an existing user to a chat thread; provided the user_id is known
# from azure.communication.identity import CommunicationUserIdentifier
#
# user_id = 'some user id'
# user_display_name = "Wilma Flinstone"
# new_user = CommunicationUserIdentifier(user_id)
# participant = ChatThreadParticipant(
# user=new_user,
# display_name=user_display_name,
# share_history_time=datetime.utcnow())

def decide_to_retry(error, **kwargs):
"""
Insert some custom logic to decide if retry is applicable based on error
"""
return True

participant = ChatThreadParticipant(
user=new_user,
display_name='Fred Flinstone',
share_history_time=datetime.utcnow())

try:
chat_thread_client.add_participant(thread_participant=participant)
except RuntimeError as e:
if e is not None and decide_to_retry(error=e):
chat_thread_client.add_participant(thread_participant=participant)

```
### Add thread participants

Use `add_participants` method to add thread participants to the thread.
Expand All @@ -466,7 +420,7 @@ Use `add_participants` method to add thread participants to the thread.
- `display_name`, optional, is the display name for the thread participant.
- `share_history_time`, optional, time from which the chat history is shared with the participant.

A `list(tuple(ChatThreadParticipant, CommunicationError))` is returned. When participant is successfully added,
A `list(tuple(ChatThreadParticipant, ChatError))` is returned. When participant is successfully added,
an empty list is expected. In case of an error encountered while adding participant, the list is populated
with the failed participants along with the error that was encountered.

Expand Down Expand Up @@ -547,7 +501,8 @@ Use `send_read_receipt` method to post a read receipt event to a thread, on beha
- Use `message_id` to specify the id of the message whose read receipt is to be sent
```python
content='hello world'
send_message_result_id = chat_thread_client.send_message(content)
send_message_result = chat_thread_client.send_message(content)
send_message_result_id = send_message_result.id
chat_thread_client.send_read_receipt(message_id=send_message_result_id)
```

Expand Down
Original file line number Diff line number Diff line change
Expand Up @@ -3,32 +3,35 @@
from ._chat_thread_client import ChatThreadClient
from ._generated.models import (
SendChatMessageResult,
ChatThreadInfo,
ChatThreadItem,
ChatMessageType,
CommunicationError
ChatError
)

from ._models import (
ChatThreadParticipant,
ChatMessage,
ChatThread,
ChatThreadProperties,
ChatMessageReadReceipt,
ChatMessageContent,
CreateChatThreadResult
)

from ._shared.user_credential import CommunicationTokenCredential

__all__ = [
'ChatClient',
'ChatThreadClient',
'ChatMessage',
'ChatMessageContent',
'ChatMessageReadReceipt',
'SendChatMessageResult',
'ChatThread',
'ChatThreadInfo',
'ChatThreadProperties',
'ChatThreadItem',
'ChatThreadParticipant',
'ChatMessageType',
'CreateChatThreadResult',
'CommunicationError'
'ChatError',
'CommunicationTokenCredential'
]
__version__ = VERSION
Loading

0 comments on commit 388beb9

Please sign in to comment.