vkontakte_api 1.1 → 1.2

Sign up to get free protection for your applications and to get access to all the features.
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
@@ -3,3 +3,4 @@
3
3
  Gemfile.lock
4
4
  pkg/*
5
5
  .yardoc/*
6
+ spec/support/credentials.yml
data/.travis.yml CHANGED
@@ -1,5 +1,4 @@
1
1
  rvm:
2
- - 1.8.7
3
2
  - 1.9.2
4
3
  - 1.9.3
5
- # - ruby-head
4
+ - 2.0.0
data/CHANGELOG.md CHANGED
@@ -1,3 +1,9 @@
1
+ ## 1.2 (14.07.2013)
2
+
3
+ * Повтор запроса при определенных ошибках
4
+ * Корректная работа метода `messages.send`
5
+ * Поддержка параметров `captcha_sid` и `captcha_img` при ошибке 14
6
+
1
7
  ## 1.1 (18.12.2012)
2
8
 
3
9
  * Передача `redirect_uri` при получении токена
data/Gemfile CHANGED
@@ -1,4 +1,4 @@
1
- source :rubygems
1
+ source 'https://rubygems.org'
2
2
 
3
3
  # Specify your gem's dependencies in vkontakte_api.gemspec
4
4
  gemspec
data/README.md CHANGED
@@ -1,4 +1,4 @@
1
- ## vkontakte_api [![Build Status](https://secure.travis-ci.org/7even/vkontakte_api.png)](http://travis-ci.org/7even/vkontakte_api) [![Dependency Status](https://gemnasium.com/7even/vkontakte_api.png)](https://gemnasium.com/7even/vkontakte_api) [![Code Climate](https://codeclimate.com/badge.png)](https://codeclimate.com/github/7even/vkontakte_api)
1
+ ## vkontakte_api [![Build Status](https://secure.travis-ci.org/7even/vkontakte_api.png)](http://travis-ci.org/7even/vkontakte_api) [![Gem Version](https://badge.fury.io/rb/vkontakte_api.png)](http://badge.fury.io/rb/vkontakte_api) [![Dependency Status](https://gemnasium.com/7even/vkontakte_api.png)](https://gemnasium.com/7even/vkontakte_api) [![Code Climate](https://codeclimate.com/github/7even/vkontakte_api.png)](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.0'
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`, содержащий случайное значение. На данный момент по непонятным причинам ВКонтакте игнорирует этот параметр, если в `scope` не указан `notify`.
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
- [Здесь](http://vkontakte-on-rails.herokuapp.com/) можно посмотреть пример использования `vkontakte_api` в rails-приложении (используются только читающие методы *.get - приложение ничего не пишет на ВКонтакте, только читает). Исходный код можно посмотреть [тут](https://github.com/7even/vkontakte_on_rails).
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
- * метод, возвращающий права текущего токена в читабельной форме (используя `getUserSettings` и кэшируя результат)
260
- * сохранение параметра `expires_at` токена в объекте `VkontakteApi::Client` после авторизации через `VkontakteApi.authorize`
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.8.7`, `1.9.2` и `1.9.3`. Если в одной из этих сред что-то работает неправильно, либо вообще не работает, то это следует считать багом, и написать об этом в [issues на Github](https://github.com/7even/vkontakte_api/issues).
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/ -r ./lib/vkontakte_api.rb'
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 :default => :spec
13
+ task default: :spec
@@ -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(:url => URL_PREFIX, :token => token).send(VkontakteApi.http_verb, method_name, flat_arguments).body
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, :preserve_raw => true
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
- :client => {
9
- :site => 'https://oauth.vk.com',
10
- :authorize_url => '/authorize',
11
- :token_url => '/access_token'
8
+ client: {
9
+ site: 'https://oauth.vk.com',
10
+ authorize_url: '/authorize',
11
+ token_url: '/access_token'
12
12
  },
13
- :client_credentials => {
13
+ client_credentials: {
14
14
  'auth_scheme' => 'request_body'
15
15
  }
16
16
  }
@@ -5,23 +5,23 @@ module VkontakteApi
5
5
 
6
6
  # Access rights and their respective number representation.
7
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
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
- :requests => true,
37
- :errors => true,
38
- :responses => false
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]
@@ -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.
@@ -33,4 +33,4 @@ module VkontakteApi
33
33
  end
34
34
  end
35
35
 
36
- Faraday.register_middleware :response, :vk_logger => VkontakteApi::Logger
36
+ Faraday.register_middleware :response, vk_logger: VkontakteApi::Logger
@@ -27,3 +27,6 @@
27
27
  - auth
28
28
  - ads
29
29
  - orders
30
+ - search
31
+ - apps
32
+ - utils
@@ -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, :resolver => resolver)
13
+ Namespace.new(method_name, resolver: resolver)
14
14
  else
15
15
  # called from Namespace or one-level method
16
- Method.new(method_name, :resolver => resolver).call(args.first || {}, &block)
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(:name => @name, :token => token)
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
@@ -1,4 +1,4 @@
1
1
  module VkontakteApi
2
2
  # Library version.
3
- VERSION = '1.1'
3
+ VERSION = '1.2'
4
4
  end
@@ -18,33 +18,35 @@ describe "Integration" do
18
18
  end
19
19
 
20
20
  it "get users" do
21
- user = @vk.users.get(:uid => 1).first
22
- user.uid.should == 1
23
- user.last_name.should_not be_empty
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
- describe "authorized requests" do
29
- before(:each) do
30
- @vk = VK::Client.new(ENV['TOKEN'])
31
- end
32
-
33
- it "get groups" do
34
- groups = @vk.groups.get
35
- groups.should include(1)
36
- end
37
- end if ENV['TOKEN']
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
- it "convert method names to vk.com format" do
45
- @vk.is_app_user?.should be_true
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 if ENV['TOKEN']
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(:uids => [1, 2, 3], :fields => %w[first_name last_name screen_name])
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(:uid => 1) do |user|
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(:scope => %w[friends groups]).should include('scope=friends%2Cgroups')
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
@@ -1,5 +1,7 @@
1
1
  require 'vkontakte_api'
2
2
  require 'pry'
3
+ require 'awesome_print'
4
+ require_relative './support/mechanized_authorization'
3
5
 
4
6
  RSpec::Matchers.define :log_requests do
5
7
  match do |logger|
@@ -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