vkontakte_api 1.0.4 → 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.
- 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
|