vkontakte_api 1.0.4 → 1.1
Sign up to get free protection for your applications and to get access to all the features.
- data/CHANGELOG.md +7 -0
- data/Guardfile +7 -0
- data/README.md +39 -6
- data/lib/vkontakte_api/authorization.rb +4 -2
- data/lib/vkontakte_api/client.rb +47 -3
- data/lib/vkontakte_api/configuration.rb +1 -1
- data/lib/vkontakte_api/logger.rb +1 -0
- data/lib/vkontakte_api/version.rb +1 -1
- data/spec/vkontakte_api/api_spec.rb +1 -1
- data/spec/vkontakte_api/authorization_spec.rb +4 -4
- data/spec/vkontakte_api/client_spec.rb +67 -1
- data/spec/vkontakte_api/logger_spec.rb +13 -1
- data/vkontakte_api.gemspec +3 -0
- metadata +51 -2
data/CHANGELOG.md
CHANGED
data/Guardfile
ADDED
data/README.md
CHANGED
@@ -136,6 +136,41 @@ VkontakteApi.authorization_url(type: :client, scope: [:friends, :photos])
|
|
136
136
|
@vk = VkontakteApi.authorize(type: :app_server)
|
137
137
|
```
|
138
138
|
|
139
|
+
### Прочее
|
140
|
+
|
141
|
+
Если клиент API (объект класса `VkontakteApi::Client`) был создан с помощью метода `VkontakteApi.authorize`, он будет содержать информацию об id текущего пользователя (`user_id`) и о времени истечения токена (`expires_at`). Получить их можно с помощью соответствующих методов:
|
142
|
+
|
143
|
+
``` ruby
|
144
|
+
vk = VkontakteApi.authorize(code: 'c1493e81f69fce1b43')
|
145
|
+
# => #<VkontakteApi::Client:0x007fa578f00ad0>
|
146
|
+
vk.user_id # => 628985
|
147
|
+
vk.expires_at # => 2012-12-18 23:22:55 +0400
|
148
|
+
# можно проверить, истекло ли время жизни токена
|
149
|
+
vk.expired? # => false
|
150
|
+
```
|
151
|
+
|
152
|
+
Также можно получить список прав доступа, которые дает данный токен, в виде, аналогичном формату параметра `scope` в авторизации:
|
153
|
+
|
154
|
+
``` ruby
|
155
|
+
vk.scope # => [:friends, :groups]
|
156
|
+
```
|
157
|
+
|
158
|
+
Это работает на основе метода `getUserSettings`, причем результат запоминается после первого обращения.
|
159
|
+
|
160
|
+
Чтобы создать короткий синоним `VK` для модуля `VkontakteApi`, достаточно вызвать метод `VkontakteApi.register_alias`:
|
161
|
+
|
162
|
+
``` ruby
|
163
|
+
VkontakteApi.register_alias
|
164
|
+
VK::Client.new # => #<VkontakteApi::Client:0x007fa578d6d948>
|
165
|
+
```
|
166
|
+
|
167
|
+
При необходимости можно удалить синоним методом `VkontakteApi.unregister_alias`:
|
168
|
+
|
169
|
+
``` ruby
|
170
|
+
VK.unregister_alias
|
171
|
+
VK # => NameError: uninitialized constant VK
|
172
|
+
```
|
173
|
+
|
139
174
|
### Обработка ошибок
|
140
175
|
|
141
176
|
Если ВКонтакте API возвращает ошибку, выбрасывается исключение класса `VkontakteApi::Error`.
|
@@ -179,7 +214,7 @@ VkontakteApi.configure do |config|
|
|
179
214
|
# faraday-адаптер для сетевых запросов
|
180
215
|
config.adapter = :net_http
|
181
216
|
# HTTP-метод для вызова методов API (:get или :post)
|
182
|
-
config.http_verb = :
|
217
|
+
config.http_verb = :post
|
183
218
|
# параметры для faraday-соединения
|
184
219
|
config.faraday_options = {
|
185
220
|
ssl: {
|
@@ -198,14 +233,11 @@ VkontakteApi.configure do |config|
|
|
198
233
|
config.log_errors = true # ошибки
|
199
234
|
config.log_responses = false # удачные ответы
|
200
235
|
end
|
201
|
-
|
202
|
-
# создание короткого алиаса VK для модуля VkontakteApi
|
203
|
-
VkontakteApi.register_alias
|
204
236
|
```
|
205
237
|
|
206
238
|
По умолчанию для HTTP-запросов используется `Net::HTTP`; можно выбрать [любой другой адаптер](https://github.com/technoweenie/faraday/blob/master/lib/faraday/adapter.rb), поддерживаемый `faraday`.
|
207
239
|
|
208
|
-
ВКонтакте [позволяет](http://vk.com/developers.php?oid=-1&p=%D0%92%D1%8B%D0%BF%D0%BE%D0%BB%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5_%D0%B7%D0%B0%D0%BF%D1%80%D0%BE%D1%81%D0%BE%D0%B2_%D0%BA_API) использовать как `GET`-, так и `POST`-запросы при вызове методов API. По умолчанию `vkontakte_api` использует `
|
240
|
+
ВКонтакте [позволяет](http://vk.com/developers.php?oid=-1&p=%D0%92%D1%8B%D0%BF%D0%BE%D0%BB%D0%BD%D0%B5%D0%BD%D0%B8%D0%B5_%D0%B7%D0%B0%D0%BF%D1%80%D0%BE%D1%81%D0%BE%D0%B2_%D0%BA_API) использовать как `GET`-, так и `POST`-запросы при вызове методов API. По умолчанию `vkontakte_api` использует `POST`, но в настройке `http_verb` можно указать `:get`, чтобы совершать `GET`-запросы.
|
209
241
|
|
210
242
|
При необходимости можно указать параметры для faraday-соединения - например, параметры прокси-сервера или путь к SSL-сертификатам.
|
211
243
|
|
@@ -225,7 +257,8 @@ $ rails generate vkontakte_api:install
|
|
225
257
|
## Roadmap
|
226
258
|
|
227
259
|
* метод, возвращающий права текущего токена в читабельной форме (используя `getUserSettings` и кэшируя результат)
|
228
|
-
* сохранение параметра `
|
260
|
+
* сохранение параметра `expires_at` токена в объекте `VkontakteApi::Client` после авторизации через `VkontakteApi.authorize`
|
261
|
+
* метод `VkontakteApi::Client#offline?`, проверяющий, является ли токен бесконечным, используя значение `VkontakteApi::Client#expires_at`
|
229
262
|
* `POST`-запросы по умолчанию
|
230
263
|
* логгирование тела `POST`-запроса
|
231
264
|
|
@@ -45,12 +45,14 @@ module VkontakteApi
|
|
45
45
|
def authorize(options = {})
|
46
46
|
type = options.delete(:type) || :site
|
47
47
|
|
48
|
+
options[:redirect_uri] ||= VkontakteApi.redirect_uri
|
49
|
+
|
48
50
|
case type
|
49
51
|
when :site
|
50
52
|
code = options.delete(:code)
|
51
|
-
token = client.auth_code.get_token(code)
|
53
|
+
token = client.auth_code.get_token(code, options)
|
52
54
|
when :app_server
|
53
|
-
token = client.client_credentials.get_token(
|
55
|
+
token = client.client_credentials.get_token(options, OPTIONS[:client_credentials].dup)
|
54
56
|
else
|
55
57
|
raise ArgumentError, "Unknown authorization type #{type.inspect}"
|
56
58
|
end
|
data/lib/vkontakte_api/client.rb
CHANGED
@@ -3,22 +3,48 @@ module VkontakteApi
|
|
3
3
|
class Client
|
4
4
|
include Resolver
|
5
5
|
|
6
|
+
# Access rights and their respective number representation.
|
7
|
+
SCOPE = {
|
8
|
+
:notify => 1,
|
9
|
+
:friends => 2,
|
10
|
+
:photos => 4,
|
11
|
+
:audio => 8,
|
12
|
+
:video => 16,
|
13
|
+
:offers => 32,
|
14
|
+
:questions => 64,
|
15
|
+
:pages => 128,
|
16
|
+
:status => 1024,
|
17
|
+
:notes => 2048,
|
18
|
+
:messages => 4096,
|
19
|
+
:wall => 8192,
|
20
|
+
:ads => 32768,
|
21
|
+
:docs => 131072,
|
22
|
+
:groups => 262144,
|
23
|
+
:notifications => 524288,
|
24
|
+
:stats => 1048576
|
25
|
+
}
|
26
|
+
|
6
27
|
# An access token needed by authorized requests.
|
7
28
|
# @return [String]
|
8
29
|
attr_reader :token
|
9
30
|
# Current user id.
|
10
31
|
# @return [Integer]
|
11
32
|
attr_reader :user_id
|
33
|
+
# Token expiration time
|
34
|
+
# @return [Time]
|
35
|
+
attr_reader :expires_at
|
12
36
|
|
13
37
|
# A new API client.
|
14
38
|
# If given an `OAuth2::AccessToken` instance, it extracts and keeps
|
15
|
-
# the token string
|
39
|
+
# the token string, the user id and the expiration time;
|
40
|
+
# otherwise it just stores the given token.
|
16
41
|
# @param [String, OAuth2::AccessToken] token An access token.
|
17
42
|
def initialize(token = nil)
|
18
43
|
if token.respond_to?(:token) && token.respond_to?(:params)
|
19
44
|
# token is an OAuth2::AccessToken
|
20
|
-
@token
|
21
|
-
@user_id
|
45
|
+
@token = token.token
|
46
|
+
@user_id = token.params['user_id']
|
47
|
+
@expires_at = Time.at(token.expires_at) unless token.expires_at.nil?
|
22
48
|
else
|
23
49
|
# token is a String or nil
|
24
50
|
@token = token
|
@@ -29,5 +55,23 @@ module VkontakteApi
|
|
29
55
|
def authorized?
|
30
56
|
!@token.nil?
|
31
57
|
end
|
58
|
+
|
59
|
+
# Did the token already expire.
|
60
|
+
def expired?
|
61
|
+
@expires_at && @expires_at < Time.now
|
62
|
+
end
|
63
|
+
|
64
|
+
# Access rights of this token.
|
65
|
+
# @return [Array] An array of symbols representing the access rights.
|
66
|
+
def scope
|
67
|
+
SCOPE.reject do |access_scope, mask|
|
68
|
+
(settings & mask).zero?
|
69
|
+
end.keys
|
70
|
+
end
|
71
|
+
|
72
|
+
private
|
73
|
+
def settings
|
74
|
+
@settings ||= self.get_user_settings
|
75
|
+
end
|
32
76
|
end
|
33
77
|
end
|
data/lib/vkontakte_api/logger.rb
CHANGED
@@ -13,8 +13,8 @@ describe VkontakteApi::Authorization do
|
|
13
13
|
@token = stub("Token")
|
14
14
|
|
15
15
|
@auth_code = stub("Authorization code strategy", :get_token => @token, :authorize_url => @url)
|
16
|
-
@implicit = stub("Implicit strategy",
|
17
|
-
@client_credentials = stub("Client credentials strategy",
|
16
|
+
@implicit = stub("Implicit strategy", :authorize_url => @url)
|
17
|
+
@client_credentials = stub("Client credentials strategy", :get_token => @token)
|
18
18
|
|
19
19
|
@client = stub("OAuth2::Client instance", :auth_code => @auth_code, :implicit => @implicit, :client_credentials => @client_credentials)
|
20
20
|
OAuth2::Client.stub(:new).and_return(@client)
|
@@ -70,14 +70,14 @@ describe VkontakteApi::Authorization do
|
|
70
70
|
end
|
71
71
|
|
72
72
|
it "gets the token" do
|
73
|
-
@auth_code.should_receive(:get_token).with(@code)
|
73
|
+
@auth_code.should_receive(:get_token).with(@code, {:redirect_uri => @redirect_uri})
|
74
74
|
@auth.authorize(:type => :site, :code => @code)
|
75
75
|
end
|
76
76
|
end
|
77
77
|
|
78
78
|
context "with an app_server type" do
|
79
79
|
it "gets the token" do
|
80
|
-
@client_credentials.should_receive(:get_token).with({}, subject::OPTIONS[:client_credentials])
|
80
|
+
@client_credentials.should_receive(:get_token).with({:redirect_uri => @redirect_uri}, subject::OPTIONS[:client_credentials])
|
81
81
|
@auth.authorize(:type => :app_server)
|
82
82
|
end
|
83
83
|
end
|
@@ -4,7 +4,12 @@ describe VkontakteApi::Client do
|
|
4
4
|
before(:each) do
|
5
5
|
@user_id = stub("User id")
|
6
6
|
@string_token = stub("Access token as a String")
|
7
|
-
@
|
7
|
+
@expires_at = Time.now - 2 * 60 * 60 # 2.hours.ago
|
8
|
+
|
9
|
+
@oauth2_token = stub("Access token as an OAuth2::AccessToken")
|
10
|
+
@oauth2_token.stub(:token).and_return(@string_token)
|
11
|
+
@oauth2_token.stub(:params).and_return('user_id' => @user_id)
|
12
|
+
@oauth2_token.stub(:expires_at).and_return(@expires_at)
|
8
13
|
end
|
9
14
|
|
10
15
|
describe "#initialize" do
|
@@ -28,6 +33,9 @@ describe VkontakteApi::Client do
|
|
28
33
|
client = VkontakteApi::Client.new(@oauth2_token)
|
29
34
|
client.token.should == @string_token
|
30
35
|
client.user_id.should == @user_id
|
36
|
+
|
37
|
+
client.expires_at.should be_a(Time)
|
38
|
+
client.expires_at.should be < Time.now
|
31
39
|
end
|
32
40
|
end
|
33
41
|
end
|
@@ -46,4 +54,62 @@ describe VkontakteApi::Client do
|
|
46
54
|
end
|
47
55
|
end
|
48
56
|
end
|
57
|
+
|
58
|
+
describe "#expired?" do
|
59
|
+
context "with an expired token" do
|
60
|
+
before(:each) do
|
61
|
+
@client = VkontakteApi::Client.new(@oauth2_token)
|
62
|
+
end
|
63
|
+
|
64
|
+
it "returns true" do
|
65
|
+
@client.should be_expired
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
context "with an actual token" do
|
70
|
+
before(:each) do
|
71
|
+
@oauth2_token.stub(:expires_at).and_return(Time.now + 2 * 24 * 60 * 60) # 2.days.from_now
|
72
|
+
@client = VkontakteApi::Client.new(@oauth2_token)
|
73
|
+
end
|
74
|
+
|
75
|
+
it "returns false" do
|
76
|
+
@client.should_not be_expired
|
77
|
+
end
|
78
|
+
end
|
79
|
+
|
80
|
+
context "with a String token" do
|
81
|
+
before(:each) do
|
82
|
+
@client = VkontakteApi::Client.new(@string_token)
|
83
|
+
end
|
84
|
+
|
85
|
+
it "returns false" do
|
86
|
+
@client.should_not be_expired
|
87
|
+
end
|
88
|
+
end
|
89
|
+
end
|
90
|
+
|
91
|
+
describe "#scope" do
|
92
|
+
before(:each) do
|
93
|
+
@client = VkontakteApi::Client.new
|
94
|
+
@client.stub(:get_user_settings).and_return(865310)
|
95
|
+
end
|
96
|
+
|
97
|
+
it "returns an array of access rights" do
|
98
|
+
scopes_array = @client.scope
|
99
|
+
|
100
|
+
[
|
101
|
+
:friends,
|
102
|
+
:photos,
|
103
|
+
:audio,
|
104
|
+
:video,
|
105
|
+
:status,
|
106
|
+
:messages,
|
107
|
+
:wall,
|
108
|
+
:groups,
|
109
|
+
:notifications
|
110
|
+
].each do |access_scope|
|
111
|
+
scopes_array.should include(access_scope)
|
112
|
+
end
|
113
|
+
end
|
114
|
+
end
|
49
115
|
end
|
@@ -6,6 +6,7 @@ describe VkontakteApi::Logger do
|
|
6
6
|
@fail_response = Oj.dump('error' => 404)
|
7
7
|
|
8
8
|
@connection = Faraday.new(:url => 'http://example.com') do |builder|
|
9
|
+
builder.request :url_encoded
|
9
10
|
builder.response :vk_logger
|
10
11
|
builder.response :mashify
|
11
12
|
builder.response :oj, :preserve_raw => true
|
@@ -14,6 +15,9 @@ describe VkontakteApi::Logger do
|
|
14
15
|
stub.get('/success') do
|
15
16
|
[200, {}, @success_response]
|
16
17
|
end
|
18
|
+
stub.post('/success') do
|
19
|
+
[200, {}, @success_response]
|
20
|
+
end
|
17
21
|
stub.get('/fail') do
|
18
22
|
[200, {}, @fail_response]
|
19
23
|
end
|
@@ -33,10 +37,18 @@ describe VkontakteApi::Logger do
|
|
33
37
|
VkontakteApi.log_requests = true
|
34
38
|
end
|
35
39
|
|
36
|
-
it "logs the request" do
|
40
|
+
it "logs the request URL" do
|
37
41
|
@logger.should_receive(:debug).with('GET http://example.com/success')
|
38
42
|
@connection.get('/success')
|
39
43
|
end
|
44
|
+
|
45
|
+
context "with a POST request" do
|
46
|
+
it "logs the request URL and the request body" do
|
47
|
+
@logger.should_receive(:debug).with('POST http://example.com/success')
|
48
|
+
@logger.should_receive(:debug).with('body: "param=1"')
|
49
|
+
@connection.post('/success', :param => 1)
|
50
|
+
end
|
51
|
+
end
|
40
52
|
end
|
41
53
|
|
42
54
|
context "without VkontakteApi.log_requests?" do
|
data/vkontakte_api.gemspec
CHANGED
@@ -24,6 +24,9 @@ Gem::Specification.new do |s|
|
|
24
24
|
|
25
25
|
s.add_development_dependency 'rake'
|
26
26
|
s.add_development_dependency 'rspec'
|
27
|
+
s.add_development_dependency 'guard-rspec'
|
28
|
+
s.add_development_dependency 'rb-fsevent', '~> 0.9.1'
|
29
|
+
s.add_development_dependency 'terminal-notifier-guard'
|
27
30
|
s.add_development_dependency 'pry'
|
28
31
|
s.add_development_dependency 'awesome_print'
|
29
32
|
end
|
metadata
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: vkontakte_api
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 1.
|
4
|
+
version: '1.1'
|
5
5
|
prerelease:
|
6
6
|
platform: ruby
|
7
7
|
authors:
|
@@ -9,7 +9,7 @@ authors:
|
|
9
9
|
autorequire:
|
10
10
|
bindir: bin
|
11
11
|
cert_chain: []
|
12
|
-
date: 2012-
|
12
|
+
date: 2012-12-17 00:00:00.000000000 Z
|
13
13
|
dependencies:
|
14
14
|
- !ruby/object:Gem::Dependency
|
15
15
|
name: faraday
|
@@ -123,6 +123,54 @@ dependencies:
|
|
123
123
|
- - ! '>='
|
124
124
|
- !ruby/object:Gem::Version
|
125
125
|
version: '0'
|
126
|
+
- !ruby/object:Gem::Dependency
|
127
|
+
name: guard-rspec
|
128
|
+
requirement: !ruby/object:Gem::Requirement
|
129
|
+
none: false
|
130
|
+
requirements:
|
131
|
+
- - ! '>='
|
132
|
+
- !ruby/object:Gem::Version
|
133
|
+
version: '0'
|
134
|
+
type: :development
|
135
|
+
prerelease: false
|
136
|
+
version_requirements: !ruby/object:Gem::Requirement
|
137
|
+
none: false
|
138
|
+
requirements:
|
139
|
+
- - ! '>='
|
140
|
+
- !ruby/object:Gem::Version
|
141
|
+
version: '0'
|
142
|
+
- !ruby/object:Gem::Dependency
|
143
|
+
name: rb-fsevent
|
144
|
+
requirement: !ruby/object:Gem::Requirement
|
145
|
+
none: false
|
146
|
+
requirements:
|
147
|
+
- - ~>
|
148
|
+
- !ruby/object:Gem::Version
|
149
|
+
version: 0.9.1
|
150
|
+
type: :development
|
151
|
+
prerelease: false
|
152
|
+
version_requirements: !ruby/object:Gem::Requirement
|
153
|
+
none: false
|
154
|
+
requirements:
|
155
|
+
- - ~>
|
156
|
+
- !ruby/object:Gem::Version
|
157
|
+
version: 0.9.1
|
158
|
+
- !ruby/object:Gem::Dependency
|
159
|
+
name: terminal-notifier-guard
|
160
|
+
requirement: !ruby/object:Gem::Requirement
|
161
|
+
none: false
|
162
|
+
requirements:
|
163
|
+
- - ! '>='
|
164
|
+
- !ruby/object:Gem::Version
|
165
|
+
version: '0'
|
166
|
+
type: :development
|
167
|
+
prerelease: false
|
168
|
+
version_requirements: !ruby/object:Gem::Requirement
|
169
|
+
none: false
|
170
|
+
requirements:
|
171
|
+
- - ! '>='
|
172
|
+
- !ruby/object:Gem::Version
|
173
|
+
version: '0'
|
126
174
|
- !ruby/object:Gem::Dependency
|
127
175
|
name: pry
|
128
176
|
requirement: !ruby/object:Gem::Requirement
|
@@ -170,6 +218,7 @@ files:
|
|
170
218
|
- .yardopts
|
171
219
|
- CHANGELOG.md
|
172
220
|
- Gemfile
|
221
|
+
- Guardfile
|
173
222
|
- MIT-LICENSE
|
174
223
|
- README.md
|
175
224
|
- Rakefile
|