Skip to content

Commit f552d7e

Browse files
authored
feat: regenerate SDK from latest chat OpenAPI spec (#269)
Regenerate the chat, common, feeds, moderation, and video clients and their models from the current chat OpenAPI spec. New endpoints: moderation.analyze, .bulk_action_appeals, .get_setup_session, .upsert_setup_session; feeds.get_or_create_follow, .get_or_create_unfollow, .get_user_interests; chat.create_segment, .update_segment, .add_segment_targets; common.cancel_import_v2_task; video.report_client_call_event. Plus the new moderation.image_analysis.complete and moderation.text_analysis.complete webhook events. Resolves an upstream OpenAPI name collision: FlagResponse now maps to the full flag record, and the moderation flag-action acknowledgement (item_id, duration) moves to the new FlagItemResponse, which moderation.flag() now returns. The /api/v2/moderation/flag wire response is unchanged. Matches the same changeset already shipped in getstream-php v7.4.0; released as a minor bump.
1 parent 97c27cc commit f552d7e

14 files changed

Lines changed: 1642 additions & 57 deletions

CHANGELOG.md

Lines changed: 22 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -70,6 +70,15 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
7070
- Conformance fixture suite under `tests/fixtures/webhooks/` (13 happy-path
7171
event directories + 8 negative cases) for SDK conformance testing across
7272
language ports.
73+
- Regenerated from the latest chat OpenAPI spec. New endpoints: `moderation.analyze`,
74+
`moderation.bulk_action_appeals`, `moderation.get_setup_session`,
75+
`moderation.upsert_setup_session`; `feeds.get_or_create_follow`,
76+
`feeds.get_or_create_unfollow`, `feeds.get_user_interests`; `chat.create_segment`,
77+
`chat.update_segment`, `chat.add_segment_targets`; `common.cancel_import_v2_task`;
78+
`video.report_client_call_event`, together with the request/response models backing them.
79+
- New webhook event types `moderation.image_analysis.complete` and
80+
`moderation.text_analysis.complete`, with `ModerationImageAnalysisCompleteEvent`
81+
and `ModerationTextAnalysisCompleteEvent` models.
7382

7483
### Changed
7584

@@ -82,6 +91,19 @@ and this project adheres to [Semantic Versioning](https://semver.org/spec/v2.0.0
8291
- Default HTTP transport now caps connections per host at `5` and closes idle sockets after `55.0s`. Previous default was httpx's `100` max-connections with `5.0s` keep-alive expiry.
8392
- No breaking changes. All existing webhook helpers (`verify_webhook_signature`,
8493
`parse_webhook_event`, `get_event_type`, event type constants) are preserved.
94+
- `FlagResponse` now represents the full flag record (`created_at`, `updated_at`,
95+
`target_message`, `target_user`, `user`, `reason`, `details`, `custom`, and related
96+
fields). The moderation flag-action acknowledgement, which carries `item_id` and
97+
`duration`, moved to the new `FlagItemResponse`; `moderation.flag()` now returns
98+
`FlagItemResponse`. The `/api/v2/moderation/flag` wire response is unchanged, so code
99+
reading `item_id`/`duration` off the parsed response is unaffected. Code referencing
100+
the `FlagResponse` type for those two fields should switch to `FlagItemResponse`.
101+
- `ChannelInput.config_overrides` and `ChannelDataUpdate.config_overrides` are now typed
102+
as `ChannelConfigOverrides` (the override-specific field set) instead of `ChannelConfig`.
103+
- `enabled` on `DeliveryReceiptsResponse`, `ReadReceiptsResponse`, and
104+
`TypingIndicatorsResponse` is now a required `bool` (was `Optional[bool]`).
105+
- `LLMRule.description`, `TargetResolution.bitrate`, and `TranslationSettings.languages` /
106+
`TranslationSettings.enabled` are now optional.
85107

86108
### Deprecated
87109

getstream/chat/async_rest_client.py

Lines changed: 62 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -282,10 +282,11 @@ async def grouped_query_channels(
282282
self,
283283
limit: Optional[int] = None,
284284
user_id: Optional[str] = None,
285+
groups: Optional[Dict[str, GroupedChannelsGroupRequest]] = None,
285286
user: Optional[UserRequest] = None,
286287
) -> StreamResponse[GroupedQueryChannelsResponse]:
287288
json = GroupedQueryChannelsRequest(
288-
limit=limit, user_id=user_id, user=user
289+
limit=limit, user_id=user_id, groups=groups, user=user
289290
).to_dict()
290291
return await self.post(
291292
"/api/v2/chat/channels/grouped", GroupedQueryChannelsResponse, json=json
@@ -1657,6 +1658,30 @@ async def search(
16571658
"/api/v2/chat/search", SearchResponse, query_params=query_params
16581659
)
16591660

1661+
@telemetry.operation_name("getstream.api.chat.create_segment")
1662+
async def create_segment(
1663+
self,
1664+
type: str,
1665+
all_sender_channels: Optional[bool] = None,
1666+
all_users: Optional[bool] = None,
1667+
description: Optional[str] = None,
1668+
id: Optional[str] = None,
1669+
name: Optional[str] = None,
1670+
filter: Optional[Dict[str, object]] = None,
1671+
) -> StreamResponse[CreateSegmentResponse]:
1672+
json = CreateSegmentRequest(
1673+
type=type,
1674+
all_sender_channels=all_sender_channels,
1675+
all_users=all_users,
1676+
description=description,
1677+
id=id,
1678+
name=name,
1679+
filter=filter,
1680+
).to_dict()
1681+
return await self.post(
1682+
"/api/v2/chat/segments", CreateSegmentResponse, json=json
1683+
)
1684+
16601685
@telemetry.operation_name("getstream.api.chat.query_segments")
16611686
async def query_segments(
16621687
self,
@@ -1691,6 +1716,42 @@ async def get_segment(self, id: str) -> StreamResponse[GetSegmentResponse]:
16911716
"/api/v2/chat/segments/{id}", GetSegmentResponse, path_params=path_params
16921717
)
16931718

1719+
@telemetry.operation_name("getstream.api.chat.update_segment")
1720+
async def update_segment(
1721+
self,
1722+
id: str,
1723+
description: Optional[str] = None,
1724+
name: Optional[str] = None,
1725+
filter: Optional[Dict[str, object]] = None,
1726+
) -> StreamResponse[UpdateSegmentResponse]:
1727+
path_params = {
1728+
"id": id,
1729+
}
1730+
json = UpdateSegmentRequest(
1731+
description=description, name=name, filter=filter
1732+
).to_dict()
1733+
return await self.put(
1734+
"/api/v2/chat/segments/{id}",
1735+
UpdateSegmentResponse,
1736+
path_params=path_params,
1737+
json=json,
1738+
)
1739+
1740+
@telemetry.operation_name("getstream.api.chat.add_segment_targets")
1741+
async def add_segment_targets(
1742+
self, id: str, target_ids: List[str]
1743+
) -> StreamResponse[Response]:
1744+
path_params = {
1745+
"id": id,
1746+
}
1747+
json = AddSegmentTargetsRequest(target_ids=target_ids).to_dict()
1748+
return await self.post(
1749+
"/api/v2/chat/segments/{id}/addtargets",
1750+
Response,
1751+
path_params=path_params,
1752+
json=json,
1753+
)
1754+
16941755
@telemetry.operation_name("getstream.api.chat.delete_segment_targets")
16951756
async def delete_segment_targets(
16961757
self, id: str, target_ids: List[str]

getstream/chat/rest_client.py

Lines changed: 60 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -278,10 +278,11 @@ def grouped_query_channels(
278278
self,
279279
limit: Optional[int] = None,
280280
user_id: Optional[str] = None,
281+
groups: Optional[Dict[str, GroupedChannelsGroupRequest]] = None,
281282
user: Optional[UserRequest] = None,
282283
) -> StreamResponse[GroupedQueryChannelsResponse]:
283284
json = GroupedQueryChannelsRequest(
284-
limit=limit, user_id=user_id, user=user
285+
limit=limit, user_id=user_id, groups=groups, user=user
285286
).to_dict()
286287
return self.post(
287288
"/api/v2/chat/channels/grouped", GroupedQueryChannelsResponse, json=json
@@ -1643,6 +1644,28 @@ def search(
16431644
"/api/v2/chat/search", SearchResponse, query_params=query_params
16441645
)
16451646

1647+
@telemetry.operation_name("getstream.api.chat.create_segment")
1648+
def create_segment(
1649+
self,
1650+
type: str,
1651+
all_sender_channels: Optional[bool] = None,
1652+
all_users: Optional[bool] = None,
1653+
description: Optional[str] = None,
1654+
id: Optional[str] = None,
1655+
name: Optional[str] = None,
1656+
filter: Optional[Dict[str, object]] = None,
1657+
) -> StreamResponse[CreateSegmentResponse]:
1658+
json = CreateSegmentRequest(
1659+
type=type,
1660+
all_sender_channels=all_sender_channels,
1661+
all_users=all_users,
1662+
description=description,
1663+
id=id,
1664+
name=name,
1665+
filter=filter,
1666+
).to_dict()
1667+
return self.post("/api/v2/chat/segments", CreateSegmentResponse, json=json)
1668+
16461669
@telemetry.operation_name("getstream.api.chat.query_segments")
16471670
def query_segments(
16481671
self,
@@ -1677,6 +1700,42 @@ def get_segment(self, id: str) -> StreamResponse[GetSegmentResponse]:
16771700
"/api/v2/chat/segments/{id}", GetSegmentResponse, path_params=path_params
16781701
)
16791702

1703+
@telemetry.operation_name("getstream.api.chat.update_segment")
1704+
def update_segment(
1705+
self,
1706+
id: str,
1707+
description: Optional[str] = None,
1708+
name: Optional[str] = None,
1709+
filter: Optional[Dict[str, object]] = None,
1710+
) -> StreamResponse[UpdateSegmentResponse]:
1711+
path_params = {
1712+
"id": id,
1713+
}
1714+
json = UpdateSegmentRequest(
1715+
description=description, name=name, filter=filter
1716+
).to_dict()
1717+
return self.put(
1718+
"/api/v2/chat/segments/{id}",
1719+
UpdateSegmentResponse,
1720+
path_params=path_params,
1721+
json=json,
1722+
)
1723+
1724+
@telemetry.operation_name("getstream.api.chat.add_segment_targets")
1725+
def add_segment_targets(
1726+
self, id: str, target_ids: List[str]
1727+
) -> StreamResponse[Response]:
1728+
path_params = {
1729+
"id": id,
1730+
}
1731+
json = AddSegmentTargetsRequest(target_ids=target_ids).to_dict()
1732+
return self.post(
1733+
"/api/v2/chat/segments/{id}/addtargets",
1734+
Response,
1735+
path_params=path_params,
1736+
json=json,
1737+
)
1738+
16801739
@telemetry.operation_name("getstream.api.chat.delete_segment_targets")
16811740
def delete_segment_targets(
16821741
self, id: str, target_ids: List[str]

getstream/common/async_rest_client.py

Lines changed: 29 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -40,6 +40,7 @@ async def update_app(
4040
self,
4141
async_url_enrich_enabled: Optional[bool] = None,
4242
auto_translation_enabled: Optional[bool] = None,
43+
before_message_send_hook_attempt_timeout_ms: Optional[int] = None,
4344
before_message_send_hook_url: Optional[str] = None,
4445
cdn_expiration_seconds: Optional[int] = None,
4546
channel_hide_members_only: Optional[bool] = None,
@@ -56,6 +57,7 @@ async def update_app(
5657
migrate_permissions_to_v2: Optional[bool] = None,
5758
moderation_analytics_enabled: Optional[bool] = None,
5859
moderation_enabled: Optional[bool] = None,
60+
moderation_onboarding_complete: Optional[bool] = None,
5961
moderation_s3_image_access_role_arn: Optional[str] = None,
6062
moderation_webhook_url: Optional[str] = None,
6163
multi_tenant_enabled: Optional[bool] = None,
@@ -70,6 +72,7 @@ async def update_app(
7072
sqs_secret: Optional[str] = None,
7173
sqs_url: Optional[str] = None,
7274
user_response_time_enabled: Optional[bool] = None,
75+
video_primary_use_case: Optional[str] = None,
7376
webhook_url: Optional[str] = None,
7477
allowed_flag_reasons: Optional[List[str]] = None,
7578
event_hooks: Optional[List[EventHook]] = None,
@@ -95,6 +98,7 @@ async def update_app(
9598
json = UpdateAppRequest(
9699
async_url_enrich_enabled=async_url_enrich_enabled,
97100
auto_translation_enabled=auto_translation_enabled,
101+
before_message_send_hook_attempt_timeout_ms=before_message_send_hook_attempt_timeout_ms,
98102
before_message_send_hook_url=before_message_send_hook_url,
99103
cdn_expiration_seconds=cdn_expiration_seconds,
100104
channel_hide_members_only=channel_hide_members_only,
@@ -111,6 +115,7 @@ async def update_app(
111115
migrate_permissions_to_v2=migrate_permissions_to_v2,
112116
moderation_analytics_enabled=moderation_analytics_enabled,
113117
moderation_enabled=moderation_enabled,
118+
moderation_onboarding_complete=moderation_onboarding_complete,
114119
moderation_s3_image_access_role_arn=moderation_s3_image_access_role_arn,
115120
moderation_webhook_url=moderation_webhook_url,
116121
multi_tenant_enabled=multi_tenant_enabled,
@@ -125,6 +130,7 @@ async def update_app(
125130
sqs_secret=sqs_secret,
126131
sqs_url=sqs_url,
127132
user_response_time_enabled=user_response_time_enabled,
133+
video_primary_use_case=video_primary_use_case,
128134
webhook_url=webhook_url,
129135
allowed_flag_reasons=allowed_flag_reasons,
130136
event_hooks=event_hooks,
@@ -161,16 +167,20 @@ async def create_block_list(
161167
self,
162168
name: str,
163169
words: List[str],
170+
is_confusable_folding_enabled: Optional[bool] = None,
164171
is_leet_check_enabled: Optional[bool] = None,
165172
is_plural_check_enabled: Optional[bool] = None,
173+
is_substring_matching_enabled: Optional[bool] = None,
166174
team: Optional[str] = None,
167175
type: Optional[str] = None,
168176
) -> StreamResponse[CreateBlockListResponse]:
169177
json = CreateBlockListRequest(
170178
name=name,
171179
words=words,
180+
is_confusable_folding_enabled=is_confusable_folding_enabled,
172181
is_leet_check_enabled=is_leet_check_enabled,
173182
is_plural_check_enabled=is_plural_check_enabled,
183+
is_substring_matching_enabled=is_substring_matching_enabled,
174184
team=team,
175185
type=type,
176186
).to_dict()
@@ -210,17 +220,21 @@ async def get_block_list(
210220
async def update_block_list(
211221
self,
212222
name: str,
223+
is_confusable_folding_enabled: Optional[bool] = None,
213224
is_leet_check_enabled: Optional[bool] = None,
214225
is_plural_check_enabled: Optional[bool] = None,
226+
is_substring_matching_enabled: Optional[bool] = None,
215227
team: Optional[str] = None,
216228
words: Optional[List[str]] = None,
217229
) -> StreamResponse[UpdateBlockListResponse]:
218230
path_params = {
219231
"name": name,
220232
}
221233
json = UpdateBlockListRequest(
234+
is_confusable_folding_enabled=is_confusable_folding_enabled,
222235
is_leet_check_enabled=is_leet_check_enabled,
223236
is_plural_check_enabled=is_plural_check_enabled,
237+
is_substring_matching_enabled=is_substring_matching_enabled,
224238
team=team,
225239
words=words,
226240
).to_dict()
@@ -304,6 +318,7 @@ async def create_device(
304318
self,
305319
id: str,
306320
push_provider: str,
321+
hardware_id: Optional[str] = None,
307322
push_provider_name: Optional[str] = None,
308323
user_id: Optional[str] = None,
309324
voip_token: Optional[bool] = None,
@@ -312,6 +327,7 @@ async def create_device(
312327
json = CreateDeviceRequest(
313328
id=id,
314329
push_provider=push_provider,
330+
hardware_id=hardware_id,
315331
push_provider_name=push_provider_name,
316332
user_id=user_id,
317333
voip_token=voip_token,
@@ -524,6 +540,19 @@ async def get_import_v2_task(
524540
"/api/v2/imports/v2/{id}", GetImportV2TaskResponse, path_params=path_params
525541
)
526542

543+
@telemetry.operation_name("getstream.api.common.cancel_import_v2_task")
544+
async def cancel_import_v2_task(
545+
self, id: str
546+
) -> StreamResponse[CancelImportV2TaskResponse]:
547+
path_params = {
548+
"id": id,
549+
}
550+
return await self.post(
551+
"/api/v2/imports/v2/{id}/cancel",
552+
CancelImportV2TaskResponse,
553+
path_params=path_params,
554+
)
555+
527556
@telemetry.operation_name("getstream.api.common.get_import")
528557
async def get_import(self, id: str) -> StreamResponse[GetImportResponse]:
529558
path_params = {

0 commit comments

Comments
 (0)