Skip to content

Commit e555d7a

Browse files
varbhatnijeesh-streamgithub-actions[bot]
authored
[MOD-436]: Add Moderation v2 API Support (#154)
* Add Moderation v2 API Support * fix rubocop errors * fix rubocop errors * seperate moderation into different file * add tests * Correct the test * Correct the tests * Correct the tests * Simplify the test * test change - 1 * test change - 2 * test change - 3 * test change - 4 * update the tests * fix sorbet error * remove puts * Update lib/stream-chat/moderation.rb Co-authored-by: nijeesh-stream <[email protected]> * Correct types * Correct types * Correct types * Make entity_creator_id optional * Fix type signatures * Fix type signatures * Update spec/client_spec.rb Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com> * Seperate moderation spec to a different file --------- Co-authored-by: nijeesh-stream <[email protected]> Co-authored-by: github-actions[bot] <41898282+github-actions[bot]@users.noreply.github.com>
1 parent ac8f3d5 commit e555d7a

File tree

3 files changed

+456
-0
lines changed

3 files changed

+456
-0
lines changed

lib/stream-chat/client.rb

Lines changed: 5 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -14,6 +14,7 @@
1414
require 'stream-chat/version'
1515
require 'stream-chat/util'
1616
require 'stream-chat/types'
17+
require 'stream-chat/moderation'
1718

1819
module StreamChat
1920
DEFAULT_BLOCKLIST = 'profanity_en_2020_v1'
@@ -35,6 +36,9 @@ class Client
3536
sig { returns(Faraday::Connection) }
3637
attr_reader :conn
3738

39+
sig { returns(Moderation) }
40+
attr_reader :moderation
41+
3842
# initializes a Stream Chat API Client
3943
#
4044
# @param [string] api_key your application api_key
@@ -64,6 +68,7 @@ def initialize(api_key, api_secret, timeout = nil, **options)
6468
end
6569
end
6670
@conn = T.let(conn, Faraday::Connection)
71+
@moderation = T.let(Moderation.new(self), Moderation)
6772
end
6873

6974
# initializes a Stream Chat API Client from STREAM_KEY and STREAM_SECRET

lib/stream-chat/moderation.rb

Lines changed: 246 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -0,0 +1,246 @@
1+
# typed: strict
2+
# frozen_string_literal: true
3+
4+
require 'stream-chat/client'
5+
require 'stream-chat/errors'
6+
require 'stream-chat/util'
7+
require 'stream-chat/types'
8+
9+
module StreamChat
10+
# Moderation class provides all the endpoints related to moderation v2
11+
class Moderation
12+
extend T::Sig
13+
14+
MODERATION_ENTITY_TYPES = T.let(
15+
{
16+
user: 'stream:user',
17+
message: 'stream:chat:v1:message'
18+
}.freeze,
19+
T::Hash[Symbol, String]
20+
)
21+
22+
sig { params(client: Client).void }
23+
def initialize(client)
24+
@client = client
25+
end
26+
27+
# Flags a user with a reason
28+
#
29+
# @param [string] flagged_user_id User ID to be flagged
30+
# @param [string] reason Reason for flagging the user
31+
# @param [Hash] options Additional options for flagging the user
32+
# @option options [String] :user_id User ID of the user who is flagging the target user
33+
# @option options [Hash] :custom Additional data to be stored with the flag
34+
sig { params(flagged_user_id: String, reason: String, options: T.untyped).returns(StreamChat::StreamResponse) }
35+
def flag_user(flagged_user_id, reason, **options)
36+
flag(T.must(MODERATION_ENTITY_TYPES[:user]), flagged_user_id, reason, **options)
37+
end
38+
39+
# Flags a message with a reason
40+
#
41+
# @param [string] message_id Message ID to be flagged
42+
# @param [string] reason Reason for flagging the message
43+
# @param [Hash] options Additional options for flagging the message
44+
# @option options [String] :user_id User ID of the user who is flagging the target message
45+
# @option options [Hash] :custom Additional data to be stored with the flag
46+
sig { params(message_id: String, reason: String, options: T.untyped).returns(StreamChat::StreamResponse) }
47+
def flag_message(message_id, reason, **options)
48+
flag(T.must(MODERATION_ENTITY_TYPES[:message]), message_id, reason, **options)
49+
end
50+
51+
# Flags an entity with a reason
52+
#
53+
# @param [string] entity_type Entity type to be flagged
54+
# @param [string] entity_id Entity ID to be flagged
55+
# @param [string] reason Reason for flagging the entity
56+
# @param [string] entity_creator_id User ID of the entity creator (optional)
57+
# @param [Hash] options Additional options for flagging the entity
58+
# @option options [String] :user_id User ID of the user who is flagging the target entity
59+
# @option options [Hash] :moderation_payload Content to be flagged
60+
# @option options [Hash] :custom Additional data to be stored with the flag
61+
sig { params(entity_type: String, entity_id: String, reason: String, entity_creator_id: String, options: T.untyped).returns(StreamChat::StreamResponse) }
62+
def flag(entity_type, entity_id, reason, entity_creator_id: '', **options)
63+
@client.post('api/v2/moderation/flag', data: {
64+
entity_type: entity_type,
65+
entity_id: entity_id,
66+
entity_creator_id: entity_creator_id,
67+
reason: reason,
68+
**options
69+
})
70+
end
71+
72+
# Mutes a user
73+
#
74+
# @param [string] target_id User ID to be muted
75+
# @param [Hash] options Additional options for muting the user
76+
# @option options [String] :user_id User ID of the user who is muting the target user
77+
# @option options [Integer] :timeout Timeout for the mute in minutes
78+
sig { params(target_id: String, options: T.untyped).returns(StreamChat::StreamResponse) }
79+
def mute_user(target_id, **options)
80+
@client.post('api/v2/moderation/mute', data: {
81+
target_ids: [target_id],
82+
**options
83+
})
84+
end
85+
86+
# Unmutes a user
87+
#
88+
# @param [string] target_id User ID to be unmuted
89+
# @param [Hash] options Additional options for unmuting the user
90+
# @option options [String] :user_id User ID of the user who is unmuting the target user
91+
sig { params(target_id: String, options: T.untyped).returns(StreamChat::StreamResponse) }
92+
def unmute_user(target_id, **options)
93+
@client.post('api/v2/moderation/unmute', data: {
94+
target_ids: [target_id],
95+
**options
96+
})
97+
end
98+
99+
# Gets moderation report for a user
100+
#
101+
# @param [string] user_id User ID for which moderation report is to be fetched
102+
# @param [Hash] options Additional options for fetching the moderation report
103+
# @option options [Boolean] :create_user_if_not_exists Create user if not exists
104+
# @option options [Boolean] :include_user_blocks Include user blocks
105+
# @option options [Boolean] :include_user_mutes Include user mutes
106+
sig { params(user_id: String, options: T.untyped).returns(StreamChat::StreamResponse) }
107+
def get_user_moderation_report(user_id, **options)
108+
@client.get('api/v2/moderation/user_report', params: {
109+
user_id: user_id,
110+
**options
111+
})
112+
end
113+
114+
# Queries review queue
115+
#
116+
# @param [Hash] filter_conditions Filter conditions for querying review queue
117+
# @param [Array] sort Sort conditions for querying review queue
118+
# @param [Hash] options Pagination options for querying review queue
119+
sig { params(filter_conditions: T.untyped, sort: T.untyped, options: T.untyped).returns(StreamChat::StreamResponse) }
120+
def query_review_queue(filter_conditions = {}, sort = [], **options)
121+
@client.post('api/v2/moderation/review_queue', data: {
122+
filter: filter_conditions,
123+
sort: StreamChat.get_sort_fields(sort),
124+
**options
125+
})
126+
end
127+
128+
# Upserts moderation config
129+
#
130+
# @param [Hash] config Moderation config to be upserted
131+
sig { params(config: T.untyped).returns(StreamChat::StreamResponse) }
132+
def upsert_config(config)
133+
@client.post('api/v2/moderation/config', data: config)
134+
end
135+
136+
# Gets moderation config
137+
#
138+
# @param [string] key Key for which moderation config is to be fetched
139+
# @param [Hash] data Additional data
140+
# @option data [String] :team Team name
141+
sig { params(key: String, data: T.untyped).returns(StreamChat::StreamResponse) }
142+
def get_config(key, data = {})
143+
@client.get("api/v2/moderation/config/#{key}", params: data)
144+
end
145+
146+
# Deletes moderation config
147+
#
148+
# @param [string] key Key for which moderation config is to be deleted
149+
# @param [Hash] data Additional data
150+
# @option data [String] :team Team name
151+
sig { params(key: String, data: T.untyped).returns(StreamChat::StreamResponse) }
152+
def delete_config(key, data = {})
153+
@client.delete("api/v2/moderation/config/#{key}", params: data)
154+
end
155+
156+
# Queries moderation configs
157+
#
158+
# @param [Hash] filter_conditions Filter conditions for querying moderation configs
159+
# @param [Array] sort Sort conditions for querying moderation configs
160+
# @param [Hash] options Additional options for querying moderation configs
161+
sig { params(filter_conditions: T.untyped, sort: T.untyped, options: T.untyped).returns(StreamChat::StreamResponse) }
162+
def query_configs(filter_conditions, sort, **options)
163+
@client.post('api/v2/moderation/configs', data: {
164+
filter: filter_conditions,
165+
sort: sort,
166+
**options
167+
})
168+
end
169+
170+
# Submits a moderation action
171+
#
172+
# @param [string] action_type Type of action to submit
173+
# @param [string] item_id ID of the item to submit action for
174+
# @param [Hash] options Additional options for submitting the action
175+
sig { params(action_type: String, item_id: String, options: T.untyped).returns(StreamChat::StreamResponse) }
176+
def submit_action(action_type, item_id, **options)
177+
@client.post('api/v2/moderation/submit_action', data: {
178+
action_type: action_type,
179+
item_id: item_id,
180+
**options
181+
})
182+
end
183+
184+
# rubocop:disable Metrics/ParameterLists
185+
# Checks content for moderation
186+
#
187+
# @param [string] entity_type Type of entity to be checked E.g., stream:user, stream:chat:v1:message, or any custom string
188+
# @param [string] entity_id ID of the entity to be checked. This is mainly for tracking purposes
189+
# @param [string] entity_creator_id ID of the entity creator
190+
# @param [Hash] moderation_payload Content to be checked for moderation
191+
# @option moderation_payload [Array<String>] :texts Array of texts to be checked for moderation
192+
# @option moderation_payload [Array<String>] :images Array of images to be checked for moderation
193+
# @option moderation_payload [Array<String>] :videos Array of videos to be checked for moderation
194+
# @option moderation_payload [Hash] :custom Additional custom data
195+
# @param [string] config_key Key of the moderation config to use
196+
# @param [Hash] options Additional options
197+
# @option options [Boolean] :force_sync Force synchronous check
198+
sig do
199+
params(
200+
entity_type: String,
201+
entity_id: String,
202+
moderation_payload: T::Hash[Symbol, T.any(T::Array[String], T::Hash[String, T.untyped])],
203+
config_key: String,
204+
entity_creator_id: String,
205+
options: T::Hash[Symbol, T::Boolean]
206+
).returns(StreamChat::StreamResponse)
207+
end
208+
def check(entity_type, entity_id, moderation_payload, config_key, entity_creator_id: '', options: {})
209+
@client.post('api/v2/moderation/check', data: {
210+
entity_type: entity_type,
211+
entity_id: entity_id,
212+
entity_creator_id: entity_creator_id,
213+
moderation_payload: moderation_payload,
214+
config_key: config_key,
215+
options: options
216+
})
217+
end
218+
# rubocop:enable Metrics/ParameterLists
219+
# Adds custom flags to an entity
220+
#
221+
# @param [string] entity_type Type of entity to be checked
222+
# @param [string] entity_id ID of the entity to be checked
223+
# @param [string] entity_creator_id ID of the entity creator
224+
# @param [Hash] moderation_payload Content to be checked for moderation
225+
# @param [Array] flags Array of custom flags to add
226+
sig { params(entity_type: String, entity_id: String, moderation_payload: T.untyped, flags: T::Array[T.untyped], entity_creator_id: String).returns(StreamChat::StreamResponse) }
227+
def add_custom_flags(entity_type, entity_id, moderation_payload, flags, entity_creator_id: '')
228+
@client.post('api/v2/moderation/custom_check', data: {
229+
entity_type: entity_type,
230+
entity_id: entity_id,
231+
entity_creator_id: entity_creator_id,
232+
moderation_payload: moderation_payload,
233+
flags: flags
234+
})
235+
end
236+
237+
# Adds custom flags to a message
238+
#
239+
# @param [string] message_id Message ID to be flagged
240+
# @param [Array] flags Array of custom flags to add
241+
sig { params(message_id: String, flags: T::Array[T.untyped]).returns(StreamChat::StreamResponse) }
242+
def add_custom_message_flags(message_id, flags)
243+
add_custom_flags(T.must(MODERATION_ENTITY_TYPES[:message]), message_id, {}, flags)
244+
end
245+
end
246+
end

0 commit comments

Comments
 (0)