Skip to content

Commit 2251672

Browse files
committed
Create conversation client
1 parent ea6f51f commit 2251672

File tree

9 files changed

+408
-130
lines changed

9 files changed

+408
-130
lines changed

packages/api/src/microsoft/teams/api/clients/conversation/__init__.py

Lines changed: 10 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -4,6 +4,15 @@
44
"""
55

66
from .activity import ConversationActivityClient
7+
from .client import ConversationClient
78
from .member import ConversationMemberClient
9+
from .params import CreateConversationParams, GetConversationsParams, GetConversationsResponse
810

9-
__all__ = ["ConversationActivityClient", "ConversationMemberClient"]
11+
__all__ = [
12+
"ConversationActivityClient",
13+
"ConversationClient",
14+
"ConversationMemberClient",
15+
"CreateConversationParams",
16+
"GetConversationsParams",
17+
"GetConversationsResponse",
18+
]
Lines changed: 155 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,155 @@
1+
"""
2+
Copyright (c) Microsoft Corporation. All rights reserved.
3+
Licensed under the MIT License.
4+
"""
5+
6+
from typing import Any, Optional, Union
7+
8+
from microsoft.teams.common.http import Client, ClientOptions
9+
10+
from ...models import ConversationResource
11+
from .activity import ConversationActivityClient
12+
from .member import ConversationMemberClient
13+
from .params import (
14+
CreateConversationParams,
15+
GetConversationsParams,
16+
GetConversationsResponse,
17+
)
18+
19+
20+
class ConversationOperations:
21+
"""Base class for conversation operations."""
22+
23+
def __init__(self, client: "ConversationClient", conversation_id: str) -> None:
24+
self._client = client
25+
self._conversation_id = conversation_id
26+
27+
28+
class ActivityOperations(ConversationOperations):
29+
"""Operations for managing activities in a conversation."""
30+
31+
async def create(self, activity: Any) -> Any:
32+
return await self._client._activities.create(self._conversation_id, activity)
33+
34+
async def update(self, activity_id: str, activity: Any) -> Any:
35+
return await self._client._activities.update(self._conversation_id, activity_id, activity)
36+
37+
async def reply(self, activity_id: str, activity: Any) -> Any:
38+
return await self._client._activities.reply(self._conversation_id, activity_id, activity)
39+
40+
async def delete(self, activity_id: str) -> None:
41+
await self._client._activities.delete(self._conversation_id, activity_id)
42+
43+
async def get_members(self, activity_id: str) -> Any:
44+
return await self._client._activities.get_members(self._conversation_id, activity_id)
45+
46+
47+
class MemberOperations(ConversationOperations):
48+
"""Operations for managing members in a conversation."""
49+
50+
async def get_all(self) -> Any:
51+
return await self._client._members.get(self._conversation_id)
52+
53+
async def get(self, member_id: str) -> Any:
54+
return await self._client._members.get_by_id(self._conversation_id, member_id)
55+
56+
async def delete(self, member_id: str) -> None:
57+
await self._client._members.delete(self._conversation_id, member_id)
58+
59+
60+
class ConversationClient:
61+
"""Client for managing Teams conversations."""
62+
63+
def __init__(self, service_url: str, options: Union[Client, ClientOptions] = None) -> None:
64+
"""Initialize the client.
65+
66+
Args:
67+
service_url: The Teams service URL.
68+
options: Either an HTTP client instance or client options. If None, a default client is created.
69+
"""
70+
self.service_url = service_url
71+
72+
if isinstance(options, Client):
73+
self._http = options
74+
else:
75+
self._http = Client(options or ClientOptions())
76+
77+
self._activities = ConversationActivityClient(service_url, self._http)
78+
self._members = ConversationMemberClient(service_url, self._http)
79+
80+
@property
81+
def http(self) -> Client:
82+
"""Get the HTTP client.
83+
84+
Returns:
85+
The HTTP client instance.
86+
"""
87+
return self._http
88+
89+
@http.setter
90+
def http(self, client: Client) -> None:
91+
"""Set the HTTP client.
92+
93+
Args:
94+
client: The HTTP client to use.
95+
"""
96+
self._http = client
97+
# Update sub-clients with new HTTP client
98+
self._activities = ConversationActivityClient(self.service_url, client)
99+
self._members = ConversationMemberClient(self.service_url, client)
100+
101+
def activities(self, conversation_id: str) -> ActivityOperations:
102+
"""Get activity operations for a conversation.
103+
104+
Args:
105+
conversation_id: The ID of the conversation.
106+
107+
Returns:
108+
An operations object for managing activities in the conversation.
109+
"""
110+
return ActivityOperations(self, conversation_id)
111+
112+
def members(self, conversation_id: str) -> MemberOperations:
113+
"""Get member operations for a conversation.
114+
115+
Args:
116+
conversation_id: The ID of the conversation.
117+
118+
Returns:
119+
An operations object for managing members in the conversation.
120+
"""
121+
return MemberOperations(self, conversation_id)
122+
123+
async def get(self, params: Optional[GetConversationsParams] = None) -> GetConversationsResponse:
124+
"""Get a list of conversations.
125+
126+
Args:
127+
params: Optional parameters for getting conversations.
128+
129+
Returns:
130+
A response containing the list of conversations and a continuation token.
131+
"""
132+
query_params = {}
133+
if params and params.continuation_token:
134+
query_params["continuationToken"] = params.continuation_token
135+
136+
response = await self._http.get(
137+
f"{self.service_url}/v3/conversations",
138+
params=query_params,
139+
)
140+
return GetConversationsResponse.model_validate(response.json())
141+
142+
async def create(self, params: CreateConversationParams) -> ConversationResource:
143+
"""Create a new conversation.
144+
145+
Args:
146+
params: Parameters for creating the conversation.
147+
148+
Returns:
149+
The created conversation resource.
150+
"""
151+
response = await self._http.post(
152+
f"{self.service_url}/v3/conversations",
153+
json=params.model_dump(by_alias=True),
154+
)
155+
return ConversationResource.model_validate(response.json())
Lines changed: 51 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,51 @@
1+
"""
2+
Copyright (c) Microsoft Corporation. All rights reserved.
3+
Licensed under the MIT License.
4+
"""
5+
6+
from typing import Any, Dict, List, Optional
7+
8+
from pydantic import BaseModel, ConfigDict, Field
9+
from pydantic.alias_generators import to_camel
10+
11+
from ...models import Account, Activity, Conversation
12+
13+
14+
class GetConversationsParams(BaseModel):
15+
"""Parameters for getting conversations."""
16+
17+
model_config = ConfigDict(
18+
alias_generator=to_camel,
19+
extra="allow",
20+
)
21+
22+
continuation_token: Optional[str] = Field(None, description="Token for pagination")
23+
24+
25+
class CreateConversationParams(BaseModel):
26+
"""Parameters for creating a conversation."""
27+
28+
model_config = ConfigDict(
29+
alias_generator=to_camel,
30+
extra="allow",
31+
)
32+
33+
is_group: bool = Field(False, description="Whether this is a group conversation")
34+
bot: Optional[Account] = Field(None, description="Bot account to add to the conversation")
35+
members: Optional[List[Account]] = Field(None, description="Members to add to the conversation")
36+
topic_name: Optional[str] = Field(None, description="Topic name for the conversation")
37+
tenant_id: Optional[str] = Field(None, description="Tenant ID for the conversation")
38+
activity: Optional[Activity] = Field(None, description="Initial activity to post in the conversation")
39+
channel_data: Optional[Dict[str, Any]] = Field(None, description="Channel-specific data")
40+
41+
42+
class GetConversationsResponse(BaseModel):
43+
"""Response from getting conversations."""
44+
45+
model_config = ConfigDict(
46+
alias_generator=to_camel,
47+
extra="allow",
48+
)
49+
50+
continuation_token: Optional[str] = Field(None, description="Token for getting the next page of conversations")
51+
conversations: List[Conversation] = Field([], description="List of conversations")

packages/api/src/microsoft/teams/api/models/__init__.py

Lines changed: 7 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -5,5 +5,11 @@
55

66
from .account import Account
77
from .activity import Activity
8+
from .conversation import Conversation, ConversationResource
89

9-
__all__ = ["Account", "Activity"]
10+
__all__ = [
11+
"Account",
12+
"Activity",
13+
"Conversation",
14+
"ConversationResource",
15+
]
Lines changed: 9 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,9 @@
1+
"""
2+
Copyright (c) Microsoft Corporation. All rights reserved.
3+
Licensed under the MIT License.
4+
"""
5+
6+
from .conversation import Conversation
7+
from .resource import ConversationResource
8+
9+
__all__ = ["Conversation", "ConversationResource"]
Lines changed: 26 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,26 @@
1+
"""
2+
Copyright (c) Microsoft Corporation. All rights reserved.
3+
Licensed under the MIT License.
4+
"""
5+
6+
from typing import Any, Dict, List, Optional
7+
8+
from pydantic import BaseModel, ConfigDict, Field
9+
from pydantic.alias_generators import to_camel
10+
11+
from ..account import Account
12+
13+
14+
class Conversation(BaseModel):
15+
"""Represents a Teams conversation."""
16+
17+
model_config = ConfigDict(
18+
alias_generator=to_camel,
19+
extra="allow",
20+
)
21+
22+
id: str = Field(..., description="The unique identifier for the conversation")
23+
type: str = Field(..., description="The type of conversation (e.g., 'channel', 'chat')")
24+
is_group: bool = Field(False, description="Whether this is a group conversation")
25+
members: Optional[List[Account]] = Field(None, description="The members of the conversation")
26+
properties: Optional[Dict[str, Any]] = Field(None, description="Additional properties for the conversation")
Lines changed: 20 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,20 @@
1+
"""
2+
Copyright (c) Microsoft Corporation. All rights reserved.
3+
Licensed under the MIT License.
4+
"""
5+
6+
from pydantic import BaseModel, ConfigDict, Field
7+
from pydantic.alias_generators import to_camel
8+
9+
10+
class ConversationResource(BaseModel):
11+
"""Resource returned when creating a conversation."""
12+
13+
model_config = ConfigDict(
14+
alias_generator=to_camel,
15+
extra="allow",
16+
)
17+
18+
id: str = Field(..., description="The ID of the created conversation")
19+
activity_id: str = Field(..., description="The ID of the activity that created the conversation")
20+
service_url: str = Field(..., description="The service URL for the conversation")
Lines changed: 14 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,14 @@
1+
"""
2+
Copyright (c) Microsoft Corporation. All rights reserved.
3+
Licensed under the MIT License.
4+
"""
5+
6+
from pydantic import BaseModel
7+
8+
9+
class ConversationResource(BaseModel):
10+
"""A response containing a resource."""
11+
12+
id: str
13+
activity_id: str
14+
service_url: str

0 commit comments

Comments
 (0)