diff --git a/__tests__/file-uploads.test.ts b/__tests__/file-uploads.test.ts index e5f6425..14256c2 100644 --- a/__tests__/file-uploads.test.ts +++ b/__tests__/file-uploads.test.ts @@ -94,7 +94,6 @@ describe.skip('channel file uploads', () => { const fileBuffer = fs.readFileSync(filePath); const response = await channel.uploadChannelFile({ - // @ts-expect-error API spec says file should be a string file: new File([fileBuffer], 'test-file.pdf'), user: { id: user.id }, }); @@ -122,7 +121,6 @@ describe.skip('channel file uploads', () => { ]; const response = await channel.uploadChannelImage({ - // @ts-expect-error API spec says file should be a string file: new File([fileBuffer], 'test-image.jpg'), user: { id: user.id }, upload_sizes: uploadSizes, diff --git a/__tests__/multipart.test.ts b/__tests__/multipart.test.ts index 9012714..114f73e 100644 --- a/__tests__/multipart.test.ts +++ b/__tests__/multipart.test.ts @@ -125,7 +125,6 @@ describe('multipart form data serialization', () => { await chat.uploadChannelImage({ type: 'messaging', id: 'channel-id', - // @ts-expect-error API spec says file should be a string file: new File(['image-contents'], 'test-image.jpg'), upload_sizes: [{ width: 100, height: 100 }], user: { id: 'user-id' }, @@ -144,7 +143,6 @@ describe('multipart form data serialization', () => { await chat.uploadChannelFile({ type: 'messaging', id: 'channel-id', - // @ts-expect-error API spec says file should be a string file: new File(['file-contents'], 'test-file.pdf'), user: { id: 'user-id' }, }); @@ -153,4 +151,62 @@ describe('multipart form data serialization', () => { expect(formData.get('user')).toBe('{"id":"user-id"}'); expect(formData.get('file')).toBeInstanceOf(File); }); + + it('encodes a channel image upload made from a channel', async () => { + const fetchSpy = mockFetch(); + const channel = new StreamChatClient(createApiClient()).channel( + 'messaging', + 'channel-id', + ); + + await channel.uploadChannelImage({ + file: new File(['image-contents'], 'test-image.jpg'), + upload_sizes: [{ width: 100, height: 100 }], + user: { id: 'user-id' }, + }); + + const [url, init] = fetchSpy.mock.calls[0]; + expect(url).toContain('/api/v2/chat/channels/messaging/channel-id/image'); + const formData = init!.body as FormData; + expect(formData.get('user')).toBe('{"id":"user-id"}'); + expect(formData.get('upload_sizes')).toBe('[{"width":100,"height":100}]'); + const sent = formData.get('file'); + expect(sent).toBeInstanceOf(File); + expect((sent as File).name).toBe('test-image.jpg'); + }); + + it('encodes a channel file upload made from a channel', async () => { + const fetchSpy = mockFetch(); + const channel = new StreamChatClient(createApiClient()).channel( + 'messaging', + 'channel-id', + ); + + await channel.uploadChannelFile({ + file: new File(['file-contents'], 'test-file.pdf'), + user: { id: 'user-id' }, + }); + + const [url, init] = fetchSpy.mock.calls[0]; + expect(url).toContain('/api/v2/chat/channels/messaging/channel-id/file'); + const formData = init!.body as FormData; + expect(formData.get('user')).toBe('{"id":"user-id"}'); + const sent = formData.get('file'); + expect(sent).toBeInstanceOf(File); + expect((sent as File).name).toBe('test-file.pdf'); + }); + + it('refuses a channel upload before the channel has an id', () => { + const fetchSpy = mockFetch(); + const channel = new StreamChatClient(createApiClient()).channel( + 'messaging', + ); + + expect(() => + channel.uploadChannelFile({ + file: new File(['file-contents'], 'test-file.pdf'), + }), + ).toThrow("Channel isn't yet created"); + expect(fetchSpy).not.toHaveBeenCalled(); + }); }); diff --git a/src/StreamChannel.ts b/src/StreamChannel.ts index ef669f0..44f8bd9 100644 --- a/src/StreamChannel.ts +++ b/src/StreamChannel.ts @@ -1,6 +1,12 @@ import { ChannelApi } from './gen/chat/ChannelApi'; -import { ChannelGetOrCreateRequest, QueryMembersPayload } from './gen/models'; +import { + ChannelGetOrCreateRequest, + QueryMembersPayload, + UploadChannelFileRequest, + UploadChannelRequest, +} from './gen/models'; import { OmitTypeId } from './types'; +import { File } from 'buffer'; export class StreamChannel extends ChannelApi { get cid() { @@ -36,4 +42,20 @@ export class StreamChannel extends ChannelApi { }, }); } + + // @ts-expect-error API spec says file should be a string + uploadChannelFile = ( + request: Omit & { file: File }, + ) => { + // @ts-expect-error API spec says file should be a string + return super.uploadChannelFile(request); + }; + + // @ts-expect-error API spec says file should be a string + uploadChannelImage = ( + request: Omit & { file: File }, + ) => { + // @ts-expect-error API spec says file should be a string + return super.uploadChannelImage(request); + }; } diff --git a/src/StreamChatClient.ts b/src/StreamChatClient.ts index dc82a27..532451e 100644 --- a/src/StreamChatClient.ts +++ b/src/StreamChatClient.ts @@ -1,8 +1,36 @@ import { ChatApi } from './gen/chat/ChatApi'; +import { UploadChannelFileRequest, UploadChannelRequest } from './gen/models'; import { StreamChannel } from './StreamChannel'; +import { File } from 'buffer'; export class StreamChatClient extends ChatApi { channel = (type: string, id?: string) => { - return new StreamChannel(this, type, id); + // The upload overrides below narrow `file` to File, so this class is no + // longer structurally a ChatApi, even though it is one at runtime + return new StreamChannel(this as unknown as ChatApi, type, id); + }; + + // @ts-expect-error API spec says file should be a string + uploadChannelFile = ( + request: Omit & { + file: File; + type: string; + id: string; + }, + ) => { + // @ts-expect-error API spec says file should be a string + return super.uploadChannelFile(request); + }; + + // @ts-expect-error API spec says file should be a string + uploadChannelImage = ( + request: Omit & { + file: File; + type: string; + id: string; + }, + ) => { + // @ts-expect-error API spec says file should be a string + return super.uploadChannelImage(request); }; } diff --git a/src/gen/common/CommonApi.ts b/src/gen/common/CommonApi.ts index bd53ffb..0c9b712 100644 --- a/src/gen/common/CommonApi.ts +++ b/src/gen/common/CommonApi.ts @@ -6,6 +6,8 @@ import { BlockUsersResponse, CancelImportV2TaskResponse, CheckExternalStorageResponse, + CheckGCPPubSubRequest, + CheckGCPPubSubResponse, CheckPushRequest, CheckPushResponse, CheckSNSRequest, @@ -375,6 +377,29 @@ export class CommonApi { return response; } + async checkGCPPubSub( + request?: CheckGCPPubSubRequest, + ): Promise> { + const body = { + gcp_pubsub_event_based_ordering_key_enabled: + request?.gcp_pubsub_event_based_ordering_key_enabled, + gcp_pubsub_region: request?.gcp_pubsub_region, + gcp_pubsub_topic: request?.gcp_pubsub_topic, + }; + + const response = await this.apiClient.sendRequest( + 'POST', + '/api/v2/check_gcp_pubsub', + undefined, + undefined, + body, + ); + + decoders['CheckGCPPubSubResponse']?.(response); + + return response; + } + async checkPush( request?: CheckPushRequest, ): Promise> { diff --git a/src/gen/feeds/FeedsApi.ts b/src/gen/feeds/FeedsApi.ts index fba2a62..6331934 100644 --- a/src/gen/feeds/FeedsApi.ts +++ b/src/gen/feeds/FeedsApi.ts @@ -27,6 +27,8 @@ import { CastPollVoteRequest, ChangeFeedVisibilityRequest, ChangeFeedVisibilityResponse, + CommentFeedbackRequest, + CommentFeedbackResponse, CreateCollectionsRequest, CreateCollectionsResponse, CreateFeedGroupRequest, @@ -1433,6 +1435,31 @@ export class FeedsApi { return response; } + async commentFeedback( + request: CommentFeedbackRequest & { id: string }, + ): Promise> { + const pathParams = { + id: request?.id, + }; + const body = { + hide: request?.hide, + user_id: request?.user_id, + user: request?.user, + }; + + const response = await this.apiClient.sendRequest( + 'POST', + '/api/v2/feeds/comments/{id}/feedback', + pathParams, + undefined, + body, + ); + + decoders['CommentFeedbackResponse']?.(response); + + return response; + } + async updateCommentPartial( request: UpdateCommentPartialRequest & { id: string }, ): Promise> { @@ -1746,6 +1773,7 @@ export class FeedsApi { user_id: request?.user_id, view: request?.view, watch: request?.watch, + discard_actors: request?.discard_actors, data: request?.data, enrichment_options: request?.enrichment_options, external_ranking: request?.external_ranking, @@ -2934,6 +2962,7 @@ export class FeedsApi { max_age_hours: request?.max_age_hours, policy: request?.policy, enabled: request?.enabled, + feed_groups: request?.feed_groups, }; const response = diff --git a/src/gen/model-decoders/decoders.ts b/src/gen/model-decoders/decoders.ts index 77a356c..4272d08 100644 --- a/src/gen/model-decoders/decoders.ts +++ b/src/gen/model-decoders/decoders.ts @@ -467,6 +467,19 @@ decoders['AsyncExportErrorEvent'] = (input?: { [key: string]: any }) => { return decode(typeMappings, input); }; +decoders['AsyncExportLabelResultsEvent'] = (input?: { [key: string]: any }) => { + const typeMappings: TypeMapping = { + created_at: { type: 'DatetimeType', isSingle: true }, + + finished_at: { type: 'DatetimeType', isSingle: true }, + + started_at: { type: 'DatetimeType', isSingle: true }, + + received_at: { type: 'DatetimeType', isSingle: true }, + }; + return decode(typeMappings, input); +}; + decoders['AsyncExportModerationLogsEvent'] = (input?: { [key: string]: any; }) => { @@ -508,6 +521,32 @@ decoders['AsyncExportUsersEvent'] = (input?: { [key: string]: any }) => { return decode(typeMappings, input); }; +decoders['AsyncImportErrorEvent'] = (input?: { [key: string]: any }) => { + const typeMappings: TypeMapping = { + created_at: { type: 'DatetimeType', isSingle: true }, + + finished_at: { type: 'DatetimeType', isSingle: true }, + + received_at: { type: 'DatetimeType', isSingle: true }, + + started_at: { type: 'DatetimeType', isSingle: true }, + }; + return decode(typeMappings, input); +}; + +decoders['AsyncImportSuccessEvent'] = (input?: { [key: string]: any }) => { + const typeMappings: TypeMapping = { + created_at: { type: 'DatetimeType', isSingle: true }, + + finished_at: { type: 'DatetimeType', isSingle: true }, + + received_at: { type: 'DatetimeType', isSingle: true }, + + started_at: { type: 'DatetimeType', isSingle: true }, + }; + return decode(typeMappings, input); +}; + decoders['AutomodDetailsResponse'] = (input?: { [key: string]: any }) => { const typeMappings: TypeMapping = { result: { type: 'MessageModerationResult', isSingle: true }, @@ -1072,6 +1111,17 @@ decoders['CallRingEvent'] = (input?: { [key: string]: any }) => { return decode(typeMappings, input); }; +decoders['CallRingSettledEvent'] = (input?: { [key: string]: any }) => { + const typeMappings: TypeMapping = { + created_at: { type: 'DatetimeType', isSingle: true }, + + rang_at: { type: 'DatetimeType', isSingle: true }, + + settled_at: { type: 'DatetimeType', isSingle: true }, + }; + return decode(typeMappings, input); +}; + decoders['CallRtmpBroadcastFailedEvent'] = (input?: { [key: string]: any }) => { const typeMappings: TypeMapping = { created_at: { type: 'DatetimeType', isSingle: true }, @@ -1921,6 +1971,17 @@ decoders['CommentDeletedEvent'] = (input?: { [key: string]: any }) => { return decode(typeMappings, input); }; +decoders['CommentFeedbackEvent'] = (input?: { [key: string]: any }) => { + const typeMappings: TypeMapping = { + created_at: { type: 'DatetimeType', isSingle: true }, + + received_at: { type: 'DatetimeType', isSingle: true }, + + user: { type: 'UserResponseCommonFields', isSingle: true }, + }; + return decode(typeMappings, input); +}; + decoders['CommentReactionAddedEvent'] = (input?: { [key: string]: any }) => { const typeMappings: TypeMapping = { created_at: { type: 'DatetimeType', isSingle: true }, @@ -2644,6 +2705,13 @@ decoders['FeedsReactionResponse'] = (input?: { [key: string]: any }) => { return decode(typeMappings, input); }; +decoders['FeedsRetentionPolicy'] = (input?: { [key: string]: any }) => { + const typeMappings: TypeMapping = { + enabled_at: { type: 'DatetimeType', isSingle: true }, + }; + return decode(typeMappings, input); +}; + decoders['FeedsShareResponse'] = (input?: { [key: string]: any }) => { const typeMappings: TypeMapping = { created_at: { type: 'DatetimeType', isSingle: true }, @@ -3027,7 +3095,7 @@ decoders['GetFeedsRetentionPolicyResponse'] = (input?: { [key: string]: any; }) => { const typeMappings: TypeMapping = { - policies: { type: 'RetentionPolicy', isSingle: false }, + policies: { type: 'FeedsRetentionPolicy', isSingle: false }, }; return decode(typeMappings, input); }; @@ -4420,6 +4488,15 @@ decoders['QueryCallParticipantsResponse'] = (input?: { return decode(typeMappings, input); }; +decoders['QueryCallRingAttemptsResponse'] = (input?: { + [key: string]: any; +}) => { + const typeMappings: TypeMapping = { + ring_attempts: { type: 'RingAttemptResponse', isSingle: false }, + }; + return decode(typeMappings, input); +}; + decoders['QueryCallSessionParticipantStatsResponse'] = (input?: { [key: string]: any; }) => { @@ -5054,6 +5131,45 @@ decoders['RevisionHistoryResponse'] = (input?: { [key: string]: any }) => { return decode(typeMappings, input); }; +decoders['RingAttemptResponse'] = (input?: { [key: string]: any }) => { + const typeMappings: TypeMapping = { + created_at: { type: 'DatetimeType', isSingle: true }, + + expires_at: { type: 'DatetimeType', isSingle: true }, + + targets: { type: 'RingTargetResponse', isSingle: false }, + + deleted_at: { type: 'DatetimeType', isSingle: true }, + + settled_at: { type: 'DatetimeType', isSingle: true }, + }; + return decode(typeMappings, input); +}; + +decoders['RingDeliveryResponse'] = (input?: { [key: string]: any }) => { + const typeMappings: TypeMapping = { + sent_at: { type: 'DatetimeType', isSingle: true }, + + acked_at: { type: 'DatetimeType', isSingle: true }, + + displayed_at: { type: 'DatetimeType', isSingle: true }, + + fetched_at: { type: 'DatetimeType', isSingle: true }, + + provider_accepted_at: { type: 'DatetimeType', isSingle: true }, + }; + return decode(typeMappings, input); +}; + +decoders['RingTargetResponse'] = (input?: { [key: string]: any }) => { + const typeMappings: TypeMapping = { + state_at: { type: 'DatetimeType', isSingle: true }, + + deliveries: { type: 'RingDeliveryResponse', isSingle: false }, + }; + return decode(typeMappings, input); +}; + decoders['Role'] = (input?: { [key: string]: any }) => { const typeMappings: TypeMapping = { created_at: { type: 'DatetimeType', isSingle: true }, @@ -5214,7 +5330,7 @@ decoders['SetFeedsRetentionPolicyResponse'] = (input?: { [key: string]: any; }) => { const typeMappings: TypeMapping = { - policy: { type: 'RetentionPolicy', isSingle: true }, + policy: { type: 'FeedsRetentionPolicy', isSingle: true }, }; return decode(typeMappings, input); }; diff --git a/src/gen/models/index.ts b/src/gen/models/index.ts index 1d22700..42890c4 100644 --- a/src/gen/models/index.ts +++ b/src/gen/models/index.ts @@ -1,12 +1,31 @@ export interface AIAudioConfigRequest { + /** + * Bodyguard credentials profile to classify transcripts with. Applies to the NLP engine only; ignored when LLM configurability is enabled. Empty falls back to the app-pinned profile, then the organization's top-level credentials + */ profile?: string; + /** + * Deprecated pre-split rule list. Still the live config while no engine config exists; once one does it is kept as a fallback for whichever engine has none of its own + */ rules?: Array; + ai_text_config?: AITextConfig; + llm_config?: LLMConfig; } export interface AIAudioConfigResponse { + /** + * Whether the engine selected by the application's LLM configurability flag has a rule that does something. Derived, not stored + */ enabled: boolean; + /** + * Bodyguard credentials profile transcripts are classified with. Applies to the NLP engine only + */ profile: string; + /** + * The active engine's rules, flattened into the pre-split shape for clients that predate the per-engine configs. This is the whole config for a policy that has no per-engine config stored + */ rules: Array; + ai_text_config?: AITextConfig; + llm_config?: LLMConfig; } export interface AIImageConfig { @@ -1449,7 +1468,7 @@ export interface AggregationConfig { */ format?: string; /** - * Maximum number of activities kept in each aggregated group. Omit to use the default of 100. Must be between 1 and 100 when set. + * Maximum number of activities kept in each aggregated group. Omit to use the default: 15 for apps migrated from Feeds v2 or created on or after 2026-10-11, 100 otherwise. Must be between 1 and 100 when set. */ group_size?: number; /** @@ -1578,7 +1597,13 @@ export interface AnalyzeTextField { export interface AppResponseFields { allow_multi_user_devices: boolean; + /** + * A boolean value determining if async url enrichment is enabled. + */ async_url_enrich_enabled: boolean; + /** + * A boolean value determining if auto translation is enabled. + */ auto_translation_enabled: boolean; before_message_send_hook_system_messages: boolean; campaign_enabled: boolean; @@ -1603,6 +1628,9 @@ export interface AppResponseFields { moderation_video_call_moderation_enabled: boolean; moderation_webhook_url: string; multi_tenant_enabled: boolean; + /** + * The name of the app. + */ name: string; organization: string; permission_version: string; @@ -1832,6 +1860,17 @@ export interface AsyncExportErrorEvent { received_at?: Date; } +export interface AsyncExportLabelResultsEvent { + created_at: Date; + finished_at: Date; + started_at: Date; + task_id: string; + url: string; + custom: Record; + type: string; + received_at?: Date; +} + export interface AsyncExportModerationLogsEvent { created_at: Date; finished_at: Date; @@ -1865,6 +1904,31 @@ export interface AsyncExportUsersEvent { received_at?: Date; } +export interface AsyncImportErrorEvent { + created_at: Date; + error: string; + finished_at: Date; + product: string; + state: string; + task_id: string; + custom: Record; + type: string; + received_at?: Date; + started_at?: Date; +} + +export interface AsyncImportSuccessEvent { + created_at: Date; + finished_at: Date; + product: string; + state: string; + task_id: string; + custom: Record; + type: string; + received_at?: Date; + started_at?: Date; +} + export interface AsyncModerationCallbackConfig { mode?: 'CALLBACK_MODE_NONE' | 'CALLBACK_MODE_REST' | 'CALLBACK_MODE_TWIRP'; server_url?: string; @@ -2108,6 +2172,10 @@ export interface BanRequest { * ID of the user to ban */ target_user_id: string; + /** + * Whether to also ban the user from future channels created by the banner + */ + ban_from_future_channels?: boolean; /** * ID of the user performing the ban */ @@ -2117,6 +2185,10 @@ export interface BanRequest { */ channel_cid?: string; delete_messages?: 'soft' | 'pruning' | 'hard'; + /** + * Whether to delete reactions by the banned user on other users' messages + */ + delete_reactions?: boolean; /** * Whether to ban the user's IP address */ @@ -2259,7 +2331,7 @@ export interface BlockListResponse { */ name: string; /** - * Block list type. One of: regex, domain, domain_allowlist, email, email_allowlist, word + * Block list type. One of: regex, domain, domain_allowlist, email, email_allowlist, word, word_allowlist */ type: string; /** @@ -3461,6 +3533,51 @@ export interface CallRingEvent { ring_id?: string; } +export interface CallRingSettledEvent { + call_cid: string; + created_at: Date; + /** + * ID of the user who rang + */ + initiated_by: string; + /** + * Final outcome of the ring: answered_all, answered_some, rejected_all, missed_all, cancelled or mixed + */ + outcome: string; + /** + * When the ring was sent + */ + rang_at: Date; + /** + * Identifies this ring of the call session, as carried on call.ring + */ + ring_id: string; + /** + * Call session ID + */ + session_id: string; + /** + * Why the ring closed: answered, rejected, cancel, timeout, ended or auto_end + */ + settle_reason: string; + /** + * When the outcome left ringing + */ + settled_at: Date; + /** + * ID of the user whose action closed the ring, or 'server' for the missed-call deadline and automatic ends + */ + settled_by: string; + /** + * Final state of every rung user, keyed by user ID + */ + targets: Record; + /** + * The type of event: "call.ring_settled" in this case + */ + type: string; +} + export interface CallRtmpBroadcastFailedEvent { /** * The unique identifier for a call (:) @@ -4847,7 +4964,13 @@ export type ChannelOwnCapability = (typeof ChannelOwnCapability)[keyof typeof ChannelOwnCapability]; export interface ChannelPushPreferencesResponse { + /** + * The scope level of the push notifications. + */ chat_level?: string; + /** + * If provided the notifications will be disabled until the set date. + */ disabled_until?: Date; chat_preferences?: ChatPreferencesResponse; } @@ -4980,6 +5103,9 @@ export interface ChannelStateResponse { channel?: ChannelResponse; draft?: DraftResponse; membership?: ChannelMemberResponse; + /** + * The push preference details. + */ push_preferences?: ChannelPushPreferencesResponse; } @@ -5031,6 +5157,9 @@ export interface ChannelStateResponseFields { channel?: ChannelResponse; draft?: DraftResponse; membership?: ChannelMemberResponse; + /** + * The push preference details. + */ push_preferences?: ChannelPushPreferencesResponse; } @@ -5451,6 +5580,37 @@ export interface CheckExternalStorageResponse { file_url: string; } +export interface CheckGCPPubSubRequest { + /** + * Publish the test message with an ordering key through the regional endpoint, as a hook with ordering enabled would; requires gcp_pubsub_region + */ + gcp_pubsub_event_based_ordering_key_enabled?: boolean; + /** + * GCP region used for the regional Pub/Sub endpoint when ordering is enabled + */ + gcp_pubsub_region?: string; + /** + * Fully qualified GCP Pub/Sub topic name (projects/{project}/topics/{topic}) + */ + gcp_pubsub_topic?: string; +} + +export interface CheckGCPPubSubResponse { + duration: string; + /** + * Validation result. One of: ok, error + */ + status: string; + /** + * Error text + */ + error?: string; + /** + * Error data + */ + data?: Record; +} + export interface CheckPushRequest { /** * Push message template for APN @@ -5961,6 +6121,68 @@ export interface CommentDeletedEvent { user?: UserResponseCommonFields; } +export interface CommentFeedbackEvent { + /** + * Date/time of creation + */ + created_at: Date; + comment_feedback: CommentFeedbackEventPayload; + custom: Record; + /** + * The type of event: "feeds.comment.feedback" in this case + */ + type: string; + received_at?: Date; + user?: UserResponseCommonFields; +} + +export interface CommentFeedbackEventPayload { + /** + * The comment that received feedback + */ + comment_id: string; + /** + * When the feedback was created + */ + created_at: Date; + /** + * Whether the comment is hidden for the user + */ + hide: boolean; + /** + * When the feedback was last updated + */ + updated_at: Date; + /** + * User response object + */ + user: UserResponse; +} + +export interface CommentFeedbackRequest { + /** + * Whether to hide this comment for the user + */ + hide?: boolean; + user_id?: string; + /** + * User request object + */ + user?: UserRequest; +} + +export interface CommentFeedbackResponse { + /** + * The ID of the comment that received feedback + */ + comment_id: string; + duration: string; + /** + * Whether the comment is hidden for the user + */ + hide: boolean; +} + export interface CommentReactionAddedEvent { /** * Date/time of creation @@ -6030,6 +6252,10 @@ export interface CommentResponse { * Number of downvotes for this comment */ downvote_count: number; + /** + * Only true in QueryComments results filtered with hidden: true + */ + hidden: boolean; /** * Unique identifier for the comment */ @@ -6284,6 +6510,11 @@ export interface ContentCountRuleParameters { time_window?: string; } +export interface ContentCountryCodeParameters { + operator?: string; + country_codes?: Array; +} + export interface ContentCustomPropertyCountParameters { operator?: string; property_key?: string; @@ -6333,7 +6564,7 @@ export interface CreateBlockListRequest { is_substring_matching_enabled?: boolean; team?: string; /** - * Block list type. One of: regex, domain, domain_allowlist, email, email_allowlist, word + * Block list type. One of: regex, domain, domain_allowlist, email, email_allowlist, word, word_allowlist */ type?: | 'regex' @@ -6341,7 +6572,8 @@ export interface CreateBlockListRequest { | 'domain_allowlist' | 'email' | 'email_allowlist' - | 'word'; + | 'word' + | 'word_allowlist'; user_id?: string; /** * User request object @@ -7034,6 +7266,9 @@ export interface CreatePollRequest { max_votes_allowed?: number; team?: string; user_id?: string; + /** + * Represents the visibility of votes in a poll. + */ voting_visibility?: 'anonymous' | 'public'; options?: Array; /** @@ -7718,7 +7953,7 @@ export interface DeleteFeedsBatchResponse { } export interface DeleteFeedsRetentionPolicyRequest { - policy: 'old-activities'; + policy: string; } export interface DeleteFeedsRetentionPolicyResponse { @@ -8022,11 +8257,11 @@ export interface DeviceErrorInfo { export interface DeviceResponse { /** - * Date/time of creation + * The date when the device was created. */ created_at: Date; /** - * Device ID + * The device identifier. */ id: string; /** @@ -8401,6 +8636,9 @@ export interface EntityCreatorResponse { name?: string; revoke_tokens_issued_before?: Date; devices?: Array; + /** + * The privacy settings of the user. + */ privacy_settings?: PrivacySettingsResponse; push_notifications?: PushNotificationSettingsResponse; teams_role?: Record; @@ -8437,6 +8675,10 @@ export interface EscalationMetadata { export interface EventHook { created_at?: Date; enabled?: boolean; + gcp_pubsub_auth_type?: string; + gcp_pubsub_event_based_ordering_key_enabled?: boolean; + gcp_pubsub_region?: string; + gcp_pubsub_topic?: string; hook_type?: string; id?: string; product?: string; @@ -9299,6 +9541,11 @@ export interface FeedsNotificationTrigger { custom?: Record; } +export interface FeedsPolicyConfig { + max_age_hours: number; + feed_groups?: Array; +} + export interface FeedsPreferences { /** * Push notification preference for comments on user's activities. One of: all, none @@ -9364,6 +9611,13 @@ export interface FeedsReactionResponse { custom?: Record; } +export interface FeedsRetentionPolicy { + app_pk: number; + enabled_at: Date; + policy: string; + config: FeedsPolicyConfig; +} + export interface FeedsRetentionRunResponse { app_pk: number; date: string; @@ -9441,6 +9695,7 @@ export interface FeedsV3CommentResponse { confidence_score: number; created_at: Date; downvote_count: number; + hidden: boolean; id: string; object_id: string; object_type: string; @@ -9515,6 +9770,10 @@ export interface FilterConfigResponse { * AI image moderation labels available as filter values. Reflects the app's effective image taxonomy: custom Bodyguard taxonomy when enabled, otherwise the standard L1 label set. */ ai_image_labels?: Array; + /** + * Labels the image OCR pipeline can flag, available as filter values on the `label` field under the ai_image category. The app's LLM labels when LLM configurability is enabled, otherwise the AI text labels. OCR and image-classification labels share the `label` field, so a name present in both matches either. + */ + ai_image_ocr_labels?: Array; /** * AI text moderation labels available as filter values */ @@ -9937,6 +10196,9 @@ export interface FullUserResponse { name?: string; revoke_tokens_issued_before?: Date; latest_hidden_channels?: Array; + /** + * The privacy settings of the user. + */ privacy_settings?: PrivacySettingsResponse; teams_role?: Record; } @@ -10012,6 +10274,9 @@ export interface GetApplicationResponse { * Duration of the request in milliseconds */ duration: string; + /** + * A type representing the app settings. + */ app: AppResponseFields; } @@ -10351,7 +10616,7 @@ export interface GetFeedsRetentionPolicyResponse { */ duration: string; enabled: boolean; - policies: Array; + policies: Array; } export interface GetFeedsRetentionPolicyRunsRequest { @@ -10591,6 +10856,10 @@ export interface GetOrCreateFeedRequest { user_id?: string; view?: string; watch?: boolean; + /** + * Feature-gated; not available for all apps. Request-scoped list of actor/user IDs whose activities are filtered from this GetOrCreateFeed response only. Merged (union) into the viewing user's in-memory blocked authors for this request; never persisted to blocked_users. Max: 1000. + */ + discard_actors?: Array; data?: FeedInput; /** * Options to skip specific enrichments to improve performance. Default is false (enrichments are included). Setting a field to true skips that enrichment. @@ -12364,6 +12633,9 @@ export interface MemberUserRequest { role?: string; teams?: Array; custom?: Record; + /** + * The privacy settings of the user. + */ privacy_settings?: PrivacySettingsResponse; teams_role?: Record; } @@ -12637,6 +12909,9 @@ export interface MessageModerationResult { * User who moderated the message */ moderated_by?: string; + /** + * Response from AI moderation + */ ai_moderation_response?: ModerationResponse; /** * Sets thresholds for AI moderation @@ -13744,9 +14019,21 @@ export interface ModerationQueueResponse { } export interface ModerationResponse { + /** + * Action taken by automod + */ action: string; + /** + * Explicit score + */ explicit: number; + /** + * Spam score + */ spam: number; + /** + * Toxicity score + */ toxic: number; } @@ -14359,7 +14646,13 @@ export interface OwnUserResponse { revoke_tokens_issued_before?: Date; blocked_user_ids?: Array; latest_hidden_channels?: Array; + /** + * The privacy settings of the user. + */ privacy_settings?: PrivacySettingsResponse; + /** + * The push preference details. + */ push_preferences?: PushPreferencesResponse; teams_role?: Record; total_unread_count_by_team?: Record; @@ -14986,8 +15279,17 @@ export interface PredefinedFilterStatsResponse { } export interface PrivacySettingsResponse { + /** + * The settings for the delivery receipt events. + */ delivery_receipts?: DeliveryReceiptsResponse; + /** + * The settings for the read receipt events. + */ read_receipts?: ReadReceiptsResponse; + /** + * The settings for typing indicator events. + */ typing_indicators?: TypingIndicatorsResponse; } @@ -15123,7 +15425,13 @@ export interface PushPreferenceInput { export interface PushPreferencesResponse { call_level?: string; + /** + * The scope level of the push notifications. + */ chat_level?: string; + /** + * If provided the notifications will be disabled until the set date. + */ disabled_until?: Date; feeds_level?: string; chat_preferences?: ChatPreferencesResponse; @@ -15586,6 +15894,48 @@ export interface QueryCallParticipantsResponse { call: CallResponse; } +export interface QueryCallRingAttemptsRequest { + /** + * Call ID + */ + id: string; + /** + * The type of call + */ + type: string; + /** + * Limit the attempts to one call session; omit to read every session of the call + */ + call_session_id?: string; +} + +export interface QueryCallRingAttemptsResponse { + /** + * The ID of the call the attempts belong to + */ + call_id: string; + /** + * The type of the call the attempts belong to + */ + call_type: string; + /** + * The number of attempts returned + */ + count: number; + /** + * Duration of the request in milliseconds + */ + duration: string; + /** + * The attempts, newest first + */ + ring_attempts: Array; + /** + * The call session the attempts were limited to, null when every session was read + */ + call_session_id?: string; +} + export interface QueryCallSessionParticipantStatsResponse { call_id: string; call_session_id: string; @@ -15858,7 +16208,7 @@ export interface QueryCommentsRequest { */ id_around?: string; /** - * When true, include soft-deleted comments in the result. Server-side only, and requires an object_id filter. Returns comments deleted by any path, including user-data deletion. Moderation-actioned comments (removed, hidden) remain excluded, and comments whose parent activity is itself deleted are not returned. + * When true, include soft-deleted comments in the result. Server-side only, and requires an object_id filter. Covers comments removed via deleteComment and via soft user-data deletion. Moderation-actioned comments (removed, hidden, shadow_blocked) remain excluded, as are comments whose parent activity is itself deleted. */ include_soft_deleted_comments?: boolean; /** @@ -16933,6 +17283,10 @@ export interface RankingConfig { * Type of ranking algorithm. Required. One of: expression, interest */ type: 'expression' | 'interest'; + /** + * Activities scoring strictly below this value are dropped from the ranked feed. Not supported on aggregated feeds + */ + exclude_below?: number; /** * Scoring formula. Required when type is 'expression' or 'interest' */ @@ -17832,6 +18186,7 @@ export interface ReviewQueueItemResponse { */ confidence_score?: number; config_key?: string; + country_code?: string; /** * ID of who created the entity */ @@ -17897,6 +18252,69 @@ export interface RevisionHistoryResponse { previous_obj_serialized?: Record; } +export interface RingAttemptResponse { + /** + * The application this ring belongs to + */ + app_pk: number; + /** + * The ID of the call that was rung + */ + call_id: string; + /** + * The type of the call that was rung + */ + call_type: string; + /** + * When the ring went out + */ + created_at: Date; + /** + * When the ring expires, i.e. when the missed call deadline fires + */ + expires_at: Date; + /** + * The user that started the ring + */ + initiated_by: string; + /** + * The derived outcome: ringing, answered_some, answered_all, rejected_all, missed_all, cancelled or mixed + */ + outcome: string; + /** + * The ring, as published in the ring_id of the call.ring event + */ + ring_id: string; + /** + * The call session that was rung + */ + session_id: string; + /** + * Why the ring settled: answered, rejected, cancel, timeout, ended or auto_end; empty while it is still ringing + */ + settle_reason: string; + /** + * The user that settled the ring, or 'server'; empty while it is still ringing + */ + settled_by: string; + /** + * Opaque context stored on the ring by the caller + */ + custom: Record; + /** + * The rung users, keyed by user ID + */ + targets: Record; + /** + * When the ring was deleted + */ + deleted_at?: Date; + /** + * When the outcome left ringing + */ + settled_at?: Date; +} + export interface RingCallRequest { /** * Indicate if call should be video @@ -17924,6 +18342,37 @@ export interface RingCallResponse { ring_id?: string; } +export interface RingDeliveryResponse { + /** + * The transport the ring was dispatched over: ws, apns_voip, apns or fcm + */ + channel: string; + /** + * When the ring was dispatched + */ + sent_at: Date; + /** + * When the device acknowledged the ring; not populated yet + */ + acked_at?: Date; + /** + * The device the ring was dispatched to, empty for websocket deliveries which fan out to every connection + */ + device_id?: string; + /** + * When the device displayed the ring; not populated yet + */ + displayed_at?: Date; + /** + * When the device fetched the call; not populated yet + */ + fetched_at?: Date; + /** + * When the push provider accepted the dispatch; not populated yet + */ + provider_accepted_at?: Date; +} + export interface RingSettings { auto_cancel_timeout_ms: number; incoming_call_timeout_ms: number; @@ -17951,6 +18400,31 @@ export interface RingSettingsResponse { missed_call_timeout_ms: number; } +export interface RingSettledTarget { + state: string; + state_at: Date; + reason?: string; +} + +export interface RingTargetResponse { + /** + * The reject or cancel reason, empty otherwise + */ + reason: string; + /** + * The target's state for this ring: pending, accepted, rejected, missed or cancelled + */ + state: string; + /** + * When the target last changed state + */ + state_at: Date; + /** + * The dispatches of this ring to the target's devices + */ + deliveries: Array; +} + export interface Role { /** * Date/time of creation @@ -18009,6 +18483,7 @@ export interface RuleBuilderCondition { channel_message_count_rule_params?: ChannelMessageCountRuleParameters; closed_caption_rule_params?: ClosedCaptionRuleParameters; content_count_rule_params?: ContentCountRuleParameters; + content_country_code_params?: ContentCountryCodeParameters; content_custom_property_count_params?: ContentCustomPropertyCountParameters; content_custom_property_params?: ContentCustomPropertyParameters; content_flag_count_rule_params?: FlagCountRuleParameters; @@ -18817,8 +19292,9 @@ export interface SessionWarningResponse { export interface SetFeedsRetentionPolicyRequest { max_age_hours: number; - policy: 'old-activities'; + policy: string; enabled?: boolean; + feed_groups?: Array; } export interface SetFeedsRetentionPolicyResponse { @@ -18827,7 +19303,7 @@ export interface SetFeedsRetentionPolicyResponse { */ duration: string; enabled: boolean; - policy: RetentionPolicy; + policy: FeedsRetentionPolicy; } export interface SetRetentionPolicyRequest { @@ -18930,14 +19406,42 @@ export interface SharedLocationResponse { } export interface SharedLocationResponseData { + /** + * The CID (type:id) of the channel that the location is attached to. + */ channel_cid: string; + /** + * The date when the location was created. + */ created_at: Date; + /** + * The ID of the device that created the location. + */ created_by_device_id: string; + /** + * The latitude of the location. + */ latitude: number; + /** + * The longitude of the location. + */ longitude: number; + /** + * The ID of the message that the location is attached to. + */ message_id: string; + /** + * The date when the location was updated. + */ updated_at: Date; + /** + * The ID of the user that created the location. + */ user_id: string; + /** + * The date when the location sharing ends. + * If it's empty, it means the location sharing is static instead of live. + */ end_at?: Date; /** * Represents channel in chat @@ -19829,6 +20333,7 @@ export interface ThreadedCommentResponse { confidence_score: number; created_at: Date; downvote_count: number; + hidden: boolean; id: string; object_id: string; object_type: string; @@ -20512,14 +21017,32 @@ export interface UnreadCountsBatchResponse { } export interface UnreadCountsChannel { + /** + * The channel CID (type:id). + */ channel_id: string; + /** + * The date which the current user last read the channel. + */ last_read: Date; + /** + * The number of unread messages inside the channel. + */ unread_count: number; } export interface UnreadCountsChannelType { + /** + * The number of unread channels of this channel type. + */ channel_count: number; + /** + * The channel type. + */ channel_type: string; + /** + * The number of unread messages of all the channels with this type. + */ unread_count: number; } @@ -20533,9 +21056,21 @@ export interface UnreadCountsResponse { } export interface UnreadCountsThread { + /** + * The date which the current user last read the thread. + */ last_read: Date; + /** + * The id of the last reply which the current user read in the thread. + */ last_read_message_id: string; + /** + * The message id of the root of the thread. + */ parent_message_id: string; + /** + * The number of unread replies inside the thread. + */ unread_count: number; } @@ -22905,6 +23440,9 @@ export interface UserRequest { * Custom user data */ custom?: Record; + /** + * The privacy settings of the user. + */ privacy_settings?: PrivacySettingsResponse; /** * Map of team-specific roles for the user @@ -22986,6 +23524,9 @@ export interface UserResponse { * List of devices user is using */ devices?: Array; + /** + * The privacy settings of the user. + */ privacy_settings?: PrivacySettingsResponse; push_notifications?: PushNotificationSettingsResponse; teams_role?: Record; @@ -23031,6 +23572,9 @@ export interface UserResponsePrivacyFields { last_active?: Date; name?: string; revoke_tokens_issued_before?: Date; + /** + * The privacy settings of the user. + */ privacy_settings?: PrivacySettingsResponse; teams_role?: Record; } @@ -23294,6 +23838,7 @@ export type WHEvent = | ({ type: 'call.recording_stopped' } & CallRecordingStoppedEvent) | ({ type: 'call.rejected' } & CallRejectedEvent) | ({ type: 'call.ring' } & CallRingEvent) + | ({ type: 'call.ring_settled' } & CallRingSettledEvent) | ({ type: 'call.rtmp_broadcast_failed' } & CallRtmpBroadcastFailedEvent) | ({ type: 'call.rtmp_broadcast_started' } & CallRtmpBroadcastStartedEvent) | ({ type: 'call.rtmp_broadcast_stopped' } & CallRtmpBroadcastStoppedEvent) @@ -23339,6 +23884,8 @@ export type WHEvent = } & AsyncBulkImageModerationEvent) | ({ type: 'export.channels.error' } & AsyncExportErrorEvent) | ({ type: 'export.channels.success' } & AsyncExportChannelsEvent) + | ({ type: 'export.label_results.error' } & AsyncExportErrorEvent) + | ({ type: 'export.label_results.success' } & AsyncExportLabelResultsEvent) | ({ type: 'export.moderation_logs.error' } & AsyncExportErrorEvent) | ({ type: 'export.moderation_logs.success'; @@ -23368,6 +23915,7 @@ export type WHEvent = | ({ type: 'feeds.bookmark_folder.updated' } & BookmarkFolderUpdatedEvent) | ({ type: 'feeds.comment.added' } & CommentAddedEvent) | ({ type: 'feeds.comment.deleted' } & CommentDeletedEvent) + | ({ type: 'feeds.comment.feedback' } & CommentFeedbackEvent) | ({ type: 'feeds.comment.reaction.added' } & CommentReactionAddedEvent) | ({ type: 'feeds.comment.reaction.deleted' } & CommentReactionDeletedEvent) | ({ type: 'feeds.comment.reaction.updated' } & CommentReactionUpdatedEvent) @@ -23388,6 +23936,8 @@ export type WHEvent = | ({ type: 'feeds.notification_feed.updated' } & NotificationFeedUpdatedEvent) | ({ type: 'feeds.stories_feed.updated' } & StoriesFeedUpdatedEvent) | ({ type: 'flag.updated' } & FlagUpdatedEvent) + | ({ type: 'import.error' } & AsyncImportErrorEvent) + | ({ type: 'import.success' } & AsyncImportSuccessEvent) | ({ type: 'ingress.error' } & IngressErrorEvent) | ({ type: 'ingress.started' } & IngressStartedEvent) | ({ type: 'ingress.stopped' } & IngressStoppedEvent) @@ -23469,6 +24019,9 @@ export interface WSEvent { thread_id?: string; user_id?: string; watcher_count?: number; + /** + * Response from AI moderation + */ automoderation_scores?: ModerationResponse; /** * Represents channel in chat @@ -23513,11 +24066,29 @@ export interface WrappedUnreadCountsResponse { * Duration of the request in milliseconds */ duration: string; + /** + * The total number of unread messages. + */ total_unread_count: number; + /** + * The total number of unread threads. + */ total_unread_threads_count: number; + /** + * The unread information per channel type. + */ channel_type: Array; + /** + * The unread information per channel. + */ channels: Array; + /** + * The unread information per thread. + */ threads: Array; + /** + * The total number of unread messages grouped by team. + */ total_unread_count_by_team?: Record; } diff --git a/src/gen/moderation/ModerationApi.ts b/src/gen/moderation/ModerationApi.ts index 4d26e8a..bfb8901 100644 --- a/src/gen/moderation/ModerationApi.ts +++ b/src/gen/moderation/ModerationApi.ts @@ -382,9 +382,11 @@ export class ModerationApi { ): Promise> { const body = { target_user_id: request?.target_user_id, + ban_from_future_channels: request?.ban_from_future_channels, banned_by_id: request?.banned_by_id, channel_cid: request?.channel_cid, delete_messages: request?.delete_messages, + delete_reactions: request?.delete_reactions, ip_ban: request?.ip_ban, reason: request?.reason, shadow: request?.shadow, diff --git a/src/gen/video/VideoApi.ts b/src/gen/video/VideoApi.ts index 447e18c..47675ac 100644 --- a/src/gen/video/VideoApi.ts +++ b/src/gen/video/VideoApi.ts @@ -45,6 +45,8 @@ import { QueryCallParticipantSessionsResponse, QueryCallParticipantsRequest, QueryCallParticipantsResponse, + QueryCallRingAttemptsRequest, + QueryCallRingAttemptsResponse, QueryCallSessionParticipantStatsResponse, QueryCallSessionParticipantStatsTimelineResponse, QueryCallSessionStatsRequest, @@ -188,6 +190,29 @@ export class VideoApi { return response; } + async queryCallRingAttempts( + request: QueryCallRingAttemptsRequest, + ): Promise> { + const body = { + id: request?.id, + type: request?.type, + call_session_id: request?.call_session_id, + }; + + const response = + await this.apiClient.sendRequest( + 'POST', + '/api/v2/video/call/ring_attempts', + undefined, + undefined, + body, + ); + + decoders['QueryCallRingAttemptsResponse']?.(response); + + return response; + } + async queryCallStats( request?: QueryCallStatsRequest, ): Promise> {