odnoklassniki 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: fa32a6ad3f01eeb19c56f001b06a75ba7564610d
4
+ data.tar.gz: 888fdd5cacb10c743b680d5858df65a98d6830ff
5
+ SHA512:
6
+ metadata.gz: d3f1963e9c51d82be4760e9c7ac58795e40a5c39262b62755df9221216b2299d7d3aa07e88065f31640e6da82a987da2a475968744186dc4da0913debda505c7
7
+ data.tar.gz: 18876b13cbc7e90b6038f78ad528ae100733555a870fb904d18c772b5d1e5c8d1a841d7f48c72efd517ba2cf7e640a5880b04ceaddf6170fa033a014450e817a
@@ -0,0 +1,3 @@
1
+ /.bundle
2
+ /Gemfile.lock
3
+ /coverage
@@ -0,0 +1,12 @@
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
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source "http://rubygems.org"
2
+
3
+ # Specify your gem's dependencies in odnoklassniki.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,22 @@
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
+
@@ -0,0 +1,106 @@
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
+ Ruby wrapper for Odnoklassniki API
5
+
6
+ Right now it is a simple wrapper on get and post requests to Odnoklassniki api.
7
+
8
+ This gem widely used in [Amplifr](https://amplifr.com) and currently being developed
9
+
10
+ <a href="https://evilmartians.com/?utm_source=odnoklassniki-gem">
11
+ <img src="https://evilmartians.com/badges/sponsored-by-evil-martians.svg" alt="Sponsored by Evil Martians" width="236" height="54">
12
+ </a>
13
+
14
+ ## Installation
15
+
16
+ ```
17
+ gem install odnoklassniki
18
+ ```
19
+
20
+ ## Usage
21
+
22
+ To use odnoklassniki api methods you should have [VALUABLE ACCESS](http://dev.odnoklassniki.ru/wiki/pages/viewpage.action?pageId=12878032) to odnoklassniki.
23
+
24
+ ### Configuration
25
+
26
+ You can create global configuration for your application. Create initializer `config/initializers/ok_api.rb`:
27
+
28
+ ```ruby
29
+ Odnoklassniki.configure do |c|
30
+ c.application_key = 'You application key'
31
+ c.client_id = 'Your client id'
32
+ c.client_secret = 'Your client secret'
33
+ end
34
+ ```
35
+
36
+ Or you can create config object and feed it to `Odnoklassniki` module:
37
+
38
+ ```ruby
39
+ config = Odnoklassniki::Config.configure do |c|
40
+ ...
41
+ end
42
+
43
+ Odnoklassniki.config = config
44
+ ```
45
+
46
+ Also, when you create new `Odnoklassniki::Client` you can pass all needed (or missed on configuration step) options right there:
47
+
48
+ ```ruby
49
+ Odnoklassniki::Client.new(access_token: 'your token', client_id: 'your client id')
50
+ ```
51
+
52
+ ### Example
53
+
54
+ ```ruby
55
+ client = Odnoklassniki::Client.new(access_token: token)
56
+
57
+ new_token = client.refresh_token! # This method will be called automaticaly just once
58
+ # for each client before performing request
59
+
60
+ client.get('friends.get')
61
+ client.get('friends/get')
62
+ client.get('api/friends/get')
63
+ client.get('/api/friends/get')
64
+ # All get requests above identical
65
+
66
+ client.post('mediatopic.post', type: 'USER_STATUS', attachment: attachment)
67
+ ```
68
+
69
+ ### Error handling
70
+
71
+ Most of errors from Odnoklassniki API retruned in success response (with status code 200).
72
+ So there is a wrapper for it in this gem:
73
+
74
+ ```ruby
75
+ begin
76
+ client.get('some.wrong.request')
77
+ rescue Odnoklassniki::Error::ClientError => e
78
+ e.inspect
79
+ end
80
+ ```
81
+
82
+ Also there are bunch of client/server error classes which structure was gratefully copied and adopted from
83
+ @sferik's twitter gem. They can be useful when Odnoklassniki API wasn't reached or when some other issue occured.
84
+
85
+ ## TODO
86
+
87
+ 1. Wrap some usual methods like `users.getCurrentUser`, `mediatopic.post` etc.
88
+ 2. Write tests with real credentials
89
+
90
+ ## Contributing
91
+
92
+ 1. Fork it
93
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
94
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
95
+ 4. Push to the branch (`git push origin my-new-feature`)
96
+ 5. Create new Pull Request
97
+
98
+ ## Contributors
99
+
100
+ * @gazay
101
+
102
+ Special thanks to @Strech, @igas.
103
+
104
+ ## License
105
+
106
+ The MIT License
@@ -0,0 +1,9 @@
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)
@@ -0,0 +1,27 @@
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
@@ -0,0 +1,75 @@
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={})
15
+ request_method(:get, method, params)
16
+ end
17
+
18
+ def post(method, params={})
19
+ request_method(:post, method, params)
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)
57
+ method, params = fallback(method) if method.is_a?(Hash)
58
+ request.send(http_method, method_path(method), params)
59
+ end
60
+
61
+ def request
62
+ refresh_token! unless @refreshed
63
+ @request ||= Request.new(credentials)
64
+ end
65
+
66
+ def credentials
67
+ {
68
+ access_token: @access_token,
69
+ client_secret: @client_secret,
70
+ application_key: @application_key
71
+ }
72
+ end
73
+
74
+ end
75
+ end
@@ -0,0 +1,31 @@
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
@@ -0,0 +1,29 @@
1
+ require 'faraday'
2
+ require 'faraday_middleware'
3
+
4
+ module Odnoklassniki
5
+ module Connection
6
+ API_HOST = 'http://api.odnoklassniki.ru'
7
+
8
+ def connection(options={})
9
+ options = options.clone
10
+
11
+ default_options = {
12
+ :headers => {
13
+ :accept => 'application/json',
14
+ :user_agent => "odnoklassniki ruby gem/#{Odnoklassniki::VERSION}"
15
+ },
16
+ :url => "#{API_HOST}/"
17
+ }
18
+
19
+ client = Faraday.default_adapter
20
+
21
+ Faraday.new(default_options.merge(options)) do |conn|
22
+ conn.request :multipart
23
+ conn.request :url_encoded
24
+ conn.adapter client
25
+ end
26
+ end
27
+
28
+ end
29
+ end
@@ -0,0 +1,182 @@
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