Skip to content

Commit

Permalink
feat: multi tenancy moderation configuration support (#1426)
Browse files Browse the repository at this point in the history
  • Loading branch information
vishalnarkhede authored Dec 23, 2024
1 parent 83ab184 commit ef8736d
Show file tree
Hide file tree
Showing 2 changed files with 142 additions and 9 deletions.
13 changes: 7 additions & 6 deletions src/moderation.ts
Original file line number Diff line number Diff line change
Expand Up @@ -20,6 +20,7 @@ import {
Pager,
CustomCheckFlag,
ReviewQueueItem,
QueryConfigsResponse,
} from './types';
import { StreamChat } from './client';
import { normalizeQuerySort } from './utils';
Expand Down Expand Up @@ -174,20 +175,20 @@ export class Moderation<StreamChatGenerics extends ExtendableGenerics = DefaultG
* Upsert moderation config
* @param {Object} config Moderation config to be upserted
*/
async upsertConfig(config: ModerationConfig = {}) {
async upsertConfig(config: ModerationConfig) {
return await this.client.post<UpsertConfigResponse>(this.client.baseURL + '/api/v2/moderation/config', config);
}

/**
* Get moderation config
* @param {string} key Key for which moderation config is to be fetched
*/
async getConfig(key: string) {
return await this.client.get<GetConfigResponse>(this.client.baseURL + '/api/v2/moderation/config/' + key);
async getConfig(key: string, data?: { team?: string }) {
return await this.client.get<GetConfigResponse>(this.client.baseURL + '/api/v2/moderation/config/' + key, data);
}

async deleteConfig(key: string) {
return await this.client.delete(this.client.baseURL + '/api/v2/moderation/config/' + key);
async deleteConfig(key: string, data?: { team?: string }) {
return await this.client.delete(this.client.baseURL + '/api/v2/moderation/config/' + key, data);
}

/**
Expand All @@ -201,7 +202,7 @@ export class Moderation<StreamChatGenerics extends ExtendableGenerics = DefaultG
sort: QueryModerationConfigsSort,
options: Pager = {},
) {
return await this.client.post(this.client.baseURL + '/api/v2/moderation/configs', {
return await this.client.post<QueryConfigsResponse>(this.client.baseURL + '/api/v2/moderation/configs', {
filter: filterConditions,
sort,
...options,
Expand Down
138 changes: 135 additions & 3 deletions src/types.ts
Original file line number Diff line number Diff line change
Expand Up @@ -3466,6 +3466,8 @@ export type QueryModerationConfigsFilters = QueryFilters<
created_at?: PrimitiveFilter<string>;
} & {
updated_at?: PrimitiveFilter<string>;
} & {
team?: string;
}
>;

Expand Down Expand Up @@ -3535,14 +3537,35 @@ export type ReviewQueueResponse = {
prev?: string;
};

export type ModerationConfig = {};
export type ModerationConfig = {
key: string;
ai_image_config?: AIImageConfig;
ai_text_config?: AITextConfig;
ai_video_config?: AIVideoConfig;
automod_platform_circumvention_config?: AutomodPlatformCircumventionConfig;
automod_semantic_filters_config?: AutomodSemanticFiltersConfig;
automod_toxicity_config?: AutomodToxicityConfig;
block_list_config?: BlockListConfig;
team?: string;
};

export type ModerationConfigResponse = ModerationConfig & {
created_at: string;
updated_at: string;
};

export type GetConfigResponse = {
config: ModerationConfig;
config: ModerationConfigResponse;
};

export type QueryConfigsResponse = {
configs: ModerationConfigResponse[];
next?: string;
prev?: string;
};

export type UpsertConfigResponse = {
config: ModerationConfig;
config: ModerationConfigResponse;
};

export type ModerationFlagOptions = {
Expand All @@ -3567,3 +3590,112 @@ export type AIState =
| 'AI_STATE_THINKING'
| 'AI_STATE_GENERATING'
| (string & {});

export type ModerationActionType = 'flag' | 'shadow' | 'remove' | 'bounce' | 'bounce_flag' | 'bounce_remove';

export type AutomodRule = {
action: ModerationActionType;
label: string;
threshold: number;
};

export type BlockListRule = {
action: ModerationActionType;
name?: string;
};

export type BlockListConfig = {
enabled: boolean;
rules: BlockListRule[];
async?: boolean;
};

export type AutomodToxicityConfig = {
enabled: boolean;
rules: AutomodRule[];
async?: boolean;
};

export type AutomodPlatformCircumventionConfig = {
enabled: boolean;
rules: AutomodRule[];
async?: boolean;
};

export type AutomodSemanticFiltersRule = {
action: ModerationActionType;
name: string;
threshold: number;
};

export type AutomodSemanticFiltersConfig = {
enabled: boolean;
rules: AutomodSemanticFiltersRule[];
async?: boolean;
};

export type AITextSeverityRule = {
action: ModerationActionType;
severity: 'low' | 'medium' | 'high' | 'critical';
};

export type AITextRule = {
label: string;
action?: ModerationActionType;
severity_rules?: AITextSeverityRule[];
};

export type AITextConfig = {
enabled: boolean;
rules: AITextRule[];
async?: boolean;
profile?: string;
severity_rules?: AITextSeverityRule[]; // Deprecated: use rules instead
};

export type AIImageRule = {
action: ModerationActionType;
label: string;
min_confidence?: number;
};

export type AIImageConfig = {
enabled: boolean;
rules: AIImageRule[];
async?: boolean;
};

export type AIVideoRule = {
action: ModerationActionType;
label: string;
min_confidence?: number;
};

export type AIVideoConfig = {
enabled: boolean;
rules: AIVideoRule[];
async?: boolean;
};

export type VelocityFilterConfigRule = {
action: 'flag' | 'shadow' | 'remove' | 'ban';
ban_duration?: number;
cascading_action?: 'flag' | 'shadow' | 'remove' | 'ban';
cascading_threshold?: number;
check_message_context?: boolean;
fast_spam_threshold?: number;
fast_spam_ttl?: number;
ip_ban?: boolean;
shadow_ban?: boolean;
slow_spam_ban_duration?: number;
slow_spam_threshold?: number;
slow_spam_ttl?: number;
};

export type VelocityFilterConfig = {
cascading_actions: boolean;
enabled: boolean;
first_message_only: boolean;
rules: VelocityFilterConfigRule[];
async?: boolean;
};

0 comments on commit ef8736d

Please sign in to comment.