Skip to content

Commit

Permalink
feat: full feature parity (#71)
Browse files Browse the repository at this point in the history
  • Loading branch information
peterdeme authored Jan 25, 2022
1 parent b025537 commit a25a1b6
Show file tree
Hide file tree
Showing 6 changed files with 113 additions and 11 deletions.
5 changes: 2 additions & 3 deletions .github/workflows/ci.yml
Original file line number Diff line number Diff line change
Expand Up @@ -28,6 +28,5 @@ jobs:

- run: bundle exec rake test
env:
STREAM_CHAT_API_KEY: ${{ secrets.STREAM_CHAT_API_KEY }}
STREAM_CHAT_API_SECRET: ${{ secrets.STREAM_CHAT_API_SECRET }}
STREAM_CHAT_API_HOST: ${{ secrets.STREAM_CHAT_API_HOST }}
STREAM_KEY: ${{ secrets.STREAM_CHAT_API_KEY }}
STREAM_SECRET: ${{ secrets.STREAM_CHAT_API_SECRET }}
9 changes: 8 additions & 1 deletion README.md
Original file line number Diff line number Diff line change
Expand Up @@ -213,7 +213,7 @@ See [an example rails application using the Ruby SDK](https://github.com/GetStre
First, make sure you can run the test suite. Tests are run via rspec

```bash
STREAM_CHAT_API_KEY=my_api_key STREAM_CHAT_API_SECRET=my_api_secret bundle exec rake spec
STREAM_KEY=my_api_key STREAM_SECRET=my_api_secret bundle exec rake spec
```

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.
Expand All @@ -229,3 +229,10 @@ The job creates a pull request with the changelog. Check if it looks good.
- Merge the pull request.

Once the PR is merged, it automatically kicks off another job which will upload the Gem to RubyGems.org and creates a GitHub release.

## We are hiring!

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.
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.

Check out our current openings and apply via [Stream's website](https://getstream.io/team/#jobs).
15 changes: 15 additions & 0 deletions lib/stream-chat/channel.rb
Original file line number Diff line number Diff line change
Expand Up @@ -13,6 +13,7 @@ class Channel # rubocop:todo Metrics/ClassLength # rubocop:todo Style/Documentat
def initialize(client, channel_type, channel_id = nil, custom_data = nil)
@channel_type = channel_type
@id = channel_id
@cid = "#{@channel_type}:#{@id}"
@client = client
@custom_data = custom_data
@custom_data = {} if @custom_data.nil?
Expand All @@ -24,6 +25,10 @@ def url
"channels/#{@channel_type}/#{@id}"
end

def get_messages(message_ids)
@client.get("#{url}/messages", params: { 'ids' => message_ids.join(',') })
end

def send_message(message, user_id)
payload = { message: add_user_id(message, user_id) }
@client.post("#{url}/message", data: payload)
Expand Down Expand Up @@ -99,6 +104,16 @@ def truncate(**options)
@client.post("#{url}/truncate", data: options)
end

def mute(user_id, expiration = nil)
data = { user_id: user_id, channel_cid: @cid }
data['expiration'] = expiration if expiration
@client.post('moderation/mute/channel', data: data)
end

def unmute(user_id)
@client.post('moderation/unmute/channel', data: { 'user_id' => user_id, 'channel_cid' => @cid })
end

def add_members(user_ids, **options)
payload = options.merge({ add_members: user_ids })
@client.post(url, data: payload)
Expand Down
36 changes: 32 additions & 4 deletions lib/stream-chat/client.rb
Original file line number Diff line number Diff line change
Expand Up @@ -35,12 +35,12 @@ class Client
# StreamChat::Client.new('my_key', 'my_secret', 3.0)
#
def initialize(api_key = '', api_secret = '', timeout = 6.0, **options)
@api_key = api_key
@api_secret = api_secret
@timeout = timeout
@api_key = api_key || ENV['STREAM_KEY']
@api_secret = api_secret || ENV['STREAM_SECRET']
@timeout = timeout || ENV['STREAM_CHAT_TIMEOUT']
@options = options
@auth_token = JWT.encode({ server: true }, @api_secret, 'HS256')
@base_url = options[:base_url] || BASE_URL
@base_url = options[:base_url] || ENV['STREAM_CHAT_URL'] || BASE_URL
@conn = Faraday.new(url: @base_url) do |faraday|
faraday.options[:open_timeout] = @timeout
faraday.options[:timeout] = @timeout
Expand Down Expand Up @@ -221,6 +221,14 @@ def delete_message(message_id)
delete("messages/#{message_id}")
end

def query_banned_users(filter_conditions, sort: nil, **options)
params = options.merge({
filter_conditions: filter_conditions,
sort: get_sort_fields(sort)
})
get('query_banned_users', params: { payload: params.to_json })
end

def query_users(filter_conditions, sort: nil, **options)
params = options.merge({
filter_conditions: filter_conditions,
Expand Down Expand Up @@ -303,6 +311,22 @@ def verify_webhook(request_body, x_signature)
signature == x_signature
end

def send_user_event(user_id, event)
post("users/#{user_id}/event", data: event)
end

def translate_message(message_id, language)
post("messages/#{message_id}/translate", data: { language: language })
end

def run_message_action(message_id, data)
post("messages/#{message_id}/action", data: data)
end

def create_guest(user)
post('guests', data: user)
end

def list_blocklists
get('blocklists')
end
Expand Down Expand Up @@ -405,6 +429,10 @@ def send_file(relative_url, file_url, user, content_type = 'application/octet-st
parse_response(response)
end

def check_push(push_data)
post('check_push', data: push_data)
end

def check_sqs(sqs_key = nil, sqs_secret = nil, sqs_url = nil)
post('check_sqs', data: { sqs_key: sqs_key, sqs_secret: sqs_secret, sqs_url: sqs_url })
end
Expand Down
15 changes: 14 additions & 1 deletion spec/channel_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -19,7 +19,7 @@ def loop_times(times)
end

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

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

it 'can get many messages' do
msg = @channel.send_message({ text: 'hi' }, @random_user[:id])
response = @channel.get_messages([msg['message']['id']])
expect(response['messages']).not_to be_empty
end

it 'can send reactions' do
msg = @channel.send_message({ 'text' => 'hi' }, @random_user[:id])
response = @channel.send_reaction(msg['message']['id'], { 'type' => 'love' }, @random_user[:id])
Expand All @@ -65,6 +71,13 @@ def loop_times(times)
expect(response['message']['latest_reactions'].length).to eq 0
end

it 'can mute and unmute a channel' do
response = @channel.mute(@random_user[:id])
expect(response['channel_mute']['channel']['cid']).not_to be_empty

@channel.unmute(@random_user[:id])
end

it 'can update metadata' do
response = @channel.update({ 'motd' => 'one apple a day...' })
expect(response).to include 'channel'
Expand Down
44 changes: 42 additions & 2 deletions spec/client_spec.rb
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,7 @@ def loop_times(times)
yield()
return
rescue StandardError, RSpec::Expectations::ExpectationNotMetError
raise if times == 0
raise if times.zero?
end

sleep(1)
Expand All @@ -20,7 +20,7 @@ def loop_times(times)
end

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

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

it 'query banned users' do
@client.ban_user(@random_user[:id], user_id: @random_users[0][:id], reason: 'rubytest')
response = @client.query_banned_users({ 'reason' => 'rubytest' }, limit: 1)
expect(response['bans'].length).to eq 1
end

it 'queries users' do
response = @client.query_users({ 'race' => { '$eq' => 'Hobbit' } }, sort: { 'age' => -1 })
expect(response['users'].length).to eq 2
Expand All @@ -279,6 +285,11 @@ def loop_times(times)
expect(response['channels'][0]['members'].length).to eq 4
end

xit 'run message action' do
resp = @channel.send_message({ text: '/giphy wave' }, @random_user[:id])
@client.run_message_action(resp['message']['id'], { user: { id: @random_user[:id] }, form_data: { image_action: 'shuffle' } })
end

it 'handles devices' do
response = @client.get_devices(@random_user[:id])
expect(response).to include 'devices'
Expand Down Expand Up @@ -331,22 +342,26 @@ def loop_times(times)
resp = @client.search({ members: { '$in' => ['legolas'] } }, text)
expect(resp['results'].length).to eq(1)
end

it 'search for messages with filter conditions' do
text = SecureRandom.uuid
@channel.send_message({ text: text }, 'legolas')
resp = @client.search({ members: { '$in' => ['legolas'] } }, { text: { '$q': text } })
expect(resp['results'].length).to eq(1)
end

it 'offset with sort should fail' do
expect do
@client.search({ members: { '$in' => ['legolas'] } }, SecureRandom.uuid, sort: [{ created_at: -1 }], offset: 2)
end.to raise_error(/cannot use offset with next or sort parameters/)
end

it 'offset with next should fail' do
expect do
@client.search({ members: { '$in' => ['legolas'] } }, SecureRandom.uuid, offset: 2, next: SecureRandom.uuid)
end.to raise_error(/cannot use offset with next or sort parameters/)
end

xit 'search for messages with sorting' do
text = SecureRandom.uuid
message_ids = ["0-#{text}", "1-#{text}"]
Expand Down Expand Up @@ -568,12 +583,37 @@ def loop_times(times)
end
end

it 'check push notification test are working' do
message_id = SecureRandom.uuid
@channel.send_message({ id: message_id, text: SecureRandom.uuid }, 'legolas')
resp = @client.check_push({ message_id: message_id, skip_devices: true, user_id: @random_user[:id] })
expect(resp['rendered_message']).not_to be_empty
end

it 'check_sqs with an invalid queue url should fail' do
resp = @client.check_sqs('key', 'secret', 'https://foo.com/bar')
expect(resp['status']).to eq 'error'
expect(resp['error']).to include 'invalid SQS url'
end

it 'can create a guest if it"s allowed' do
guest_user = @client.create_guest({ user: { id: SecureRandom.uuid } })
expect(guest_user['access_token']).not_to be_empty
rescue StreamChat::StreamAPIException
# Guest user isn't turned on for every test app, so ignore it
end

it 'can send custom events' do
@client.send_user_event(@random_user[:id], { event: { type: 'friendship-request' } })
end

it 'can translate a message' do
message_id = SecureRandom.uuid
@channel.send_message({ id: message_id, text: SecureRandom.uuid }, 'legolas')
response = @client.translate_message(message_id, 'hu')
expect(response['message']).not_to be_empty
end

describe 'custom commands' do
before(:all) do
@cmd = SecureRandom.uuid
Expand Down

0 comments on commit a25a1b6

Please sign in to comment.