From ce1480fec45f2e6cc4ae705d779a124e26c90323 Mon Sep 17 00:00:00 2001 From: Varsh Date: Fri, 9 May 2025 17:21:05 +0200 Subject: [PATCH 01/15] add delete_messages field to banrequest --- getstream/models/__init__.py | 5 ++++- 1 file changed, 4 insertions(+), 1 deletion(-) diff --git a/getstream/models/__init__.py b/getstream/models/__init__.py index 5e201c92..6a1476a8 100644 --- a/getstream/models/__init__.py +++ b/getstream/models/__init__.py @@ -5,7 +5,7 @@ from dataclasses_json import config as dc_config from datetime import datetime from marshmallow import fields -from typing import List, Dict, Optional, Final, NewType +from typing import List, Dict, Optional, Final, NewType, Literal from getstream.utils import encode_datetime, datetime_from_unix_ns @@ -798,6 +798,9 @@ class BanActionRequest(DataClassJsonMixin): timeout: Optional[int] = dc_field( default=None, metadata=dc_config(field_name="timeout") ) + delete_messages: Optional[Literal["hard", "delete"]] = dc_field( + default=None, metadata=dc_config(field_name="delete_messages") + ) @dataclass From 775e90d12e24199a584ddcb81d836a47ddc2c462 Mon Sep 17 00:00:00 2001 From: Vishal Narkhede Date: Mon, 19 May 2025 14:15:12 +0200 Subject: [PATCH 02/15] added client.py for moderation --- getstream/moderation/client.py | 9 +++++++++ getstream/stream.py | 15 +++++++++++++++ 2 files changed, 24 insertions(+) create mode 100644 getstream/moderation/client.py diff --git a/getstream/moderation/client.py b/getstream/moderation/client.py new file mode 100644 index 00000000..06f4ede7 --- /dev/null +++ b/getstream/moderation/client.py @@ -0,0 +1,9 @@ +from getstream.moderation.rest_client import ModerationRestClient + + +class ModerationClient(ModerationRestClient): + def __init__(self, api_key: str, base_url, token, timeout, stream): + super().__init__( + api_key=api_key, base_url=base_url, token=token, timeout=timeout + ) + self.stream = stream diff --git a/getstream/stream.py b/getstream/stream.py index 85f0fd65..0d66ceaa 100644 --- a/getstream/stream.py +++ b/getstream/stream.py @@ -8,6 +8,7 @@ from getstream.models import UserRequest from getstream.utils import validate_and_clean_url from getstream.video.client import VideoClient +from getstream.moderation.client import ModerationClient BASE_URL = "https://chat.stream-io-api.com/" @@ -69,6 +70,20 @@ def chat(self): timeout=self.timeout, stream=self, ) + + @cached_property + def moderation(self): + """ + Moderation stream client. + + """ + return ModerationClient( + api_key=self.api_key, + base_url=self.base_url, + token=self.token, + timeout=self.timeout, + stream=self, + ) def upsert_users(self, *users: UserRequest): """ From 33de372872bd021f5c34b162d066493e71e7c430 Mon Sep 17 00:00:00 2001 From: github-actions Date: Mon, 19 May 2025 12:19:27 +0000 Subject: [PATCH 03/15] chore(release): 2.2.1 --- getstream/version.py | 2 +- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/getstream/version.py b/getstream/version.py index 3c00bb49..3f755ed2 100644 --- a/getstream/version.py +++ b/getstream/version.py @@ -1 +1 @@ -VERSION = "2.2.0" +VERSION = "2.2.1" diff --git a/pyproject.toml b/pyproject.toml index be32d36c..03a317c7 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "getstream" -version = "2.2.0" +version = "2.2.1" description = "" authors = [ { name = "sachaarbonel", email = "sacha.arbonel@hotmail.fr" }, From 7f9827baf8b7da78841e7828766c6262c4db7417 Mon Sep 17 00:00:00 2001 From: Tommaso Barbugli Date: Mon, 23 Jun 2025 22:48:30 +0200 Subject: [PATCH 04/15] latest spec --- getstream/chat/rest_client.py | 81 ++++++ getstream/common/rest_client.py | 31 +++ getstream/models/__init__.py | 389 +++++++++++++++++++++++++++- getstream/moderation/rest_client.py | 2 + getstream/stream.py | 2 +- uv.lock | 2 +- 6 files changed, 500 insertions(+), 7 deletions(-) diff --git a/getstream/chat/rest_client.py b/getstream/chat/rest_client.py index cb070c4e..45bc07c9 100644 --- a/getstream/chat/rest_client.py +++ b/getstream/chat/rest_client.py @@ -645,6 +645,7 @@ def create_channel_type( typing_events: Optional[bool] = None, uploads: Optional[bool] = None, url_enrichment: Optional[bool] = None, + user_message_reminders: Optional[bool] = None, blocklists: Optional[List[BlockListOptions]] = None, commands: Optional[List[str]] = None, permissions: Optional[List[PolicyRequest]] = None, @@ -674,6 +675,7 @@ def create_channel_type( typing_events=typing_events, uploads=uploads, url_enrichment=url_enrichment, + user_message_reminders=user_message_reminders, blocklists=blocklists, commands=commands, permissions=permissions, @@ -730,6 +732,7 @@ def update_channel_type( typing_events: Optional[bool] = None, uploads: Optional[bool] = None, url_enrichment: Optional[bool] = None, + user_message_reminders: Optional[bool] = None, allowed_flag_reasons: Optional[List[str]] = None, blocklists: Optional[List[BlockListOptions]] = None, commands: Optional[List[str]] = None, @@ -764,6 +767,7 @@ def update_channel_type( typing_events=typing_events, uploads=uploads, url_enrichment=url_enrichment, + user_message_reminders=user_message_reminders, allowed_flag_reasons=allowed_flag_reasons, blocklists=blocklists, commands=commands, @@ -1171,6 +1175,59 @@ def remove_poll_vote( path_params=path_params, ) + def delete_reminder( + self, message_id: str, user_id: Optional[str] = None + ) -> StreamResponse[DeleteReminderResponse]: + query_params = build_query_param(user_id=user_id) + path_params = { + "message_id": message_id, + } + + return self.delete( + "/api/v2/chat/messages/{message_id}/reminders", + DeleteReminderResponse, + query_params=query_params, + path_params=path_params, + ) + + def update_reminder( + self, + message_id: str, + remind_at: Optional[datetime] = None, + user_id: Optional[str] = None, + user: Optional[UserRequest] = None, + ) -> StreamResponse[UpdateReminderResponse]: + path_params = { + "message_id": message_id, + } + json = build_body_dict(remind_at=remind_at, user_id=user_id, user=user) + + return self.patch( + "/api/v2/chat/messages/{message_id}/reminders", + UpdateReminderResponse, + path_params=path_params, + json=json, + ) + + def create_reminder( + self, + message_id: str, + remind_at: Optional[datetime] = None, + user_id: Optional[str] = None, + user: Optional[UserRequest] = None, + ) -> StreamResponse[ReminderResponseData]: + path_params = { + "message_id": message_id, + } + json = build_body_dict(remind_at=remind_at, user_id=user_id, user=user) + + return self.post( + "/api/v2/chat/messages/{message_id}/reminders", + ReminderResponseData, + path_params=path_params, + json=json, + ) + def get_replies( self, parent_id: str, @@ -1551,6 +1608,30 @@ def query_banned_users( query_params=query_params, ) + def query_reminders( + self, + limit: Optional[int] = None, + next: Optional[str] = None, + prev: Optional[str] = None, + user_id: Optional[str] = None, + sort: Optional[List[SortParamRequest]] = None, + filter: Optional[Dict[str, object]] = None, + user: Optional[UserRequest] = None, + ) -> StreamResponse[QueryRemindersResponse]: + json = build_body_dict( + limit=limit, + next=next, + prev=prev, + user_id=user_id, + sort=sort, + filter=filter, + user=user, + ) + + return self.post( + "/api/v2/chat/reminders/query", QueryRemindersResponse, json=json + ) + def search( self, payload: Optional[SearchPayload] = None ) -> StreamResponse[SearchResponse]: diff --git a/getstream/common/rest_client.py b/getstream/common/rest_client.py index 7ce3a49e..45928998 100644 --- a/getstream/common/rest_client.py +++ b/getstream/common/rest_client.py @@ -55,6 +55,7 @@ def update_app( sqs_url: Optional[str] = None, webhook_url: Optional[str] = None, allowed_flag_reasons: Optional[List[str]] = None, + event_hooks: Optional[List[EventHook]] = None, image_moderation_block_labels: Optional[List[str]] = None, image_moderation_labels: Optional[List[str]] = None, user_search_disallowed_roles: Optional[List[str]] = None, @@ -103,6 +104,7 @@ def update_app( sqs_url=sqs_url, webhook_url=webhook_url, allowed_flag_reasons=allowed_flag_reasons, + event_hooks=event_hooks, image_moderation_block_labels=image_moderation_block_labels, image_moderation_labels=image_moderation_labels, user_search_disallowed_roles=user_search_disallowed_roles, @@ -190,6 +192,7 @@ def update_block_list( def check_push( self, apn_template: Optional[str] = None, + event_type: Optional[str] = None, firebase_data_template: Optional[str] = None, firebase_template: Optional[str] = None, message_id: Optional[str] = None, @@ -201,6 +204,7 @@ def check_push( ) -> StreamResponse[CheckPushResponse]: json = build_body_dict( apn_template=apn_template, + event_type=event_type, firebase_data_template=firebase_data_template, firebase_template=firebase_template, message_id=message_id, @@ -472,6 +476,33 @@ def get_task(self, id: str) -> StreamResponse[GetTaskResponse]: return self.get("/api/v2/tasks/{id}", GetTaskResponse, path_params=path_params) + def delete_file(self, url: Optional[str] = None) -> StreamResponse[Response]: + query_params = build_query_param(url=url) + + return self.delete("/api/v2/uploads/file", Response, query_params=query_params) + + def upload_file( + self, file: Optional[str] = None, user: Optional[OnlyUserID] = None + ) -> StreamResponse[FileUploadResponse]: + json = build_body_dict(file=file, user=user) + + return self.post("/api/v2/uploads/file", FileUploadResponse, json=json) + + def delete_image(self, url: Optional[str] = None) -> StreamResponse[Response]: + query_params = build_query_param(url=url) + + return self.delete("/api/v2/uploads/image", Response, query_params=query_params) + + def upload_image( + self, + file: Optional[str] = None, + upload_sizes: Optional[List[ImageSize]] = None, + user: Optional[OnlyUserID] = None, + ) -> StreamResponse[ImageUploadResponse]: + json = build_body_dict(file=file, upload_sizes=upload_sizes, user=user) + + return self.post("/api/v2/uploads/image", ImageUploadResponse, json=json) + def query_users( self, payload: Optional[QueryUsersPayload] = None ) -> StreamResponse[QueryUsersResponse]: diff --git a/getstream/models/__init__.py b/getstream/models/__init__.py index c85174a4..5032c546 100644 --- a/getstream/models/__init__.py +++ b/getstream/models/__init__.py @@ -212,6 +212,17 @@ class ActionLogResponse(DataClassJsonMixin): ) +@dataclass +class ActionSequence(DataClassJsonMixin): + action: str = dc_field(metadata=dc_config(field_name="action")) + blur: bool = dc_field(metadata=dc_config(field_name="blur")) + cooldown_period: int = dc_field(metadata=dc_config(field_name="cooldown_period")) + threshold: int = dc_field(metadata=dc_config(field_name="threshold")) + time_window: int = dc_field(metadata=dc_config(field_name="time_window")) + warning: bool = dc_field(metadata=dc_config(field_name="warning")) + warning_text: str = dc_field(metadata=dc_config(field_name="warning_text")) + + @dataclass class AnyEvent(DataClassJsonMixin): created_at: datetime = dc_field( @@ -285,7 +296,11 @@ class AppResponseFields(DataClassJsonMixin): suspended_explanation: str = dc_field( metadata=dc_config(field_name="suspended_explanation") ) + use_hook_v2: bool = dc_field(metadata=dc_config(field_name="use_hook_v2")) webhook_url: str = dc_field(metadata=dc_config(field_name="webhook_url")) + event_hooks: "List[EventHook]" = dc_field( + metadata=dc_config(field_name="event_hooks") + ) user_search_disallowed_roles: List[str] = dc_field( metadata=dc_config(field_name="user_search_disallowed_roles") ) @@ -295,7 +310,7 @@ class AppResponseFields(DataClassJsonMixin): call_types: "Dict[str, Optional[CallType]]" = dc_field( metadata=dc_config(field_name="call_types") ) - channel_configs: "Dict[str, Optional[ChannelConfig]]" = dc_field( + channel_configs: "Dict[str, ChannelConfig]" = dc_field( metadata=dc_config(field_name="channel_configs") ) file_upload_config: "FileUploadConfig" = dc_field( @@ -1713,6 +1728,43 @@ class CallMissedEvent(DataClassJsonMixin): type: str = dc_field(default="call.missed", metadata=dc_config(field_name="type")) +@dataclass +class CallModerationBlurEvent(DataClassJsonMixin): + call_cid: str = dc_field(metadata=dc_config(field_name="call_cid")) + created_at: datetime = dc_field( + metadata=dc_config( + field_name="created_at", + encoder=encode_datetime, + decoder=datetime_from_unix_ns, + mm_field=fields.DateTime(format="iso"), + ) + ) + user_id: str = dc_field(metadata=dc_config(field_name="user_id")) + custom: Dict[str, object] = dc_field(metadata=dc_config(field_name="custom")) + type: str = dc_field( + default="call.moderation_blur", metadata=dc_config(field_name="type") + ) + + +@dataclass +class CallModerationWarningEvent(DataClassJsonMixin): + call_cid: str = dc_field(metadata=dc_config(field_name="call_cid")) + created_at: datetime = dc_field( + metadata=dc_config( + field_name="created_at", + encoder=encode_datetime, + decoder=datetime_from_unix_ns, + mm_field=fields.DateTime(format="iso"), + ) + ) + message: str = dc_field(metadata=dc_config(field_name="message")) + user_id: str = dc_field(metadata=dc_config(field_name="user_id")) + custom: Dict[str, object] = dc_field(metadata=dc_config(field_name="custom")) + type: str = dc_field( + default="call.moderation_warning", metadata=dc_config(field_name="type") + ) + + @dataclass class CallNotificationEvent(DataClassJsonMixin): call_cid: str = dc_field(metadata=dc_config(field_name="call_cid")) @@ -2692,6 +2744,9 @@ class CallTranscriptionFailedEvent(DataClassJsonMixin): type: str = dc_field( default="call.transcription_failed", metadata=dc_config(field_name="type") ) + error: Optional[str] = dc_field( + default=None, metadata=dc_config(field_name="error") + ) @dataclass @@ -2759,9 +2814,6 @@ class CallType(DataClassJsonMixin): mm_field=fields.DateTime(format="iso"), ) ) - enable_live_insights: bool = dc_field( - metadata=dc_config(field_name="EnableLiveInsights") - ) external_storage: str = dc_field(metadata=dc_config(field_name="ExternalStorage")) name: str = dc_field(metadata=dc_config(field_name="Name")) pk: int = dc_field(metadata=dc_config(field_name="PK")) @@ -3196,6 +3248,9 @@ class ChannelConfig(DataClassJsonMixin): ) uploads: bool = dc_field(metadata=dc_config(field_name="uploads")) url_enrichment: bool = dc_field(metadata=dc_config(field_name="url_enrichment")) + user_message_reminders: bool = dc_field( + metadata=dc_config(field_name="user_message_reminders") + ) commands: List[str] = dc_field(metadata=dc_config(field_name="commands")) blocklist: Optional[str] = dc_field( default=None, metadata=dc_config(field_name="blocklist") @@ -3206,7 +3261,7 @@ class ChannelConfig(DataClassJsonMixin): partition_size: Optional[int] = dc_field( default=None, metadata=dc_config(field_name="partition_size") ) - partition_ttl: Optional[str] = dc_field( + partition_ttl: Optional[int] = dc_field( default=None, metadata=dc_config(field_name="partition_ttl") ) allowed_flag_reasons: Optional[List[str]] = dc_field( @@ -3266,6 +3321,9 @@ class ChannelConfigWithInfo(DataClassJsonMixin): ) uploads: bool = dc_field(metadata=dc_config(field_name="uploads")) url_enrichment: bool = dc_field(metadata=dc_config(field_name="url_enrichment")) + user_message_reminders: bool = dc_field( + metadata=dc_config(field_name="user_message_reminders") + ) commands: "List[Command]" = dc_field(metadata=dc_config(field_name="commands")) blocklist: Optional[str] = dc_field( default=None, metadata=dc_config(field_name="blocklist") @@ -4055,6 +4113,9 @@ class ChannelTypeConfig(DataClassJsonMixin): ) uploads: bool = dc_field(metadata=dc_config(field_name="uploads")) url_enrichment: bool = dc_field(metadata=dc_config(field_name="url_enrichment")) + user_message_reminders: bool = dc_field( + metadata=dc_config(field_name="user_message_reminders") + ) commands: "List[Command]" = dc_field(metadata=dc_config(field_name="commands")) permissions: "List[PolicyRequest]" = dc_field( metadata=dc_config(field_name="permissions") @@ -4186,6 +4247,9 @@ class CheckPushRequest(DataClassJsonMixin): apn_template: Optional[str] = dc_field( default=None, metadata=dc_config(field_name="apn_template") ) + event_type: Optional[str] = dc_field( + default=None, metadata=dc_config(field_name="event_type") + ) firebase_data_template: Optional[str] = dc_field( default=None, metadata=dc_config(field_name="firebase_data_template") ) @@ -4215,6 +4279,9 @@ class CheckPushRequest(DataClassJsonMixin): @dataclass class CheckPushResponse(DataClassJsonMixin): duration: str = dc_field(metadata=dc_config(field_name="duration")) + event_type: Optional[str] = dc_field( + default=None, metadata=dc_config(field_name="event_type") + ) rendered_apn_template: Optional[str] = dc_field( default=None, metadata=dc_config(field_name="rendered_apn_template") ) @@ -4449,6 +4516,9 @@ class ConfigOverrides(DataClassJsonMixin): url_enrichment: Optional[bool] = dc_field( default=None, metadata=dc_config(field_name="url_enrichment") ) + user_message_reminders: Optional[bool] = dc_field( + default=None, metadata=dc_config(field_name="user_message_reminders") + ) @dataclass @@ -4500,6 +4570,9 @@ class ConfigResponse(DataClassJsonMixin): velocity_filter_config: "Optional[VelocityFilterConfig]" = dc_field( default=None, metadata=dc_config(field_name="velocity_filter_config") ) + video_call_rule_config: "Optional[VideoCallRuleConfig]" = dc_field( + default=None, metadata=dc_config(field_name="video_call_rule_config") + ) @dataclass @@ -4646,6 +4719,9 @@ class CreateChannelTypeRequest(DataClassJsonMixin): url_enrichment: Optional[bool] = dc_field( default=None, metadata=dc_config(field_name="url_enrichment") ) + user_message_reminders: Optional[bool] = dc_field( + default=None, metadata=dc_config(field_name="user_message_reminders") + ) blocklists: "Optional[List[BlockListOptions]]" = dc_field( default=None, metadata=dc_config(field_name="blocklists") ) @@ -4707,6 +4783,9 @@ class CreateChannelTypeResponse(DataClassJsonMixin): ) uploads: bool = dc_field(metadata=dc_config(field_name="uploads")) url_enrichment: bool = dc_field(metadata=dc_config(field_name="url_enrichment")) + user_message_reminders: bool = dc_field( + metadata=dc_config(field_name="user_message_reminders") + ) commands: List[str] = dc_field(metadata=dc_config(field_name="commands")) permissions: "List[PolicyRequest]" = dc_field( metadata=dc_config(field_name="permissions") @@ -4887,6 +4966,25 @@ class CreatePollRequest(DataClassJsonMixin): ) +@dataclass +class CreateReminderRequest(DataClassJsonMixin): + remind_at: Optional[datetime] = dc_field( + default=None, + metadata=dc_config( + field_name="remind_at", + encoder=encode_datetime, + decoder=datetime_from_unix_ns, + mm_field=fields.DateTime(format="iso"), + ), + ) + user_id: Optional[str] = dc_field( + default=None, metadata=dc_config(field_name="user_id") + ) + user: "Optional[UserRequest]" = dc_field( + default=None, metadata=dc_config(field_name="user") + ) + + @dataclass class CreateRoleRequest(DataClassJsonMixin): name: str = dc_field(metadata=dc_config(field_name="name")) @@ -5166,6 +5264,11 @@ class DeleteRecordingResponse(DataClassJsonMixin): duration: str = dc_field(metadata=dc_config(field_name="duration")) +@dataclass +class DeleteReminderResponse(DataClassJsonMixin): + duration: str = dc_field(metadata=dc_config(field_name="duration")) + + @dataclass class DeleteSegmentTargetsRequest(DataClassJsonMixin): target_ids: List[str] = dc_field(metadata=dc_config(field_name="target_ids")) @@ -5711,6 +5814,83 @@ class ErrorResult(DataClassJsonMixin): ) +@dataclass +class EventHook(DataClassJsonMixin): + created_at: Optional[datetime] = dc_field( + default=None, + metadata=dc_config( + field_name="created_at", + encoder=encode_datetime, + decoder=datetime_from_unix_ns, + mm_field=fields.DateTime(format="iso"), + ), + ) + enabled: Optional[bool] = dc_field( + default=None, metadata=dc_config(field_name="enabled") + ) + hook_type: Optional[str] = dc_field( + default=None, metadata=dc_config(field_name="hook_type") + ) + id: Optional[str] = dc_field(default=None, metadata=dc_config(field_name="id")) + sns_auth_type: Optional[str] = dc_field( + default=None, metadata=dc_config(field_name="sns_auth_type") + ) + sns_key: Optional[str] = dc_field( + default=None, metadata=dc_config(field_name="sns_key") + ) + sns_region: Optional[str] = dc_field( + default=None, metadata=dc_config(field_name="sns_region") + ) + sns_role_arn: Optional[str] = dc_field( + default=None, metadata=dc_config(field_name="sns_role_arn") + ) + sns_secret: Optional[str] = dc_field( + default=None, metadata=dc_config(field_name="sns_secret") + ) + sns_topic_arn: Optional[str] = dc_field( + default=None, metadata=dc_config(field_name="sns_topic_arn") + ) + sqs_auth_type: Optional[str] = dc_field( + default=None, metadata=dc_config(field_name="sqs_auth_type") + ) + sqs_key: Optional[str] = dc_field( + default=None, metadata=dc_config(field_name="sqs_key") + ) + sqs_queue_url: Optional[str] = dc_field( + default=None, metadata=dc_config(field_name="sqs_queue_url") + ) + sqs_region: Optional[str] = dc_field( + default=None, metadata=dc_config(field_name="sqs_region") + ) + sqs_role_arn: Optional[str] = dc_field( + default=None, metadata=dc_config(field_name="sqs_role_arn") + ) + sqs_secret: Optional[str] = dc_field( + default=None, metadata=dc_config(field_name="sqs_secret") + ) + timeout_ms: Optional[int] = dc_field( + default=None, metadata=dc_config(field_name="timeout_ms") + ) + updated_at: Optional[datetime] = dc_field( + default=None, + metadata=dc_config( + field_name="updated_at", + encoder=encode_datetime, + decoder=datetime_from_unix_ns, + mm_field=fields.DateTime(format="iso"), + ), + ) + webhook_url: Optional[str] = dc_field( + default=None, metadata=dc_config(field_name="webhook_url") + ) + event_types: Optional[List[str]] = dc_field( + default=None, metadata=dc_config(field_name="event_types") + ) + callback: "Optional[AsyncModerationCallbackConfig]" = dc_field( + default=None, metadata=dc_config(field_name="callback") + ) + + @dataclass class EventNotificationSettings(DataClassJsonMixin): enabled: bool = dc_field(metadata=dc_config(field_name="enabled")) @@ -6307,6 +6487,9 @@ class GetCallReportResponse(DataClassJsonMixin): duration: str = dc_field(metadata=dc_config(field_name="duration")) session_id: str = dc_field(metadata=dc_config(field_name="session_id")) report: "ReportResponse" = dc_field(metadata=dc_config(field_name="report")) + video_reactions: "Optional[List[VideoReactionsResponse]]" = dc_field( + default=None, metadata=dc_config(field_name="video_reactions") + ) chat_activity: "Optional[ChatActivityStatsResponse]" = dc_field( default=None, metadata=dc_config(field_name="chat_activity") ) @@ -6412,6 +6595,9 @@ class GetChannelTypeResponse(DataClassJsonMixin): ) uploads: bool = dc_field(metadata=dc_config(field_name="uploads")) url_enrichment: bool = dc_field(metadata=dc_config(field_name="url_enrichment")) + user_message_reminders: bool = dc_field( + metadata=dc_config(field_name="user_message_reminders") + ) commands: "List[Command]" = dc_field(metadata=dc_config(field_name="commands")) permissions: "List[PolicyRequest]" = dc_field( metadata=dc_config(field_name="permissions") @@ -6807,6 +6993,14 @@ class HLSSettingsResponse(DataClassJsonMixin): layout: "LayoutSettingsResponse" = dc_field(metadata=dc_config(field_name="layout")) +@dataclass +class HarmConfig(DataClassJsonMixin): + severity: int = dc_field(metadata=dc_config(field_name="severity")) + action_sequences: "List[ActionSequence]" = dc_field( + metadata=dc_config(field_name="action_sequences") + ) + + @dataclass class HideChannelRequest(DataClassJsonMixin): clear_history: Optional[bool] = dc_field( @@ -7463,6 +7657,9 @@ class Message(DataClassJsonMixin): quoted_message: "Optional[Message]" = dc_field( default=None, metadata=dc_config(field_name="quoted_message") ) + reminder: "Optional[MessageReminder]" = dc_field( + default=None, metadata=dc_config(field_name="reminder") + ) user: "Optional[User]" = dc_field( default=None, metadata=dc_config(field_name="user") ) @@ -7764,6 +7961,48 @@ class MessageReadEvent(DataClassJsonMixin): ) +@dataclass +class MessageReminder(DataClassJsonMixin): + channel_cid: str = dc_field(metadata=dc_config(field_name="channel_cid")) + created_at: datetime = dc_field( + metadata=dc_config( + field_name="created_at", + encoder=encode_datetime, + decoder=datetime_from_unix_ns, + mm_field=fields.DateTime(format="iso"), + ) + ) + message_id: str = dc_field(metadata=dc_config(field_name="message_id")) + task_id: str = dc_field(metadata=dc_config(field_name="task_id")) + updated_at: datetime = dc_field( + metadata=dc_config( + field_name="updated_at", + encoder=encode_datetime, + decoder=datetime_from_unix_ns, + mm_field=fields.DateTime(format="iso"), + ) + ) + user_id: str = dc_field(metadata=dc_config(field_name="user_id")) + remind_at: Optional[datetime] = dc_field( + default=None, + metadata=dc_config( + field_name="remind_at", + encoder=encode_datetime, + decoder=datetime_from_unix_ns, + mm_field=fields.DateTime(format="iso"), + ), + ) + channel: "Optional[Channel]" = dc_field( + default=None, metadata=dc_config(field_name="channel") + ) + message: "Optional[Message]" = dc_field( + default=None, metadata=dc_config(field_name="message") + ) + user: "Optional[User]" = dc_field( + default=None, metadata=dc_config(field_name="user") + ) + + @dataclass class MessageRequest(DataClassJsonMixin): html: Optional[str] = dc_field(default=None, metadata=dc_config(field_name="html")) @@ -7959,6 +8198,9 @@ class MessageResponse(DataClassJsonMixin): reaction_groups: "Optional[Dict[str, Optional[ReactionGroupResponse]]]" = dc_field( default=None, metadata=dc_config(field_name="reaction_groups") ) + reminder: "Optional[ReminderResponseData]" = dc_field( + default=None, metadata=dc_config(field_name="reminder") + ) @dataclass @@ -8192,6 +8434,9 @@ class MessageWithChannelResponse(DataClassJsonMixin): reaction_groups: "Optional[Dict[str, Optional[ReactionGroupResponse]]]" = dc_field( default=None, metadata=dc_config(field_name="reaction_groups") ) + reminder: "Optional[ReminderResponseData]" = dc_field( + default=None, metadata=dc_config(field_name="reminder") + ) @dataclass @@ -10147,6 +10392,37 @@ class QueryReactionsResponse(DataClassJsonMixin): prev: Optional[str] = dc_field(default=None, metadata=dc_config(field_name="prev")) +@dataclass +class QueryRemindersRequest(DataClassJsonMixin): + limit: Optional[int] = dc_field( + default=None, metadata=dc_config(field_name="limit") + ) + next: Optional[str] = dc_field(default=None, metadata=dc_config(field_name="next")) + prev: Optional[str] = dc_field(default=None, metadata=dc_config(field_name="prev")) + user_id: Optional[str] = dc_field( + default=None, metadata=dc_config(field_name="user_id") + ) + sort: "Optional[List[SortParamRequest]]" = dc_field( + default=None, metadata=dc_config(field_name="sort") + ) + filter: Optional[Dict[str, object]] = dc_field( + default=None, metadata=dc_config(field_name="filter") + ) + user: "Optional[UserRequest]" = dc_field( + default=None, metadata=dc_config(field_name="user") + ) + + +@dataclass +class QueryRemindersResponse(DataClassJsonMixin): + duration: str = dc_field(metadata=dc_config(field_name="duration")) + reminders: "List[ReminderResponseData]" = dc_field( + metadata=dc_config(field_name="reminders") + ) + next: Optional[str] = dc_field(default=None, metadata=dc_config(field_name="next")) + prev: Optional[str] = dc_field(default=None, metadata=dc_config(field_name="prev")) + + @dataclass class QueryReviewQueueRequest(DataClassJsonMixin): limit: Optional[int] = dc_field( @@ -10738,6 +11014,47 @@ class RecordingEgressConfig(DataClassJsonMixin): ) +@dataclass +class ReminderResponseData(DataClassJsonMixin): + channel_cid: str = dc_field(metadata=dc_config(field_name="channel_cid")) + created_at: datetime = dc_field( + metadata=dc_config( + field_name="created_at", + encoder=encode_datetime, + decoder=datetime_from_unix_ns, + mm_field=fields.DateTime(format="iso"), + ) + ) + message_id: str = dc_field(metadata=dc_config(field_name="message_id")) + updated_at: datetime = dc_field( + metadata=dc_config( + field_name="updated_at", + encoder=encode_datetime, + decoder=datetime_from_unix_ns, + mm_field=fields.DateTime(format="iso"), + ) + ) + user_id: str = dc_field(metadata=dc_config(field_name="user_id")) + remind_at: Optional[datetime] = dc_field( + default=None, + metadata=dc_config( + field_name="remind_at", + encoder=encode_datetime, + decoder=datetime_from_unix_ns, + mm_field=fields.DateTime(format="iso"), + ), + ) + channel: "Optional[ChannelResponse]" = dc_field( + default=None, metadata=dc_config(field_name="channel") + ) + message: "Optional[Message]" = dc_field( + default=None, metadata=dc_config(field_name="message") + ) + user: "Optional[User]" = dc_field( + default=None, metadata=dc_config(field_name="user") + ) + + @dataclass class ReportByHistogramBucket(DataClassJsonMixin): category: str = dc_field(metadata=dc_config(field_name="category")) @@ -11420,6 +11737,9 @@ class SearchResultMessage(DataClassJsonMixin): reaction_groups: "Optional[Dict[str, Optional[ReactionGroupResponse]]]" = dc_field( default=None, metadata=dc_config(field_name="reaction_groups") ) + reminder: "Optional[ReminderResponseData]" = dc_field( + default=None, metadata=dc_config(field_name="reminder") + ) @dataclass @@ -12588,6 +12908,9 @@ class UpdateAppRequest(DataClassJsonMixin): allowed_flag_reasons: Optional[List[str]] = dc_field( default=None, metadata=dc_config(field_name="allowed_flag_reasons") ) + event_hooks: "Optional[List[EventHook]]" = dc_field( + default=None, metadata=dc_config(field_name="event_hooks") + ) image_moderation_block_labels: Optional[List[str]] = dc_field( default=None, metadata=dc_config(field_name="image_moderation_block_labels") ) @@ -12903,6 +13226,9 @@ class UpdateChannelTypeRequest(DataClassJsonMixin): url_enrichment: Optional[bool] = dc_field( default=None, metadata=dc_config(field_name="url_enrichment") ) + user_message_reminders: Optional[bool] = dc_field( + default=None, metadata=dc_config(field_name="user_message_reminders") + ) allowed_flag_reasons: Optional[List[str]] = dc_field( default=None, metadata=dc_config(field_name="allowed_flag_reasons") ) @@ -12970,6 +13296,9 @@ class UpdateChannelTypeResponse(DataClassJsonMixin): ) uploads: bool = dc_field(metadata=dc_config(field_name="uploads")) url_enrichment: bool = dc_field(metadata=dc_config(field_name="url_enrichment")) + user_message_reminders: bool = dc_field( + metadata=dc_config(field_name="user_message_reminders") + ) commands: List[str] = dc_field(metadata=dc_config(field_name="commands")) permissions: "List[PolicyRequest]" = dc_field( metadata=dc_config(field_name="permissions") @@ -13176,6 +13505,33 @@ class UpdatePollRequest(DataClassJsonMixin): ) +@dataclass +class UpdateReminderRequest(DataClassJsonMixin): + remind_at: Optional[datetime] = dc_field( + default=None, + metadata=dc_config( + field_name="remind_at", + encoder=encode_datetime, + decoder=datetime_from_unix_ns, + mm_field=fields.DateTime(format="iso"), + ), + ) + user_id: Optional[str] = dc_field( + default=None, metadata=dc_config(field_name="user_id") + ) + user: "Optional[UserRequest]" = dc_field( + default=None, metadata=dc_config(field_name="user") + ) + + +@dataclass +class UpdateReminderResponse(DataClassJsonMixin): + duration: str = dc_field(metadata=dc_config(field_name="duration")) + reminder: "ReminderResponseData" = dc_field( + metadata=dc_config(field_name="reminder") + ) + + @dataclass class UpdateThreadPartialRequest(DataClassJsonMixin): user_id: Optional[str] = dc_field( @@ -13321,6 +13677,9 @@ class UpsertConfigRequest(DataClassJsonMixin): velocity_filter_config: "Optional[VelocityFilterConfig]" = dc_field( default=None, metadata=dc_config(field_name="velocity_filter_config") ) + video_call_rule_config: "Optional[VideoCallRuleConfig]" = dc_field( + default=None, metadata=dc_config(field_name="video_call_rule_config") + ) @dataclass @@ -14178,6 +14537,11 @@ class VelocityFilterConfigRule(DataClassJsonMixin): ) +@dataclass +class VideoCallRuleConfig(DataClassJsonMixin): + rules: "Dict[str, HarmConfig]" = dc_field(metadata=dc_config(field_name="rules")) + + @dataclass class VideoEndCallRequest(DataClassJsonMixin): pass @@ -14195,6 +14559,21 @@ class VideoOrientation(DataClassJsonMixin): ) +@dataclass +class VideoReactionOverTimeResponse(DataClassJsonMixin): + by_minute: "Optional[List[CountByMinuteResponse]]" = dc_field( + default=None, metadata=dc_config(field_name="by_minute") + ) + + +@dataclass +class VideoReactionsResponse(DataClassJsonMixin): + reaction: str = dc_field(metadata=dc_config(field_name="reaction")) + count_over_time: "Optional[VideoReactionOverTimeResponse]" = dc_field( + default=None, metadata=dc_config(field_name="count_over_time") + ) + + @dataclass class VideoSettings(DataClassJsonMixin): access_request_enabled: bool = dc_field( diff --git a/getstream/moderation/rest_client.py b/getstream/moderation/rest_client.py index e9073a16..c51448f7 100644 --- a/getstream/moderation/rest_client.py +++ b/getstream/moderation/rest_client.py @@ -107,6 +107,7 @@ def upsert_config( rule_builder_config: Optional[RuleBuilderConfig] = None, user: Optional[UserRequest] = None, velocity_filter_config: Optional[VelocityFilterConfig] = None, + video_call_rule_config: Optional[VideoCallRuleConfig] = None, ) -> StreamResponse[UpsertConfigResponse]: json = build_body_dict( key=key, @@ -126,6 +127,7 @@ def upsert_config( rule_builder_config=rule_builder_config, user=user, velocity_filter_config=velocity_filter_config, + video_call_rule_config=video_call_rule_config, ) return self.post("/api/v2/moderation/config", UpsertConfigResponse, json=json) diff --git a/getstream/stream.py b/getstream/stream.py index 0d66ceaa..713733bf 100644 --- a/getstream/stream.py +++ b/getstream/stream.py @@ -70,7 +70,7 @@ def chat(self): timeout=self.timeout, stream=self, ) - + @cached_property def moderation(self): """ diff --git a/uv.lock b/uv.lock index e4c79726..e8609520 100644 --- a/uv.lock +++ b/uv.lock @@ -148,7 +148,7 @@ wheels = [ [[package]] name = "getstream" -version = "2.1.0" +version = "2.2.1" source = { editable = "." } dependencies = [ { name = "dataclasses-json" }, From 7982c1bc72843ca63b9a73ee833fb6cff7921d21 Mon Sep 17 00:00:00 2001 From: vivekd22 Date: Thu, 3 Jul 2025 21:10:16 +0200 Subject: [PATCH 05/15] chore: add new release workflow --- .github/workflows/release-v2.yml | 181 +++++++++++++++++++++++++++++++ 1 file changed, 181 insertions(+) create mode 100644 .github/workflows/release-v2.yml diff --git a/.github/workflows/release-v2.yml b/.github/workflows/release-v2.yml new file mode 100644 index 00000000..0367de0d --- /dev/null +++ b/.github/workflows/release-v2.yml @@ -0,0 +1,181 @@ +name: ReleaseV2 (TestPyPI) + +on: + workflow_dispatch: + inputs: + python-version: + description: "Python version to use" + default: "3.12" + required: false + +permissions: + contents: read + id-token: write # required for OIDC publishing to TestPyPI via trusted publisher + +jobs: + build-core: + name: Build & Test Core SDK + runs-on: ubuntu-latest + outputs: + version: ${{ steps.get_version.outputs.version }} + steps: + - name: Checkout repository + uses: actions/checkout@v4 + + - name: Set up Python ${{ github.event.inputs.python-version || '3.12' }} + uses: actions/setup-python@v5 + with: + python-version: ${{ github.event.inputs.python-version || '3.12' }} + + - name: Install build tooling (uv & test deps) + run: | + python -m pip install --upgrade pip + # Install uv (once) using pip, then use uv for the rest + python -m pip install uv + uv pip install pytest pytest-asyncio coverage[toml] + + - name: Sync environment & install dev extras + run: | + uv sync --dev ## TODO Change to actual command with packages, groups etc + + - name: Build core distributions + run: | + uv build -o dist + + - name: Run tests with coverage (core only) + env: + PYTHONPATH: "${{ github.workspace }}" + run: | + uv run pytest --cov=getstream --cov-report=xml --ignore=getstream/plugins + + - name: Upload coverage artifact + uses: actions/upload-artifact@v4 + with: + name: core-coverage-xml + path: coverage.xml + + - name: Extract package version + id: get_version + run: | + python - <<'PY' + import tomllib, pathlib, os + meta = tomllib.loads(pathlib.Path('pyproject.toml').read_text()) + version = meta['project']['version'] + with open(os.environ['GITHUB_OUTPUT'], 'a') as fh: + fh.write(f'version={version}\n') + PY + + - name: Publish core to TestPyPI + uses: pypa/gh-action-pypi-publish@release/v1 + with: + repository-url: https://test.pypi.org/legacy/ + packages-dir: dist + environment: + name: testpypi + + test-core-index: + name: Verify Core from TestPyPI + needs: build-core + runs-on: ubuntu-latest + env: + UV_NO_SOURCES: "1" + steps: + - name: Set up Python + uses: actions/setup-python@v5 + with: + python-version: ${{ github.event.inputs.python-version || '3.12' }} + + - name: Install uv and testing tools + run: | + python -m pip install uv + uv pip install pytest pytest-asyncio + + - name: Install core from TestPyPI using uv + run: | + uv pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple getstream==${{ needs.build-core.outputs.version }} + + - name: Run core tests against TestPyPI artifact + run: | + UV_NO_SOURCES=1 uv run pytest tests/ --ignore=getstream/plugins + + build-plugins: + name: Build & Test Plugin Packages + runs-on: ubuntu-latest + needs: test-core-index + env: + CORE_VERSION: ${{ needs.build-core.outputs.version }} + UV_NO_SOURCES: "1" + steps: + - uses: actions/checkout@v4 + + - uses: actions/setup-python@v5 + with: + python-version: ${{ github.event.inputs.python-version || '3.12' }} + + - name: Install uv & tooling + run: | + python -m pip install uv + uv pip install pytest pytest-asyncio + + - name: Install new core from TestPyPI using uv (for plugin builds/tests) + run: | + uv pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple getstream==${CORE_VERSION} + + - name: Build all plugin dists (no workspace sources) + run: | + UV_NO_SOURCES=1 uv build --all-packages -o dist-plugins --wheel --sdist + + - name: Run plugin tests (local wheels, core from TestPyPI) + run: | + # Install all built plugin wheels using uv + uv pip install dist-plugins/*.whl + uv run pytest getstream/plugins + + - name: Publish plugins to TestPyPI + uses: pypa/gh-action-pypi-publish@release/v1 + with: + repository-url: https://test.pypi.org/legacy/ + packages-dir: dist-plugins + environment: + name: testpypi + + test-plugins-index: + name: Verify Plugins from TestPyPI + runs-on: ubuntu-latest + needs: build-plugins + env: + CORE_VERSION: ${{ needs.build-core.outputs.version }} + UV_NO_SOURCES: "1" + steps: + - uses: actions/setup-python@v5 + with: + python-version: ${{ github.event.inputs.python-version || '3.12' }} + + - name: Install uv & test tools + run: | + python -m pip install uv + uv pip install pytest pytest-asyncio + + - name: Install core and plugins from TestPyPI using uv + run: | + uv pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple getstream==${CORE_VERSION} + uv pip install --index-url https://test.pypi.org/simple/ --extra-index-url https://pypi.org/simple "getstream-plugins-*" + + - name: Run all plugin tests against TestPyPI artifacts + run: | + uv run pytest getstream/plugins + + summarize: + name: Publish Test Deployment Report + runs-on: ubuntu-latest + needs: test-plugins-index + steps: + - name: Generate summary + run: | + echo "### Release V2 Test Report" >> $GITHUB_STEP_SUMMARY + echo "* Core Version: ${{ needs.build-core.outputs.version }}" >> $GITHUB_STEP_SUMMARY + echo "* Core build & tests: ✅" >> $GITHUB_STEP_SUMMARY + echo "* Core published to TestPyPI: ✅" >> $GITHUB_STEP_SUMMARY + echo "* Plugins built & tests: ✅" >> $GITHUB_STEP_SUMMARY + echo "* Plugins published to TestPyPI: ✅" >> $GITHUB_STEP_SUMMARY + echo "* Tests against TestPyPI packages: ✅" >> $GITHUB_STEP_SUMMARY \ No newline at end of file From 6dd83c0413432d1ea82eaa2cc7a17cfc44d31809 Mon Sep 17 00:00:00 2001 From: vivekd22 Date: Thu, 3 Jul 2025 21:13:28 +0200 Subject: [PATCH 06/15] chore: add new release workflow --- .github/workflows/release-v2.yml | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/.github/workflows/release-v2.yml b/.github/workflows/release-v2.yml index 0367de0d..59d24e1d 100644 --- a/.github/workflows/release-v2.yml +++ b/.github/workflows/release-v2.yml @@ -36,7 +36,7 @@ jobs: - name: Sync environment & install dev extras run: | - uv sync --dev ## TODO Change to actual command with packages, groups etc + uv sync --dev --all-packages --all-groups --all-extras - name: Build core distributions run: | @@ -178,4 +178,4 @@ jobs: echo "* Core published to TestPyPI: ✅" >> $GITHUB_STEP_SUMMARY echo "* Plugins built & tests: ✅" >> $GITHUB_STEP_SUMMARY echo "* Plugins published to TestPyPI: ✅" >> $GITHUB_STEP_SUMMARY - echo "* Tests against TestPyPI packages: ✅" >> $GITHUB_STEP_SUMMARY \ No newline at end of file + echo "* Tests against TestPyPI packages: ✅" >> $GITHUB_STEP_SUMMARY From 152a064c94e1bddb2692ad5aba222fdf302626ea Mon Sep 17 00:00:00 2001 From: Tommaso Barbugli Date: Wed, 9 Jul 2025 15:48:06 +0200 Subject: [PATCH 07/15] call status --- getstream/chat/rest_client.py | 4 + getstream/common/rest_client.py | 36 +++ getstream/models/__init__.py | 435 ++++++++++++++++++++++++++++++-- getstream/video/rest_client.py | 5 + tests/test_video_examples.py | 8 + 5 files changed, 465 insertions(+), 23 deletions(-) diff --git a/getstream/chat/rest_client.py b/getstream/chat/rest_client.py index 45bc07c9..db83b21a 100644 --- a/getstream/chat/rest_client.py +++ b/getstream/chat/rest_client.py @@ -641,6 +641,7 @@ def create_channel_type( read_events: Optional[bool] = None, replies: Optional[bool] = None, search: Optional[bool] = None, + shared_locations: Optional[bool] = None, skip_last_msg_update_for_system_msgs: Optional[bool] = None, typing_events: Optional[bool] = None, uploads: Optional[bool] = None, @@ -671,6 +672,7 @@ def create_channel_type( read_events=read_events, replies=replies, search=search, + shared_locations=shared_locations, skip_last_msg_update_for_system_msgs=skip_last_msg_update_for_system_msgs, typing_events=typing_events, uploads=uploads, @@ -728,6 +730,7 @@ def update_channel_type( reminders: Optional[bool] = None, replies: Optional[bool] = None, search: Optional[bool] = None, + shared_locations: Optional[bool] = None, skip_last_msg_update_for_system_msgs: Optional[bool] = None, typing_events: Optional[bool] = None, uploads: Optional[bool] = None, @@ -763,6 +766,7 @@ def update_channel_type( reminders=reminders, replies=replies, search=search, + shared_locations=shared_locations, skip_last_msg_update_for_system_msgs=skip_last_msg_update_for_system_msgs, typing_events=typing_events, uploads=uploads, diff --git a/getstream/common/rest_client.py b/getstream/common/rest_client.py index 45928998..6ad2134b 100644 --- a/getstream/common/rest_client.py +++ b/getstream/common/rest_client.py @@ -583,6 +583,42 @@ def delete_users( return self.post("/api/v2/users/delete", DeleteUsersResponse, json=json) + def get_user_live_locations( + self, user_id: Optional[str] = None + ) -> StreamResponse[SharedLocationsResponse]: + query_params = build_query_param(user_id=user_id) + + return self.get( + "/api/v2/users/live_locations", + SharedLocationsResponse, + query_params=query_params, + ) + + def update_live_location( + self, + created_by_device_id: str, + message_id: str, + end_at: Optional[datetime] = None, + latitude: Optional[float] = None, + longitude: Optional[float] = None, + user_id: Optional[str] = None, + ) -> StreamResponse[SharedLocationResponse]: + query_params = build_query_param(user_id=user_id) + json = build_body_dict( + created_by_device_id=created_by_device_id, + message_id=message_id, + end_at=end_at, + latitude=latitude, + longitude=longitude, + ) + + return self.put( + "/api/v2/users/live_locations", + SharedLocationResponse, + query_params=query_params, + json=json, + ) + def reactivate_users( self, user_ids: List[str], diff --git a/getstream/models/__init__.py b/getstream/models/__init__.py index 5032c546..1fc76566 100644 --- a/getstream/models/__init__.py +++ b/getstream/models/__init__.py @@ -201,7 +201,7 @@ class ActionLogResponse(DataClassJsonMixin): type: str = dc_field(metadata=dc_config(field_name="type")) user_id: str = dc_field(metadata=dc_config(field_name="user_id")) custom: Dict[str, object] = dc_field(metadata=dc_config(field_name="custom")) - review_queue_item: "Optional[ReviewQueueItem]" = dc_field( + review_queue_item: "Optional[ReviewQueueItemResponse]" = dc_field( default=None, metadata=dc_config(field_name="review_queue_item") ) target_user: "Optional[UserResponse]" = dc_field( @@ -223,6 +223,46 @@ class ActionSequence(DataClassJsonMixin): warning_text: str = dc_field(metadata=dc_config(field_name="warning_text")) +@dataclass +class ActiveCallsFPSStats(DataClassJsonMixin): + p05: float = dc_field(metadata=dc_config(field_name="p05")) + p10: float = dc_field(metadata=dc_config(field_name="p10")) + p50: float = dc_field(metadata=dc_config(field_name="p50")) + p90: float = dc_field(metadata=dc_config(field_name="p90")) + + +@dataclass +class ActiveCallsLatencyStats(DataClassJsonMixin): + p50: float = dc_field(metadata=dc_config(field_name="p50")) + p95: float = dc_field(metadata=dc_config(field_name="p95")) + p99: float = dc_field(metadata=dc_config(field_name="p99")) + + +@dataclass +class ActiveCallsMetrics(DataClassJsonMixin): + join_call_api: "Optional[JoinCallAPIMetrics]" = dc_field( + default=None, metadata=dc_config(field_name="join_call_api") + ) + publishers: "Optional[PublishersMetrics]" = dc_field( + default=None, metadata=dc_config(field_name="publishers") + ) + subscribers: "Optional[SubscribersMetrics]" = dc_field( + default=None, metadata=dc_config(field_name="subscribers") + ) + + +@dataclass +class ActiveCallsSummary(DataClassJsonMixin): + active_calls: int = dc_field(metadata=dc_config(field_name="active_calls")) + active_publishers: int = dc_field( + metadata=dc_config(field_name="active_publishers") + ) + active_subscribers: int = dc_field( + metadata=dc_config(field_name="active_subscribers") + ) + participants: int = dc_field(metadata=dc_config(field_name="participants")) + + @dataclass class AnyEvent(DataClassJsonMixin): created_at: datetime = dc_field( @@ -622,12 +662,6 @@ class Attachment(DataClassJsonMixin): image_url: Optional[str] = dc_field( default=None, metadata=dc_config(field_name="image_url") ) - latitude: Optional[float] = dc_field( - default=None, metadata=dc_config(field_name="latitude") - ) - longitude: Optional[float] = dc_field( - default=None, metadata=dc_config(field_name="longitude") - ) og_scrape_url: Optional[str] = dc_field( default=None, metadata=dc_config(field_name="og_scrape_url") ) @@ -640,9 +674,6 @@ class Attachment(DataClassJsonMixin): pretext: Optional[str] = dc_field( default=None, metadata=dc_config(field_name="pretext") ) - stopped_sharing: Optional[bool] = dc_field( - default=None, metadata=dc_config(field_name="stopped_sharing") - ) text: Optional[str] = dc_field(default=None, metadata=dc_config(field_name="text")) thumb_url: Optional[str] = dc_field( default=None, metadata=dc_config(field_name="thumb_url") @@ -1798,8 +1829,8 @@ class CallParticipant(DataClassJsonMixin): ) ) online: bool = dc_field(metadata=dc_config(field_name="online")) - role: str = dc_field(metadata=dc_config(field_name="Role")) role: str = dc_field(metadata=dc_config(field_name="role")) + role: str = dc_field(metadata=dc_config(field_name="Role")) user_session_id: str = dc_field(metadata=dc_config(field_name="UserSessionID")) custom: Dict[str, object] = dc_field(metadata=dc_config(field_name="custom")) teams_role: "Dict[str, str]" = dc_field(metadata=dc_config(field_name="teams_role")) @@ -3182,6 +3213,9 @@ class Channel(DataClassJsonMixin): default=None, metadata=dc_config(field_name="member_count") ) team: Optional[str] = dc_field(default=None, metadata=dc_config(field_name="team")) + active_live_locations: "Optional[List[SharedLocation]]" = dc_field( + default=None, metadata=dc_config(field_name="active_live_locations") + ) invites: "Optional[List[ChannelMember]]" = dc_field( default=None, metadata=dc_config(field_name="invites") ) @@ -3234,6 +3268,7 @@ class ChannelConfig(DataClassJsonMixin): reminders: bool = dc_field(metadata=dc_config(field_name="reminders")) replies: bool = dc_field(metadata=dc_config(field_name="replies")) search: bool = dc_field(metadata=dc_config(field_name="search")) + shared_locations: bool = dc_field(metadata=dc_config(field_name="shared_locations")) skip_last_msg_update_for_system_msgs: bool = dc_field( metadata=dc_config(field_name="skip_last_msg_update_for_system_msgs") ) @@ -3307,6 +3342,7 @@ class ChannelConfigWithInfo(DataClassJsonMixin): reminders: bool = dc_field(metadata=dc_config(field_name="reminders")) replies: bool = dc_field(metadata=dc_config(field_name="replies")) search: bool = dc_field(metadata=dc_config(field_name="search")) + shared_locations: bool = dc_field(metadata=dc_config(field_name="shared_locations")) skip_last_msg_update_for_system_msgs: bool = dc_field( metadata=dc_config(field_name="skip_last_msg_update_for_system_msgs") ) @@ -3807,6 +3843,7 @@ class ChannelOwnCapability: ) SEND_TYPING_EVENTS: Final[ChannelOwnCapabilityType] = "send-typing-events" SET_CHANNEL_COOLDOWN: Final[ChannelOwnCapabilityType] = "set-channel-cooldown" + SHARE_LOCATION: Final[ChannelOwnCapabilityType] = "share-location" SKIP_SLOW_MODE: Final[ChannelOwnCapabilityType] = "skip-slow-mode" SLOW_MODE: Final[ChannelOwnCapabilityType] = "slow-mode" TYPING_EVENTS: Final[ChannelOwnCapabilityType] = "typing-events" @@ -3970,6 +4007,9 @@ class ChannelStateResponse(DataClassJsonMixin): watcher_count: Optional[int] = dc_field( default=None, metadata=dc_config(field_name="watcher_count") ) + active_live_locations: "Optional[List[SharedLocationResponseData]]" = dc_field( + default=None, metadata=dc_config(field_name="active_live_locations") + ) pending_messages: "Optional[List[PendingMessageResponse]]" = dc_field( default=None, metadata=dc_config(field_name="pending_messages") ) @@ -4020,6 +4060,9 @@ class ChannelStateResponseFields(DataClassJsonMixin): watcher_count: Optional[int] = dc_field( default=None, metadata=dc_config(field_name="watcher_count") ) + active_live_locations: "Optional[List[SharedLocationResponseData]]" = dc_field( + default=None, metadata=dc_config(field_name="active_live_locations") + ) pending_messages: "Optional[List[PendingMessageResponse]]" = dc_field( default=None, metadata=dc_config(field_name="pending_messages") ) @@ -4099,6 +4142,7 @@ class ChannelTypeConfig(DataClassJsonMixin): reminders: bool = dc_field(metadata=dc_config(field_name="reminders")) replies: bool = dc_field(metadata=dc_config(field_name="replies")) search: bool = dc_field(metadata=dc_config(field_name="search")) + shared_locations: bool = dc_field(metadata=dc_config(field_name="shared_locations")) skip_last_msg_update_for_system_msgs: bool = dc_field( metadata=dc_config(field_name="skip_last_msg_update_for_system_msgs") ) @@ -4340,7 +4384,7 @@ class CheckResponse(DataClassJsonMixin): task_id: Optional[str] = dc_field( default=None, metadata=dc_config(field_name="task_id") ) - item: "Optional[ReviewQueueItem]" = dc_field( + item: "Optional[ReviewQueueItemResponse]" = dc_field( default=None, metadata=dc_config(field_name="item") ) @@ -4507,6 +4551,9 @@ class ConfigOverrides(DataClassJsonMixin): replies: Optional[bool] = dc_field( default=None, metadata=dc_config(field_name="replies") ) + shared_locations: Optional[bool] = dc_field( + default=None, metadata=dc_config(field_name="shared_locations") + ) typing_events: Optional[bool] = dc_field( default=None, metadata=dc_config(field_name="typing_events") ) @@ -4706,6 +4753,9 @@ class CreateChannelTypeRequest(DataClassJsonMixin): search: Optional[bool] = dc_field( default=None, metadata=dc_config(field_name="search") ) + shared_locations: Optional[bool] = dc_field( + default=None, metadata=dc_config(field_name="shared_locations") + ) skip_last_msg_update_for_system_msgs: Optional[bool] = dc_field( default=None, metadata=dc_config(field_name="skip_last_msg_update_for_system_msgs"), @@ -4769,6 +4819,7 @@ class CreateChannelTypeResponse(DataClassJsonMixin): reminders: bool = dc_field(metadata=dc_config(field_name="reminders")) replies: bool = dc_field(metadata=dc_config(field_name="replies")) search: bool = dc_field(metadata=dc_config(field_name="search")) + shared_locations: bool = dc_field(metadata=dc_config(field_name="shared_locations")) skip_last_msg_update_for_system_msgs: bool = dc_field( metadata=dc_config(field_name="skip_last_msg_update_for_system_msgs") ) @@ -6460,6 +6511,36 @@ class GeofenceSettingsResponse(DataClassJsonMixin): names: List[str] = dc_field(metadata=dc_config(field_name="names")) +@dataclass +class GetActiveCallsStatusResponse(DataClassJsonMixin): + duration: str = dc_field(metadata=dc_config(field_name="duration")) + end_time: datetime = dc_field( + metadata=dc_config( + field_name="end_time", + encoder=encode_datetime, + decoder=datetime_from_unix_ns, + mm_field=fields.DateTime(format="iso"), + ) + ) + start_time: datetime = dc_field( + metadata=dc_config( + field_name="start_time", + encoder=encode_datetime, + decoder=datetime_from_unix_ns, + mm_field=fields.DateTime(format="iso"), + ) + ) + call_cids: "Dict[str, Dict[str, str]]" = dc_field( + metadata=dc_config(field_name="call_cids") + ) + metrics: "Optional[ActiveCallsMetrics]" = dc_field( + default=None, metadata=dc_config(field_name="metrics") + ) + summary: "Optional[ActiveCallsSummary]" = dc_field( + default=None, metadata=dc_config(field_name="summary") + ) + + @dataclass class GetApplicationResponse(DataClassJsonMixin): duration: str = dc_field(metadata=dc_config(field_name="duration")) @@ -6581,6 +6662,7 @@ class GetChannelTypeResponse(DataClassJsonMixin): reminders: bool = dc_field(metadata=dc_config(field_name="reminders")) replies: bool = dc_field(metadata=dc_config(field_name="replies")) search: bool = dc_field(metadata=dc_config(field_name="search")) + shared_locations: bool = dc_field(metadata=dc_config(field_name="shared_locations")) skip_last_msg_update_for_system_msgs: bool = dc_field( metadata=dc_config(field_name="skip_last_msg_update_for_system_msgs") ) @@ -6737,12 +6819,6 @@ class GetOGResponse(DataClassJsonMixin): image_url: Optional[str] = dc_field( default=None, metadata=dc_config(field_name="image_url") ) - latitude: Optional[float] = dc_field( - default=None, metadata=dc_config(field_name="latitude") - ) - longitude: Optional[float] = dc_field( - default=None, metadata=dc_config(field_name="longitude") - ) og_scrape_url: Optional[str] = dc_field( default=None, metadata=dc_config(field_name="og_scrape_url") ) @@ -6755,9 +6831,6 @@ class GetOGResponse(DataClassJsonMixin): pretext: Optional[str] = dc_field( default=None, metadata=dc_config(field_name="pretext") ) - stopped_sharing: Optional[bool] = dc_field( - default=None, metadata=dc_config(field_name="stopped_sharing") - ) text: Optional[str] = dc_field(default=None, metadata=dc_config(field_name="text")) thumb_url: Optional[str] = dc_field( default=None, metadata=dc_config(field_name="thumb_url") @@ -7146,6 +7219,15 @@ class ImportTaskHistory(DataClassJsonMixin): prev_state: str = dc_field(metadata=dc_config(field_name="prev_state")) +@dataclass +class JoinCallAPIMetrics(DataClassJsonMixin): + failures: float = dc_field(metadata=dc_config(field_name="failures")) + total: float = dc_field(metadata=dc_config(field_name="total")) + latency: "Optional[ActiveCallsLatencyStats]" = dc_field( + default=None, metadata=dc_config(field_name="latency") + ) + + @dataclass class Label(DataClassJsonMixin): name: str = dc_field(metadata=dc_config(field_name="name")) @@ -7219,12 +7301,18 @@ class LimitInfo(DataClassJsonMixin): @dataclass class LimitsSettings(DataClassJsonMixin): + max_participants_exclude_roles: List[str] = dc_field( + metadata=dc_config(field_name="max_participants_exclude_roles") + ) max_duration_seconds: Optional[int] = dc_field( default=None, metadata=dc_config(field_name="max_duration_seconds") ) max_participants: Optional[int] = dc_field( default=None, metadata=dc_config(field_name="max_participants") ) + max_participants_exclude_owner: Optional[bool] = dc_field( + default=None, metadata=dc_config(field_name="max_participants_exclude_owner") + ) @dataclass @@ -7235,16 +7323,28 @@ class LimitsSettingsRequest(DataClassJsonMixin): max_participants: Optional[int] = dc_field( default=None, metadata=dc_config(field_name="max_participants") ) + max_participants_exclude_owner: Optional[bool] = dc_field( + default=None, metadata=dc_config(field_name="max_participants_exclude_owner") + ) + max_participants_exclude_roles: Optional[List[str]] = dc_field( + default=None, metadata=dc_config(field_name="max_participants_exclude_roles") + ) @dataclass class LimitsSettingsResponse(DataClassJsonMixin): + max_participants_exclude_roles: List[str] = dc_field( + metadata=dc_config(field_name="max_participants_exclude_roles") + ) max_duration_seconds: Optional[int] = dc_field( default=None, metadata=dc_config(field_name="max_duration_seconds") ) max_participants: Optional[int] = dc_field( default=None, metadata=dc_config(field_name="max_participants") ) + max_participants_exclude_owner: Optional[bool] = dc_field( + default=None, metadata=dc_config(field_name="max_participants_exclude_owner") + ) @dataclass @@ -7660,6 +7760,9 @@ class Message(DataClassJsonMixin): reminder: "Optional[MessageReminder]" = dc_field( default=None, metadata=dc_config(field_name="reminder") ) + shared_location: "Optional[SharedLocation]" = dc_field( + default=None, metadata=dc_config(field_name="shared_location") + ) user: "Optional[User]" = dc_field( default=None, metadata=dc_config(field_name="user") ) @@ -8061,6 +8164,9 @@ class MessageRequest(DataClassJsonMixin): custom: Optional[Dict[str, object]] = dc_field( default=None, metadata=dc_config(field_name="custom") ) + shared_location: "Optional[SharedLocation]" = dc_field( + default=None, metadata=dc_config(field_name="shared_location") + ) user: "Optional[UserRequest]" = dc_field( default=None, metadata=dc_config(field_name="user") ) @@ -8201,6 +8307,9 @@ class MessageResponse(DataClassJsonMixin): reminder: "Optional[ReminderResponseData]" = dc_field( default=None, metadata=dc_config(field_name="reminder") ) + shared_location: "Optional[SharedLocationResponseData]" = dc_field( + default=None, metadata=dc_config(field_name="shared_location") + ) @dataclass @@ -8437,6 +8546,9 @@ class MessageWithChannelResponse(DataClassJsonMixin): reminder: "Optional[ReminderResponseData]" = dc_field( default=None, metadata=dc_config(field_name="reminder") ) + shared_location: "Optional[SharedLocationResponseData]" = dc_field( + default=None, metadata=dc_config(field_name="shared_location") + ) @dataclass @@ -8542,7 +8654,7 @@ class ModerationFlagResponse(DataClassJsonMixin): moderation_payload: "Optional[ModerationPayload]" = dc_field( default=None, metadata=dc_config(field_name="moderation_payload") ) - review_queue_item: "Optional[ReviewQueueItem]" = dc_field( + review_queue_item: "Optional[ReviewQueueItemResponse]" = dc_field( default=None, metadata=dc_config(field_name="review_queue_item") ) user: "Optional[UserResponse]" = dc_field( @@ -8912,6 +9024,9 @@ class OwnUser(DataClassJsonMixin): devices: "List[Device]" = dc_field(metadata=dc_config(field_name="devices")) mutes: "List[UserMute]" = dc_field(metadata=dc_config(field_name="mutes")) custom: Dict[str, object] = dc_field(metadata=dc_config(field_name="custom")) + total_unread_count_by_team: "Dict[str, int]" = dc_field( + metadata=dc_config(field_name="total_unread_count_by_team") + ) deactivated_at: Optional[datetime] = dc_field( default=None, metadata=dc_config( @@ -9063,6 +9178,9 @@ class OwnUserResponse(DataClassJsonMixin): teams_role: "Optional[Dict[str, str]]" = dc_field( default=None, metadata=dc_config(field_name="teams_role") ) + total_unread_count_by_team: "Optional[Dict[str, int]]" = dc_field( + default=None, metadata=dc_config(field_name="total_unread_count_by_team") + ) @dataclass @@ -9515,6 +9633,26 @@ class PrivacySettingsResponse(DataClassJsonMixin): ) +@dataclass +class PublisherAllMetrics(DataClassJsonMixin): + audio: "Optional[PublisherAudioMetrics]" = dc_field( + default=None, metadata=dc_config(field_name="audio") + ) + rtt_ms: "Optional[ActiveCallsLatencyStats]" = dc_field( + default=None, metadata=dc_config(field_name="rtt_ms") + ) + video: "Optional[PublisherVideoMetrics]" = dc_field( + default=None, metadata=dc_config(field_name="video") + ) + + +@dataclass +class PublisherAudioMetrics(DataClassJsonMixin): + jitter_ms: "Optional[ActiveCallsLatencyStats]" = dc_field( + default=None, metadata=dc_config(field_name="jitter_ms") + ) + + @dataclass class PublisherStatsResponse(DataClassJsonMixin): total: int = dc_field(metadata=dc_config(field_name="total")) @@ -9524,6 +9662,26 @@ class PublisherStatsResponse(DataClassJsonMixin): ) +@dataclass +class PublisherVideoMetrics(DataClassJsonMixin): + fps_30: "Optional[ActiveCallsFPSStats]" = dc_field( + default=None, metadata=dc_config(field_name="fps_30") + ) + frame_encoding_time_ms: "Optional[ActiveCallsLatencyStats]" = dc_field( + default=None, metadata=dc_config(field_name="frame_encoding_time_ms") + ) + jitter_ms: "Optional[ActiveCallsLatencyStats]" = dc_field( + default=None, metadata=dc_config(field_name="jitter_ms") + ) + + +@dataclass +class PublishersMetrics(DataClassJsonMixin): + all: "Optional[PublisherAllMetrics]" = dc_field( + default=None, metadata=dc_config(field_name="all") + ) + + @dataclass class PushConfig(DataClassJsonMixin): version: str = dc_field(metadata=dc_config(field_name="version")) @@ -11137,6 +11295,7 @@ class ReviewQueueItem(DataClassJsonMixin): flags: "List[Flag]" = dc_field(metadata=dc_config(field_name="flags")) languages: List[str] = dc_field(metadata=dc_config(field_name="languages")) teams: List[str] = dc_field(metadata=dc_config(field_name="teams")) + completed_at: "NullTime" = dc_field(metadata=dc_config(field_name="completed_at")) reviewed_at: "NullTime" = dc_field(metadata=dc_config(field_name="reviewed_at")) activity: "Optional[EnrichedActivity]" = dc_field( default=None, metadata=dc_config(field_name="activity") @@ -11740,6 +11899,9 @@ class SearchResultMessage(DataClassJsonMixin): reminder: "Optional[ReminderResponseData]" = dc_field( default=None, metadata=dc_config(field_name="reminder") ) + shared_location: "Optional[SharedLocationResponseData]" = dc_field( + default=None, metadata=dc_config(field_name="shared_location") + ) @dataclass @@ -11959,6 +12121,148 @@ class ShadowBlockActionRequest(DataClassJsonMixin): pass +@dataclass +class SharedLocation(DataClassJsonMixin): + channel_cid: str = dc_field(metadata=dc_config(field_name="channel_cid")) + created_at: datetime = dc_field( + metadata=dc_config( + field_name="created_at", + encoder=encode_datetime, + decoder=datetime_from_unix_ns, + mm_field=fields.DateTime(format="iso"), + ) + ) + created_by_device_id: str = dc_field( + metadata=dc_config(field_name="created_by_device_id") + ) + message_id: str = dc_field(metadata=dc_config(field_name="message_id")) + updated_at: datetime = dc_field( + metadata=dc_config( + field_name="updated_at", + encoder=encode_datetime, + decoder=datetime_from_unix_ns, + mm_field=fields.DateTime(format="iso"), + ) + ) + user_id: str = dc_field(metadata=dc_config(field_name="user_id")) + end_at: Optional[datetime] = dc_field( + default=None, + metadata=dc_config( + field_name="end_at", + encoder=encode_datetime, + decoder=datetime_from_unix_ns, + mm_field=fields.DateTime(format="iso"), + ), + ) + latitude: Optional[float] = dc_field( + default=None, metadata=dc_config(field_name="latitude") + ) + longitude: Optional[float] = dc_field( + default=None, metadata=dc_config(field_name="longitude") + ) + channel: "Optional[Channel]" = dc_field( + default=None, metadata=dc_config(field_name="channel") + ) + message: "Optional[Message]" = dc_field( + default=None, metadata=dc_config(field_name="message") + ) + + +@dataclass +class SharedLocationResponse(DataClassJsonMixin): + channel_cid: str = dc_field(metadata=dc_config(field_name="channel_cid")) + created_at: datetime = dc_field( + metadata=dc_config( + field_name="created_at", + encoder=encode_datetime, + decoder=datetime_from_unix_ns, + mm_field=fields.DateTime(format="iso"), + ) + ) + created_by_device_id: str = dc_field( + metadata=dc_config(field_name="created_by_device_id") + ) + duration: str = dc_field(metadata=dc_config(field_name="duration")) + latitude: float = dc_field(metadata=dc_config(field_name="latitude")) + longitude: float = dc_field(metadata=dc_config(field_name="longitude")) + message_id: str = dc_field(metadata=dc_config(field_name="message_id")) + updated_at: datetime = dc_field( + metadata=dc_config( + field_name="updated_at", + encoder=encode_datetime, + decoder=datetime_from_unix_ns, + mm_field=fields.DateTime(format="iso"), + ) + ) + user_id: str = dc_field(metadata=dc_config(field_name="user_id")) + end_at: Optional[datetime] = dc_field( + default=None, + metadata=dc_config( + field_name="end_at", + encoder=encode_datetime, + decoder=datetime_from_unix_ns, + mm_field=fields.DateTime(format="iso"), + ), + ) + channel: "Optional[ChannelResponse]" = dc_field( + default=None, metadata=dc_config(field_name="channel") + ) + message: "Optional[MessageResponse]" = dc_field( + default=None, metadata=dc_config(field_name="message") + ) + + +@dataclass +class SharedLocationResponseData(DataClassJsonMixin): + channel_cid: str = dc_field(metadata=dc_config(field_name="channel_cid")) + created_at: datetime = dc_field( + metadata=dc_config( + field_name="created_at", + encoder=encode_datetime, + decoder=datetime_from_unix_ns, + mm_field=fields.DateTime(format="iso"), + ) + ) + created_by_device_id: str = dc_field( + metadata=dc_config(field_name="created_by_device_id") + ) + latitude: float = dc_field(metadata=dc_config(field_name="latitude")) + longitude: float = dc_field(metadata=dc_config(field_name="longitude")) + message_id: str = dc_field(metadata=dc_config(field_name="message_id")) + updated_at: datetime = dc_field( + metadata=dc_config( + field_name="updated_at", + encoder=encode_datetime, + decoder=datetime_from_unix_ns, + mm_field=fields.DateTime(format="iso"), + ) + ) + user_id: str = dc_field(metadata=dc_config(field_name="user_id")) + end_at: Optional[datetime] = dc_field( + default=None, + metadata=dc_config( + field_name="end_at", + encoder=encode_datetime, + decoder=datetime_from_unix_ns, + mm_field=fields.DateTime(format="iso"), + ), + ) + channel: "Optional[ChannelResponse]" = dc_field( + default=None, metadata=dc_config(field_name="channel") + ) + message: "Optional[MessageResponse]" = dc_field( + default=None, metadata=dc_config(field_name="message") + ) + + +@dataclass +class SharedLocationsResponse(DataClassJsonMixin): + duration: str = dc_field(metadata=dc_config(field_name="duration")) + active_live_locations: "List[SharedLocationResponseData]" = dc_field( + metadata=dc_config(field_name="active_live_locations") + ) + + @dataclass class ShowChannelRequest(DataClassJsonMixin): user_id: Optional[str] = dc_field( @@ -12253,11 +12557,37 @@ class SubmitActionRequest(DataClassJsonMixin): @dataclass class SubmitActionResponse(DataClassJsonMixin): duration: str = dc_field(metadata=dc_config(field_name="duration")) - item: "Optional[ReviewQueueItem]" = dc_field( + item: "Optional[ReviewQueueItemResponse]" = dc_field( default=None, metadata=dc_config(field_name="item") ) +@dataclass +class SubscriberAllMetrics(DataClassJsonMixin): + audio: "Optional[SubscriberAudioMetrics]" = dc_field( + default=None, metadata=dc_config(field_name="audio") + ) + rtt_ms: "Optional[ActiveCallsLatencyStats]" = dc_field( + default=None, metadata=dc_config(field_name="rtt_ms") + ) + video: "Optional[SubscriberVideoMetrics]" = dc_field( + default=None, metadata=dc_config(field_name="video") + ) + + +@dataclass +class SubscriberAudioMetrics(DataClassJsonMixin): + concealment_pct: "Optional[ActiveCallsLatencyStats]" = dc_field( + default=None, metadata=dc_config(field_name="concealment_pct") + ) + jitter_ms: "Optional[ActiveCallsLatencyStats]" = dc_field( + default=None, metadata=dc_config(field_name="jitter_ms") + ) + packets_lost_pct: "Optional[ActiveCallsLatencyStats]" = dc_field( + default=None, metadata=dc_config(field_name="packets_lost_pct") + ) + + @dataclass class SubscriberStatsResponse(DataClassJsonMixin): total: int = dc_field(metadata=dc_config(field_name="total")) @@ -12267,6 +12597,32 @@ class SubscriberStatsResponse(DataClassJsonMixin): unique: int = dc_field(metadata=dc_config(field_name="unique")) +@dataclass +class SubscriberVideoMetrics(DataClassJsonMixin): + fps_30: "Optional[ActiveCallsFPSStats]" = dc_field( + default=None, metadata=dc_config(field_name="fps_30") + ) + frame_decoding_time_ms: "Optional[ActiveCallsLatencyStats]" = dc_field( + default=None, metadata=dc_config(field_name="frame_decoding_time_ms") + ) + freeze_duration_seconds: "Optional[ActiveCallsLatencyStats]" = dc_field( + default=None, metadata=dc_config(field_name="freeze_duration_seconds") + ) + jitter_ms: "Optional[ActiveCallsLatencyStats]" = dc_field( + default=None, metadata=dc_config(field_name="jitter_ms") + ) + packets_lost_pct: "Optional[ActiveCallsLatencyStats]" = dc_field( + default=None, metadata=dc_config(field_name="packets_lost_pct") + ) + + +@dataclass +class SubscribersMetrics(DataClassJsonMixin): + all: "Optional[SubscriberAllMetrics]" = dc_field( + default=None, metadata=dc_config(field_name="all") + ) + + @dataclass class TargetResolution(DataClassJsonMixin): bitrate: int = dc_field(metadata=dc_config(field_name="bitrate")) @@ -12792,6 +13148,9 @@ class UnreadCountsResponse(DataClassJsonMixin): threads: "List[UnreadCountsThread]" = dc_field( metadata=dc_config(field_name="threads") ) + total_unread_count_by_team: "Dict[str, int]" = dc_field( + metadata=dc_config(field_name="total_unread_count_by_team") + ) @dataclass @@ -13213,6 +13572,9 @@ class UpdateChannelTypeRequest(DataClassJsonMixin): search: Optional[bool] = dc_field( default=None, metadata=dc_config(field_name="search") ) + shared_locations: Optional[bool] = dc_field( + default=None, metadata=dc_config(field_name="shared_locations") + ) skip_last_msg_update_for_system_msgs: Optional[bool] = dc_field( default=None, metadata=dc_config(field_name="skip_last_msg_update_for_system_msgs"), @@ -13282,6 +13644,7 @@ class UpdateChannelTypeResponse(DataClassJsonMixin): reminders: bool = dc_field(metadata=dc_config(field_name="reminders")) replies: bool = dc_field(metadata=dc_config(field_name="replies")) search: bool = dc_field(metadata=dc_config(field_name="search")) + shared_locations: bool = dc_field(metadata=dc_config(field_name="shared_locations")) skip_last_msg_update_for_system_msgs: bool = dc_field( metadata=dc_config(field_name="skip_last_msg_update_for_system_msgs") ) @@ -13367,6 +13730,29 @@ class UpdateExternalStorageResponse(DataClassJsonMixin): type: str = dc_field(metadata=dc_config(field_name="type")) +@dataclass +class UpdateLiveLocationRequest(DataClassJsonMixin): + created_by_device_id: str = dc_field( + metadata=dc_config(field_name="created_by_device_id") + ) + message_id: str = dc_field(metadata=dc_config(field_name="message_id")) + end_at: Optional[datetime] = dc_field( + default=None, + metadata=dc_config( + field_name="end_at", + encoder=encode_datetime, + decoder=datetime_from_unix_ns, + mm_field=fields.DateTime(format="iso"), + ), + ) + latitude: Optional[float] = dc_field( + default=None, metadata=dc_config(field_name="latitude") + ) + longitude: Optional[float] = dc_field( + default=None, metadata=dc_config(field_name="longitude") + ) + + @dataclass class UpdateMemberPartialRequest(DataClassJsonMixin): unset: Optional[List[str]] = dc_field( @@ -14747,6 +15133,9 @@ class WrappedUnreadCountsResponse(DataClassJsonMixin): threads: "List[UnreadCountsThread]" = dc_field( metadata=dc_config(field_name="threads") ) + total_unread_count_by_team: "Dict[str, int]" = dc_field( + metadata=dc_config(field_name="total_unread_count_by_team") + ) @dataclass diff --git a/getstream/video/rest_client.py b/getstream/video/rest_client.py index 47684459..775743e4 100644 --- a/getstream/video/rest_client.py +++ b/getstream/video/rest_client.py @@ -21,6 +21,11 @@ def __init__(self, api_key: str, base_url: str, timeout: float, token: str): token=token, ) + def get_active_calls_status(self) -> StreamResponse[GetActiveCallsStatusResponse]: + return self.get( + "/api/v2/video/active_calls_status", GetActiveCallsStatusResponse + ) + def query_user_feedback( self, full: Optional[bool] = None, diff --git a/tests/test_video_examples.py b/tests/test_video_examples.py index 2bf10142..362d5f93 100644 --- a/tests/test_video_examples.py +++ b/tests/test_video_examples.py @@ -338,6 +338,14 @@ def test_start_stop_frame_recording(client: Stream): ) +def test_call_status(client): + import json + + response = client.video.get_active_calls_status() + print(json.dumps(response.data.to_json())) + print(response) + + def test_query_call_participants(client): call = client.video.call("default", "call-id") call.get_or_create( From d381180b52cb2dc3fbcb5a287d82145684c3cdc0 Mon Sep 17 00:00:00 2001 From: Tommaso Barbugli Date: Fri, 11 Jul 2025 11:24:07 +0200 Subject: [PATCH 08/15] codegen --- getstream/models/__init__.py | 20 ++++---------------- tests/test_video_examples.py | 8 -------- 2 files changed, 4 insertions(+), 24 deletions(-) diff --git a/getstream/models/__init__.py b/getstream/models/__init__.py index 1fc76566..9273a7cd 100644 --- a/getstream/models/__init__.py +++ b/getstream/models/__init__.py @@ -234,8 +234,7 @@ class ActiveCallsFPSStats(DataClassJsonMixin): @dataclass class ActiveCallsLatencyStats(DataClassJsonMixin): p50: float = dc_field(metadata=dc_config(field_name="p50")) - p95: float = dc_field(metadata=dc_config(field_name="p95")) - p99: float = dc_field(metadata=dc_config(field_name="p99")) + p90: float = dc_field(metadata=dc_config(field_name="p90")) @dataclass @@ -515,7 +514,7 @@ 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.moderation_logs.error", metadata=dc_config(field_name="type") + default="export.users.error", metadata=dc_config(field_name="type") ) received_at: Optional[datetime] = dc_field( default=None, @@ -1829,8 +1828,8 @@ class CallParticipant(DataClassJsonMixin): ) ) online: bool = dc_field(metadata=dc_config(field_name="online")) - role: str = dc_field(metadata=dc_config(field_name="role")) role: str = dc_field(metadata=dc_config(field_name="Role")) + role: str = dc_field(metadata=dc_config(field_name="role")) user_session_id: str = dc_field(metadata=dc_config(field_name="UserSessionID")) custom: Dict[str, object] = dc_field(metadata=dc_config(field_name="custom")) teams_role: "Dict[str, str]" = dc_field(metadata=dc_config(field_name="teams_role")) @@ -6530,9 +6529,6 @@ class GetActiveCallsStatusResponse(DataClassJsonMixin): mm_field=fields.DateTime(format="iso"), ) ) - call_cids: "Dict[str, Dict[str, str]]" = dc_field( - metadata=dc_config(field_name="call_cids") - ) metrics: "Optional[ActiveCallsMetrics]" = dc_field( default=None, metadata=dc_config(field_name="metrics") ) @@ -8002,9 +7998,7 @@ class MessageNewEvent(DataClassJsonMixin): ) ) watcher_count: int = dc_field(metadata=dc_config(field_name="watcher_count")) - type: str = dc_field( - default="notification.thread_message_new", metadata=dc_config(field_name="type") - ) + type: str = dc_field(default="message.new", metadata=dc_config(field_name="type")) team: Optional[str] = dc_field(default=None, metadata=dc_config(field_name="team")) thread_participants: "Optional[List[User]]" = dc_field( default=None, metadata=dc_config(field_name="thread_participants") @@ -12602,12 +12596,6 @@ class SubscriberVideoMetrics(DataClassJsonMixin): fps_30: "Optional[ActiveCallsFPSStats]" = dc_field( default=None, metadata=dc_config(field_name="fps_30") ) - frame_decoding_time_ms: "Optional[ActiveCallsLatencyStats]" = dc_field( - default=None, metadata=dc_config(field_name="frame_decoding_time_ms") - ) - freeze_duration_seconds: "Optional[ActiveCallsLatencyStats]" = dc_field( - default=None, metadata=dc_config(field_name="freeze_duration_seconds") - ) jitter_ms: "Optional[ActiveCallsLatencyStats]" = dc_field( default=None, metadata=dc_config(field_name="jitter_ms") ) diff --git a/tests/test_video_examples.py b/tests/test_video_examples.py index 362d5f93..2bf10142 100644 --- a/tests/test_video_examples.py +++ b/tests/test_video_examples.py @@ -338,14 +338,6 @@ def test_start_stop_frame_recording(client: Stream): ) -def test_call_status(client): - import json - - response = client.video.get_active_calls_status() - print(json.dumps(response.data.to_json())) - print(response) - - def test_query_call_participants(client): call = client.video.call("default", "call-id") call.get_or_create( From 70ac662c841cb6eef7def126373caa45b39ea9d1 Mon Sep 17 00:00:00 2001 From: github-actions Date: Fri, 11 Jul 2025 09:29:46 +0000 Subject: [PATCH 09/15] chore(release): 2.2.2 --- getstream/version.py | 2 +- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/getstream/version.py b/getstream/version.py index 3f755ed2..4c337c20 100644 --- a/getstream/version.py +++ b/getstream/version.py @@ -1 +1 @@ -VERSION = "2.2.1" +VERSION = "2.2.2" diff --git a/pyproject.toml b/pyproject.toml index 03a317c7..1901e2f0 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "getstream" -version = "2.2.1" +version = "2.2.2" description = "" authors = [ { name = "sachaarbonel", email = "sacha.arbonel@hotmail.fr" }, From a47f242e4f3a099ee0f777d5ee8fed20d2fb9cc2 Mon Sep 17 00:00:00 2001 From: Vishal Narkhede Date: Wed, 13 Aug 2025 18:35:49 +0300 Subject: [PATCH 10/15] sync with openapi spec --- getstream/chat/rest_client.py | 245 +---------- getstream/common/rest_client.py | 248 ++++++++++- getstream/models/__init__.py | 735 +++++++++++++++++++++++++++++--- uv.lock | 2 +- 4 files changed, 908 insertions(+), 322 deletions(-) diff --git a/getstream/chat/rest_client.py b/getstream/chat/rest_client.py index db83b21a..fe8c4e97 100644 --- a/getstream/chat/rest_client.py +++ b/getstream/chat/rest_client.py @@ -1162,7 +1162,7 @@ def cast_poll_vote( json=json, ) - def remove_poll_vote( + def delete_poll_vote( self, message_id: str, poll_id: str, vote_id: str, user_id: Optional[str] = None ) -> StreamResponse[PollVoteResponse]: query_params = build_query_param(user_id=user_id) @@ -1316,249 +1316,6 @@ def unmute_channel( "/api/v2/chat/moderation/unmute/channel", UnmuteResponse, json=json ) - def create_poll( - self, - name: str, - allow_answers: Optional[bool] = None, - allow_user_suggested_options: Optional[bool] = None, - description: Optional[str] = None, - enforce_unique_vote: Optional[bool] = None, - id: Optional[str] = None, - is_closed: Optional[bool] = None, - max_votes_allowed: Optional[int] = None, - user_id: Optional[str] = None, - voting_visibility: Optional[str] = None, - options: Optional[List[PollOptionInput]] = None, - custom: Optional[Dict[str, object]] = None, - user: Optional[UserRequest] = None, - ) -> StreamResponse[PollResponse]: - json = build_body_dict( - name=name, - allow_answers=allow_answers, - allow_user_suggested_options=allow_user_suggested_options, - description=description, - enforce_unique_vote=enforce_unique_vote, - id=id, - is_closed=is_closed, - max_votes_allowed=max_votes_allowed, - user_id=user_id, - voting_visibility=voting_visibility, - options=options, - custom=custom, - user=user, - ) - - return self.post("/api/v2/chat/polls", PollResponse, json=json) - - def update_poll( - self, - id: str, - name: str, - allow_answers: Optional[bool] = None, - allow_user_suggested_options: Optional[bool] = None, - description: Optional[str] = None, - enforce_unique_vote: Optional[bool] = None, - is_closed: Optional[bool] = None, - max_votes_allowed: Optional[int] = None, - user_id: Optional[str] = None, - voting_visibility: Optional[str] = None, - options: Optional[List[PollOptionRequest]] = None, - custom: Optional[Dict[str, object]] = None, - user: Optional[UserRequest] = None, - ) -> StreamResponse[PollResponse]: - json = build_body_dict( - id=id, - name=name, - allow_answers=allow_answers, - allow_user_suggested_options=allow_user_suggested_options, - description=description, - enforce_unique_vote=enforce_unique_vote, - is_closed=is_closed, - max_votes_allowed=max_votes_allowed, - user_id=user_id, - voting_visibility=voting_visibility, - options=options, - custom=custom, - user=user, - ) - - return self.put("/api/v2/chat/polls", PollResponse, json=json) - - def query_polls( - self, - user_id: Optional[str] = None, - limit: Optional[int] = None, - next: Optional[str] = None, - prev: Optional[str] = None, - sort: Optional[List[SortParamRequest]] = None, - filter: Optional[Dict[str, object]] = None, - ) -> StreamResponse[QueryPollsResponse]: - query_params = build_query_param(user_id=user_id) - json = build_body_dict( - limit=limit, next=next, prev=prev, sort=sort, filter=filter - ) - - return self.post( - "/api/v2/chat/polls/query", - QueryPollsResponse, - query_params=query_params, - json=json, - ) - - def delete_poll( - self, poll_id: str, user_id: Optional[str] = None - ) -> StreamResponse[Response]: - query_params = build_query_param(user_id=user_id) - path_params = { - "poll_id": poll_id, - } - - return self.delete( - "/api/v2/chat/polls/{poll_id}", - Response, - query_params=query_params, - path_params=path_params, - ) - - def get_poll( - self, poll_id: str, user_id: Optional[str] = None - ) -> StreamResponse[PollResponse]: - query_params = build_query_param(user_id=user_id) - path_params = { - "poll_id": poll_id, - } - - return self.get( - "/api/v2/chat/polls/{poll_id}", - PollResponse, - query_params=query_params, - path_params=path_params, - ) - - def update_poll_partial( - self, - poll_id: str, - user_id: Optional[str] = None, - unset: Optional[List[str]] = None, - set: Optional[Dict[str, object]] = None, - user: Optional[UserRequest] = None, - ) -> StreamResponse[PollResponse]: - path_params = { - "poll_id": poll_id, - } - json = build_body_dict(user_id=user_id, unset=unset, set=set, user=user) - - return self.patch( - "/api/v2/chat/polls/{poll_id}", - PollResponse, - path_params=path_params, - json=json, - ) - - def create_poll_option( - self, - poll_id: str, - text: str, - position: Optional[int] = None, - user_id: Optional[str] = None, - custom: Optional[Dict[str, object]] = None, - user: Optional[UserRequest] = None, - ) -> StreamResponse[PollOptionResponse]: - path_params = { - "poll_id": poll_id, - } - json = build_body_dict( - text=text, position=position, user_id=user_id, custom=custom, user=user - ) - - return self.post( - "/api/v2/chat/polls/{poll_id}/options", - PollOptionResponse, - path_params=path_params, - json=json, - ) - - def update_poll_option( - self, - poll_id: str, - id: str, - text: str, - user_id: Optional[str] = None, - custom: Optional[Dict[str, object]] = None, - user: Optional[UserRequest] = None, - ) -> StreamResponse[PollOptionResponse]: - path_params = { - "poll_id": poll_id, - } - json = build_body_dict( - id=id, text=text, user_id=user_id, custom=custom, user=user - ) - - return self.put( - "/api/v2/chat/polls/{poll_id}/options", - PollOptionResponse, - path_params=path_params, - json=json, - ) - - def delete_poll_option( - self, poll_id: str, option_id: str, user_id: Optional[str] = None - ) -> StreamResponse[Response]: - query_params = build_query_param(user_id=user_id) - path_params = { - "poll_id": poll_id, - "option_id": option_id, - } - - return self.delete( - "/api/v2/chat/polls/{poll_id}/options/{option_id}", - Response, - query_params=query_params, - path_params=path_params, - ) - - def get_poll_option( - self, poll_id: str, option_id: str, user_id: Optional[str] = None - ) -> StreamResponse[PollOptionResponse]: - query_params = build_query_param(user_id=user_id) - path_params = { - "poll_id": poll_id, - "option_id": option_id, - } - - return self.get( - "/api/v2/chat/polls/{poll_id}/options/{option_id}", - PollOptionResponse, - query_params=query_params, - path_params=path_params, - ) - - def query_poll_votes( - self, - poll_id: str, - user_id: Optional[str] = None, - limit: Optional[int] = None, - next: Optional[str] = None, - prev: Optional[str] = None, - sort: Optional[List[SortParamRequest]] = None, - filter: Optional[Dict[str, object]] = None, - ) -> StreamResponse[PollVotesResponse]: - query_params = build_query_param(user_id=user_id) - path_params = { - "poll_id": poll_id, - } - json = build_body_dict( - limit=limit, next=next, prev=prev, sort=sort, filter=filter - ) - - return self.post( - "/api/v2/chat/polls/{poll_id}/votes", - PollVotesResponse, - query_params=query_params, - path_params=path_params, - json=json, - ) - def update_push_notification_preferences( self, preferences: List[PushPreferenceInput] ) -> StreamResponse[UpsertPushPreferencesResponse]: diff --git a/getstream/common/rest_client.py b/getstream/common/rest_client.py index 6ad2134b..cc895605 100644 --- a/getstream/common/rest_client.py +++ b/getstream/common/rest_client.py @@ -53,6 +53,7 @@ def update_app( sqs_key: Optional[str] = None, sqs_secret: Optional[str] = None, sqs_url: Optional[str] = None, + user_response_time_enabled: Optional[bool] = None, webhook_url: Optional[str] = None, allowed_flag_reasons: Optional[List[str]] = None, event_hooks: Optional[List[EventHook]] = None, @@ -102,6 +103,7 @@ def update_app( sqs_key=sqs_key, sqs_secret=sqs_secret, sqs_url=sqs_url, + user_response_time_enabled=user_response_time_enabled, webhook_url=webhook_url, allowed_flag_reasons=allowed_flag_reasons, event_hooks=event_hooks, @@ -412,6 +414,243 @@ def get_permission(self, id: str) -> StreamResponse[GetCustomPermissionResponse] path_params=path_params, ) + def create_poll( + self, + name: str, + allow_answers: Optional[bool] = None, + allow_user_suggested_options: Optional[bool] = None, + description: Optional[str] = None, + enforce_unique_vote: Optional[bool] = None, + id: Optional[str] = None, + is_closed: Optional[bool] = None, + max_votes_allowed: Optional[int] = None, + user_id: Optional[str] = None, + voting_visibility: Optional[str] = None, + options: Optional[List[PollOptionInput]] = None, + custom: Optional[Dict[str, object]] = None, + user: Optional[UserRequest] = None, + ) -> StreamResponse[PollResponse]: + json = build_body_dict( + name=name, + allow_answers=allow_answers, + allow_user_suggested_options=allow_user_suggested_options, + description=description, + enforce_unique_vote=enforce_unique_vote, + id=id, + is_closed=is_closed, + max_votes_allowed=max_votes_allowed, + user_id=user_id, + voting_visibility=voting_visibility, + options=options, + custom=custom, + user=user, + ) + + return self.post("/api/v2/polls", PollResponse, json=json) + + def update_poll( + self, + id: str, + name: str, + allow_answers: Optional[bool] = None, + allow_user_suggested_options: Optional[bool] = None, + description: Optional[str] = None, + enforce_unique_vote: Optional[bool] = None, + is_closed: Optional[bool] = None, + max_votes_allowed: Optional[int] = None, + user_id: Optional[str] = None, + voting_visibility: Optional[str] = None, + options: Optional[List[PollOptionRequest]] = None, + custom: Optional[Dict[str, object]] = None, + user: Optional[UserRequest] = None, + ) -> StreamResponse[PollResponse]: + json = build_body_dict( + id=id, + name=name, + allow_answers=allow_answers, + allow_user_suggested_options=allow_user_suggested_options, + description=description, + enforce_unique_vote=enforce_unique_vote, + is_closed=is_closed, + max_votes_allowed=max_votes_allowed, + user_id=user_id, + voting_visibility=voting_visibility, + options=options, + custom=custom, + user=user, + ) + + return self.put("/api/v2/polls", PollResponse, json=json) + + def query_polls( + self, + user_id: Optional[str] = None, + limit: Optional[int] = None, + next: Optional[str] = None, + prev: Optional[str] = None, + sort: Optional[List[SortParamRequest]] = None, + filter: Optional[Dict[str, object]] = None, + ) -> StreamResponse[QueryPollsResponse]: + query_params = build_query_param(user_id=user_id) + json = build_body_dict( + limit=limit, next=next, prev=prev, sort=sort, filter=filter + ) + + return self.post( + "/api/v2/polls/query", + QueryPollsResponse, + query_params=query_params, + json=json, + ) + + def delete_poll( + self, poll_id: str, user_id: Optional[str] = None + ) -> StreamResponse[Response]: + query_params = build_query_param(user_id=user_id) + path_params = { + "poll_id": poll_id, + } + + return self.delete( + "/api/v2/polls/{poll_id}", + Response, + query_params=query_params, + path_params=path_params, + ) + + def get_poll( + self, poll_id: str, user_id: Optional[str] = None + ) -> StreamResponse[PollResponse]: + query_params = build_query_param(user_id=user_id) + path_params = { + "poll_id": poll_id, + } + + return self.get( + "/api/v2/polls/{poll_id}", + PollResponse, + query_params=query_params, + path_params=path_params, + ) + + def update_poll_partial( + self, + poll_id: str, + user_id: Optional[str] = None, + unset: Optional[List[str]] = None, + set: Optional[Dict[str, object]] = None, + user: Optional[UserRequest] = None, + ) -> StreamResponse[PollResponse]: + path_params = { + "poll_id": poll_id, + } + json = build_body_dict(user_id=user_id, unset=unset, set=set, user=user) + + return self.patch( + "/api/v2/polls/{poll_id}", PollResponse, path_params=path_params, json=json + ) + + def create_poll_option( + self, + poll_id: str, + text: str, + user_id: Optional[str] = None, + custom: Optional[Dict[str, object]] = None, + user: Optional[UserRequest] = None, + ) -> StreamResponse[PollOptionResponse]: + path_params = { + "poll_id": poll_id, + } + json = build_body_dict(text=text, user_id=user_id, custom=custom, user=user) + + return self.post( + "/api/v2/polls/{poll_id}/options", + PollOptionResponse, + path_params=path_params, + json=json, + ) + + def update_poll_option( + self, + poll_id: str, + id: str, + text: str, + user_id: Optional[str] = None, + custom: Optional[Dict[str, object]] = None, + user: Optional[UserRequest] = None, + ) -> StreamResponse[PollOptionResponse]: + path_params = { + "poll_id": poll_id, + } + json = build_body_dict( + id=id, text=text, user_id=user_id, custom=custom, user=user + ) + + return self.put( + "/api/v2/polls/{poll_id}/options", + PollOptionResponse, + path_params=path_params, + json=json, + ) + + def delete_poll_option( + self, poll_id: str, option_id: str, user_id: Optional[str] = None + ) -> StreamResponse[Response]: + query_params = build_query_param(user_id=user_id) + path_params = { + "poll_id": poll_id, + "option_id": option_id, + } + + return self.delete( + "/api/v2/polls/{poll_id}/options/{option_id}", + Response, + query_params=query_params, + path_params=path_params, + ) + + def get_poll_option( + self, poll_id: str, option_id: str, user_id: Optional[str] = None + ) -> StreamResponse[PollOptionResponse]: + query_params = build_query_param(user_id=user_id) + path_params = { + "poll_id": poll_id, + "option_id": option_id, + } + + return self.get( + "/api/v2/polls/{poll_id}/options/{option_id}", + PollOptionResponse, + query_params=query_params, + path_params=path_params, + ) + + def query_poll_votes( + self, + poll_id: str, + user_id: Optional[str] = None, + limit: Optional[int] = None, + next: Optional[str] = None, + prev: Optional[str] = None, + sort: Optional[List[SortParamRequest]] = None, + filter: Optional[Dict[str, object]] = None, + ) -> StreamResponse[PollVotesResponse]: + query_params = build_query_param(user_id=user_id) + path_params = { + "poll_id": poll_id, + } + json = build_body_dict( + limit=limit, next=next, prev=prev, sort=sort, filter=filter + ) + + return self.post( + "/api/v2/polls/{poll_id}/votes", + PollVotesResponse, + query_params=query_params, + path_params=path_params, + json=json, + ) + def list_push_providers(self) -> StreamResponse[ListPushProvidersResponse]: return self.get("/api/v2/push_providers", ListPushProvidersResponse) @@ -566,6 +805,7 @@ def delete_users( user_ids: List[str], calls: Optional[str] = None, conversations: Optional[str] = None, + files: Optional[bool] = None, messages: Optional[str] = None, new_call_owner_id: Optional[str] = None, new_channel_owner_id: Optional[str] = None, @@ -575,6 +815,7 @@ def delete_users( user_ids=user_ids, calls=calls, conversations=conversations, + files=files, messages=messages, new_call_owner_id=new_call_owner_id, new_channel_owner_id=new_channel_owner_id, @@ -596,7 +837,6 @@ def get_user_live_locations( def update_live_location( self, - created_by_device_id: str, message_id: str, end_at: Optional[datetime] = None, latitude: Optional[float] = None, @@ -605,11 +845,7 @@ def update_live_location( ) -> StreamResponse[SharedLocationResponse]: query_params = build_query_param(user_id=user_id) json = build_body_dict( - created_by_device_id=created_by_device_id, - message_id=message_id, - end_at=end_at, - latitude=latitude, - longitude=longitude, + message_id=message_id, end_at=end_at, latitude=latitude, longitude=longitude ) return self.put( diff --git a/getstream/models/__init__.py b/getstream/models/__init__.py index 9273a7cd..5bbdb324 100644 --- a/getstream/models/__init__.py +++ b/getstream/models/__init__.py @@ -250,6 +250,12 @@ class ActiveCallsMetrics(DataClassJsonMixin): ) +@dataclass +class ActiveCallsResolutionStats(DataClassJsonMixin): + p10: float = dc_field(metadata=dc_config(field_name="p10")) + p50: float = dc_field(metadata=dc_config(field_name="p50")) + + @dataclass class ActiveCallsSummary(DataClassJsonMixin): active_calls: int = dc_field(metadata=dc_config(field_name="active_calls")) @@ -262,6 +268,31 @@ class ActiveCallsSummary(DataClassJsonMixin): participants: int = dc_field(metadata=dc_config(field_name="participants")) +@dataclass +class ActivityMarkedEvent(DataClassJsonMixin): + all_read: bool = dc_field(metadata=dc_config(field_name="all_read")) + all_seen: bool = dc_field(metadata=dc_config(field_name="all_seen")) + created_at: datetime = dc_field( + metadata=dc_config( + field_name="created_at", + encoder=encode_datetime, + decoder=datetime_from_unix_ns, + mm_field=fields.DateTime(format="iso"), + ) + ) + feed_id: str = dc_field(metadata=dc_config(field_name="feed_id")) + user_id: str = dc_field(metadata=dc_config(field_name="user_id")) + type: str = dc_field( + default="activity.marked", metadata=dc_config(field_name="type") + ) + marked_read: Optional[List[str]] = dc_field( + default=None, metadata=dc_config(field_name="marked_read") + ) + marked_watched: Optional[List[str]] = dc_field( + default=None, metadata=dc_config(field_name="marked_watched") + ) + + @dataclass class AnyEvent(DataClassJsonMixin): created_at: datetime = dc_field( @@ -305,6 +336,9 @@ class AppResponseFields(DataClassJsonMixin): image_moderation_enabled: bool = dc_field( metadata=dc_config(field_name="image_moderation_enabled") ) + moderation_bulk_submit_action_enabled: bool = dc_field( + metadata=dc_config(field_name="moderation_bulk_submit_action_enabled") + ) moderation_enabled: bool = dc_field( metadata=dc_config(field_name="moderation_enabled") ) @@ -336,6 +370,9 @@ class AppResponseFields(DataClassJsonMixin): metadata=dc_config(field_name="suspended_explanation") ) use_hook_v2: bool = dc_field(metadata=dc_config(field_name="use_hook_v2")) + user_response_time_enabled: bool = dc_field( + metadata=dc_config(field_name="user_response_time_enabled") + ) webhook_url: str = dc_field(metadata=dc_config(field_name="webhook_url")) event_hooks: "List[EventHook]" = dc_field( metadata=dc_config(field_name="event_hooks") @@ -514,7 +551,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.users.error", metadata=dc_config(field_name="type") + default="export.bulk_image_moderation.error", + metadata=dc_config(field_name="type"), ) received_at: Optional[datetime] = dc_field( default=None, @@ -910,6 +948,14 @@ class BanActionRequest(DataClassJsonMixin): ) +@dataclass +class BanOptions(DataClassJsonMixin): + duration: int = dc_field(metadata=dc_config(field_name="duration")) + ip_ban: bool = dc_field(metadata=dc_config(field_name="ip_ban")) + reason: str = dc_field(metadata=dc_config(field_name="reason")) + shadow_ban: bool = dc_field(metadata=dc_config(field_name="shadow_ban")) + + @dataclass class BanRequest(DataClassJsonMixin): target_user_id: str = dc_field(metadata=dc_config(field_name="target_user_id")) @@ -975,6 +1021,11 @@ class BanResponse(DataClassJsonMixin): ) +@dataclass +class BlockContentOptions(DataClassJsonMixin): + reason: str = dc_field(metadata=dc_config(field_name="reason")) + + @dataclass class BlockListConfig(DataClassJsonMixin): enabled: bool = dc_field(metadata=dc_config(field_name="enabled")) @@ -1828,11 +1879,14 @@ class CallParticipant(DataClassJsonMixin): ) ) online: bool = dc_field(metadata=dc_config(field_name="online")) - role: str = dc_field(metadata=dc_config(field_name="Role")) role: str = dc_field(metadata=dc_config(field_name="role")) + role: str = dc_field(metadata=dc_config(field_name="Role")) user_session_id: str = dc_field(metadata=dc_config(field_name="UserSessionID")) custom: Dict[str, object] = dc_field(metadata=dc_config(field_name="custom")) teams_role: "Dict[str, str]" = dc_field(metadata=dc_config(field_name="teams_role")) + avg_response_time: Optional[int] = dc_field( + default=None, metadata=dc_config(field_name="avg_response_time") + ) ban_expires: Optional[datetime] = dc_field( default=None, metadata=dc_config( @@ -2414,6 +2468,30 @@ class CallSessionEndedEvent(DataClassJsonMixin): ) +@dataclass +class CallSessionParticipantCountsUpdatedEvent(DataClassJsonMixin): + anonymous_participant_count: int = dc_field( + metadata=dc_config(field_name="anonymous_participant_count") + ) + call_cid: str = dc_field(metadata=dc_config(field_name="call_cid")) + created_at: datetime = dc_field( + metadata=dc_config( + field_name="created_at", + encoder=encode_datetime, + decoder=datetime_from_unix_ns, + mm_field=fields.DateTime(format="iso"), + ) + ) + session_id: str = dc_field(metadata=dc_config(field_name="session_id")) + participants_count_by_role: "Dict[str, int]" = dc_field( + metadata=dc_config(field_name="participants_count_by_role") + ) + type: str = dc_field( + default="call.session_participant_count_updated", + metadata=dc_config(field_name="type"), + ) + + @dataclass class CallSessionParticipantJoinedEvent(DataClassJsonMixin): call_cid: str = dc_field(metadata=dc_config(field_name="call_cid")) @@ -2573,6 +2651,9 @@ class CallSettings(DataClassJsonMixin): geofencing: "Optional[GeofenceSettings]" = dc_field( default=None, metadata=dc_config(field_name="geofencing") ) + ingress: "Optional[IngressSettings]" = dc_field( + default=None, metadata=dc_config(field_name="ingress") + ) limits: "Optional[LimitsSettings]" = dc_field( default=None, metadata=dc_config(field_name="limits") ) @@ -2616,6 +2697,9 @@ class CallSettingsRequest(DataClassJsonMixin): geofencing: "Optional[GeofenceSettingsRequest]" = dc_field( default=None, metadata=dc_config(field_name="geofencing") ) + ingress: "Optional[IngressSettingsRequest]" = dc_field( + default=None, metadata=dc_config(field_name="ingress") + ) limits: "Optional[LimitsSettingsRequest]" = dc_field( default=None, metadata=dc_config(field_name="limits") ) @@ -2675,6 +2759,9 @@ class CallSettingsResponse(DataClassJsonMixin): metadata=dc_config(field_name="transcription") ) video: "VideoSettingsResponse" = dc_field(metadata=dc_config(field_name="video")) + ingress: "Optional[IngressSettingsResponse]" = dc_field( + default=None, metadata=dc_config(field_name="ingress") + ) @dataclass @@ -4613,6 +4700,9 @@ class ConfigResponse(DataClassJsonMixin): block_list_config: "Optional[BlockListConfig]" = dc_field( default=None, metadata=dc_config(field_name="block_list_config") ) + rule_builder_config: "Optional[RuleBuilderConfig]" = dc_field( + default=None, metadata=dc_config(field_name="rule_builder_config") + ) velocity_filter_config: "Optional[VelocityFilterConfig]" = dc_field( default=None, metadata=dc_config(field_name="velocity_filter_config") ) @@ -4621,6 +4711,12 @@ class ConfigResponse(DataClassJsonMixin): ) +@dataclass +class ContentCountRuleParameters(DataClassJsonMixin): + threshold: int = dc_field(metadata=dc_config(field_name="threshold")) + time_window: str = dc_field(metadata=dc_config(field_name="time_window")) + + @dataclass class CountByMinuteResponse(DataClassJsonMixin): count: int = dc_field(metadata=dc_config(field_name="count")) @@ -4963,9 +5059,6 @@ class CreateImportURLResponse(DataClassJsonMixin): @dataclass class CreatePollOptionRequest(DataClassJsonMixin): text: str = dc_field(metadata=dc_config(field_name="text")) - position: Optional[int] = dc_field( - default=None, metadata=dc_config(field_name="position") - ) user_id: Optional[str] = dc_field( default=None, metadata=dc_config(field_name="user_id") ) @@ -5354,6 +5447,9 @@ class DeleteUsersRequest(DataClassJsonMixin): conversations: Optional[str] = dc_field( default=None, metadata=dc_config(field_name="conversations") ) + files: Optional[bool] = dc_field( + default=None, metadata=dc_config(field_name="files") + ) messages: Optional[str] = dc_field( default=None, metadata=dc_config(field_name="messages") ) @@ -5669,6 +5765,9 @@ class EntityCreator(DataClassJsonMixin): role: str = dc_field(metadata=dc_config(field_name="role")) custom: Dict[str, object] = dc_field(metadata=dc_config(field_name="custom")) teams_role: "Dict[str, str]" = dc_field(metadata=dc_config(field_name="teams_role")) + avg_response_time: Optional[int] = dc_field( + default=None, metadata=dc_config(field_name="avg_response_time") + ) ban_expires: Optional[datetime] = dc_field( default=None, metadata=dc_config( @@ -5790,6 +5889,9 @@ class EntityCreatorResponse(DataClassJsonMixin): ) teams: List[str] = dc_field(metadata=dc_config(field_name="teams")) custom: Dict[str, object] = dc_field(metadata=dc_config(field_name="custom")) + avg_response_time: Optional[int] = dc_field( + default=None, metadata=dc_config(field_name="avg_response_time") + ) ban_expires: Optional[datetime] = dc_field( default=None, metadata=dc_config( @@ -6179,8 +6281,9 @@ class Flag(DataClassJsonMixin): mm_field=fields.DateTime(format="iso"), ) ) - entity_id: str = dc_field(metadata=dc_config(field_name="entity_id")) - entity_type: str = dc_field(metadata=dc_config(field_name="entity_type")) + created_by_automod: bool = dc_field( + metadata=dc_config(field_name="created_by_automod") + ) updated_at: datetime = dc_field( metadata=dc_config( field_name="updated_at", @@ -6189,42 +6292,64 @@ class Flag(DataClassJsonMixin): mm_field=fields.DateTime(format="iso"), ) ) - result: "List[Dict[str, object]]" = dc_field( - metadata=dc_config(field_name="result") - ) - entity_creator_id: Optional[str] = dc_field( - default=None, metadata=dc_config(field_name="entity_creator_id") - ) - is_streamed_content: Optional[bool] = dc_field( - default=None, metadata=dc_config(field_name="is_streamed_content") - ) - moderation_payload_hash: Optional[str] = dc_field( - default=None, metadata=dc_config(field_name="moderation_payload_hash") + approved_at: Optional[datetime] = dc_field( + default=None, + metadata=dc_config( + field_name="approved_at", + encoder=encode_datetime, + decoder=datetime_from_unix_ns, + mm_field=fields.DateTime(format="iso"), + ), ) reason: Optional[str] = dc_field( default=None, metadata=dc_config(field_name="reason") ) - review_queue_item_id: Optional[str] = dc_field( - default=None, metadata=dc_config(field_name="review_queue_item_id") + rejected_at: Optional[datetime] = dc_field( + default=None, + metadata=dc_config( + field_name="rejected_at", + encoder=encode_datetime, + decoder=datetime_from_unix_ns, + mm_field=fields.DateTime(format="iso"), + ), ) - type: Optional[str] = dc_field(default=None, metadata=dc_config(field_name="type")) - labels: Optional[List[str]] = dc_field( - default=None, metadata=dc_config(field_name="labels") + reviewed_at: Optional[datetime] = dc_field( + default=None, + metadata=dc_config( + field_name="reviewed_at", + encoder=encode_datetime, + decoder=datetime_from_unix_ns, + mm_field=fields.DateTime(format="iso"), + ), + ) + reviewed_by: Optional[str] = dc_field( + default=None, metadata=dc_config(field_name="reviewed_by") + ) + target_message_id: Optional[str] = dc_field( + default=None, metadata=dc_config(field_name="target_message_id") ) custom: Optional[Dict[str, object]] = dc_field( default=None, metadata=dc_config(field_name="custom") ) - moderation_payload: "Optional[ModerationPayload]" = dc_field( - default=None, metadata=dc_config(field_name="moderation_payload") + details: "Optional[FlagDetails]" = dc_field( + default=None, metadata=dc_config(field_name="details") ) - review_queue_item: "Optional[ReviewQueueItem]" = dc_field( - default=None, metadata=dc_config(field_name="review_queue_item") + target_message: "Optional[Message]" = dc_field( + default=None, metadata=dc_config(field_name="target_message") + ) + target_user: "Optional[User]" = dc_field( + default=None, metadata=dc_config(field_name="target_user") ) user: "Optional[User]" = dc_field( default=None, metadata=dc_config(field_name="user") ) +@dataclass +class FlagContentOptions(DataClassJsonMixin): + reason: str = dc_field(metadata=dc_config(field_name="reason")) + + @dataclass class FlagDetails(DataClassJsonMixin): original_text: str = dc_field(metadata=dc_config(field_name="original_text")) @@ -6326,6 +6451,11 @@ class FlagUpdatedEvent(DataClassJsonMixin): ) +@dataclass +class FlagUserOptions(DataClassJsonMixin): + reason: str = dc_field(metadata=dc_config(field_name="reason")) + + @dataclass class FrameRecordSettings(DataClassJsonMixin): capture_interval_in_seconds: int = dc_field( @@ -6421,6 +6551,9 @@ class FullUserResponse(DataClassJsonMixin): mutes: "List[UserMuteResponse]" = dc_field(metadata=dc_config(field_name="mutes")) teams: List[str] = dc_field(metadata=dc_config(field_name="teams")) custom: Dict[str, object] = dc_field(metadata=dc_config(field_name="custom")) + avg_response_time: Optional[int] = dc_field( + default=None, metadata=dc_config(field_name="avg_response_time") + ) ban_expires: Optional[datetime] = dc_field( default=None, metadata=dc_config( @@ -7108,6 +7241,13 @@ class HuaweiConfigFields(DataClassJsonMixin): ) +@dataclass +class ImageContentParameters(DataClassJsonMixin): + harm_labels: Optional[List[str]] = dc_field( + default=None, metadata=dc_config(field_name="harm_labels") + ) + + @dataclass class ImageData(DataClassJsonMixin): frames: str = dc_field(metadata=dc_config(field_name="frames")) @@ -7117,6 +7257,15 @@ class ImageData(DataClassJsonMixin): width: str = dc_field(metadata=dc_config(field_name="width")) +@dataclass +class ImageRuleParameters(DataClassJsonMixin): + threshold: int = dc_field(metadata=dc_config(field_name="threshold")) + time_window: str = dc_field(metadata=dc_config(field_name="time_window")) + harm_labels: Optional[List[str]] = dc_field( + default=None, metadata=dc_config(field_name="harm_labels") + ) + + @dataclass class ImageSize(DataClassJsonMixin): crop: Optional[str] = dc_field(default=None, metadata=dc_config(field_name="crop")) @@ -7215,6 +7364,112 @@ class ImportTaskHistory(DataClassJsonMixin): prev_state: str = dc_field(metadata=dc_config(field_name="prev_state")) +@dataclass +class IngressAudioEncodingOptions(DataClassJsonMixin): + bitrate: int = dc_field(metadata=dc_config(field_name="bitrate")) + channels: int = dc_field(metadata=dc_config(field_name="channels")) + enable_dtx: bool = dc_field(metadata=dc_config(field_name="enable_dtx")) + + +@dataclass +class IngressAudioEncodingOptionsRequest(DataClassJsonMixin): + bitrate: int = dc_field(metadata=dc_config(field_name="bitrate")) + channels: int = dc_field(metadata=dc_config(field_name="channels")) + enable_dtx: Optional[bool] = dc_field( + default=None, metadata=dc_config(field_name="enable_dtx") + ) + + +@dataclass +class IngressAudioEncodingResponse(DataClassJsonMixin): + bitrate: int = dc_field(metadata=dc_config(field_name="bitrate")) + channels: int = dc_field(metadata=dc_config(field_name="channels")) + enable_dtx: bool = dc_field(metadata=dc_config(field_name="enable_dtx")) + + +@dataclass +class IngressSettings(DataClassJsonMixin): + enabled: bool = dc_field(metadata=dc_config(field_name="enabled")) + audio_encoding_options: "Optional[IngressAudioEncodingOptions]" = dc_field( + default=None, metadata=dc_config(field_name="audio_encoding_options") + ) + video_encoding_options: "Optional[Dict[str, IngressVideoEncodingOptions]]" = ( + dc_field(default=None, metadata=dc_config(field_name="video_encoding_options")) + ) + + +@dataclass +class IngressSettingsRequest(DataClassJsonMixin): + enabled: Optional[bool] = dc_field( + default=None, metadata=dc_config(field_name="enabled") + ) + audio_encoding_options: "Optional[IngressAudioEncodingOptionsRequest]" = dc_field( + default=None, metadata=dc_config(field_name="audio_encoding_options") + ) + video_encoding_options: "Optional[Dict[str, IngressVideoEncodingOptionsRequest]]" = dc_field( + default=None, metadata=dc_config(field_name="video_encoding_options") + ) + + +@dataclass +class IngressSettingsResponse(DataClassJsonMixin): + enabled: bool = dc_field(metadata=dc_config(field_name="enabled")) + audio_encoding_options: "Optional[IngressAudioEncodingResponse]" = dc_field( + default=None, metadata=dc_config(field_name="audio_encoding_options") + ) + video_encoding_options: "Optional[Dict[str, IngressVideoEncodingResponse]]" = ( + dc_field(default=None, metadata=dc_config(field_name="video_encoding_options")) + ) + + +@dataclass +class IngressVideoEncodingOptions(DataClassJsonMixin): + layers: "List[IngressVideoLayer]" = dc_field( + metadata=dc_config(field_name="layers") + ) + + +@dataclass +class IngressVideoEncodingOptionsRequest(DataClassJsonMixin): + layers: "List[IngressVideoLayerRequest]" = dc_field( + metadata=dc_config(field_name="layers") + ) + + +@dataclass +class IngressVideoEncodingResponse(DataClassJsonMixin): + layers: "List[IngressVideoLayerResponse]" = dc_field( + metadata=dc_config(field_name="layers") + ) + + +@dataclass +class IngressVideoLayer(DataClassJsonMixin): + bitrate: int = dc_field(metadata=dc_config(field_name="bitrate")) + codec: str = dc_field(metadata=dc_config(field_name="codec")) + frame_rate: int = dc_field(metadata=dc_config(field_name="frame_rate")) + max_dimension: int = dc_field(metadata=dc_config(field_name="max_dimension")) + min_dimension: int = dc_field(metadata=dc_config(field_name="min_dimension")) + + +@dataclass +class IngressVideoLayerRequest(DataClassJsonMixin): + bitrate: int = dc_field(metadata=dc_config(field_name="bitrate")) + codec: str = dc_field(metadata=dc_config(field_name="codec")) + frame_rate_limit: int = dc_field(metadata=dc_config(field_name="frame_rate_limit")) + max_dimension: int = dc_field(metadata=dc_config(field_name="max_dimension")) + min_dimension: int = dc_field(metadata=dc_config(field_name="min_dimension")) + + +@dataclass +class IngressVideoLayerResponse(DataClassJsonMixin): + bitrate: int = dc_field(metadata=dc_config(field_name="bitrate")) + codec: str = dc_field(metadata=dc_config(field_name="codec")) + frame_rate_limit: int = dc_field(metadata=dc_config(field_name="frame_rate_limit")) + max_dimension: int = dc_field(metadata=dc_config(field_name="max_dimension")) + min_dimension: int = dc_field(metadata=dc_config(field_name="min_dimension")) + + @dataclass class JoinCallAPIMetrics(DataClassJsonMixin): failures: float = dc_field(metadata=dc_config(field_name="failures")) @@ -8614,6 +8869,9 @@ class ModerationCustomActionEvent(DataClassJsonMixin): @dataclass class ModerationDashboardPreferences(DataClassJsonMixin): + flag_user_on_flagged_content: Optional[bool] = dc_field( + default=None, metadata=dc_config(field_name="flag_user_on_flagged_content") + ) media_queue_blur_enabled: Optional[bool] = dc_field( default=None, metadata=dc_config(field_name="media_queue_blur_enabled") ) @@ -8624,9 +8882,9 @@ class ModerationFlagResponse(DataClassJsonMixin): created_at: str = dc_field(metadata=dc_config(field_name="created_at")) entity_id: str = dc_field(metadata=dc_config(field_name="entity_id")) entity_type: str = dc_field(metadata=dc_config(field_name="entity_type")) - id: str = dc_field(metadata=dc_config(field_name="id")) type: str = dc_field(metadata=dc_config(field_name="type")) updated_at: str = dc_field(metadata=dc_config(field_name="updated_at")) + user_id: str = dc_field(metadata=dc_config(field_name="user_id")) entity_creator_id: Optional[str] = dc_field( default=None, metadata=dc_config(field_name="entity_creator_id") ) @@ -9021,6 +9279,9 @@ class OwnUser(DataClassJsonMixin): total_unread_count_by_team: "Dict[str, int]" = dc_field( metadata=dc_config(field_name="total_unread_count_by_team") ) + avg_response_time: Optional[int] = dc_field( + default=None, metadata=dc_config(field_name="avg_response_time") + ) deactivated_at: Optional[datetime] = dc_field( default=None, metadata=dc_config( @@ -9117,6 +9378,9 @@ class OwnUserResponse(DataClassJsonMixin): mutes: "List[UserMuteResponse]" = dc_field(metadata=dc_config(field_name="mutes")) teams: List[str] = dc_field(metadata=dc_config(field_name="teams")) custom: Dict[str, object] = dc_field(metadata=dc_config(field_name="custom")) + avg_response_time: Optional[int] = dc_field( + default=None, metadata=dc_config(field_name="avg_response_time") + ) deactivated_at: Optional[datetime] = dc_field( default=None, metadata=dc_config( @@ -9246,6 +9510,44 @@ class ParticipantReportResponse(DataClassJsonMixin): ) +@dataclass +class PendingMessageEvent(DataClassJsonMixin): + created_at: datetime = dc_field( + metadata=dc_config( + field_name="created_at", + encoder=encode_datetime, + decoder=datetime_from_unix_ns, + mm_field=fields.DateTime(format="iso"), + ) + ) + method: str = dc_field(metadata=dc_config(field_name="method")) + custom: Dict[str, object] = dc_field(metadata=dc_config(field_name="custom")) + type: str = dc_field( + default="message.pending", metadata=dc_config(field_name="type") + ) + received_at: Optional[datetime] = dc_field( + default=None, + metadata=dc_config( + field_name="received_at", + encoder=encode_datetime, + decoder=datetime_from_unix_ns, + mm_field=fields.DateTime(format="iso"), + ), + ) + channel: "Optional[Channel]" = dc_field( + default=None, metadata=dc_config(field_name="channel") + ) + message: "Optional[Message]" = dc_field( + default=None, metadata=dc_config(field_name="message") + ) + metadata: "Optional[Dict[str, str]]" = dc_field( + default=None, metadata=dc_config(field_name="metadata") + ) + user: "Optional[User]" = dc_field( + default=None, metadata=dc_config(field_name="user") + ) + + @dataclass class PendingMessageResponse(DataClassJsonMixin): channel: "Optional[ChannelResponse]" = dc_field( @@ -9501,7 +9803,7 @@ class PollResponseData(DataClassJsonMixin): own_votes: "List[PollVoteResponseData]" = dc_field( metadata=dc_config(field_name="own_votes") ) - custom: Dict[str, object] = dc_field(metadata=dc_config(field_name="Custom")) + custom: Dict[str, object] = dc_field(metadata=dc_config(field_name="custom")) latest_votes_by_option: "Dict[str, List[PollVoteResponseData]]" = dc_field( metadata=dc_config(field_name="latest_votes_by_option") ) @@ -9667,6 +9969,9 @@ class PublisherVideoMetrics(DataClassJsonMixin): jitter_ms: "Optional[ActiveCallsLatencyStats]" = dc_field( default=None, metadata=dc_config(field_name="jitter_ms") ) + resolution: "Optional[ActiveCallsResolutionStats]" = dc_field( + default=None, metadata=dc_config(field_name="resolution") + ) @dataclass @@ -9717,6 +10022,9 @@ class PushNotificationSettingsResponse(DataClassJsonMixin): @dataclass class PushPreferenceInput(DataClassJsonMixin): + call_level: Optional[str] = dc_field( + default=None, metadata=dc_config(field_name="call_level") + ) channel_cid: Optional[str] = dc_field( default=None, metadata=dc_config(field_name="channel_cid") ) @@ -11166,6 +11474,108 @@ class RecordingEgressConfig(DataClassJsonMixin): ) +@dataclass +class ReminderCreatedEvent(DataClassJsonMixin): + cid: str = dc_field(metadata=dc_config(field_name="cid")) + created_at: datetime = dc_field( + metadata=dc_config( + field_name="created_at", + encoder=encode_datetime, + decoder=datetime_from_unix_ns, + mm_field=fields.DateTime(format="iso"), + ) + ) + message_id: str = dc_field(metadata=dc_config(field_name="message_id")) + user_id: str = dc_field(metadata=dc_config(field_name="user_id")) + custom: Dict[str, object] = dc_field(metadata=dc_config(field_name="custom")) + type: str = dc_field( + default="reminder.created", metadata=dc_config(field_name="type") + ) + parent_id: Optional[str] = dc_field( + default=None, metadata=dc_config(field_name="parent_id") + ) + received_at: Optional[datetime] = dc_field( + default=None, + metadata=dc_config( + field_name="received_at", + encoder=encode_datetime, + decoder=datetime_from_unix_ns, + mm_field=fields.DateTime(format="iso"), + ), + ) + reminder: "Optional[ReminderResponseData]" = dc_field( + default=None, metadata=dc_config(field_name="reminder") + ) + + +@dataclass +class ReminderDeletedEvent(DataClassJsonMixin): + cid: str = dc_field(metadata=dc_config(field_name="cid")) + created_at: datetime = dc_field( + metadata=dc_config( + field_name="created_at", + encoder=encode_datetime, + decoder=datetime_from_unix_ns, + mm_field=fields.DateTime(format="iso"), + ) + ) + message_id: str = dc_field(metadata=dc_config(field_name="message_id")) + user_id: str = dc_field(metadata=dc_config(field_name="user_id")) + custom: Dict[str, object] = dc_field(metadata=dc_config(field_name="custom")) + type: str = dc_field( + default="reminder.deleted", metadata=dc_config(field_name="type") + ) + parent_id: Optional[str] = dc_field( + default=None, metadata=dc_config(field_name="parent_id") + ) + received_at: Optional[datetime] = dc_field( + default=None, + metadata=dc_config( + field_name="received_at", + encoder=encode_datetime, + decoder=datetime_from_unix_ns, + mm_field=fields.DateTime(format="iso"), + ), + ) + reminder: "Optional[ReminderResponseData]" = dc_field( + default=None, metadata=dc_config(field_name="reminder") + ) + + +@dataclass +class ReminderNotificationEvent(DataClassJsonMixin): + cid: str = dc_field(metadata=dc_config(field_name="cid")) + created_at: datetime = dc_field( + metadata=dc_config( + field_name="created_at", + encoder=encode_datetime, + decoder=datetime_from_unix_ns, + mm_field=fields.DateTime(format="iso"), + ) + ) + message_id: str = dc_field(metadata=dc_config(field_name="message_id")) + user_id: str = dc_field(metadata=dc_config(field_name="user_id")) + custom: Dict[str, object] = dc_field(metadata=dc_config(field_name="custom")) + type: str = dc_field( + default="notification.reminder_due", metadata=dc_config(field_name="type") + ) + parent_id: Optional[str] = dc_field( + default=None, metadata=dc_config(field_name="parent_id") + ) + received_at: Optional[datetime] = dc_field( + default=None, + metadata=dc_config( + field_name="received_at", + encoder=encode_datetime, + decoder=datetime_from_unix_ns, + mm_field=fields.DateTime(format="iso"), + ), + ) + reminder: "Optional[ReminderResponseData]" = dc_field( + default=None, metadata=dc_config(field_name="reminder") + ) + + @dataclass class ReminderResponseData(DataClassJsonMixin): channel_cid: str = dc_field(metadata=dc_config(field_name="channel_cid")) @@ -11207,6 +11617,40 @@ class ReminderResponseData(DataClassJsonMixin): ) +@dataclass +class ReminderUpdatedEvent(DataClassJsonMixin): + cid: str = dc_field(metadata=dc_config(field_name="cid")) + created_at: datetime = dc_field( + metadata=dc_config( + field_name="created_at", + encoder=encode_datetime, + decoder=datetime_from_unix_ns, + mm_field=fields.DateTime(format="iso"), + ) + ) + message_id: str = dc_field(metadata=dc_config(field_name="message_id")) + user_id: str = dc_field(metadata=dc_config(field_name="user_id")) + custom: Dict[str, object] = dc_field(metadata=dc_config(field_name="custom")) + type: str = dc_field( + default="reminder.updated", metadata=dc_config(field_name="type") + ) + parent_id: Optional[str] = dc_field( + default=None, metadata=dc_config(field_name="parent_id") + ) + received_at: Optional[datetime] = dc_field( + default=None, + metadata=dc_config( + field_name="received_at", + encoder=encode_datetime, + decoder=datetime_from_unix_ns, + mm_field=fields.DateTime(format="iso"), + ), + ) + reminder: "Optional[ReminderResponseData]" = dc_field( + default=None, metadata=dc_config(field_name="reminder") + ) + + @dataclass class ReportByHistogramBucket(DataClassJsonMixin): category: str = dc_field(metadata=dc_config(field_name="category")) @@ -11286,9 +11730,13 @@ class ReviewQueueItem(DataClassJsonMixin): ) actions: "List[ActionLog]" = dc_field(metadata=dc_config(field_name="actions")) bans: "List[Ban]" = dc_field(metadata=dc_config(field_name="bans")) + flag_labels: List[str] = dc_field(metadata=dc_config(field_name="flag_labels")) + flag_types: List[str] = dc_field(metadata=dc_config(field_name="flag_types")) flags: "List[Flag]" = dc_field(metadata=dc_config(field_name="flags")) languages: List[str] = dc_field(metadata=dc_config(field_name="languages")) + reporter_ids: List[str] = dc_field(metadata=dc_config(field_name="reporter_ids")) teams: List[str] = dc_field(metadata=dc_config(field_name="teams")) + archived_at: "NullTime" = dc_field(metadata=dc_config(field_name="archived_at")) completed_at: "NullTime" = dc_field(metadata=dc_config(field_name="completed_at")) reviewed_at: "NullTime" = dc_field(metadata=dc_config(field_name="reviewed_at")) activity: "Optional[EnrichedActivity]" = dc_field( @@ -11343,7 +11791,7 @@ class ReviewQueueItemNewEvent(DataClassJsonMixin): mm_field=fields.DateTime(format="iso"), ), ) - flags: "Optional[List[FlagResponse]]" = dc_field( + flags: "Optional[List[ModerationFlagResponse]]" = dc_field( default=None, metadata=dc_config(field_name="flags") ) action: "Optional[ActionLogResponse]" = dc_field( @@ -11387,7 +11835,9 @@ class ReviewQueueItemResponse(DataClassJsonMixin): metadata=dc_config(field_name="actions") ) bans: "List[Ban]" = dc_field(metadata=dc_config(field_name="bans")) - flags: "List[FlagResponse]" = dc_field(metadata=dc_config(field_name="flags")) + flags: "List[ModerationFlagResponse]" = dc_field( + metadata=dc_config(field_name="flags") + ) languages: List[str] = dc_field(metadata=dc_config(field_name="languages")) completed_at: Optional[datetime] = dc_field( default=None, @@ -11468,7 +11918,7 @@ class ReviewQueueItemUpdatedEvent(DataClassJsonMixin): mm_field=fields.DateTime(format="iso"), ), ) - flags: "Optional[List[FlagResponse]]" = dc_field( + flags: "Optional[List[ModerationFlagResponse]]" = dc_field( default=None, metadata=dc_config(field_name="flags") ) action: "Optional[ActionLogResponse]" = dc_field( @@ -11543,62 +11993,90 @@ class Role(DataClassJsonMixin): @dataclass class RuleBuilderAction(DataClassJsonMixin): - duration: Optional[int] = dc_field( - default=None, metadata=dc_config(field_name="duration") + type: str = dc_field(metadata=dc_config(field_name="type")) + ban_options: "Optional[BanOptions]" = dc_field( + default=None, metadata=dc_config(field_name="ban_options") ) - ip_ban: Optional[bool] = dc_field( - default=None, metadata=dc_config(field_name="ip_ban") + flag_content_options: "Optional[FlagContentOptions]" = dc_field( + default=None, metadata=dc_config(field_name="flag_content_options") ) - reason: Optional[str] = dc_field( - default=None, metadata=dc_config(field_name="reason") + flag_user_options: "Optional[FlagUserOptions]" = dc_field( + default=None, metadata=dc_config(field_name="flag_user_options") ) - shadow_ban: Optional[bool] = dc_field( - default=None, metadata=dc_config(field_name="shadow_ban") + remove_content_options: "Optional[BlockContentOptions]" = dc_field( + default=None, metadata=dc_config(field_name="remove_content_options") ) - type: Optional[str] = dc_field(default=None, metadata=dc_config(field_name="type")) @dataclass class RuleBuilderCondition(DataClassJsonMixin): - provider: Optional[str] = dc_field( - default=None, metadata=dc_config(field_name="provider") + type: str = dc_field(metadata=dc_config(field_name="type")) + confidence: Optional[float] = dc_field( + default=None, metadata=dc_config(field_name="confidence") ) - threshold: Optional[int] = dc_field( - default=None, metadata=dc_config(field_name="threshold") + content_count_rule_params: "Optional[ContentCountRuleParameters]" = dc_field( + default=None, metadata=dc_config(field_name="content_count_rule_params") ) - time_window: Optional[str] = dc_field( - default=None, metadata=dc_config(field_name="time_window") + image_content_params: "Optional[ImageContentParameters]" = dc_field( + default=None, metadata=dc_config(field_name="image_content_params") ) - labels: Optional[List[str]] = dc_field( - default=None, metadata=dc_config(field_name="labels") + image_rule_params: "Optional[ImageRuleParameters]" = dc_field( + default=None, metadata=dc_config(field_name="image_rule_params") + ) + text_content_params: "Optional[TextContentParameters]" = dc_field( + default=None, metadata=dc_config(field_name="text_content_params") + ) + text_rule_params: "Optional[TextRuleParameters]" = dc_field( + default=None, metadata=dc_config(field_name="text_rule_params") + ) + user_created_within_params: "Optional[UserCreatedWithinParameters]" = dc_field( + default=None, metadata=dc_config(field_name="user_created_within_params") + ) + user_rule_params: "Optional[UserRuleParameters]" = dc_field( + default=None, metadata=dc_config(field_name="user_rule_params") + ) + video_content_params: "Optional[VideoContentParameters]" = dc_field( + default=None, metadata=dc_config(field_name="video_content_params") + ) + video_rule_params: "Optional[VideoRuleParameters]" = dc_field( + default=None, metadata=dc_config(field_name="video_rule_params") + ) + + +@dataclass +class RuleBuilderConditionGroup(DataClassJsonMixin): + logic: str = dc_field(metadata=dc_config(field_name="logic")) + conditions: "List[RuleBuilderCondition]" = dc_field( + metadata=dc_config(field_name="conditions") ) @dataclass class RuleBuilderConfig(DataClassJsonMixin): + rules: "List[RuleBuilderRule]" = dc_field(metadata=dc_config(field_name="rules")) _async: Optional[bool] = dc_field( default=None, metadata=dc_config(field_name="async") ) - enabled: Optional[bool] = dc_field( - default=None, metadata=dc_config(field_name="enabled") - ) - rules: "Optional[List[RuleBuilderRule]]" = dc_field( - default=None, metadata=dc_config(field_name="rules") - ) @dataclass class RuleBuilderRule(DataClassJsonMixin): - enabled: Optional[bool] = dc_field( - default=None, metadata=dc_config(field_name="enabled") + enabled: bool = dc_field(metadata=dc_config(field_name="enabled")) + id: str = dc_field(metadata=dc_config(field_name="id")) + name: str = dc_field(metadata=dc_config(field_name="name")) + rule_type: str = dc_field(metadata=dc_config(field_name="rule_type")) + action: "RuleBuilderAction" = dc_field(metadata=dc_config(field_name="action")) + cooldown_period: Optional[str] = dc_field( + default=None, metadata=dc_config(field_name="cooldown_period") + ) + logic: Optional[str] = dc_field( + default=None, metadata=dc_config(field_name="logic") ) - id: Optional[str] = dc_field(default=None, metadata=dc_config(field_name="id")) - name: Optional[str] = dc_field(default=None, metadata=dc_config(field_name="name")) conditions: "Optional[List[RuleBuilderCondition]]" = dc_field( default=None, metadata=dc_config(field_name="conditions") ) - action: "Optional[RuleBuilderAction]" = dc_field( - default=None, metadata=dc_config(field_name="action") + groups: "Optional[List[RuleBuilderConditionGroup]]" = dc_field( + default=None, metadata=dc_config(field_name="groups") ) @@ -12618,6 +13096,40 @@ class TargetResolution(DataClassJsonMixin): width: int = dc_field(metadata=dc_config(field_name="width")) +@dataclass +class TextContentParameters(DataClassJsonMixin): + contains_url: Optional[bool] = dc_field( + default=None, metadata=dc_config(field_name="contains_url") + ) + severity: Optional[str] = dc_field( + default=None, metadata=dc_config(field_name="severity") + ) + blocklist_match: Optional[List[str]] = dc_field( + default=None, metadata=dc_config(field_name="blocklist_match") + ) + harm_labels: Optional[List[str]] = dc_field( + default=None, metadata=dc_config(field_name="harm_labels") + ) + + +@dataclass +class TextRuleParameters(DataClassJsonMixin): + threshold: int = dc_field(metadata=dc_config(field_name="threshold")) + time_window: str = dc_field(metadata=dc_config(field_name="time_window")) + contains_url: Optional[bool] = dc_field( + default=None, metadata=dc_config(field_name="contains_url") + ) + severity: Optional[str] = dc_field( + default=None, metadata=dc_config(field_name="severity") + ) + blocklist_match: Optional[List[str]] = dc_field( + default=None, metadata=dc_config(field_name="blocklist_match") + ) + harm_labels: Optional[List[str]] = dc_field( + default=None, metadata=dc_config(field_name="harm_labels") + ) + + @dataclass class ThreadParticipant(DataClassJsonMixin): app_pk: int = dc_field(metadata=dc_config(field_name="app_pk")) @@ -13136,8 +13648,8 @@ class UnreadCountsResponse(DataClassJsonMixin): threads: "List[UnreadCountsThread]" = dc_field( metadata=dc_config(field_name="threads") ) - total_unread_count_by_team: "Dict[str, int]" = dc_field( - metadata=dc_config(field_name="total_unread_count_by_team") + total_unread_count_by_team: "Optional[Dict[str, int]]" = dc_field( + default=None, metadata=dc_config(field_name="total_unread_count_by_team") ) @@ -13249,6 +13761,9 @@ class UpdateAppRequest(DataClassJsonMixin): sqs_url: Optional[str] = dc_field( default=None, metadata=dc_config(field_name="sqs_url") ) + user_response_time_enabled: Optional[bool] = dc_field( + default=None, metadata=dc_config(field_name="user_response_time_enabled") + ) webhook_url: Optional[str] = dc_field( default=None, metadata=dc_config(field_name="webhook_url") ) @@ -13720,9 +14235,6 @@ class UpdateExternalStorageResponse(DataClassJsonMixin): @dataclass class UpdateLiveLocationRequest(DataClassJsonMixin): - created_by_device_id: str = dc_field( - metadata=dc_config(field_name="created_by_device_id") - ) message_id: str = dc_field(metadata=dc_config(field_name="message_id")) end_at: Optional[datetime] = dc_field( default=None, @@ -14163,6 +14675,9 @@ class User(DataClassJsonMixin): role: str = dc_field(metadata=dc_config(field_name="role")) custom: Dict[str, object] = dc_field(metadata=dc_config(field_name="custom")) teams_role: "Dict[str, str]" = dc_field(metadata=dc_config(field_name="teams_role")) + avg_response_time: Optional[int] = dc_field( + default=None, metadata=dc_config(field_name="avg_response_time") + ) ban_expires: Optional[datetime] = dc_field( default=None, metadata=dc_config( @@ -14283,6 +14798,13 @@ class UserBannedEvent(DataClassJsonMixin): ) +@dataclass +class UserCreatedWithinParameters(DataClassJsonMixin): + max_age: Optional[str] = dc_field( + default=None, metadata=dc_config(field_name="max_age") + ) + + @dataclass class UserCustomEventRequest(DataClassJsonMixin): type: str = dc_field(metadata=dc_config(field_name="type")) @@ -14387,6 +14909,48 @@ class UserFlaggedEvent(DataClassJsonMixin): ) +@dataclass +class UserMessagesDeletedEvent(DataClassJsonMixin): + created_at: datetime = dc_field( + metadata=dc_config( + field_name="created_at", + encoder=encode_datetime, + decoder=datetime_from_unix_ns, + mm_field=fields.DateTime(format="iso"), + ) + ) + hard_delete: bool = dc_field(metadata=dc_config(field_name="hard_delete")) + soft_delete: bool = dc_field(metadata=dc_config(field_name="soft_delete")) + custom: Dict[str, object] = dc_field(metadata=dc_config(field_name="custom")) + user: "UserResponseCommonFields" = dc_field(metadata=dc_config(field_name="user")) + type: str = dc_field( + default="user.messages.deleted", metadata=dc_config(field_name="type") + ) + channel_id: Optional[str] = dc_field( + default=None, metadata=dc_config(field_name="channel_id") + ) + channel_member_count: Optional[int] = dc_field( + default=None, metadata=dc_config(field_name="channel_member_count") + ) + channel_type: Optional[str] = dc_field( + default=None, metadata=dc_config(field_name="channel_type") + ) + cid: Optional[str] = dc_field(default=None, metadata=dc_config(field_name="cid")) + received_at: Optional[datetime] = dc_field( + default=None, + metadata=dc_config( + field_name="received_at", + encoder=encode_datetime, + decoder=datetime_from_unix_ns, + mm_field=fields.DateTime(format="iso"), + ), + ) + team: Optional[str] = dc_field(default=None, metadata=dc_config(field_name="team")) + channel_custom: Optional[Dict[str, object]] = dc_field( + default=None, metadata=dc_config(field_name="channel_custom") + ) + + @dataclass class UserMute(DataClassJsonMixin): created_at: datetime = dc_field( @@ -14561,6 +15125,9 @@ class UserResponse(DataClassJsonMixin): ) teams: List[str] = dc_field(metadata=dc_config(field_name="teams")) custom: Dict[str, object] = dc_field(metadata=dc_config(field_name="custom")) + avg_response_time: Optional[int] = dc_field( + default=None, metadata=dc_config(field_name="avg_response_time") + ) ban_expires: Optional[datetime] = dc_field( default=None, metadata=dc_config( @@ -14652,6 +15219,9 @@ class UserResponseCommonFields(DataClassJsonMixin): ) teams: List[str] = dc_field(metadata=dc_config(field_name="teams")) custom: Dict[str, object] = dc_field(metadata=dc_config(field_name="custom")) + avg_response_time: Optional[int] = dc_field( + default=None, metadata=dc_config(field_name="avg_response_time") + ) deactivated_at: Optional[datetime] = dc_field( default=None, metadata=dc_config( @@ -14725,6 +15295,9 @@ class UserResponsePrivacyFields(DataClassJsonMixin): ) teams: List[str] = dc_field(metadata=dc_config(field_name="teams")) custom: Dict[str, object] = dc_field(metadata=dc_config(field_name="custom")) + avg_response_time: Optional[int] = dc_field( + default=None, metadata=dc_config(field_name="avg_response_time") + ) deactivated_at: Optional[datetime] = dc_field( default=None, metadata=dc_config( @@ -14776,6 +15349,13 @@ class UserResponsePrivacyFields(DataClassJsonMixin): ) +@dataclass +class UserRuleParameters(DataClassJsonMixin): + max_age: Optional[str] = dc_field( + default=None, metadata=dc_config(field_name="max_age") + ) + + @dataclass class UserUnbannedEvent(DataClassJsonMixin): channel_id: str = dc_field(metadata=dc_config(field_name="channel_id")) @@ -14916,6 +15496,13 @@ class VideoCallRuleConfig(DataClassJsonMixin): rules: "Dict[str, HarmConfig]" = dc_field(metadata=dc_config(field_name="rules")) +@dataclass +class VideoContentParameters(DataClassJsonMixin): + harm_labels: Optional[List[str]] = dc_field( + default=None, metadata=dc_config(field_name="harm_labels") + ) + + @dataclass class VideoEndCallRequest(DataClassJsonMixin): pass @@ -14948,6 +15535,15 @@ class VideoReactionsResponse(DataClassJsonMixin): ) +@dataclass +class VideoRuleParameters(DataClassJsonMixin): + threshold: int = dc_field(metadata=dc_config(field_name="threshold")) + time_window: str = dc_field(metadata=dc_config(field_name="time_window")) + harm_labels: Optional[List[str]] = dc_field( + default=None, metadata=dc_config(field_name="harm_labels") + ) + + @dataclass class VideoSettings(DataClassJsonMixin): access_request_enabled: bool = dc_field( @@ -15005,9 +15601,6 @@ class VoteData(DataClassJsonMixin): option_id: Optional[str] = dc_field( default=None, metadata=dc_config(field_name="option_id") ) - option: "Optional[PollOptionResponseData]" = dc_field( - default=None, metadata=dc_config(field_name="Option") - ) @dataclass @@ -15121,8 +15714,8 @@ class WrappedUnreadCountsResponse(DataClassJsonMixin): threads: "List[UnreadCountsThread]" = dc_field( metadata=dc_config(field_name="threads") ) - total_unread_count_by_team: "Dict[str, int]" = dc_field( - metadata=dc_config(field_name="total_unread_count_by_team") + total_unread_count_by_team: "Optional[Dict[str, int]]" = dc_field( + default=None, metadata=dc_config(field_name="total_unread_count_by_team") ) diff --git a/uv.lock b/uv.lock index e8609520..10aa81b1 100644 --- a/uv.lock +++ b/uv.lock @@ -148,7 +148,7 @@ wheels = [ [[package]] name = "getstream" -version = "2.2.1" +version = "2.2.2" source = { editable = "." } dependencies = [ { name = "dataclasses-json" }, From 63565bca40ab2599d109865609107f779877226a Mon Sep 17 00:00:00 2001 From: github-actions Date: Wed, 13 Aug 2025 18:17:31 +0000 Subject: [PATCH 11/15] chore(release): 2.3.0 --- getstream/version.py | 2 +- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/getstream/version.py b/getstream/version.py index 4c337c20..707faadc 100644 --- a/getstream/version.py +++ b/getstream/version.py @@ -1 +1 @@ -VERSION = "2.2.2" +VERSION = "2.3.0" diff --git a/pyproject.toml b/pyproject.toml index 1901e2f0..f7fbae7f 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "getstream" -version = "2.2.2" +version = "2.3.0" description = "" authors = [ { name = "sachaarbonel", email = "sacha.arbonel@hotmail.fr" }, From 4f936b40c72321bc0a89a5ed5bc727b0e15ad1cc Mon Sep 17 00:00:00 2001 From: Tommaso Barbugli Date: Fri, 15 Aug 2025 12:03:31 +0200 Subject: [PATCH 12/15] more call metrics --- getstream/chat/rest_client.py | 245 +----------- getstream/common/rest_client.py | 248 +++++++++++- getstream/models/__init__.py | 689 +++++++++++++++++++++++++++++--- uv.lock | 2 +- 4 files changed, 881 insertions(+), 303 deletions(-) diff --git a/getstream/chat/rest_client.py b/getstream/chat/rest_client.py index db83b21a..fe8c4e97 100644 --- a/getstream/chat/rest_client.py +++ b/getstream/chat/rest_client.py @@ -1162,7 +1162,7 @@ def cast_poll_vote( json=json, ) - def remove_poll_vote( + def delete_poll_vote( self, message_id: str, poll_id: str, vote_id: str, user_id: Optional[str] = None ) -> StreamResponse[PollVoteResponse]: query_params = build_query_param(user_id=user_id) @@ -1316,249 +1316,6 @@ def unmute_channel( "/api/v2/chat/moderation/unmute/channel", UnmuteResponse, json=json ) - def create_poll( - self, - name: str, - allow_answers: Optional[bool] = None, - allow_user_suggested_options: Optional[bool] = None, - description: Optional[str] = None, - enforce_unique_vote: Optional[bool] = None, - id: Optional[str] = None, - is_closed: Optional[bool] = None, - max_votes_allowed: Optional[int] = None, - user_id: Optional[str] = None, - voting_visibility: Optional[str] = None, - options: Optional[List[PollOptionInput]] = None, - custom: Optional[Dict[str, object]] = None, - user: Optional[UserRequest] = None, - ) -> StreamResponse[PollResponse]: - json = build_body_dict( - name=name, - allow_answers=allow_answers, - allow_user_suggested_options=allow_user_suggested_options, - description=description, - enforce_unique_vote=enforce_unique_vote, - id=id, - is_closed=is_closed, - max_votes_allowed=max_votes_allowed, - user_id=user_id, - voting_visibility=voting_visibility, - options=options, - custom=custom, - user=user, - ) - - return self.post("/api/v2/chat/polls", PollResponse, json=json) - - def update_poll( - self, - id: str, - name: str, - allow_answers: Optional[bool] = None, - allow_user_suggested_options: Optional[bool] = None, - description: Optional[str] = None, - enforce_unique_vote: Optional[bool] = None, - is_closed: Optional[bool] = None, - max_votes_allowed: Optional[int] = None, - user_id: Optional[str] = None, - voting_visibility: Optional[str] = None, - options: Optional[List[PollOptionRequest]] = None, - custom: Optional[Dict[str, object]] = None, - user: Optional[UserRequest] = None, - ) -> StreamResponse[PollResponse]: - json = build_body_dict( - id=id, - name=name, - allow_answers=allow_answers, - allow_user_suggested_options=allow_user_suggested_options, - description=description, - enforce_unique_vote=enforce_unique_vote, - is_closed=is_closed, - max_votes_allowed=max_votes_allowed, - user_id=user_id, - voting_visibility=voting_visibility, - options=options, - custom=custom, - user=user, - ) - - return self.put("/api/v2/chat/polls", PollResponse, json=json) - - def query_polls( - self, - user_id: Optional[str] = None, - limit: Optional[int] = None, - next: Optional[str] = None, - prev: Optional[str] = None, - sort: Optional[List[SortParamRequest]] = None, - filter: Optional[Dict[str, object]] = None, - ) -> StreamResponse[QueryPollsResponse]: - query_params = build_query_param(user_id=user_id) - json = build_body_dict( - limit=limit, next=next, prev=prev, sort=sort, filter=filter - ) - - return self.post( - "/api/v2/chat/polls/query", - QueryPollsResponse, - query_params=query_params, - json=json, - ) - - def delete_poll( - self, poll_id: str, user_id: Optional[str] = None - ) -> StreamResponse[Response]: - query_params = build_query_param(user_id=user_id) - path_params = { - "poll_id": poll_id, - } - - return self.delete( - "/api/v2/chat/polls/{poll_id}", - Response, - query_params=query_params, - path_params=path_params, - ) - - def get_poll( - self, poll_id: str, user_id: Optional[str] = None - ) -> StreamResponse[PollResponse]: - query_params = build_query_param(user_id=user_id) - path_params = { - "poll_id": poll_id, - } - - return self.get( - "/api/v2/chat/polls/{poll_id}", - PollResponse, - query_params=query_params, - path_params=path_params, - ) - - def update_poll_partial( - self, - poll_id: str, - user_id: Optional[str] = None, - unset: Optional[List[str]] = None, - set: Optional[Dict[str, object]] = None, - user: Optional[UserRequest] = None, - ) -> StreamResponse[PollResponse]: - path_params = { - "poll_id": poll_id, - } - json = build_body_dict(user_id=user_id, unset=unset, set=set, user=user) - - return self.patch( - "/api/v2/chat/polls/{poll_id}", - PollResponse, - path_params=path_params, - json=json, - ) - - def create_poll_option( - self, - poll_id: str, - text: str, - position: Optional[int] = None, - user_id: Optional[str] = None, - custom: Optional[Dict[str, object]] = None, - user: Optional[UserRequest] = None, - ) -> StreamResponse[PollOptionResponse]: - path_params = { - "poll_id": poll_id, - } - json = build_body_dict( - text=text, position=position, user_id=user_id, custom=custom, user=user - ) - - return self.post( - "/api/v2/chat/polls/{poll_id}/options", - PollOptionResponse, - path_params=path_params, - json=json, - ) - - def update_poll_option( - self, - poll_id: str, - id: str, - text: str, - user_id: Optional[str] = None, - custom: Optional[Dict[str, object]] = None, - user: Optional[UserRequest] = None, - ) -> StreamResponse[PollOptionResponse]: - path_params = { - "poll_id": poll_id, - } - json = build_body_dict( - id=id, text=text, user_id=user_id, custom=custom, user=user - ) - - return self.put( - "/api/v2/chat/polls/{poll_id}/options", - PollOptionResponse, - path_params=path_params, - json=json, - ) - - def delete_poll_option( - self, poll_id: str, option_id: str, user_id: Optional[str] = None - ) -> StreamResponse[Response]: - query_params = build_query_param(user_id=user_id) - path_params = { - "poll_id": poll_id, - "option_id": option_id, - } - - return self.delete( - "/api/v2/chat/polls/{poll_id}/options/{option_id}", - Response, - query_params=query_params, - path_params=path_params, - ) - - def get_poll_option( - self, poll_id: str, option_id: str, user_id: Optional[str] = None - ) -> StreamResponse[PollOptionResponse]: - query_params = build_query_param(user_id=user_id) - path_params = { - "poll_id": poll_id, - "option_id": option_id, - } - - return self.get( - "/api/v2/chat/polls/{poll_id}/options/{option_id}", - PollOptionResponse, - query_params=query_params, - path_params=path_params, - ) - - def query_poll_votes( - self, - poll_id: str, - user_id: Optional[str] = None, - limit: Optional[int] = None, - next: Optional[str] = None, - prev: Optional[str] = None, - sort: Optional[List[SortParamRequest]] = None, - filter: Optional[Dict[str, object]] = None, - ) -> StreamResponse[PollVotesResponse]: - query_params = build_query_param(user_id=user_id) - path_params = { - "poll_id": poll_id, - } - json = build_body_dict( - limit=limit, next=next, prev=prev, sort=sort, filter=filter - ) - - return self.post( - "/api/v2/chat/polls/{poll_id}/votes", - PollVotesResponse, - query_params=query_params, - path_params=path_params, - json=json, - ) - def update_push_notification_preferences( self, preferences: List[PushPreferenceInput] ) -> StreamResponse[UpsertPushPreferencesResponse]: diff --git a/getstream/common/rest_client.py b/getstream/common/rest_client.py index 6ad2134b..cc895605 100644 --- a/getstream/common/rest_client.py +++ b/getstream/common/rest_client.py @@ -53,6 +53,7 @@ def update_app( sqs_key: Optional[str] = None, sqs_secret: Optional[str] = None, sqs_url: Optional[str] = None, + user_response_time_enabled: Optional[bool] = None, webhook_url: Optional[str] = None, allowed_flag_reasons: Optional[List[str]] = None, event_hooks: Optional[List[EventHook]] = None, @@ -102,6 +103,7 @@ def update_app( sqs_key=sqs_key, sqs_secret=sqs_secret, sqs_url=sqs_url, + user_response_time_enabled=user_response_time_enabled, webhook_url=webhook_url, allowed_flag_reasons=allowed_flag_reasons, event_hooks=event_hooks, @@ -412,6 +414,243 @@ def get_permission(self, id: str) -> StreamResponse[GetCustomPermissionResponse] path_params=path_params, ) + def create_poll( + self, + name: str, + allow_answers: Optional[bool] = None, + allow_user_suggested_options: Optional[bool] = None, + description: Optional[str] = None, + enforce_unique_vote: Optional[bool] = None, + id: Optional[str] = None, + is_closed: Optional[bool] = None, + max_votes_allowed: Optional[int] = None, + user_id: Optional[str] = None, + voting_visibility: Optional[str] = None, + options: Optional[List[PollOptionInput]] = None, + custom: Optional[Dict[str, object]] = None, + user: Optional[UserRequest] = None, + ) -> StreamResponse[PollResponse]: + json = build_body_dict( + name=name, + allow_answers=allow_answers, + allow_user_suggested_options=allow_user_suggested_options, + description=description, + enforce_unique_vote=enforce_unique_vote, + id=id, + is_closed=is_closed, + max_votes_allowed=max_votes_allowed, + user_id=user_id, + voting_visibility=voting_visibility, + options=options, + custom=custom, + user=user, + ) + + return self.post("/api/v2/polls", PollResponse, json=json) + + def update_poll( + self, + id: str, + name: str, + allow_answers: Optional[bool] = None, + allow_user_suggested_options: Optional[bool] = None, + description: Optional[str] = None, + enforce_unique_vote: Optional[bool] = None, + is_closed: Optional[bool] = None, + max_votes_allowed: Optional[int] = None, + user_id: Optional[str] = None, + voting_visibility: Optional[str] = None, + options: Optional[List[PollOptionRequest]] = None, + custom: Optional[Dict[str, object]] = None, + user: Optional[UserRequest] = None, + ) -> StreamResponse[PollResponse]: + json = build_body_dict( + id=id, + name=name, + allow_answers=allow_answers, + allow_user_suggested_options=allow_user_suggested_options, + description=description, + enforce_unique_vote=enforce_unique_vote, + is_closed=is_closed, + max_votes_allowed=max_votes_allowed, + user_id=user_id, + voting_visibility=voting_visibility, + options=options, + custom=custom, + user=user, + ) + + return self.put("/api/v2/polls", PollResponse, json=json) + + def query_polls( + self, + user_id: Optional[str] = None, + limit: Optional[int] = None, + next: Optional[str] = None, + prev: Optional[str] = None, + sort: Optional[List[SortParamRequest]] = None, + filter: Optional[Dict[str, object]] = None, + ) -> StreamResponse[QueryPollsResponse]: + query_params = build_query_param(user_id=user_id) + json = build_body_dict( + limit=limit, next=next, prev=prev, sort=sort, filter=filter + ) + + return self.post( + "/api/v2/polls/query", + QueryPollsResponse, + query_params=query_params, + json=json, + ) + + def delete_poll( + self, poll_id: str, user_id: Optional[str] = None + ) -> StreamResponse[Response]: + query_params = build_query_param(user_id=user_id) + path_params = { + "poll_id": poll_id, + } + + return self.delete( + "/api/v2/polls/{poll_id}", + Response, + query_params=query_params, + path_params=path_params, + ) + + def get_poll( + self, poll_id: str, user_id: Optional[str] = None + ) -> StreamResponse[PollResponse]: + query_params = build_query_param(user_id=user_id) + path_params = { + "poll_id": poll_id, + } + + return self.get( + "/api/v2/polls/{poll_id}", + PollResponse, + query_params=query_params, + path_params=path_params, + ) + + def update_poll_partial( + self, + poll_id: str, + user_id: Optional[str] = None, + unset: Optional[List[str]] = None, + set: Optional[Dict[str, object]] = None, + user: Optional[UserRequest] = None, + ) -> StreamResponse[PollResponse]: + path_params = { + "poll_id": poll_id, + } + json = build_body_dict(user_id=user_id, unset=unset, set=set, user=user) + + return self.patch( + "/api/v2/polls/{poll_id}", PollResponse, path_params=path_params, json=json + ) + + def create_poll_option( + self, + poll_id: str, + text: str, + user_id: Optional[str] = None, + custom: Optional[Dict[str, object]] = None, + user: Optional[UserRequest] = None, + ) -> StreamResponse[PollOptionResponse]: + path_params = { + "poll_id": poll_id, + } + json = build_body_dict(text=text, user_id=user_id, custom=custom, user=user) + + return self.post( + "/api/v2/polls/{poll_id}/options", + PollOptionResponse, + path_params=path_params, + json=json, + ) + + def update_poll_option( + self, + poll_id: str, + id: str, + text: str, + user_id: Optional[str] = None, + custom: Optional[Dict[str, object]] = None, + user: Optional[UserRequest] = None, + ) -> StreamResponse[PollOptionResponse]: + path_params = { + "poll_id": poll_id, + } + json = build_body_dict( + id=id, text=text, user_id=user_id, custom=custom, user=user + ) + + return self.put( + "/api/v2/polls/{poll_id}/options", + PollOptionResponse, + path_params=path_params, + json=json, + ) + + def delete_poll_option( + self, poll_id: str, option_id: str, user_id: Optional[str] = None + ) -> StreamResponse[Response]: + query_params = build_query_param(user_id=user_id) + path_params = { + "poll_id": poll_id, + "option_id": option_id, + } + + return self.delete( + "/api/v2/polls/{poll_id}/options/{option_id}", + Response, + query_params=query_params, + path_params=path_params, + ) + + def get_poll_option( + self, poll_id: str, option_id: str, user_id: Optional[str] = None + ) -> StreamResponse[PollOptionResponse]: + query_params = build_query_param(user_id=user_id) + path_params = { + "poll_id": poll_id, + "option_id": option_id, + } + + return self.get( + "/api/v2/polls/{poll_id}/options/{option_id}", + PollOptionResponse, + query_params=query_params, + path_params=path_params, + ) + + def query_poll_votes( + self, + poll_id: str, + user_id: Optional[str] = None, + limit: Optional[int] = None, + next: Optional[str] = None, + prev: Optional[str] = None, + sort: Optional[List[SortParamRequest]] = None, + filter: Optional[Dict[str, object]] = None, + ) -> StreamResponse[PollVotesResponse]: + query_params = build_query_param(user_id=user_id) + path_params = { + "poll_id": poll_id, + } + json = build_body_dict( + limit=limit, next=next, prev=prev, sort=sort, filter=filter + ) + + return self.post( + "/api/v2/polls/{poll_id}/votes", + PollVotesResponse, + query_params=query_params, + path_params=path_params, + json=json, + ) + def list_push_providers(self) -> StreamResponse[ListPushProvidersResponse]: return self.get("/api/v2/push_providers", ListPushProvidersResponse) @@ -566,6 +805,7 @@ def delete_users( user_ids: List[str], calls: Optional[str] = None, conversations: Optional[str] = None, + files: Optional[bool] = None, messages: Optional[str] = None, new_call_owner_id: Optional[str] = None, new_channel_owner_id: Optional[str] = None, @@ -575,6 +815,7 @@ def delete_users( user_ids=user_ids, calls=calls, conversations=conversations, + files=files, messages=messages, new_call_owner_id=new_call_owner_id, new_channel_owner_id=new_channel_owner_id, @@ -596,7 +837,6 @@ def get_user_live_locations( def update_live_location( self, - created_by_device_id: str, message_id: str, end_at: Optional[datetime] = None, latitude: Optional[float] = None, @@ -605,11 +845,7 @@ def update_live_location( ) -> StreamResponse[SharedLocationResponse]: query_params = build_query_param(user_id=user_id) json = build_body_dict( - created_by_device_id=created_by_device_id, - message_id=message_id, - end_at=end_at, - latitude=latitude, - longitude=longitude, + message_id=message_id, end_at=end_at, latitude=latitude, longitude=longitude ) return self.put( diff --git a/getstream/models/__init__.py b/getstream/models/__init__.py index 9273a7cd..c1f2078f 100644 --- a/getstream/models/__init__.py +++ b/getstream/models/__init__.py @@ -223,6 +223,12 @@ class ActionSequence(DataClassJsonMixin): warning_text: str = dc_field(metadata=dc_config(field_name="warning_text")) +@dataclass +class ActiveCallsBitrateStats(DataClassJsonMixin): + p10: float = dc_field(metadata=dc_config(field_name="p10")) + p50: float = dc_field(metadata=dc_config(field_name="p50")) + + @dataclass class ActiveCallsFPSStats(DataClassJsonMixin): p05: float = dc_field(metadata=dc_config(field_name="p05")) @@ -250,6 +256,12 @@ class ActiveCallsMetrics(DataClassJsonMixin): ) +@dataclass +class ActiveCallsResolutionStats(DataClassJsonMixin): + p10: float = dc_field(metadata=dc_config(field_name="p10")) + p50: float = dc_field(metadata=dc_config(field_name="p50")) + + @dataclass class ActiveCallsSummary(DataClassJsonMixin): active_calls: int = dc_field(metadata=dc_config(field_name="active_calls")) @@ -262,6 +274,31 @@ class ActiveCallsSummary(DataClassJsonMixin): participants: int = dc_field(metadata=dc_config(field_name="participants")) +@dataclass +class ActivityMarkedEvent(DataClassJsonMixin): + all_read: bool = dc_field(metadata=dc_config(field_name="all_read")) + all_seen: bool = dc_field(metadata=dc_config(field_name="all_seen")) + created_at: datetime = dc_field( + metadata=dc_config( + field_name="created_at", + encoder=encode_datetime, + decoder=datetime_from_unix_ns, + mm_field=fields.DateTime(format="iso"), + ) + ) + feed_id: str = dc_field(metadata=dc_config(field_name="feed_id")) + user_id: str = dc_field(metadata=dc_config(field_name="user_id")) + type: str = dc_field( + default="activity.marked", metadata=dc_config(field_name="type") + ) + marked_read: Optional[List[str]] = dc_field( + default=None, metadata=dc_config(field_name="marked_read") + ) + marked_watched: Optional[List[str]] = dc_field( + default=None, metadata=dc_config(field_name="marked_watched") + ) + + @dataclass class AnyEvent(DataClassJsonMixin): created_at: datetime = dc_field( @@ -305,6 +342,9 @@ class AppResponseFields(DataClassJsonMixin): image_moderation_enabled: bool = dc_field( metadata=dc_config(field_name="image_moderation_enabled") ) + moderation_bulk_submit_action_enabled: bool = dc_field( + metadata=dc_config(field_name="moderation_bulk_submit_action_enabled") + ) moderation_enabled: bool = dc_field( metadata=dc_config(field_name="moderation_enabled") ) @@ -336,6 +376,9 @@ class AppResponseFields(DataClassJsonMixin): metadata=dc_config(field_name="suspended_explanation") ) use_hook_v2: bool = dc_field(metadata=dc_config(field_name="use_hook_v2")) + user_response_time_enabled: bool = dc_field( + metadata=dc_config(field_name="user_response_time_enabled") + ) webhook_url: str = dc_field(metadata=dc_config(field_name="webhook_url")) event_hooks: "List[EventHook]" = dc_field( metadata=dc_config(field_name="event_hooks") @@ -514,7 +557,7 @@ 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.users.error", metadata=dc_config(field_name="type") + default="export.moderation_logs.error", metadata=dc_config(field_name="type") ) received_at: Optional[datetime] = dc_field( default=None, @@ -910,6 +953,14 @@ class BanActionRequest(DataClassJsonMixin): ) +@dataclass +class BanOptions(DataClassJsonMixin): + duration: int = dc_field(metadata=dc_config(field_name="duration")) + ip_ban: bool = dc_field(metadata=dc_config(field_name="ip_ban")) + reason: str = dc_field(metadata=dc_config(field_name="reason")) + shadow_ban: bool = dc_field(metadata=dc_config(field_name="shadow_ban")) + + @dataclass class BanRequest(DataClassJsonMixin): target_user_id: str = dc_field(metadata=dc_config(field_name="target_user_id")) @@ -975,6 +1026,11 @@ class BanResponse(DataClassJsonMixin): ) +@dataclass +class BlockContentOptions(DataClassJsonMixin): + reason: str = dc_field(metadata=dc_config(field_name="reason")) + + @dataclass class BlockListConfig(DataClassJsonMixin): enabled: bool = dc_field(metadata=dc_config(field_name="enabled")) @@ -1833,6 +1889,9 @@ class CallParticipant(DataClassJsonMixin): user_session_id: str = dc_field(metadata=dc_config(field_name="UserSessionID")) custom: Dict[str, object] = dc_field(metadata=dc_config(field_name="custom")) teams_role: "Dict[str, str]" = dc_field(metadata=dc_config(field_name="teams_role")) + avg_response_time: Optional[int] = dc_field( + default=None, metadata=dc_config(field_name="avg_response_time") + ) ban_expires: Optional[datetime] = dc_field( default=None, metadata=dc_config( @@ -2414,6 +2473,30 @@ class CallSessionEndedEvent(DataClassJsonMixin): ) +@dataclass +class CallSessionParticipantCountsUpdatedEvent(DataClassJsonMixin): + anonymous_participant_count: int = dc_field( + metadata=dc_config(field_name="anonymous_participant_count") + ) + call_cid: str = dc_field(metadata=dc_config(field_name="call_cid")) + created_at: datetime = dc_field( + metadata=dc_config( + field_name="created_at", + encoder=encode_datetime, + decoder=datetime_from_unix_ns, + mm_field=fields.DateTime(format="iso"), + ) + ) + session_id: str = dc_field(metadata=dc_config(field_name="session_id")) + participants_count_by_role: "Dict[str, int]" = dc_field( + metadata=dc_config(field_name="participants_count_by_role") + ) + type: str = dc_field( + default="call.session_participant_count_updated", + metadata=dc_config(field_name="type"), + ) + + @dataclass class CallSessionParticipantJoinedEvent(DataClassJsonMixin): call_cid: str = dc_field(metadata=dc_config(field_name="call_cid")) @@ -2573,6 +2656,9 @@ class CallSettings(DataClassJsonMixin): geofencing: "Optional[GeofenceSettings]" = dc_field( default=None, metadata=dc_config(field_name="geofencing") ) + ingress: "Optional[IngressSettings]" = dc_field( + default=None, metadata=dc_config(field_name="ingress") + ) limits: "Optional[LimitsSettings]" = dc_field( default=None, metadata=dc_config(field_name="limits") ) @@ -2616,6 +2702,9 @@ class CallSettingsRequest(DataClassJsonMixin): geofencing: "Optional[GeofenceSettingsRequest]" = dc_field( default=None, metadata=dc_config(field_name="geofencing") ) + ingress: "Optional[IngressSettingsRequest]" = dc_field( + default=None, metadata=dc_config(field_name="ingress") + ) limits: "Optional[LimitsSettingsRequest]" = dc_field( default=None, metadata=dc_config(field_name="limits") ) @@ -2675,6 +2764,9 @@ class CallSettingsResponse(DataClassJsonMixin): metadata=dc_config(field_name="transcription") ) video: "VideoSettingsResponse" = dc_field(metadata=dc_config(field_name="video")) + ingress: "Optional[IngressSettingsResponse]" = dc_field( + default=None, metadata=dc_config(field_name="ingress") + ) @dataclass @@ -4613,6 +4705,9 @@ class ConfigResponse(DataClassJsonMixin): block_list_config: "Optional[BlockListConfig]" = dc_field( default=None, metadata=dc_config(field_name="block_list_config") ) + rule_builder_config: "Optional[RuleBuilderConfig]" = dc_field( + default=None, metadata=dc_config(field_name="rule_builder_config") + ) velocity_filter_config: "Optional[VelocityFilterConfig]" = dc_field( default=None, metadata=dc_config(field_name="velocity_filter_config") ) @@ -4621,6 +4716,12 @@ class ConfigResponse(DataClassJsonMixin): ) +@dataclass +class ContentCountRuleParameters(DataClassJsonMixin): + threshold: int = dc_field(metadata=dc_config(field_name="threshold")) + time_window: str = dc_field(metadata=dc_config(field_name="time_window")) + + @dataclass class CountByMinuteResponse(DataClassJsonMixin): count: int = dc_field(metadata=dc_config(field_name="count")) @@ -4963,9 +5064,6 @@ class CreateImportURLResponse(DataClassJsonMixin): @dataclass class CreatePollOptionRequest(DataClassJsonMixin): text: str = dc_field(metadata=dc_config(field_name="text")) - position: Optional[int] = dc_field( - default=None, metadata=dc_config(field_name="position") - ) user_id: Optional[str] = dc_field( default=None, metadata=dc_config(field_name="user_id") ) @@ -5354,6 +5452,9 @@ class DeleteUsersRequest(DataClassJsonMixin): conversations: Optional[str] = dc_field( default=None, metadata=dc_config(field_name="conversations") ) + files: Optional[bool] = dc_field( + default=None, metadata=dc_config(field_name="files") + ) messages: Optional[str] = dc_field( default=None, metadata=dc_config(field_name="messages") ) @@ -5669,6 +5770,9 @@ class EntityCreator(DataClassJsonMixin): role: str = dc_field(metadata=dc_config(field_name="role")) custom: Dict[str, object] = dc_field(metadata=dc_config(field_name="custom")) teams_role: "Dict[str, str]" = dc_field(metadata=dc_config(field_name="teams_role")) + avg_response_time: Optional[int] = dc_field( + default=None, metadata=dc_config(field_name="avg_response_time") + ) ban_expires: Optional[datetime] = dc_field( default=None, metadata=dc_config( @@ -5790,6 +5894,9 @@ class EntityCreatorResponse(DataClassJsonMixin): ) teams: List[str] = dc_field(metadata=dc_config(field_name="teams")) custom: Dict[str, object] = dc_field(metadata=dc_config(field_name="custom")) + avg_response_time: Optional[int] = dc_field( + default=None, metadata=dc_config(field_name="avg_response_time") + ) ban_expires: Optional[datetime] = dc_field( default=None, metadata=dc_config( @@ -6225,6 +6332,11 @@ class Flag(DataClassJsonMixin): ) +@dataclass +class FlagContentOptions(DataClassJsonMixin): + reason: str = dc_field(metadata=dc_config(field_name="reason")) + + @dataclass class FlagDetails(DataClassJsonMixin): original_text: str = dc_field(metadata=dc_config(field_name="original_text")) @@ -6326,6 +6438,11 @@ class FlagUpdatedEvent(DataClassJsonMixin): ) +@dataclass +class FlagUserOptions(DataClassJsonMixin): + reason: str = dc_field(metadata=dc_config(field_name="reason")) + + @dataclass class FrameRecordSettings(DataClassJsonMixin): capture_interval_in_seconds: int = dc_field( @@ -6421,6 +6538,9 @@ class FullUserResponse(DataClassJsonMixin): mutes: "List[UserMuteResponse]" = dc_field(metadata=dc_config(field_name="mutes")) teams: List[str] = dc_field(metadata=dc_config(field_name="teams")) custom: Dict[str, object] = dc_field(metadata=dc_config(field_name="custom")) + avg_response_time: Optional[int] = dc_field( + default=None, metadata=dc_config(field_name="avg_response_time") + ) ban_expires: Optional[datetime] = dc_field( default=None, metadata=dc_config( @@ -7108,6 +7228,13 @@ class HuaweiConfigFields(DataClassJsonMixin): ) +@dataclass +class ImageContentParameters(DataClassJsonMixin): + harm_labels: Optional[List[str]] = dc_field( + default=None, metadata=dc_config(field_name="harm_labels") + ) + + @dataclass class ImageData(DataClassJsonMixin): frames: str = dc_field(metadata=dc_config(field_name="frames")) @@ -7117,6 +7244,15 @@ class ImageData(DataClassJsonMixin): width: str = dc_field(metadata=dc_config(field_name="width")) +@dataclass +class ImageRuleParameters(DataClassJsonMixin): + threshold: int = dc_field(metadata=dc_config(field_name="threshold")) + time_window: str = dc_field(metadata=dc_config(field_name="time_window")) + harm_labels: Optional[List[str]] = dc_field( + default=None, metadata=dc_config(field_name="harm_labels") + ) + + @dataclass class ImageSize(DataClassJsonMixin): crop: Optional[str] = dc_field(default=None, metadata=dc_config(field_name="crop")) @@ -7215,6 +7351,112 @@ class ImportTaskHistory(DataClassJsonMixin): prev_state: str = dc_field(metadata=dc_config(field_name="prev_state")) +@dataclass +class IngressAudioEncodingOptions(DataClassJsonMixin): + bitrate: int = dc_field(metadata=dc_config(field_name="bitrate")) + channels: int = dc_field(metadata=dc_config(field_name="channels")) + enable_dtx: bool = dc_field(metadata=dc_config(field_name="enable_dtx")) + + +@dataclass +class IngressAudioEncodingOptionsRequest(DataClassJsonMixin): + bitrate: int = dc_field(metadata=dc_config(field_name="bitrate")) + channels: int = dc_field(metadata=dc_config(field_name="channels")) + enable_dtx: Optional[bool] = dc_field( + default=None, metadata=dc_config(field_name="enable_dtx") + ) + + +@dataclass +class IngressAudioEncodingResponse(DataClassJsonMixin): + bitrate: int = dc_field(metadata=dc_config(field_name="bitrate")) + channels: int = dc_field(metadata=dc_config(field_name="channels")) + enable_dtx: bool = dc_field(metadata=dc_config(field_name="enable_dtx")) + + +@dataclass +class IngressSettings(DataClassJsonMixin): + enabled: bool = dc_field(metadata=dc_config(field_name="enabled")) + audio_encoding_options: "Optional[IngressAudioEncodingOptions]" = dc_field( + default=None, metadata=dc_config(field_name="audio_encoding_options") + ) + video_encoding_options: "Optional[Dict[str, IngressVideoEncodingOptions]]" = ( + dc_field(default=None, metadata=dc_config(field_name="video_encoding_options")) + ) + + +@dataclass +class IngressSettingsRequest(DataClassJsonMixin): + enabled: Optional[bool] = dc_field( + default=None, metadata=dc_config(field_name="enabled") + ) + audio_encoding_options: "Optional[IngressAudioEncodingOptionsRequest]" = dc_field( + default=None, metadata=dc_config(field_name="audio_encoding_options") + ) + video_encoding_options: "Optional[Dict[str, IngressVideoEncodingOptionsRequest]]" = dc_field( + default=None, metadata=dc_config(field_name="video_encoding_options") + ) + + +@dataclass +class IngressSettingsResponse(DataClassJsonMixin): + enabled: bool = dc_field(metadata=dc_config(field_name="enabled")) + audio_encoding_options: "Optional[IngressAudioEncodingResponse]" = dc_field( + default=None, metadata=dc_config(field_name="audio_encoding_options") + ) + video_encoding_options: "Optional[Dict[str, IngressVideoEncodingResponse]]" = ( + dc_field(default=None, metadata=dc_config(field_name="video_encoding_options")) + ) + + +@dataclass +class IngressVideoEncodingOptions(DataClassJsonMixin): + layers: "List[IngressVideoLayer]" = dc_field( + metadata=dc_config(field_name="layers") + ) + + +@dataclass +class IngressVideoEncodingOptionsRequest(DataClassJsonMixin): + layers: "List[IngressVideoLayerRequest]" = dc_field( + metadata=dc_config(field_name="layers") + ) + + +@dataclass +class IngressVideoEncodingResponse(DataClassJsonMixin): + layers: "List[IngressVideoLayerResponse]" = dc_field( + metadata=dc_config(field_name="layers") + ) + + +@dataclass +class IngressVideoLayer(DataClassJsonMixin): + bitrate: int = dc_field(metadata=dc_config(field_name="bitrate")) + codec: str = dc_field(metadata=dc_config(field_name="codec")) + frame_rate: int = dc_field(metadata=dc_config(field_name="frame_rate")) + max_dimension: int = dc_field(metadata=dc_config(field_name="max_dimension")) + min_dimension: int = dc_field(metadata=dc_config(field_name="min_dimension")) + + +@dataclass +class IngressVideoLayerRequest(DataClassJsonMixin): + bitrate: int = dc_field(metadata=dc_config(field_name="bitrate")) + codec: str = dc_field(metadata=dc_config(field_name="codec")) + frame_rate_limit: int = dc_field(metadata=dc_config(field_name="frame_rate_limit")) + max_dimension: int = dc_field(metadata=dc_config(field_name="max_dimension")) + min_dimension: int = dc_field(metadata=dc_config(field_name="min_dimension")) + + +@dataclass +class IngressVideoLayerResponse(DataClassJsonMixin): + bitrate: int = dc_field(metadata=dc_config(field_name="bitrate")) + codec: str = dc_field(metadata=dc_config(field_name="codec")) + frame_rate_limit: int = dc_field(metadata=dc_config(field_name="frame_rate_limit")) + max_dimension: int = dc_field(metadata=dc_config(field_name="max_dimension")) + min_dimension: int = dc_field(metadata=dc_config(field_name="min_dimension")) + + @dataclass class JoinCallAPIMetrics(DataClassJsonMixin): failures: float = dc_field(metadata=dc_config(field_name="failures")) @@ -7998,7 +8240,9 @@ class MessageNewEvent(DataClassJsonMixin): ) ) watcher_count: int = dc_field(metadata=dc_config(field_name="watcher_count")) - type: str = dc_field(default="message.new", metadata=dc_config(field_name="type")) + type: str = dc_field( + default="notification.thread_message_new", metadata=dc_config(field_name="type") + ) team: Optional[str] = dc_field(default=None, metadata=dc_config(field_name="team")) thread_participants: "Optional[List[User]]" = dc_field( default=None, metadata=dc_config(field_name="thread_participants") @@ -8614,6 +8858,9 @@ class ModerationCustomActionEvent(DataClassJsonMixin): @dataclass class ModerationDashboardPreferences(DataClassJsonMixin): + flag_user_on_flagged_content: Optional[bool] = dc_field( + default=None, metadata=dc_config(field_name="flag_user_on_flagged_content") + ) media_queue_blur_enabled: Optional[bool] = dc_field( default=None, metadata=dc_config(field_name="media_queue_blur_enabled") ) @@ -8624,9 +8871,12 @@ class ModerationFlagResponse(DataClassJsonMixin): created_at: str = dc_field(metadata=dc_config(field_name="created_at")) entity_id: str = dc_field(metadata=dc_config(field_name="entity_id")) entity_type: str = dc_field(metadata=dc_config(field_name="entity_type")) - id: str = dc_field(metadata=dc_config(field_name="id")) type: str = dc_field(metadata=dc_config(field_name="type")) updated_at: str = dc_field(metadata=dc_config(field_name="updated_at")) + user_id: str = dc_field(metadata=dc_config(field_name="user_id")) + result: "List[Dict[str, object]]" = dc_field( + metadata=dc_config(field_name="result") + ) entity_creator_id: Optional[str] = dc_field( default=None, metadata=dc_config(field_name="entity_creator_id") ) @@ -8639,9 +8889,6 @@ class ModerationFlagResponse(DataClassJsonMixin): labels: Optional[List[str]] = dc_field( default=None, metadata=dc_config(field_name="labels") ) - result: "Optional[List[Dict[str, object]]]" = dc_field( - default=None, metadata=dc_config(field_name="result") - ) custom: Optional[Dict[str, object]] = dc_field( default=None, metadata=dc_config(field_name="custom") ) @@ -9021,6 +9268,9 @@ class OwnUser(DataClassJsonMixin): total_unread_count_by_team: "Dict[str, int]" = dc_field( metadata=dc_config(field_name="total_unread_count_by_team") ) + avg_response_time: Optional[int] = dc_field( + default=None, metadata=dc_config(field_name="avg_response_time") + ) deactivated_at: Optional[datetime] = dc_field( default=None, metadata=dc_config( @@ -9117,6 +9367,9 @@ class OwnUserResponse(DataClassJsonMixin): mutes: "List[UserMuteResponse]" = dc_field(metadata=dc_config(field_name="mutes")) teams: List[str] = dc_field(metadata=dc_config(field_name="teams")) custom: Dict[str, object] = dc_field(metadata=dc_config(field_name="custom")) + avg_response_time: Optional[int] = dc_field( + default=None, metadata=dc_config(field_name="avg_response_time") + ) deactivated_at: Optional[datetime] = dc_field( default=None, metadata=dc_config( @@ -9246,6 +9499,44 @@ class ParticipantReportResponse(DataClassJsonMixin): ) +@dataclass +class PendingMessageEvent(DataClassJsonMixin): + created_at: datetime = dc_field( + metadata=dc_config( + field_name="created_at", + encoder=encode_datetime, + decoder=datetime_from_unix_ns, + mm_field=fields.DateTime(format="iso"), + ) + ) + method: str = dc_field(metadata=dc_config(field_name="method")) + custom: Dict[str, object] = dc_field(metadata=dc_config(field_name="custom")) + type: str = dc_field( + default="message.pending", metadata=dc_config(field_name="type") + ) + received_at: Optional[datetime] = dc_field( + default=None, + metadata=dc_config( + field_name="received_at", + encoder=encode_datetime, + decoder=datetime_from_unix_ns, + mm_field=fields.DateTime(format="iso"), + ), + ) + channel: "Optional[Channel]" = dc_field( + default=None, metadata=dc_config(field_name="channel") + ) + message: "Optional[Message]" = dc_field( + default=None, metadata=dc_config(field_name="message") + ) + metadata: "Optional[Dict[str, str]]" = dc_field( + default=None, metadata=dc_config(field_name="metadata") + ) + user: "Optional[User]" = dc_field( + default=None, metadata=dc_config(field_name="user") + ) + + @dataclass class PendingMessageResponse(DataClassJsonMixin): channel: "Optional[ChannelResponse]" = dc_field( @@ -9501,7 +9792,7 @@ class PollResponseData(DataClassJsonMixin): own_votes: "List[PollVoteResponseData]" = dc_field( metadata=dc_config(field_name="own_votes") ) - custom: Dict[str, object] = dc_field(metadata=dc_config(field_name="Custom")) + custom: Dict[str, object] = dc_field(metadata=dc_config(field_name="custom")) latest_votes_by_option: "Dict[str, List[PollVoteResponseData]]" = dc_field( metadata=dc_config(field_name="latest_votes_by_option") ) @@ -9658,6 +9949,9 @@ class PublisherStatsResponse(DataClassJsonMixin): @dataclass class PublisherVideoMetrics(DataClassJsonMixin): + bitrate: "Optional[ActiveCallsBitrateStats]" = dc_field( + default=None, metadata=dc_config(field_name="bitrate") + ) fps_30: "Optional[ActiveCallsFPSStats]" = dc_field( default=None, metadata=dc_config(field_name="fps_30") ) @@ -9667,6 +9961,9 @@ class PublisherVideoMetrics(DataClassJsonMixin): jitter_ms: "Optional[ActiveCallsLatencyStats]" = dc_field( default=None, metadata=dc_config(field_name="jitter_ms") ) + resolution: "Optional[ActiveCallsResolutionStats]" = dc_field( + default=None, metadata=dc_config(field_name="resolution") + ) @dataclass @@ -9717,6 +10014,9 @@ class PushNotificationSettingsResponse(DataClassJsonMixin): @dataclass class PushPreferenceInput(DataClassJsonMixin): + call_level: Optional[str] = dc_field( + default=None, metadata=dc_config(field_name="call_level") + ) channel_cid: Optional[str] = dc_field( default=None, metadata=dc_config(field_name="channel_cid") ) @@ -11166,6 +11466,108 @@ class RecordingEgressConfig(DataClassJsonMixin): ) +@dataclass +class ReminderCreatedEvent(DataClassJsonMixin): + cid: str = dc_field(metadata=dc_config(field_name="cid")) + created_at: datetime = dc_field( + metadata=dc_config( + field_name="created_at", + encoder=encode_datetime, + decoder=datetime_from_unix_ns, + mm_field=fields.DateTime(format="iso"), + ) + ) + message_id: str = dc_field(metadata=dc_config(field_name="message_id")) + user_id: str = dc_field(metadata=dc_config(field_name="user_id")) + custom: Dict[str, object] = dc_field(metadata=dc_config(field_name="custom")) + type: str = dc_field( + default="reminder.created", metadata=dc_config(field_name="type") + ) + parent_id: Optional[str] = dc_field( + default=None, metadata=dc_config(field_name="parent_id") + ) + received_at: Optional[datetime] = dc_field( + default=None, + metadata=dc_config( + field_name="received_at", + encoder=encode_datetime, + decoder=datetime_from_unix_ns, + mm_field=fields.DateTime(format="iso"), + ), + ) + reminder: "Optional[ReminderResponseData]" = dc_field( + default=None, metadata=dc_config(field_name="reminder") + ) + + +@dataclass +class ReminderDeletedEvent(DataClassJsonMixin): + cid: str = dc_field(metadata=dc_config(field_name="cid")) + created_at: datetime = dc_field( + metadata=dc_config( + field_name="created_at", + encoder=encode_datetime, + decoder=datetime_from_unix_ns, + mm_field=fields.DateTime(format="iso"), + ) + ) + message_id: str = dc_field(metadata=dc_config(field_name="message_id")) + user_id: str = dc_field(metadata=dc_config(field_name="user_id")) + custom: Dict[str, object] = dc_field(metadata=dc_config(field_name="custom")) + type: str = dc_field( + default="reminder.deleted", metadata=dc_config(field_name="type") + ) + parent_id: Optional[str] = dc_field( + default=None, metadata=dc_config(field_name="parent_id") + ) + received_at: Optional[datetime] = dc_field( + default=None, + metadata=dc_config( + field_name="received_at", + encoder=encode_datetime, + decoder=datetime_from_unix_ns, + mm_field=fields.DateTime(format="iso"), + ), + ) + reminder: "Optional[ReminderResponseData]" = dc_field( + default=None, metadata=dc_config(field_name="reminder") + ) + + +@dataclass +class ReminderNotificationEvent(DataClassJsonMixin): + cid: str = dc_field(metadata=dc_config(field_name="cid")) + created_at: datetime = dc_field( + metadata=dc_config( + field_name="created_at", + encoder=encode_datetime, + decoder=datetime_from_unix_ns, + mm_field=fields.DateTime(format="iso"), + ) + ) + message_id: str = dc_field(metadata=dc_config(field_name="message_id")) + user_id: str = dc_field(metadata=dc_config(field_name="user_id")) + custom: Dict[str, object] = dc_field(metadata=dc_config(field_name="custom")) + type: str = dc_field( + default="notification.reminder_due", metadata=dc_config(field_name="type") + ) + parent_id: Optional[str] = dc_field( + default=None, metadata=dc_config(field_name="parent_id") + ) + received_at: Optional[datetime] = dc_field( + default=None, + metadata=dc_config( + field_name="received_at", + encoder=encode_datetime, + decoder=datetime_from_unix_ns, + mm_field=fields.DateTime(format="iso"), + ), + ) + reminder: "Optional[ReminderResponseData]" = dc_field( + default=None, metadata=dc_config(field_name="reminder") + ) + + @dataclass class ReminderResponseData(DataClassJsonMixin): channel_cid: str = dc_field(metadata=dc_config(field_name="channel_cid")) @@ -11207,6 +11609,40 @@ class ReminderResponseData(DataClassJsonMixin): ) +@dataclass +class ReminderUpdatedEvent(DataClassJsonMixin): + cid: str = dc_field(metadata=dc_config(field_name="cid")) + created_at: datetime = dc_field( + metadata=dc_config( + field_name="created_at", + encoder=encode_datetime, + decoder=datetime_from_unix_ns, + mm_field=fields.DateTime(format="iso"), + ) + ) + message_id: str = dc_field(metadata=dc_config(field_name="message_id")) + user_id: str = dc_field(metadata=dc_config(field_name="user_id")) + custom: Dict[str, object] = dc_field(metadata=dc_config(field_name="custom")) + type: str = dc_field( + default="reminder.updated", metadata=dc_config(field_name="type") + ) + parent_id: Optional[str] = dc_field( + default=None, metadata=dc_config(field_name="parent_id") + ) + received_at: Optional[datetime] = dc_field( + default=None, + metadata=dc_config( + field_name="received_at", + encoder=encode_datetime, + decoder=datetime_from_unix_ns, + mm_field=fields.DateTime(format="iso"), + ), + ) + reminder: "Optional[ReminderResponseData]" = dc_field( + default=None, metadata=dc_config(field_name="reminder") + ) + + @dataclass class ReportByHistogramBucket(DataClassJsonMixin): category: str = dc_field(metadata=dc_config(field_name="category")) @@ -11286,9 +11722,13 @@ class ReviewQueueItem(DataClassJsonMixin): ) actions: "List[ActionLog]" = dc_field(metadata=dc_config(field_name="actions")) bans: "List[Ban]" = dc_field(metadata=dc_config(field_name="bans")) + flag_labels: List[str] = dc_field(metadata=dc_config(field_name="flag_labels")) + flag_types: List[str] = dc_field(metadata=dc_config(field_name="flag_types")) flags: "List[Flag]" = dc_field(metadata=dc_config(field_name="flags")) languages: List[str] = dc_field(metadata=dc_config(field_name="languages")) + reporter_ids: List[str] = dc_field(metadata=dc_config(field_name="reporter_ids")) teams: List[str] = dc_field(metadata=dc_config(field_name="teams")) + archived_at: "NullTime" = dc_field(metadata=dc_config(field_name="archived_at")) completed_at: "NullTime" = dc_field(metadata=dc_config(field_name="completed_at")) reviewed_at: "NullTime" = dc_field(metadata=dc_config(field_name="reviewed_at")) activity: "Optional[EnrichedActivity]" = dc_field( @@ -11343,7 +11783,7 @@ class ReviewQueueItemNewEvent(DataClassJsonMixin): mm_field=fields.DateTime(format="iso"), ), ) - flags: "Optional[List[FlagResponse]]" = dc_field( + flags: "Optional[List[ModerationFlagResponse]]" = dc_field( default=None, metadata=dc_config(field_name="flags") ) action: "Optional[ActionLogResponse]" = dc_field( @@ -11387,7 +11827,9 @@ class ReviewQueueItemResponse(DataClassJsonMixin): metadata=dc_config(field_name="actions") ) bans: "List[Ban]" = dc_field(metadata=dc_config(field_name="bans")) - flags: "List[FlagResponse]" = dc_field(metadata=dc_config(field_name="flags")) + flags: "List[ModerationFlagResponse]" = dc_field( + metadata=dc_config(field_name="flags") + ) languages: List[str] = dc_field(metadata=dc_config(field_name="languages")) completed_at: Optional[datetime] = dc_field( default=None, @@ -11468,7 +11910,7 @@ class ReviewQueueItemUpdatedEvent(DataClassJsonMixin): mm_field=fields.DateTime(format="iso"), ), ) - flags: "Optional[List[FlagResponse]]" = dc_field( + flags: "Optional[List[ModerationFlagResponse]]" = dc_field( default=None, metadata=dc_config(field_name="flags") ) action: "Optional[ActionLogResponse]" = dc_field( @@ -11543,62 +11985,90 @@ class Role(DataClassJsonMixin): @dataclass class RuleBuilderAction(DataClassJsonMixin): - duration: Optional[int] = dc_field( - default=None, metadata=dc_config(field_name="duration") + type: str = dc_field(metadata=dc_config(field_name="type")) + ban_options: "Optional[BanOptions]" = dc_field( + default=None, metadata=dc_config(field_name="ban_options") ) - ip_ban: Optional[bool] = dc_field( - default=None, metadata=dc_config(field_name="ip_ban") + flag_content_options: "Optional[FlagContentOptions]" = dc_field( + default=None, metadata=dc_config(field_name="flag_content_options") ) - reason: Optional[str] = dc_field( - default=None, metadata=dc_config(field_name="reason") + flag_user_options: "Optional[FlagUserOptions]" = dc_field( + default=None, metadata=dc_config(field_name="flag_user_options") ) - shadow_ban: Optional[bool] = dc_field( - default=None, metadata=dc_config(field_name="shadow_ban") + remove_content_options: "Optional[BlockContentOptions]" = dc_field( + default=None, metadata=dc_config(field_name="remove_content_options") ) - type: Optional[str] = dc_field(default=None, metadata=dc_config(field_name="type")) @dataclass class RuleBuilderCondition(DataClassJsonMixin): - provider: Optional[str] = dc_field( - default=None, metadata=dc_config(field_name="provider") + type: str = dc_field(metadata=dc_config(field_name="type")) + confidence: Optional[float] = dc_field( + default=None, metadata=dc_config(field_name="confidence") ) - threshold: Optional[int] = dc_field( - default=None, metadata=dc_config(field_name="threshold") + content_count_rule_params: "Optional[ContentCountRuleParameters]" = dc_field( + default=None, metadata=dc_config(field_name="content_count_rule_params") ) - time_window: Optional[str] = dc_field( - default=None, metadata=dc_config(field_name="time_window") + image_content_params: "Optional[ImageContentParameters]" = dc_field( + default=None, metadata=dc_config(field_name="image_content_params") ) - labels: Optional[List[str]] = dc_field( - default=None, metadata=dc_config(field_name="labels") + image_rule_params: "Optional[ImageRuleParameters]" = dc_field( + default=None, metadata=dc_config(field_name="image_rule_params") + ) + text_content_params: "Optional[TextContentParameters]" = dc_field( + default=None, metadata=dc_config(field_name="text_content_params") + ) + text_rule_params: "Optional[TextRuleParameters]" = dc_field( + default=None, metadata=dc_config(field_name="text_rule_params") + ) + user_created_within_params: "Optional[UserCreatedWithinParameters]" = dc_field( + default=None, metadata=dc_config(field_name="user_created_within_params") + ) + user_rule_params: "Optional[UserRuleParameters]" = dc_field( + default=None, metadata=dc_config(field_name="user_rule_params") + ) + video_content_params: "Optional[VideoContentParameters]" = dc_field( + default=None, metadata=dc_config(field_name="video_content_params") + ) + video_rule_params: "Optional[VideoRuleParameters]" = dc_field( + default=None, metadata=dc_config(field_name="video_rule_params") + ) + + +@dataclass +class RuleBuilderConditionGroup(DataClassJsonMixin): + logic: str = dc_field(metadata=dc_config(field_name="logic")) + conditions: "List[RuleBuilderCondition]" = dc_field( + metadata=dc_config(field_name="conditions") ) @dataclass class RuleBuilderConfig(DataClassJsonMixin): + rules: "List[RuleBuilderRule]" = dc_field(metadata=dc_config(field_name="rules")) _async: Optional[bool] = dc_field( default=None, metadata=dc_config(field_name="async") ) - enabled: Optional[bool] = dc_field( - default=None, metadata=dc_config(field_name="enabled") - ) - rules: "Optional[List[RuleBuilderRule]]" = dc_field( - default=None, metadata=dc_config(field_name="rules") - ) @dataclass class RuleBuilderRule(DataClassJsonMixin): - enabled: Optional[bool] = dc_field( - default=None, metadata=dc_config(field_name="enabled") + enabled: bool = dc_field(metadata=dc_config(field_name="enabled")) + id: str = dc_field(metadata=dc_config(field_name="id")) + name: str = dc_field(metadata=dc_config(field_name="name")) + rule_type: str = dc_field(metadata=dc_config(field_name="rule_type")) + action: "RuleBuilderAction" = dc_field(metadata=dc_config(field_name="action")) + cooldown_period: Optional[str] = dc_field( + default=None, metadata=dc_config(field_name="cooldown_period") + ) + logic: Optional[str] = dc_field( + default=None, metadata=dc_config(field_name="logic") ) - id: Optional[str] = dc_field(default=None, metadata=dc_config(field_name="id")) - name: Optional[str] = dc_field(default=None, metadata=dc_config(field_name="name")) conditions: "Optional[List[RuleBuilderCondition]]" = dc_field( default=None, metadata=dc_config(field_name="conditions") ) - action: "Optional[RuleBuilderAction]" = dc_field( - default=None, metadata=dc_config(field_name="action") + groups: "Optional[List[RuleBuilderConditionGroup]]" = dc_field( + default=None, metadata=dc_config(field_name="groups") ) @@ -12618,6 +13088,40 @@ class TargetResolution(DataClassJsonMixin): width: int = dc_field(metadata=dc_config(field_name="width")) +@dataclass +class TextContentParameters(DataClassJsonMixin): + contains_url: Optional[bool] = dc_field( + default=None, metadata=dc_config(field_name="contains_url") + ) + severity: Optional[str] = dc_field( + default=None, metadata=dc_config(field_name="severity") + ) + blocklist_match: Optional[List[str]] = dc_field( + default=None, metadata=dc_config(field_name="blocklist_match") + ) + harm_labels: Optional[List[str]] = dc_field( + default=None, metadata=dc_config(field_name="harm_labels") + ) + + +@dataclass +class TextRuleParameters(DataClassJsonMixin): + threshold: int = dc_field(metadata=dc_config(field_name="threshold")) + time_window: str = dc_field(metadata=dc_config(field_name="time_window")) + contains_url: Optional[bool] = dc_field( + default=None, metadata=dc_config(field_name="contains_url") + ) + severity: Optional[str] = dc_field( + default=None, metadata=dc_config(field_name="severity") + ) + blocklist_match: Optional[List[str]] = dc_field( + default=None, metadata=dc_config(field_name="blocklist_match") + ) + harm_labels: Optional[List[str]] = dc_field( + default=None, metadata=dc_config(field_name="harm_labels") + ) + + @dataclass class ThreadParticipant(DataClassJsonMixin): app_pk: int = dc_field(metadata=dc_config(field_name="app_pk")) @@ -13136,8 +13640,8 @@ class UnreadCountsResponse(DataClassJsonMixin): threads: "List[UnreadCountsThread]" = dc_field( metadata=dc_config(field_name="threads") ) - total_unread_count_by_team: "Dict[str, int]" = dc_field( - metadata=dc_config(field_name="total_unread_count_by_team") + total_unread_count_by_team: "Optional[Dict[str, int]]" = dc_field( + default=None, metadata=dc_config(field_name="total_unread_count_by_team") ) @@ -13249,6 +13753,9 @@ class UpdateAppRequest(DataClassJsonMixin): sqs_url: Optional[str] = dc_field( default=None, metadata=dc_config(field_name="sqs_url") ) + user_response_time_enabled: Optional[bool] = dc_field( + default=None, metadata=dc_config(field_name="user_response_time_enabled") + ) webhook_url: Optional[str] = dc_field( default=None, metadata=dc_config(field_name="webhook_url") ) @@ -13720,9 +14227,6 @@ class UpdateExternalStorageResponse(DataClassJsonMixin): @dataclass class UpdateLiveLocationRequest(DataClassJsonMixin): - created_by_device_id: str = dc_field( - metadata=dc_config(field_name="created_by_device_id") - ) message_id: str = dc_field(metadata=dc_config(field_name="message_id")) end_at: Optional[datetime] = dc_field( default=None, @@ -14163,6 +14667,9 @@ class User(DataClassJsonMixin): role: str = dc_field(metadata=dc_config(field_name="role")) custom: Dict[str, object] = dc_field(metadata=dc_config(field_name="custom")) teams_role: "Dict[str, str]" = dc_field(metadata=dc_config(field_name="teams_role")) + avg_response_time: Optional[int] = dc_field( + default=None, metadata=dc_config(field_name="avg_response_time") + ) ban_expires: Optional[datetime] = dc_field( default=None, metadata=dc_config( @@ -14283,6 +14790,13 @@ class UserBannedEvent(DataClassJsonMixin): ) +@dataclass +class UserCreatedWithinParameters(DataClassJsonMixin): + max_age: Optional[str] = dc_field( + default=None, metadata=dc_config(field_name="max_age") + ) + + @dataclass class UserCustomEventRequest(DataClassJsonMixin): type: str = dc_field(metadata=dc_config(field_name="type")) @@ -14387,6 +14901,48 @@ class UserFlaggedEvent(DataClassJsonMixin): ) +@dataclass +class UserMessagesDeletedEvent(DataClassJsonMixin): + created_at: datetime = dc_field( + metadata=dc_config( + field_name="created_at", + encoder=encode_datetime, + decoder=datetime_from_unix_ns, + mm_field=fields.DateTime(format="iso"), + ) + ) + hard_delete: bool = dc_field(metadata=dc_config(field_name="hard_delete")) + soft_delete: bool = dc_field(metadata=dc_config(field_name="soft_delete")) + custom: Dict[str, object] = dc_field(metadata=dc_config(field_name="custom")) + user: "UserResponseCommonFields" = dc_field(metadata=dc_config(field_name="user")) + type: str = dc_field( + default="user.messages.deleted", metadata=dc_config(field_name="type") + ) + channel_id: Optional[str] = dc_field( + default=None, metadata=dc_config(field_name="channel_id") + ) + channel_member_count: Optional[int] = dc_field( + default=None, metadata=dc_config(field_name="channel_member_count") + ) + channel_type: Optional[str] = dc_field( + default=None, metadata=dc_config(field_name="channel_type") + ) + cid: Optional[str] = dc_field(default=None, metadata=dc_config(field_name="cid")) + received_at: Optional[datetime] = dc_field( + default=None, + metadata=dc_config( + field_name="received_at", + encoder=encode_datetime, + decoder=datetime_from_unix_ns, + mm_field=fields.DateTime(format="iso"), + ), + ) + team: Optional[str] = dc_field(default=None, metadata=dc_config(field_name="team")) + channel_custom: Optional[Dict[str, object]] = dc_field( + default=None, metadata=dc_config(field_name="channel_custom") + ) + + @dataclass class UserMute(DataClassJsonMixin): created_at: datetime = dc_field( @@ -14561,6 +15117,9 @@ class UserResponse(DataClassJsonMixin): ) teams: List[str] = dc_field(metadata=dc_config(field_name="teams")) custom: Dict[str, object] = dc_field(metadata=dc_config(field_name="custom")) + avg_response_time: Optional[int] = dc_field( + default=None, metadata=dc_config(field_name="avg_response_time") + ) ban_expires: Optional[datetime] = dc_field( default=None, metadata=dc_config( @@ -14652,6 +15211,9 @@ class UserResponseCommonFields(DataClassJsonMixin): ) teams: List[str] = dc_field(metadata=dc_config(field_name="teams")) custom: Dict[str, object] = dc_field(metadata=dc_config(field_name="custom")) + avg_response_time: Optional[int] = dc_field( + default=None, metadata=dc_config(field_name="avg_response_time") + ) deactivated_at: Optional[datetime] = dc_field( default=None, metadata=dc_config( @@ -14725,6 +15287,9 @@ class UserResponsePrivacyFields(DataClassJsonMixin): ) teams: List[str] = dc_field(metadata=dc_config(field_name="teams")) custom: Dict[str, object] = dc_field(metadata=dc_config(field_name="custom")) + avg_response_time: Optional[int] = dc_field( + default=None, metadata=dc_config(field_name="avg_response_time") + ) deactivated_at: Optional[datetime] = dc_field( default=None, metadata=dc_config( @@ -14776,6 +15341,13 @@ class UserResponsePrivacyFields(DataClassJsonMixin): ) +@dataclass +class UserRuleParameters(DataClassJsonMixin): + max_age: Optional[str] = dc_field( + default=None, metadata=dc_config(field_name="max_age") + ) + + @dataclass class UserUnbannedEvent(DataClassJsonMixin): channel_id: str = dc_field(metadata=dc_config(field_name="channel_id")) @@ -14916,6 +15488,13 @@ class VideoCallRuleConfig(DataClassJsonMixin): rules: "Dict[str, HarmConfig]" = dc_field(metadata=dc_config(field_name="rules")) +@dataclass +class VideoContentParameters(DataClassJsonMixin): + harm_labels: Optional[List[str]] = dc_field( + default=None, metadata=dc_config(field_name="harm_labels") + ) + + @dataclass class VideoEndCallRequest(DataClassJsonMixin): pass @@ -14948,6 +15527,15 @@ class VideoReactionsResponse(DataClassJsonMixin): ) +@dataclass +class VideoRuleParameters(DataClassJsonMixin): + threshold: int = dc_field(metadata=dc_config(field_name="threshold")) + time_window: str = dc_field(metadata=dc_config(field_name="time_window")) + harm_labels: Optional[List[str]] = dc_field( + default=None, metadata=dc_config(field_name="harm_labels") + ) + + @dataclass class VideoSettings(DataClassJsonMixin): access_request_enabled: bool = dc_field( @@ -15005,9 +15593,6 @@ class VoteData(DataClassJsonMixin): option_id: Optional[str] = dc_field( default=None, metadata=dc_config(field_name="option_id") ) - option: "Optional[PollOptionResponseData]" = dc_field( - default=None, metadata=dc_config(field_name="Option") - ) @dataclass @@ -15121,8 +15706,8 @@ class WrappedUnreadCountsResponse(DataClassJsonMixin): threads: "List[UnreadCountsThread]" = dc_field( metadata=dc_config(field_name="threads") ) - total_unread_count_by_team: "Dict[str, int]" = dc_field( - metadata=dc_config(field_name="total_unread_count_by_team") + total_unread_count_by_team: "Optional[Dict[str, int]]" = dc_field( + default=None, metadata=dc_config(field_name="total_unread_count_by_team") ) diff --git a/uv.lock b/uv.lock index e8609520..10aa81b1 100644 --- a/uv.lock +++ b/uv.lock @@ -148,7 +148,7 @@ wheels = [ [[package]] name = "getstream" -version = "2.2.1" +version = "2.2.2" source = { editable = "." } dependencies = [ { name = "dataclasses-json" }, From d711f7a0d8fb5c933fa177f9aadd51db44c2e581 Mon Sep 17 00:00:00 2001 From: Tommaso Barbugli Date: Fri, 15 Aug 2025 14:56:53 +0200 Subject: [PATCH 13/15] regen --- getstream/models/__init__.py | 8 +++++--- tests/test_video_examples.py | 6 ++++++ 2 files changed, 11 insertions(+), 3 deletions(-) diff --git a/getstream/models/__init__.py b/getstream/models/__init__.py index c1f2078f..79298d55 100644 --- a/getstream/models/__init__.py +++ b/getstream/models/__init__.py @@ -557,7 +557,7 @@ 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.moderation_logs.error", metadata=dc_config(field_name="type") + default="export.channels.error", metadata=dc_config(field_name="type") ) received_at: Optional[datetime] = dc_field( default=None, @@ -1884,8 +1884,8 @@ class CallParticipant(DataClassJsonMixin): ) ) online: bool = dc_field(metadata=dc_config(field_name="online")) - role: str = dc_field(metadata=dc_config(field_name="Role")) role: str = dc_field(metadata=dc_config(field_name="role")) + role: str = dc_field(metadata=dc_config(field_name="Role")) user_session_id: str = dc_field(metadata=dc_config(field_name="UserSessionID")) custom: Dict[str, object] = dc_field(metadata=dc_config(field_name="custom")) teams_role: "Dict[str, str]" = dc_field(metadata=dc_config(field_name="teams_role")) @@ -14911,7 +14911,6 @@ class UserMessagesDeletedEvent(DataClassJsonMixin): mm_field=fields.DateTime(format="iso"), ) ) - hard_delete: bool = dc_field(metadata=dc_config(field_name="hard_delete")) soft_delete: bool = dc_field(metadata=dc_config(field_name="soft_delete")) custom: Dict[str, object] = dc_field(metadata=dc_config(field_name="custom")) user: "UserResponseCommonFields" = dc_field(metadata=dc_config(field_name="user")) @@ -14928,6 +14927,9 @@ class UserMessagesDeletedEvent(DataClassJsonMixin): default=None, metadata=dc_config(field_name="channel_type") ) cid: Optional[str] = dc_field(default=None, metadata=dc_config(field_name="cid")) + hard_delete: Optional[bool] = dc_field( + default=None, metadata=dc_config(field_name="hard_delete") + ) received_at: Optional[datetime] = dc_field( default=None, metadata=dc_config( diff --git a/tests/test_video_examples.py b/tests/test_video_examples.py index 2bf10142..e05fe290 100644 --- a/tests/test_video_examples.py +++ b/tests/test_video_examples.py @@ -379,6 +379,12 @@ def test_create_call_with_custom_frame_recording_settings(client: Stream): assert response.data.call.settings.frame_recording.quality == "1080p" +def test_fps(client: Stream): + response = client.video.get_active_calls_status() + resolution = response.data.metrics.publishers.all.video.resolution + print(resolution.p10) + + @pytest.mark.skip_in_ci def test_create_call_type_with_custom_frame_recording_settings(client: Stream): # create a call type with frame recording settings From 58eaea24f95ccd5f0b661dedd71dec98a4e6ffe8 Mon Sep 17 00:00:00 2001 From: Tommaso Barbugli Date: Fri, 15 Aug 2025 15:01:41 +0200 Subject: [PATCH 14/15] regen --- getstream/models/__init__.py | 72 ++++++++++++++---------------------- uv.lock | 2 +- 2 files changed, 28 insertions(+), 46 deletions(-) diff --git a/getstream/models/__init__.py b/getstream/models/__init__.py index e9262b9f..f76d7821 100644 --- a/getstream/models/__init__.py +++ b/getstream/models/__init__.py @@ -1885,8 +1885,8 @@ class CallParticipant(DataClassJsonMixin): ) ) online: bool = dc_field(metadata=dc_config(field_name="online")) - role: str = dc_field(metadata=dc_config(field_name="role")) role: str = dc_field(metadata=dc_config(field_name="Role")) + role: str = dc_field(metadata=dc_config(field_name="role")) user_session_id: str = dc_field(metadata=dc_config(field_name="UserSessionID")) custom: Dict[str, object] = dc_field(metadata=dc_config(field_name="custom")) teams_role: "Dict[str, str]" = dc_field(metadata=dc_config(field_name="teams_role")) @@ -6287,9 +6287,8 @@ class Flag(DataClassJsonMixin): mm_field=fields.DateTime(format="iso"), ) ) - created_by_automod: bool = dc_field( - metadata=dc_config(field_name="created_by_automod") - ) + entity_id: str = dc_field(metadata=dc_config(field_name="entity_id")) + entity_type: str = dc_field(metadata=dc_config(field_name="entity_type")) updated_at: datetime = dc_field( metadata=dc_config( field_name="updated_at", @@ -6298,53 +6297,36 @@ class Flag(DataClassJsonMixin): mm_field=fields.DateTime(format="iso"), ) ) - approved_at: Optional[datetime] = dc_field( - default=None, - metadata=dc_config( - field_name="approved_at", - encoder=encode_datetime, - decoder=datetime_from_unix_ns, - mm_field=fields.DateTime(format="iso"), - ), + result: "List[Dict[str, object]]" = dc_field( + metadata=dc_config(field_name="result") ) - reason: Optional[str] = dc_field( - default=None, metadata=dc_config(field_name="reason") + entity_creator_id: Optional[str] = dc_field( + default=None, metadata=dc_config(field_name="entity_creator_id") ) - rejected_at: Optional[datetime] = dc_field( - default=None, - metadata=dc_config( - field_name="rejected_at", - encoder=encode_datetime, - decoder=datetime_from_unix_ns, - mm_field=fields.DateTime(format="iso"), - ), + is_streamed_content: Optional[bool] = dc_field( + default=None, metadata=dc_config(field_name="is_streamed_content") ) - reviewed_at: Optional[datetime] = dc_field( - default=None, - metadata=dc_config( - field_name="reviewed_at", - encoder=encode_datetime, - decoder=datetime_from_unix_ns, - mm_field=fields.DateTime(format="iso"), - ), + moderation_payload_hash: Optional[str] = dc_field( + default=None, metadata=dc_config(field_name="moderation_payload_hash") ) - reviewed_by: Optional[str] = dc_field( - default=None, metadata=dc_config(field_name="reviewed_by") + reason: Optional[str] = dc_field( + default=None, metadata=dc_config(field_name="reason") + ) + review_queue_item_id: Optional[str] = dc_field( + default=None, metadata=dc_config(field_name="review_queue_item_id") ) - target_message_id: Optional[str] = dc_field( - default=None, metadata=dc_config(field_name="target_message_id") + type: Optional[str] = dc_field(default=None, metadata=dc_config(field_name="type")) + labels: Optional[List[str]] = dc_field( + default=None, metadata=dc_config(field_name="labels") ) custom: Optional[Dict[str, object]] = dc_field( default=None, metadata=dc_config(field_name="custom") ) - details: "Optional[FlagDetails]" = dc_field( - default=None, metadata=dc_config(field_name="details") - ) - target_message: "Optional[Message]" = dc_field( - default=None, metadata=dc_config(field_name="target_message") + moderation_payload: "Optional[ModerationPayload]" = dc_field( + default=None, metadata=dc_config(field_name="moderation_payload") ) - target_user: "Optional[User]" = dc_field( - default=None, metadata=dc_config(field_name="target_user") + review_queue_item: "Optional[ReviewQueueItem]" = dc_field( + default=None, metadata=dc_config(field_name="review_queue_item") ) user: "Optional[User]" = dc_field( default=None, metadata=dc_config(field_name="user") @@ -8259,9 +8241,7 @@ class MessageNewEvent(DataClassJsonMixin): ) ) watcher_count: int = dc_field(metadata=dc_config(field_name="watcher_count")) - type: str = dc_field( - default="notification.thread_message_new", metadata=dc_config(field_name="type") - ) + type: str = dc_field(default="message.new", metadata=dc_config(field_name="type")) team: Optional[str] = dc_field(default=None, metadata=dc_config(field_name="team")) thread_participants: "Optional[List[User]]" = dc_field( default=None, metadata=dc_config(field_name="thread_participants") @@ -14930,7 +14910,6 @@ class UserMessagesDeletedEvent(DataClassJsonMixin): mm_field=fields.DateTime(format="iso"), ) ) - hard_delete: bool = dc_field(metadata=dc_config(field_name="hard_delete")) soft_delete: bool = dc_field(metadata=dc_config(field_name="soft_delete")) custom: Dict[str, object] = dc_field(metadata=dc_config(field_name="custom")) user: "UserResponseCommonFields" = dc_field(metadata=dc_config(field_name="user")) @@ -14947,6 +14926,9 @@ class UserMessagesDeletedEvent(DataClassJsonMixin): default=None, metadata=dc_config(field_name="channel_type") ) cid: Optional[str] = dc_field(default=None, metadata=dc_config(field_name="cid")) + hard_delete: Optional[bool] = dc_field( + default=None, metadata=dc_config(field_name="hard_delete") + ) received_at: Optional[datetime] = dc_field( default=None, metadata=dc_config( diff --git a/uv.lock b/uv.lock index 10aa81b1..014d29ae 100644 --- a/uv.lock +++ b/uv.lock @@ -148,7 +148,7 @@ wheels = [ [[package]] name = "getstream" -version = "2.2.2" +version = "2.3.0" source = { editable = "." } dependencies = [ { name = "dataclasses-json" }, From 24ec347563043b4218d6fb59b2ad48313b95e32a Mon Sep 17 00:00:00 2001 From: github-actions Date: Fri, 15 Aug 2025 13:03:35 +0000 Subject: [PATCH 15/15] chore(release): 2.3.1 --- getstream/version.py | 2 +- pyproject.toml | 2 +- 2 files changed, 2 insertions(+), 2 deletions(-) diff --git a/getstream/version.py b/getstream/version.py index 707faadc..cbfab60f 100644 --- a/getstream/version.py +++ b/getstream/version.py @@ -1 +1 @@ -VERSION = "2.3.0" +VERSION = "2.3.1" diff --git a/pyproject.toml b/pyproject.toml index f7fbae7f..aef26b82 100644 --- a/pyproject.toml +++ b/pyproject.toml @@ -1,6 +1,6 @@ [project] name = "getstream" -version = "2.3.0" +version = "2.3.1" description = "" authors = [ { name = "sachaarbonel", email = "sacha.arbonel@hotmail.fr" },