Skip to content

Commit a25a1b6

Browse files
authored
feat: full feature parity (#71)
1 parent b025537 commit a25a1b6

File tree

6 files changed

+113
-11
lines changed

6 files changed

+113
-11
lines changed

.github/workflows/ci.yml

Lines changed: 2 additions & 3 deletions
Original file line numberDiff line numberDiff line change
@@ -28,6 +28,5 @@ jobs:
2828

2929
- run: bundle exec rake test
3030
env:
31-
STREAM_CHAT_API_KEY: ${{ secrets.STREAM_CHAT_API_KEY }}
32-
STREAM_CHAT_API_SECRET: ${{ secrets.STREAM_CHAT_API_SECRET }}
33-
STREAM_CHAT_API_HOST: ${{ secrets.STREAM_CHAT_API_HOST }}
31+
STREAM_KEY: ${{ secrets.STREAM_CHAT_API_KEY }}
32+
STREAM_SECRET: ${{ secrets.STREAM_CHAT_API_SECRET }}

README.md

Lines changed: 8 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -213,7 +213,7 @@ See [an example rails application using the Ruby SDK](https://github.com/GetStre
213213
First, make sure you can run the test suite. Tests are run via rspec
214214

215215
```bash
216-
STREAM_CHAT_API_KEY=my_api_key STREAM_CHAT_API_SECRET=my_api_secret bundle exec rake spec
216+
STREAM_KEY=my_api_key STREAM_SECRET=my_api_secret bundle exec rake spec
217217
```
218218

219219
This repository follows a commit message convention in order to automatically generate the [CHANGELOG](./CHANGELOG.md). Make sure you follow the rules of [conventional commits](https://www.conventionalcommits.org/) when opening a pull request.
@@ -229,3 +229,10 @@ The job creates a pull request with the changelog. Check if it looks good.
229229
- Merge the pull request.
230230

231231
Once the PR is merged, it automatically kicks off another job which will upload the Gem to RubyGems.org and creates a GitHub release.
232+
233+
## We are hiring!
234+
235+
We've recently closed a [$38 million Series B funding round](https://techcrunch.com/2021/03/04/stream-raises-38m-as-its-chat-and-activity-feed-apis-power-communications-for-1b-users/) and we keep actively growing.
236+
Our APIs are used by more than a billion end-users, and you'll have a chance to make a huge impact on the product within a team of the strongest engineers all over the world.
237+
238+
Check out our current openings and apply via [Stream's website](https://getstream.io/team/#jobs).

lib/stream-chat/channel.rb

Lines changed: 15 additions & 0 deletions
Original file line numberDiff line numberDiff line change
@@ -13,6 +13,7 @@ class Channel # rubocop:todo Metrics/ClassLength # rubocop:todo Style/Documentat
1313
def initialize(client, channel_type, channel_id = nil, custom_data = nil)
1414
@channel_type = channel_type
1515
@id = channel_id
16+
@cid = "#{@channel_type}:#{@id}"
1617
@client = client
1718
@custom_data = custom_data
1819
@custom_data = {} if @custom_data.nil?
@@ -24,6 +25,10 @@ def url
2425
"channels/#{@channel_type}/#{@id}"
2526
end
2627

28+
def get_messages(message_ids)
29+
@client.get("#{url}/messages", params: { 'ids' => message_ids.join(',') })
30+
end
31+
2732
def send_message(message, user_id)
2833
payload = { message: add_user_id(message, user_id) }
2934
@client.post("#{url}/message", data: payload)
@@ -99,6 +104,16 @@ def truncate(**options)
99104
@client.post("#{url}/truncate", data: options)
100105
end
101106

107+
def mute(user_id, expiration = nil)
108+
data = { user_id: user_id, channel_cid: @cid }
109+
data['expiration'] = expiration if expiration
110+
@client.post('moderation/mute/channel', data: data)
111+
end
112+
113+
def unmute(user_id)
114+
@client.post('moderation/unmute/channel', data: { 'user_id' => user_id, 'channel_cid' => @cid })
115+
end
116+
102117
def add_members(user_ids, **options)
103118
payload = options.merge({ add_members: user_ids })
104119
@client.post(url, data: payload)

lib/stream-chat/client.rb

Lines changed: 32 additions & 4 deletions
Original file line numberDiff line numberDiff line change
@@ -35,12 +35,12 @@ class Client
3535
# StreamChat::Client.new('my_key', 'my_secret', 3.0)
3636
#
3737
def initialize(api_key = '', api_secret = '', timeout = 6.0, **options)
38-
@api_key = api_key
39-
@api_secret = api_secret
40-
@timeout = timeout
38+
@api_key = api_key || ENV['STREAM_KEY']
39+
@api_secret = api_secret || ENV['STREAM_SECRET']
40+
@timeout = timeout || ENV['STREAM_CHAT_TIMEOUT']
4141
@options = options
4242
@auth_token = JWT.encode({ server: true }, @api_secret, 'HS256')
43-
@base_url = options[:base_url] || BASE_URL
43+
@base_url = options[:base_url] || ENV['STREAM_CHAT_URL'] || BASE_URL
4444
@conn = Faraday.new(url: @base_url) do |faraday|
4545
faraday.options[:open_timeout] = @timeout
4646
faraday.options[:timeout] = @timeout
@@ -221,6 +221,14 @@ def delete_message(message_id)
221221
delete("messages/#{message_id}")
222222
end
223223

224+
def query_banned_users(filter_conditions, sort: nil, **options)
225+
params = options.merge({
226+
filter_conditions: filter_conditions,
227+
sort: get_sort_fields(sort)
228+
})
229+
get('query_banned_users', params: { payload: params.to_json })
230+
end
231+
224232
def query_users(filter_conditions, sort: nil, **options)
225233
params = options.merge({
226234
filter_conditions: filter_conditions,
@@ -303,6 +311,22 @@ def verify_webhook(request_body, x_signature)
303311
signature == x_signature
304312
end
305313

314+
def send_user_event(user_id, event)
315+
post("users/#{user_id}/event", data: event)
316+
end
317+
318+
def translate_message(message_id, language)
319+
post("messages/#{message_id}/translate", data: { language: language })
320+
end
321+
322+
def run_message_action(message_id, data)
323+
post("messages/#{message_id}/action", data: data)
324+
end
325+
326+
def create_guest(user)
327+
post('guests', data: user)
328+
end
329+
306330
def list_blocklists
307331
get('blocklists')
308332
end
@@ -405,6 +429,10 @@ def send_file(relative_url, file_url, user, content_type = 'application/octet-st
405429
parse_response(response)
406430
end
407431

432+
def check_push(push_data)
433+
post('check_push', data: push_data)
434+
end
435+
408436
def check_sqs(sqs_key = nil, sqs_secret = nil, sqs_url = nil)
409437
post('check_sqs', data: { sqs_key: sqs_key, sqs_secret: sqs_secret, sqs_url: sqs_url })
410438
end

spec/channel_spec.rb

Lines changed: 14 additions & 1 deletion
Original file line numberDiff line numberDiff line change
@@ -19,7 +19,7 @@ def loop_times(times)
1919
end
2020

2121
before(:all) do
22-
@client = StreamChat::Client.new(ENV['STREAM_CHAT_API_KEY'], ENV['STREAM_CHAT_API_SECRET'], base_url: ENV['STREAM_CHAT_API_HOST'])
22+
@client = StreamChat::Client.new(ENV['STREAM_KEY'], ENV['STREAM_SECRET'], base_url: ENV['STREAM_CHAT_URL'])
2323
end
2424

2525
before(:each) do
@@ -49,6 +49,12 @@ def loop_times(times)
4949
expect(response['event']['type']).to eq 'typing.start'
5050
end
5151

52+
it 'can get many messages' do
53+
msg = @channel.send_message({ text: 'hi' }, @random_user[:id])
54+
response = @channel.get_messages([msg['message']['id']])
55+
expect(response['messages']).not_to be_empty
56+
end
57+
5258
it 'can send reactions' do
5359
msg = @channel.send_message({ 'text' => 'hi' }, @random_user[:id])
5460
response = @channel.send_reaction(msg['message']['id'], { 'type' => 'love' }, @random_user[:id])
@@ -65,6 +71,13 @@ def loop_times(times)
6571
expect(response['message']['latest_reactions'].length).to eq 0
6672
end
6773

74+
it 'can mute and unmute a channel' do
75+
response = @channel.mute(@random_user[:id])
76+
expect(response['channel_mute']['channel']['cid']).not_to be_empty
77+
78+
@channel.unmute(@random_user[:id])
79+
end
80+
6881
it 'can update metadata' do
6982
response = @channel.update({ 'motd' => 'one apple a day...' })
7083
expect(response).to include 'channel'

spec/client_spec.rb

Lines changed: 42 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -11,7 +11,7 @@ def loop_times(times)
1111
yield()
1212
return
1313
rescue StandardError, RSpec::Expectations::ExpectationNotMetError
14-
raise if times == 0
14+
raise if times.zero?
1515
end
1616

1717
sleep(1)
@@ -20,7 +20,7 @@ def loop_times(times)
2020
end
2121

2222
before(:all) do
23-
@client = StreamChat::Client.new(ENV['STREAM_CHAT_API_KEY'], ENV['STREAM_CHAT_API_SECRET'], base_url: ENV['STREAM_CHAT_API_HOST'])
23+
@client = StreamChat::Client.new(ENV['STREAM_KEY'], ENV['STREAM_SECRET'], base_url: ENV['STREAM_CHAT_URL'])
2424

2525
@fellowship_of_the_ring = [
2626
{ id: 'frodo-baggins', name: 'Frodo Baggins', race: 'Hobbit', age: 50 },
@@ -266,6 +266,12 @@ def loop_times(times)
266266
@client.delete_message(msg_id)
267267
end
268268

269+
it 'query banned users' do
270+
@client.ban_user(@random_user[:id], user_id: @random_users[0][:id], reason: 'rubytest')
271+
response = @client.query_banned_users({ 'reason' => 'rubytest' }, limit: 1)
272+
expect(response['bans'].length).to eq 1
273+
end
274+
269275
it 'queries users' do
270276
response = @client.query_users({ 'race' => { '$eq' => 'Hobbit' } }, sort: { 'age' => -1 })
271277
expect(response['users'].length).to eq 2
@@ -279,6 +285,11 @@ def loop_times(times)
279285
expect(response['channels'][0]['members'].length).to eq 4
280286
end
281287

288+
xit 'run message action' do
289+
resp = @channel.send_message({ text: '/giphy wave' }, @random_user[:id])
290+
@client.run_message_action(resp['message']['id'], { user: { id: @random_user[:id] }, form_data: { image_action: 'shuffle' } })
291+
end
292+
282293
it 'handles devices' do
283294
response = @client.get_devices(@random_user[:id])
284295
expect(response).to include 'devices'
@@ -331,22 +342,26 @@ def loop_times(times)
331342
resp = @client.search({ members: { '$in' => ['legolas'] } }, text)
332343
expect(resp['results'].length).to eq(1)
333344
end
345+
334346
it 'search for messages with filter conditions' do
335347
text = SecureRandom.uuid
336348
@channel.send_message({ text: text }, 'legolas')
337349
resp = @client.search({ members: { '$in' => ['legolas'] } }, { text: { '$q': text } })
338350
expect(resp['results'].length).to eq(1)
339351
end
352+
340353
it 'offset with sort should fail' do
341354
expect do
342355
@client.search({ members: { '$in' => ['legolas'] } }, SecureRandom.uuid, sort: [{ created_at: -1 }], offset: 2)
343356
end.to raise_error(/cannot use offset with next or sort parameters/)
344357
end
358+
345359
it 'offset with next should fail' do
346360
expect do
347361
@client.search({ members: { '$in' => ['legolas'] } }, SecureRandom.uuid, offset: 2, next: SecureRandom.uuid)
348362
end.to raise_error(/cannot use offset with next or sort parameters/)
349363
end
364+
350365
xit 'search for messages with sorting' do
351366
text = SecureRandom.uuid
352367
message_ids = ["0-#{text}", "1-#{text}"]
@@ -568,12 +583,37 @@ def loop_times(times)
568583
end
569584
end
570585

586+
it 'check push notification test are working' do
587+
message_id = SecureRandom.uuid
588+
@channel.send_message({ id: message_id, text: SecureRandom.uuid }, 'legolas')
589+
resp = @client.check_push({ message_id: message_id, skip_devices: true, user_id: @random_user[:id] })
590+
expect(resp['rendered_message']).not_to be_empty
591+
end
592+
571593
it 'check_sqs with an invalid queue url should fail' do
572594
resp = @client.check_sqs('key', 'secret', 'https://foo.com/bar')
573595
expect(resp['status']).to eq 'error'
574596
expect(resp['error']).to include 'invalid SQS url'
575597
end
576598

599+
it 'can create a guest if it"s allowed' do
600+
guest_user = @client.create_guest({ user: { id: SecureRandom.uuid } })
601+
expect(guest_user['access_token']).not_to be_empty
602+
rescue StreamChat::StreamAPIException
603+
# Guest user isn't turned on for every test app, so ignore it
604+
end
605+
606+
it 'can send custom events' do
607+
@client.send_user_event(@random_user[:id], { event: { type: 'friendship-request' } })
608+
end
609+
610+
it 'can translate a message' do
611+
message_id = SecureRandom.uuid
612+
@channel.send_message({ id: message_id, text: SecureRandom.uuid }, 'legolas')
613+
response = @client.translate_message(message_id, 'hu')
614+
expect(response['message']).not_to be_empty
615+
end
616+
577617
describe 'custom commands' do
578618
before(:all) do
579619
@cmd = SecureRandom.uuid

0 commit comments

Comments
 (0)