diff --git a/getstream/chat/async_channel.py b/getstream/chat/async_channel.py index c77204fb..c9a24e01 100644 --- a/getstream/chat/async_channel.py +++ b/getstream/chat/async_channel.py @@ -9,7 +9,7 @@ def __init__( self, client, channel_type: str, - channel_id: str | None = None, + channel_id: str = None, custom_data: Dict = None, ): self.channel_id = channel_id diff --git a/getstream/chat/async_rest_client.py b/getstream/chat/async_rest_client.py index d06634ca..1162e6a6 100644 --- a/getstream/chat/async_rest_client.py +++ b/getstream/chat/async_rest_client.py @@ -13,7 +13,7 @@ def __init__( base_url: str, timeout: float, token: str, - user_agent: str | None = None, + user_agent: str = None, ): """ Initializes ChatClient with BaseClient instance @@ -243,11 +243,18 @@ async def channel_batch_update( self, operation: str, filter: Dict[str, object], + custom_unset: Optional[List[str]] = None, members: Optional[List[ChannelBatchMemberRequest]] = None, + custom_set: Optional[Dict[str, object]] = None, data: Optional[ChannelDataUpdate] = None, ) -> StreamResponse[ChannelBatchUpdateResponse]: json = ChannelBatchUpdateRequest( - operation=operation, filter=filter, members=members, data=data + operation=operation, + filter=filter, + custom_unset=custom_unset, + members=members, + custom_set=custom_set, + data=data, ).to_dict() return await self.put( "/api/v2/chat/channels/batch", ChannelBatchUpdateResponse, json=json @@ -1465,14 +1472,14 @@ async def query_reactions( @telemetry.operation_name("getstream.api.chat.translate_message") async def translate_message( self, id: str, language: str - ) -> StreamResponse[MessageActionResponse]: + ) -> StreamResponse[TranslateMessageResponse]: path_params = { "id": id, } json = TranslateMessageRequest(language=language).to_dict() return await self.post( "/api/v2/chat/messages/{id}/translate", - MessageActionResponse, + TranslateMessageResponse, path_params=path_params, json=json, ) @@ -1573,7 +1580,7 @@ async def create_reminder( remind_at: Optional[datetime] = None, user_id: Optional[str] = None, user: Optional[UserRequest] = None, - ) -> StreamResponse[ReminderResponseData]: + ) -> StreamResponse[CreateReminderResponse]: path_params = { "message_id": message_id, } @@ -1582,7 +1589,7 @@ async def create_reminder( ).to_dict() return await self.post( "/api/v2/chat/messages/{message_id}/reminders", - ReminderResponseData, + CreateReminderResponse, path_params=path_params, json=json, ) diff --git a/getstream/chat/channel.py b/getstream/chat/channel.py index af24273e..c3974a28 100644 --- a/getstream/chat/channel.py +++ b/getstream/chat/channel.py @@ -9,7 +9,7 @@ def __init__( self, client, channel_type: str, - channel_id: str | None = None, + channel_id: str = None, custom_data: Dict = None, ): self.channel_id = channel_id diff --git a/getstream/chat/rest_client.py b/getstream/chat/rest_client.py index 79cdee20..c20a4b48 100644 --- a/getstream/chat/rest_client.py +++ b/getstream/chat/rest_client.py @@ -13,7 +13,7 @@ def __init__( base_url: str, timeout: float, token: str, - user_agent: str | None = None, + user_agent: str = None, ): """ Initializes ChatClient with BaseClient instance @@ -239,11 +239,18 @@ def channel_batch_update( self, operation: str, filter: Dict[str, object], + custom_unset: Optional[List[str]] = None, members: Optional[List[ChannelBatchMemberRequest]] = None, + custom_set: Optional[Dict[str, object]] = None, data: Optional[ChannelDataUpdate] = None, ) -> StreamResponse[ChannelBatchUpdateResponse]: json = ChannelBatchUpdateRequest( - operation=operation, filter=filter, members=members, data=data + operation=operation, + filter=filter, + custom_unset=custom_unset, + members=members, + custom_set=custom_set, + data=data, ).to_dict() return self.put( "/api/v2/chat/channels/batch", ChannelBatchUpdateResponse, json=json @@ -1453,14 +1460,14 @@ def query_reactions( @telemetry.operation_name("getstream.api.chat.translate_message") def translate_message( self, id: str, language: str - ) -> StreamResponse[MessageActionResponse]: + ) -> StreamResponse[TranslateMessageResponse]: path_params = { "id": id, } json = TranslateMessageRequest(language=language).to_dict() return self.post( "/api/v2/chat/messages/{id}/translate", - MessageActionResponse, + TranslateMessageResponse, path_params=path_params, json=json, ) @@ -1561,7 +1568,7 @@ def create_reminder( remind_at: Optional[datetime] = None, user_id: Optional[str] = None, user: Optional[UserRequest] = None, - ) -> StreamResponse[ReminderResponseData]: + ) -> StreamResponse[CreateReminderResponse]: path_params = { "message_id": message_id, } @@ -1570,7 +1577,7 @@ def create_reminder( ).to_dict() return self.post( "/api/v2/chat/messages/{message_id}/reminders", - ReminderResponseData, + CreateReminderResponse, path_params=path_params, json=json, ) diff --git a/getstream/common/async_rest_client.py b/getstream/common/async_rest_client.py index d5348240..2f7881cc 100644 --- a/getstream/common/async_rest_client.py +++ b/getstream/common/async_rest_client.py @@ -13,7 +13,7 @@ def __init__( base_url: str, timeout: float, token: str, - user_agent: str | None = None, + user_agent: str = None, ): """ Initializes CommonClient with BaseClient instance @@ -56,7 +56,9 @@ async def update_app( guest_user_creation_disabled: Optional[bool] = None, image_moderation_enabled: Optional[bool] = None, max_aggregated_activities_length: Optional[int] = None, + member_custom_on_mentioned_users_enabled: Optional[bool] = None, member_custom_on_messages_enabled: Optional[bool] = None, + member_custom_on_typing_events_enabled: Optional[bool] = None, migrate_permissions_to_v2: Optional[bool] = None, moderation_analytics_enabled: Optional[bool] = None, moderation_enabled: Optional[bool] = None, @@ -118,7 +120,9 @@ async def update_app( guest_user_creation_disabled=guest_user_creation_disabled, image_moderation_enabled=image_moderation_enabled, max_aggregated_activities_length=max_aggregated_activities_length, + member_custom_on_mentioned_users_enabled=member_custom_on_mentioned_users_enabled, member_custom_on_messages_enabled=member_custom_on_messages_enabled, + member_custom_on_typing_events_enabled=member_custom_on_typing_events_enabled, migrate_permissions_to_v2=migrate_permissions_to_v2, moderation_analytics_enabled=moderation_analytics_enabled, moderation_enabled=moderation_enabled, diff --git a/getstream/common/rest_client.py b/getstream/common/rest_client.py index 50e94f91..1003add8 100644 --- a/getstream/common/rest_client.py +++ b/getstream/common/rest_client.py @@ -13,7 +13,7 @@ def __init__( base_url: str, timeout: float, token: str, - user_agent: str | None = None, + user_agent: str = None, ): """ Initializes CommonClient with BaseClient instance @@ -56,7 +56,9 @@ def update_app( guest_user_creation_disabled: Optional[bool] = None, image_moderation_enabled: Optional[bool] = None, max_aggregated_activities_length: Optional[int] = None, + member_custom_on_mentioned_users_enabled: Optional[bool] = None, member_custom_on_messages_enabled: Optional[bool] = None, + member_custom_on_typing_events_enabled: Optional[bool] = None, migrate_permissions_to_v2: Optional[bool] = None, moderation_analytics_enabled: Optional[bool] = None, moderation_enabled: Optional[bool] = None, @@ -118,7 +120,9 @@ def update_app( guest_user_creation_disabled=guest_user_creation_disabled, image_moderation_enabled=image_moderation_enabled, max_aggregated_activities_length=max_aggregated_activities_length, + member_custom_on_mentioned_users_enabled=member_custom_on_mentioned_users_enabled, member_custom_on_messages_enabled=member_custom_on_messages_enabled, + member_custom_on_typing_events_enabled=member_custom_on_typing_events_enabled, migrate_permissions_to_v2=migrate_permissions_to_v2, moderation_analytics_enabled=moderation_analytics_enabled, moderation_enabled=moderation_enabled, diff --git a/getstream/feeds/rest_client.py b/getstream/feeds/rest_client.py index 33469a2e..97f8a127 100644 --- a/getstream/feeds/rest_client.py +++ b/getstream/feeds/rest_client.py @@ -13,7 +13,7 @@ def __init__( base_url: str, timeout: float, token: str, - user_agent: str | None = None, + user_agent: str = None, ): """ Initializes FeedsClient with BaseClient instance @@ -1323,10 +1323,12 @@ def list_feed_groups( def create_feed_group( self, id: str, + default_follower_role: Optional[str] = None, default_visibility: Optional[str] = None, activity_processors: Optional[List[ActivityProcessorConfig]] = None, activity_selectors: Optional[List[ActivitySelectorConfig]] = None, activity_filter: Optional[ActivityFilterConfig] = None, + activity_processing: Optional[ActivityProcessingConfig] = None, aggregation: Optional[AggregationConfig] = None, custom: Optional[Dict[str, object]] = None, notification: Optional[NotificationConfig] = None, @@ -1336,10 +1338,12 @@ def create_feed_group( ) -> StreamResponse[CreateFeedGroupResponse]: json = CreateFeedGroupRequest( id=id, + default_follower_role=default_follower_role, default_visibility=default_visibility, activity_processors=activity_processors, activity_selectors=activity_selectors, activity_filter=activity_filter, + activity_processing=activity_processing, aggregation=aggregation, custom=custom, notification=notification, @@ -1779,10 +1783,12 @@ def get_feed_group( def get_or_create_feed_group( self, id: str, + default_follower_role: Optional[str] = None, default_visibility: Optional[str] = None, activity_processors: Optional[List[ActivityProcessorConfig]] = None, activity_selectors: Optional[List[ActivitySelectorConfig]] = None, activity_filter: Optional[ActivityFilterConfig] = None, + activity_processing: Optional[ActivityProcessingConfig] = None, aggregation: Optional[AggregationConfig] = None, custom: Optional[Dict[str, object]] = None, notification: Optional[NotificationConfig] = None, @@ -1794,10 +1800,12 @@ def get_or_create_feed_group( "id": id, } json = GetOrCreateFeedGroupRequest( + default_follower_role=default_follower_role, default_visibility=default_visibility, activity_processors=activity_processors, activity_selectors=activity_selectors, activity_filter=activity_filter, + activity_processing=activity_processing, aggregation=aggregation, custom=custom, notification=notification, @@ -1816,10 +1824,12 @@ def get_or_create_feed_group( def update_feed_group( self, id: str, + default_follower_role: Optional[str] = None, default_visibility: Optional[str] = None, activity_processors: Optional[List[ActivityProcessorConfig]] = None, activity_selectors: Optional[List[ActivitySelectorConfig]] = None, activity_filter: Optional[ActivityFilterConfig] = None, + activity_processing: Optional[ActivityProcessingConfig] = None, aggregation: Optional[AggregationConfig] = None, custom: Optional[Dict[str, object]] = None, notification: Optional[NotificationConfig] = None, @@ -1831,10 +1841,12 @@ def update_feed_group( "id": id, } json = UpdateFeedGroupRequest( + default_follower_role=default_follower_role, default_visibility=default_visibility, activity_processors=activity_processors, activity_selectors=activity_selectors, activity_filter=activity_filter, + activity_processing=activity_processing, aggregation=aggregation, custom=custom, notification=notification, @@ -1971,10 +1983,13 @@ def update_feed_visibility( @telemetry.operation_name("getstream.api.feeds.create_feeds_batch") def create_feeds_batch( - self, feeds: List[FeedRequest], enrich_own_fields: Optional[bool] = None + self, + feeds: List[FeedRequest], + create_users: Optional[bool] = None, + enrich_own_fields: Optional[bool] = None, ) -> StreamResponse[CreateFeedsBatchResponse]: json = CreateFeedsBatchRequest( - feeds=feeds, enrich_own_fields=enrich_own_fields + feeds=feeds, create_users=create_users, enrich_own_fields=enrich_own_fields ).to_dict() return self.post( "/api/v2/feeds/feeds/batch", CreateFeedsBatchResponse, json=json diff --git a/getstream/models/__init__.py b/getstream/models/__init__.py index 2efc3bb0..86e33507 100644 --- a/getstream/models/__init__.py +++ b/getstream/models/__init__.py @@ -2,7 +2,7 @@ from dataclasses import dataclass from dataclasses import field as dc_field from datetime import datetime -from typing import Dict, Final, List, NewType, Optional # noqa: F401, UP035 +from typing import Dict, Final, List, NewType, Optional from dataclasses_json import DataClassJsonMixin from dataclasses_json import config as dc_config @@ -69,6 +69,20 @@ class AITextConfig(DataClassJsonMixin): @dataclass class AIVideoConfig(DataClassJsonMixin): + _async: bool | None = dc_field(default=None, metadata=dc_config(field_name="async")) + enabled: bool | None = dc_field( + default=None, metadata=dc_config(field_name="enabled") + ) + provider: str | None = dc_field( + default=None, metadata=dc_config(field_name="provider") + ) + rules: "list[AWSRekognitionRule] | None" = dc_field( + default=None, metadata=dc_config(field_name="rules") + ) + + +@dataclass +class AIVideoConfigRequest(DataClassJsonMixin): _async: bool | None = dc_field(default=None, metadata=dc_config(field_name="async")) enabled: bool | None = dc_field( default=None, metadata=dc_config(field_name="enabled") @@ -78,6 +92,13 @@ class AIVideoConfig(DataClassJsonMixin): ) +@dataclass +class AIVideoConfigResponse(DataClassJsonMixin): + enabled: bool = dc_field(metadata=dc_config(field_name="enabled")) + rules: "list[AWSRekognitionRule]" = dc_field(metadata=dc_config(field_name="rules")) + _async: bool | None = dc_field(default=None, metadata=dc_config(field_name="async")) + + @dataclass class APIError(DataClassJsonMixin): # API error code @@ -229,7 +250,7 @@ class AcceptFollowRequest(DataClassJsonMixin): source: str = dc_field(metadata=dc_config(field_name="source")) # Fully qualified ID of the target feed target: str = dc_field(metadata=dc_config(field_name="target")) - # Optional role for the follower in the follow relationship + # Optional role for the follower in the follow relationship. Server-side only. Either a built-in ('feed_follower' (the default) or 'feed_member_viewer') or any role your app has defined; grants are not inspected. follower_role: str | None = dc_field( default=None, metadata=dc_config(field_name="follower_role") ) @@ -649,6 +670,18 @@ class ActivityPinnedEvent(DataClassJsonMixin): ) +@dataclass +class ActivityProcessingConfig(DataClassJsonMixin): + # When set, the LLM activity processors may only write interest tags from this list. Tags are matched literally after lower-casing and trimming, so a generic vocabulary matches more often than in-house terms. Mutually exclusive with blocked_tags. + allowed_tags: list[str] | None = dc_field( + default=None, metadata=dc_config(field_name="allowed_tags") + ) + # Interest tags the LLM activity processors are never allowed to write. Mutually exclusive with allowed_tags. + blocked_tags: list[str] | None = dc_field( + default=None, metadata=dc_config(field_name="blocked_tags") + ) + + @dataclass class ActivityProcessorConfig(DataClassJsonMixin): # Type of activity processor (required) @@ -1830,7 +1863,7 @@ class AnalyzeRequest(DataClassJsonMixin): @dataclass class AnalyzeResponse(DataClassJsonMixin): duration: str = dc_field(metadata=dc_config(field_name="duration")) - # Always `complete` — /analyze is sync-only and the full verdict is in the response. + # `complete` (all fields screened), `partial` (mix of verdicts and per-field errors), or `pending` (async). status: str = dc_field(metadata=dc_config(field_name="status")) # Per-image moderation verdicts keyed by caller label. images: "dict[str, AnalyzeImageField] | None" = dc_field( @@ -1904,15 +1937,24 @@ class AppResponseFields(DataClassJsonMixin): max_aggregated_activities_length: int = dc_field( metadata=dc_config(field_name="max_aggregated_activities_length") ) + member_custom_on_mentioned_users_enabled: bool = dc_field( + metadata=dc_config(field_name="member_custom_on_mentioned_users_enabled") + ) member_custom_on_messages_enabled: bool = dc_field( metadata=dc_config(field_name="member_custom_on_messages_enabled") ) + member_custom_on_typing_events_enabled: bool = dc_field( + metadata=dc_config(field_name="member_custom_on_typing_events_enabled") + ) moderation_audio_call_moderation_enabled: bool = dc_field( metadata=dc_config(field_name="moderation_audio_call_moderation_enabled") ) moderation_enabled: bool = dc_field( metadata=dc_config(field_name="moderation_enabled") ) + moderation_keyframe_video_enabled: bool = dc_field( + metadata=dc_config(field_name="moderation_keyframe_video_enabled") + ) moderation_llm_configurability_enabled: bool = dc_field( metadata=dc_config(field_name="moderation_llm_configurability_enabled") ) @@ -2357,7 +2399,8 @@ class AsyncExportErrorEvent(DataClassJsonMixin): task_id: str = dc_field(metadata=dc_config(field_name="task_id")) custom: dict[str, object] = dc_field(metadata=dc_config(field_name="custom")) type: str = dc_field( - default="export.channels.error", metadata=dc_config(field_name="type") + default="export.bulk_image_moderation.error", + metadata=dc_config(field_name="type"), ) received_at: datetime | None = dc_field( default=None, @@ -6075,9 +6118,17 @@ class ChannelBatchUpdateRequest(DataClassJsonMixin): operation: str = dc_field(metadata=dc_config(field_name="operation")) # Filter to apply to the query filter: dict[str, object] = dc_field(metadata=dc_config(field_name="filter")) + # `updateData` only. Deletes these keys from each channel's existing custom object, leaving every other custom key untouched. Keys are dot-paths; deleting a key that does not exist is a no-op. Cannot be combined with `data.custom` + custom_unset: list[str] | None = dc_field( + default=None, metadata=dc_config(field_name="custom_unset") + ) members: "list[ChannelBatchMemberRequest] | None" = dc_field( default=None, metadata=dc_config(field_name="members") ) + # `updateData` only. Merges these keys into each channel's existing custom object, leaving every other custom key untouched. Keys are dot-paths, so `a.b` sets key `b` inside object `a` (the parent object must already exist). Cannot be combined with `data.custom` + custom_set: dict[str, object] | None = dc_field( + default=None, metadata=dc_config(field_name="custom_set") + ) data: "ChannelDataUpdate | None" = dc_field( default=None, metadata=dc_config(field_name="data") ) @@ -6726,16 +6777,17 @@ class ChannelMemberPartialResponse(DataClassJsonMixin): @dataclass class ChannelMemberRequest(DataClassJsonMixin): - user_id: str = dc_field(metadata=dc_config(field_name="user_id")) # Role of the member in the channel channel_role: str | None = dc_field( default=None, metadata=dc_config(field_name="channel_role") ) + user_id: str | None = dc_field( + default=None, metadata=dc_config(field_name="user_id") + ) custom: dict[str, object] | None = dc_field( default=None, metadata=dc_config(field_name="custom") ) - # User response object - user: "UserResponse | None" = dc_field( + user: "MemberUserRequest | None" = dc_field( default=None, metadata=dc_config(field_name="user") ) @@ -9143,7 +9195,7 @@ class ConfigResponse(DataClassJsonMixin): ai_text_config: "AITextConfig | None" = dc_field( default=None, metadata=dc_config(field_name="ai_text_config") ) - ai_video_config: "AIVideoConfig | None" = dc_field( + ai_video_config: "AIVideoConfigResponse | None" = dc_field( default=None, metadata=dc_config(field_name="ai_video_config") ) automod_platform_circumvention_config: "AutomodPlatformCircumventionConfig | None" = dc_field( @@ -9718,6 +9770,10 @@ class CreateExternalStorageResponse(DataClassJsonMixin): class CreateFeedGroupRequest(DataClassJsonMixin): # Unique identifier for the feed group id: str = dc_field(metadata=dc_config(field_name="id")) + # Role new followers of feeds in this group are given. Either a built-in (feed_follower, feed_member_viewer) or any role your app has defined. Empty means feed_follower. Applied when the follow is accepted, so a follow that starts pending picks it up on approval + default_follower_role: str | None = dc_field( + default=None, metadata=dc_config(field_name="default_follower_role") + ) # Default visibility for the feed group, can be 'public', 'visible', 'followers', 'members', or 'private'. Defaults to 'visible' if not provided. default_visibility: str | None = dc_field( default=None, metadata=dc_config(field_name="default_visibility") @@ -9733,6 +9789,9 @@ class CreateFeedGroupRequest(DataClassJsonMixin): activity_filter: "ActivityFilterConfig | None" = dc_field( default=None, metadata=dc_config(field_name="activity_filter") ) + activity_processing: "ActivityProcessingConfig | None" = dc_field( + default=None, metadata=dc_config(field_name="activity_processing") + ) aggregation: "AggregationConfig | None" = dc_field( default=None, metadata=dc_config(field_name="aggregation") ) @@ -9788,6 +9847,10 @@ class CreateFeedViewResponse(DataClassJsonMixin): class CreateFeedsBatchRequest(DataClassJsonMixin): # List of feeds to create feeds: "list[FeedRequest]" = dc_field(metadata=dc_config(field_name="feeds")) + # Server-side only. If true, auto-creates users referenced by feeds[].created_by_id that don't already exist. Default: false. + create_users: bool | None = dc_field( + default=None, metadata=dc_config(field_name="create_users") + ) # If true, enriches the created feeds with own_* fields (own_follows, own_followings, own_capabilities, own_membership). Defaults to false for performance. enrich_own_fields: bool | None = dc_field( default=None, metadata=dc_config(field_name="enrich_own_fields") @@ -10101,6 +10164,15 @@ class CreateReminderRequest(DataClassJsonMixin): ) +@dataclass +class CreateReminderResponse(DataClassJsonMixin): + # Duration of the request in milliseconds + duration: str = dc_field(metadata=dc_config(field_name="duration")) + reminder: "ReminderResponseData" = dc_field( + metadata=dc_config(field_name="reminder") + ) + + @dataclass class CreateRoleRequest(DataClassJsonMixin): # Role name @@ -11919,6 +11991,9 @@ class FeedGroup(DataClassJsonMixin): mm_field=fields.DateTime(format="iso"), ) ) + default_follower_role: str = dc_field( + metadata=dc_config(field_name="default_follower_role") + ) default_visibility: str = dc_field( metadata=dc_config(field_name="default_visibility") ) @@ -12068,6 +12143,10 @@ class FeedGroupResponse(DataClassJsonMixin): mm_field=fields.DateTime(format="iso"), ) ) + # Role new followers of feeds in this group are given. Either a built-in (feed_follower, feed_member_viewer) or any role your app has defined. Empty means feed_follower. Applied when the follow is accepted, so a follow that starts pending picks it up on approval + default_follower_role: str | None = dc_field( + default=None, metadata=dc_config(field_name="default_follower_role") + ) # Default visibility for activities. One of: public, visible, followers, members, private default_visibility: str | None = dc_field( default=None, metadata=dc_config(field_name="default_visibility") @@ -12092,6 +12171,9 @@ class FeedGroupResponse(DataClassJsonMixin): activity_filter: "ActivityFilterConfig | None" = dc_field( default=None, metadata=dc_config(field_name="activity_filter") ) + activity_processing: "ActivityProcessingConfig | None" = dc_field( + default=None, metadata=dc_config(field_name="activity_processing") + ) aggregation: "AggregationConfig | None" = dc_field( default=None, metadata=dc_config(field_name="aggregation") ) @@ -13775,7 +13857,7 @@ class FollowResponse(DataClassJsonMixin): mm_field=fields.DateTime(format="iso"), ) ) - # Role of the follower (source user) in the follow relationship + # Role of the follower (source user) in the follow relationship, as stored. A reserved name, or a role your app no longer defines, is reported as stored but evaluated as 'feed_follower'. follower_role: str = dc_field(metadata=dc_config(field_name="follower_role")) # Push preference for notifications. One of: all, none push_preference: str = dc_field(metadata=dc_config(field_name="push_preference")) @@ -14801,6 +14883,10 @@ class GetOrCreateCallResponse(DataClassJsonMixin): @dataclass class GetOrCreateFeedGroupRequest(DataClassJsonMixin): + # Role new followers of feeds in this group are given. Either a built-in (feed_follower, feed_member_viewer) or any role your app has defined. Empty means feed_follower. Applied when the follow is accepted, so a follow that starts pending picks it up on approval + default_follower_role: str | None = dc_field( + default=None, metadata=dc_config(field_name="default_follower_role") + ) # Default visibility for the feed group, can be 'public', 'visible', 'followers', 'members', or 'private'. Defaults to 'visible' if not provided. default_visibility: str | None = dc_field( default=None, metadata=dc_config(field_name="default_visibility") @@ -14816,6 +14902,9 @@ class GetOrCreateFeedGroupRequest(DataClassJsonMixin): activity_filter: "ActivityFilterConfig | None" = dc_field( default=None, metadata=dc_config(field_name="activity_filter") ) + activity_processing: "ActivityProcessingConfig | None" = dc_field( + default=None, metadata=dc_config(field_name="activity_processing") + ) aggregation: "AggregationConfig | None" = dc_field( default=None, metadata=dc_config(field_name="aggregation") ) @@ -16930,6 +17019,32 @@ class MemberUpdatedEvent(DataClassJsonMixin): ) +@dataclass +class MemberUserRequest(DataClassJsonMixin): + id: str = dc_field(metadata=dc_config(field_name="id")) + image: str | None = dc_field(default=None, metadata=dc_config(field_name="image")) + invisible: bool | None = dc_field( + default=None, metadata=dc_config(field_name="invisible") + ) + language: str | None = dc_field( + default=None, metadata=dc_config(field_name="language") + ) + name: str | None = dc_field(default=None, metadata=dc_config(field_name="name")) + role: str | None = dc_field(default=None, metadata=dc_config(field_name="role")) + teams: list[str] | None = dc_field( + default=None, metadata=dc_config(field_name="teams") + ) + custom: dict[str, object] | None = dc_field( + default=None, metadata=dc_config(field_name="custom") + ) + privacy_settings: "PrivacySettingsResponse | None" = dc_field( + default=None, metadata=dc_config(field_name="privacy_settings") + ) + teams_role: "dict[str, str] | None" = dc_field( + default=None, metadata=dc_config(field_name="teams_role") + ) + + @dataclass class MembersResponse(DataClassJsonMixin): # Duration of the request in milliseconds @@ -17786,6 +17901,12 @@ class MessageResponse(DataClassJsonMixin): member: "ChannelMemberPartialResponse | None" = dc_field( default=None, metadata=dc_config(field_name="member") ) + # Channel member data for the users mentioned in the message, keyed by user id. Only present when the app has member custom on mentioned users enabled, and only for the first two mentioned users of each message + mentioned_channel_members: "dict[str, ChannelMemberPartialResponse] | None" = ( + dc_field( + default=None, metadata=dc_config(field_name="mentioned_channel_members") + ) + ) moderation: "ModerationV2Response | None" = dc_field( default=None, metadata=dc_config(field_name="moderation") ) @@ -18148,6 +18269,12 @@ class MessageWithChannelResponse(DataClassJsonMixin): member: "ChannelMemberPartialResponse | None" = dc_field( default=None, metadata=dc_config(field_name="member") ) + # Channel member data for the users mentioned in the message, keyed by user id. Only present when the app has member custom on mentioned users enabled, and only for the first two mentioned users of each message + mentioned_channel_members: "dict[str, ChannelMemberPartialResponse] | None" = ( + dc_field( + default=None, metadata=dc_config(field_name="mentioned_channel_members") + ) + ) moderation: "ModerationV2Response | None" = dc_field( default=None, metadata=dc_config(field_name="moderation") ) @@ -18586,6 +18713,15 @@ class ModerationFlagResponse(DataClassJsonMixin): result: "list[dict[str, object]]" = dc_field( metadata=dc_config(field_name="result") ) + content_published_at: datetime | None = dc_field( + default=None, + metadata=dc_config( + field_name="content_published_at", + encoder=encode_datetime, + decoder=datetime_from_unix_ns, + mm_field=fields.DateTime(format="iso"), + ), + ) entity_creator_id: str | None = dc_field( default=None, metadata=dc_config(field_name="entity_creator_id") ) @@ -20556,6 +20692,7 @@ class PollResponseData(DataClassJsonMixin): ) ) vote_count: int = dc_field(metadata=dc_config(field_name="vote_count")) + # Voting visibility of the poll voting_visibility: str = dc_field( metadata=dc_config(field_name="voting_visibility") ) @@ -22329,10 +22466,6 @@ class QueryLabelResultsResponse(DataClassJsonMixin): @dataclass class QueryMembersPayload(DataClassJsonMixin): type: str = dc_field(metadata=dc_config(field_name="type")) - # Filter conditions to apply to the query - filter_conditions: dict[str, object] = dc_field( - metadata=dc_config(field_name="filter_conditions") - ) id: str | None = dc_field(default=None, metadata=dc_config(field_name="id")) limit: int | None = dc_field(default=None, metadata=dc_config(field_name="limit")) offset: int | None = dc_field(default=None, metadata=dc_config(field_name="offset")) @@ -22346,6 +22479,10 @@ class QueryMembersPayload(DataClassJsonMixin): sort: "list[SortParamRequest] | None" = dc_field( default=None, metadata=dc_config(field_name="sort") ) + # Filter conditions to apply to the query + filter_conditions: dict[str, object] | None = dc_field( + default=None, metadata=dc_config(field_name="filter_conditions") + ) # User request object user: "UserRequest | None" = dc_field( default=None, metadata=dc_config(field_name="user") @@ -23701,6 +23838,9 @@ class ReminderCreatedEvent(DataClassJsonMixin): # The ID of the user for whom the reminder was created user_id: str = dc_field(metadata=dc_config(field_name="user_id")) custom: dict[str, object] = dc_field(metadata=dc_config(field_name="custom")) + reminder: "ReminderResponseData" = dc_field( + metadata=dc_config(field_name="reminder") + ) # The type of event: "reminder.created" in this case type: str = dc_field( default="reminder.created", metadata=dc_config(field_name="type") @@ -23718,9 +23858,6 @@ class ReminderCreatedEvent(DataClassJsonMixin): mm_field=fields.DateTime(format="iso"), ), ) - reminder: "ReminderResponseData | None" = dc_field( - default=None, metadata=dc_config(field_name="reminder") - ) @dataclass @@ -23741,6 +23878,9 @@ class ReminderDeletedEvent(DataClassJsonMixin): # The ID of the user for whom the reminder was created user_id: str = dc_field(metadata=dc_config(field_name="user_id")) custom: dict[str, object] = dc_field(metadata=dc_config(field_name="custom")) + reminder: "ReminderResponseData" = dc_field( + metadata=dc_config(field_name="reminder") + ) # The type of event: "reminder.deleted" in this case type: str = dc_field( default="reminder.deleted", metadata=dc_config(field_name="type") @@ -23758,9 +23898,6 @@ class ReminderDeletedEvent(DataClassJsonMixin): mm_field=fields.DateTime(format="iso"), ), ) - reminder: "ReminderResponseData | None" = dc_field( - default=None, metadata=dc_config(field_name="reminder") - ) @dataclass @@ -23781,6 +23918,9 @@ class ReminderNotificationEvent(DataClassJsonMixin): # The ID of the user for whom the reminder was created user_id: str = dc_field(metadata=dc_config(field_name="user_id")) custom: dict[str, object] = dc_field(metadata=dc_config(field_name="custom")) + reminder: "ReminderResponseData" = dc_field( + metadata=dc_config(field_name="reminder") + ) # The type of event: "notification.reminder_due" in this case type: str = dc_field( default="notification.reminder_due", metadata=dc_config(field_name="type") @@ -23797,9 +23937,6 @@ class ReminderNotificationEvent(DataClassJsonMixin): mm_field=fields.DateTime(format="iso"), ), ) - reminder: "ReminderResponseData | None" = dc_field( - default=None, metadata=dc_config(field_name="reminder") - ) @dataclass @@ -23864,6 +24001,9 @@ class ReminderUpdatedEvent(DataClassJsonMixin): # The ID of the user for whom the reminder was created user_id: str = dc_field(metadata=dc_config(field_name="user_id")) custom: dict[str, object] = dc_field(metadata=dc_config(field_name="custom")) + reminder: "ReminderResponseData" = dc_field( + metadata=dc_config(field_name="reminder") + ) # The type of event: "reminder.updated" in this case type: str = dc_field( default="reminder.updated", metadata=dc_config(field_name="type") @@ -23881,9 +24021,6 @@ class ReminderUpdatedEvent(DataClassJsonMixin): mm_field=fields.DateTime(format="iso"), ), ) - reminder: "ReminderResponseData | None" = dc_field( - default=None, metadata=dc_config(field_name="reminder") - ) @dataclass @@ -25225,6 +25362,11 @@ class SearchResultMessage(DataClassJsonMixin): member: "ChannelMemberPartialResponse | None" = dc_field( default=None, metadata=dc_config(field_name="member") ) + mentioned_channel_members: "dict[str, ChannelMemberPartialResponse] | None" = ( + dc_field( + default=None, metadata=dc_config(field_name="mentioned_channel_members") + ) + ) moderation: "ModerationV2Response | None" = dc_field( default=None, metadata=dc_config(field_name="moderation") ) @@ -27104,6 +27246,14 @@ class TranslateMessageRequest(DataClassJsonMixin): language: str = dc_field(metadata=dc_config(field_name="language")) +@dataclass +class TranslateMessageResponse(DataClassJsonMixin): + # Duration of the request in milliseconds + duration: str = dc_field(metadata=dc_config(field_name="duration")) + # Represents any chat message + message: "MessageResponse" = dc_field(metadata=dc_config(field_name="message")) + + @dataclass class TranslationSettings(DataClassJsonMixin): enabled: bool | None = dc_field( @@ -27213,7 +27363,8 @@ class UnbanActionRequestPayload(DataClassJsonMixin): @dataclass class UnbanRequest(DataClassJsonMixin): - # ID of the user performing the unban + # ID of the user performing the unban Deprecated: not used by the unban flow + # Deprecated unbanned_by_id: str | None = dc_field( default=None, metadata=dc_config(field_name="unbanned_by_id") ) @@ -27731,9 +27882,17 @@ class UpdateAppRequest(DataClassJsonMixin): max_aggregated_activities_length: int | None = dc_field( default=None, metadata=dc_config(field_name="max_aggregated_activities_length") ) + member_custom_on_mentioned_users_enabled: bool | None = dc_field( + default=None, + metadata=dc_config(field_name="member_custom_on_mentioned_users_enabled"), + ) member_custom_on_messages_enabled: bool | None = dc_field( default=None, metadata=dc_config(field_name="member_custom_on_messages_enabled") ) + member_custom_on_typing_events_enabled: bool | None = dc_field( + default=None, + metadata=dc_config(field_name="member_custom_on_typing_events_enabled"), + ) migrate_permissions_to_v2: bool | None = dc_field( default=None, metadata=dc_config(field_name="migrate_permissions_to_v2") ) @@ -28646,6 +28805,11 @@ class UpdateExternalStorageResponse(DataClassJsonMixin): @dataclass class UpdateFeedGroupRequest(DataClassJsonMixin): + # Role new followers of feeds in this group are given. Either a built-in (feed_follower, feed_member_viewer) or any role your app has defined. Empty means feed_follower. Applied when the follow is accepted, so a follow that starts pending picks it up on approval + default_follower_role: str | None = dc_field( + default=None, metadata=dc_config(field_name="default_follower_role") + ) + # Default visibility for the feed group. One of: public, visible, followers, members, private default_visibility: str | None = dc_field( default=None, metadata=dc_config(field_name="default_visibility") ) @@ -28660,6 +28824,9 @@ class UpdateFeedGroupRequest(DataClassJsonMixin): activity_filter: "ActivityFilterConfig | None" = dc_field( default=None, metadata=dc_config(field_name="activity_filter") ) + activity_processing: "ActivityProcessingConfig | None" = dc_field( + default=None, metadata=dc_config(field_name="activity_processing") + ) aggregation: "AggregationConfig | None" = dc_field( default=None, metadata=dc_config(field_name="aggregation") ) @@ -28815,6 +28982,7 @@ class UpdateFollowRequest(DataClassJsonMixin): enrich_own_fields: bool | None = dc_field( default=None, metadata=dc_config(field_name="enrich_own_fields") ) + # Optional role for the follower in the follow relationship. Server-side only. Either a built-in ('feed_follower' (the default) or 'feed_member_viewer') or any role your app has defined; grants are not inspected. follower_role: str | None = dc_field( default=None, metadata=dc_config(field_name="follower_role") ) @@ -29541,7 +29709,7 @@ class UpsertConfigRequest(DataClassJsonMixin): ai_text_config: "AITextConfig | None" = dc_field( default=None, metadata=dc_config(field_name="ai_text_config") ) - ai_video_config: "AIVideoConfig | None" = dc_field( + ai_video_config: "AIVideoConfigRequest | None" = dc_field( default=None, metadata=dc_config(field_name="ai_video_config") ) automod_platform_circumvention_config: "AutomodPlatformCircumventionConfig | None" = dc_field( diff --git a/getstream/moderation/async_rest_client.py b/getstream/moderation/async_rest_client.py index ff02ca1d..7284b3b0 100644 --- a/getstream/moderation/async_rest_client.py +++ b/getstream/moderation/async_rest_client.py @@ -13,7 +13,7 @@ def __init__( base_url: str, timeout: float, token: str, - user_agent: str | None = None, + user_agent: str = None, ): """ Initializes ModerationClient with BaseClient instance @@ -368,7 +368,7 @@ async def upsert_config( ai_audio_config: Optional[AIAudioConfigRequest] = None, ai_image_config: Optional[AIImageConfig] = None, ai_text_config: Optional[AITextConfig] = None, - ai_video_config: Optional[AIVideoConfig] = None, + ai_video_config: Optional[AIVideoConfigRequest] = None, automod_platform_circumvention_config: Optional[ AutomodPlatformCircumventionConfig ] = None, diff --git a/getstream/moderation/rest_client.py b/getstream/moderation/rest_client.py index d9c08df2..3ee39076 100644 --- a/getstream/moderation/rest_client.py +++ b/getstream/moderation/rest_client.py @@ -13,7 +13,7 @@ def __init__( base_url: str, timeout: float, token: str, - user_agent: str | None = None, + user_agent: str = None, ): """ Initializes ModerationClient with BaseClient instance @@ -364,7 +364,7 @@ def upsert_config( ai_audio_config: Optional[AIAudioConfigRequest] = None, ai_image_config: Optional[AIImageConfig] = None, ai_text_config: Optional[AITextConfig] = None, - ai_video_config: Optional[AIVideoConfig] = None, + ai_video_config: Optional[AIVideoConfigRequest] = None, automod_platform_circumvention_config: Optional[ AutomodPlatformCircumventionConfig ] = None, diff --git a/getstream/video/async_rest_client.py b/getstream/video/async_rest_client.py index 1af0b573..993e7317 100644 --- a/getstream/video/async_rest_client.py +++ b/getstream/video/async_rest_client.py @@ -13,7 +13,7 @@ def __init__( base_url: str, timeout: float, token: str, - user_agent: str | None = None, + user_agent: str = None, ): """ Initializes VideoClient with BaseClient instance @@ -1398,9 +1398,9 @@ async def query_aggregate_call_stats( @telemetry.operation_name("getstream.api.video.get_daily_digest") async def get_daily_digest( - self, date: Optional[str] = None, app_id: Optional[str] = None + self, date: Optional[str] = None, target_app_id: Optional[str] = None ) -> StreamResponse[GetDailyDigestResponse]: - query_params = build_query_param(date=date, app_id=app_id) + query_params = build_query_param(date=date, target_app_id=target_app_id) return await self.get( "/api/v2/video/stats/daily_digest", GetDailyDigestResponse, diff --git a/getstream/video/rest_client.py b/getstream/video/rest_client.py index 51a6322e..7d634b52 100644 --- a/getstream/video/rest_client.py +++ b/getstream/video/rest_client.py @@ -13,7 +13,7 @@ def __init__( base_url: str, timeout: float, token: str, - user_agent: str | None = None, + user_agent: str = None, ): """ Initializes VideoClient with BaseClient instance @@ -1390,9 +1390,9 @@ def query_aggregate_call_stats( @telemetry.operation_name("getstream.api.video.get_daily_digest") def get_daily_digest( - self, date: Optional[str] = None, app_id: Optional[str] = None + self, date: Optional[str] = None, target_app_id: Optional[str] = None ) -> StreamResponse[GetDailyDigestResponse]: - query_params = build_query_param(date=date, app_id=app_id) + query_params = build_query_param(date=date, target_app_id=target_app_id) return self.get( "/api/v2/video/stats/daily_digest", GetDailyDigestResponse, diff --git a/pyproject.toml b/pyproject.toml index 54b88283..beeac5f9 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -130,5 +130,10 @@ exclude = [ [tool.ruff.lint] ignore = ["F405", "F403"] +[tool.ruff.lint.per-file-ignores] +# dataclasses_json resolves the generated string annotations at runtime, so these +# typing names are live even though they read as unused. +"getstream/models/__init__.py" = ["F401", "UP035"] + [tool.hatch.metadata] allow-direct-references = true