circle-so-python-sdk 0.1.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (48) hide show
  1. circle/__init__.py +24 -0
  2. circle/api/__init__.py +1 -0
  3. circle/api/admin_access_groups.py +133 -0
  4. circle/api/admin_community.py +122 -0
  5. circle/api/admin_courses.py +172 -0
  6. circle/api/admin_events.py +101 -0
  7. circle/api/admin_misc.py +305 -0
  8. circle/api/admin_posts.py +200 -0
  9. circle/api/admin_spaces.py +301 -0
  10. circle/api/admin_tags.py +146 -0
  11. circle/api/auth.py +63 -0
  12. circle/api/headless_chat_notif_members.py +323 -0
  13. circle/api/headless_misc.py +218 -0
  14. circle/api/headless_spaces_posts.py +279 -0
  15. circle/client.py +197 -0
  16. circle/constants.py +5 -0
  17. circle/exceptions.py +34 -0
  18. circle/http.py +227 -0
  19. circle/models/__init__.py +5 -0
  20. circle/models/admin/__init__.py +47 -0
  21. circle/models/admin/community.py +82 -0
  22. circle/models/admin/courses.py +30 -0
  23. circle/models/admin/events.py +67 -0
  24. circle/models/admin/members.py +105 -0
  25. circle/models/admin/misc.py +240 -0
  26. circle/models/admin/posts.py +172 -0
  27. circle/models/admin/spaces.py +146 -0
  28. circle/models/admin/tags.py +85 -0
  29. circle/models/auth.py +21 -0
  30. circle/models/base.py +28 -0
  31. circle/models/headless/__init__.py +50 -0
  32. circle/models/headless/chat.py +134 -0
  33. circle/models/headless/comments.py +60 -0
  34. circle/models/headless/courses.py +109 -0
  35. circle/models/headless/members.py +105 -0
  36. circle/models/headless/misc.py +120 -0
  37. circle/models/headless/notifications.py +66 -0
  38. circle/models/headless/posts.py +137 -0
  39. circle/models/headless/spaces.py +80 -0
  40. circle/pagination.py +116 -0
  41. circle/py.typed +1 -0
  42. circle/rate_limit.py +36 -0
  43. circle/validation.py +67 -0
  44. circle/webhooks.py +39 -0
  45. circle_so_python_sdk-0.1.0.dist-info/METADATA +120 -0
  46. circle_so_python_sdk-0.1.0.dist-info/RECORD +48 -0
  47. circle_so_python_sdk-0.1.0.dist-info/WHEEL +4 -0
  48. circle_so_python_sdk-0.1.0.dist-info/licenses/LICENSE +21 -0
@@ -0,0 +1,305 @@
1
+ """Admin API -- Forms, Segments, Invitations, and Misc endpoints."""
2
+ from __future__ import annotations
3
+ from typing import Any, Dict, List, Optional, Tuple
4
+ from circle.constants import ADMIN_V2_PREFIX as _P
5
+ from circle.http import AsyncTransport, SyncTransport
6
+ from circle.models.admin.misc import (
7
+ Form, FormList, FormSubmission, FormSubmissionList,
8
+ CommunitySegment, CommunitySegmentList, InvitationLink, InvitationLinkList,
9
+ Embed, DirectUpload, LiveRoom, LiveRoomList,
10
+ FlaggedContent, FlaggedContentList, LeaderboardMember, AdvancedSearchResults,
11
+ )
12
+ from circle.models.admin.community import ChatPreferences
13
+
14
+ _Req = Tuple[str, str, Dict[str, Any]]
15
+
16
+
17
+ # -- Param helpers --
18
+
19
+ def _list_forms_req(page: int, per_page: int, name: Optional[str]) -> _Req:
20
+ p: Dict[str, Any] = {"page": page, "per_page": per_page}
21
+ if name:
22
+ p["name"] = name
23
+ return "GET", f"{_P}/forms", {"params": p}
24
+
25
+
26
+ def _list_community_segments_req(page: int, per_page: int, title: Optional[str]) -> _Req:
27
+ p: Dict[str, Any] = {"page": page, "per_page": per_page}
28
+ if title:
29
+ p["title"] = title
30
+ return "GET", f"{_P}/community_segments", {"params": p}
31
+
32
+
33
+ def _list_invitation_links_req(page: int, per_page: int, name: Optional[str],
34
+ status: Optional[str]) -> _Req:
35
+ p: Dict[str, Any] = {"page": page, "per_page": per_page}
36
+ if name:
37
+ p["name"] = name
38
+ if status:
39
+ p["status"] = status
40
+ return "GET", f"{_P}/invitation_links", {"params": p}
41
+
42
+
43
+ def _list_flagged_contents_req(page: int, per_page: int, status: Optional[str]) -> _Req:
44
+ p: Dict[str, Any] = {"page": page, "per_page": per_page}
45
+ if status:
46
+ p["status"] = status
47
+ return "GET", f"{_P}/flagged_contents", {"params": p}
48
+
49
+
50
+ def _advanced_search_req(query: str, page: int, per_page: int,
51
+ type: Optional[str], kwargs: Dict[str, Any]) -> _Req:
52
+ p: Dict[str, Any] = {"query": query, "page": page, "per_page": per_page, **kwargs}
53
+ if type:
54
+ p["type"] = type
55
+ return "GET", f"{_P}/advanced_search", {"params": p}
56
+
57
+
58
+ # ---------------------------------------------------------------------------
59
+ # Sync client
60
+ # ---------------------------------------------------------------------------
61
+
62
+ class AdminMiscClient:
63
+ def __init__(self, transport: SyncTransport) -> None:
64
+ self._t = transport
65
+
66
+ # -- Forms --
67
+ def list_forms(self, *, page: int = 1, per_page: int = 60, name: Optional[str] = None) -> FormList:
68
+ m, p, kw = _list_forms_req(page, per_page, name)
69
+ return FormList.model_validate(self._t.request(m, p, **kw))
70
+
71
+ def show_form(self, form_id: int) -> Form:
72
+ return Form.model_validate(self._t.request("GET", f"{_P}/forms/{form_id}"))
73
+
74
+ def update_form(self, form_id: int, **kwargs: Any) -> Form:
75
+ return Form.model_validate(self._t.request("PUT", f"{_P}/forms/{form_id}", json=kwargs))
76
+
77
+ def delete_form(self, form_id: int) -> Dict[str, Any]:
78
+ return self._t.request("DELETE", f"{_P}/forms/{form_id}")
79
+
80
+ def duplicate_form(self, form_id: int) -> Form:
81
+ return Form.model_validate(self._t.request("POST", f"{_P}/forms/{form_id}/duplicate"))
82
+
83
+ def list_form_submissions(self, form_id: int, *, page: int = 1, per_page: int = 10) -> FormSubmissionList:
84
+ return FormSubmissionList.model_validate(
85
+ self._t.request("GET", f"{_P}/forms/{form_id}/submissions",
86
+ params={"page": page, "per_page": per_page}))
87
+
88
+ def create_form_submission(self, form_id: int, *, elements: List[Dict[str, Any]]) -> Dict[str, Any]:
89
+ return self._t.request("POST", f"{_P}/forms/{form_id}/submissions", json={"elements": elements})
90
+
91
+ # -- Community Segments --
92
+ def list_community_segments(self, *, page: int = 1, per_page: int = 60,
93
+ title: Optional[str] = None) -> CommunitySegmentList:
94
+ m, p, kw = _list_community_segments_req(page, per_page, title)
95
+ return CommunitySegmentList.model_validate(self._t.request(m, p, **kw))
96
+
97
+ def create_community_segment(self, **kwargs: Any) -> CommunitySegment:
98
+ return CommunitySegment.model_validate(self._t.request("POST", f"{_P}/community_segments", json=kwargs))
99
+
100
+ def update_community_segment(self, segment_id: int, **kwargs: Any) -> CommunitySegment:
101
+ return CommunitySegment.model_validate(
102
+ self._t.request("PUT", f"{_P}/community_segments/{segment_id}", json=kwargs))
103
+
104
+ def delete_community_segment(self, segment_id: int) -> Dict[str, Any]:
105
+ return self._t.request("DELETE", f"{_P}/community_segments/{segment_id}")
106
+
107
+ def duplicate_community_segment(self, segment_id: int, *, title: str) -> CommunitySegment:
108
+ return CommunitySegment.model_validate(
109
+ self._t.request("POST", f"{_P}/community_segments/{segment_id}/duplicate", params={"title": title}))
110
+
111
+ # -- Invitation Links --
112
+ def list_invitation_links(self, *, page: int = 1, per_page: int = 10, name: Optional[str] = None,
113
+ status: Optional[str] = None) -> InvitationLinkList:
114
+ m, p, kw = _list_invitation_links_req(page, per_page, name, status)
115
+ return InvitationLinkList.model_validate(self._t.request(m, p, **kw))
116
+
117
+ def delete_invitation_link(self, link_id: int) -> Dict[str, Any]:
118
+ return self._t.request("DELETE", f"{_P}/invitation_links/{link_id}")
119
+
120
+ def revoke_invitation_link(self, link_id: int) -> Dict[str, Any]:
121
+ return self._t.request("PATCH", f"{_P}/invitation_links/{link_id}/revoke")
122
+
123
+ # -- Chat Preferences --
124
+ def update_chat_preferences(self, **kwargs: Any) -> ChatPreferences:
125
+ return ChatPreferences.model_validate(self._t.request("PUT", f"{_P}/chat_preferences", json=kwargs))
126
+
127
+ # -- Direct Uploads --
128
+ def create_direct_upload(self, *, blob: Dict[str, Any]) -> DirectUpload:
129
+ return DirectUpload.model_validate(self._t.request("POST", f"{_P}/direct_uploads", json={"blob": blob}))
130
+
131
+ # -- Embeds --
132
+ def create_embed(self, *, url: str) -> Embed:
133
+ return Embed.model_validate(self._t.request("POST", f"{_P}/embeds", json={"url": url}))
134
+
135
+ def get_embed(self, sgid: str) -> Embed:
136
+ return Embed.model_validate(self._t.request("GET", f"{_P}/embeds/{sgid}"))
137
+
138
+ # -- Messages --
139
+ def create_message(self, *, rich_text_body: Dict[str, Any],
140
+ user_email: Optional[str] = None, user_emails: Optional[List[str]] = None) -> Dict[str, Any]:
141
+ body: Dict[str, Any] = {"rich_text_body": rich_text_body}
142
+ if user_email:
143
+ body["user_email"] = user_email
144
+ if user_emails:
145
+ body["user_emails"] = user_emails
146
+ return self._t.request("POST", f"{_P}/messages", json=body)
147
+
148
+ # -- Advanced Search --
149
+ def advanced_search(self, *, query: str, page: int = 1, per_page: int = 20,
150
+ type: Optional[str] = None, **kwargs: Any) -> AdvancedSearchResults:
151
+ m, p, kw = _advanced_search_req(query, page, per_page, type, kwargs)
152
+ return AdvancedSearchResults.model_validate(self._t.request(m, p, **kw))
153
+
154
+ # -- Leaderboard --
155
+ def get_leaderboard(self, *, period: Optional[str] = None) -> List[LeaderboardMember]:
156
+ p: Dict[str, Any] = {}
157
+ if period:
158
+ p["period"] = period
159
+ data = self._t.request("GET", f"{_P}/gamification/leaderboard", params=p)
160
+ return [LeaderboardMember.model_validate(r) for r in data]
161
+
162
+ # -- Flagged Contents --
163
+ def list_flagged_contents(self, *, page: int = 1, per_page: int = 10,
164
+ status: Optional[str] = None) -> FlaggedContentList:
165
+ m, p, kw = _list_flagged_contents_req(page, per_page, status)
166
+ return FlaggedContentList.model_validate(self._t.request(m, p, **kw))
167
+
168
+ def report_flagged_content(self, **kwargs: Any) -> FlaggedContent:
169
+ return FlaggedContent.model_validate(
170
+ self._t.request("POST", f"{_P}/flagged_contents", json={"flagged_content": kwargs}))
171
+
172
+ # -- Live Rooms --
173
+ def list_live_rooms(self, *, page: int = 1, per_page: int = 20) -> LiveRoomList:
174
+ return LiveRoomList.model_validate(
175
+ self._t.request("GET", f"{_P}/live/rooms", params={"page": page, "per_page": per_page}))
176
+
177
+ def list_live_room_transcripts(self, room_id: int) -> Dict[str, Any]:
178
+ return self._t.request("GET", f"{_P}/live/rooms/{room_id}/transcripts")
179
+
180
+
181
+ # ---------------------------------------------------------------------------
182
+ # Async client
183
+ # ---------------------------------------------------------------------------
184
+
185
+ class AsyncAdminMiscClient:
186
+ def __init__(self, transport: AsyncTransport) -> None:
187
+ self._t = transport
188
+
189
+ # -- Forms --
190
+ async def list_forms(self, *, page: int = 1, per_page: int = 60, name: Optional[str] = None) -> FormList:
191
+ m, p, kw = _list_forms_req(page, per_page, name)
192
+ return FormList.model_validate(await self._t.request(m, p, **kw))
193
+
194
+ async def show_form(self, form_id: int) -> Form:
195
+ return Form.model_validate(await self._t.request("GET", f"{_P}/forms/{form_id}"))
196
+
197
+ async def update_form(self, form_id: int, **kwargs: Any) -> Form:
198
+ return Form.model_validate(await self._t.request("PUT", f"{_P}/forms/{form_id}", json=kwargs))
199
+
200
+ async def delete_form(self, form_id: int) -> Dict[str, Any]:
201
+ return await self._t.request("DELETE", f"{_P}/forms/{form_id}")
202
+
203
+ async def duplicate_form(self, form_id: int) -> Form:
204
+ return Form.model_validate(await self._t.request("POST", f"{_P}/forms/{form_id}/duplicate"))
205
+
206
+ async def list_form_submissions(self, form_id: int, *, page: int = 1, per_page: int = 10) -> FormSubmissionList:
207
+ return FormSubmissionList.model_validate(
208
+ await self._t.request("GET", f"{_P}/forms/{form_id}/submissions",
209
+ params={"page": page, "per_page": per_page}))
210
+
211
+ async def create_form_submission(self, form_id: int, *, elements: List[Dict[str, Any]]) -> Dict[str, Any]:
212
+ return await self._t.request("POST", f"{_P}/forms/{form_id}/submissions", json={"elements": elements})
213
+
214
+ # -- Community Segments --
215
+ async def list_community_segments(self, *, page: int = 1, per_page: int = 60,
216
+ title: Optional[str] = None) -> CommunitySegmentList:
217
+ m, p, kw = _list_community_segments_req(page, per_page, title)
218
+ return CommunitySegmentList.model_validate(await self._t.request(m, p, **kw))
219
+
220
+ async def create_community_segment(self, **kwargs: Any) -> CommunitySegment:
221
+ return CommunitySegment.model_validate(
222
+ await self._t.request("POST", f"{_P}/community_segments", json=kwargs))
223
+
224
+ async def update_community_segment(self, segment_id: int, **kwargs: Any) -> CommunitySegment:
225
+ return CommunitySegment.model_validate(
226
+ await self._t.request("PUT", f"{_P}/community_segments/{segment_id}", json=kwargs))
227
+
228
+ async def delete_community_segment(self, segment_id: int) -> Dict[str, Any]:
229
+ return await self._t.request("DELETE", f"{_P}/community_segments/{segment_id}")
230
+
231
+ async def duplicate_community_segment(self, segment_id: int, *, title: str) -> CommunitySegment:
232
+ return CommunitySegment.model_validate(
233
+ await self._t.request("POST", f"{_P}/community_segments/{segment_id}/duplicate",
234
+ params={"title": title}))
235
+
236
+ # -- Invitation Links --
237
+ async def list_invitation_links(self, *, page: int = 1, per_page: int = 10, name: Optional[str] = None,
238
+ status: Optional[str] = None) -> InvitationLinkList:
239
+ m, p, kw = _list_invitation_links_req(page, per_page, name, status)
240
+ return InvitationLinkList.model_validate(await self._t.request(m, p, **kw))
241
+
242
+ async def delete_invitation_link(self, link_id: int) -> Dict[str, Any]:
243
+ return await self._t.request("DELETE", f"{_P}/invitation_links/{link_id}")
244
+
245
+ async def revoke_invitation_link(self, link_id: int) -> Dict[str, Any]:
246
+ return await self._t.request("PATCH", f"{_P}/invitation_links/{link_id}/revoke")
247
+
248
+ # -- Chat Preferences --
249
+ async def update_chat_preferences(self, **kwargs: Any) -> ChatPreferences:
250
+ return ChatPreferences.model_validate(await self._t.request("PUT", f"{_P}/chat_preferences", json=kwargs))
251
+
252
+ # -- Direct Uploads --
253
+ async def create_direct_upload(self, *, blob: Dict[str, Any]) -> DirectUpload:
254
+ return DirectUpload.model_validate(
255
+ await self._t.request("POST", f"{_P}/direct_uploads", json={"blob": blob}))
256
+
257
+ # -- Embeds --
258
+ async def create_embed(self, *, url: str) -> Embed:
259
+ return Embed.model_validate(await self._t.request("POST", f"{_P}/embeds", json={"url": url}))
260
+
261
+ async def get_embed(self, sgid: str) -> Embed:
262
+ return Embed.model_validate(await self._t.request("GET", f"{_P}/embeds/{sgid}"))
263
+
264
+ # -- Messages --
265
+ async def create_message(self, *, rich_text_body: Dict[str, Any],
266
+ user_email: Optional[str] = None,
267
+ user_emails: Optional[List[str]] = None) -> Dict[str, Any]:
268
+ body: Dict[str, Any] = {"rich_text_body": rich_text_body}
269
+ if user_email:
270
+ body["user_email"] = user_email
271
+ if user_emails:
272
+ body["user_emails"] = user_emails
273
+ return await self._t.request("POST", f"{_P}/messages", json=body)
274
+
275
+ # -- Advanced Search --
276
+ async def advanced_search(self, *, query: str, page: int = 1, per_page: int = 20,
277
+ type: Optional[str] = None, **kwargs: Any) -> AdvancedSearchResults:
278
+ m, p, kw = _advanced_search_req(query, page, per_page, type, kwargs)
279
+ return AdvancedSearchResults.model_validate(await self._t.request(m, p, **kw))
280
+
281
+ # -- Leaderboard --
282
+ async def get_leaderboard(self, *, period: Optional[str] = None) -> List[LeaderboardMember]:
283
+ p: Dict[str, Any] = {}
284
+ if period:
285
+ p["period"] = period
286
+ data = await self._t.request("GET", f"{_P}/gamification/leaderboard", params=p)
287
+ return [LeaderboardMember.model_validate(r) for r in data]
288
+
289
+ # -- Flagged Contents --
290
+ async def list_flagged_contents(self, *, page: int = 1, per_page: int = 10,
291
+ status: Optional[str] = None) -> FlaggedContentList:
292
+ m, p, kw = _list_flagged_contents_req(page, per_page, status)
293
+ return FlaggedContentList.model_validate(await self._t.request(m, p, **kw))
294
+
295
+ async def report_flagged_content(self, **kwargs: Any) -> FlaggedContent:
296
+ return FlaggedContent.model_validate(
297
+ await self._t.request("POST", f"{_P}/flagged_contents", json={"flagged_content": kwargs}))
298
+
299
+ # -- Live Rooms --
300
+ async def list_live_rooms(self, *, page: int = 1, per_page: int = 20) -> LiveRoomList:
301
+ return LiveRoomList.model_validate(
302
+ await self._t.request("GET", f"{_P}/live/rooms", params={"page": page, "per_page": per_page}))
303
+
304
+ async def list_live_room_transcripts(self, room_id: int) -> Dict[str, Any]:
305
+ return await self._t.request("GET", f"{_P}/live/rooms/{room_id}/transcripts")
@@ -0,0 +1,200 @@
1
+ """Admin API -- Posts, Comments, Topics."""
2
+ from __future__ import annotations
3
+ from typing import Any, Dict, Optional
4
+ from circle.constants import ADMIN_V2_PREFIX as _P
5
+ from circle.http import AsyncTransport, SyncTransport
6
+ from circle.models.admin.posts import (
7
+ BasicPost, PostList, BasicPostCreatedResponse, BasicPostUpdatedResponse, BasicPostDeletedResponse,
8
+ ImagePost, ImagePostCreatedResponse, AISummary, Comment, CommentList, Topic, TopicList,
9
+ )
10
+
11
+
12
+ def _list_posts_params(page: int, per_page: int, space_id: Optional[int],
13
+ space_group_id: Optional[int], status: Optional[str],
14
+ search_text: Optional[str], sort: Optional[str]) -> Dict[str, Any]:
15
+ p: Dict[str, Any] = {"page": page, "per_page": per_page}
16
+ if space_id: p["space_id"] = space_id
17
+ if space_group_id: p["space_group_id"] = space_group_id
18
+ if status: p["status"] = status
19
+ if search_text: p["search_text"] = search_text
20
+ if sort: p["sort"] = sort
21
+ return p
22
+
23
+
24
+ def _list_comments_params(page: int, per_page: int, space_id: Optional[int],
25
+ post_id: Optional[int], search_text: Optional[str]) -> Dict[str, Any]:
26
+ p: Dict[str, Any] = {"page": page, "per_page": per_page}
27
+ if space_id: p["space_id"] = space_id
28
+ if post_id: p["post_id"] = post_id
29
+ if search_text: p["search_text"] = search_text
30
+ return p
31
+
32
+
33
+ def _list_topics_params(page: int, per_page: int, name: Optional[str],
34
+ sort: Optional[str]) -> Dict[str, Any]:
35
+ p: Dict[str, Any] = {"page": page, "per_page": per_page}
36
+ if name: p["name"] = name
37
+ if sort: p["sort"] = sort
38
+ return p
39
+
40
+
41
+ class PostsClient:
42
+ def __init__(self, transport: SyncTransport) -> None:
43
+ self._t = transport
44
+
45
+ # -- Posts --
46
+ def list_posts(self, *, page: int = 1, per_page: int = 60, space_id: Optional[int] = None,
47
+ space_group_id: Optional[int] = None, status: Optional[str] = None,
48
+ search_text: Optional[str] = None, sort: Optional[str] = None) -> PostList:
49
+ return PostList.model_validate(self._t.request(
50
+ "GET", f"{_P}/posts", params=_list_posts_params(page, per_page, space_id, space_group_id, status, search_text, sort)))
51
+
52
+ def create_post(self, *, space_id: int, name: str, **kwargs: Any) -> BasicPostCreatedResponse:
53
+ return BasicPostCreatedResponse.model_validate(
54
+ self._t.request("POST", f"{_P}/posts", json={"space_id": space_id, "name": name, **kwargs}))
55
+
56
+ def show_post(self, post_id: int) -> BasicPost:
57
+ return BasicPost.model_validate(self._t.request("GET", f"{_P}/posts/{post_id}"))
58
+
59
+ def update_post(self, post_id: int, **kwargs: Any) -> BasicPostUpdatedResponse:
60
+ return BasicPostUpdatedResponse.model_validate(
61
+ self._t.request("PUT", f"{_P}/posts/{post_id}", json=kwargs))
62
+
63
+ def delete_post(self, post_id: int) -> BasicPostDeletedResponse:
64
+ return BasicPostDeletedResponse.model_validate(self._t.request("DELETE", f"{_P}/posts/{post_id}"))
65
+
66
+ def get_post_summary(self, post_id: int) -> AISummary:
67
+ return AISummary.model_validate(self._t.request("GET", f"{_P}/posts/{post_id}/summary"))
68
+
69
+ # -- Image Posts --
70
+ def create_image_post(self, space_id: int, **kwargs: Any) -> ImagePostCreatedResponse:
71
+ return ImagePostCreatedResponse.model_validate(
72
+ self._t.request("POST", f"{_P}/spaces/{space_id}/images/posts", json=kwargs))
73
+
74
+ def delete_image_post(self, space_id: int, post_id: int) -> BasicPostDeletedResponse:
75
+ return BasicPostDeletedResponse.model_validate(
76
+ self._t.request("DELETE", f"{_P}/spaces/{space_id}/images/posts/{post_id}"))
77
+
78
+ def duplicate_image_post(self, space_id: int, post_id: int, **kwargs: Any) -> ImagePostCreatedResponse:
79
+ return ImagePostCreatedResponse.model_validate(
80
+ self._t.request("POST", f"{_P}/spaces/{space_id}/images/posts/{post_id}/duplicate", json=kwargs))
81
+
82
+ # -- Post Followers --
83
+ def unfollow_post(self, post_id: int, *, community_member_id: int) -> Dict[str, Any]:
84
+ return self._t.request("DELETE", f"{_P}/posts/{post_id}/post_followers",
85
+ params={"community_member_id": community_member_id})
86
+
87
+ # -- Comments --
88
+ def list_comments(self, *, page: int = 1, per_page: int = 10, space_id: Optional[int] = None,
89
+ post_id: Optional[int] = None, search_text: Optional[str] = None) -> CommentList:
90
+ return CommentList.model_validate(self._t.request(
91
+ "GET", f"{_P}/comments", params=_list_comments_params(page, per_page, space_id, post_id, search_text)))
92
+
93
+ def create_comment(self, *, body: str, post_id: int, **kwargs: Any) -> Comment:
94
+ return Comment.model_validate(
95
+ self._t.request("POST", f"{_P}/comments", json={"body": body, "post_id": post_id, **kwargs}))
96
+
97
+ def show_comment(self, comment_id: int) -> Comment:
98
+ return Comment.model_validate(self._t.request("GET", f"{_P}/comments/{comment_id}"))
99
+
100
+ def delete_comment(self, comment_id: int) -> Dict[str, Any]:
101
+ return self._t.request("DELETE", f"{_P}/comments/{comment_id}")
102
+
103
+ # -- Topics --
104
+ def list_topics(self, *, page: int = 1, per_page: int = 10, name: Optional[str] = None,
105
+ sort: Optional[str] = None) -> TopicList:
106
+ return TopicList.model_validate(self._t.request(
107
+ "GET", f"{_P}/topics", params=_list_topics_params(page, per_page, name, sort)))
108
+
109
+ def create_topic(self, *, name: str, **kwargs: Any) -> Topic:
110
+ return Topic.model_validate(self._t.request("POST", f"{_P}/topics", json={"name": name, **kwargs}))
111
+
112
+ def show_topic(self, topic_id: int) -> Topic:
113
+ return Topic.model_validate(self._t.request("GET", f"{_P}/topics/{topic_id}"))
114
+
115
+ def update_topic(self, topic_id: int, **kwargs: Any) -> Topic:
116
+ return Topic.model_validate(self._t.request("PUT", f"{_P}/topics/{topic_id}", json=kwargs))
117
+
118
+ def delete_topic(self, topic_id: int) -> Dict[str, Any]:
119
+ return self._t.request("DELETE", f"{_P}/topics/{topic_id}")
120
+
121
+
122
+ class AsyncPostsClient:
123
+ def __init__(self, transport: AsyncTransport) -> None:
124
+ self._t = transport
125
+
126
+ # -- Posts --
127
+ async def list_posts(self, *, page: int = 1, per_page: int = 60, space_id: Optional[int] = None,
128
+ space_group_id: Optional[int] = None, status: Optional[str] = None,
129
+ search_text: Optional[str] = None, sort: Optional[str] = None) -> PostList:
130
+ return PostList.model_validate(await self._t.request(
131
+ "GET", f"{_P}/posts", params=_list_posts_params(page, per_page, space_id, space_group_id, status, search_text, sort)))
132
+
133
+ async def create_post(self, *, space_id: int, name: str, **kwargs: Any) -> BasicPostCreatedResponse:
134
+ return BasicPostCreatedResponse.model_validate(
135
+ await self._t.request("POST", f"{_P}/posts", json={"space_id": space_id, "name": name, **kwargs}))
136
+
137
+ async def show_post(self, post_id: int) -> BasicPost:
138
+ return BasicPost.model_validate(await self._t.request("GET", f"{_P}/posts/{post_id}"))
139
+
140
+ async def update_post(self, post_id: int, **kwargs: Any) -> BasicPostUpdatedResponse:
141
+ return BasicPostUpdatedResponse.model_validate(
142
+ await self._t.request("PUT", f"{_P}/posts/{post_id}", json=kwargs))
143
+
144
+ async def delete_post(self, post_id: int) -> BasicPostDeletedResponse:
145
+ return BasicPostDeletedResponse.model_validate(await self._t.request("DELETE", f"{_P}/posts/{post_id}"))
146
+
147
+ async def get_post_summary(self, post_id: int) -> AISummary:
148
+ return AISummary.model_validate(await self._t.request("GET", f"{_P}/posts/{post_id}/summary"))
149
+
150
+ # -- Image Posts --
151
+ async def create_image_post(self, space_id: int, **kwargs: Any) -> ImagePostCreatedResponse:
152
+ return ImagePostCreatedResponse.model_validate(
153
+ await self._t.request("POST", f"{_P}/spaces/{space_id}/images/posts", json=kwargs))
154
+
155
+ async def delete_image_post(self, space_id: int, post_id: int) -> BasicPostDeletedResponse:
156
+ return BasicPostDeletedResponse.model_validate(
157
+ await self._t.request("DELETE", f"{_P}/spaces/{space_id}/images/posts/{post_id}"))
158
+
159
+ async def duplicate_image_post(self, space_id: int, post_id: int, **kwargs: Any) -> ImagePostCreatedResponse:
160
+ return ImagePostCreatedResponse.model_validate(
161
+ await self._t.request("POST", f"{_P}/spaces/{space_id}/images/posts/{post_id}/duplicate", json=kwargs))
162
+
163
+ # -- Post Followers --
164
+ async def unfollow_post(self, post_id: int, *, community_member_id: int) -> Dict[str, Any]:
165
+ return await self._t.request("DELETE", f"{_P}/posts/{post_id}/post_followers",
166
+ params={"community_member_id": community_member_id})
167
+
168
+ # -- Comments --
169
+ async def list_comments(self, *, page: int = 1, per_page: int = 10, space_id: Optional[int] = None,
170
+ post_id: Optional[int] = None, search_text: Optional[str] = None) -> CommentList:
171
+ return CommentList.model_validate(await self._t.request(
172
+ "GET", f"{_P}/comments", params=_list_comments_params(page, per_page, space_id, post_id, search_text)))
173
+
174
+ async def create_comment(self, *, body: str, post_id: int, **kwargs: Any) -> Comment:
175
+ return Comment.model_validate(
176
+ await self._t.request("POST", f"{_P}/comments", json={"body": body, "post_id": post_id, **kwargs}))
177
+
178
+ async def show_comment(self, comment_id: int) -> Comment:
179
+ return Comment.model_validate(await self._t.request("GET", f"{_P}/comments/{comment_id}"))
180
+
181
+ async def delete_comment(self, comment_id: int) -> Dict[str, Any]:
182
+ return await self._t.request("DELETE", f"{_P}/comments/{comment_id}")
183
+
184
+ # -- Topics --
185
+ async def list_topics(self, *, page: int = 1, per_page: int = 10, name: Optional[str] = None,
186
+ sort: Optional[str] = None) -> TopicList:
187
+ return TopicList.model_validate(await self._t.request(
188
+ "GET", f"{_P}/topics", params=_list_topics_params(page, per_page, name, sort)))
189
+
190
+ async def create_topic(self, *, name: str, **kwargs: Any) -> Topic:
191
+ return Topic.model_validate(await self._t.request("POST", f"{_P}/topics", json={"name": name, **kwargs}))
192
+
193
+ async def show_topic(self, topic_id: int) -> Topic:
194
+ return Topic.model_validate(await self._t.request("GET", f"{_P}/topics/{topic_id}"))
195
+
196
+ async def update_topic(self, topic_id: int, **kwargs: Any) -> Topic:
197
+ return Topic.model_validate(await self._t.request("PUT", f"{_P}/topics/{topic_id}", json=kwargs))
198
+
199
+ async def delete_topic(self, topic_id: int) -> Dict[str, Any]:
200
+ return await self._t.request("DELETE", f"{_P}/topics/{topic_id}")