From c11684615fdd0b8f997d4be6aebb67420ff6e77c Mon Sep 17 00:00:00 2001 From: Faiz Shaikh Date: Mon, 23 Mar 2026 17:01:19 +0100 Subject: [PATCH 1/5] test: add retention policy endpoint tests Co-Authored-By: Claude Opus 4.6 (1M context) --- tests/Integration/ChatMiscIntegrationTest.php | 90 +++++++++++++++++++ 1 file changed, 90 insertions(+) diff --git a/tests/Integration/ChatMiscIntegrationTest.php b/tests/Integration/ChatMiscIntegrationTest.php index 26e3853..d31a00e 100644 --- a/tests/Integration/ChatMiscIntegrationTest.php +++ b/tests/Integration/ChatMiscIntegrationTest.php @@ -640,6 +640,96 @@ public function channelBatchUpdate(): void self::markTestSkipped('ChannelBatchUpdate is not yet available in the generated SDK'); } + // ========================================================================= + // Retention Policy + // ========================================================================= + + /** + * @test + */ + public function setRetentionPolicy(): string + { + try { + $resp = $this->client->setRetentionPolicy(new GeneratedModels\SetRetentionPolicyRequest( + policy: 'old-messages', + maxAgeHours: 720, + )); + $this->assertResponseSuccess($resp, 'set retention policy'); + self::assertNotNull($resp->getData()->policy, 'Policy should be returned'); + } catch (\Exception $e) { + if (str_contains($e->getMessage(), 'not enabled') || str_contains($e->getMessage(), 'retention')) { + self::markTestSkipped('Retention policies are not enabled for this app'); + } + + throw $e; + } + + return 'old-messages'; + } + + /** + * @test + * @depends setRetentionPolicy + */ + public function getRetentionPolicy(string $policyName): string + { + try { + $resp = $this->client->getRetentionPolicy(); + $this->assertResponseSuccess($resp, 'get retention policy'); + self::assertNotNull($resp->getData()->policies, 'Policies list should be returned'); + self::assertNotEmpty($resp->getData()->policies, 'Should have at least one policy'); + } catch (\Exception $e) { + if (str_contains($e->getMessage(), 'not enabled') || str_contains($e->getMessage(), 'retention')) { + self::markTestSkipped('Retention policies are not enabled for this app'); + } + + throw $e; + } + + return $policyName; + } + + /** + * @test + * @depends getRetentionPolicy + */ + public function getRetentionPolicyRuns(string $policyName): string + { + try { + $resp = $this->client->getRetentionPolicyRuns(limit: 10, offset: 0); + $this->assertResponseSuccess($resp, 'get retention policy runs'); + self::assertNotNull($resp->getData()->runs, 'Runs list should be returned'); + } catch (\Exception $e) { + if (str_contains($e->getMessage(), 'not enabled') || str_contains($e->getMessage(), 'retention')) { + self::markTestSkipped('Retention policies are not enabled for this app'); + } + + throw $e; + } + + return $policyName; + } + + /** + * @test + * @depends getRetentionPolicyRuns + */ + public function deleteRetentionPolicy(string $policyName): void + { + try { + $resp = $this->client->deleteRetentionPolicy(new GeneratedModels\DeleteRetentionPolicyRequest( + policy: $policyName, + )); + $this->assertResponseSuccess($resp, 'delete retention policy'); + } catch (\Exception $e) { + if (str_contains($e->getMessage(), 'not enabled') || str_contains($e->getMessage(), 'retention')) { + self::markTestSkipped('Retention policies are not enabled for this app'); + } + + throw $e; + } + } + protected static function sharedUserCount(): int { return 2; From ce5f27c73276db66458dff2caca45b4843dbc9c8 Mon Sep 17 00:00:00 2001 From: Faiz Shaikh Date: Mon, 23 Mar 2026 17:23:41 +0100 Subject: [PATCH 2/5] test: remove retention policy creation/update tests Co-Authored-By: Claude Opus 4.6 (1M context) --- tests/Integration/ChatMiscIntegrationTest.php | 20 ++++++------------- 1 file changed, 6 insertions(+), 14 deletions(-) diff --git a/tests/Integration/ChatMiscIntegrationTest.php b/tests/Integration/ChatMiscIntegrationTest.php index d31a00e..cb8861f 100644 --- a/tests/Integration/ChatMiscIntegrationTest.php +++ b/tests/Integration/ChatMiscIntegrationTest.php @@ -647,15 +647,16 @@ public function channelBatchUpdate(): void /** * @test */ - public function setRetentionPolicy(): string + public function getRetentionPolicy(): string { + $policyName = 'old-messages'; + + // Ensure a policy exists before querying try { - $resp = $this->client->setRetentionPolicy(new GeneratedModels\SetRetentionPolicyRequest( - policy: 'old-messages', + $this->client->setRetentionPolicy(new GeneratedModels\SetRetentionPolicyRequest( + policy: $policyName, maxAgeHours: 720, )); - $this->assertResponseSuccess($resp, 'set retention policy'); - self::assertNotNull($resp->getData()->policy, 'Policy should be returned'); } catch (\Exception $e) { if (str_contains($e->getMessage(), 'not enabled') || str_contains($e->getMessage(), 'retention')) { self::markTestSkipped('Retention policies are not enabled for this app'); @@ -664,15 +665,6 @@ public function setRetentionPolicy(): string throw $e; } - return 'old-messages'; - } - - /** - * @test - * @depends setRetentionPolicy - */ - public function getRetentionPolicy(string $policyName): string - { try { $resp = $this->client->getRetentionPolicy(); $this->assertResponseSuccess($resp, 'get retention policy'); From 49b34e897adbbd23c52fe67bac00b34214ae9da3 Mon Sep 17 00:00:00 2001 From: Faiz Shaikh Date: Mon, 23 Mar 2026 17:29:43 +0100 Subject: [PATCH 3/5] test: remove delete retention policy test Co-Authored-By: Claude Opus 4.6 (1M context) --- tests/Integration/ChatMiscIntegrationTest.php | 23 +------------------ 1 file changed, 1 insertion(+), 22 deletions(-) diff --git a/tests/Integration/ChatMiscIntegrationTest.php b/tests/Integration/ChatMiscIntegrationTest.php index cb8861f..527cb0a 100644 --- a/tests/Integration/ChatMiscIntegrationTest.php +++ b/tests/Integration/ChatMiscIntegrationTest.php @@ -685,7 +685,7 @@ public function getRetentionPolicy(): string * @test * @depends getRetentionPolicy */ - public function getRetentionPolicyRuns(string $policyName): string + public function getRetentionPolicyRuns(string $policyName): void { try { $resp = $this->client->getRetentionPolicyRuns(limit: 10, offset: 0); @@ -699,27 +699,6 @@ public function getRetentionPolicyRuns(string $policyName): string throw $e; } - return $policyName; - } - - /** - * @test - * @depends getRetentionPolicyRuns - */ - public function deleteRetentionPolicy(string $policyName): void - { - try { - $resp = $this->client->deleteRetentionPolicy(new GeneratedModels\DeleteRetentionPolicyRequest( - policy: $policyName, - )); - $this->assertResponseSuccess($resp, 'delete retention policy'); - } catch (\Exception $e) { - if (str_contains($e->getMessage(), 'not enabled') || str_contains($e->getMessage(), 'retention')) { - self::markTestSkipped('Retention policies are not enabled for this app'); - } - - throw $e; - } } protected static function sharedUserCount(): int From 68ce879c2423c0d6bac6caaca0fd52638c0c80d1 Mon Sep 17 00:00:00 2001 From: Faiz Shaikh Date: Mon, 23 Mar 2026 17:30:44 +0100 Subject: [PATCH 4/5] test: remove delete retention policy tests Co-Authored-By: Claude Opus 4.6 (1M context) --- tests/Integration/ChatMiscIntegrationTest.php | 16 ++++++++++------ 1 file changed, 10 insertions(+), 6 deletions(-) diff --git a/tests/Integration/ChatMiscIntegrationTest.php b/tests/Integration/ChatMiscIntegrationTest.php index 527cb0a..55ff34f 100644 --- a/tests/Integration/ChatMiscIntegrationTest.php +++ b/tests/Integration/ChatMiscIntegrationTest.php @@ -647,7 +647,7 @@ public function channelBatchUpdate(): void /** * @test */ - public function getRetentionPolicy(): string + public function getRetentionPolicy(): void { $policyName = 'old-messages'; @@ -676,16 +676,21 @@ public function getRetentionPolicy(): string } throw $e; + } finally { + // Clean up the policy we created + try { + $this->client->deleteRetentionPolicy(new GeneratedModels\DeleteRetentionPolicyRequest( + policy: $policyName, + )); + } catch (\Exception $ignore) { + } } - - return $policyName; } /** * @test - * @depends getRetentionPolicy */ - public function getRetentionPolicyRuns(string $policyName): void + public function getRetentionPolicyRuns(): void { try { $resp = $this->client->getRetentionPolicyRuns(limit: 10, offset: 0); @@ -698,7 +703,6 @@ public function getRetentionPolicyRuns(string $policyName): void throw $e; } - } protected static function sharedUserCount(): int From 4faade4d7ee2e9ede145540de2f9bde6e840c599 Mon Sep 17 00:00:00 2001 From: Faiz Shaikh Date: Tue, 31 Mar 2026 12:57:02 +0200 Subject: [PATCH 5/5] feat: regenerate from latest OpenAPI spec, keep only retention runs test Regenerated SDK from latest serverside-api.yaml spec. Updated retention policy integration test to only test getRetentionPolicyRuns endpoint. Co-Authored-By: Claude Opus 4.6 (1M context) --- src/Generated/ChatTrait.php | 17 +-- src/Generated/CommonTrait.php | 53 +++++++++ src/Generated/FeedsTrait.php | 53 ++++++++- src/Generated/ModerationTrait.php | 28 +++++ src/Generated/Webhook.php | 3 + src/GeneratedModels/ActivityRequest.php | 3 +- src/GeneratedModels/ActivityResponse.php | 1 + src/GeneratedModels/AddActivityRequest.php | 3 +- .../AddCommentReactionRequest.php | 3 +- src/GeneratedModels/AddCommentRequest.php | 3 +- src/GeneratedModels/AddReactionRequest.php | 3 +- .../AddUserGroupMembersRequest.php | 1 + src/GeneratedModels/AggregationConfig.php | 1 + src/GeneratedModels/CallLevelEventPayload.php | 18 +++ .../CallStatsParticipantCounts.php | 2 + src/GeneratedModels/CheckRequest.php | 1 + src/GeneratedModels/CommentRestoredEvent.php | 25 ++++ src/GeneratedModels/EnrichedCollection.php | 21 ++++ src/GeneratedModels/EnrichmentOptions.php | 1 + src/GeneratedModels/EscalatePayload.php | 20 ++++ src/GeneratedModels/EscalationMetadata.php | 17 +++ src/GeneratedModels/FeedsPreferences.php | 3 +- .../FeedsPreferencesResponse.php | 1 + src/GeneratedModels/FeedsReactionGroup.php | 17 +++ .../FeedsV3ActivityResponse.php | 60 ++++++++++ .../FeedsV3CommentResponse.php | 41 +++++++ src/GeneratedModels/FollowRequest.php | 3 +- .../GetExternalStorageAWSS3Response.php | 18 +++ .../GetExternalStorageResponse.php | 22 ++++ src/GeneratedModels/GetFlagCountRequest.php | 16 +++ src/GeneratedModels/GetFlagCountResponse.php | 16 +++ .../GetRetentionPolicyRunsRequest.php | 21 ++++ .../GetRetentionPolicyRunsResponse.php | 6 +- .../ImageContentParameters.php | 2 + src/GeneratedModels/ImageRuleParameters.php | 1 + .../InsertActionLogRequest.php | 23 ++++ .../InsertActionLogResponse.php | 18 +++ .../ModerationActionConfigResponse.php | 1 + .../ModerationDashboardPreferences.php | 2 + src/GeneratedModels/NotificationTarget.php | 1 + src/GeneratedModels/NotificationTrigger.php | 1 + .../QueryBannedUsersPayload.php | 2 +- .../QueryCallMembersRequest.php | 4 +- .../QueryCallParticipantsRequest.php | 2 +- ...eryCallSessionParticipantStatsResponse.php | 3 + src/GeneratedModels/QueryCallStatsRequest.php | 4 +- src/GeneratedModels/QueryCallsRequest.php | 2 +- src/GeneratedModels/QueryChannelsRequest.php | 2 +- src/GeneratedModels/QueryMembersPayload.php | 7 +- .../QueryMessageFlagsPayload.php | 4 +- .../QueryUserFeedbackRequest.php | 4 +- src/GeneratedModels/QueryUsersPayload.php | 7 +- src/GeneratedModels/ReactionGroupResponse.php | 3 + .../ReactionGroupUserResponse.php | 20 ++++ src/GeneratedModels/RestoreCommentRequest.php | 16 +++ .../RestoreCommentResponse.php | 17 +++ src/GeneratedModels/RetentionRunResponse.php | 18 +++ .../ReviewQueueItemResponse.php | 8 +- src/GeneratedModels/SubmitActionRequest.php | 3 +- src/GeneratedModels/TextContentParameters.php | 1 + src/GeneratedModels/TriggeredRuleResponse.php | 4 +- src/GeneratedModels/UnfollowBatchRequest.php | 6 +- src/GeneratedModels/UnfollowPair.php | 17 +++ .../UpdateActivityPartialChangeRequest.php | 3 +- .../UpdateActivityPartialRequest.php | 3 +- src/GeneratedModels/UpdateActivityRequest.php | 3 +- .../UpdateCommentPartialRequest.php | 23 ++++ .../UpdateCommentPartialResponse.php | 16 +++ src/GeneratedModels/UpdateCommentRequest.php | 3 +- src/GeneratedModels/UpdateFollowRequest.php | 3 +- .../UpsertExternalStorageAWSS3Request.php | 18 +++ .../UpsertExternalStorageRequest.php | 16 +++ .../UpsertExternalStorageResponse.php | 18 +++ .../ValidateExternalStorageResponse.php | 18 +++ .../VideoContentParameters.php | 1 + tests/Integration/ChatMiscIntegrationTest.php | 49 +------- tests/WebhookTest.php | 110 ++++++------------ 77 files changed, 809 insertions(+), 179 deletions(-) create mode 100644 src/GeneratedModels/CallLevelEventPayload.php create mode 100644 src/GeneratedModels/CommentRestoredEvent.php create mode 100644 src/GeneratedModels/EnrichedCollection.php create mode 100644 src/GeneratedModels/EscalatePayload.php create mode 100644 src/GeneratedModels/EscalationMetadata.php create mode 100644 src/GeneratedModels/FeedsReactionGroup.php create mode 100644 src/GeneratedModels/FeedsV3ActivityResponse.php create mode 100644 src/GeneratedModels/FeedsV3CommentResponse.php create mode 100644 src/GeneratedModels/GetExternalStorageAWSS3Response.php create mode 100644 src/GeneratedModels/GetExternalStorageResponse.php create mode 100644 src/GeneratedModels/GetFlagCountRequest.php create mode 100644 src/GeneratedModels/GetFlagCountResponse.php create mode 100644 src/GeneratedModels/GetRetentionPolicyRunsRequest.php create mode 100644 src/GeneratedModels/InsertActionLogRequest.php create mode 100644 src/GeneratedModels/InsertActionLogResponse.php create mode 100644 src/GeneratedModels/ReactionGroupUserResponse.php create mode 100644 src/GeneratedModels/RestoreCommentRequest.php create mode 100644 src/GeneratedModels/RestoreCommentResponse.php create mode 100644 src/GeneratedModels/RetentionRunResponse.php create mode 100644 src/GeneratedModels/UnfollowPair.php create mode 100644 src/GeneratedModels/UpdateCommentPartialRequest.php create mode 100644 src/GeneratedModels/UpdateCommentPartialResponse.php create mode 100644 src/GeneratedModels/UpsertExternalStorageAWSS3Request.php create mode 100644 src/GeneratedModels/UpsertExternalStorageRequest.php create mode 100644 src/GeneratedModels/UpsertExternalStorageResponse.php create mode 100644 src/GeneratedModels/ValidateExternalStorageResponse.php diff --git a/src/Generated/ChatTrait.php b/src/Generated/ChatTrait.php index 0fefa1f..f2665bf 100644 --- a/src/Generated/ChatTrait.php +++ b/src/Generated/ChatTrait.php @@ -1363,25 +1363,18 @@ public function deleteRetentionPolicy(GeneratedModels\DeleteRetentionPolicyReque return StreamResponse::fromJson($this->makeRequest('POST', $path, $queryParams, $requestData), GeneratedModels\DeleteRetentionPolicyResponse::class); } /** - * Returns paginated retention cleanup run history for the app. Server-side only. + * Returns filtered and sorted retention cleanup run history for the app. Supports filter_conditions on 'policy' (possible values: 'old-messages', 'inactive-channels') and 'date' fields. Server-side only. * - * @param int $limit - * @param int $offset + * @param GeneratedModels\GetRetentionPolicyRunsRequest $requestData * @return StreamResponse * @throws StreamException */ - public function getRetentionPolicyRuns(int $limit, int $offset): StreamResponse { + public function getRetentionPolicyRuns(GeneratedModels\GetRetentionPolicyRunsRequest $requestData): StreamResponse { $path = '/api/v2/chat/retention_policy/runs'; $queryParams = []; - if ($limit !== null) { - $queryParams['limit'] = $limit; - } - if ($offset !== null) { - $queryParams['offset'] = $offset; - } - $requestData = null; - return StreamResponse::fromJson($this->makeRequest('GET', $path, $queryParams, $requestData), GeneratedModels\GetRetentionPolicyRunsResponse::class); + // Use the provided request data array directly + return StreamResponse::fromJson($this->makeRequest('POST', $path, $queryParams, $requestData), GeneratedModels\GetRetentionPolicyRunsResponse::class); } /** * Search messages across channels diff --git a/src/Generated/CommonTrait.php b/src/Generated/CommonTrait.php index 8b1b113..7112aaa 100644 --- a/src/Generated/CommonTrait.php +++ b/src/Generated/CommonTrait.php @@ -390,6 +390,59 @@ public function createImportV2Task(GeneratedModels\CreateImportV2TaskRequest $re // Use the provided request data array directly return StreamResponse::fromJson($this->makeRequest('POST', $path, $queryParams, $requestData), GeneratedModels\CreateImportV2TaskResponse::class); } + /** + * Removes the external storage configuration for the app. Idempotent: succeeds even if no configuration exists. + * + * @return StreamResponse + * @throws StreamException + */ + public function deleteImporterExternalStorage(): StreamResponse { + $path = '/api/v2/imports/v2/external-storage'; + + $queryParams = []; + $requestData = null; + return StreamResponse::fromJson($this->makeRequest('DELETE', $path, $queryParams, $requestData), GeneratedModels\DeleteExternalStorageResponse::class); + } + /** + * Returns the current external storage configuration for the app. Returns 404 if no configuration exists. + * + * @return StreamResponse + * @throws StreamException + */ + public function getImporterExternalStorage(): StreamResponse { + $path = '/api/v2/imports/v2/external-storage'; + + $queryParams = []; + $requestData = null; + return StreamResponse::fromJson($this->makeRequest('GET', $path, $queryParams, $requestData), GeneratedModels\GetExternalStorageResponse::class); + } + /** + * Creates or updates the external storage configuration for the app. Currently only AWS S3 (via cross-account IAM role assumption) is supported. + * + * @param GeneratedModels\UpsertExternalStorageRequest $requestData + * @return StreamResponse + * @throws StreamException + */ + public function upsertImporterExternalStorage(GeneratedModels\UpsertExternalStorageRequest $requestData): StreamResponse { + $path = '/api/v2/imports/v2/external-storage'; + + $queryParams = []; + // Use the provided request data array directly + return StreamResponse::fromJson($this->makeRequest('PUT', $path, $queryParams, $requestData), GeneratedModels\UpsertExternalStorageResponse::class); + } + /** + * Validates the configured external S3 storage by performing a live STS AssumeRole and S3 ListObjectsV2 check. + * + * @return StreamResponse + * @throws StreamException + */ + public function validateImporterExternalStorage(): StreamResponse { + $path = '/api/v2/imports/v2/external-storage/validate'; + + $queryParams = []; + $requestData = null; + return StreamResponse::fromJson($this->makeRequest('POST', $path, $queryParams, $requestData), GeneratedModels\ValidateExternalStorageResponse::class); + } /** * Deletes an import v2 task. Can only delete tasks in queued state. * diff --git a/src/Generated/FeedsTrait.php b/src/Generated/FeedsTrait.php index 1333932..751d38b 100644 --- a/src/Generated/FeedsTrait.php +++ b/src/Generated/FeedsTrait.php @@ -534,6 +534,7 @@ public function queryCollections(GeneratedModels\QueryCollectionsRequest $reques * @param int $depth * @param string $sort * @param int $repliesLimit + * @param string $idAround * @param string $userID * @param int $limit * @param string $prev @@ -541,7 +542,7 @@ public function queryCollections(GeneratedModels\QueryCollectionsRequest $reques * @return StreamResponse * @throws StreamException */ - public function getComments(string $objectID, string $objectType, int $depth, string $sort, int $repliesLimit, string $userID, int $limit, string $prev, string $next): StreamResponse { + public function getComments(string $objectID, string $objectType, int $depth, string $sort, int $repliesLimit, string $idAround, string $userID, int $limit, string $prev, string $next): StreamResponse { $path = '/api/v2/feeds/comments'; $queryParams = []; @@ -560,6 +561,9 @@ public function getComments(string $objectID, string $objectType, int $depth, st if ($repliesLimit !== null) { $queryParams['replies_limit'] = $repliesLimit; } + if ($idAround !== null) { + $queryParams['id_around'] = $idAround; + } if ($userID !== null) { $queryParams['user_id'] = $userID; } @@ -671,6 +675,25 @@ public function updateComment(string $id, GeneratedModels\UpdateCommentRequest $ // Use the provided request data array directly return StreamResponse::fromJson($this->makeRequest('PATCH', $path, $queryParams, $requestData), GeneratedModels\UpdateCommentResponse::class); } + /** + * Updates certain fields of the comment. Use 'set' to update specific fields and 'unset' to remove fields. + * Sends events: + * - feeds.activity.updated + * - feeds.comment.updated + * + * @param string $id + * @param GeneratedModels\UpdateCommentPartialRequest $requestData + * @return StreamResponse + * @throws StreamException + */ + public function updateCommentPartial(string $id, GeneratedModels\UpdateCommentPartialRequest $requestData): StreamResponse { + $path = '/api/v2/feeds/comments/{id}/partial'; + $path = str_replace('{id}', (string) $id, $path); + + $queryParams = []; + // Use the provided request data array directly + return StreamResponse::fromJson($this->makeRequest('POST', $path, $queryParams, $requestData), GeneratedModels\UpdateCommentPartialResponse::class); + } /** * Adds a reaction to a comment * @@ -735,6 +758,7 @@ public function deleteCommentReaction(string $id, string $type, bool $deleteNoti * @param int $depth * @param string $sort * @param int $repliesLimit + * @param string $idAround * @param string $userID * @param int $limit * @param string $prev @@ -742,7 +766,7 @@ public function deleteCommentReaction(string $id, string $type, bool $deleteNoti * @return StreamResponse * @throws StreamException */ - public function getCommentReplies(string $id, int $depth, string $sort, int $repliesLimit, string $userID, int $limit, string $prev, string $next): StreamResponse { + public function getCommentReplies(string $id, int $depth, string $sort, int $repliesLimit, string $idAround, string $userID, int $limit, string $prev, string $next): StreamResponse { $path = '/api/v2/feeds/comments/{id}/replies'; $path = str_replace('{id}', (string) $id, $path); @@ -756,6 +780,9 @@ public function getCommentReplies(string $id, int $depth, string $sort, int $rep if ($repliesLimit !== null) { $queryParams['replies_limit'] = $repliesLimit; } + if ($idAround !== null) { + $queryParams['id_around'] = $idAround; + } if ($userID !== null) { $queryParams['user_id'] = $userID; } @@ -771,6 +798,22 @@ public function getCommentReplies(string $id, int $depth, string $sort, int $rep $requestData = null; return StreamResponse::fromJson($this->makeRequest('GET', $path, $queryParams, $requestData), GeneratedModels\GetCommentRepliesResponse::class); } + /** + * Restores a soft-deleted comment by its ID. The comment and all its descendants are restored. Requires moderator permissions. + * + * @param string $id + * @param GeneratedModels\RestoreCommentRequest $requestData + * @return StreamResponse + * @throws StreamException + */ + public function restoreComment(string $id, GeneratedModels\RestoreCommentRequest $requestData): StreamResponse { + $path = '/api/v2/feeds/comments/{id}/restore'; + $path = str_replace('{id}', (string) $id, $path); + + $queryParams = []; + // Use the provided request data array directly + return StreamResponse::fromJson($this->makeRequest('POST', $path, $queryParams, $requestData), GeneratedModels\RestoreCommentResponse::class); + } /** * List all feed groups for the application * @@ -1449,11 +1492,12 @@ public function rejectFollow(GeneratedModels\RejectFollowRequest $requestData): * @param string $source * @param string $target * @param bool $deleteNotificationActivity + * @param bool $keepHistory * @param bool $enrichOwnFields * @return StreamResponse * @throws StreamException */ - public function unfollow(string $source, string $target, bool $deleteNotificationActivity, bool $enrichOwnFields): StreamResponse { + public function unfollow(string $source, string $target, bool $deleteNotificationActivity, bool $keepHistory, bool $enrichOwnFields): StreamResponse { $path = '/api/v2/feeds/follows/{source}/{target}'; $path = str_replace('{source}', (string) $source, $path); $path = str_replace('{target}', (string) $target, $path); @@ -1462,6 +1506,9 @@ public function unfollow(string $source, string $target, bool $deleteNotificatio if ($deleteNotificationActivity !== null) { $queryParams['delete_notification_activity'] = $deleteNotificationActivity; } + if ($keepHistory !== null) { + $queryParams['keep_history'] = $keepHistory; + } if ($enrichOwnFields !== null) { $queryParams['enrich_own_fields'] = $enrichOwnFields; } diff --git a/src/Generated/ModerationTrait.php b/src/Generated/ModerationTrait.php index 6915058..ea34a76 100644 --- a/src/Generated/ModerationTrait.php +++ b/src/Generated/ModerationTrait.php @@ -14,6 +14,20 @@ */ trait ModerationTrait { + /** + * Insert a moderation action log entry. Server-side only. Used by product services to log moderation-related actions. + * + * @param GeneratedModels\InsertActionLogRequest $requestData + * @return StreamResponse + * @throws StreamException + */ + public function insertActionLog(GeneratedModels\InsertActionLogRequest $requestData): StreamResponse { + $path = '/api/v2/moderation/action_logs'; + + $queryParams = []; + // Use the provided request data array directly + return StreamResponse::fromJson($this->makeRequest('POST', $path, $queryParams, $requestData), GeneratedModels\InsertActionLogResponse::class); + } /** * Appeal against the moderation decision * @@ -247,6 +261,20 @@ public function flag(GeneratedModels\FlagRequest $requestData): StreamResponse { // Use the provided request data array directly return StreamResponse::fromJson($this->makeRequest('POST', $path, $queryParams, $requestData), GeneratedModels\FlagResponse::class); } + /** + * Returns the number of moderation flags created against a specific user's content. Optionally filter by entity type. + * + * @param GeneratedModels\GetFlagCountRequest $requestData + * @return StreamResponse + * @throws StreamException + */ + public function getFlagCount(GeneratedModels\GetFlagCountRequest $requestData): StreamResponse { + $path = '/api/v2/moderation/flag_count'; + + $queryParams = []; + // Use the provided request data array directly + return StreamResponse::fromJson($this->makeRequest('POST', $path, $queryParams, $requestData), GeneratedModels\GetFlagCountResponse::class); + } /** * Query flags associated with moderation items. This is used for building a moderation dashboard. * diff --git a/src/Generated/Webhook.php b/src/Generated/Webhook.php index 2526b06..fdb289c 100644 --- a/src/Generated/Webhook.php +++ b/src/Generated/Webhook.php @@ -95,6 +95,7 @@ use GetStream\GeneratedModels\CommentReactionAddedEvent; use GetStream\GeneratedModels\CommentReactionDeletedEvent; use GetStream\GeneratedModels\CommentReactionUpdatedEvent; +use GetStream\GeneratedModels\CommentRestoredEvent; use GetStream\GeneratedModels\CommentUpdatedEvent; use GetStream\GeneratedModels\CustomEvent; use GetStream\GeneratedModels\CustomVideoEvent; @@ -275,6 +276,7 @@ class Webhook public const EVENT_TYPE_FEEDS_COMMENT_REACTION_ADDED = 'feeds.comment.reaction.added'; public const EVENT_TYPE_FEEDS_COMMENT_REACTION_DELETED = 'feeds.comment.reaction.deleted'; public const EVENT_TYPE_FEEDS_COMMENT_REACTION_UPDATED = 'feeds.comment.reaction.updated'; + public const EVENT_TYPE_FEEDS_COMMENT_RESTORED = 'feeds.comment.restored'; public const EVENT_TYPE_FEEDS_COMMENT_UPDATED = 'feeds.comment.updated'; public const EVENT_TYPE_FEEDS_FEED_CREATED = 'feeds.feed.created'; public const EVENT_TYPE_FEEDS_FEED_DELETED = 'feeds.feed.deleted'; @@ -503,6 +505,7 @@ private static function getEventClass(string $eventType): ?string 'feeds.comment.reaction.added' => CommentReactionAddedEvent::class, 'feeds.comment.reaction.deleted' => CommentReactionDeletedEvent::class, 'feeds.comment.reaction.updated' => CommentReactionUpdatedEvent::class, + 'feeds.comment.restored' => CommentRestoredEvent::class, 'feeds.comment.updated' => CommentUpdatedEvent::class, 'feeds.feed.created' => FeedCreatedEvent::class, 'feeds.feed.deleted' => FeedDeletedEvent::class, diff --git a/src/GeneratedModels/ActivityRequest.php b/src/GeneratedModels/ActivityRequest.php index 6f5fef2..ee5ca42 100644 --- a/src/GeneratedModels/ActivityRequest.php +++ b/src/GeneratedModels/ActivityRequest.php @@ -29,7 +29,8 @@ public function __construct( public ?object $custom = null, // Custom data for the activity public ?bool $skipEnrichUrl = null, // Whether to skip URL enrichment for the activity public ?bool $createNotificationActivity = null, // Whether to create notification activities for mentioned users - public ?bool $copyCustomToNotification = null, // Whether to copy custom data to the notification activity (only applies when create_notification_activity is true) + /** @deprecated */ + public ?bool $copyCustomToNotification = null, // Whether to copy custom data to the notification activity (only applies when create_notification_activity is true) Deprecated: use notification_context.trigger.custom and notification_context.target.custom instead public ?bool $skipPush = null, // Whether to skip push notifications ) { } diff --git a/src/GeneratedModels/ActivityResponse.php b/src/GeneratedModels/ActivityResponse.php index 7d59aae..2198c12 100644 --- a/src/GeneratedModels/ActivityResponse.php +++ b/src/GeneratedModels/ActivityResponse.php @@ -25,6 +25,7 @@ public function __construct( public ?NotificationContext $notificationContext = null, public ?int $popularity = null, // Popularity score of the activity public ?int $score = null, // Ranking score for this activity + public ?object $scoreVars = null, // Variable values used at ranking time. Only included when include_score_vars is enabled in enrichment options. public ?string $selectorSource = null, // Which activity selector provided this activity (e.g., 'following', 'popular', 'interest'). Only set when using multiple activity selectors with ranking. /** @var array|null */ #[ArrayOf(CommentResponse::class)] diff --git a/src/GeneratedModels/AddActivityRequest.php b/src/GeneratedModels/AddActivityRequest.php index 7e46f00..00d60af 100644 --- a/src/GeneratedModels/AddActivityRequest.php +++ b/src/GeneratedModels/AddActivityRequest.php @@ -29,7 +29,8 @@ public function __construct( public ?object $custom = null, // Custom data for the activity public ?bool $skipEnrichUrl = null, // Whether to skip URL enrichment for the activity public ?bool $createNotificationActivity = null, // Whether to create notification activities for mentioned users - public ?bool $copyCustomToNotification = null, // Whether to copy custom data to the notification activity (only applies when create_notification_activity is true) + /** @deprecated */ + public ?bool $copyCustomToNotification = null, // Whether to copy custom data to the notification activity (only applies when create_notification_activity is true) Deprecated: use notification_context.trigger.custom and notification_context.target.custom instead public ?bool $skipPush = null, // Whether to skip push notifications public ?bool $enrichOwnFields = null, ) { diff --git a/src/GeneratedModels/AddCommentReactionRequest.php b/src/GeneratedModels/AddCommentReactionRequest.php index 7027415..a4c167b 100644 --- a/src/GeneratedModels/AddCommentReactionRequest.php +++ b/src/GeneratedModels/AddCommentReactionRequest.php @@ -9,7 +9,8 @@ public function __construct( public ?string $type = null, // The type of reaction, eg upvote, like, ... public ?object $custom = null, // Optional custom data to add to the reaction public ?bool $createNotificationActivity = null, // Whether to create a notification activity for this reaction - public ?bool $copyCustomToNotification = null, // Whether to copy custom data to the notification activity (only applies when create_notification_activity is true) + /** @deprecated */ + public ?bool $copyCustomToNotification = null, // Whether to copy custom data to the notification activity (only applies when create_notification_activity is true) Deprecated: use notification_context.trigger.custom and notification_context.target.custom instead public ?bool $skipPush = null, public ?bool $enforceUnique = null, // Whether to enforce unique reactions per user (remove other reaction types from the user when adding this one) public ?string $userID = null, diff --git a/src/GeneratedModels/AddCommentRequest.php b/src/GeneratedModels/AddCommentRequest.php index bbb1918..afc8be6 100644 --- a/src/GeneratedModels/AddCommentRequest.php +++ b/src/GeneratedModels/AddCommentRequest.php @@ -17,7 +17,8 @@ public function __construct( public ?string $parentID = null, // ID of parent comment for replies. When provided, object_id and object_type are automatically inherited from the parent comment. public ?object $custom = null, // Custom data for the comment public ?bool $createNotificationActivity = null, // Whether to create a notification activity for this comment - public ?bool $copyCustomToNotification = null, // Whether to copy custom data to the notification activity (only applies when create_notification_activity is true) + /** @deprecated */ + public ?bool $copyCustomToNotification = null, // Whether to copy custom data to the notification activity (only applies when create_notification_activity is true) Deprecated: use notification_context.trigger.custom and notification_context.target.custom instead public ?bool $skipPush = null, public ?bool $skipEnrichUrl = null, // Whether to skip URL enrichment for this comment public ?string $userID = null, diff --git a/src/GeneratedModels/AddReactionRequest.php b/src/GeneratedModels/AddReactionRequest.php index e095515..245871c 100644 --- a/src/GeneratedModels/AddReactionRequest.php +++ b/src/GeneratedModels/AddReactionRequest.php @@ -9,7 +9,8 @@ public function __construct( public ?string $type = null, // Type of reaction public ?object $custom = null, // Custom data for the reaction public ?bool $createNotificationActivity = null, // Whether to create a notification activity for this reaction - public ?bool $copyCustomToNotification = null, // Whether to copy custom data to the notification activity (only applies when create_notification_activity is true) + /** @deprecated */ + public ?bool $copyCustomToNotification = null, // Whether to copy custom data to the notification activity (only applies when create_notification_activity is true) Deprecated: use notification_context.trigger.custom and notification_context.target.custom instead public ?bool $skipPush = null, public ?bool $enforceUnique = null, // Whether to enforce unique reactions per user (remove other reaction types from the user when adding this one) public ?string $userID = null, diff --git a/src/GeneratedModels/AddUserGroupMembersRequest.php b/src/GeneratedModels/AddUserGroupMembersRequest.php index 69aa695..7a35970 100644 --- a/src/GeneratedModels/AddUserGroupMembersRequest.php +++ b/src/GeneratedModels/AddUserGroupMembersRequest.php @@ -10,6 +10,7 @@ class AddUserGroupMembersRequest extends BaseModel { public function __construct( public ?array $memberIds = null, // List of user IDs to add as members + public ?bool $asAdmin = null, // Whether to add the members as group admins. Defaults to false public ?string $teamID = null, ) { } diff --git a/src/GeneratedModels/AggregationConfig.php b/src/GeneratedModels/AggregationConfig.php index 4b050f6..85ff9c7 100644 --- a/src/GeneratedModels/AggregationConfig.php +++ b/src/GeneratedModels/AggregationConfig.php @@ -7,6 +7,7 @@ class AggregationConfig extends BaseModel { public function __construct( public ?string $format = null, // Format for activity aggregation + public ?string $scoreStrategy = null, // Strategy for computing aggregated group scores from member activity scores when ranking is enabled. Valid values: sum, max, avg ) { } diff --git a/src/GeneratedModels/CallLevelEventPayload.php b/src/GeneratedModels/CallLevelEventPayload.php new file mode 100644 index 0000000..0e662de --- /dev/null +++ b/src/GeneratedModels/CallLevelEventPayload.php @@ -0,0 +1,18 @@ +|null */ + #[ArrayOf(Attachment::class)] + public ?array $attachments = null, + /** @var array|null */ + #[ArrayOf(UserResponse::class)] + public ?array $mentionedUsers = null, + /** @var array|null */ + #[ArrayOf(FeedsV3CommentResponse::class)] + public ?array $comments = null, + public ?object $custom = null, + public ?object $searchData = null, + public ?array $filterTags = null, + public ?array $interestTags = null, + /** @var array|null */ + #[MapOf(EnrichedCollection::class)] + public ?array $collections = null, + public ?ModerationV2Response $moderation = null, + public ?string $moderationAction = null, + public ?int $popularity = null, + public ?int $commentCount = null, + public ?int $bookmarkCount = null, + public ?int $shareCount = null, + public ?int $reactionCount = null, + public ?int $score = null, + public ?array $metrics = null, + public ?array $latestReactions = null, + /** @var array|null */ + #[MapOf(FeedsReactionGroup::class)] + public ?array $reactionGroups = null, + public ?array $ownReactions = null, + public ?array $ownBookmarks = null, + public ?bool $hidden = null, + public ?bool $preview = null, + ) { + } + + // BaseModel automatically handles jsonSerialize(), toArray(), and fromJson() using constructor types! + // Use #[JsonKey('user_id')] to override field names if needed. +} diff --git a/src/GeneratedModels/FeedsV3CommentResponse.php b/src/GeneratedModels/FeedsV3CommentResponse.php new file mode 100644 index 0000000..7484d39 --- /dev/null +++ b/src/GeneratedModels/FeedsV3CommentResponse.php @@ -0,0 +1,41 @@ +|null */ + #[ArrayOf(UserResponse::class)] + public ?array $mentionedUsers = null, + public ?array $ownReactions = null, + /** @var array|null */ + #[ArrayOf(Attachment::class)] + public ?array $attachments = null, + public ?object $custom = null, + public ?\DateTime $createdAt = null, + public ?\DateTime $updatedAt = null, + public ?\DateTime $editedAt = null, + public ?\DateTime $deletedAt = null, + public ?int $upvoteCount = null, + public ?int $downvoteCount = null, + public ?int $score = null, + public ?int $confidenceScore = null, + public ?int $controversyScore = null, + public ?int $replyCount = null, + public ?int $reactionCount = null, + public ?ModerationV2Response $moderation = null, + ) { + } + + // BaseModel automatically handles jsonSerialize(), toArray(), and fromJson() using constructor types! + // Use #[JsonKey('user_id')] to override field names if needed. +} diff --git a/src/GeneratedModels/FollowRequest.php b/src/GeneratedModels/FollowRequest.php index 1441d73..50d7efb 100644 --- a/src/GeneratedModels/FollowRequest.php +++ b/src/GeneratedModels/FollowRequest.php @@ -11,7 +11,8 @@ public function __construct( public ?object $custom = null, // Custom data for the follow relationship public ?string $pushPreference = null, // Push preference for the follow relationship public ?bool $createNotificationActivity = null, // Whether to create a notification activity for this follow - public ?bool $copyCustomToNotification = null, // Whether to copy custom data to the notification activity (only applies when create_notification_activity is true) + /** @deprecated */ + public ?bool $copyCustomToNotification = null, // Whether to copy custom data to the notification activity (only applies when create_notification_activity is true) Deprecated: use notification_context.trigger.custom and notification_context.target.custom instead public ?bool $skipPush = null, // Whether to skip push for this follow public ?string $status = null, // Status of the follow relationship. One of: accepted, pending, rejected public ?bool $enrichOwnFields = null, // If true, enriches the follow's source_feed and target_feed with own_* fields (own_follows, own_followings, own_capabilities, own_membership). Defaults to false for performance. diff --git a/src/GeneratedModels/GetExternalStorageAWSS3Response.php b/src/GeneratedModels/GetExternalStorageAWSS3Response.php new file mode 100644 index 0000000..44e1bf4 --- /dev/null +++ b/src/GeneratedModels/GetExternalStorageAWSS3Response.php @@ -0,0 +1,18 @@ +|null */ + #[ArrayOf(SortParamRequest::class)] + public ?array $sort = null, // Array of sort parameters + public ?int $limit = null, + public ?string $next = null, + public ?string $prev = null, + ) { + } + + // BaseModel automatically handles jsonSerialize(), toArray(), and fromJson() using constructor types! + // Use #[JsonKey('user_id')] to override field names if needed. +} diff --git a/src/GeneratedModels/GetRetentionPolicyRunsResponse.php b/src/GeneratedModels/GetRetentionPolicyRunsResponse.php index 52399ff..85befe7 100644 --- a/src/GeneratedModels/GetRetentionPolicyRunsResponse.php +++ b/src/GeneratedModels/GetRetentionPolicyRunsResponse.php @@ -9,9 +9,11 @@ class GetRetentionPolicyRunsResponse extends BaseModel { public function __construct( - /** @var array|null */ - #[ArrayOf(RetentionCleanupRun::class)] + /** @var array|null */ + #[ArrayOf(RetentionRunResponse::class)] public ?array $runs = null, + public ?string $next = null, + public ?string $prev = null, public ?string $duration = null, // Duration of the request in milliseconds ) { } diff --git a/src/GeneratedModels/ImageContentParameters.php b/src/GeneratedModels/ImageContentParameters.php index 9b2e587..56387b5 100644 --- a/src/GeneratedModels/ImageContentParameters.php +++ b/src/GeneratedModels/ImageContentParameters.php @@ -7,6 +7,8 @@ class ImageContentParameters extends BaseModel { public function __construct( public ?array $harmLabels = null, + public ?string $labelOperator = null, + public ?int $minConfidence = null, ) { } diff --git a/src/GeneratedModels/ImageRuleParameters.php b/src/GeneratedModels/ImageRuleParameters.php index 953257a..faf2176 100644 --- a/src/GeneratedModels/ImageRuleParameters.php +++ b/src/GeneratedModels/ImageRuleParameters.php @@ -9,6 +9,7 @@ public function __construct( public ?int $threshold = null, public ?string $timeWindow = null, public ?array $harmLabels = null, + public ?int $minConfidence = null, ) { } diff --git a/src/GeneratedModels/InsertActionLogRequest.php b/src/GeneratedModels/InsertActionLogRequest.php new file mode 100644 index 0000000..028729f --- /dev/null +++ b/src/GeneratedModels/InsertActionLogRequest.php @@ -0,0 +1,23 @@ +|null */ #[ArrayOf(SortParamRequest::class)] public ?array $sort = null, // Array of sort parameters diff --git a/src/GeneratedModels/QueryCallMembersRequest.php b/src/GeneratedModels/QueryCallMembersRequest.php index 861397b..863d2a3 100644 --- a/src/GeneratedModels/QueryCallMembersRequest.php +++ b/src/GeneratedModels/QueryCallMembersRequest.php @@ -8,10 +8,10 @@ class QueryCallMembersRequest extends BaseModel public function __construct( public ?string $type = null, public ?string $id = null, - public ?object $filterConditions = null, + public ?object $filterConditions = null, // Filter conditions to apply to the query /** @var array|null */ #[ArrayOf(SortParamRequest::class)] - public ?array $sort = null, + public ?array $sort = null, // Array of sort parameters public ?int $limit = null, public ?string $next = null, public ?string $prev = null, diff --git a/src/GeneratedModels/QueryCallParticipantsRequest.php b/src/GeneratedModels/QueryCallParticipantsRequest.php index 6daa362..306aeaf 100644 --- a/src/GeneratedModels/QueryCallParticipantsRequest.php +++ b/src/GeneratedModels/QueryCallParticipantsRequest.php @@ -6,7 +6,7 @@ class QueryCallParticipantsRequest extends BaseModel { public function __construct( - public ?object $filterConditions = null, + public ?object $filterConditions = null, // Filter conditions to apply to the query ) { } diff --git a/src/GeneratedModels/QueryCallSessionParticipantStatsResponse.php b/src/GeneratedModels/QueryCallSessionParticipantStatsResponse.php index 5e9baf8..bbf7ef5 100644 --- a/src/GeneratedModels/QueryCallSessionParticipantStatsResponse.php +++ b/src/GeneratedModels/QueryCallSessionParticipantStatsResponse.php @@ -21,6 +21,9 @@ public function __construct( /** @var array|null */ #[ArrayOf(CallStatsParticipant::class)] public ?array $participants = null, + /** @var array|null */ + #[ArrayOf(CallLevelEventPayload::class)] + public ?array $callEvents = null, public ?string $tmpDataSource = null, ) { } diff --git a/src/GeneratedModels/QueryCallStatsRequest.php b/src/GeneratedModels/QueryCallStatsRequest.php index 23b1fda..8cd04a0 100644 --- a/src/GeneratedModels/QueryCallStatsRequest.php +++ b/src/GeneratedModels/QueryCallStatsRequest.php @@ -6,10 +6,10 @@ class QueryCallStatsRequest extends BaseModel { public function __construct( - public ?object $filterConditions = null, + public ?object $filterConditions = null, // Filter conditions to apply to the query /** @var array|null */ #[ArrayOf(SortParamRequest::class)] - public ?array $sort = null, + public ?array $sort = null, // Array of sort parameters public ?int $limit = null, public ?string $next = null, public ?string $prev = null, diff --git a/src/GeneratedModels/QueryCallsRequest.php b/src/GeneratedModels/QueryCallsRequest.php index ed25b5f..830236a 100644 --- a/src/GeneratedModels/QueryCallsRequest.php +++ b/src/GeneratedModels/QueryCallsRequest.php @@ -6,7 +6,7 @@ class QueryCallsRequest extends BaseModel { public function __construct( - public ?object $filterConditions = null, + public ?object $filterConditions = null, // Filter conditions to apply to the query /** @var array|null */ #[ArrayOf(SortParamRequest::class)] public ?array $sort = null, // Array of sort parameters diff --git a/src/GeneratedModels/QueryChannelsRequest.php b/src/GeneratedModels/QueryChannelsRequest.php index 73d3870..eae2f8e 100644 --- a/src/GeneratedModels/QueryChannelsRequest.php +++ b/src/GeneratedModels/QueryChannelsRequest.php @@ -6,7 +6,7 @@ class QueryChannelsRequest extends BaseModel { public function __construct( - public ?object $filterConditions = null, + public ?object $filterConditions = null, // Filter conditions to apply to the query /** @var array|null */ #[ArrayOf(SortParamRequest::class)] public ?array $sort = null, // List of sort parameters diff --git a/src/GeneratedModels/QueryMembersPayload.php b/src/GeneratedModels/QueryMembersPayload.php index 33157c1..cd5d933 100644 --- a/src/GeneratedModels/QueryMembersPayload.php +++ b/src/GeneratedModels/QueryMembersPayload.php @@ -3,9 +3,6 @@ declare(strict_types=1); namespace GetStream\GeneratedModels; -/** - * Client request - */ class QueryMembersPayload extends BaseModel { public function __construct( @@ -14,10 +11,10 @@ public function __construct( /** @var array|null */ #[ArrayOf(ChannelMemberRequest::class)] public ?array $members = null, - public ?object $filterConditions = null, + public ?object $filterConditions = null, // Filter conditions to apply to the query /** @var array|null */ #[ArrayOf(SortParamRequest::class)] - public ?array $sort = null, + public ?array $sort = null, // Array of sort parameters public ?int $limit = null, public ?int $offset = null, public ?string $userID = null, diff --git a/src/GeneratedModels/QueryMessageFlagsPayload.php b/src/GeneratedModels/QueryMessageFlagsPayload.php index df53d08..a25ca01 100644 --- a/src/GeneratedModels/QueryMessageFlagsPayload.php +++ b/src/GeneratedModels/QueryMessageFlagsPayload.php @@ -6,13 +6,13 @@ class QueryMessageFlagsPayload extends BaseModel { public function __construct( - public ?object $filterConditions = null, + public ?object $filterConditions = null, // Filter conditions to apply to the query public ?bool $showDeletedMessages = null, // Whether to include deleted messages in the results public ?int $limit = null, public ?int $offset = null, /** @var array|null */ #[ArrayOf(SortParamRequest::class)] - public ?array $sort = null, + public ?array $sort = null, // Array of sort parameters public ?string $userID = null, public ?UserRequest $user = null, ) { diff --git a/src/GeneratedModels/QueryUserFeedbackRequest.php b/src/GeneratedModels/QueryUserFeedbackRequest.php index af76b42..20b2c47 100644 --- a/src/GeneratedModels/QueryUserFeedbackRequest.php +++ b/src/GeneratedModels/QueryUserFeedbackRequest.php @@ -6,10 +6,10 @@ class QueryUserFeedbackRequest extends BaseModel { public function __construct( - public ?object $filterConditions = null, + public ?object $filterConditions = null, // Filter conditions to apply to the query /** @var array|null */ #[ArrayOf(SortParamRequest::class)] - public ?array $sort = null, + public ?array $sort = null, // Array of sort parameters public ?int $limit = null, public ?string $next = null, public ?string $prev = null, diff --git a/src/GeneratedModels/QueryUsersPayload.php b/src/GeneratedModels/QueryUsersPayload.php index f9a11f0..a49f125 100644 --- a/src/GeneratedModels/QueryUsersPayload.php +++ b/src/GeneratedModels/QueryUsersPayload.php @@ -3,16 +3,13 @@ declare(strict_types=1); namespace GetStream\GeneratedModels; -/** - * Client request - */ class QueryUsersPayload extends BaseModel { public function __construct( - public ?object $filterConditions = null, + public ?object $filterConditions = null, // Filter conditions to apply to the query /** @var array|null */ #[ArrayOf(SortParamRequest::class)] - public ?array $sort = null, + public ?array $sort = null, // Array of sort parameters public ?bool $presence = null, public ?bool $includeDeactivatedUsers = null, public ?int $limit = null, diff --git a/src/GeneratedModels/ReactionGroupResponse.php b/src/GeneratedModels/ReactionGroupResponse.php index 4e82620..91105a2 100644 --- a/src/GeneratedModels/ReactionGroupResponse.php +++ b/src/GeneratedModels/ReactionGroupResponse.php @@ -13,6 +13,9 @@ public function __construct( public ?int $sumScores = null, // SumScores is the sum of all scores of reactions of this type. Medium allows you to clap articles more than once and shows the sum of all claps from all users. For example, you can send `clap` x5 using `score: 5`. public ?\DateTime $firstReactionAt = null, // FirstReactionAt is the time of the first reaction of this type. This is the same also if all reaction of this type are deleted, because if someone will react again with the same type, will be preserved the sorting. public ?\DateTime $lastReactionAt = null, // LastReactionAt is the time of the last reaction of this type. + /** @var array|null */ + #[ArrayOf(ReactionGroupUserResponse::class)] + public ?array $latestReactionsBy = null, // The most recent users who reacted with this type, ordered by most recent first. ) { } diff --git a/src/GeneratedModels/ReactionGroupUserResponse.php b/src/GeneratedModels/ReactionGroupUserResponse.php new file mode 100644 index 0000000..950fccc --- /dev/null +++ b/src/GeneratedModels/ReactionGroupUserResponse.php @@ -0,0 +1,20 @@ +|null */ - #[ArrayOf(FollowPair::class)] - public ?array $follows = null, // List of follow relationships to remove + /** @var array|null */ + #[ArrayOf(UnfollowPair::class)] + public ?array $follows = null, // List of follow relationships to remove, each with optional keep_history public ?bool $deleteNotificationActivity = null, // Whether to delete the corresponding notification activity (default: false) public ?bool $enrichOwnFields = null, // If true, enriches the follow's source_feed and target_feed with own_* fields (own_follows, own_followings, own_capabilities, own_membership). Defaults to false for performance. ) { diff --git a/src/GeneratedModels/UnfollowPair.php b/src/GeneratedModels/UnfollowPair.php new file mode 100644 index 0000000..f5e96aa --- /dev/null +++ b/src/GeneratedModels/UnfollowPair.php @@ -0,0 +1,17 @@ +client->setRetentionPolicy(new GeneratedModels\SetRetentionPolicyRequest( - policy: $policyName, - maxAgeHours: 720, - )); - } catch (\Exception $e) { - if (str_contains($e->getMessage(), 'not enabled') || str_contains($e->getMessage(), 'retention')) { - self::markTestSkipped('Retention policies are not enabled for this app'); - } - - throw $e; - } - - try { - $resp = $this->client->getRetentionPolicy(); - $this->assertResponseSuccess($resp, 'get retention policy'); - self::assertNotNull($resp->getData()->policies, 'Policies list should be returned'); - self::assertNotEmpty($resp->getData()->policies, 'Should have at least one policy'); - } catch (\Exception $e) { - if (str_contains($e->getMessage(), 'not enabled') || str_contains($e->getMessage(), 'retention')) { - self::markTestSkipped('Retention policies are not enabled for this app'); - } - - throw $e; - } finally { - // Clean up the policy we created - try { - $this->client->deleteRetentionPolicy(new GeneratedModels\DeleteRetentionPolicyRequest( - policy: $policyName, - )); - } catch (\Exception $ignore) { - } - } - } - /** * @test */ public function getRetentionPolicyRuns(): void { try { - $resp = $this->client->getRetentionPolicyRuns(limit: 10, offset: 0); + $resp = $this->client->getRetentionPolicyRuns(new GeneratedModels\GetRetentionPolicyRunsRequest( + limit: 10, + )); $this->assertResponseSuccess($resp, 'get retention policy runs'); self::assertNotNull($resp->getData()->runs, 'Runs list should be returned'); } catch (\Exception $e) { diff --git a/tests/WebhookTest.php b/tests/WebhookTest.php index 21f7462..7758efb 100644 --- a/tests/WebhookTest.php +++ b/tests/WebhookTest.php @@ -1,115 +1,88 @@ -computeSignature($this->body, $this->secret); - self::assertTrue(Webhook::verifySignature($this->body, $signature, $this->secret)); + $this->assertTrue(Webhook::verifySignature($this->body, $signature, $this->secret)); } - /** - * @test - */ - public function verifySignatureWrongSignature(): void + public function testVerifySignatureWrongSignature(): void { - self::assertFalse(Webhook::verifySignature($this->body, 'invalidsignature', $this->secret)); + $this->assertFalse(Webhook::verifySignature($this->body, 'invalidsignature', $this->secret)); } - /** - * @test - */ - public function verifySignatureTamperedBody(): void + public function testVerifySignatureTamperedBody(): void { $signature = $this->computeSignature($this->body, $this->secret); - self::assertFalse(Webhook::verifySignature('{"type":"tampered"}', $signature, $this->secret)); + $this->assertFalse(Webhook::verifySignature('{"type":"tampered"}', $signature, $this->secret)); } - /** - * @test - */ - public function verifySignatureWrongSecret(): void + public function testVerifySignatureWrongSecret(): void { $signature = $this->computeSignature($this->body, $this->secret); - self::assertFalse(Webhook::verifySignature($this->body, $signature, 'wrong-secret')); + $this->assertFalse(Webhook::verifySignature($this->body, $signature, 'wrong-secret')); } - /** - * @test - */ - public function verifySignatureEmptySignature(): void + public function testVerifySignatureEmptySignature(): void { - self::assertFalse(Webhook::verifySignature($this->body, '', $this->secret)); + $this->assertFalse(Webhook::verifySignature($this->body, '', $this->secret)); } - /** - * @test - */ - public function getEventTypeValid(): void + public function testGetEventTypeValid(): void { - self::assertSame('message.new', Webhook::getEventType('{"type":"message.new"}')); + $this->assertEquals('message.new', Webhook::getEventType('{"type":"message.new"}')); } - /** - * @test - */ - public function getEventTypeFromArray(): void + public function testGetEventTypeFromArray(): void { - self::assertSame('message.new', Webhook::getEventType(['type' => 'message.new'])); + $this->assertEquals('message.new', Webhook::getEventType(['type' => 'message.new'])); } - /** - * @test - */ - public function getEventTypeMissingField(): void + public function testGetEventTypeMissingField(): void { - self::assertNull(Webhook::getEventType('{"foo":"bar"}')); + $this->assertNull(Webhook::getEventType('{"foo":"bar"}')); } - /** - * @test - */ - public function getEventTypeInvalidJson(): void + public function testGetEventTypeInvalidJson(): void { $this->expectException(\InvalidArgumentException::class); Webhook::getEventType('not json'); } - /** - * @test - */ - public function getEventTypeEmptyObject(): void + public function testGetEventTypeEmptyObject(): void { - self::assertNull(Webhook::getEventType('{}')); + $this->assertNull(Webhook::getEventType('{}')); } /** - * @dataProvider provideParseWebhookEventCases - * - * @test + * @dataProvider webhookEventProvider */ - public function parseWebhookEvent(string $eventType, string $expectedClassName): void + public function testParseWebhookEvent(string $eventType, string $expectedClassName): void { $payload = '{"type":"' . $eventType . '"}'; $event = Webhook::parseWebhookEvent($payload); - self::assertNotNull($event); + $this->assertNotNull($event); $parts = explode('\\', get_class($event)); - self::assertSame($expectedClassName, end($parts)); + $this->assertEquals($expectedClassName, end($parts)); } - public static function provideParseWebhookEventCases(): iterable + public static function webhookEventProvider(): array { return [ '*' => ['*', 'CustomEvent'], @@ -215,6 +188,7 @@ public static function provideParseWebhookEventCases(): iterable 'feeds.comment.reaction.added' => ['feeds.comment.reaction.added', 'CommentReactionAddedEvent'], 'feeds.comment.reaction.deleted' => ['feeds.comment.reaction.deleted', 'CommentReactionDeletedEvent'], 'feeds.comment.reaction.updated' => ['feeds.comment.reaction.updated', 'CommentReactionUpdatedEvent'], + 'feeds.comment.restored' => ['feeds.comment.restored', 'CommentRestoredEvent'], 'feeds.comment.updated' => ['feeds.comment.updated', 'CommentUpdatedEvent'], 'feeds.feed.created' => ['feeds.feed.created', 'FeedCreatedEvent'], 'feeds.feed.deleted' => ['feeds.feed.deleted', 'FeedDeletedEvent'], @@ -281,38 +255,24 @@ public static function provideParseWebhookEventCases(): iterable ]; } - /** - * @test - */ - public function parseWebhookEventUnknownType(): void + public function testParseWebhookEventUnknownType(): void { $this->expectException(\InvalidArgumentException::class); $this->expectExceptionMessage('Unknown webhook event type'); Webhook::parseWebhookEvent('{"type":"unknown.event"}'); } - /** - * @test - */ - public function parseWebhookEventMissingType(): void + public function testParseWebhookEventMissingType(): void { $this->expectException(\InvalidArgumentException::class); $this->expectExceptionMessage("missing 'type' field"); Webhook::parseWebhookEvent('{"foo":"bar"}'); } - /** - * @test - */ - public function parseWebhookEventInvalidJson(): void + public function testParseWebhookEventInvalidJson(): void { $this->expectException(\InvalidArgumentException::class); $this->expectExceptionMessage('Invalid JSON'); Webhook::parseWebhookEvent('not json'); } - - private function computeSignature(string $body, string $secret): string - { - return hash_hmac('sha256', $body, $secret); - } }