vkontakte_api 1.1 → 1.2
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 +7 -0
- data/.gitignore +1 -0
- data/.travis.yml +1 -2
- data/CHANGELOG.md +6 -0
- data/Gemfile +1 -1
- data/README.md +13 -10
- data/Rakefile +2 -2
- data/lib/vkontakte_api/api.rb +3 -2
- data/lib/vkontakte_api/authorization.rb +5 -5
- data/lib/vkontakte_api/client.rb +17 -17
- data/lib/vkontakte_api/configuration.rb +8 -3
- data/lib/vkontakte_api/error.rb +9 -0
- data/lib/vkontakte_api/logger.rb +1 -1
- data/lib/vkontakte_api/namespaces.yml +3 -0
- data/lib/vkontakte_api/resolver.rb +11 -3
- data/lib/vkontakte_api/version.rb +1 -1
- data/spec/integration_spec.rb +25 -23
- data/spec/spec_helper.rb +2 -0
- data/spec/support/mechanized_authorization.rb +57 -0
- data/spec/vkontakte_api/api_spec.rb +11 -11
- data/spec/vkontakte_api/authorization_spec.rb +26 -26
- data/spec/vkontakte_api/client_spec.rb +3 -3
- data/spec/vkontakte_api/error_spec.rb +10 -10
- data/spec/vkontakte_api/logger_spec.rb +4 -4
- data/spec/vkontakte_api/method_spec.rb +7 -7
- data/spec/vkontakte_api/resolvable_spec.rb +4 -4
- data/spec/vkontakte_api/resolver_spec.rb +26 -12
- data/spec/vkontakte_api/result_spec.rb +13 -13
- data/spec/vkontakte_api/uploading_spec.rb +12 -12
- data/spec/vkontakte_api/utils_spec.rb +6 -6
- data/spec/vkontakte_api_spec.rb +1 -1
- data/vkontakte_api.gemspec +5 -2
- metadata +40 -51
checksums.yaml
ADDED
@@ -0,0 +1,7 @@
|
|
1
|
+
---
|
2
|
+
SHA1:
|
3
|
+
metadata.gz: d37878c023a9ef41c525a2e80d94a1116bf7cdf4
|
4
|
+
data.tar.gz: d6bee0ae8a1dfa7a74d74e26327f5cf880214e9b
|
5
|
+
SHA512:
|
6
|
+
metadata.gz: 100e3698409e4c1c76ac1adbbb75609675b92c965905e5218b32cc5f1dae49d0f69783db01bb7ca5729e724bae8e4718e0f3ffc7cb8ec8cc86a87a7e0d399301
|
7
|
+
data.tar.gz: 43b9a423fd114d904b395f34fdf510eb72a48657722b2a88c2e15f82bdb8544b6aa2180fe8eb225a3e28aec20b12bbf3bc31cabb788f1f34739f62457d7ada19
|
data/.gitignore
CHANGED
data/.travis.yml
CHANGED
data/CHANGELOG.md
CHANGED
data/Gemfile
CHANGED
data/README.md
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
## vkontakte_api [](http://travis-ci.org/7even/vkontakte_api) [](https://gemnasium.com/7even/vkontakte_api) [](http://travis-ci.org/7even/vkontakte_api) [](http://badge.fury.io/rb/vkontakte_api) [](https://gemnasium.com/7even/vkontakte_api) [](https://codeclimate.com/github/7even/vkontakte_api)
|
2
2
|
|
3
3
|
`vkontakte_api` - ruby-адаптер для ВКонтакте API. Он позволяет вызывать методы API, загружать файлы на сервера ВКонтакте, а также поддерживает все 3 доступных способа авторизации (при этом позволяя использовать стороннее решение).
|
4
4
|
|
@@ -6,7 +6,7 @@
|
|
6
6
|
|
7
7
|
``` ruby
|
8
8
|
# Gemfile
|
9
|
-
gem 'vkontakte_api', '~> 1.
|
9
|
+
gem 'vkontakte_api', '~> 1.2'
|
10
10
|
```
|
11
11
|
|
12
12
|
или просто
|
@@ -78,7 +78,7 @@ VkontakteApi.upload(url: url, photo: ['/path/to/file.jpg', 'image/jpeg'])
|
|
78
78
|
|
79
79
|
Авторизация сайтов проходит в 2 шага. Сначала пользователь перенаправляется на страницу ВКонтакте для подтверждения запрошенных у него прав сайта на доступ к его данным. Со списком возможных прав можно ознакомиться [здесь](http://vk.com/developers.php?oid=-1&p=%D0%9F%D1%80%D0%B0%D0%B2%D0%B0_%D0%B4%D0%BE%D1%81%D1%82%D1%83%D0%BF%D0%B0_%D0%BF%D1%80%D0%B8%D0%BB%D0%BE%D0%B6%D0%B5%D0%BD%D0%B8%D0%B9). Допустим, нужно получить доступ к друзьям (`friends`) и фотографиям (`photos`) пользователя.
|
80
80
|
|
81
|
-
В соответствии с [рекомендациями](http://tools.ietf.org/html/draft-ietf-oauth-v2-30#section-10.12) в протоколе OAuth2 для защиты от [CSRF](http://ru.wikipedia.org/wiki/%D0%9F%D0%BE%D0%B4%D0%B4%D0%B5%D0%BB%D0%BA%D0%B0_%D0%BC%D0%B5%D0%B6%D1%81%D0%B0%D0%B9%D1%82%D0%BE%D0%B2%D1%8B%D1%85_%D0%B7%D0%B0%D0%BF%D1%80%D0%BE%D1%81%D0%BE%D0%B2), нужно передать параметр `state`, содержащий случайное значение.
|
81
|
+
В соответствии с [рекомендациями](http://tools.ietf.org/html/draft-ietf-oauth-v2-30#section-10.12) в протоколе OAuth2 для защиты от [CSRF](http://ru.wikipedia.org/wiki/%D0%9F%D0%BE%D0%B4%D0%B4%D0%B5%D0%BB%D0%BA%D0%B0_%D0%BC%D0%B5%D0%B6%D1%81%D0%B0%D0%B9%D1%82%D0%BE%D0%B2%D1%8B%D1%85_%D0%B7%D0%B0%D0%BF%D1%80%D0%BE%D1%81%D0%BE%D0%B2), нужно передать параметр `state`, содержащий случайное значение.
|
82
82
|
|
83
83
|
``` ruby
|
84
84
|
session[:state] = Digest::MD5.hexdigest(rand.to_s)
|
@@ -181,6 +181,8 @@ vk.friends.get(uid: 1, fields: [:first_name, :last_name, :photo])
|
|
181
181
|
# VkontakteApi::Error: VKontakte returned an error 7: 'Permission to perform this action is denied' after calling method 'friends.get' with parameters {"uid"=>"1", "fields"=>"first_name,last_name,photo"}.
|
182
182
|
```
|
183
183
|
|
184
|
+
Особый случай ошибки - 14: необходимо ввести код с captcha. В этом случае можно получить параметры капчи методами `VkontakteApi::Error#captcha_sid` и `VkontakteApi::Error#captcha_img` - например, [так](https://github.com/7even/vkontakte_api/issues/10#issuecomment-11666091).
|
185
|
+
|
184
186
|
### Логгирование
|
185
187
|
|
186
188
|
`vkontakte_api` логгирует служебную информацию о запросах при вызове методов. По умолчанию все пишется в `STDOUT`, но в настройке можно указать любой другой совместимый логгер, например `Rails.logger`.
|
@@ -197,7 +199,9 @@ vk.friends.get(uid: 1, fields: [:first_name, :last_name, :photo])
|
|
197
199
|
|
198
200
|
### Пример использования
|
199
201
|
|
200
|
-
|
202
|
+
Пример использования `vkontakte_api` совместно с `eventmachine` можно посмотреть [здесь](https://github.com/7even/vkontakte_on_em).
|
203
|
+
|
204
|
+
Также был написан [пример использования с rails](https://github.com/7even/vkontakte_on_rails), но он больше не работает из-за отсутствия прав на вызов метода `newsfeed.get`.
|
201
205
|
|
202
206
|
## Настройка
|
203
207
|
|
@@ -226,6 +230,8 @@ VkontakteApi.configure do |config|
|
|
226
230
|
password: 'bar'
|
227
231
|
}
|
228
232
|
}
|
233
|
+
# максимальное количество повторов запроса при ошибках
|
234
|
+
config.max_retries = 2
|
229
235
|
|
230
236
|
# логгер
|
231
237
|
config.logger = Rails.logger
|
@@ -256,14 +262,11 @@ $ rails generate vkontakte_api:install
|
|
256
262
|
|
257
263
|
## Roadmap
|
258
264
|
|
259
|
-
*
|
260
|
-
*
|
261
|
-
* метод `VkontakteApi::Client#offline?`, проверяющий, является ли токен бесконечным, используя значение `VkontakteApi::Client#expires_at`
|
262
|
-
* `POST`-запросы по умолчанию
|
263
|
-
* логгирование тела `POST`-запроса
|
265
|
+
* настраиваемый retry запроса при стандартных исключениях
|
266
|
+
* CLI-интерфейс с автоматической авторизацией
|
264
267
|
|
265
268
|
## Участие в разработке
|
266
269
|
|
267
270
|
Если вы хотите поучаствовать в разработке проекта, форкните репозиторий, положите свои изменения в отдельную ветку, покройте их спеками и отправьте мне pull request.
|
268
271
|
|
269
|
-
`vkontakte_api` тестируется под MRI `1.
|
272
|
+
`vkontakte_api` тестируется под MRI `1.9.2`, `1.9.3` и `2.0.0`. Если в одной из этих сред что-то работает неправильно, либо вообще не работает, то это следует считать багом, и написать об этом в [issues на Github](https://github.com/7even/vkontakte_api/issues).
|
data/Rakefile
CHANGED
@@ -2,7 +2,7 @@ require 'bundler/gem_tasks'
|
|
2
2
|
|
3
3
|
desc 'Fires up the console with preloaded vkontakte_api'
|
4
4
|
task :console do
|
5
|
-
sh 'pry -I ./lib
|
5
|
+
sh 'pry -I ./lib -r ./lib/vkontakte_api'
|
6
6
|
end
|
7
7
|
|
8
8
|
require 'rspec/core/rake_task'
|
@@ -10,4 +10,4 @@ RSpec::Core::RakeTask.new do |t|
|
|
10
10
|
t.rspec_opts = '--color --format doc'
|
11
11
|
end
|
12
12
|
|
13
|
-
task :
|
13
|
+
task default: :spec
|
data/lib/vkontakte_api/api.rb
CHANGED
@@ -14,7 +14,7 @@ module VkontakteApi
|
|
14
14
|
# @return [Hashie::Mash] Mashed server response.
|
15
15
|
def call(method_name, args = {}, token = nil)
|
16
16
|
flat_arguments = Utils.flatten_arguments(args)
|
17
|
-
connection(:
|
17
|
+
connection(url: URL_PREFIX, token: token).send(VkontakteApi.http_verb, method_name, flat_arguments).body
|
18
18
|
end
|
19
19
|
|
20
20
|
# Faraday connection.
|
@@ -30,9 +30,10 @@ module VkontakteApi
|
|
30
30
|
builder.request :oauth2, token unless token.nil?
|
31
31
|
builder.request :multipart
|
32
32
|
builder.request :url_encoded
|
33
|
+
builder.request :retry, VkontakteApi.max_retries
|
33
34
|
builder.response :vk_logger
|
34
35
|
builder.response :mashify
|
35
|
-
builder.response :oj, :
|
36
|
+
builder.response :oj, preserve_raw: true
|
36
37
|
builder.adapter VkontakteApi.adapter
|
37
38
|
end
|
38
39
|
end
|
@@ -5,12 +5,12 @@ module VkontakteApi
|
|
5
5
|
module Authorization
|
6
6
|
# Authorization options.
|
7
7
|
OPTIONS = {
|
8
|
-
:
|
9
|
-
:
|
10
|
-
:
|
11
|
-
:
|
8
|
+
client: {
|
9
|
+
site: 'https://oauth.vk.com',
|
10
|
+
authorize_url: '/authorize',
|
11
|
+
token_url: '/access_token'
|
12
12
|
},
|
13
|
-
:
|
13
|
+
client_credentials: {
|
14
14
|
'auth_scheme' => 'request_body'
|
15
15
|
}
|
16
16
|
}
|
data/lib/vkontakte_api/client.rb
CHANGED
@@ -5,23 +5,23 @@ module VkontakteApi
|
|
5
5
|
|
6
6
|
# Access rights and their respective number representation.
|
7
7
|
SCOPE = {
|
8
|
-
:
|
9
|
-
:
|
10
|
-
:
|
11
|
-
:
|
12
|
-
:
|
13
|
-
:
|
14
|
-
:
|
15
|
-
:
|
16
|
-
:
|
17
|
-
:
|
18
|
-
:
|
19
|
-
:
|
20
|
-
:
|
21
|
-
:
|
22
|
-
:
|
23
|
-
:
|
24
|
-
:
|
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
25
|
}
|
26
26
|
|
27
27
|
# An access token needed by authorized requests.
|
@@ -13,6 +13,7 @@ module VkontakteApi
|
|
13
13
|
:adapter,
|
14
14
|
:http_verb,
|
15
15
|
:faraday_options,
|
16
|
+
:max_retries,
|
16
17
|
:logger,
|
17
18
|
:log_requests,
|
18
19
|
:log_errors,
|
@@ -31,11 +32,14 @@ module VkontakteApi
|
|
31
32
|
# Default HTTP verb for API methods.
|
32
33
|
DEFAULT_HTTP_VERB = :post
|
33
34
|
|
35
|
+
# Default max retries count.
|
36
|
+
DEFAULT_MAX_RETRIES = 2
|
37
|
+
|
34
38
|
# Logger default options.
|
35
39
|
DEFAULT_LOGGER_OPTIONS = {
|
36
|
-
:
|
37
|
-
:
|
38
|
-
:
|
40
|
+
requests: true,
|
41
|
+
errors: true,
|
42
|
+
responses: false
|
39
43
|
}
|
40
44
|
|
41
45
|
# A global configuration set via the block.
|
@@ -54,6 +58,7 @@ module VkontakteApi
|
|
54
58
|
@adapter = DEFAULT_ADAPTER
|
55
59
|
@http_verb = DEFAULT_HTTP_VERB
|
56
60
|
@faraday_options = {}
|
61
|
+
@max_retries = DEFAULT_MAX_RETRIES
|
57
62
|
@logger = ::Logger.new(STDOUT)
|
58
63
|
@log_requests = DEFAULT_LOGGER_OPTIONS[:requests]
|
59
64
|
@log_errors = DEFAULT_LOGGER_OPTIONS[:errors]
|
data/lib/vkontakte_api/error.rb
CHANGED
@@ -4,6 +4,12 @@ module VkontakteApi
|
|
4
4
|
# An error code.
|
5
5
|
# @return [Fixnum]
|
6
6
|
attr_reader :error_code
|
7
|
+
# Captcha identifier (only for "Captcha needed" errors).
|
8
|
+
# @return [String]
|
9
|
+
attr_reader :captcha_sid
|
10
|
+
# Captcha image URL (only for "Captcha needed" errors).
|
11
|
+
# @return [String]
|
12
|
+
attr_reader :captcha_img
|
7
13
|
|
8
14
|
# An exception is initialized by the data from response mash.
|
9
15
|
# @param [Hash] data Error data.
|
@@ -17,6 +23,9 @@ module VkontakteApi
|
|
17
23
|
@access_token = request_params.delete('access_token')
|
18
24
|
@oauth = request_params.delete('oauth')
|
19
25
|
@params = request_params
|
26
|
+
|
27
|
+
@captcha_sid = data.captcha_sid
|
28
|
+
@captcha_img = data.captcha_img
|
20
29
|
end
|
21
30
|
|
22
31
|
# A full description of the error.
|
data/lib/vkontakte_api/logger.rb
CHANGED
@@ -10,17 +10,17 @@ module VkontakteApi
|
|
10
10
|
|
11
11
|
if Resolver.namespaces.include?(method_name)
|
12
12
|
# called from Client
|
13
|
-
Namespace.new(method_name, :
|
13
|
+
Namespace.new(method_name, resolver: resolver)
|
14
14
|
else
|
15
15
|
# called from Namespace or one-level method
|
16
|
-
Method.new(method_name, :
|
16
|
+
Method.new(method_name, resolver: resolver).call(args.first || {}, &block)
|
17
17
|
end
|
18
18
|
end
|
19
19
|
|
20
20
|
# A `Hashie::Mash` structure holding the name and token of current instance.
|
21
21
|
# @return [Hashie::Mash]
|
22
22
|
def resolver
|
23
|
-
@resolver ||= Hashie::Mash.new(:
|
23
|
+
@resolver ||= Hashie::Mash.new(name: @name, token: token)
|
24
24
|
end
|
25
25
|
|
26
26
|
class << self
|
@@ -35,6 +35,14 @@ module VkontakteApi
|
|
35
35
|
|
36
36
|
@namespaces
|
37
37
|
end
|
38
|
+
|
39
|
+
# When this module is included, it undefines the `:send` instance method in the `base_class`
|
40
|
+
# so it can be resolved via `method_missing`.
|
41
|
+
def included(base_class)
|
42
|
+
base_class.class_eval do
|
43
|
+
undef_method :send
|
44
|
+
end
|
45
|
+
end
|
38
46
|
end
|
39
47
|
end
|
40
48
|
end
|
data/spec/integration_spec.rb
CHANGED
@@ -18,33 +18,35 @@ describe "Integration" do
|
|
18
18
|
end
|
19
19
|
|
20
20
|
it "get users" do
|
21
|
-
user = @vk.users.get(:
|
22
|
-
user.uid.should
|
23
|
-
user.last_name.should_not
|
21
|
+
user = @vk.users.get(uid: 1).first
|
22
|
+
user.uid.should == 1
|
23
|
+
user.last_name.should_not be_empty
|
24
24
|
user.first_name.should_not be_empty
|
25
25
|
end
|
26
26
|
end
|
27
27
|
|
28
|
-
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
describe "requests with camelCase and predicate methods" do
|
40
|
-
before(:each) do
|
41
|
-
@vk = VK::Client.new(ENV['TOKEN'])
|
28
|
+
if MechanizedAuthorization.on?
|
29
|
+
describe "authorized requests" do
|
30
|
+
before(:each) do
|
31
|
+
@vk = MechanizedAuthorization.client
|
32
|
+
end
|
33
|
+
|
34
|
+
it "get groups" do
|
35
|
+
groups = @vk.groups.get
|
36
|
+
groups.should include(1)
|
37
|
+
end
|
42
38
|
end
|
43
39
|
|
44
|
-
|
45
|
-
|
40
|
+
describe "requests with camelCase and predicate methods" do
|
41
|
+
before(:each) do
|
42
|
+
@vk = MechanizedAuthorization.client
|
43
|
+
end
|
44
|
+
|
45
|
+
it "convert method names to vk.com format" do
|
46
|
+
@vk.is_app_user?.should be_true
|
47
|
+
end
|
46
48
|
end
|
47
|
-
end
|
49
|
+
end
|
48
50
|
|
49
51
|
describe "requests with array arguments" do
|
50
52
|
before(:each) do
|
@@ -52,7 +54,7 @@ describe "Integration" do
|
|
52
54
|
end
|
53
55
|
|
54
56
|
it "join arrays with a comma" do
|
55
|
-
users = @vk.users.get(:
|
57
|
+
users = @vk.users.get(uids: [1, 2, 3], fields: %w[first_name last_name screen_name])
|
56
58
|
users.first.screen_name.should_not be_empty
|
57
59
|
end
|
58
60
|
end
|
@@ -63,7 +65,7 @@ describe "Integration" do
|
|
63
65
|
end
|
64
66
|
|
65
67
|
it "map the result with a block" do
|
66
|
-
users = @vk.users.get(:
|
68
|
+
users = @vk.users.get(uid: 1) do |user|
|
67
69
|
"#{user.last_name} #{user.first_name}"
|
68
70
|
end
|
69
71
|
|
@@ -74,7 +76,7 @@ describe "Integration" do
|
|
74
76
|
describe "authorization" do
|
75
77
|
context "with a scope" do
|
76
78
|
it "returns a correct url" do
|
77
|
-
VK.authorization_url(:
|
79
|
+
VK.authorization_url(scope: %w[friends groups]).should include('scope=friends%2Cgroups')
|
78
80
|
end
|
79
81
|
end
|
80
82
|
end
|
data/spec/spec_helper.rb
CHANGED
@@ -0,0 +1,57 @@
|
|
1
|
+
require 'mechanize'
|
2
|
+
|
3
|
+
module MechanizedAuthorization
|
4
|
+
class << self
|
5
|
+
def client
|
6
|
+
@client ||= begin
|
7
|
+
agent = Mechanize.new
|
8
|
+
|
9
|
+
configure
|
10
|
+
agent.get VkontakteApi.authorization_url(scope: [:friends, :groups], type: :client)
|
11
|
+
|
12
|
+
agent.page.form_with(action: /login.vk.com/) do |form|
|
13
|
+
form.email = settings.email
|
14
|
+
form.pass = settings.password
|
15
|
+
end.submit
|
16
|
+
|
17
|
+
# uri.fragment: access_token=ee6b952fa432c70&expires_in=86400&user_id=123456
|
18
|
+
params = agent.page.uri.fragment.split('&').inject({}) do |hash, pair|
|
19
|
+
key, value = pair.split('=')
|
20
|
+
hash[key] = value
|
21
|
+
hash
|
22
|
+
end
|
23
|
+
token = params['access_token']
|
24
|
+
|
25
|
+
VkontakteApi::Client.new(token)
|
26
|
+
end
|
27
|
+
end
|
28
|
+
|
29
|
+
def on?
|
30
|
+
!off?
|
31
|
+
end
|
32
|
+
|
33
|
+
private
|
34
|
+
def off?
|
35
|
+
ENV['NO_AUTH'] || !File.exists?(credentials_path)
|
36
|
+
end
|
37
|
+
|
38
|
+
def configure
|
39
|
+
VkontakteApi.configure do |config|
|
40
|
+
config.app_id = settings.app_id
|
41
|
+
config.app_secret = settings.app_secret
|
42
|
+
end
|
43
|
+
end
|
44
|
+
|
45
|
+
def settings
|
46
|
+
@settings ||= Hashie::Mash.new(settings_hash)
|
47
|
+
end
|
48
|
+
|
49
|
+
def settings_hash
|
50
|
+
YAML.load_file(credentials_path)
|
51
|
+
end
|
52
|
+
|
53
|
+
def credentials_path
|
54
|
+
File.expand_path('../credentials.yml', __FILE__)
|
55
|
+
end
|
56
|
+
end
|
57
|
+
end
|