stream-chat-ruby 3.21.0 → 3.23.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml CHANGED
@@ -1,7 +1,7 @@
1
1
  ---
2
2
  SHA256:
3
- metadata.gz: 04f9d9c833c0a76e5028a2ab0cf93b8825901500e56f6956276d6308e80644da
4
- data.tar.gz: ac0c1c38c99ad7d1ab32f7f80c7a8becb9e22f41ecd96e5b4ae11538b5a73313
3
+ metadata.gz: 9b7896b214aa6d889a30c567056fdf2d0f6d4b6220d83a17acee469ba2b88aca
4
+ data.tar.gz: 4d7127a19485858f8ff18eef48996adc46dc4f6ae5661c6813a984a38017dd4b
5
5
  SHA512:
6
- metadata.gz: c372e48ee5d7889c9d8931c57524aa6bb9e9465828dee77a52ec1f2cabfe1bc32392aebf15230cb87427dbf4dff12569569f6b269cfe1d61ba39760763311657
7
- data.tar.gz: 5fbaf82414b47e6f1b647280deb88ed07c62c38d833bb5698c1345326bfadc907d40112235815ce98b7a82df5b117ca7de816dc64701579dc8cd110a4f7e5859
6
+ metadata.gz: 152671fd7190cb2762c3499996ade2c7fd4d4e1dfa823a05214da862d399ae39bcef64183b6ebd6e23912cba9b1685e93b8a1b7e4a06a43f8248d129bd460de4
7
+ data.tar.gz: 5f92a082a28faedd95b017fcc5f70f43b7c82d386da8149e4d50b03a60486f63360588b9ae280e8c71aff086cdecf6a60209fd447156e1315a02fea983b447fa
data/CHANGELOG.md CHANGED
@@ -2,6 +2,10 @@
2
2
 
3
3
  All notable changes to this project will be documented in this file. See [standard-version](https://github.com/conventional-changelog/standard-version) for commit guidelines.
4
4
 
5
+ ## [3.23.0](https://github.com/GetStream/stream-chat-ruby/compare/v3.22.0...v3.23.0) (2026-01-29)
6
+
7
+ ## [3.22.0](https://github.com/GetStream/stream-chat-ruby/compare/v3.21.0...v3.22.0) (2026-01-15)
8
+
5
9
  ## [3.21.0](https://github.com/GetStream/stream-chat-ruby/compare/v3.20.0...v3.21.0) (2025-11-12)
6
10
 
7
11
 
@@ -0,0 +1,111 @@
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
+ class Campaign
11
+ extend T::Sig
12
+
13
+ sig { returns(T.nilable(String)) }
14
+ attr_reader :campaign_id
15
+
16
+ sig { returns(T.nilable(StringKeyHash)) }
17
+ attr_reader :data
18
+
19
+ sig { params(client: StreamChat::Client, campaign_id: T.nilable(String), data: T.nilable(StringKeyHash)).void }
20
+ def initialize(client, campaign_id = nil, data = nil)
21
+ @client = client
22
+ @campaign_id = campaign_id
23
+ @data = data
24
+ end
25
+
26
+ # Creates a campaign.
27
+ #
28
+ # @param [String, nil] campaign_id Optional campaign ID. If provided, sets the campaign_id.
29
+ # @param [StringKeyHash, nil] data Optional campaign data to merge with existing data.
30
+ # @return [StreamChat::StreamResponse] API response
31
+ sig { params(campaign_id: T.nilable(String), data: T.nilable(StringKeyHash)).returns(StreamChat::StreamResponse) }
32
+ def create(campaign_id: nil, data: nil)
33
+ @campaign_id = campaign_id if campaign_id
34
+ @data = merge_campaign_data(@data, data) if data
35
+
36
+ state = @client.create_campaign(campaign_id: @campaign_id, data: @data)
37
+
38
+ @campaign_id = state['campaign']['id'] if @campaign_id.nil? && state.status_code >= 200 && state.status_code < 300 && state['campaign']
39
+ state
40
+ end
41
+
42
+ # Gets a campaign by ID.
43
+ #
44
+ # @return [StreamChat::StreamResponse] API response
45
+ sig { returns(StreamChat::StreamResponse) }
46
+ def get
47
+ raise StreamChannelException, 'campaign does not have an id' if @campaign_id.nil?
48
+
49
+ @client.get_campaign(@campaign_id)
50
+ end
51
+
52
+ # Updates a campaign.
53
+ #
54
+ # @param [StringKeyHash] data Campaign data to update
55
+ # @return [StreamChat::StreamResponse] API response
56
+ sig { params(data: StringKeyHash).returns(StreamChat::StreamResponse) }
57
+ def update(data)
58
+ raise StreamChannelException, 'campaign does not have an id' if @campaign_id.nil?
59
+
60
+ @client.update_campaign(@campaign_id, data)
61
+ end
62
+
63
+ # Deletes a campaign.
64
+ #
65
+ # @param [Hash] options Optional deletion options
66
+ # @return [StreamChat::StreamResponse] API response
67
+ sig { params(options: T.untyped).returns(StreamChat::StreamResponse) }
68
+ def delete(**options)
69
+ raise StreamChannelException, 'campaign does not have an id' if @campaign_id.nil?
70
+
71
+ @client.delete_campaign(@campaign_id, **options)
72
+ end
73
+
74
+ # Starts a campaign.
75
+ #
76
+ # @param [DateTime, Time, String, nil] scheduled_for Optional scheduled start time
77
+ # @param [DateTime, Time, String, nil] stop_at Optional scheduled stop time
78
+ # @return [StreamChat::StreamResponse] API response
79
+ sig { params(scheduled_for: T.nilable(T.any(DateTime, Time, String)), stop_at: T.nilable(T.any(DateTime, Time, String))).returns(StreamChat::StreamResponse) }
80
+ def start(scheduled_for: nil, stop_at: nil)
81
+ raise StreamChannelException, 'campaign does not have an id' if @campaign_id.nil?
82
+
83
+ @client.start_campaign(@campaign_id, scheduled_for: scheduled_for, stop_at: stop_at)
84
+ end
85
+
86
+ # Stops a campaign.
87
+ #
88
+ # @return [StreamChat::StreamResponse] API response
89
+ sig { returns(StreamChat::StreamResponse) }
90
+ def stop
91
+ raise StreamChannelException, 'campaign does not have an id' if @campaign_id.nil?
92
+
93
+ @client.stop_campaign(@campaign_id)
94
+ end
95
+
96
+ private
97
+
98
+ # Merges two campaign data hashes.
99
+ #
100
+ # @param [StringKeyHash, nil] data1 First campaign data hash
101
+ # @param [StringKeyHash, nil] data2 Second campaign data hash
102
+ # @return [StringKeyHash] Merged campaign data
103
+ sig { params(data1: T.nilable(StringKeyHash), data2: T.nilable(StringKeyHash)).returns(StringKeyHash) }
104
+ def merge_campaign_data(data1, data2)
105
+ return T.must(data2) if data1.nil?
106
+ return data1 if data2.nil?
107
+
108
+ data1.merge(data2)
109
+ end
110
+ end
111
+ end
@@ -97,6 +97,22 @@ module StreamChat
97
97
  state
98
98
  end
99
99
 
100
+ # Refreshes the channel state from the server.
101
+ # Updates the channel's members attribute with fresh data.
102
+ sig { returns(StreamChat::StreamResponse) }
103
+ def refresh_state
104
+ url = "channels/#{@channel_type}/#{@id}/query"
105
+ state = @client.post(url, data: { state: true })
106
+
107
+ # Members can be at top level or inside channel object (like Go's updateChannel)
108
+ if state['members'] && !state['members'].empty?
109
+ @members = state['members']
110
+ elsif state['channel'] && state['channel']['members']
111
+ @members = state['channel']['members']
112
+ end
113
+ state
114
+ end
115
+
100
116
  # Queries members of a channel.
101
117
  #
102
118
  # The queryMembers endpoint allows you to list and paginate members from a channel. The
@@ -323,9 +339,9 @@ module StreamChat
323
339
  end
324
340
 
325
341
  # Removes the ban for a user on this channel.
326
- sig { params(user_id: String).returns(StreamChat::StreamResponse) }
327
- def unban_user(user_id)
328
- @client.unban_user(user_id, type: @channel_type, id: @id)
342
+ sig { params(user_id: String, options: T.untyped).returns(StreamChat::StreamResponse) }
343
+ def unban_user(user_id, **options)
344
+ @client.unban_user(user_id, type: @channel_type, id: @id, **options)
329
345
  end
330
346
 
331
347
  # Removes a channel from query channel requests for that user until a new message is added.
@@ -0,0 +1,214 @@
1
+ # typed: strict
2
+ # frozen_string_literal: true
3
+
4
+ require 'stream-chat/client'
5
+ require 'stream-chat/stream_response'
6
+ require 'stream-chat/types'
7
+
8
+ module StreamChat
9
+ class ChannelBatchUpdater
10
+ extend T::Sig
11
+
12
+ sig { params(client: StreamChat::Client).void }
13
+ def initialize(client)
14
+ @client = client
15
+ end
16
+
17
+ # Member operations
18
+
19
+ # addMembers - Add members to channels matching the filter
20
+ # @param filter [StringKeyHash] Filter to select channels
21
+ # @param members [T.any(T::Array[String], T::Array[StringKeyHash])] Members to add
22
+ # @return [StreamChat::StreamResponse] The server response
23
+ sig { params(filter: StringKeyHash, members: T.any(T::Array[String], T::Array[StringKeyHash])).returns(StreamChat::StreamResponse) }
24
+ def add_members(filter, members)
25
+ @client.update_channels_batch(
26
+ {
27
+ operation: 'addMembers',
28
+ filter: filter,
29
+ members: members
30
+ }
31
+ )
32
+ end
33
+
34
+ # removeMembers - Remove members from channels matching the filter
35
+ # @param filter [StringKeyHash] Filter to select channels
36
+ # @param members [T::Array[StringKeyHash]] Members to remove (each with user_id key)
37
+ # @return [StreamChat::StreamResponse] The server response
38
+ sig { params(filter: StringKeyHash, members: T::Array[StringKeyHash]).returns(StreamChat::StreamResponse) }
39
+ def remove_members(filter, members)
40
+ @client.update_channels_batch(
41
+ {
42
+ operation: 'removeMembers',
43
+ filter: filter,
44
+ members: members
45
+ }
46
+ )
47
+ end
48
+
49
+ # inviteMembers - Invite members to channels matching the filter
50
+ # @param filter [StringKeyHash] Filter to select channels
51
+ # @param members [T.any(T::Array[String], T::Array[StringKeyHash])] Members to invite
52
+ # @return [StreamChat::StreamResponse] The server response
53
+ sig { params(filter: StringKeyHash, members: T.any(T::Array[String], T::Array[StringKeyHash])).returns(StreamChat::StreamResponse) }
54
+ def invite_members(filter, members)
55
+ @client.update_channels_batch(
56
+ {
57
+ operation: 'invites',
58
+ filter: filter,
59
+ members: members
60
+ }
61
+ )
62
+ end
63
+
64
+ # addModerators - Add moderators to channels matching the filter
65
+ # @param filter [StringKeyHash] Filter to select channels
66
+ # @param members [T::Array[String]] Member IDs to promote to moderator
67
+ # @return [StreamChat::StreamResponse] The server response
68
+ sig { params(filter: StringKeyHash, members: T::Array[String]).returns(StreamChat::StreamResponse) }
69
+ def add_moderators(filter, members)
70
+ @client.update_channels_batch(
71
+ {
72
+ operation: 'addModerators',
73
+ filter: filter,
74
+ members: members
75
+ }
76
+ )
77
+ end
78
+
79
+ # demoteModerators - Remove moderator role from members in channels matching the filter
80
+ # @param filter [StringKeyHash] Filter to select channels
81
+ # @param members [T::Array[String]] Member IDs to demote
82
+ # @return [StreamChat::StreamResponse] The server response
83
+ sig { params(filter: StringKeyHash, members: T::Array[String]).returns(StreamChat::StreamResponse) }
84
+ def demote_moderators(filter, members)
85
+ @client.update_channels_batch(
86
+ {
87
+ operation: 'demoteModerators',
88
+ filter: filter,
89
+ members: members
90
+ }
91
+ )
92
+ end
93
+
94
+ # assignRoles - Assign roles to members in channels matching the filter
95
+ # @param filter [StringKeyHash] Filter to select channels
96
+ # @param members [T::Array[StringKeyHash]] Members with role assignments
97
+ # @return [StreamChat::StreamResponse] The server response
98
+ sig { params(filter: StringKeyHash, members: T::Array[StringKeyHash]).returns(StreamChat::StreamResponse) }
99
+ def assign_roles(filter, members)
100
+ @client.update_channels_batch(
101
+ {
102
+ operation: 'assignRoles',
103
+ filter: filter,
104
+ members: members
105
+ }
106
+ )
107
+ end
108
+
109
+ # Visibility operations
110
+
111
+ # hide - Hide channels matching the filter
112
+ # @param filter [StringKeyHash] Filter to select channels
113
+ # @return [StreamChat::StreamResponse] The server response
114
+ sig { params(filter: StringKeyHash).returns(StreamChat::StreamResponse) }
115
+ def hide(filter)
116
+ @client.update_channels_batch(
117
+ {
118
+ operation: 'hide',
119
+ filter: filter
120
+ }
121
+ )
122
+ end
123
+
124
+ # show - Show channels matching the filter
125
+ # @param filter [StringKeyHash] Filter to select channels
126
+ # @return [StreamChat::StreamResponse] The server response
127
+ sig { params(filter: StringKeyHash).returns(StreamChat::StreamResponse) }
128
+ def show(filter)
129
+ @client.update_channels_batch(
130
+ {
131
+ operation: 'show',
132
+ filter: filter
133
+ }
134
+ )
135
+ end
136
+
137
+ # archive - Archive channels matching the filter for specified members
138
+ # @param filter [StringKeyHash] Filter to select channels
139
+ # @param members [T::Array[StringKeyHash]] Members to archive channels for (each with user_id key)
140
+ # @return [StreamChat::StreamResponse] The server response
141
+ sig { params(filter: StringKeyHash, members: T::Array[StringKeyHash]).returns(StreamChat::StreamResponse) }
142
+ def archive(filter, members)
143
+ @client.update_channels_batch(
144
+ {
145
+ operation: 'archive',
146
+ filter: filter,
147
+ members: members
148
+ }
149
+ )
150
+ end
151
+
152
+ # unarchive - Unarchive channels matching the filter for specified members
153
+ # @param filter [StringKeyHash] Filter to select channels
154
+ # @param members [T::Array[StringKeyHash]] Members to unarchive channels for (each with user_id key)
155
+ # @return [StreamChat::StreamResponse] The server response
156
+ sig { params(filter: StringKeyHash, members: T::Array[StringKeyHash]).returns(StreamChat::StreamResponse) }
157
+ def unarchive(filter, members)
158
+ @client.update_channels_batch(
159
+ {
160
+ operation: 'unarchive',
161
+ filter: filter,
162
+ members: members
163
+ }
164
+ )
165
+ end
166
+
167
+ # Data operations
168
+
169
+ # updateData - Update data on channels matching the filter
170
+ # @param filter [StringKeyHash] Filter to select channels
171
+ # @param data [StringKeyHash] Data to update
172
+ # @return [StreamChat::StreamResponse] The server response
173
+ sig { params(filter: StringKeyHash, data: StringKeyHash).returns(StreamChat::StreamResponse) }
174
+ def update_data(filter, data)
175
+ @client.update_channels_batch(
176
+ {
177
+ operation: 'updateData',
178
+ filter: filter,
179
+ data: data
180
+ }
181
+ )
182
+ end
183
+
184
+ # addFilterTags - Add filter tags to channels matching the filter
185
+ # @param filter [StringKeyHash] Filter to select channels
186
+ # @param tags [T::Array[String]] Tags to add
187
+ # @return [StreamChat::StreamResponse] The server response
188
+ sig { params(filter: StringKeyHash, tags: T::Array[String]).returns(StreamChat::StreamResponse) }
189
+ def add_filter_tags(filter, tags)
190
+ @client.update_channels_batch(
191
+ {
192
+ operation: 'addFilterTags',
193
+ filter: filter,
194
+ filter_tags_update: tags
195
+ }
196
+ )
197
+ end
198
+
199
+ # removeFilterTags - Remove filter tags from channels matching the filter
200
+ # @param filter [StringKeyHash] Filter to select channels
201
+ # @param tags [T::Array[String]] Tags to remove
202
+ # @return [StreamChat::StreamResponse] The server response
203
+ sig { params(filter: StringKeyHash, tags: T::Array[String]).returns(StreamChat::StreamResponse) }
204
+ def remove_filter_tags(filter, tags)
205
+ @client.update_channels_batch(
206
+ {
207
+ operation: 'removeFilterTags',
208
+ filter: filter,
209
+ filter_tags_update: tags
210
+ }
211
+ )
212
+ end
213
+ end
214
+ end
@@ -10,12 +10,14 @@ require 'time'
10
10
  require 'date'
11
11
  require 'sorbet-runtime'
12
12
  require 'stream-chat/channel'
13
+ require 'stream-chat/campaign'
13
14
  require 'stream-chat/errors'
14
15
  require 'stream-chat/stream_response'
15
16
  require 'stream-chat/version'
16
17
  require 'stream-chat/util'
17
18
  require 'stream-chat/types'
18
19
  require 'stream-chat/moderation'
20
+ require 'stream-chat/channel_batch_updater'
19
21
 
20
22
  module StreamChat
21
23
  DEFAULT_BLOCKLIST = 'profanity_en_2020_v1'
@@ -484,6 +486,15 @@ module StreamChat
484
486
  get('query_banned_users', params: { payload: params.to_json })
485
487
  end
486
488
 
489
+ # Queries future channel bans.
490
+ #
491
+ # Future channel bans are automatically applied when a user creates a new channel
492
+ # or adds a member to an existing channel.
493
+ sig { params(options: T.untyped).returns(StreamChat::StreamResponse) }
494
+ def query_future_channel_bans(**options)
495
+ get('query_future_channel_bans', params: { payload: options.to_json })
496
+ end
497
+
487
498
  # Allows you to search for users and see if they are online/offline.
488
499
  # You can filter and sort on the custom fields you've set for your user, the user id, and when the user was last active.
489
500
  sig { params(filter_conditions: StringKeyHash, sort: T.nilable(T::Hash[String, Integer]), options: T.untyped).returns(StreamChat::StreamResponse) }
@@ -555,6 +566,101 @@ module StreamChat
555
566
  StreamChat::Channel.new(self, channel_type, channel_id, data)
556
567
  end
557
568
 
569
+ # Creates a campaign instance
570
+ #
571
+ # @param [String, nil] campaign_id the campaign identifier
572
+ # @param [StringKeyHash, nil] data additional campaign data
573
+ #
574
+ # @return [StreamChat::Campaign]
575
+ #
576
+ sig { params(campaign_id: T.nilable(String), data: T.nilable(StringKeyHash)).returns(StreamChat::Campaign) }
577
+ def campaign(campaign_id: nil, data: nil)
578
+ StreamChat::Campaign.new(self, campaign_id, data)
579
+ end
580
+
581
+ # Creates a campaign.
582
+ #
583
+ # @param [String, nil] campaign_id Optional campaign ID
584
+ # @param [StringKeyHash, nil] data Campaign data including message_template, sender_id, segment_ids or user_ids, etc.
585
+ # @return [StreamChat::StreamResponse] API response
586
+ sig { params(campaign_id: T.nilable(String), data: T.nilable(StringKeyHash)).returns(StreamChat::StreamResponse) }
587
+ def create_campaign(campaign_id: nil, data: nil)
588
+ payload = {}
589
+ payload['id'] = campaign_id if campaign_id
590
+ payload.merge!(data) if data
591
+ post('campaigns', data: payload)
592
+ end
593
+
594
+ # Gets a campaign by ID.
595
+ #
596
+ # @param [String] campaign_id The campaign ID
597
+ # @return [StreamChat::StreamResponse] API response
598
+ sig { params(campaign_id: String).returns(StreamChat::StreamResponse) }
599
+ def get_campaign(campaign_id)
600
+ get("campaigns/#{campaign_id}")
601
+ end
602
+
603
+ # Updates a campaign.
604
+ #
605
+ # @param [String] campaign_id The campaign ID
606
+ # @param [StringKeyHash] data Campaign data to update
607
+ # @return [StreamChat::StreamResponse] API response
608
+ sig { params(campaign_id: String, data: StringKeyHash).returns(StreamChat::StreamResponse) }
609
+ def update_campaign(campaign_id, data)
610
+ put("campaigns/#{campaign_id}", data: data)
611
+ end
612
+
613
+ # Deletes a campaign.
614
+ #
615
+ # @param [String] campaign_id The campaign ID
616
+ # @param [Hash] options Optional deletion options (e.g., gdpr: true)
617
+ # @return [StreamChat::StreamResponse] API response
618
+ sig { params(campaign_id: String, options: T.untyped).returns(StreamChat::StreamResponse) }
619
+ def delete_campaign(campaign_id, **options)
620
+ delete("campaigns/#{campaign_id}", params: options)
621
+ end
622
+
623
+ # Starts a campaign.
624
+ #
625
+ # @param [String] campaign_id The campaign ID
626
+ # @param [DateTime, Time, String, nil] scheduled_for Optional scheduled start time
627
+ # @param [DateTime, Time, String, nil] stop_at Optional scheduled stop time
628
+ # @return [StreamChat::StreamResponse] API response
629
+ sig { params(campaign_id: String, scheduled_for: T.nilable(T.any(DateTime, Time, String)), stop_at: T.nilable(T.any(DateTime, Time, String))).returns(StreamChat::StreamResponse) }
630
+ def start_campaign(campaign_id, scheduled_for: nil, stop_at: nil)
631
+ payload = {}
632
+ payload['scheduled_for'] = StreamChat.normalize_timestamp(scheduled_for) if scheduled_for
633
+ payload['stop_at'] = StreamChat.normalize_timestamp(stop_at) if stop_at
634
+ post("campaigns/#{campaign_id}/start", data: payload)
635
+ end
636
+
637
+ # Stops a campaign.
638
+ #
639
+ # @param [String] campaign_id The campaign ID
640
+ # @return [StreamChat::StreamResponse] API response
641
+ sig { params(campaign_id: String).returns(StreamChat::StreamResponse) }
642
+ def stop_campaign(campaign_id)
643
+ post("campaigns/#{campaign_id}/stop")
644
+ end
645
+
646
+ # Queries campaigns.
647
+ #
648
+ # You can query campaigns based on built-in fields as well as any custom field you add to campaigns.
649
+ # Multiple filters can be combined using AND, OR logical operators, each filter can use its
650
+ # comparison (equality, inequality, greater than, greater or equal, etc.).
651
+ # @param [StringKeyHash] filter_conditions Filter conditions for the query
652
+ # @param [Hash, nil] sort Optional sort parameters (e.g., { 'created_at' => -1 })
653
+ # @param [Hash] options Additional query options (limit, offset, etc.)
654
+ # @return [StreamChat::StreamResponse] API response
655
+ sig { params(filter_conditions: StringKeyHash, sort: T.nilable(T::Hash[String, Integer]), options: T.untyped).returns(StreamChat::StreamResponse) }
656
+ def query_campaigns(filter_conditions, sort: nil, **options)
657
+ data = options.merge({
658
+ filter: filter_conditions,
659
+ sort: StreamChat.get_sort_fields(sort)
660
+ })
661
+ post('campaigns/query', data: data)
662
+ end
663
+
558
664
  # Adds a device to a user.
559
665
  sig { params(device_id: String, push_provider: String, user_id: String, push_provider_name: T.nilable(String)).returns(StreamChat::StreamResponse) }
560
666
  def add_device(device_id, push_provider, user_id, push_provider_name = nil)
@@ -1058,7 +1164,7 @@ module StreamChat
1058
1164
  sig { params(user_id: String, filter_conditions: T::Hash[T.untyped, T.untyped], sort: T.nilable(T::Array[T::Hash[T.untyped, T.untyped]]), options: T.untyped).returns(StreamChat::StreamResponse) }
1059
1165
  def query_reminders(user_id, filter_conditions = {}, sort: nil, **options)
1060
1166
  params = options.merge({
1061
- filter_conditions: filter_conditions,
1167
+ filter: filter_conditions,
1062
1168
  sort: sort || [{ field: 'remind_at', direction: 1 }],
1063
1169
  user_id: user_id
1064
1170
  })
@@ -1074,6 +1180,21 @@ module StreamChat
1074
1180
  post('channels/delivered', data: data || {}, params: { user_id: user_id })
1075
1181
  end
1076
1182
 
1183
+ # Update channels in batch.
1184
+ # @param payload [StringKeyHash] Payload containing operation, filter, and optional members/data/filter_tags_update
1185
+ # @return [StreamChat::StreamResponse] API response
1186
+ sig { params(payload: StringKeyHash).returns(StreamChat::StreamResponse) }
1187
+ def update_channels_batch(payload)
1188
+ put('channels/batch', data: payload)
1189
+ end
1190
+
1191
+ # Returns a ChannelBatchUpdater instance for batch channel operations.
1192
+ # @return [StreamChat::ChannelBatchUpdater] A ChannelBatchUpdater instance
1193
+ sig { returns(StreamChat::ChannelBatchUpdater) }
1194
+ def channel_batch_updater
1195
+ ChannelBatchUpdater.new(self)
1196
+ end
1197
+
1077
1198
  private
1078
1199
 
1079
1200
  sig { returns(T::Hash[String, String]) }
@@ -2,5 +2,5 @@
2
2
  # frozen_string_literal: true
3
3
 
4
4
  module StreamChat
5
- VERSION = '3.21.0'
5
+ VERSION = '3.23.0'
6
6
  end
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: stream-chat-ruby
3
3
  version: !ruby/object:Gem::Version
4
- version: 3.21.0
4
+ version: 3.23.0
5
5
  platform: ruby
6
6
  authors:
7
7
  - getstream.io
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2025-11-12 00:00:00.000000000 Z
11
+ date: 2026-01-30 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: faraday
@@ -113,7 +113,9 @@ files:
113
113
  - Rakefile
114
114
  - SECURITY.md
115
115
  - lib/stream-chat.rb
116
+ - lib/stream-chat/campaign.rb
116
117
  - lib/stream-chat/channel.rb
118
+ - lib/stream-chat/channel_batch_updater.rb
117
119
  - lib/stream-chat/client.rb
118
120
  - lib/stream-chat/errors.rb
119
121
  - lib/stream-chat/moderation.rb