quickblox-rb 0.1.0 → 0.1.1

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
  SHA1:
3
- metadata.gz: 694963a669f27b2ee03e195281aa3468cda2ba2b
4
- data.tar.gz: 50cc70ee95e0b84634014de900634cfac75fe840
3
+ metadata.gz: a62c994036f7f4e4ffb461e24a664b029c9101b1
4
+ data.tar.gz: 30e791e6285a85be06c4d5b97e533370db23797c
5
5
  SHA512:
6
- metadata.gz: dad34d550c462ac9007a1ec770f8c493b780c55fbf489b69e6cb5f1f9600bce4f129d39b4f5af01778592e2fc9cc6b8c1f3ecedfc023a404183f8e2231c38d15
7
- data.tar.gz: a8ef607b86e59faef52641a1af729386fb7ad492c5b3140819404d068bfcfbdec94bbb21472ec0886ef027f797b0cb319f0db4d10e34f36558114c9f467c689d
6
+ metadata.gz: 6c0de68e336198bef5a9fdcb31fad0a118e10e4c6cc0fa60f2c45e5e7b68e7e759724b32c8f3f33d0828c074fe88f361cb2ab9243d175e7ef9975ca2f781ff79
7
+ data.tar.gz: 643788c04e8816b483de330ea719a65a29053e00899696f5c04c117c77b93107bc2bedd5c1bc13a89faf358ac98decb542a1e377ca904cf222f7799ec83b10f9
data/.gems CHANGED
@@ -1,3 +1,4 @@
1
1
  cutest -v 1.2.3
2
2
  mocoso -v 1.2.3
3
3
  requests -v 1.0.0
4
+ silueta -v 0.0.3
data/.gitignore CHANGED
@@ -1 +1,2 @@
1
1
  .gs/
2
+ *.gem
data/Makefile CHANGED
@@ -1,4 +1,4 @@
1
1
  build:
2
- cutest test/**/*_test.rb
2
+ RUBYLIB=./lib cutest test/**/*_test.rb
3
3
 
4
4
  .PHONY: build
data/README.md CHANGED
@@ -2,3 +2,9 @@
2
2
 
3
3
  This is a gem to work with [Quickblox API](http://quickblox.com/developers/Overview) in Ruby.
4
4
 
5
+ ## Development
6
+
7
+ 1. Install [dep](https://github.com/cyx/dep) with `gem install dep`.
8
+ 2. Run `dep install` to install dependencies.
9
+ 3. Run the tests with `make`
10
+
data/lib/models.rb ADDED
@@ -0,0 +1,75 @@
1
+ require "silueta"
2
+ require "silueta/types"
3
+
4
+ module Quickblox::Models
5
+ class Session
6
+ include Silueta
7
+
8
+ attribute :token
9
+ attribute :user_id, cast: Types::Integer
10
+ attribute :expiration, cast: ->(value) { value && DateTime.parse(value) }
11
+
12
+ def self.build(hash)
13
+ new(
14
+ token: hash.fetch("token"),
15
+ user_id: hash.fetch("user_id"),
16
+ expiration: hash.fetch("expiration")
17
+ )
18
+ end
19
+ end
20
+
21
+ class User
22
+ include Silueta
23
+
24
+ attribute :id, cast: Types::Integer
25
+ attribute :full_name
26
+ attribute :email
27
+ attribute :login
28
+ attribute :phone
29
+
30
+ def self.build(hash)
31
+ email = hash.fetch("email") || JSON.parse(hash.fetch("custom_data")).fetch("email")
32
+ new(
33
+ id: hash.fetch("id"),
34
+ full_name: hash.fetch("full_name"),
35
+ email: email,
36
+ login: hash.fetch("login"),
37
+ phone: hash.fetch("phone")
38
+ )
39
+ end
40
+ end
41
+
42
+ class Chat
43
+ include Silueta
44
+
45
+ attribute :messages
46
+ attribute :buyer
47
+ attribute :seller
48
+
49
+ def self.build(messages, buyer: nil, seller: nil)
50
+ message_models = []
51
+ if buyer && seller
52
+ message_models = messages.map do |message|
53
+ Quickblox::Models::Message.new(
54
+ created_at: message.fetch("created_at"),
55
+ text: message.fetch("message"),
56
+ dialog_id: message.fetch("chat_dialog_id"),
57
+ sender: (message.fetch("sender_id") == buyer.id ? buyer : seller)
58
+ )
59
+ end
60
+ end
61
+
62
+ new(messages: message_models, buyer: buyer, seller: seller)
63
+ end
64
+ end
65
+
66
+ class Message
67
+ include Silueta
68
+
69
+ attribute :created_at
70
+ attribute :text
71
+ attribute :dialog_id
72
+ attribute :sender
73
+ end
74
+ end
75
+
data/lib/quickblox.rb CHANGED
@@ -1,85 +1,5 @@
1
- require "requests/sugar"
2
- require "securerandom"
3
- require "json"
1
+ Quickblox = Module.new
4
2
 
5
- class Quickblox
6
- QB_ENDPOINT = "https://api.quickblox.com".freeze
7
- QB_HEADER_API_VERSION = "QuickBlox-REST-API-Version".freeze
8
- QB_HEADER_TOKEN = "QB-Token".freeze
9
-
10
- attr :auth_key,
11
- :auth_secret,
12
- :application_id,
13
- :email,
14
- :password,
15
- :session
16
-
17
- def initialize(**args)
18
- @auth_key = args.fetch(:auth_key)
19
- @auth_secret = args.fetch(:auth_secret)
20
- @application_id = args.fetch(:application_id)
21
- @email = args[:email]
22
- @password = args[:password]
23
- end
24
-
25
- def create_session
26
- data = {
27
- "application_id" => application_id,
28
- "auth_key" => auth_key,
29
- "nonce" => SecureRandom.random_number(100000),
30
- "timestamp" => Time.now.to_i,
31
- }
32
-
33
- data["user[email]"] = email if email
34
- data["user[password]"] = password if password
35
-
36
- signature = sign(data)
37
-
38
- data["signature"] = signature
39
-
40
- response = Requests.post(
41
- QB_ENDPOINT + "/session.json",
42
- headers: { QB_HEADER_API_VERSION => "0.1.1" },
43
- data: data
44
- )
45
-
46
- if response.status == 201
47
- @session = response.json.fetch("session")
48
- end
49
- end
50
-
51
- def transcript(dialog_id:)
52
- response = Requests.get(
53
- QB_ENDPOINT + "/chat/Message.json",
54
- headers: {
55
- QB_HEADER_API_VERSION => "0.1.1",
56
- QB_HEADER_TOKEN => session_token
57
- },
58
- params: {
59
- chat_dialog_id: dialog_id,
60
- mark_as_read: 0
61
- }
62
- )
63
-
64
- if response.status == 200
65
- response.json
66
- end
67
- end
68
-
69
- private
70
-
71
- def sign(data)
72
- normalized_string = data.each_key
73
- .sort
74
- .map { |key| "#{key}=#{data[key]}" }
75
- .join("&")
76
-
77
- sha1 = OpenSSL::Digest::SHA1.new
78
- OpenSSL::HMAC.hexdigest(sha1, auth_secret, normalized_string)
79
- end
80
-
81
- def session_token
82
- (@session || create_session).fetch("token")
83
- end
84
- end
3
+ require_relative "quickblox_api"
4
+ require_relative "models"
85
5
 
@@ -0,0 +1,114 @@
1
+ require "requests/sugar"
2
+ require "securerandom"
3
+ require "json"
4
+
5
+ class Quickblox::API
6
+ QB_ENDPOINT = "https://api.quickblox.com".freeze
7
+ QB_HEADER_API_VERSION = "QuickBlox-REST-API-Version".freeze
8
+ QB_HEADER_TOKEN = "QB-Token".freeze
9
+ QB_HEADER_EXPIRATION = "qb-token-expirationdate".freeze
10
+
11
+ attr :auth_key,
12
+ :auth_secret,
13
+ :application_id,
14
+ :email,
15
+ :password,
16
+ :session,
17
+ :last_response
18
+
19
+ def initialize(**args)
20
+ @auth_key = args.fetch(:auth_key)
21
+ @auth_secret = args.fetch(:auth_secret)
22
+ @application_id = args.fetch(:application_id)
23
+ @email = args[:email]
24
+ @password = args[:password]
25
+ end
26
+
27
+ def create_session
28
+ data = {
29
+ "application_id" => application_id,
30
+ "auth_key" => auth_key,
31
+ "nonce" => SecureRandom.random_number(100000),
32
+ "timestamp" => Time.now.to_i,
33
+ }
34
+
35
+ data["user[email]"] = email if email
36
+ data["user[password]"] = password if password
37
+
38
+ signature = sign(data)
39
+
40
+ data["signature"] = signature
41
+
42
+ response = Requests.post(
43
+ QB_ENDPOINT + "/session.json",
44
+ headers: { QB_HEADER_API_VERSION => "0.1.1" },
45
+ data: data
46
+ )
47
+
48
+ @last_response = response
49
+
50
+ if response.status == 201
51
+ session = response.json.fetch("session")
52
+ session["expiration"] = response.headers.fetch(QB_HEADER_EXPIRATION).first
53
+ @session = Quickblox::Models::Session.build(session)
54
+ end
55
+ end
56
+
57
+ def find_user(user_id:)
58
+ response = Requests.get(
59
+ QB_ENDPOINT + "/users/#{user_id}.json",
60
+ headers: {
61
+ QB_HEADER_API_VERSION => "0.1.1",
62
+ QB_HEADER_TOKEN => session_token
63
+ },
64
+ )
65
+
66
+ @last_response = response
67
+
68
+ if response.status == 200
69
+ user = response.json.fetch("user")
70
+ Quickblox::Models::User.build(user)
71
+ end
72
+ end
73
+
74
+ def chat_transcript(dialog_id:)
75
+ response = Requests.get(
76
+ QB_ENDPOINT + "/chat/Message.json",
77
+ headers: {
78
+ QB_HEADER_API_VERSION => "0.1.1",
79
+ QB_HEADER_TOKEN => session_token
80
+ },
81
+ params: {
82
+ chat_dialog_id: dialog_id,
83
+ mark_as_read: 0
84
+ }
85
+ )
86
+
87
+ if response.status == 200
88
+ messages = response.json.fetch("items")
89
+
90
+ buyer, seller = [
91
+ find_user(user_id: messages.first.fetch("sender_id")),
92
+ find_user(user_id: messages.first.fetch("recipient_id"))
93
+ ]
94
+
95
+ Quickblox::Models::Chat.build(messages, buyer: buyer, seller: seller)
96
+ end
97
+ end
98
+
99
+ private
100
+
101
+ def sign(data)
102
+ normalized_string = data.each_key
103
+ .sort
104
+ .map { |key| "#{key}=#{data[key]}" }
105
+ .join("&")
106
+
107
+ sha1 = OpenSSL::Digest::SHA1.new
108
+ OpenSSL::HMAC.hexdigest(sha1, auth_secret, normalized_string)
109
+ end
110
+
111
+ def session_token
112
+ (@session || create_session).token
113
+ end
114
+ end
data/quickblox-rb.gemspec CHANGED
@@ -1,6 +1,6 @@
1
1
  Gem::Specification.new do |s|
2
2
  s.name = "quickblox-rb"
3
- s.version = "0.1.0"
3
+ s.version = "0.1.1"
4
4
  s.summary = "Ruby gem to work with Quickblox API"
5
5
  s.description = s.summary
6
6
  s.authors = ["Lucas Tolchinsky"]
@@ -11,6 +11,7 @@ Gem::Specification.new do |s|
11
11
  s.files = `git ls-files`.split("\n")
12
12
 
13
13
  s.add_runtime_dependency "requests"
14
+ s.add_runtime_dependency "silueta"
14
15
 
15
16
  s.add_development_dependency "cutest"
16
17
  s.add_development_dependency "mocoso"
@@ -0,0 +1,148 @@
1
+ require "cutest"
2
+ require "mocoso"
3
+ require "quickblox"
4
+ require "date"
5
+ require_relative "quickblox_responses"
6
+
7
+ include Mocoso
8
+
9
+ scope "initialization" do
10
+ test "with application credentials" do
11
+ qb = Quickblox::API.new(
12
+ auth_key: "AUTH_KEY",
13
+ auth_secret: "AUTH_SECRET",
14
+ application_id: 1234,
15
+ )
16
+
17
+ assert_equal "AUTH_KEY", qb.auth_key
18
+ assert_equal "AUTH_SECRET", qb.auth_secret
19
+ assert_equal 1234, qb.application_id
20
+ assert qb.email.nil?
21
+ assert qb.password.nil?
22
+ end
23
+
24
+ test "with user credentials" do
25
+ qb = Quickblox::API.new(
26
+ auth_key: "AUTH_KEY",
27
+ auth_secret: "AUTH_SECRET",
28
+ application_id: 1234,
29
+ email: "account@owner.com",
30
+ password: "foobarbaz"
31
+ )
32
+
33
+ assert_equal "AUTH_KEY", qb.auth_key
34
+ assert_equal "AUTH_SECRET", qb.auth_secret
35
+ assert_equal 1234, qb.application_id
36
+ assert_equal "account@owner.com", qb.email
37
+ assert_equal "foobarbaz", qb.password
38
+ end
39
+ end
40
+
41
+ test "#create_session" do
42
+ qb = Quickblox::API.new(
43
+ auth_key: "AUTH_KEY",
44
+ auth_secret: "AUTH_SECRET",
45
+ application_id: 1234,
46
+ email: "account@owner.com",
47
+ password: "foobarbaz"
48
+ )
49
+
50
+ # This is a real life example of a response to POST /session.json
51
+ # We only care about the expiration header.
52
+ mock_response = Requests::Response.new(
53
+ 201,
54
+ { "qb-token-expirationdate" => ["2016-05-02 19:52:00 UTC"] },
55
+ QB_RESPONSES.fetch(:session)
56
+ )
57
+
58
+ assert qb.session.nil?
59
+
60
+ stub(Requests, :request, mock_response) { qb.create_session }
61
+
62
+ assert qb.session
63
+ assert_equal Quickblox::Models::Session, qb.session.class
64
+ assert_equal "le-token-stuff", qb.session.token
65
+ assert_equal DateTime.parse("2016-05-02 19:52:00 UTC"), qb.session.expiration
66
+ end
67
+
68
+ test "#last_response" do
69
+ qb = Quickblox::API.new(
70
+ auth_key: "AUTH_KEY",
71
+ auth_secret: "AUTH_SECRET",
72
+ application_id: 1234,
73
+ email: "account@owner.com",
74
+ password: "foobarbaz"
75
+ )
76
+
77
+ mock_response = Requests::Response.new(
78
+ 201,
79
+ { "qb-token-expirationdate" => ["2016-05-02 19:52:00 UTC"] },
80
+ "{\"session\": {\"token\":\"le-token\",\"user_id\":\"5\"}}"
81
+ )
82
+
83
+ assert qb.last_response.nil?
84
+
85
+ stub(Requests, :request, mock_response) { qb.create_session }
86
+
87
+ assert_equal mock_response, qb.last_response
88
+ end
89
+
90
+ test "#find_user" do
91
+ qb = Quickblox::API.new(
92
+ auth_key: "AUTH_KEY",
93
+ auth_secret: "AUTH_SECRET",
94
+ application_id: 1234,
95
+ email: "account@owner.com",
96
+ password: "foobarbaz"
97
+ )
98
+
99
+ mock_response = Requests::Response.new(200, {}, QB_RESPONSES.fetch(:user))
100
+
101
+ user = stub(Requests, :request, mock_response) do
102
+ stub(qb, :session_token, "token") { qb.find_user(user_id: 900) }
103
+ end
104
+
105
+ assert user
106
+ assert_equal Quickblox::Models::User, user.class
107
+ assert_equal 900, user.id
108
+ assert_equal "mister@one.com", user.email
109
+ assert_equal "Mr One", user.full_name
110
+ assert_equal "1133445566", user.phone
111
+ assert_equal "One", user.login
112
+ end
113
+
114
+ test "#chat_transcript" do
115
+ qb = Quickblox::API.new(
116
+ auth_key: "AUTH_KEY",
117
+ auth_secret: "AUTH_SECRET",
118
+ application_id: 1234,
119
+ email: "account@owner.com",
120
+ password: "foobarbaz"
121
+ )
122
+
123
+ mock_response = Requests::Response.new(200, {}, QB_RESPONSES.fetch(:messages))
124
+
125
+ mock_user = Quickblox::Models::User.new(
126
+ id: 12243767,
127
+ email: "bar@foo.com",
128
+ full_name: "User",
129
+ )
130
+
131
+ chat = stub(Requests, :request, mock_response) do
132
+ stub(qb, :find_user, mock_user) do
133
+ stub(qb, :session_token, "token") { qb.chat_transcript(dialog_id: "5727676fa28f9a49") }
134
+ end
135
+ end
136
+
137
+ assert chat
138
+ assert_equal Quickblox::Models::Chat, chat.class
139
+ assert_equal mock_user, chat.buyer
140
+ assert_equal mock_user, chat.seller
141
+ assert_equal 1, chat.messages.size
142
+
143
+ message = chat.messages.first
144
+ assert message
145
+ assert_equal Quickblox::Models::Message, message.class
146
+ assert_equal mock_user, message.sender
147
+ end
148
+
@@ -0,0 +1,5 @@
1
+ QB_RESPONSES = {
2
+ session: "{\"session\":{\"_id\":\"572793c0a28f9a658800002a\",\"application_id\":35265,\"created_at\":\"2016-05-02T17:52:00Z\",\"device_id\":0,\"nonce\":29601,\"token\":\"le-token-stuff\",\"ts\":1462211496,\"updated_at\":\"2016-05-02T17:52:00Z\",\"user_id\":0,\"id\":18862}}",
3
+ user: "{\"user\":{\"id\":900,\"owner_id\":45,\"full_name\":\"Mr One\",\"email\":\"mister@one.com\",\"login\":\"One\",\"phone\":\"1133445566\",\"website\":null,\"created_at\":\"2016-02-10T12:07:50Z\",\"updated_at\":\"2016-03-16T17:42:27Z\",\"last_request_at\":\"2016-03-17T12:34:00Z\",\"external_user_id\":null,\"facebook_id\":null,\"twitter_id\":null,\"blob_id\":null,\"custom_data\":null,\"twitter_digits_id\":null,\"user_tags\":\"tag1,tag2\"}}",
4
+ messages: "{\"skip\":0,\"limit\":100,\"items\":[{\"_id\":\"5727677a28fee63e74000000\",\"attachments\":[],\"chat_dialog_id\":\"5727676fa28f9a49\",\"created_at\":\"2016-05-02T14:43:07Z\",\"date_sent\":1462200187,\"delivered_ids\":[12243767,11716786],\"message\":\"Hola buen d\xC3\xADa\",\"read_ids\":[12243767,11716786],\"recipient_id\":100,\"sender_id\":100,\"updated_at\":\"2016-05-02T15:01:48Z\",\"read\":1}]}",
5
+ }
metadata CHANGED
@@ -1,14 +1,14 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: quickblox-rb
3
3
  version: !ruby/object:Gem::Version
4
- version: 0.1.0
4
+ version: 0.1.1
5
5
  platform: ruby
6
6
  authors:
7
7
  - Lucas Tolchinsky
8
8
  autorequire:
9
9
  bindir: bin
10
10
  cert_chain: []
11
- date: 2016-05-02 00:00:00.000000000 Z
11
+ date: 2016-05-03 00:00:00.000000000 Z
12
12
  dependencies:
13
13
  - !ruby/object:Gem::Dependency
14
14
  name: requests
@@ -24,6 +24,20 @@ dependencies:
24
24
  - - ">="
25
25
  - !ruby/object:Gem::Version
26
26
  version: '0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: silueta
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ">="
32
+ - !ruby/object:Gem::Version
33
+ version: '0'
34
+ type: :runtime
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ">="
39
+ - !ruby/object:Gem::Version
40
+ version: '0'
27
41
  - !ruby/object:Gem::Dependency
28
42
  name: cutest
29
43
  requirement: !ruby/object:Gem::Requirement
@@ -63,9 +77,12 @@ files:
63
77
  - ".gitignore"
64
78
  - Makefile
65
79
  - README.md
80
+ - lib/models.rb
66
81
  - lib/quickblox.rb
82
+ - lib/quickblox_api.rb
67
83
  - quickblox-rb.gemspec
68
- - test/quickblox_test.rb
84
+ - test/quickblox_api_test.rb
85
+ - test/quickblox_responses.rb
69
86
  homepage: https://github.com/properati/quickblox-rb
70
87
  licenses:
71
88
  - MIT
@@ -1,79 +0,0 @@
1
- require "cutest"
2
- require "mocoso"
3
- require_relative "../lib/quickblox"
4
-
5
- include Mocoso
6
-
7
- scope "initialization" do
8
- test "with application credentials" do
9
- qb = Quickblox.new(
10
- auth_key: "AUTH_KEY",
11
- auth_secret: "AUTH_SECRET",
12
- application_id: 1234,
13
- )
14
-
15
- assert_equal "AUTH_KEY", qb.auth_key
16
- assert_equal "AUTH_SECRET", qb.auth_secret
17
- assert_equal 1234, qb.application_id
18
- assert qb.email.nil?
19
- assert qb.password.nil?
20
- end
21
-
22
- test "with user credentials" do
23
- qb = Quickblox.new(
24
- auth_key: "AUTH_KEY",
25
- auth_secret: "AUTH_SECRET",
26
- application_id: 1234,
27
- email: "account@owner.com",
28
- password: "foobarbaz"
29
- )
30
-
31
- assert_equal "AUTH_KEY", qb.auth_key
32
- assert_equal "AUTH_SECRET", qb.auth_secret
33
- assert_equal 1234, qb.application_id
34
- assert_equal "account@owner.com", qb.email
35
- assert_equal "foobarbaz", qb.password
36
- end
37
- end
38
-
39
- test "create session" do
40
- qb = Quickblox.new(
41
- auth_key: "AUTH_KEY",
42
- auth_secret: "AUTH_SECRET",
43
- application_id: 1234,
44
- email: "account@owner.com",
45
- password: "foobarbaz"
46
- )
47
-
48
- # This is a real life example of a response to POST /session.json
49
- mock_response = Requests::Response.new(
50
- 201,
51
- {
52
- "access-control-allow-origin"=>["*"],
53
- "cache-control"=>["max-age=0, private, must-revalidate"],
54
- "content-type"=>["application/json; charset=utf-8"],
55
- "date"=>["Mon, 02 May 2016 17:52:01 GMT"],
56
- "etag"=>["\"442ceb087b8b83fee1ba7f28e082caca\""],
57
- "qb-token-expirationdate"=>["2016-05-02 19:52:00 UTC"],
58
- "quickblox-rest-api-version"=>["0.1.1"],
59
- "server"=>["nginx/1.8.1"],
60
- "status"=>["201 Created"],
61
- "strict-transport-security"=>["max-age=15768000;"],
62
- "x-rack-cache"=>["invalidate, pass"],
63
- "x-request-id"=>["2d7b3f554389b95e8561d89fc77104bd"],
64
- "x-runtime"=>["0.014038"],
65
- "x-ua-compatible"=>["IE=Edge,chrome=1"],
66
- "content-length"=>["259"],
67
- "connection"=>["keep-alive"]
68
- },
69
- "{\"session\":{\"_id\":\"572793c0a28f9a658800002a\",\"application_id\":35265,\"created_at\":\"2016-05-02T17:52:00Z\",\"device_id\":0,\"nonce\":29601,\"token\":\"le-token-stuff\",\"ts\":1462211496,\"updated_at\":\"2016-05-02T17:52:00Z\",\"user_id\":0,\"id\":18862}}"
70
- )
71
-
72
- assert qb.session.nil?
73
-
74
- stub(Requests, :request, mock_response) { qb.create_session }
75
-
76
- assert qb.session
77
- assert_equal "le-token-stuff", qb.session.fetch("token")
78
- end
79
-