From 8e5b67dbde4f5965b1c334ab47b7c455c5b02504 Mon Sep 17 00:00:00 2001 From: nijeeshjoshy Date: Tue, 1 Apr 2025 17:10:30 +0200 Subject: [PATCH 1/7] feat: add deactivate_users method to StreamChat client and corresponding tests --- lib/stream-chat/client.rb | 7 +++++++ spec/client_spec.rb | 6 ++++++ 2 files changed, 13 insertions(+) diff --git a/lib/stream-chat/client.rb b/lib/stream-chat/client.rb index 2c0e13f..f5affb3 100644 --- a/lib/stream-chat/client.rb +++ b/lib/stream-chat/client.rb @@ -280,6 +280,13 @@ def deactivate_user(user_id, **options) post("users/#{user_id}/deactivate", params: options) end + + # Deactivates a users + sig { params(user_ids: T::Array[String], options: T.untyped).returns(StreamChat::StreamResponse) } + def deactivate_users(user_ids, **options) + post("users/deactivate", data: { user_ids: user_ids, **options }) + end + # Reactivates a deactivated user. Use deactivate_user to deactivate a user. sig { params(user_id: String, options: T.untyped).returns(StreamChat::StreamResponse) } def reactivate_user(user_id, **options) diff --git a/spec/client_spec.rb b/spec/client_spec.rb index cd4f87b..c9fce48 100644 --- a/spec/client_spec.rb +++ b/spec/client_spec.rb @@ -169,6 +169,12 @@ def loop_times(times) expect(response['user']['id']).to eq(@random_user[:id]) end + it 'deactivates multiple users' do + response = @client.deactivate_users([@random_users[0][:id], @random_users[1][:id]]) + expect(response).to include 'users' + expect(response['users'].length).to eq(2) + end + it 'reactivates a user' do @client.deactivate_user(@random_user[:id]) response = @client.reactivate_user(@random_user[:id]) From bc0c1b1c94f5c672d5ff193e4a6e070650ae304b Mon Sep 17 00:00:00 2001 From: nijeeshjoshy Date: Wed, 2 Apr 2025 14:27:46 +0200 Subject: [PATCH 2/7] feat: implement draft message management in StreamChat - Added methods to create, get, and delete draft messages in the Channel class. - Introduced a method to query draft messages in the Client class. - Added corresponding tests for draft message functionality in channel_spec.rb and client_spec.rb. --- lib/stream-chat/channel.rb | 36 ++++++++++++++++++++++ lib/stream-chat/client.rb | 16 ++++++++++ spec/channel_spec.rb | 61 ++++++++++++++++++++++++++++++++++++++ spec/client_spec.rb | 45 ++++++++++++++++++++++++++++ 4 files changed, 158 insertions(+) diff --git a/lib/stream-chat/channel.rb b/lib/stream-chat/channel.rb index f910695..a4d6068 100644 --- a/lib/stream-chat/channel.rb +++ b/lib/stream-chat/channel.rb @@ -360,6 +360,42 @@ def delete_image(url) @client.delete("#{self.url}/image", params: { url: url }) end + # Creates or updates a draft message for this channel. + # + # @param [StringKeyHash] message The draft message content + # @param [String] user_id The ID of the user creating/updating the draft + # @param [String] parent_id Optional parent message ID for thread drafts + # @return [StreamChat::StreamResponse] + sig { params(message: StringKeyHash, user_id: String).returns(StreamChat::StreamResponse) } + def create_draft(message, user_id) + payload = { message: add_user_id(message, user_id) } + @client.post("#{url}/draft", data: payload) + end + + # Deletes a draft message for this channel. + # + # @param [String] user_id The ID of the user deleting the draft + # @param [String] parent_id Optional parent message ID for thread drafts + # @return [StreamChat::StreamResponse] + sig { params(user_id: String, parent_id: T.nilable(String)).returns(StreamChat::StreamResponse) } + def delete_draft(user_id, parent_id: nil) + params = { user_id: user_id } + params[:parent_id] = parent_id if parent_id + @client.delete("#{url}/draft", params: params) + end + + # Gets a draft message for this channel. + # + # @param [String] user_id The ID of the user getting the draft + # @param [String] parent_id Optional parent message ID for thread drafts + # @return [StreamChat::StreamResponse] + sig { params(user_id: String, parent_id: T.nilable(String)).returns(StreamChat::StreamResponse) } + def get_draft(user_id, parent_id: nil) + params = { user_id: user_id } + params[:parent_id] = parent_id if parent_id + @client.get("#{url}/draft", params: params) + end + private sig { params(payload: StringKeyHash, user_id: String).returns(StringKeyHash) } diff --git a/lib/stream-chat/client.rb b/lib/stream-chat/client.rb index f5affb3..14dbaed 100644 --- a/lib/stream-chat/client.rb +++ b/lib/stream-chat/client.rb @@ -790,6 +790,22 @@ def create_command(command) post('commands', data: command) end + # Queries draft messages for the current user. + # + # @param [String] user_id The ID of the user to query drafts for + # @param [StringKeyHash] filter Optional filter conditions for the query + # @param [Array] sort Optional sort parameters + # @param [Hash] options Additional query options + # @return [StreamChat::StreamResponse] + sig { params(user_id: String, filter: T.nilable(StringKeyHash), sort: T.nilable(T::Array[StringKeyHash]), options: T.untyped).returns(StreamChat::StreamResponse) } + def query_drafts(user_id, filter: nil, sort: nil, **options) + data = { user_id: user_id } + data['filter'] = filter if filter + data['sort'] = sort if sort + data.merge!(options) if options + post('drafts/query', data: data) + end + # Gets a comamnd. sig { params(name: String).returns(StreamChat::StreamResponse) } def get_command(name) diff --git a/spec/channel_spec.rb b/spec/channel_spec.rb index e5873c6..0962463 100644 --- a/spec/channel_spec.rb +++ b/spec/channel_spec.rb @@ -430,4 +430,65 @@ def loop_times(times) # Verify the custom field was unset expect(updated_msg['message']).not_to include 'custom_field' end + + it 'can create draft message' do + draft_message = { 'text' => 'This is a draft message' } + response = @channel.create_draft(draft_message, @random_user[:id]) + + expect(response).to include 'draft' + expect(response['draft']['message']['text']).to eq 'This is a draft message' + expect(response['draft']['channel_cid']).to eq @channel.cid + end + + it 'can get draft message' do + # First create a draft + draft_message = { 'text' => 'This is a draft to retrieve' } + @channel.create_draft(draft_message, @random_user[:id]) + + # Then get the draft + response = @channel.get_draft(@random_user[:id]) + + expect(response).to include 'draft' + expect(response['draft']['message']['text']).to eq 'This is a draft to retrieve' + expect(response['draft']['channel_cid']).to eq @channel.cid + end + + it 'can delete draft message' do + # First create a draft + draft_message = { 'text' => 'This is a draft to delete' } + @channel.create_draft(draft_message, @random_user[:id]) + + # Then delete the draft + @channel.delete_draft(@random_user[:id]) + + # Verify it's deleted by trying to get it + expect { @channel.get_draft(@random_user[:id]) }.to raise_error(StreamChat::StreamAPIException) + end + + it 'can create and manage thread draft' do + # First create a parent message + msg = @channel.send_message({ 'text' => 'Parent message' }, @random_user[:id]) + parent_id = msg['message']['id'] + + # Create a draft reply + draft_reply = { 'text' => 'This is a draft reply', 'parent_id' => parent_id } + response = @channel.create_draft(draft_reply, @random_user[:id]) + + expect(response).to include 'draft' + expect(response['draft']['message']['text']).to eq 'This is a draft reply' + expect(response['draft']['parent_id']).to eq parent_id + + # Get the draft reply + response = @channel.get_draft(@random_user[:id], parent_id: parent_id) + + expect(response).to include 'draft' + expect(response['draft']['message']['text']).to eq 'This is a draft reply' + expect(response['draft']['parent_id']).to eq parent_id + + # Delete the draft reply + @channel.delete_draft(@random_user[:id], parent_id: parent_id) + + # Verify it's deleted + expect { @channel.get_draft(@random_user[:id], parent_id: parent_id) }.to raise_error(StreamChat::StreamAPIException) + end end diff --git a/spec/client_spec.rb b/spec/client_spec.rb index c9fce48..dc9a515 100644 --- a/spec/client_spec.rb +++ b/spec/client_spec.rb @@ -788,6 +788,51 @@ def loop_times(times) list_resp = @client.list_imports({ limit: 1 }) expect(list_resp['import_tasks'].length).to eq 1 end + + it 'can query drafts' do + # Create multiple drafts in different channels + draft1 = { 'text' => 'Draft in channel 1' } + @channel.create_draft(draft1, @random_user[:id]) + + # Create another channel with a draft + channel2 = @client.channel('messaging', data: {'members' => @random_users.map { |u| u[:id] } }) + channel2.create(@random_user[:id]) + + draft2 = { 'text' => 'Draft in channel 2' } + channel2.create_draft(draft2, @random_user[:id]) + + # Sort by created_at + sort = [{ 'field' => 'created_at', 'direction' => 1 }] + response = @client.query_drafts(@random_user[:id], sort: sort) + expect(response['drafts']).not_to be_empty + expect(response['drafts'].length).to eq(2) + expect(response['drafts'][0]['channel']['id']).to eq(@channel.id) + expect(response['drafts'][1]['channel']['id']).to eq(channel2.id) + + # Query for a specific channel + response = @client.query_drafts(@random_user[:id], filter: { 'channel_cid' => @channel.cid }) + expect(response['drafts']).not_to be_empty + expect(response['drafts'].length).to eq(1) + expect(response['drafts'][0]['channel']['id']).to eq(@channel.id) + + # Query all drafts for the user + response = @client.query_drafts(@random_user[:id]) + expect(response['drafts']).not_to be_empty + expect(response['drafts'].length).to eq(2) + + # Paginate + response = @client.query_drafts(@random_user[:id], sort: sort, limit: 1) + expect(response['drafts']).not_to be_empty + expect(response['drafts'].length).to eq(1) + expect(response['drafts'][0]['channel']['id']).to eq(@channel.id) + + # Cleanup + begin + channel2.delete + rescue StandardError + # Ignore errors if channel is already deleted + end + end end describe 'permissions' do From 6e5a576d70e4737f3a61b1448aed12af36eb226c Mon Sep 17 00:00:00 2001 From: nijeeshjoshy Date: Wed, 2 Apr 2025 14:30:26 +0200 Subject: [PATCH 3/7] removed unwanted changes --- .tool-versions | 1 + lib/stream-chat/client.rb | 7 ------- 2 files changed, 1 insertion(+), 7 deletions(-) create mode 100644 .tool-versions diff --git a/.tool-versions b/.tool-versions new file mode 100644 index 0000000..ae5ecdb --- /dev/null +++ b/.tool-versions @@ -0,0 +1 @@ +ruby 3.4.2 diff --git a/lib/stream-chat/client.rb b/lib/stream-chat/client.rb index 14dbaed..00fa892 100644 --- a/lib/stream-chat/client.rb +++ b/lib/stream-chat/client.rb @@ -280,13 +280,6 @@ def deactivate_user(user_id, **options) post("users/#{user_id}/deactivate", params: options) end - - # Deactivates a users - sig { params(user_ids: T::Array[String], options: T.untyped).returns(StreamChat::StreamResponse) } - def deactivate_users(user_ids, **options) - post("users/deactivate", data: { user_ids: user_ids, **options }) - end - # Reactivates a deactivated user. Use deactivate_user to deactivate a user. sig { params(user_id: String, options: T.untyped).returns(StreamChat::StreamResponse) } def reactivate_user(user_id, **options) From 21d8acafec66345d55390fc738f1a15465ae3879 Mon Sep 17 00:00:00 2001 From: nijeeshjoshy Date: Wed, 2 Apr 2025 14:30:34 +0200 Subject: [PATCH 4/7] rubocop corrections --- spec/client_spec.rb | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/spec/client_spec.rb b/spec/client_spec.rb index dc9a515..4084d50 100644 --- a/spec/client_spec.rb +++ b/spec/client_spec.rb @@ -795,7 +795,7 @@ def loop_times(times) @channel.create_draft(draft1, @random_user[:id]) # Create another channel with a draft - channel2 = @client.channel('messaging', data: {'members' => @random_users.map { |u| u[:id] } }) + channel2 = @client.channel('messaging', data: { 'members' => @random_users.map { |u| u[:id] } }) channel2.create(@random_user[:id]) draft2 = { 'text' => 'Draft in channel 2' } From 3f981b8b6473043c6d133542db66be7349f5808a Mon Sep 17 00:00:00 2001 From: nijeeshjoshy Date: Wed, 2 Apr 2025 14:33:35 +0200 Subject: [PATCH 5/7] chore: removed unwanted changes --- spec/client_spec.rb | 6 ------ 1 file changed, 6 deletions(-) diff --git a/spec/client_spec.rb b/spec/client_spec.rb index 4084d50..d5b394d 100644 --- a/spec/client_spec.rb +++ b/spec/client_spec.rb @@ -169,12 +169,6 @@ def loop_times(times) expect(response['user']['id']).to eq(@random_user[:id]) end - it 'deactivates multiple users' do - response = @client.deactivate_users([@random_users[0][:id], @random_users[1][:id]]) - expect(response).to include 'users' - expect(response['users'].length).to eq(2) - end - it 'reactivates a user' do @client.deactivate_user(@random_user[:id]) response = @client.reactivate_user(@random_user[:id]) From 1dd01f8a87df1a01c0a8993b26a827afd485f6d5 Mon Sep 17 00:00:00 2001 From: nijeeshjoshy Date: Wed, 2 Apr 2025 14:34:32 +0200 Subject: [PATCH 6/7] chore: removed unwanted file changes --- .tool-versions | 1 - 1 file changed, 1 deletion(-) delete mode 100644 .tool-versions diff --git a/.tool-versions b/.tool-versions deleted file mode 100644 index ae5ecdb..0000000 --- a/.tool-versions +++ /dev/null @@ -1 +0,0 @@ -ruby 3.4.2 From 171910427945b451f1731a13ddefaad536d8fae3 Mon Sep 17 00:00:00 2001 From: nijeeshjoshy Date: Wed, 2 Apr 2025 14:36:23 +0200 Subject: [PATCH 7/7] chore: removed unwanted rdoc comment --- lib/stream-chat/channel.rb | 1 - 1 file changed, 1 deletion(-) diff --git a/lib/stream-chat/channel.rb b/lib/stream-chat/channel.rb index a4d6068..ed91ed7 100644 --- a/lib/stream-chat/channel.rb +++ b/lib/stream-chat/channel.rb @@ -364,7 +364,6 @@ def delete_image(url) # # @param [StringKeyHash] message The draft message content # @param [String] user_id The ID of the user creating/updating the draft - # @param [String] parent_id Optional parent message ID for thread drafts # @return [StreamChat::StreamResponse] sig { params(message: StringKeyHash, user_id: String).returns(StreamChat::StreamResponse) } def create_draft(message, user_id)