├── .gitignore ├── lib ├── odnoklassniki │ ├── version.rb │ ├── rest │ │ ├── mediatopic.rb │ │ ├── user.rb │ │ └── mediatopic │ │ │ ├── content.rb │ │ │ └── photoalbum.rb │ ├── utils.rb │ ├── connection.rb │ ├── config.rb │ ├── client.rb │ ├── request.rb │ └── error.rb └── odnoklassniki.rb ├── Gemfile ├── Rakefile ├── .travis.yml ├── test ├── test_helper.rb ├── lib │ ├── odnoklassniki │ │ ├── error_test.rb │ │ ├── config_test.rb │ │ ├── request_test.rb │ │ └── client_test.rb │ └── odnoklassniki_test.rb └── vcr_cassettes │ ├── client_wrong_credentials_post.yml │ ├── wrong_credentials_getCurrentUser.yml │ ├── client_wrong_credentials_getCurrentUser.yml │ ├── client_wrong_credentials_token.yml │ └── wrong_credentials_token.yml ├── LICENSE ├── odnoklassniki.gemspec └── README.md /.gitignore: -------------------------------------------------------------------------------- 1 | /.bundle 2 | /Gemfile.lock 3 | /coverage 4 | -------------------------------------------------------------------------------- /lib/odnoklassniki/version.rb: -------------------------------------------------------------------------------- 1 | module Odnoklassniki 2 | VERSION = '0.0.3' 3 | end 4 | -------------------------------------------------------------------------------- /Gemfile: -------------------------------------------------------------------------------- 1 | source "http://rubygems.org" 2 | 3 | # Specify your gem's dependencies in odnoklassniki.gemspec 4 | gemspec 5 | -------------------------------------------------------------------------------- /Rakefile: -------------------------------------------------------------------------------- 1 | require 'rubygems' 2 | require 'rake' 3 | require 'rake/testtask' 4 | 5 | Rake::TestTask.new do |t| 6 | t.test_files = Dir.glob('test/**/*_test.rb') 7 | end 8 | 9 | task(default: :test) 10 | -------------------------------------------------------------------------------- /.travis.yml: -------------------------------------------------------------------------------- 1 | language: ruby 2 | rvm: 3 | - 2.0.0 4 | - 2.1.0 5 | - 2.1.5 6 | - 2.2.0 7 | - jruby-19mode # JRuby in 1.9 mode 8 | - rbx 9 | matrix: 10 | allow_failures: 11 | - rvm: jruby-19mode 12 | - rvm: rbx 13 | -------------------------------------------------------------------------------- /lib/odnoklassniki/rest/mediatopic.rb: -------------------------------------------------------------------------------- 1 | module Odnoklassniki 2 | module REST 3 | class Mediatopic 4 | 5 | attr_accessor :client 6 | 7 | def initialize(client) 8 | @client = client 9 | end 10 | 11 | end 12 | end 13 | end 14 | -------------------------------------------------------------------------------- /lib/odnoklassniki/utils.rb: -------------------------------------------------------------------------------- 1 | module Odnoklassniki 2 | module Utils 3 | 4 | class << self 5 | 6 | def _symbolize_keys(hash) 7 | symbolized = {} 8 | hash.each do |k, v| 9 | v = _symbolize_keys(v) if v.is_a?(Hash) 10 | symbolized[k.to_sym] = v 11 | end 12 | symbolized 13 | end 14 | 15 | end 16 | 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /test/test_helper.rb: -------------------------------------------------------------------------------- 1 | if ENV['COV'] == '1' 2 | require 'simplecov' 3 | SimpleCov.start 4 | end 5 | 6 | require 'minitest/autorun' 7 | require "minitest/reporters" 8 | Minitest::Reporters.use! 9 | 10 | require 'vcr' 11 | VCR.configure do |config| 12 | config.cassette_library_dir = "test/vcr_cassettes" 13 | config.hook_into :webmock # or :fakeweb 14 | end 15 | 16 | require_relative '../lib/odnoklassniki' 17 | -------------------------------------------------------------------------------- /lib/odnoklassniki/rest/user.rb: -------------------------------------------------------------------------------- 1 | module Odnoklassniki 2 | module REST 3 | class User 4 | 5 | attr_accessor :client 6 | 7 | def initialize(client) 8 | @client = client 9 | end 10 | 11 | def current_user(fields=[]) 12 | options = fields.empty? ? {} : fiels.join(',') 13 | client.get('users.getCurrentUser', options) 14 | end 15 | 16 | end 17 | end 18 | end 19 | -------------------------------------------------------------------------------- /test/lib/odnoklassniki/error_test.rb: -------------------------------------------------------------------------------- 1 | require_relative '../../test_helper' 2 | 3 | class TestOdnoklassnikiError < Minitest::Test 4 | 5 | def test_from_response 6 | error = Odnoklassniki::Error. 7 | from_response({ 'error_msg' => 'message', 'error_code' => 123 }) 8 | assert_instance_of Odnoklassniki::Error, error 9 | assert_equal error.code, 123 10 | assert_equal error.message, 'message' 11 | end 12 | 13 | end 14 | -------------------------------------------------------------------------------- /lib/odnoklassniki.rb: -------------------------------------------------------------------------------- 1 | require_relative 'odnoklassniki/error' 2 | require_relative 'odnoklassniki/version' 3 | require_relative 'odnoklassniki/client' 4 | require_relative 'odnoklassniki/config' 5 | 6 | module Odnoklassniki 7 | 8 | class << self 9 | attr_accessor :config 10 | 11 | def new(options = {}) 12 | Odnoklassniki::Client.new(options) 13 | end 14 | 15 | def configure 16 | @config = Odnoklassniki::Config.new 17 | yield @config 18 | @config 19 | end 20 | 21 | def options 22 | (@config && @config.options) || {} 23 | end 24 | 25 | end 26 | 27 | end 28 | -------------------------------------------------------------------------------- /test/lib/odnoklassniki_test.rb: -------------------------------------------------------------------------------- 1 | require_relative '../test_helper' 2 | 3 | class TestOdnoklassniki < Minitest::Test 4 | 5 | def setup 6 | @options = { 7 | access_token: '1', 8 | client_id: '2', 9 | client_secret: '3', 10 | application_key: '4' 11 | } 12 | Odnoklassniki.configure do |c| 13 | @options.each { |k, v| c.send("#{k}=", v) } 14 | end 15 | end 16 | 17 | def test_new 18 | assert_instance_of Odnoklassniki::Client, Odnoklassniki.new 19 | end 20 | 21 | def test_configure 22 | assert_equal Odnoklassniki::Client.new.instance_variable_get(:@access_token), '1' 23 | end 24 | 25 | def test_options 26 | assert_equal Odnoklassniki.options, @options 27 | end 28 | 29 | end 30 | -------------------------------------------------------------------------------- /lib/odnoklassniki/connection.rb: -------------------------------------------------------------------------------- 1 | require 'faraday' 2 | 3 | module Odnoklassniki 4 | module Connection 5 | API_HOST = 'http://api.odnoklassniki.ru' 6 | 7 | def connection(options={}) 8 | options = options.clone 9 | 10 | default_options = { 11 | :headers => { 12 | :accept => 'application/json', 13 | :user_agent => "odnoklassniki ruby gem/#{Odnoklassniki::VERSION}" 14 | }, 15 | :url => "#{API_HOST}/" 16 | } 17 | 18 | client = Faraday.default_adapter 19 | 20 | Faraday.new(default_options.merge(options)) do |conn| 21 | conn.request :multipart 22 | conn.request :url_encoded 23 | conn.adapter client 24 | end 25 | end 26 | 27 | end 28 | end 29 | -------------------------------------------------------------------------------- /test/lib/odnoklassniki/config_test.rb: -------------------------------------------------------------------------------- 1 | require_relative '../../test_helper' 2 | 3 | class TestOdnoklassnikiConfig < Minitest::Test 4 | 5 | def setup 6 | @options = { 7 | access_token: '1', 8 | client_id: '2', 9 | client_secret: '3', 10 | application_key: '4' 11 | } 12 | end 13 | 14 | def test_configure 15 | config = Odnoklassniki::Config.configure do |c| 16 | @options.each do |k, v| 17 | c.send("#{k}=", v) 18 | end 19 | end 20 | assert_equal config.options, @options 21 | end 22 | 23 | def test_new 24 | config = Odnoklassniki::Config.new(@options) 25 | assert_equal config.options, @options 26 | end 27 | 28 | def test_options 29 | opts = @options.merge({some_unused_key: 123}) 30 | config = Odnoklassniki::Config.new(opts) 31 | assert_equal config.options, @options 32 | end 33 | 34 | end 35 | -------------------------------------------------------------------------------- /lib/odnoklassniki/config.rb: -------------------------------------------------------------------------------- 1 | module Odnoklassniki 2 | class Config 3 | 4 | VALID_OPTIONS_KEYS = [:access_token, 5 | :client_id, 6 | :client_secret, 7 | :application_key].freeze 8 | 9 | attr_accessor *VALID_OPTIONS_KEYS 10 | 11 | def self.configure 12 | config = self.new 13 | yield config 14 | config 15 | end 16 | 17 | def initialize(options={}) 18 | @access_token = options[:access_token] || options['access_token'] 19 | @client_id = options[:client_id] || options['client_id'] 20 | @client_secret = options[:client_secret] || options['client_secret'] 21 | @application_key = options[:application_key] || options['application_key'] 22 | end 23 | 24 | def options 25 | options = {} 26 | VALID_OPTIONS_KEYS.each{ |pname| options[pname] = send(pname) } 27 | options 28 | end 29 | 30 | end 31 | end 32 | -------------------------------------------------------------------------------- /test/lib/odnoklassniki/request_test.rb: -------------------------------------------------------------------------------- 1 | require_relative '../../test_helper' 2 | 3 | class TestOdnoklassnikiRequest < Minitest::Test 4 | 5 | def setup 6 | @request = Odnoklassniki::Request.new({ 7 | access_token: 'token', 8 | client_secret: 'client_secret', 9 | application_key: 'application_key' 10 | }) 11 | end 12 | 13 | def test_get_with_wrong_credentials 14 | VCR.use_cassette('wrong_credentials_getCurrentUser') do 15 | error = assert_raises Odnoklassniki::Error::ClientError do 16 | @request.get('/api/users/getCurrentUser') 17 | end 18 | assert_equal 'PARAM_API_KEY : Application not exist', error.message 19 | assert_equal 101, error.code 20 | end 21 | end 22 | 23 | def test_post_with_wrong_credentials 24 | VCR.use_cassette('wrong_credentials_token') do 25 | error = assert_raises Odnoklassniki::Error::ClientError do 26 | @request.post('/oauth/token.do') 27 | end 28 | assert_match /Provide OAUTH request parameters!/, error.message 29 | assert_equal error.code, nil 30 | end 31 | end 32 | 33 | end 34 | -------------------------------------------------------------------------------- /LICENSE: -------------------------------------------------------------------------------- 1 | The MIT License (MIT) 2 | 3 | Copyright (c) 2015 Alexey Gaziev 4 | 5 | Permission is hereby granted, free of charge, to any person obtaining a copy 6 | of this software and associated documentation files (the "Software"), to deal 7 | in the Software without restriction, including without limitation the rights 8 | to use, copy, modify, merge, publish, distribute, sublicense, and/or sell 9 | copies of the Software, and to permit persons to whom the Software is 10 | furnished to do so, subject to the following conditions: 11 | 12 | The above copyright notice and this permission notice shall be included in all 13 | copies or substantial portions of the Software. 14 | 15 | THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR 16 | IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, 17 | FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE 18 | AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER 19 | LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, 20 | OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE 21 | SOFTWARE. 22 | 23 | -------------------------------------------------------------------------------- /test/vcr_cassettes/client_wrong_credentials_post.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: http://api.odnoklassniki.ru/api/mediatopic/post 6 | body: 7 | encoding: UTF-8 8 | string: '' 9 | headers: 10 | Accept: 11 | - application/json 12 | User-Agent: 13 | - odnoklassniki ruby gem/0.0.1 14 | Content-Length: 15 | - '0' 16 | Accept-Encoding: 17 | - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 18 | response: 19 | status: 20 | code: 200 21 | message: OK 22 | headers: 23 | Server: 24 | - Apache-Coyote/1.1 25 | Invocation-Error: 26 | - '101' 27 | Pragma: 28 | - no-cache 29 | Expires: 30 | - Thu, 01 Jan 1970 00:00:00 GMT 31 | Cache-Control: 32 | - no-cache 33 | - no-store 34 | Content-Type: 35 | - application/json;charset=utf-8 36 | Content-Language: 37 | - en-US 38 | Content-Length: 39 | - '85' 40 | Date: 41 | - Wed, 04 Feb 2015 14:30:21 GMT 42 | Connection: 43 | - close 44 | body: 45 | encoding: UTF-8 46 | string: '{"error_code":101,"error_data":null,"error_msg":"PARAM_API_KEY : No 47 | application key"}' 48 | http_version: 49 | recorded_at: Wed, 04 Feb 2015 14:30:22 GMT 50 | recorded_with: VCR 2.9.3 51 | -------------------------------------------------------------------------------- /test/vcr_cassettes/wrong_credentials_getCurrentUser.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: http://api.odnoklassniki.ru/api/users/getCurrentUser?access_token=token&application_key=application_key&sig=4784959f6620c78221bff139d6cf9309 6 | body: 7 | encoding: US-ASCII 8 | string: '' 9 | headers: 10 | Accept: 11 | - application/json 12 | User-Agent: 13 | - odnoklassniki ruby gem/0.0.1 14 | Accept-Encoding: 15 | - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 16 | response: 17 | status: 18 | code: 200 19 | message: OK 20 | headers: 21 | Server: 22 | - Apache-Coyote/1.1 23 | Invocation-Error: 24 | - '101' 25 | Pragma: 26 | - no-cache 27 | Expires: 28 | - Thu, 01 Jan 1970 00:00:00 GMT 29 | Cache-Control: 30 | - no-cache 31 | - no-store 32 | Content-Type: 33 | - application/json;charset=utf-8 34 | Content-Language: 35 | - en-US 36 | Content-Length: 37 | - '88' 38 | Date: 39 | - Wed, 04 Feb 2015 12:56:52 GMT 40 | Connection: 41 | - close 42 | body: 43 | encoding: UTF-8 44 | string: '{"error_code":101,"error_msg":"PARAM_API_KEY : Application not exist","error_data":null}' 45 | http_version: 46 | recorded_at: Wed, 04 Feb 2015 12:56:52 GMT 47 | recorded_with: VCR 2.9.3 48 | -------------------------------------------------------------------------------- /test/vcr_cassettes/client_wrong_credentials_getCurrentUser.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: get 5 | uri: http://api.odnoklassniki.ru/api/users/getCurrentUser?access_token=token&application_key=application_key&sig=4784959f6620c78221bff139d6cf9309 6 | body: 7 | encoding: US-ASCII 8 | string: '' 9 | headers: 10 | Accept: 11 | - application/json 12 | User-Agent: 13 | - odnoklassniki ruby gem/0.0.1 14 | Accept-Encoding: 15 | - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 16 | response: 17 | status: 18 | code: 200 19 | message: OK 20 | headers: 21 | Server: 22 | - Apache-Coyote/1.1 23 | Invocation-Error: 24 | - '101' 25 | Pragma: 26 | - no-cache 27 | Expires: 28 | - Thu, 01 Jan 1970 00:00:00 GMT 29 | Cache-Control: 30 | - no-cache 31 | - no-store 32 | Content-Type: 33 | - application/json;charset=utf-8 34 | Content-Language: 35 | - en-US 36 | Content-Length: 37 | - '88' 38 | Date: 39 | - Wed, 04 Feb 2015 14:30:21 GMT 40 | Connection: 41 | - close 42 | body: 43 | encoding: UTF-8 44 | string: '{"error_code":101,"error_data":null,"error_msg":"PARAM_API_KEY : Application 45 | not exist"}' 46 | http_version: 47 | recorded_at: Wed, 04 Feb 2015 14:30:21 GMT 48 | recorded_with: VCR 2.9.3 49 | -------------------------------------------------------------------------------- /odnoklassniki.gemspec: -------------------------------------------------------------------------------- 1 | lib = File.expand_path('../lib', __FILE__) 2 | $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib) 3 | require 'odnoklassniki/version' 4 | 5 | Gem::Specification.new do |s| 6 | s.name = 'odnoklassniki' 7 | s.version = Odnoklassniki::VERSION 8 | s.platform = Gem::Platform::RUBY 9 | s.authors = ['gazay'] 10 | s.licenses = ['MIT'] 11 | s.email = ['alex.gaziev@gmail.com'] 12 | s.homepage = 'https://github.com/gazay/odnoklassniki' 13 | s.summary = %q{Ruby wrapper for Odnoklassniki API} 14 | s.description = %q{Ruby wrapper for REST Odnoklassniki API calls. GET and POST calls.} 15 | 16 | s.rubyforge_project = 'odnoklassniki' 17 | 18 | s.files = `git ls-files`.split("\n") 19 | s.require_paths = ['lib'] 20 | s.add_dependency 'faraday', '>= 0.9', '< 2' 21 | s.add_dependency 'multi_json', '~> 1.10', '>= 1.10.0' 22 | s.add_development_dependency 'pry', '0.10.1' 23 | s.add_development_dependency 'byebug', '3.5.1' 24 | s.add_development_dependency 'pry-byebug', '3.0.0' 25 | s.add_development_dependency 'minitest', '5.5.1' 26 | s.add_development_dependency 'minitest-reporters', '1.0.10' 27 | s.add_development_dependency 'simplecov', '0.9.1' 28 | s.add_development_dependency 'rake', '10.1.0' 29 | s.add_development_dependency 'vcr', '2.9.3' 30 | s.add_development_dependency 'webmock', '1.20.4' 31 | end 32 | -------------------------------------------------------------------------------- /test/lib/odnoklassniki/client_test.rb: -------------------------------------------------------------------------------- 1 | require_relative '../../test_helper' 2 | 3 | class TestOdnoklassnikiClient < Minitest::Test 4 | 5 | def setup 6 | @client = Odnoklassniki::Client.new({ 7 | access_token: 'token', 8 | client_id: 'client_id', 9 | client_secret: 'client_secret', 10 | application_key: 'application_key' 11 | }) 12 | end 13 | 14 | def test_get_with_wrong_credentials 15 | VCR.use_cassette('client_wrong_credentials_getCurrentUser') do 16 | error = assert_raises Odnoklassniki::Error::ClientError do 17 | @client.instance_variable_set(:@refreshed, true) 18 | @client.get('users.getCurrentUser') 19 | end 20 | assert_equal 'PARAM_API_KEY : Application not exist', error.message 21 | assert_equal 101, error.code 22 | end 23 | end 24 | 25 | def test_post_with_wrong_credentials 26 | VCR.use_cassette('client_wrong_credentials_post') do 27 | error = assert_raises Odnoklassniki::Error::ClientError do 28 | @client.instance_variable_set(:@refreshed, true) 29 | @client.post('mediatopic.post') 30 | end 31 | assert_match /No application key/, error.message 32 | assert_equal 101, error.code 33 | end 34 | end 35 | 36 | def test_refresh_token_with_wrong_credentials 37 | VCR.use_cassette('client_wrong_credentials_token') do 38 | error = assert_raises Odnoklassniki::Error::ClientError do 39 | @client.refresh_token! 40 | end 41 | assert_equal nil, error.code 42 | end 43 | end 44 | 45 | end 46 | -------------------------------------------------------------------------------- /test/vcr_cassettes/client_wrong_credentials_token.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: http://api.odnoklassniki.ru/oauth/token.do 6 | body: 7 | encoding: UTF-8 8 | string: access_token=token&application_key=application_key&client_id=client_id&client_secret=client_secret&grant_type=refresh_token&refresh_token=token&sig=c40601c8f1fdd56139160d7140af3ed0 9 | headers: 10 | Accept: 11 | - application/json 12 | User-Agent: 13 | - odnoklassniki ruby gem/0.0.1 14 | Content-Type: 15 | - application/x-www-form-urlencoded 16 | Accept-Encoding: 17 | - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 18 | response: 19 | status: 20 | code: 200 21 | message: OK 22 | headers: 23 | Server: 24 | - Apache-Coyote/1.1 25 | Set-Cookie: 26 | - JSESSIONID=9190C3142FFCE4EF71502920B5597956; Path=/; HttpOnly 27 | Content-Type: 28 | - text/html;charset=utf-8 29 | Content-Language: 30 | - en-US 31 | Content-Length: 32 | - '146' 33 | Date: 34 | - Wed, 04 Feb 2015 14:30:22 GMT 35 | Connection: 36 | - close 37 | body: 38 | encoding: UTF-8 39 | string: |2 40 | 41 | 42 | 43 | 44 | 45 | 46 | 47 | 48 | 49 | 50 | 51 | 52 | Error : Failed to convert value of type [java.lang.String] to required type [java.lang.Long] 53 | 54 | 55 | http_version: 56 | recorded_at: Wed, 04 Feb 2015 14:30:23 GMT 57 | recorded_with: VCR 2.9.3 58 | -------------------------------------------------------------------------------- /lib/odnoklassniki/client.rb: -------------------------------------------------------------------------------- 1 | require_relative 'request' 2 | 3 | module Odnoklassniki 4 | class Client 5 | 6 | def initialize(attrs= {}) 7 | attrs = Odnoklassniki.options.merge(attrs) 8 | Config::VALID_OPTIONS_KEYS.each do |key| 9 | instance_variable_set("@#{key}".to_sym, attrs[key]) 10 | end 11 | @refreshed = false 12 | end 13 | 14 | def get(method, params={}, &block) 15 | request_method(:get, method, params, block) 16 | end 17 | 18 | def post(method, params={}, &block) 19 | request_method(:post, method, params, block) 20 | end 21 | 22 | def refresh_token! 23 | @refreshed = true 24 | data = request.post('/oauth/token.do', refresh_credentials) 25 | @request = nil 26 | @access_token = data['access_token'] 27 | end 28 | 29 | private 30 | 31 | def fallback(params) 32 | [params.delete(:method), params] 33 | end 34 | 35 | def method_path(method) 36 | if method.start_with?('api') 37 | "/#{method}" 38 | elsif method.start_with?('/api') 39 | method 40 | elsif method.start_with?('/') 41 | "/api#{method}" 42 | else 43 | "/api/#{method}" 44 | end.gsub('.', '/') 45 | end 46 | 47 | def refresh_credentials 48 | { 49 | refresh_token: @access_token, 50 | grant_type: 'refresh_token', 51 | client_id: @client_id, 52 | client_secret: @client_secret 53 | } 54 | end 55 | 56 | def request_method(http_method, method, params, block) 57 | method, params = fallback(method) if method.is_a?(Hash) 58 | response = request.send(http_method, method_path(method), params) 59 | response = block.call response if block 60 | response 61 | end 62 | 63 | def request 64 | refresh_token! unless @refreshed 65 | @request ||= Request.new(credentials) 66 | end 67 | 68 | def credentials 69 | { 70 | access_token: @access_token, 71 | client_secret: @client_secret, 72 | application_key: @application_key 73 | } 74 | end 75 | 76 | end 77 | end 78 | -------------------------------------------------------------------------------- /test/vcr_cassettes/wrong_credentials_token.yml: -------------------------------------------------------------------------------- 1 | --- 2 | http_interactions: 3 | - request: 4 | method: post 5 | uri: http://api.odnoklassniki.ru/oauth/token.do 6 | body: 7 | encoding: UTF-8 8 | string: '' 9 | headers: 10 | Accept: 11 | - application/json 12 | User-Agent: 13 | - odnoklassniki ruby gem/0.0.1 14 | Content-Length: 15 | - '0' 16 | Accept-Encoding: 17 | - gzip;q=1.0,deflate;q=0.6,identity;q=0.3 18 | response: 19 | status: 20 | code: 400 21 | message: Bad Request 22 | headers: 23 | Server: 24 | - Apache-Coyote/1.1 25 | Content-Type: 26 | - text/html;charset=utf-8 27 | Content-Language: 28 | - en 29 | Transfer-Encoding: 30 | - chunked 31 | Vary: 32 | - Accept-Encoding 33 | Date: 34 | - Wed, 04 Feb 2015 13:00:29 GMT 35 | Connection: 36 | - close 37 | body: 38 | encoding: UTF-8 39 | string: 'Apache Tomcat/7.0.57 - Error report

HTTP 47 | Status 400 - Provide OAUTH request parameters!


type 48 | Status report

message Provide OAUTH request parameters!

description 49 | The request sent by the client was syntactically incorrect.


Apache Tomcat/7.0.57

' 51 | http_version: 52 | recorded_at: Wed, 04 Feb 2015 13:00:29 GMT 53 | recorded_with: VCR 2.9.3 54 | -------------------------------------------------------------------------------- /lib/odnoklassniki/request.rb: -------------------------------------------------------------------------------- 1 | require_relative 'connection' 2 | require 'multi_json' 3 | 4 | module Odnoklassniki 5 | class Request 6 | 7 | include Odnoklassniki::Connection 8 | 9 | def initialize(credentials) 10 | @access_token = credentials[:access_token] 11 | @client_secret = credentials[:client_secret] 12 | @application_key = credentials[:application_key] 13 | end 14 | 15 | # Performs a get request 16 | def get(path, params={}) 17 | respond perform_request(:get, path, params) 18 | end 19 | 20 | # Performs post request 21 | def post(path, params={}) 22 | respond perform_request(:post, path, params) 23 | end 24 | 25 | private 26 | 27 | def perform_request(method, path, params) 28 | signed_params = signed params 29 | 30 | connection.send(method) do |req| 31 | req.url path 32 | if method == :get 33 | req.params = signed_params 34 | else 35 | req.body = signed_params unless params.empty? 36 | end 37 | end 38 | end 39 | 40 | def respond(response) 41 | parsed_body = \ 42 | begin 43 | MultiJson.load(response.body) 44 | rescue MultiJson::DecodeError 45 | #Есть случаи отдачи кривого JSON от одноклассников 46 | gsubed = response.body. 47 | gsub(/[^"]}/, '"}'). 48 | gsub(/([^"}]),"([^}])/, '\1","\2') 49 | MultiJson.load(gsubed) 50 | end 51 | 52 | fail_or_return_body(response.status, parsed_body) 53 | rescue MultiJson::DecodeError => e 54 | raise Odnoklassniki::Error::ClientError.new(e.message) 55 | end 56 | 57 | def fail_or_return_body(code, body) 58 | error = error(code, body) 59 | fail(error) if error 60 | body 61 | end 62 | 63 | def error(code, body) 64 | if ![200, 201].include?(code) 65 | if klass = Odnoklassniki::Error::ERRORS[code] 66 | klass.from_response(body) 67 | end 68 | else 69 | if body.is_a?(Hash) && body['error_code'] 70 | Odnoklassniki::Error::ClientError.from_response(body) 71 | end 72 | end 73 | end 74 | 75 | def signed(params) 76 | params = params.merge(application_key: @application_key) 77 | params.merge(sig: signature(params), access_token: @access_token) 78 | end 79 | 80 | def signature(params) 81 | sorted_concatenated_params = 82 | Hash[params.sort].map { |k, v| "#{k}=#{v}" }.join 83 | secret_part = Digest::MD5.hexdigest("#{@access_token}#{@client_secret}") 84 | Digest::MD5.hexdigest("#{sorted_concatenated_params}#{secret_part}") 85 | end 86 | 87 | end 88 | end 89 | -------------------------------------------------------------------------------- /lib/odnoklassniki/rest/mediatopic/content.rb: -------------------------------------------------------------------------------- 1 | module Odnoklassniki 2 | module REST 3 | class Mediatopic 4 | class Content 5 | VIDEO_LINK_PATTERN = /youtu\.?be|vimeo/.freeze 6 | AUDIO_LINK_PATTERN = /soundcloud|snd\.cc/.freeze 7 | EMBEDABLE_LINK_PATTERN = /#{VIDEO_LINK_PATTERN}|#{AUDIO_LINK_PATTERN}/.freeze 8 | TEXT_TYPE = 'text'.freeze 9 | LINK_TYPE = 'link'.freeze 10 | PHOTO_TYPE = 'photo'.freeze 11 | 12 | attr_accessor :options 13 | 14 | # Options: 15 | # text: string with message to OK (default: '') 16 | # images: Array of File (default: []) 17 | # account_type: :group/:personal (default: :personal) 18 | def initialize(options={}) 19 | @options = Odnoklassniki::Utils._symbolize_kyes(options) 20 | end 21 | 22 | def message 23 | @message ||= { 24 | type: TEXT_TYPE, 25 | text: (text || '') 26 | } 27 | end 28 | 29 | def link 30 | @link ||= \ 31 | external_url.blank? ? nil : {type: LINK_TYPE, url: external_url} 32 | end 33 | 34 | def images 35 | @images ||= [uploaded_images].compact 36 | end 37 | 38 | private 39 | 40 | def image_id_key 41 | @image_id_key ||= options[:account_type] == :group ? :id : :photoId 42 | end 43 | 44 | def uploaded_images 45 | return if options[:images].blank? 46 | 47 | photos = options[:images].map do |photo| 48 | {image_id_key => photoalbum.upload(photo)} 49 | end 50 | 51 | {type: PHOTO_TYPE, list: photos} 52 | end 53 | 54 | def photoalbum 55 | @photoalbum ||= Photoalbum.new(account) 56 | end 57 | 58 | def has_single_embedable_link? 59 | has_single_link? && embedable_url?(urls[0]) 60 | end 61 | 62 | def has_single_link? 63 | urls.count == 1 64 | end 65 | 66 | def text 67 | @text ||= options[:text] 68 | end 69 | 70 | def urls 71 | @urls ||= ::Twitter::Extractor.extract_urls(text) 72 | end 73 | 74 | def embedable_url?(url) 75 | url =~ EMBEDABLE_LINK_PATTERN 76 | end 77 | 78 | def external_url 79 | return unless resource.external_url? 80 | return resource.external_url unless shorten_links? 81 | 82 | @publication.links.where(original_url: resource.external_url) 83 | .first_or_create.short_or_generate 84 | end 85 | 86 | def _symbalize_keys(hash) 87 | symbolized = {} 88 | hash.each do |k, v| 89 | symbolized[k.to_sym] = v 90 | end 91 | hash 92 | end 93 | 94 | end 95 | end 96 | end 97 | end 98 | -------------------------------------------------------------------------------- /lib/odnoklassniki/rest/mediatopic/photoalbum.rb: -------------------------------------------------------------------------------- 1 | require 'net/http' 2 | require 'net/http/post/multipart' 3 | require 'http_uploader' 4 | 5 | require_relative '../odnoklassniki' 6 | 7 | module Odnoklassniki 8 | module REST 9 | class Mediatopic 10 | class Photoalbum 11 | 12 | GET_ALBUMS_METHOD = 'photos.getAlbums' 13 | CREATE_ALBUM_METHOD = 'photos.createAlbum' 14 | GET_ALBUM_UPLOAD_URL_METHOD = 'photosV2.getUploadUrl' 15 | COMMIT_PHOTO_METHOD = 'photosV2.commit' 16 | 17 | ALBUM_NAME = 'apiok' 18 | ALBUM_CREATION_OPTIONS = { 19 | title: ALBUM_NAME, 20 | description: 'Album for uploads from odnoklassniki api gem', 21 | type: 'public' 22 | } 23 | 24 | attr_accessor :params 25 | 26 | # Options: 27 | # account: { id: Identifier for account in OK, 28 | # type: :group/:personal } 29 | # client: Client for specified account 30 | def initialize(options) 31 | @options = Odnoklassniki::Utils._symbolize_keys(options) 32 | @account = @options[:account] 33 | @api = @options[:client] 34 | end 35 | 36 | def upload(photo) 37 | upload_photoalbum_photo(photo) 38 | end 39 | 40 | private 41 | 42 | Error = Class.new(StandardError) 43 | FindingError = Class.new(Error) 44 | CreationError = Class.new(Error) 45 | UploadingError = Class.new(Error) 46 | 47 | def upload_photoalbum_photo(photo) 48 | upload_response = ::HttpUploader.new(photoalbum_upload_url) 49 | .upload(photo.to_io, 50 | photo.basename, 51 | query_param: :pic1, content_type: photo.content_type) 52 | 53 | unless Net::HTTPSuccess === upload_response 54 | raise UploadingError, "Failed to upload file. Reason: #{upload_response.body}" 55 | end 56 | 57 | photo_id, photo_attributes = JSON.parse(upload_response.body) 58 | .try(:[], 'photos').try(:flatten) 59 | 60 | if photo_id.blank? || photo_attributes.blank? 61 | raise UploadingError, "Broken upload response. Response: #{upload_response.body}" 62 | end 63 | 64 | if @account[:type] == :personal 65 | commit_uploaded_photo(photo_id, photo_attributes['token']) 66 | else 67 | photo_attributes['token'] 68 | end 69 | end 70 | 71 | def photoalbum 72 | @photoalbum ||= begin 73 | params = {method: GET_ALBUMS_METHOD} 74 | params.merge!(gid: @account[:id]) if @account[:type] == :group 75 | 76 | @api.get(params).try(:[], 'albums').to_a 77 | .find { |album| album['title'] == ALBUM_NAME } 78 | rescue API::Error 79 | raise FindingError 80 | end 81 | end 82 | 83 | def create_photoalbum 84 | return photoalbum['aid'] if photoalbum.present? 85 | 86 | params = {method: CREATE_ALBUM_METHOD}.merge!(ALBUM_CREATION_OPTIONS) 87 | params.merge!(gid: @account[:id]) if @account[:type] == :group 88 | 89 | @api.get(params) 90 | rescue API::Error 91 | raise CreationError 92 | end 93 | 94 | def photoalbum_upload_url 95 | params = {method: GET_ALBUM_UPLOAD_URL_METHOD} 96 | 97 | if @account[:type] == :group 98 | params.merge!(gid: @account[:id]) 99 | else 100 | params.merge!(aid: create_photoalbum) 101 | end 102 | 103 | @api.get(params) { |json| URI.parse json['upload_url'] } 104 | end 105 | 106 | def commit_uploaded_photo(photo_id, photo_token) 107 | params = {method: COMMIT_PHOTO_METHOD, photo_id: photo_id, token: photo_token} 108 | @api.get(params) do |commit_response| 109 | commit_response['photos'][0]['assigned_photo_id'] 110 | end 111 | end 112 | 113 | end # class Photoalbum 114 | end # class Odnoklassniki 115 | end # module Content 116 | end # module Social 117 | 118 | -------------------------------------------------------------------------------- /README.md: -------------------------------------------------------------------------------- 1 | # Odnoklassniki 2 | [![Build Status](https://travis-ci.org/gazay/odnoklassniki.svg)](http://travis-ci.org/gazay/odnoklassniki) [![CodeClimate](https://d3s6mut3hikguw.cloudfront.net/github/gazay/odnoklassniki/badges/gpa.svg)](https://codeclimate.com/github/gazay/odnoklassniki) 3 | 4 | **Odnoklassniki** is a Ruby wrapper for the [Odnoklassniki social network API](http://apiok.ru/). 5 | 6 | At the moment, it is just a simple wrapper for GET and POST requests for Odnoklassniki API. 7 | 8 | This gem is widely used by [Amplifr](https://amplifr.com/?utm_source=odnoklassniki-gem) social media management tool and is currently under development. 9 | 10 | 11 | Amplifr 12 | 13 | 14 | 15 | Sponsored by Evil Martians 16 | 17 | 18 | ## Installation 19 | 20 | You can install the gem via RubyGems: 21 | 22 | ``` 23 | gem install odnoklassniki 24 | ``` 25 | 26 | Or by using Bundler: put 27 | 28 | ```ruby 29 | gem 'odnoklassniki' 30 | ``` 31 | 32 | in your `Gemfile`. 33 | 34 | ## Usage 35 | 36 | To use Odnoklassniki API methods you should have "[VALUABLE ACCESS](http://apiok.ru/wiki/display/api/Authorization+OAuth+2.0)" to Odnoklassniki. 37 | 38 | ### Configuration 39 | 40 | When using the gem with a Ruby on Rails application, you can configure Odnoklassniki globally by creating an initializer: `config/initializers/ok_api.rb` 41 | 42 | ```ruby 43 | Odnoklassniki.configure do |c| 44 | c.application_key = 'You application key' 45 | c.client_id = 'Your client id' 46 | c.client_secret = 'Your client secret' 47 | end 48 | ``` 49 | 50 | Or you can create a `Config` object and feed it to the `Odnoklassniki` module: 51 | 52 | ```ruby 53 | config = Odnoklassniki::Config.configure do |c| 54 | # ... 55 | end 56 | 57 | Odnoklassniki.config = config 58 | ``` 59 | 60 | Also, when creating a new `Odnoklassniki::Client`, you can pass along all required (or missing from the configuration step) options right there: 61 | 62 | ```ruby 63 | Odnoklassniki::Client.new(access_token: 'your token', client_id: 'your client id') 64 | ``` 65 | 66 | ### Example 67 | 68 | ```ruby 69 | client = Odnoklassniki::Client.new(access_token: token) 70 | 71 | new_token = client.refresh_token! # This method will be called automatically just once 72 | # for each client before performing the request 73 | 74 | client.get('friends.get') 75 | client.get('friends/get') 76 | client.get('api/friends/get') 77 | client.get('/api/friends/get') 78 | # NOTE: All GET requests above are identical! 79 | 80 | client.post('mediatopic.post', type: 'USER_STATUS', attachment: attachment) 81 | ``` 82 | 83 | ### Error Handling 84 | 85 | Unfortunately, most errors from Odnoklassniki API are returned within a _success_ response (200 HTTP status code). 86 | So, there is a wrapper just for that in this gem: 87 | 88 | ```ruby 89 | begin 90 | client.get('some.wrong.request') 91 | rescue Odnoklassniki::Error::ClientError => e 92 | e.inspect 93 | end 94 | ``` 95 | 96 | Also there is a bunch of client/server error classes whose structure was gratefully copied and adopted from 97 | [@sferik](https://github.com/sferik)'s [twitter](https://github.com/sferik/twitter) gem. 98 | They can be useful in case when Odnoklassniki API wasn't reached at all or when some other issue has occured. 99 | 100 | ## TODO 101 | 102 | 1. Wrap some usual methods like `users.getCurrentUser`, `mediatopic.post` etc. 103 | 2. Write tests with real credentials 104 | 105 | ## Contributing 106 | 107 | 1. Fork it 108 | 2. Create your feature branch (`git checkout -b my-new-feature`) 109 | 3. Commit your changes (`git commit -am 'Add some feature'`) 110 | 4. Push to the branch (`git push origin my-new-feature`) 111 | 5. Create new Pull Request 112 | 113 | ## Contributors 114 | 115 | * @gazay 116 | 117 | Special thanks to [@strech](https://github.com/strech), [@igas](https://github.com/igas). 118 | 119 | ## License 120 | 121 | [The MIT License](https://github.com/gazay/odnoklassniki/blob/master/LICENSE) 122 | -------------------------------------------------------------------------------- /lib/odnoklassniki/error.rb: -------------------------------------------------------------------------------- 1 | # Taken and adopted from https://github.com/sferik/twitter gem 2 | module Odnoklassniki 3 | # Custom error class for rescuing from all Odnoklassniki errors 4 | class Error < StandardError 5 | # @return [Integer] 6 | attr_reader :code 7 | 8 | # Raised when Odnoklassniki returns a 2xx HTTP status code 9 | ClientError = Class.new(self) 10 | 11 | # Raised when Odnoklassniki returns the HTTP status code 400 12 | BadRequest = Class.new(ClientError) 13 | 14 | # Raised when Odnoklassniki returns the HTTP status code 401 15 | Unauthorized = Class.new(ClientError) 16 | 17 | # Raised when Odnoklassniki returns the HTTP status code 403 18 | Forbidden = Class.new(ClientError) 19 | 20 | # Raised when Odnoklassniki returns the HTTP status code 404 21 | NotFound = Class.new(ClientError) 22 | 23 | # Raised when Odnoklassniki returns the HTTP status code 406 24 | NotAcceptable = Class.new(ClientError) 25 | 26 | # Raised when Odnoklassniki returns the HTTP status code 422 27 | UnprocessableEntity = Class.new(ClientError) 28 | 29 | # Raised when Odnoklassniki returns the HTTP status code 429 30 | TooManyRequests = Class.new(ClientError) 31 | 32 | # Raised when Odnoklassniki returns a 5xx HTTP status code 33 | ServerError = Class.new(self) 34 | 35 | # Raised when Odnoklassniki returns the HTTP status code 500 36 | InternalServerError = Class.new(ServerError) 37 | 38 | # Raised when Odnoklassniki returns the HTTP status code 502 39 | BadGateway = Class.new(ServerError) 40 | 41 | # Raised when Odnoklassniki returns the HTTP status code 503 42 | ServiceUnavailable = Class.new(ServerError) 43 | 44 | # Raised when Odnoklassniki returns the HTTP status code 504 45 | GatewayTimeout = Class.new(ServerError) 46 | 47 | ERRORS = { 48 | 200 => Odnoklassniki::Error::ClientError, 49 | 400 => Odnoklassniki::Error::BadRequest, 50 | 401 => Odnoklassniki::Error::Unauthorized, 51 | 403 => Odnoklassniki::Error::Forbidden, 52 | 404 => Odnoklassniki::Error::NotFound, 53 | 406 => Odnoklassniki::Error::NotAcceptable, 54 | 422 => Odnoklassniki::Error::UnprocessableEntity, 55 | 429 => Odnoklassniki::Error::TooManyRequests, 56 | 500 => Odnoklassniki::Error::InternalServerError, 57 | 502 => Odnoklassniki::Error::BadGateway, 58 | 503 => Odnoklassniki::Error::ServiceUnavailable, 59 | 504 => Odnoklassniki::Error::GatewayTimeout, 60 | } 61 | 62 | module Code 63 | UNKNOWN = 1 # Unknown error 64 | SERVICE = 2 # Service temporary unavailable 65 | METHOD = 3 # Method does not exist. 66 | REQUEST = 4 # Failed to process request due to invalid request 67 | ACTION_BLOCKED = 7 # The requested action is temporarily blocked for current user 68 | FLOOD_BLOCKED = 8 # The execution of method is blocked due to flood 69 | IP_BLOCKED = 9 # The execution of method is blocked by IP address due to suspicious activity of current user or due to other restrictions applied to given method 70 | PERMISSION_DENIED = 10 # Permission denied. Possible reason - user not authorized application to perform operation 71 | LIMIT_REACHED = 11 # Method invocation limit reached 72 | CANCELLED = 12 # Operation was cancelled by user 73 | NOT_MULTIPART = 21 # Not a multi-part request when uploading photo 74 | NOT_ACTIVATED = 22 # User must activate his profile to complete the action 75 | NOT_YET_INVOLVED = 23 # User not involved to the application - see notes (in russian) 76 | NOT_OWNER = 24 # User does not own specified object 77 | NOT_ACTIVE = 25 # Notification sending error. User not active in application. 78 | TOTAL_LIMIT_REACHED = 26 # Notification sending error. Notification limit reached. notes (in russian) 79 | PARAM = 100 # Missing or invalid parameter 80 | PARAM_API_KEY = 101 # Parameter application_key not specified or invalid 81 | PARAM_SESSION_EXPIRED = 102 # Session key is expired 82 | PARAM_SESSION_KEY = 103 # Invalid session key 83 | PARAM_SIGNATURE = 104 # Invalid signature 84 | PARAM_RESIGNATURE = 105 # Invalid re-signature 85 | PARAM_ENTITY_ID = 106 # Invalid entity ID (discussions) 86 | PARAM_USER_ID = 110 # Invalid user ID 87 | PARAM_ALBUM_ID = 120 # Invalid album ID 88 | PARAM_PHOTO_ID = 121 # Invalid photo ID 89 | PARAM_WIDGET = 130 # Invalid Widget ID 90 | PARAM_MESSAGE_ID = 140 # Invalid message ID 91 | PARAM_COMMENT_ID = 141 # Invalid comment ID 92 | PARAM_HAPPENING_ID = 150 # Invalid happening ID 93 | PARAM_HAPPENING_PHOTO_ID = 151 # Invalid happening photo ID 94 | PARAM_GROUP_ID = 160 # Invalid group ID 95 | PARAM_PERMISSION = 200 # Application can not perform operation. In most cases, caused by access to operation without user authorization 96 | PARAM_APPLICATION_DISABLED = 210 # Application is disabled 97 | PARAM_DECISION = 211 # Invalid decision ID 98 | PARAM_BADGE_ID = 212 # Invalid badge ID 99 | PARAM_PRESENT_ID = 213 # Invalid present ID 100 | PARAM_RELATION_TYPE = 214 # Invalid relation type 101 | NOT_FOUND = 300 # Requested information is not found 102 | EDIT_PHOTO_FILE = 324 # Error processing multi-part request 103 | AUTH_LOGIN = 401 # Authentication failure. Invalid login/password or authentication token or user is deleted/blocked. 104 | AUTH_LOGIN_CAPTCHA = 402 # Authentication failure. Captcha entry is required for login. 105 | AUTH_LOGIN_WEB_HUMAN_CHECK = 403 # Authentication failure. 106 | NOT_SESSION_METHOD = 451 # Session is prohibited for the method, but session key was specified 107 | SESSION_REQUIRED = 453 # Session key was not specified for the method, which requires session 108 | CENSOR_MATCH = 454 # Text rejected by censor 109 | FRIEND_RESTRICTION = 455 # Cannot perform operation because friend set restriction on it (put to "black list" or made his/her account private) 110 | GROUP_RESTRICTION = 456 # Cannot perform operation because group set restriction on it 111 | UNAUTHORIZED_RESTRICTION = 457 # Unauthorized access 112 | PRIVACY_RESTRICTION = 458 # Same as FRIEND_RESTRICTION 113 | PHOTO_SIZE_LIMIT_EXCEEDED = 500 # The size in bytes of image binary content exceeds the limits 114 | PHOTO_SIZE_TOO_SMALL = 501 # The image size in pixels are too small 115 | PHOTO_SIZE_TOO_BIG = 502 # The image size in pixels are too big 116 | PHOTO_INVALID_FORMAT = 503 # The image format cannot be recognized 117 | PHOTO_IMAGE_CORRUPTED = 504 # The image format is recognized, but the content is corrupted 118 | PHOTO_NO_IMAGE = 505 # No image is found in request 119 | PHOTO_PIN_TOO_MUCH = 508 # Too much photopin's on photo. 120 | IDS_BLOCKED = 511 # Photopin error from antispam system 121 | PHOTO_ALBUM_NOT_BELONGS_TO_USER = 512 # Album not belongs to the user 122 | PHOTO_ALBUM_NOT_BELONGS_TO_GROUP = 513 # Album not belongs to the specified group 123 | MEDIA_TOPIC_BLOCK_LIMIT = 600 # Too many media parameters 124 | MEDIA_TOPIC_TEXT_LIMIT = 601 # Text limit reached 125 | MEDIA_TOPIC_POLL_QUESTION_TEXT_LIMIT = 602 # Question text limit reached 126 | MEDIA_TOPIC_POLL_ANSWERS_LIMIT = 603 # Too many answer parameters 127 | MEDIA_TOPIC_POLL_ANSWER_TEXT_LIMIT = 604 # Answer text limit reached 128 | MEDIA_TOPIC_WITH_FRIENDS_LIMIT = 605 # Pinned friends count limit reached 129 | MEDIA_TOPIC_WITH_FRIENDS_USER_LIMIT = 606 # Pinned friends count limit reached (user-specific) 130 | GROUP_DUPLICATE_JOIN_REQUEST = 610 # Group join request already registered. 131 | COMMENT_NOT_FOUND = 700 # Comment not found 132 | INVALID_AUTHOR = 701 # Invalid author 133 | COMMENT_NOT_ACTIVE = 702 # Comment was removed 134 | TIMEOUT_EXCEEDED = 704 # Edit timeout exceeded 135 | CHAT_NOT_FOUND = 705 # Chat not found 136 | MESSAGE_NOT_ACTIVE = 706 # Message was removed 137 | NO_SUCH_APP = 900 # Returned, when try to get public application information for not existing application 138 | CALLBACK_INVALID_PAYMENT = 1001 # Error returned by the application server to notify about invalid transaction details 139 | PAYMENT_IS_REQUIRED_PAYMENT = 1002 # Payment is required to use service 140 | INVALID_PAYMENT = 1003 # Invalid payment transaction 141 | DUPLICATE_PAYMENT = 1004 # Instant payment is too frequent 142 | NOT_ENOUGH_MONEY = 1005 # User has no requested amount of money on his account 143 | VCHAT_SERVICE_DISABLED = 1101 # Video chat is disabled. 144 | TARGET_USER_UNAVAILABLE = 1102 # Target user is not available for video chat or video message/ 145 | FRIENDSHIP_REQUIRED = 1103 # Target user must be a friend. 146 | BATCH = 1200 # Batching error. 147 | APP_NO_PLATFORM_ALLOWED = 1300 # No platforms allowed for this application 148 | APP_DEVICE_NOT_ALLOWED = 1301 # Specified device not allowed 149 | APP_DEVICE_NOT_SPECIFIED = 1302 # Device not specified 150 | APP_EMPTY_SEARCH_PARAMS = 1400 # Location search error. 151 | APP_SEARCH_SCENARIO_DOES_NOT_EXIST = 1401 # Location search error. 152 | SYSTEM = 9999 # Critical system error. Please report these problems support 153 | end 154 | 155 | class << self 156 | # Create a new error from an HTTP response 157 | # 158 | # @param response [HTTP::Response] 159 | # @return [Odnoklassniki::Error] 160 | def from_response(body) 161 | new(*parse_error(body)) 162 | end 163 | 164 | private 165 | 166 | def parse_error(body) 167 | [body['error_msg'].to_s, body['error_code']] 168 | end 169 | 170 | end 171 | 172 | # Initializes a new Error object 173 | # 174 | # @param message [Exception, String] 175 | # @param code [Integer] 176 | # @return [Odnoklassniki::Error] 177 | def initialize(message = '', code = nil) 178 | super(message) 179 | @code = code 180 | end 181 | end 182 | end 183 | --------------------------------------------------------------------------------