diff --git a/moderation.go b/moderation.go new file mode 100644 index 0000000..3e1d7c4 --- /dev/null +++ b/moderation.go @@ -0,0 +1,196 @@ +// Code generated by GetStream internal OpenAPI code generator. DO NOT EDIT. +package getstream + +import ( + "context" +) + +type ModerationClient struct { + client *Client +} + +func NewModerationClient(client *Client) *ModerationClient { + return &ModerationClient{ + client: client, + } +} + +// Ban a user from a channel or the entire app +func (c *ModerationClient) Ban(ctx context.Context, request *BanRequest) (*StreamResponse[BanResponse], error) { + var result BanResponse + res, err := MakeRequest[BanRequest, BanResponse](c.client, ctx, "POST", "/api/v2/moderation/ban", nil, request, &result, nil) + return res, err +} + +// Moderate multiple images in bulk using a CSV file +func (c *ModerationClient) BulkImageModeration(ctx context.Context, request *BulkImageModerationRequest) (*StreamResponse[BulkImageModerationResponse], error) { + var result BulkImageModerationResponse + res, err := MakeRequest[BulkImageModerationRequest, BulkImageModerationResponse](c.client, ctx, "POST", "/api/v2/moderation/bulk_image_moderation", nil, request, &result, nil) + return res, err +} + +// Run moderation checks on the provided content +func (c *ModerationClient) Check(ctx context.Context, request *CheckRequest) (*StreamResponse[CheckResponse], error) { + var result CheckResponse + res, err := MakeRequest[CheckRequest, CheckResponse](c.client, ctx, "POST", "/api/v2/moderation/check", nil, request, &result, nil) + return res, err +} + +// Create a new moderation configuration or update an existing one. Configure settings for content filtering, AI analysis, toxicity detection, and other moderation features. +func (c *ModerationClient) UpsertConfig(ctx context.Context, request *UpsertConfigRequest) (*StreamResponse[UpsertConfigResponse], error) { + var result UpsertConfigResponse + res, err := MakeRequest[UpsertConfigRequest, UpsertConfigResponse](c.client, ctx, "POST", "/api/v2/moderation/config", nil, request, &result, nil) + return res, err +} + +// Delete a specific moderation policy by its name +func (c *ModerationClient) DeleteConfig(ctx context.Context, key string, request *DeleteConfigRequest) (*StreamResponse[DeleteModerationConfigResponse], error) { + var result DeleteModerationConfigResponse + pathParams := map[string]string{ + "key": key, + } + params := extractQueryParams(request) + res, err := MakeRequest[any, DeleteModerationConfigResponse](c.client, ctx, "DELETE", "/api/v2/moderation/config/{key}", params, nil, &result, pathParams) + return res, err +} + +// Retrieve a specific moderation configuration by its key and team. This configuration contains settings for various moderation features like toxicity detection, AI analysis, and filtering rules. +func (c *ModerationClient) GetConfig(ctx context.Context, key string, request *GetConfigRequest) (*StreamResponse[GetConfigResponse], error) { + var result GetConfigResponse + pathParams := map[string]string{ + "key": key, + } + params := extractQueryParams(request) + res, err := MakeRequest[any, GetConfigResponse](c.client, ctx, "GET", "/api/v2/moderation/config/{key}", params, nil, &result, pathParams) + return res, err +} + +// Search and filter moderation configurations across your application. This endpoint is designed for building moderation dashboards and managing multiple configuration sets. +func (c *ModerationClient) QueryModerationConfigs(ctx context.Context, request *QueryModerationConfigsRequest) (*StreamResponse[QueryModerationConfigsResponse], error) { + var result QueryModerationConfigsResponse + res, err := MakeRequest[QueryModerationConfigsRequest, QueryModerationConfigsResponse](c.client, ctx, "POST", "/api/v2/moderation/configs", nil, request, &result, nil) + return res, err +} + +// Custom check, add your own AI model reports to the review queue +func (c *ModerationClient) CustomCheck(ctx context.Context, request *CustomCheckRequest) (*StreamResponse[CustomCheckResponse], error) { + var result CustomCheckResponse + res, err := MakeRequest[CustomCheckRequest, CustomCheckResponse](c.client, ctx, "POST", "/api/v2/moderation/custom_check", nil, request, &result, nil) + return res, err +} + +// Delete a specific moderation template by its name +func (c *ModerationClient) V2DeleteTemplate(ctx context.Context, request *V2DeleteTemplateRequest) (*StreamResponse[DeleteModerationTemplateResponse], error) { + var result DeleteModerationTemplateResponse + res, err := MakeRequest[any, DeleteModerationTemplateResponse](c.client, ctx, "DELETE", "/api/v2/moderation/feeds_moderation_template", nil, nil, &result, nil) + return res, err +} + +// Retrieve a list of feed moderation templates that define preset moderation rules and configurations. Limited to 100 templates per request. +func (c *ModerationClient) V2QueryTemplates(ctx context.Context, request *V2QueryTemplatesRequest) (*StreamResponse[QueryFeedModerationTemplatesResponse], error) { + var result QueryFeedModerationTemplatesResponse + res, err := MakeRequest[any, QueryFeedModerationTemplatesResponse](c.client, ctx, "GET", "/api/v2/moderation/feeds_moderation_template", nil, nil, &result, nil) + return res, err +} + +// Upsert feeds template for moderation +func (c *ModerationClient) V2UpsertTemplate(ctx context.Context, request *V2UpsertTemplateRequest) (*StreamResponse[UpsertModerationTemplateResponse], error) { + var result UpsertModerationTemplateResponse + res, err := MakeRequest[V2UpsertTemplateRequest, UpsertModerationTemplateResponse](c.client, ctx, "POST", "/api/v2/moderation/feeds_moderation_template", nil, request, &result, nil) + return res, err +} + +// Flag any type of content (messages, users, channels, activities) for moderation review. Supports custom content types and additional metadata for flagged content. +func (c *ModerationClient) Flag(ctx context.Context, request *FlagRequest) (*StreamResponse[FlagResponse], error) { + var result FlagResponse + res, err := MakeRequest[FlagRequest, FlagResponse](c.client, ctx, "POST", "/api/v2/moderation/flag", nil, request, &result, nil) + return res, err +} + +// Query flags associated with moderation items. This is used for building a moderation dashboard. +func (c *ModerationClient) QueryModerationFlags(ctx context.Context, request *QueryModerationFlagsRequest) (*StreamResponse[QueryModerationFlagsResponse], error) { + var result QueryModerationFlagsResponse + res, err := MakeRequest[QueryModerationFlagsRequest, QueryModerationFlagsResponse](c.client, ctx, "POST", "/api/v2/moderation/flags", nil, request, &result, nil) + return res, err +} + +// Search and filter moderation action logs with support for pagination. View the history of moderation actions taken, including who performed them and when. +func (c *ModerationClient) QueryModerationLogs(ctx context.Context, request *QueryModerationLogsRequest) (*StreamResponse[QueryModerationLogsResponse], error) { + var result QueryModerationLogsResponse + res, err := MakeRequest[QueryModerationLogsRequest, QueryModerationLogsResponse](c.client, ctx, "POST", "/api/v2/moderation/logs", nil, request, &result, nil) + return res, err +} + +// Create or update a moderation rule that can apply app-wide or to specific moderation configs +func (c *ModerationClient) UpsertModerationRule(ctx context.Context, request *UpsertModerationRuleRequest) (*StreamResponse[UpsertModerationRuleResponse], error) { + var result UpsertModerationRuleResponse + res, err := MakeRequest[UpsertModerationRuleRequest, UpsertModerationRuleResponse](c.client, ctx, "POST", "/api/v2/moderation/moderation_rule", nil, request, &result, nil) + return res, err +} + +// Delete an existing moderation rule +func (c *ModerationClient) DeleteModerationRule(ctx context.Context, request *DeleteModerationRuleRequest) (*StreamResponse[DeleteModerationRuleResponse], error) { + var result DeleteModerationRuleResponse + res, err := MakeRequest[any, DeleteModerationRuleResponse](c.client, ctx, "DELETE", "/api/v2/moderation/moderation_rule/{id}", nil, nil, &result, nil) + return res, err +} + +// Get a specific moderation rule by ID +func (c *ModerationClient) GetModerationRule(ctx context.Context, request *GetModerationRuleRequest) (*StreamResponse[GetModerationRuleResponse], error) { + var result GetModerationRuleResponse + res, err := MakeRequest[any, GetModerationRuleResponse](c.client, ctx, "GET", "/api/v2/moderation/moderation_rule/{id}", nil, nil, &result, nil) + return res, err +} + +// Search and filter moderation rules across your application. This endpoint is designed for building moderation dashboards and managing multiple rule sets. +func (c *ModerationClient) QueryModerationRules(ctx context.Context, request *QueryModerationRulesRequest) (*StreamResponse[QueryModerationRulesResponse], error) { + var result QueryModerationRulesResponse + res, err := MakeRequest[QueryModerationRulesRequest, QueryModerationRulesResponse](c.client, ctx, "POST", "/api/v2/moderation/moderation_rules", nil, request, &result, nil) + return res, err +} + +// Mute a user. Mutes are generally not visible to the user you mute, while block is something you notice. +func (c *ModerationClient) Mute(ctx context.Context, request *MuteRequest) (*StreamResponse[MuteResponse], error) { + var result MuteResponse + res, err := MakeRequest[MuteRequest, MuteResponse](c.client, ctx, "POST", "/api/v2/moderation/mute", nil, request, &result, nil) + return res, err +} + +// Query review queue items allows you to filter the review queue items. This is used for building a moderation dashboard. +func (c *ModerationClient) QueryReviewQueue(ctx context.Context, request *QueryReviewQueueRequest) (*StreamResponse[QueryReviewQueueResponse], error) { + var result QueryReviewQueueResponse + res, err := MakeRequest[QueryReviewQueueRequest, QueryReviewQueueResponse](c.client, ctx, "POST", "/api/v2/moderation/review_queue", nil, request, &result, nil) + return res, err +} + +// Retrieve a specific review queue item by its ID +func (c *ModerationClient) GetReviewQueueItem(ctx context.Context, id string, request *GetReviewQueueItemRequest) (*StreamResponse[GetReviewQueueItemResponse], error) { + var result GetReviewQueueItemResponse + pathParams := map[string]string{ + "id": id, + } + res, err := MakeRequest[any, GetReviewQueueItemResponse](c.client, ctx, "GET", "/api/v2/moderation/review_queue/{id}", nil, nil, &result, pathParams) + return res, err +} + +// Take action on flagged content, such as marking content as safe, deleting content, banning users, or executing custom moderation actions. Supports various action types with configurable parameters. +func (c *ModerationClient) SubmitAction(ctx context.Context, request *SubmitActionRequest) (*StreamResponse[SubmitActionResponse], error) { + var result SubmitActionResponse + res, err := MakeRequest[SubmitActionRequest, SubmitActionResponse](c.client, ctx, "POST", "/api/v2/moderation/submit_action", nil, request, &result, nil) + return res, err +} + +// Unban a user from a channel or globally. +func (c *ModerationClient) Unban(ctx context.Context, request *UnbanRequest) (*StreamResponse[UnbanResponse], error) { + var result UnbanResponse + params := extractQueryParams(request) + res, err := MakeRequest[UnbanRequest, UnbanResponse](c.client, ctx, "POST", "/api/v2/moderation/unban", params, request, &result, nil) + return res, err +} + +// Unmute a user +func (c *ModerationClient) Unmute(ctx context.Context, request *UnmuteRequest) (*StreamResponse[UnmuteResponse], error) { + var result UnmuteResponse + res, err := MakeRequest[UnmuteRequest, UnmuteResponse](c.client, ctx, "POST", "/api/v2/moderation/unmute", nil, request, &result, nil) + return res, err +} diff --git a/moderation_integration_test.go b/moderation_integration_test.go new file mode 100644 index 0000000..407836d --- /dev/null +++ b/moderation_integration_test.go @@ -0,0 +1,187 @@ +// Code generated by GetStream internal OpenAPI code generator. DO NOT EDIT. +package getstream_test + +import ( + "context" + "testing" + + "github.com/GetStream/getstream-go/v3" + "github.com/stretchr/testify/require" +) + +func TestModerationBanWithReason(t *testing.T) { + client, err := getstream.NewClient("key", "secret", getstream.WithHTTPClient(&StubHTTPClient{})) + require.NoError(t, err) + + // snippet-start: BanWithReason + request := &getstream.BanRequest{ + TargetUserID: "user123", + Reason: getstream.PtrTo("spam"), + Timeout: getstream.PtrTo(60), // 60 minutes + BannedByID: getstream.PtrTo("moderator456"), + } + + _, err = client.Moderation().Ban(context.Background(), request) + // snippet-stop: BanWithReason + require.NoError(t, err) +} + +func TestModerationBanFromChannel(t *testing.T) { + client, err := getstream.NewClient("key", "secret", getstream.WithHTTPClient(&StubHTTPClient{})) + require.NoError(t, err) + + // snippet-start: BanFromChannel + request := &getstream.BanRequest{ + TargetUserID: "user123", + ChannelCid: getstream.PtrTo("messaging:general"), + Reason: getstream.PtrTo("inappropriate content"), + BannedByID: getstream.PtrTo("moderator456"), + } + + _, err = client.Moderation().Ban(context.Background(), request) + // snippet-stop: BanFromChannel + require.NoError(t, err) +} + +func TestModerationMuteUser(t *testing.T) { + client, err := getstream.NewClient("key", "secret", getstream.WithHTTPClient(&StubHTTPClient{})) + require.NoError(t, err) + + // snippet-start: MuteUser + request := &getstream.MuteRequest{ + TargetIds: []string{"user123", "user456"}, + Timeout: getstream.PtrTo(30), // 30 minutes + UserID: getstream.PtrTo("moderator789"), + } + + _, err = client.Moderation().Mute(context.Background(), request) + // snippet-stop: MuteUser + require.NoError(t, err) +} + +func TestModerationFlagMessage(t *testing.T) { + client, err := getstream.NewClient("key", "secret", getstream.WithHTTPClient(&StubHTTPClient{})) + require.NoError(t, err) + + // snippet-start: FlagMessage + request := &getstream.FlagRequest{ + EntityType: "message", + EntityID: "message123", + EntityCreatorID: getstream.PtrTo("user456"), + Reason: getstream.PtrTo("harassment"), + UserID: getstream.PtrTo("reporter789"), + } + + _, err = client.Moderation().Flag(context.Background(), request) + // snippet-stop: FlagMessage + require.NoError(t, err) +} + +func TestModerationFlagUser(t *testing.T) { + client, err := getstream.NewClient("key", "secret", getstream.WithHTTPClient(&StubHTTPClient{})) + require.NoError(t, err) + + // snippet-start: FlagUser + request := &getstream.FlagRequest{ + EntityType: "user", + EntityID: "user123", + EntityCreatorID: getstream.PtrTo("user123"), + Reason: getstream.PtrTo("spam"), + UserID: getstream.PtrTo("reporter456"), + } + + _, err = client.Moderation().Flag(context.Background(), request) + // snippet-stop: FlagUser + require.NoError(t, err) +} + +func TestModerationCheckContent(t *testing.T) { + client, err := getstream.NewClient("key", "secret", getstream.WithHTTPClient(&StubHTTPClient{})) + require.NoError(t, err) + + // snippet-start: CheckContent + request := &getstream.CheckRequest{ + EntityType: "message", + EntityID: "message123", + EntityCreatorID: "user456", + ModerationPayload: &getstream.ModerationPayload{ + Texts: []string{"This is some content to moderate"}, + }, + } + + _, err = client.Moderation().Check(context.Background(), request) + // snippet-stop: CheckContent + require.NoError(t, err) +} + +func TestModerationSubmitModerationAction(t *testing.T) { + client, err := getstream.NewClient("key", "secret", getstream.WithHTTPClient(&StubHTTPClient{})) + require.NoError(t, err) + + // snippet-start: SubmitModerationAction + request := &getstream.SubmitActionRequest{ + ItemID: "review_item_123", + ActionType: "mark_reviewed", + UserID: getstream.PtrTo("moderator456"), + } + + _, err = client.Moderation().SubmitAction(context.Background(), request) + // snippet-stop: SubmitModerationAction + require.NoError(t, err) +} + +func TestModerationQueryReviewQueueWithFilter(t *testing.T) { + client, err := getstream.NewClient("key", "secret", getstream.WithHTTPClient(&StubHTTPClient{})) + require.NoError(t, err) + + // snippet-start: QueryReviewQueueWithFilter + request := &getstream.QueryReviewQueueRequest{ + Filter: map[string]interface{}{ + "status": "pending", + }, + Limit: getstream.PtrTo(25), + } + + _, err = client.Moderation().QueryReviewQueue(context.Background(), request) + // snippet-stop: QueryReviewQueueWithFilter + require.NoError(t, err) +} + +func TestModerationCreateConfig(t *testing.T) { + client, err := getstream.NewClient("key", "secret", getstream.WithHTTPClient(&StubHTTPClient{})) + require.NoError(t, err) + + // snippet-start: CreateModerationConfig + request := &getstream.UpsertConfigRequest{ + Key: "chat:messaging:general", + AutomodToxicityConfig: &getstream.AutomodToxicityConfig{ + Enabled: getstream.PtrTo(true), + Rules: []getstream.AutomodRule{ + { + Label: "toxic", + Threshold: 0.8, + Action: "remove", + }, + }, + }, + } + + _, err = client.Moderation().UpsertConfig(context.Background(), request) + // snippet-stop: CreateModerationConfig + require.NoError(t, err) +} + +func TestModerationUnbanUser(t *testing.T) { + client, err := getstream.NewClient("key", "secret", getstream.WithHTTPClient(&StubHTTPClient{})) + require.NoError(t, err) + + // snippet-start: UnbanUser + request := &getstream.UnbanRequest{ + TargetUserID: "user123", + UnbannedByID: getstream.PtrTo("moderator456"), + } + + _, err = client.Moderation().Unban(context.Background(), request) + // snippet-stop: UnbanUser + require.NoError(t, err) +} diff --git a/stream.go b/stream.go index 6f78859..df0465d 100644 --- a/stream.go +++ b/stream.go @@ -2,9 +2,10 @@ package getstream type Stream struct { *Client - chat *ChatClient - video *VideoClient - feeds *FeedsClient + chat *ChatClient + video *VideoClient + feeds *FeedsClient + moderation *ModerationClient } func NewClientFromEnvVars(options ...ClientOption) (*Stream, error) { @@ -67,3 +68,11 @@ func (s *Stream) Feeds() *FeedsClient { } return s.feeds } + +// Moderation client +func (s *Stream) Moderation() *ModerationClient { + if s.moderation == nil { + s.moderation = NewModerationClient(s.Client) + } + return s.moderation +}