diff --git a/src/client.ts b/src/client.ts index 5b464b9848..6901001927 100644 --- a/src/client.ts +++ b/src/client.ts @@ -96,6 +96,7 @@ import { GetMessageAPIResponse, GetRateLimitsResponse, GetUnreadCountAPIResponse, + GetUnreadCountBatchAPIResponse, ListChannelResponse, ListCommandsResponse, ListImportsPaginationOptions, @@ -123,12 +124,10 @@ import { PushProviderListResponse, PushProviderUpsertResponse, QueryChannelsAPIResponse, + QuerySegmentsOptions, ReactionResponse, ReactivateUserOptions, ReactivateUsersOptions, - Recipient, - RecipientFilters, - RecipientQueryOptions, ReservedMessageFields, ReviewFlagReportOptions, ReviewFlagReportResponse, @@ -138,8 +137,7 @@ import { SearchPayload, Segment, SegmentData, - SegmentFilters, - SegmentQueryOptions, + SegmentType, SendFileAPIResponse, StreamChatOptions, SyncOptions, @@ -159,6 +157,7 @@ import { UpdatedMessage, UpdateMessageAPIResponse, UpdateMessageOptions, + UpdateSegmentData, UserCustomEvent, UserFilters, UserOptions, @@ -1688,10 +1687,28 @@ export class StreamChat} + */ async getUnreadCount(userID?: string) { return await this.get(this.baseURL + '/unread', userID ? { user_id: userID } : {}); } + /** + * getUnreadCountBatch - Returns unread counts for multiple users at once. Only works server side. + * + * @param {string[]} [userIDs] List of user IDs to fetch unread counts for. + * + * @return {} + */ + async getUnreadCountBatch(userIDs: string[]) { + return await this.post(this.baseURL + '/unread_batch', { user_ids: userIDs }); + } + /** * removeDevice - Removes the device with the given id. Clientside users can only delete their own devices * @@ -2824,56 +2841,132 @@ export class StreamChat { + const body = { + id, + type, + name, + data, + }; + const { segment } = await this.post<{ segment: Segment }>(this.baseURL + `/segments`, body); + return segment; + } + + /** + * createUserSegment - Creates a user segment + * + * @param {string} id Segment ID (valid UUID) + * @param {string} name Segment name + * @param {SegmentData} data Segment data + * + * @return {Segment} The created Segment + */ + async createUserSegment(id: string, name: string, data?: SegmentData): Promise { + return await this.createSegment('user', id, name, data); + } + + /** + * createChannelSegment - Creates a channel segment + * + * @param {string} id Segment ID (valid UUID) + * @param {string} name Segment name + * @param {SegmentData} data Segment data + * + * @return {Segment} The created Segment + */ + async createChannelSegment(id: string, name: string, data?: SegmentData): Promise { + return await this.createSegment('channel', id, name, data); + } + + /** + * updateSegment - Update a segment + * + * @param {string} id Segment ID + * @param {Partial} data Data to update + * + * @return {Segment} Updated Segment */ - async createSegment(params: SegmentData) { - const { segment } = await this.post<{ segment: Segment }>(this.baseURL + `/segments`, { segment: params }); + async updateSegment(id: string, data: Partial) { + const { segment } = await this.put<{ segment: Segment }>(this.baseURL + `/segments/${id}`, data); return segment; } /** - * querySegments - Query Campaign Segments + * addSegmentTargets - Add targets to a segment + * + * @param {string} id Segment ID + * @param {string[]} targets Targets to add to the segment + * + * @return {APIResponse} API response + */ + async addSegmentTargets(id: string, targets: string[]) { + const body = { targets }; + return await this.post(this.baseURL + `/segments/${id}/addtargets`, body); + } + + /** + * deleteSegmentTargets - Delete targets from a segment + * + * @param {string} id Segment ID + * @param {string[]} targets Targets to add to the segment + * + * @return {APIResponse} API response + */ + async deleteSegmentTargets(id: string, targets: string[]) { + const body = { targets }; + return await this.post(this.baseURL + `/segments/${id}/deletetargets`, body); + } + + /** + * querySegments - Query Segments * + * @param {filter} filter MongoDB style filter conditions + * @param {QuerySegmentsOptions} options Options for sorting/paginating the results * * @return {Segment[]} Segments */ - async querySegments(filters: SegmentFilters, options: SegmentQueryOptions = {}) { + async querySegments(filter: {}, options: QuerySegmentsOptions = {}) { return await this.get<{ segments: Segment[]; }>(this.baseURL + `/segments`, { payload: { - filter_conditions: filters, + filter, ...options, }, }); } /** - * updateSegment - Update a Campaign Segment + * deleteSegment - Delete a Campaign Segment * * @param {string} id Segment ID - * @param {Partial} params Segment data * - * @return {Segment} Updated Segment + * @return {Promise} The Server Response */ - async updateSegment(id: string, params: Partial) { - const { segment } = await this.put<{ segment: Segment }>(this.baseURL + `/segments/${id}`, { segment: params }); - return segment; + async deleteSegment(id: string) { + return await this.delete(this.baseURL + `/segments/${id}`); } /** - * deleteSegment - Delete a Campaign Segment + * segmentTargetExists - Check if a target exists in a segment * - * @param {string} id Segment ID + * @param {string} segmentId Segment ID + * @param {string} targetId Target ID * * @return {Promise} The Server Response */ - async deleteSegment(id: string) { - return this.delete(this.baseURL + `/segments/${id}`); + async segmentTargetExists(segmentId: string, targetId: string) { + return await this.get(this.baseURL + `/segments/${segmentId}/target/${targetId}`); } /** @@ -2987,27 +3080,6 @@ export class StreamChat(this.baseURL + `/campaigns/${id}/test`, { users }); } - /** - * queryRecipients - Query Campaign Recipient Results - * - * - * @return {Recipient[]} Recipients - */ - async queryRecipients(filters: RecipientFilters, options: RecipientQueryOptions = {}) { - return await this.get<{ - campaigns: Record; - recipients: Recipient[]; - segments: Record; - channels?: Record>; - users?: Record>; - }>(this.baseURL + `/recipients`, { - payload: { - filter_conditions: filters, - ...options, - }, - }); - } - /** * enrichURL - Get OpenGraph data of the given link * diff --git a/src/types.ts b/src/types.ts index 9aefd6235b..da3c418a9a 100644 --- a/src/types.ts +++ b/src/types.ts @@ -114,6 +114,10 @@ export type AppSettingsAPIResponse = APIResponse & { channel_types: Record< string, @@ -2400,22 +2409,43 @@ export type DeleteUserOptions = { user?: DeleteType; }; +export type SegmentType = 'channel' | 'user'; + export type SegmentData = { description: string; filter: {}; - name: string; - type: 'channel' | 'user'; }; export type Segment = { created_at: string; + deleted_at: string; id: string; - in_use: boolean; + locked: boolean; + name: string; size: number; - status: 'computing' | 'ready'; + type: SegmentType; updated_at: string; } & SegmentData; +export type UpdateSegmentData = { + name: string; +} & SegmentData; + +export type SortParam = { + field: string; + direction?: AscDesc; +}; + +export type Pager = { + limit?: number; + next?: string; + prev?: string; +}; + +export type QuerySegmentsOptions = { + sort?: SortParam[]; +} & Pager; + export type CampaignSortField = { field: string; // eslint-disable-next-line @typescript-eslint/no-explicit-any @@ -2433,12 +2463,9 @@ export type CampaignQueryOptions = { }; export type SegmentQueryOptions = CampaignQueryOptions; -export type RecipientQueryOptions = CampaignQueryOptions; // TODO: add better typing -export type SegmentFilters = {}; export type CampaignFilters = {}; -export type RecipientFilters = {}; export type CampaignData = { attachments: Attachment[]; @@ -2479,20 +2506,7 @@ export type TestCampaignResponse = { results?: Record; }; -export type DeleteCampaignOptions = { - recipients?: boolean; -}; - -export type Recipient = { - campaign_id: string; - channel_cid: string; - created_at: string; - status: 'pending' | 'sent' | 'failed'; - updated_at: string; - details?: string; - message_id?: string; - receiver_id?: string; -}; +export type DeleteCampaignOptions = {}; export type TaskStatus = { created_at: string;