Skip to content

Commit d7a935f

Browse files
authored
feat: add campaign support (#124)
1 parent 2442633 commit d7a935f

File tree

3 files changed

+89
-36
lines changed

3 files changed

+89
-36
lines changed

README.md

Lines changed: 39 additions & 13 deletions
Original file line numberDiff line numberDiff line change
@@ -57,7 +57,7 @@ client = StreamChat::Client.new('STREAM_KEY', 'STREAM_SECRET')
5757
> # Wrong:
5858
> user = { "user" => { "id" => "bob-1"}}
5959
> # Correct:
60-
> user = { :user => { :id => "bob-1" }}
60+
> user = { user: { id: "bob-1" }}
6161
> ```
6262
6363
### Generate a token for client-side usage:
@@ -70,25 +70,25 @@ client.create_token('bob-1')
7070

7171
```ruby
7272
client.upsert_user({
73-
:id => 'bob-1',
74-
:role => 'admin',
75-
:name => 'Robert Tables'
73+
id: 'bob-1',
74+
role: 'admin',
75+
name: 'Robert Tables'
7676
})
7777

7878
# Batch update is also supported
79-
jane = {:id => 'jane-1'}
80-
june = {:id => 'june-1'}
79+
jane = {id: 'jane-1'}
80+
june = {id: 'june-1'}
8181
client.upsert_users([jane, june])
8282
```
8383

8484
### Channel types
8585

8686
```ruby
8787
client.create_channel_type({
88-
:name => 'livechat',
89-
:automod => 'disabled',
90-
:commands => ['ban'],
91-
:mutes => true
88+
name: 'livechat',
89+
automod: 'disabled',
90+
commands: ['ban'],
91+
mutes: true
9292
})
9393

9494
channel_types = client.list_channel_types()
@@ -109,7 +109,7 @@ chan.add_members(['bob-1', 'jane-77'])
109109

110110
### Reactions
111111
```ruby
112-
chan.send_reaction(m1['id'], {:type => 'like'}, 'bob-1')
112+
chan.send_reaction(m1['id'], {type: 'like'}, 'bob-1')
113113
```
114114

115115
### Moderation
@@ -125,7 +125,7 @@ chan.unban_user('bob-1')
125125
### Messages
126126

127127
```ruby
128-
m1 = chan.send_message({:text => 'Hi Jane!'}, 'bob-1')
128+
m1 = chan.send_message({text: 'Hi Jane!'}, 'bob-1')
129129

130130
deleted_message = client.delete_message(m1['message']['id'])
131131

@@ -158,13 +158,39 @@ client.delete_blocklist('my_blocker')
158158

159159
```ruby
160160
# Register an export
161-
response = client.export_channels({:type => 'messaging', :id => 'jane'})
161+
response = client.export_channels({type: 'messaging', id: 'jane'})
162162

163163
# Check completion
164164
status_response = client.get_export_channel_status(response['task_id'])
165165
# status_response['status'] == 'pending', 'completed'
166166
```
167167

168+
### Campaigns
169+
170+
```ruby
171+
# Create a user or channel segment
172+
client.create_segment({ name: 'test', type: 'user', filter: { uniq: 'a flag on users' } })
173+
174+
# Create a campaign that uses the segment
175+
client.create_campaign({
176+
name: 'test',
177+
text: 'Hi',
178+
sender_id: campaign_sender,
179+
segment_id: segment_id,
180+
channel_type: 'messaging'
181+
})
182+
183+
# Schedule the campaign
184+
client.schedule_campaign(campaign_id, Time.now.to_i)
185+
186+
# Query the campaign to check the status
187+
response = client.query_campaigns(filter_conditions: { id: campaign_id })
188+
response['campaigns'][0]['status'] == 'completed'
189+
190+
# Read sent information
191+
client.query_recipients(filter_conditions: { campaign_id: campaign_id })
192+
```
193+
168194
### Rate limits
169195

170196
```ruby

lib/stream-chat/client.rb

Lines changed: 17 additions & 23 deletions
Original file line numberDiff line numberDiff line change
@@ -869,16 +869,10 @@ def create_campaign(campaign)
869869
post('campaigns', data: { campaign: campaign })
870870
end
871871

872-
# Gets a campaign.
873-
sig { params(campaign_id: String).returns(StreamChat::StreamResponse) }
874-
def get_campaign(campaign_id)
875-
get("campaigns/#{campaign_id}")
876-
end
877-
878-
# Lists all campaigns. Options dictionary can contain 'offset' and 'limit' keys for pagination.
879-
sig { params(options: StringKeyHash).returns(StreamChat::StreamResponse) }
880-
def list_campaigns(options)
881-
get('campaigns', params: options)
872+
# Queries campaigns similar to query_channels or query_users.
873+
sig { params(params: T.untyped).returns(StreamChat::StreamResponse) }
874+
def query_campaigns(**params)
875+
get('campaigns', params: { payload: params.to_json })
882876
end
883877

884878
# Updates a campaign.
@@ -894,9 +888,9 @@ def delete_campaign(campaign_id)
894888
end
895889

896890
# Schedules a campaign.
897-
sig { params(campaign_id: String, send_at: Integer).returns(StreamChat::StreamResponse) }
898-
def schedule_campaign(campaign_id, send_at)
899-
patch("campaigns/#{campaign_id}/schedule", data: { send_at: send_at })
891+
sig { params(campaign_id: String, scheduled_for: Integer).returns(StreamChat::StreamResponse) }
892+
def schedule_campaign(campaign_id, scheduled_for)
893+
patch("campaigns/#{campaign_id}/schedule", data: { scheduled_for: scheduled_for })
900894
end
901895

902896
# Stops a campaign.
@@ -923,16 +917,10 @@ def create_segment(segment)
923917
post('segments', data: { segment: segment })
924918
end
925919

926-
# Gets a campaign segment.
927-
sig { params(segment_id: String).returns(StreamChat::StreamResponse) }
928-
def get_segment(segment_id)
929-
get("segments/#{segment_id}")
930-
end
931-
932-
# Lists all campaign segments. Options dictionary can contain 'offset' and 'limit' keys for pagination.
933-
sig { params(options: StringKeyHash).returns(StreamChat::StreamResponse) }
934-
def list_segments(options)
935-
get('segments', params: options)
920+
# Queries campaign segments.
921+
sig { params(params: T.untyped).returns(StreamChat::StreamResponse) }
922+
def query_segments(**params)
923+
get('segments', params: { payload: params.to_json })
936924
end
937925

938926
# Updates a campaign segment.
@@ -947,6 +935,12 @@ def delete_segment(segment_id)
947935
delete("segments/#{segment_id}")
948936
end
949937

938+
# Queries campaign recipients.
939+
sig { params(params: T.untyped).returns(StreamChat::StreamResponse) }
940+
def query_recipients(**params)
941+
get('recipients', params: { payload: params.to_json })
942+
end
943+
950944
private
951945

952946
sig { returns(T::Hash[String, String]) }

spec/client_spec.rb

Lines changed: 33 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -729,6 +729,39 @@ def loop_times(times)
729729
end
730730
end
731731

732+
describe 'campaigns', campaigns: true do
733+
before(:all) do
734+
@campaign_selector = SecureRandom.uuid
735+
@campaign_receiver = SecureRandom.uuid
736+
@campaign_sender = SecureRandom.uuid
737+
@client.upsert_user({ id: @campaign_receiver, uniq: @campaign_selector, receiver: true })
738+
@client.upsert_user({ id: @campaign_sender, sender: true })
739+
end
740+
741+
it 'full flow' do
742+
response = @client.create_segment({ name: 'test', type: 'user', filter: { uniq: @campaign_selector } })
743+
segment = response['segment']
744+
response = @client.create_campaign({ name: 'test', text: 'Hi', sender_id: @campaign_sender, segment_id: segment['id'], channel_type: 'messaging' })
745+
campaign = response['campaign']
746+
@client.schedule_campaign(campaign['id'], Time.now.to_i)
747+
748+
response = @client.query_segments(filter_conditions: { id: segment['id'] })
749+
expect(response['segments'].length).to eq 1
750+
751+
loop do
752+
response = @client.query_campaigns(filter_conditions: { id: campaign['id'] })
753+
if response['campaigns'].length == 1 && response['campaigns'][0]['status'] == 'completed'
754+
response = @client.query_recipients(filter_conditions: { campaign_id: campaign['id'] })
755+
puts response.to_json
756+
expect(response['recipients'].length).to eq 1
757+
expect(response['recipients'][0]['receiver_id']).to eq @campaign_receiver
758+
break
759+
end
760+
sleep(0.5)
761+
end
762+
end
763+
end
764+
732765
describe 'permissions' do
733766
before(:all) do
734767
@permission_id = SecureRandom.uuid

0 commit comments

Comments
 (0)