diff --git a/getstream/chat/rest_client.py b/getstream/chat/rest_client.py index 28389573..59ac94e3 100644 --- a/getstream/chat/rest_client.py +++ b/getstream/chat/rest_client.py @@ -963,7 +963,7 @@ def send_reaction( def delete_reaction( self, id: str, type: str, user_id: Optional[str] = None - ) -> StreamResponse[ReactionRemovalResponse]: + ) -> StreamResponse[DeleteReactionResponse]: query_params = build_query_param(user_id=user_id) path_params = { "id": id, @@ -972,7 +972,7 @@ def delete_reaction( return self.delete( "/api/v2/chat/messages/{id}/reaction/{type}", - ReactionRemovalResponse, + DeleteReactionResponse, query_params=query_params, path_params=path_params, ) @@ -1418,6 +1418,15 @@ def query_poll_votes( json=json, ) + def update_push_notification_preferences( + self, preferences: List[PushPreferenceInput] + ) -> StreamResponse[UpsertPushPreferencesResponse]: + json = build_body_dict(preferences=preferences) + + return self.post( + "/api/v2/chat/push_preferences", UpsertPushPreferencesResponse, json=json + ) + def query_banned_users( self, payload: Optional[QueryBannedUsersPayload] = None ) -> StreamResponse[QueryBannedUsersResponse]: diff --git a/getstream/common/rest_client.py b/getstream/common/rest_client.py index bd7e9565..ff327ca5 100644 --- a/getstream/common/rest_client.py +++ b/getstream/common/rest_client.py @@ -116,44 +116,69 @@ def update_app( return self.patch("/api/v2/app", Response, json=json) - def list_block_lists(self) -> StreamResponse[ListBlockListResponse]: - return self.get("/api/v2/blocklists", ListBlockListResponse) + def list_block_lists( + self, team: Optional[str] = None + ) -> StreamResponse[ListBlockListResponse]: + query_params = build_query_param(team=team) + + return self.get( + "/api/v2/blocklists", ListBlockListResponse, query_params=query_params + ) def create_block_list( - self, name: str, words: List[str], type: Optional[str] = None - ) -> StreamResponse[Response]: - json = build_body_dict(name=name, words=words, type=type) + self, + name: str, + words: List[str], + team: Optional[str] = None, + type: Optional[str] = None, + ) -> StreamResponse[CreateBlockListResponse]: + json = build_body_dict(name=name, words=words, team=team, type=type) - return self.post("/api/v2/blocklists", Response, json=json) + return self.post("/api/v2/blocklists", CreateBlockListResponse, json=json) - def delete_block_list(self, name: str) -> StreamResponse[Response]: + def delete_block_list( + self, name: str, team: Optional[str] = None + ) -> StreamResponse[Response]: + query_params = build_query_param(team=team) path_params = { "name": name, } return self.delete( - "/api/v2/blocklists/{name}", Response, path_params=path_params + "/api/v2/blocklists/{name}", + Response, + query_params=query_params, + path_params=path_params, ) - def get_block_list(self, name: str) -> StreamResponse[GetBlockListResponse]: + def get_block_list( + self, name: str, team: Optional[str] = None + ) -> StreamResponse[GetBlockListResponse]: + query_params = build_query_param(team=team) path_params = { "name": name, } return self.get( - "/api/v2/blocklists/{name}", GetBlockListResponse, path_params=path_params + "/api/v2/blocklists/{name}", + GetBlockListResponse, + query_params=query_params, + path_params=path_params, ) def update_block_list( - self, name: str, words: Optional[List[str]] = None - ) -> StreamResponse[Response]: + self, name: str, team: Optional[str] = None, words: Optional[List[str]] = None + ) -> StreamResponse[UpdateBlockListResponse]: path_params = { "name": name, } - json = build_body_dict(words=words) + json = build_body_dict(team=team, words=words) return self.put( - "/api/v2/blocklists/{name}", Response, path_params=path_params, json=json + "/api/v2/blocklists/{name}", + UpdateBlockListResponse, + path_params=path_params, + json=json, ) def check_push( diff --git a/getstream/models/__init__.py b/getstream/models/__init__.py index b8326130..f20ccde3 100644 --- a/getstream/models/__init__.py +++ b/getstream/models/__init__.py @@ -201,9 +201,6 @@ class ActionLogResponse(DataClassJsonMixin): @dataclass class AggregatedStats(DataClassJsonMixin): - countrywise_aggregate_stats: "Optional[Dict[str, Optional[CountrywiseAggregateStats]]]" = dc_field( - default=None, metadata=dc_config(field_name="countrywise_aggregate_stats") - ) publisher_aggregate_stats: "Optional[PublisherAggregateStats]" = dc_field( default=None, metadata=dc_config(field_name="publisher_aggregate_stats") ) @@ -255,6 +252,9 @@ class AppResponseFields(DataClassJsonMixin): moderation_enabled: bool = dc_field( metadata=dc_config(field_name="moderation_enabled") ) + moderation_multitenant_blocklist_enabled: bool = dc_field( + metadata=dc_config(field_name="moderation_multitenant_blocklist_enabled") + ) moderation_webhook_url: str = dc_field( metadata=dc_config(field_name="moderation_webhook_url") ) @@ -725,6 +725,8 @@ class BlockListResponse(DataClassJsonMixin): mm_field=fields.DateTime(format="iso"), ), ) + id: Optional[str] = dc_field(default=None, metadata=dc_config(field_name="id")) + team: Optional[str] = dc_field(default=None, metadata=dc_config(field_name="team")) updated_at: Optional[datetime] = dc_field( default=None, metadata=dc_config( @@ -740,6 +742,7 @@ class BlockListResponse(DataClassJsonMixin): class BlockListRule(DataClassJsonMixin): action: str = dc_field(metadata=dc_config(field_name="action")) name: str = dc_field(metadata=dc_config(field_name="name")) + team: str = dc_field(metadata=dc_config(field_name="team")) @dataclass @@ -1048,6 +1051,89 @@ class CallEvent(DataClassJsonMixin): ) +@dataclass +class CallFrameRecordingFailedEvent(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"), + ) + ) + egress_id: str = dc_field(metadata=dc_config(field_name="egress_id")) + call: "CallResponse" = dc_field(metadata=dc_config(field_name="call")) + type: str = dc_field( + default="call.frame_recording_failed", metadata=dc_config(field_name="type") + ) + + +@dataclass +class CallFrameRecordingFrameReadyEvent(DataClassJsonMixin): + call_cid: str = dc_field(metadata=dc_config(field_name="call_cid")) + captured_at: datetime = dc_field( + metadata=dc_config( + field_name="captured_at", + encoder=encode_datetime, + decoder=datetime_from_unix_ns, + mm_field=fields.DateTime(format="iso"), + ) + ) + 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"), + ) + ) + egress_id: str = dc_field(metadata=dc_config(field_name="egress_id")) + session_id: str = dc_field(metadata=dc_config(field_name="session_id")) + track_type: str = dc_field(metadata=dc_config(field_name="track_type")) + url: str = dc_field(metadata=dc_config(field_name="url")) + users: "Dict[str, UserResponse]" = dc_field(metadata=dc_config(field_name="users")) + type: str = dc_field( + default="call.frame_recording_ready", metadata=dc_config(field_name="type") + ) + + +@dataclass +class CallFrameRecordingStartedEvent(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"), + ) + ) + egress_id: str = dc_field(metadata=dc_config(field_name="egress_id")) + call: "CallResponse" = dc_field(metadata=dc_config(field_name="call")) + type: str = dc_field( + default="call.frame_recording_started", metadata=dc_config(field_name="type") + ) + + +@dataclass +class CallFrameRecordingStoppedEvent(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"), + ) + ) + egress_id: str = dc_field(metadata=dc_config(field_name="egress_id")) + call: "CallResponse" = dc_field(metadata=dc_config(field_name="call")) + type: str = dc_field( + default="call.frame_recording_stopped", metadata=dc_config(field_name="type") + ) + + @dataclass class CallHLSBroadcastingFailedEvent(DataClassJsonMixin): call_cid: str = dc_field(metadata=dc_config(field_name="call_cid")) @@ -1076,6 +1162,7 @@ class CallHLSBroadcastingStartedEvent(DataClassJsonMixin): ) ) hls_playlist_url: str = dc_field(metadata=dc_config(field_name="hls_playlist_url")) + call: "CallResponse" = dc_field(metadata=dc_config(field_name="call")) type: str = dc_field( default="call.hls_broadcasting_started", metadata=dc_config(field_name="type") ) @@ -1312,6 +1399,7 @@ class CallRecordingFailedEvent(DataClassJsonMixin): mm_field=fields.DateTime(format="iso"), ) ) + egress_id: str = dc_field(metadata=dc_config(field_name="egress_id")) type: str = dc_field( default="call.recording_failed", metadata=dc_config(field_name="type") ) @@ -1328,6 +1416,7 @@ class CallRecordingReadyEvent(DataClassJsonMixin): mm_field=fields.DateTime(format="iso"), ) ) + egress_id: str = dc_field(metadata=dc_config(field_name="egress_id")) call_recording: "CallRecording" = dc_field( metadata=dc_config(field_name="call_recording") ) @@ -1347,6 +1436,7 @@ class CallRecordingStartedEvent(DataClassJsonMixin): mm_field=fields.DateTime(format="iso"), ) ) + egress_id: str = dc_field(metadata=dc_config(field_name="egress_id")) type: str = dc_field( default="call.recording_started", metadata=dc_config(field_name="type") ) @@ -1363,6 +1453,7 @@ class CallRecordingStoppedEvent(DataClassJsonMixin): mm_field=fields.DateTime(format="iso"), ) ) + egress_id: str = dc_field(metadata=dc_config(field_name="egress_id")) type: str = dc_field( default="call.recording_stopped", metadata=dc_config(field_name="type") ) @@ -1751,6 +1842,9 @@ class CallSettings(DataClassJsonMixin): broadcasting: "Optional[BroadcastSettings]" = dc_field( default=None, metadata=dc_config(field_name="broadcasting") ) + frame_recording: "Optional[FrameRecordSettings]" = dc_field( + default=None, metadata=dc_config(field_name="frame_recording") + ) geofencing: "Optional[GeofenceSettings]" = dc_field( default=None, metadata=dc_config(field_name="geofencing") ) @@ -1791,6 +1885,9 @@ class CallSettingsRequest(DataClassJsonMixin): broadcasting: "Optional[BroadcastSettingsRequest]" = dc_field( default=None, metadata=dc_config(field_name="broadcasting") ) + frame_recording: "Optional[FrameRecordingSettingsRequest]" = dc_field( + default=None, metadata=dc_config(field_name="frame_recording") + ) geofencing: "Optional[GeofenceSettingsRequest]" = dc_field( default=None, metadata=dc_config(field_name="geofencing") ) @@ -1829,6 +1926,9 @@ class CallSettingsResponse(DataClassJsonMixin): broadcasting: "BroadcastSettingsResponse" = dc_field( metadata=dc_config(field_name="broadcasting") ) + frame_recording: "FrameRecordingSettingsResponse" = dc_field( + metadata=dc_config(field_name="frame_recording") + ) geofencing: "GeofenceSettingsResponse" = dc_field( metadata=dc_config(field_name="geofencing") ) @@ -1932,6 +2032,7 @@ class CallTranscriptionFailedEvent(DataClassJsonMixin): mm_field=fields.DateTime(format="iso"), ) ) + egress_id: str = dc_field(metadata=dc_config(field_name="egress_id")) type: str = dc_field( default="call.transcription_failed", metadata=dc_config(field_name="type") ) @@ -1948,6 +2049,7 @@ class CallTranscriptionReadyEvent(DataClassJsonMixin): mm_field=fields.DateTime(format="iso"), ) ) + egress_id: str = dc_field(metadata=dc_config(field_name="egress_id")) call_transcription: "CallTranscription" = dc_field( metadata=dc_config(field_name="call_transcription") ) @@ -1967,6 +2069,7 @@ class CallTranscriptionStartedEvent(DataClassJsonMixin): mm_field=fields.DateTime(format="iso"), ) ) + egress_id: str = dc_field(metadata=dc_config(field_name="egress_id")) type: str = dc_field( default="call.transcription_started", metadata=dc_config(field_name="type") ) @@ -1983,6 +2086,7 @@ class CallTranscriptionStoppedEvent(DataClassJsonMixin): mm_field=fields.DateTime(format="iso"), ) ) + egress_id: str = dc_field(metadata=dc_config(field_name="egress_id")) type: str = dc_field( default="call.transcription_stopped", metadata=dc_config(field_name="type") ) @@ -2120,6 +2224,7 @@ class CampaignCompletedEvent(DataClassJsonMixin): mm_field=fields.DateTime(format="iso"), ) ) + custom: Dict[str, object] = dc_field(metadata=dc_config(field_name="custom")) type: str = dc_field( default="campaign.completed", metadata=dc_config(field_name="type") ) @@ -2162,6 +2267,7 @@ class CampaignResponse(DataClassJsonMixin): id: str = dc_field(metadata=dc_config(field_name="id")) name: str = dc_field(metadata=dc_config(field_name="name")) sender_id: str = dc_field(metadata=dc_config(field_name="sender_id")) + sender_mode: str = dc_field(metadata=dc_config(field_name="sender_mode")) skip_push: bool = dc_field(metadata=dc_config(field_name="skip_push")) skip_webhook: bool = dc_field(metadata=dc_config(field_name="skip_webhook")) status: str = dc_field(metadata=dc_config(field_name="status")) @@ -2217,6 +2323,7 @@ class CampaignStartedEvent(DataClassJsonMixin): mm_field=fields.DateTime(format="iso"), ) ) + custom: Dict[str, object] = dc_field(metadata=dc_config(field_name="custom")) type: str = dc_field( default="campaign.started", metadata=dc_config(field_name="type") ) @@ -2956,6 +3063,22 @@ class ChannelOwnCapability: UPLOAD_FILE: Final[ChannelOwnCapabilityType] = "upload-file" +@dataclass +class ChannelPushPreferences(DataClassJsonMixin): + chat_level: Optional[str] = dc_field( + default=None, metadata=dc_config(field_name="chat_level") + ) + disabled_until: Optional[datetime] = dc_field( + default=None, + metadata=dc_config( + field_name="disabled_until", + encoder=encode_datetime, + decoder=datetime_from_unix_ns, + mm_field=fields.DateTime(format="iso"), + ), + ) + + @dataclass class ChannelResponse(DataClassJsonMixin): cid: str = dc_field(metadata=dc_config(field_name="cid")) @@ -3107,6 +3230,9 @@ class ChannelStateResponse(DataClassJsonMixin): membership: "Optional[ChannelMember]" = dc_field( default=None, metadata=dc_config(field_name="membership") ) + push_preferences: "Optional[ChannelPushPreferences]" = dc_field( + default=None, metadata=dc_config(field_name="push_preferences") + ) @dataclass @@ -3151,6 +3277,9 @@ class ChannelStateResponseFields(DataClassJsonMixin): membership: "Optional[ChannelMember]" = dc_field( default=None, metadata=dc_config(field_name="membership") ) + push_preferences: "Optional[ChannelPushPreferences]" = dc_field( + default=None, metadata=dc_config(field_name="push_preferences") + ) @dataclass @@ -3404,6 +3533,9 @@ class CheckRequest(DataClassJsonMixin): ) entity_id: str = dc_field(metadata=dc_config(field_name="entity_id")) entity_type: str = dc_field(metadata=dc_config(field_name="entity_type")) + config_team: Optional[str] = dc_field( + default=None, metadata=dc_config(field_name="config_team") + ) test_mode: Optional[bool] = dc_field( default=None, metadata=dc_config(field_name="test_mode") ) @@ -3521,10 +3653,12 @@ class CollectUserFeedbackRequest(DataClassJsonMixin): rating: int = dc_field(metadata=dc_config(field_name="rating")) sdk: str = dc_field(metadata=dc_config(field_name="sdk")) sdk_version: str = dc_field(metadata=dc_config(field_name="sdk_version")) - user_session_id: str = dc_field(metadata=dc_config(field_name="user_session_id")) reason: Optional[str] = dc_field( default=None, metadata=dc_config(field_name="reason") ) + user_session_id: Optional[str] = dc_field( + default=None, metadata=dc_config(field_name="user_session_id") + ) custom: Optional[Dict[str, object]] = dc_field( default=None, metadata=dc_config(field_name="custom") ) @@ -3662,32 +3796,22 @@ class Count(DataClassJsonMixin): value: int = dc_field(metadata=dc_config(field_name="value")) -@dataclass -class CountrywiseAggregateStats(DataClassJsonMixin): - participant_count: "Optional[Count]" = dc_field( - default=None, metadata=dc_config(field_name="participant_count") - ) - publisher_jitter: "Optional[TimeStats]" = dc_field( - default=None, metadata=dc_config(field_name="publisher_jitter") - ) - publisher_latency: "Optional[TimeStats]" = dc_field( - default=None, metadata=dc_config(field_name="publisher_latency") - ) - subscriber_jitter: "Optional[TimeStats]" = dc_field( - default=None, metadata=dc_config(field_name="subscriber_jitter") - ) - subscriber_latency: "Optional[TimeStats]" = dc_field( - default=None, metadata=dc_config(field_name="subscriber_latency") - ) - - @dataclass class CreateBlockListRequest(DataClassJsonMixin): name: str = dc_field(metadata=dc_config(field_name="name")) words: List[str] = dc_field(metadata=dc_config(field_name="words")) + team: Optional[str] = dc_field(default=None, metadata=dc_config(field_name="team")) type: Optional[str] = dc_field(default=None, metadata=dc_config(field_name="type")) +@dataclass +class CreateBlockListResponse(DataClassJsonMixin): + duration: str = dc_field(metadata=dc_config(field_name="duration")) + blocklist: "Optional[BlockListResponse]" = dc_field( + default=None, metadata=dc_config(field_name="blocklist") + ) + + @dataclass class CreateCallTypeRequest(DataClassJsonMixin): name: str = dc_field(metadata=dc_config(field_name="name")) @@ -4311,6 +4435,13 @@ class DeleteReactionRequest(DataClassJsonMixin): ) +@dataclass +class DeleteReactionResponse(DataClassJsonMixin): + duration: str = dc_field(metadata=dc_config(field_name="duration")) + message: "MessageResponse" = dc_field(metadata=dc_config(field_name="message")) + reaction: "ReactionResponse" = dc_field(metadata=dc_config(field_name="reaction")) + + @dataclass class DeleteRecordingResponse(DataClassJsonMixin): duration: str = dc_field(metadata=dc_config(field_name="duration")) @@ -4453,6 +4584,7 @@ class EdgeResponse(DataClassJsonMixin): @dataclass class EgressHLSResponse(DataClassJsonMixin): playlist_url: str = dc_field(metadata=dc_config(field_name="playlist_url")) + status: str = dc_field(metadata=dc_config(field_name="status")) @dataclass @@ -4478,6 +4610,9 @@ class EgressRTMPResponse(DataClassJsonMixin): class EgressResponse(DataClassJsonMixin): broadcasting: bool = dc_field(metadata=dc_config(field_name="broadcasting")) rtmps: "List[EgressRTMPResponse]" = dc_field(metadata=dc_config(field_name="rtmps")) + frame_recording: "Optional[FrameRecordingResponse]" = dc_field( + default=None, metadata=dc_config(field_name="frame_recording") + ) hls: "Optional[EgressHLSResponse]" = dc_field( default=None, metadata=dc_config(field_name="hls") ) @@ -4659,9 +4794,6 @@ class EntityCreator(DataClassJsonMixin): privacy_settings: "Optional[PrivacySettings]" = dc_field( default=None, metadata=dc_config(field_name="privacy_settings") ) - push_notifications: "Optional[PushNotificationSettings]" = dc_field( - default=None, metadata=dc_config(field_name="push_notifications") - ) @dataclass @@ -4696,7 +4828,6 @@ class EntityCreatorResponse(DataClassJsonMixin): blocked_user_ids: List[str] = dc_field( metadata=dc_config(field_name="blocked_user_ids") ) - devices: "List[DeviceResponse]" = dc_field(metadata=dc_config(field_name="devices")) teams: List[str] = dc_field(metadata=dc_config(field_name="teams")) custom: Dict[str, object] = dc_field(metadata=dc_config(field_name="custom")) ban_expires: Optional[datetime] = dc_field( @@ -4748,6 +4879,9 @@ class EntityCreatorResponse(DataClassJsonMixin): mm_field=fields.DateTime(format="iso"), ), ) + devices: "Optional[List[DeviceResponse]]" = dc_field( + default=None, metadata=dc_config(field_name="devices") + ) privacy_settings: "Optional[PrivacySettingsResponse]" = dc_field( default=None, metadata=dc_config(field_name="privacy_settings") ) @@ -5202,6 +5336,7 @@ class FlagUpdatedEvent(DataClassJsonMixin): mm_field=fields.DateTime(format="iso"), ) ) + custom: Dict[str, object] = dc_field(metadata=dc_config(field_name="custom")) type: str = dc_field(default="flag.updated", metadata=dc_config(field_name="type")) received_at: Optional[datetime] = dc_field( default=None, @@ -5223,6 +5358,44 @@ class FlagUpdatedEvent(DataClassJsonMixin): ) +@dataclass +class FrameRecordSettings(DataClassJsonMixin): + capture_interval_in_seconds: int = dc_field( + metadata=dc_config(field_name="capture_interval_in_seconds") + ) + mode: str = dc_field(metadata=dc_config(field_name="mode")) + quality: Optional[str] = dc_field( + default=None, metadata=dc_config(field_name="quality") + ) + + +@dataclass +class FrameRecordingResponse(DataClassJsonMixin): + status: str = dc_field(metadata=dc_config(field_name="status")) + + +@dataclass +class FrameRecordingSettingsRequest(DataClassJsonMixin): + capture_interval_in_seconds: int = dc_field( + metadata=dc_config(field_name="capture_interval_in_seconds") + ) + mode: str = dc_field(metadata=dc_config(field_name="mode")) + quality: Optional[str] = dc_field( + default=None, metadata=dc_config(field_name="quality") + ) + + +@dataclass +class FrameRecordingSettingsResponse(DataClassJsonMixin): + capture_interval_in_seconds: int = dc_field( + metadata=dc_config(field_name="capture_interval_in_seconds") + ) + mode: str = dc_field(metadata=dc_config(field_name="mode")) + quality: Optional[str] = dc_field( + default=None, metadata=dc_config(field_name="quality") + ) + + @dataclass class FullUserResponse(DataClassJsonMixin): banned: bool = dc_field(metadata=dc_config(field_name="banned")) @@ -5310,9 +5483,6 @@ class FullUserResponse(DataClassJsonMixin): privacy_settings: "Optional[PrivacySettingsResponse]" = dc_field( default=None, metadata=dc_config(field_name="privacy_settings") ) - push_notifications: "Optional[PushNotificationSettingsResponse]" = dc_field( - default=None, metadata=dc_config(field_name="push_notifications") - ) @dataclass @@ -5657,6 +5827,24 @@ class GetMessageResponse(DataClassJsonMixin): ) +@dataclass +class GetModerationAnalyticsRequest(DataClassJsonMixin): + end_date: Optional[str] = dc_field( + default=None, metadata=dc_config(field_name="end_date") + ) + start_date: Optional[str] = dc_field( + default=None, metadata=dc_config(field_name="start_date") + ) + + +@dataclass +class GetModerationAnalyticsResponse(DataClassJsonMixin): + duration: str = dc_field(metadata=dc_config(field_name="duration")) + analytics: "Optional[ModerationAnalytics]" = dc_field( + default=None, metadata=dc_config(field_name="analytics") + ) + + @dataclass class GetOGResponse(DataClassJsonMixin): duration: str = dc_field(metadata=dc_config(field_name="duration")) @@ -6868,6 +7056,15 @@ class MessageReadEvent(DataClassJsonMixin): ) ) type: str = dc_field(default="message.read", metadata=dc_config(field_name="type")) + channel_last_message_at: Optional[datetime] = dc_field( + default=None, + metadata=dc_config( + field_name="channel_last_message_at", + encoder=encode_datetime, + decoder=datetime_from_unix_ns, + mm_field=fields.DateTime(format="iso"), + ), + ) last_read_message_id: Optional[str] = dc_field( default=None, metadata=dc_config(field_name="last_read_message_id") ) @@ -6875,7 +7072,7 @@ class MessageReadEvent(DataClassJsonMixin): thread: "Optional[ThreadResponse]" = dc_field( default=None, metadata=dc_config(field_name="thread") ) - user: "Optional[UserResponse]" = dc_field( + user: "Optional[UserResponseCommonFields]" = dc_field( default=None, metadata=dc_config(field_name="user") ) @@ -7298,6 +7495,52 @@ class ModerationActionConfig(DataClassJsonMixin): custom: Dict[str, object] = dc_field(metadata=dc_config(field_name="custom")) +@dataclass +class ModerationAnalytics(DataClassJsonMixin): + total_items_moderated: int = dc_field( + metadata=dc_config(field_name="total_items_moderated") + ) + ai_image_harms: "List[Dict[str, object]]" = dc_field( + metadata=dc_config(field_name="ai_image_harms") + ) + ai_text_harms: "List[Dict[str, object]]" = dc_field( + metadata=dc_config(field_name="ai_text_harms") + ) + ai_video_harms: "List[Dict[str, object]]" = dc_field( + metadata=dc_config(field_name="ai_video_harms") + ) + blocklist_by_list: "List[Dict[str, object]]" = dc_field( + metadata=dc_config(field_name="blocklist_by_list") + ) + blocklist_matches: "List[Dict[str, object]]" = dc_field( + metadata=dc_config(field_name="blocklist_matches") + ) + model_accuracy: "List[Dict[str, object]]" = dc_field( + metadata=dc_config(field_name="model_accuracy") + ) + moderator_actions: "List[Dict[str, object]]" = dc_field( + metadata=dc_config(field_name="moderator_actions") + ) + moderator_productivity: "List[Dict[str, object]]" = dc_field( + metadata=dc_config(field_name="moderator_productivity") + ) + semantic_filter_top_matches: "List[Dict[str, object]]" = dc_field( + metadata=dc_config(field_name="semantic_filter_top_matches") + ) + sla_metrics: "List[Dict[str, object]]" = dc_field( + metadata=dc_config(field_name="sla_metrics") + ) + usage_metrics: "List[Dict[str, object]]" = dc_field( + metadata=dc_config(field_name="usage_metrics") + ) + action_distribution_over_time: "Dict[str, Dict[str, object]]" = dc_field( + metadata=dc_config(field_name="action_distribution_over_time") + ) + detection_by_engine_over_time: "Dict[str, Dict[str, object]]" = dc_field( + metadata=dc_config(field_name="detection_by_engine_over_time") + ) + + @dataclass class ModerationCustomActionEvent(DataClassJsonMixin): created_at: datetime = dc_field( @@ -7332,8 +7575,9 @@ class ModerationEvent(DataClassJsonMixin): mm_field=fields.DateTime(format="iso"), ) ) + custom: Dict[str, object] = dc_field(metadata=dc_config(field_name="custom")) type: str = dc_field( - default="review_queue_item.new", metadata=dc_config(field_name="type") + default="review_queue_item.updated", metadata=dc_config(field_name="type") ) received_at: Optional[datetime] = dc_field( default=None, @@ -7672,30 +7916,9 @@ class NotificationSettings(DataClassJsonMixin): ) -@dataclass -class NullBool(DataClassJsonMixin): - has_value: Optional[bool] = dc_field( - default=None, metadata=dc_config(field_name="HasValue") - ) - value: Optional[bool] = dc_field( - default=None, metadata=dc_config(field_name="Value") - ) - - @dataclass class NullTime(DataClassJsonMixin): - has_value: Optional[bool] = dc_field( - default=None, metadata=dc_config(field_name="HasValue") - ) - value: Optional[datetime] = dc_field( - default=None, - metadata=dc_config( - field_name="Value", - encoder=encode_datetime, - decoder=datetime_from_unix_ns, - mm_field=fields.DateTime(format="iso"), - ), - ) + pass @dataclass @@ -7725,10 +7948,12 @@ class OwnCapability: SEND_VIDEO: Final[OwnCapabilityType] = "send-video" START_BROADCAST_CALL: Final[OwnCapabilityType] = "start-broadcast-call" START_CLOSED_CAPTIONS_CALL: Final[OwnCapabilityType] = "start-closed-captions-call" + START_FRAME_RECORD_CALL: Final[OwnCapabilityType] = "start-frame-record-call" START_RECORD_CALL: Final[OwnCapabilityType] = "start-record-call" START_TRANSCRIPTION_CALL: Final[OwnCapabilityType] = "start-transcription-call" STOP_BROADCAST_CALL: Final[OwnCapabilityType] = "stop-broadcast-call" STOP_CLOSED_CAPTIONS_CALL: Final[OwnCapabilityType] = "stop-closed-captions-call" + STOP_FRAME_RECORD_CALL: Final[OwnCapabilityType] = "stop-frame-record-call" STOP_RECORD_CALL: Final[OwnCapabilityType] = "stop-record-call" STOP_TRANSCRIPTION_CALL: Final[OwnCapabilityType] = "stop-transcription-call" UPDATE_CALL: Final[OwnCapabilityType] = "update-call" @@ -7823,8 +8048,8 @@ class OwnUser(DataClassJsonMixin): privacy_settings: "Optional[PrivacySettings]" = dc_field( default=None, metadata=dc_config(field_name="privacy_settings") ) - push_notifications: "Optional[PushNotificationSettings]" = dc_field( - default=None, metadata=dc_config(field_name="push_notifications") + push_preferences: "Optional[PushPreferences]" = dc_field( + default=None, metadata=dc_config(field_name="push_preferences") ) @@ -7914,8 +8139,8 @@ class OwnUserResponse(DataClassJsonMixin): privacy_settings: "Optional[PrivacySettingsResponse]" = dc_field( default=None, metadata=dc_config(field_name="privacy_settings") ) - push_notifications: "Optional[PushNotificationSettingsResponse]" = dc_field( - default=None, metadata=dc_config(field_name="push_notifications") + push_preferences: "Optional[PushPreferences]" = dc_field( + default=None, metadata=dc_config(field_name="push_preferences") ) @@ -8363,7 +8588,7 @@ class PushNotificationFields(DataClassJsonMixin): @dataclass -class PushNotificationSettings(DataClassJsonMixin): +class PushNotificationSettingsResponse(DataClassJsonMixin): disabled: Optional[bool] = dc_field( default=None, metadata=dc_config(field_name="disabled") ) @@ -8379,19 +8604,37 @@ class PushNotificationSettings(DataClassJsonMixin): @dataclass -class PushNotificationSettingsInput(DataClassJsonMixin): - disabled: "Optional[NullBool]" = dc_field( - default=None, metadata=dc_config(field_name="disabled") +class PushPreferenceInput(DataClassJsonMixin): + channel_cid: Optional[str] = dc_field( + default=None, metadata=dc_config(field_name="channel_cid") + ) + chat_level: Optional[str] = dc_field( + default=None, metadata=dc_config(field_name="chat_level") + ) + disabled_until: Optional[datetime] = dc_field( + default=None, + metadata=dc_config( + field_name="disabled_until", + encoder=encode_datetime, + decoder=datetime_from_unix_ns, + mm_field=fields.DateTime(format="iso"), + ), ) - disabled_until: "Optional[NullTime]" = dc_field( - default=None, metadata=dc_config(field_name="disabled_until") + remove_disable: Optional[bool] = dc_field( + default=None, metadata=dc_config(field_name="remove_disable") + ) + user_id: Optional[str] = dc_field( + default=None, metadata=dc_config(field_name="user_id") ) @dataclass -class PushNotificationSettingsResponse(DataClassJsonMixin): - disabled: Optional[bool] = dc_field( - default=None, metadata=dc_config(field_name="disabled") +class PushPreferences(DataClassJsonMixin): + call_level: Optional[str] = dc_field( + default=None, metadata=dc_config(field_name="call_level") + ) + chat_level: Optional[str] = dc_field( + default=None, metadata=dc_config(field_name="chat_level") ) disabled_until: Optional[datetime] = dc_field( default=None, @@ -9103,7 +9346,7 @@ class QueryReviewQueueResponse(DataClassJsonMixin): action_config: "Dict[str, List[ModerationActionConfig]]" = dc_field( metadata=dc_config(field_name="action_config") ) - stats: "Dict[str, int]" = dc_field(metadata=dc_config(field_name="stats")) + stats: Dict[str, object] = dc_field(metadata=dc_config(field_name="stats")) 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")) @@ -9464,17 +9707,6 @@ class ReactionNewEvent(DataClassJsonMixin): ) -@dataclass -class ReactionRemovalResponse(DataClassJsonMixin): - duration: str = dc_field(metadata=dc_config(field_name="duration")) - message: "Optional[Message]" = dc_field( - default=None, metadata=dc_config(field_name="message") - ) - reaction: "Optional[Reaction]" = dc_field( - default=None, metadata=dc_config(field_name="reaction") - ) - - @dataclass class ReactionRequest(DataClassJsonMixin): type: str = dc_field(metadata=dc_config(field_name="type")) @@ -9668,7 +9900,6 @@ class RecordSettingsResponse(DataClassJsonMixin): class ReportByHistogramBucket(DataClassJsonMixin): category: str = dc_field(metadata=dc_config(field_name="category")) count: int = dc_field(metadata=dc_config(field_name="count")) - mean: float = dc_field(metadata=dc_config(field_name="mean")) sum: float = dc_field(metadata=dc_config(field_name="sum")) lower_bound: "Optional[Bound]" = dc_field( default=None, metadata=dc_config(field_name="lower_bound") @@ -9706,6 +9937,7 @@ class RestoreUsersRequest(DataClassJsonMixin): @dataclass class ReviewQueueItem(DataClassJsonMixin): + ai_text_severity: str = dc_field(metadata=dc_config(field_name="ai_text_severity")) bounce_count: int = dc_field(metadata=dc_config(field_name="bounce_count")) content_changed: bool = dc_field(metadata=dc_config(field_name="content_changed")) created_at: datetime = dc_field( @@ -9744,7 +9976,6 @@ class ReviewQueueItem(DataClassJsonMixin): flags: "List[Flag2]" = 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")) assigned_to: "Optional[User]" = dc_field( default=None, metadata=dc_config(field_name="assigned_to") @@ -9768,6 +9999,7 @@ class ReviewQueueItem(DataClassJsonMixin): @dataclass class ReviewQueueItemResponse(DataClassJsonMixin): + ai_text_severity: str = dc_field(metadata=dc_config(field_name="ai_text_severity")) created_at: datetime = dc_field( metadata=dc_config( field_name="created_at", @@ -9820,6 +10052,9 @@ class ReviewQueueItemResponse(DataClassJsonMixin): mm_field=fields.DateTime(format="iso"), ), ) + teams: Optional[List[str]] = dc_field( + default=None, metadata=dc_config(field_name="teams") + ) assigned_to: "Optional[UserResponse]" = dc_field( default=None, metadata=dc_config(field_name="assigned_to") ) @@ -10430,10 +10665,22 @@ class StartClosedCaptionsResponse(DataClassJsonMixin): @dataclass -class StartHLSBroadcastingRequest(DataClassJsonMixin): - pass - - +class StartFrameRecordingRequest(DataClassJsonMixin): + recording_external_storage: Optional[str] = dc_field( + default=None, metadata=dc_config(field_name="recording_external_storage") + ) + + +@dataclass +class StartFrameRecordingResponse(DataClassJsonMixin): + duration: str = dc_field(metadata=dc_config(field_name="duration")) + + +@dataclass +class StartHLSBroadcastingRequest(DataClassJsonMixin): + pass + + @dataclass class StartHLSBroadcastingResponse(DataClassJsonMixin): duration: str = dc_field(metadata=dc_config(field_name="duration")) @@ -10509,6 +10756,16 @@ class StopClosedCaptionsResponse(DataClassJsonMixin): duration: str = dc_field(metadata=dc_config(field_name="duration")) +@dataclass +class StopFrameRecordingRequest(DataClassJsonMixin): + pass + + +@dataclass +class StopFrameRecordingResponse(DataClassJsonMixin): + duration: str = dc_field(metadata=dc_config(field_name="duration")) + + @dataclass class StopHLSBroadcastingRequest(DataClassJsonMixin): pass @@ -11318,11 +11575,20 @@ class UpdateAppRequest(DataClassJsonMixin): @dataclass class UpdateBlockListRequest(DataClassJsonMixin): + team: Optional[str] = dc_field(default=None, metadata=dc_config(field_name="team")) words: Optional[List[str]] = dc_field( default=None, metadata=dc_config(field_name="words") ) +@dataclass +class UpdateBlockListResponse(DataClassJsonMixin): + duration: str = dc_field(metadata=dc_config(field_name="duration")) + blocklist: "Optional[BlockListResponse]" = dc_field( + default=None, metadata=dc_config(field_name="blocklist") + ) + + @dataclass class UpdateCallMembersRequest(DataClassJsonMixin): remove_members: Optional[List[str]] = dc_field( @@ -12027,6 +12293,24 @@ class UpsertModerationTemplateResponse(DataClassJsonMixin): ) +@dataclass +class UpsertPushPreferencesRequest(DataClassJsonMixin): + preferences: "List[PushPreferenceInput]" = dc_field( + metadata=dc_config(field_name="preferences") + ) + + +@dataclass +class UpsertPushPreferencesResponse(DataClassJsonMixin): + duration: str = dc_field(metadata=dc_config(field_name="duration")) + user_channel_preferences: "Dict[str, Dict[str, ChannelPushPreferences]]" = dc_field( + metadata=dc_config(field_name="user_channel_preferences") + ) + user_preferences: "Dict[str, PushPreferences]" = dc_field( + metadata=dc_config(field_name="user_preferences") + ) + + @dataclass class UpsertPushProviderRequest(DataClassJsonMixin): push_provider: "Optional[PushProvider]" = dc_field( @@ -12133,9 +12417,6 @@ class User(DataClassJsonMixin): privacy_settings: "Optional[PrivacySettings]" = dc_field( default=None, metadata=dc_config(field_name="privacy_settings") ) - push_notifications: "Optional[PushNotificationSettings]" = dc_field( - default=None, metadata=dc_config(field_name="push_notifications") - ) @dataclass @@ -12238,82 +12519,6 @@ class UserDeletedEvent(DataClassJsonMixin): ) -@dataclass -class UserEventPayload(DataClassJsonMixin): - banned: bool = dc_field(metadata=dc_config(field_name="banned")) - 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"), - ) - ) - id: str = dc_field(metadata=dc_config(field_name="id")) - language: str = dc_field(metadata=dc_config(field_name="language")) - online: bool = dc_field(metadata=dc_config(field_name="online")) - role: str = dc_field(metadata=dc_config(field_name="role")) - 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"), - ) - ) - blocked_user_ids: List[str] = dc_field( - metadata=dc_config(field_name="blocked_user_ids") - ) - teams: List[str] = dc_field(metadata=dc_config(field_name="teams")) - custom: Dict[str, object] = dc_field(metadata=dc_config(field_name="custom")) - deactivated_at: Optional[datetime] = dc_field( - default=None, - metadata=dc_config( - field_name="deactivated_at", - encoder=encode_datetime, - decoder=datetime_from_unix_ns, - mm_field=fields.DateTime(format="iso"), - ), - ) - deleted_at: Optional[datetime] = dc_field( - default=None, - metadata=dc_config( - field_name="deleted_at", - encoder=encode_datetime, - decoder=datetime_from_unix_ns, - mm_field=fields.DateTime(format="iso"), - ), - ) - image: Optional[str] = dc_field( - default=None, metadata=dc_config(field_name="image") - ) - invisible: Optional[bool] = dc_field( - default=None, metadata=dc_config(field_name="invisible") - ) - last_active: Optional[datetime] = dc_field( - default=None, - metadata=dc_config( - field_name="last_active", - encoder=encode_datetime, - decoder=datetime_from_unix_ns, - mm_field=fields.DateTime(format="iso"), - ), - ) - name: Optional[str] = dc_field(default=None, metadata=dc_config(field_name="name")) - revoke_tokens_issued_before: Optional[datetime] = dc_field( - default=None, - metadata=dc_config( - field_name="revoke_tokens_issued_before", - encoder=encode_datetime, - decoder=datetime_from_unix_ns, - mm_field=fields.DateTime(format="iso"), - ), - ) - privacy_settings: "Optional[PrivacySettingsResponse]" = dc_field( - default=None, metadata=dc_config(field_name="privacy_settings") - ) - - @dataclass class UserFeedbackReport(DataClassJsonMixin): unreported_count: int = dc_field(metadata=dc_config(field_name="unreported_count")) @@ -12516,9 +12721,6 @@ class UserRequest(DataClassJsonMixin): privacy_settings: "Optional[PrivacySettingsResponse]" = dc_field( default=None, metadata=dc_config(field_name="privacy_settings") ) - push_notifications: "Optional[PushNotificationSettingsInput]" = dc_field( - default=None, metadata=dc_config(field_name="push_notifications") - ) @dataclass @@ -12549,7 +12751,6 @@ class UserResponse(DataClassJsonMixin): blocked_user_ids: List[str] = dc_field( metadata=dc_config(field_name="blocked_user_ids") ) - devices: "List[DeviceResponse]" = dc_field(metadata=dc_config(field_name="devices")) teams: List[str] = dc_field(metadata=dc_config(field_name="teams")) custom: Dict[str, object] = dc_field(metadata=dc_config(field_name="custom")) ban_expires: Optional[datetime] = dc_field( @@ -12601,6 +12802,9 @@ class UserResponse(DataClassJsonMixin): mm_field=fields.DateTime(format="iso"), ), ) + devices: "Optional[List[DeviceResponse]]" = dc_field( + default=None, metadata=dc_config(field_name="devices") + ) privacy_settings: "Optional[PrivacySettingsResponse]" = dc_field( default=None, metadata=dc_config(field_name="privacy_settings") ) @@ -12609,6 +12813,152 @@ class UserResponse(DataClassJsonMixin): ) +@dataclass +class UserResponseCommonFields(DataClassJsonMixin): + banned: bool = dc_field(metadata=dc_config(field_name="banned")) + 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"), + ) + ) + id: str = dc_field(metadata=dc_config(field_name="id")) + language: str = dc_field(metadata=dc_config(field_name="language")) + online: bool = dc_field(metadata=dc_config(field_name="online")) + role: str = dc_field(metadata=dc_config(field_name="role")) + 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"), + ) + ) + blocked_user_ids: List[str] = dc_field( + metadata=dc_config(field_name="blocked_user_ids") + ) + teams: List[str] = dc_field(metadata=dc_config(field_name="teams")) + custom: Dict[str, object] = dc_field(metadata=dc_config(field_name="custom")) + deactivated_at: Optional[datetime] = dc_field( + default=None, + metadata=dc_config( + field_name="deactivated_at", + encoder=encode_datetime, + decoder=datetime_from_unix_ns, + mm_field=fields.DateTime(format="iso"), + ), + ) + deleted_at: Optional[datetime] = dc_field( + default=None, + metadata=dc_config( + field_name="deleted_at", + encoder=encode_datetime, + decoder=datetime_from_unix_ns, + mm_field=fields.DateTime(format="iso"), + ), + ) + image: Optional[str] = dc_field( + default=None, metadata=dc_config(field_name="image") + ) + last_active: Optional[datetime] = dc_field( + default=None, + metadata=dc_config( + field_name="last_active", + encoder=encode_datetime, + decoder=datetime_from_unix_ns, + mm_field=fields.DateTime(format="iso"), + ), + ) + name: Optional[str] = dc_field(default=None, metadata=dc_config(field_name="name")) + revoke_tokens_issued_before: Optional[datetime] = dc_field( + default=None, + metadata=dc_config( + field_name="revoke_tokens_issued_before", + encoder=encode_datetime, + decoder=datetime_from_unix_ns, + mm_field=fields.DateTime(format="iso"), + ), + ) + + +@dataclass +class UserResponsePrivacyFields(DataClassJsonMixin): + banned: bool = dc_field(metadata=dc_config(field_name="banned")) + 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"), + ) + ) + id: str = dc_field(metadata=dc_config(field_name="id")) + language: str = dc_field(metadata=dc_config(field_name="language")) + online: bool = dc_field(metadata=dc_config(field_name="online")) + role: str = dc_field(metadata=dc_config(field_name="role")) + 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"), + ) + ) + blocked_user_ids: List[str] = dc_field( + metadata=dc_config(field_name="blocked_user_ids") + ) + teams: List[str] = dc_field(metadata=dc_config(field_name="teams")) + custom: Dict[str, object] = dc_field(metadata=dc_config(field_name="custom")) + deactivated_at: Optional[datetime] = dc_field( + default=None, + metadata=dc_config( + field_name="deactivated_at", + encoder=encode_datetime, + decoder=datetime_from_unix_ns, + mm_field=fields.DateTime(format="iso"), + ), + ) + deleted_at: Optional[datetime] = dc_field( + default=None, + metadata=dc_config( + field_name="deleted_at", + encoder=encode_datetime, + decoder=datetime_from_unix_ns, + mm_field=fields.DateTime(format="iso"), + ), + ) + image: Optional[str] = dc_field( + default=None, metadata=dc_config(field_name="image") + ) + invisible: Optional[bool] = dc_field( + default=None, metadata=dc_config(field_name="invisible") + ) + last_active: Optional[datetime] = dc_field( + default=None, + metadata=dc_config( + field_name="last_active", + encoder=encode_datetime, + decoder=datetime_from_unix_ns, + mm_field=fields.DateTime(format="iso"), + ), + ) + name: Optional[str] = dc_field(default=None, metadata=dc_config(field_name="name")) + revoke_tokens_issued_before: Optional[datetime] = dc_field( + default=None, + metadata=dc_config( + field_name="revoke_tokens_issued_before", + encoder=encode_datetime, + decoder=datetime_from_unix_ns, + mm_field=fields.DateTime(format="iso"), + ), + ) + privacy_settings: "Optional[PrivacySettingsResponse]" = dc_field( + default=None, metadata=dc_config(field_name="privacy_settings") + ) + + @dataclass class UserSessionStats(DataClassJsonMixin): freeze_duration_seconds: int = dc_field( @@ -12847,7 +13197,8 @@ class UserUpdatedEvent(DataClassJsonMixin): mm_field=fields.DateTime(format="iso"), ) ) - user: "UserEventPayload" = dc_field(metadata=dc_config(field_name="user")) + custom: Dict[str, object] = dc_field(metadata=dc_config(field_name="custom")) + user: "UserResponsePrivacyFields" = dc_field(metadata=dc_config(field_name="user")) type: str = dc_field(default="user.updated", metadata=dc_config(field_name="type")) received_at: Optional[datetime] = dc_field( default=None, @@ -12999,6 +13350,15 @@ class WSEvent(DataClassJsonMixin): channel_id: Optional[str] = dc_field( default=None, metadata=dc_config(field_name="channel_id") ) + channel_last_message_at: Optional[datetime] = dc_field( + default=None, + metadata=dc_config( + field_name="channel_last_message_at", + encoder=encode_datetime, + decoder=datetime_from_unix_ns, + mm_field=fields.DateTime(format="iso"), + ), + ) channel_type: Optional[str] = dc_field( default=None, metadata=dc_config(field_name="channel_type") ) diff --git a/getstream/video/call.py b/getstream/video/call.py index 98e72988..17c44b30 100644 --- a/getstream/video/call.py +++ b/getstream/video/call.py @@ -96,23 +96,21 @@ def send_call_event( def collect_user_feedback( self, - session: str, rating: int, sdk: str, sdk_version: str, - user_session_id: str, reason: Optional[str] = None, + user_session_id: Optional[str] = None, custom: Optional[Dict[str, object]] = None, ) -> StreamResponse[CollectUserFeedbackResponse]: response = self.client.collect_user_feedback( type=self.call_type, id=self.id, - session=session, rating=rating, sdk=sdk, sdk_version=sdk_version, - user_session_id=user_session_id, reason=reason, + user_session_id=user_session_id, custom=custom, ) self._sync_from_response(response.data) @@ -255,6 +253,17 @@ def start_closed_captions( self._sync_from_response(response.data) return response + def start_frame_recording( + self, recording_external_storage: Optional[str] = None + ) -> StreamResponse[StartFrameRecordingResponse]: + response = self.client.start_frame_recording( + type=self.call_type, + id=self.id, + recording_external_storage=recording_external_storage, + ) + self._sync_from_response(response.data) + return response + def start_recording( self, recording_external_storage: Optional[str] = None ) -> StreamResponse[StartRecordingResponse]: @@ -303,6 +312,11 @@ def stop_closed_captions( self._sync_from_response(response.data) return response + def stop_frame_recording(self) -> StreamResponse[StopFrameRecordingResponse]: + response = self.client.stop_frame_recording(type=self.call_type, id=self.id) + self._sync_from_response(response.data) + return response + def stop_live( self, continue_closed_caption: Optional[bool] = None, diff --git a/getstream/video/rest_client.py b/getstream/video/rest_client.py index 7b215f40..3582d154 100644 --- a/getstream/video/rest_client.py +++ b/getstream/video/rest_client.py @@ -221,30 +221,28 @@ def collect_user_feedback( self, type: str, id: str, - session: str, rating: int, sdk: str, sdk_version: str, - user_session_id: str, reason: Optional[str] = None, + user_session_id: Optional[str] = None, custom: Optional[Dict[str, object]] = None, ) -> StreamResponse[CollectUserFeedbackResponse]: path_params = { "type": type, "id": id, - "session": session, } json = build_body_dict( rating=rating, sdk=sdk, sdk_version=sdk_version, - user_session_id=user_session_id, reason=reason, + user_session_id=user_session_id, custom=custom, ) return self.post( - "/api/v2/video/call/{type}/{id}/feedback/{session}", + "/api/v2/video/call/{type}/{id}/feedback", CollectUserFeedbackResponse, path_params=path_params, json=json, @@ -382,6 +380,22 @@ def list_recordings( path_params=path_params, ) + def get_call_report( + self, type: str, id: str, session_id: Optional[str] = None + ) -> StreamResponse[GetCallReportResponse]: + query_params = build_query_param(session_id=session_id) + path_params = { + "type": type, + "id": id, + } + + return self.get( + "/api/v2/video/call/{type}/{id}/report", + GetCallReportResponse, + query_params=query_params, + path_params=path_params, + ) + def start_rtmp_broadcasts( self, type: str, id: str, broadcasts: List[RTMPBroadcastRequest] ) -> StreamResponse[StartRTMPBroadcastsResponse]: @@ -471,6 +485,22 @@ def start_closed_captions( json=json, ) + def start_frame_recording( + self, type: str, id: str, recording_external_storage: Optional[str] = None + ) -> StreamResponse[StartFrameRecordingResponse]: + path_params = { + "type": type, + "id": id, + } + json = build_body_dict(recording_external_storage=recording_external_storage) + + return self.post( + "/api/v2/video/call/{type}/{id}/start_frame_recording", + StartFrameRecordingResponse, + path_params=path_params, + json=json, + ) + def start_recording( self, type: str, id: str, recording_external_storage: Optional[str] = None ) -> StreamResponse[StartRecordingResponse]: @@ -557,6 +587,20 @@ def stop_closed_captions( json=json, ) + def stop_frame_recording( + self, type: str, id: str + ) -> StreamResponse[StopFrameRecordingResponse]: + path_params = { + "type": type, + "id": id, + } + + return self.post( + "/api/v2/video/call/{type}/{id}/stop_frame_recording", + StopFrameRecordingResponse, + path_params=path_params, + ) + def stop_live( self, type: str, @@ -817,19 +861,3 @@ def query_aggregate_call_stats( return self.post( "/api/v2/video/stats", QueryAggregateCallStatsResponse, json=json ) - - def get_call_report( - self, type: str, id: str, session_id: Optional[str] = None - ) -> StreamResponse[GetCallReportResponse]: - query_params = build_query_param(session_id=session_id) - path_params = { - "type": type, - "id": id, - } - - return self.get( - "/api/v2/video/call/{type}/{id}/report", - GetCallReportResponse, - query_params=query_params, - path_params=path_params, - ) diff --git a/tests/test_video_examples.py b/tests/test_video_examples.py index de7e07a3..50592bcc 100644 --- a/tests/test_video_examples.py +++ b/tests/test_video_examples.py @@ -1,6 +1,8 @@ +import pytest import uuid from getstream import Stream +from getstream.base import StreamAPIException from getstream.models import ( CallRequest, CallSettingsRequest, @@ -9,6 +11,7 @@ LimitsSettingsRequest, BackstageSettingsRequest, SessionSettingsRequest, + FrameRecordingSettingsRequest, ) from getstream.video.call import Call from datetime import datetime, timezone, timedelta @@ -274,19 +277,6 @@ def test_create_call_with_backstage_and_join_ahead_set(client: Stream, call: Cal assert response.data.call.join_ahead_time_seconds == 0 -def test_create_call_with_default_session_inactivity_timeout(call: Call): - user_id = str(uuid.uuid4()) - - # create a call and expect the default session inactivity timeout to be 30 seconds - response = call.get_or_create( - data=CallRequest( - created_by_id=user_id, - ) - ) - - assert response.data.call.settings.session.inactivity_timeout_seconds == 30 - - def test_create_call_with_custom_session_inactivity_timeout(call: Call): user_id = str(uuid.uuid4()) @@ -317,3 +307,66 @@ def test_create_call_type_with_custom_session_inactivity_timeout(client: Stream) ) assert response.data.settings.session.inactivity_timeout_seconds == 300 + + +def test_start_stop_frame_recording(client: Stream): + user_id = str(uuid.uuid4()) + + # create a call and set its frame recording settings + call = client.video.call("default", uuid.uuid4()) + call.get_or_create(data=CallRequest(created_by_id=user_id)) + + with pytest.raises(StreamAPIException) as e_info: + call.start_recording() + + assert e_info.value.status_code == 400 + assert ( + e_info.value.api_error.message + == 'StartRecording failed with error: "there is no active session"' + ) + + with pytest.raises(StreamAPIException) as e_info: + call.stop_recording() + + assert e_info.value.status_code == 400 + assert ( + e_info.value.api_error.message + == 'StopRecording failed with error: "call egress is not running"' + ) + + +def test_create_call_with_custom_frame_recording_settings(client: Stream): + user_id = str(uuid.uuid4()) + + # create a call and set its frame recording settings + call = client.video.call("default", uuid.uuid4()) + response = call.get_or_create( + data=CallRequest( + created_by_id=user_id, + settings_override=CallSettingsRequest( + frame_recording=FrameRecordingSettingsRequest( + capture_interval_in_seconds=3, mode="auto-on", quality="1080p" + ), + ), + ) + ) + + assert response.data.call.settings.frame_recording.capture_interval_in_seconds == 3 + assert response.data.call.settings.frame_recording.mode == "auto-on" + assert response.data.call.settings.frame_recording.quality == "1080p" + + +def test_create_call_type_with_custom_frame_recording_settings(client: Stream): + # create a call type with frame recording settings + response = client.video.create_call_type( + name="frame_recording_" + str(uuid.uuid4()), + settings=CallSettingsRequest( + frame_recording=FrameRecordingSettingsRequest( + capture_interval_in_seconds=5, mode="auto-on", quality="720p" + ), + ), + ) + + assert response.data.settings.frame_recording.capture_interval_in_seconds == 5 + assert response.data.settings.frame_recording.mode == "auto-on" + assert response.data.settings.frame_recording.quality == "720p"