odnoklassniki 0.0.1 → 0.0.2
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/README.md +34 -19
- data/lib/odnoklassniki/client.rb +8 -6
- data/lib/odnoklassniki/request.rb +5 -1
- data/lib/odnoklassniki/rest/mediatopic.rb +13 -0
- data/lib/odnoklassniki/rest/mediatopic/content.rb +97 -0
- data/lib/odnoklassniki/rest/mediatopic/photoalbum.rb +117 -0
- data/lib/odnoklassniki/rest/user.rb +18 -0
- data/lib/odnoklassniki/utils.rb +18 -0
- data/lib/odnoklassniki/version.rb +1 -1
- metadata +8 -3
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 2b3a824e8027e9e9d9ba740492920481a3310b1b
|
4
|
+
data.tar.gz: fe9adca08f39d5d97e7eab6b432ee0d41a98c5cf
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 24f487fbb1cbacf25299394843fda7dba17555f0ca40ed46ff718d36d061226ec525e69cb17178eca4f730b35e6d4bdd9f779930a6929310c8ff01144ab77c21
|
7
|
+
data.tar.gz: 0294159377a0adf28f714b91f9c2eebee75799e4ef1c8a1ab0d874edc2c8a116dc8bfc6dbd3c63f355410bbafa2b9b7f4f55a5cb5fcbb06cb56c12e0a794fc1a
|
data/README.md
CHANGED
@@ -1,11 +1,15 @@
|
|
1
1
|
# Odnoklassniki
|
2
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
3
|
|
4
|
-
Ruby wrapper for Odnoklassniki API
|
4
|
+
**Odnoklassniki** is a Ruby wrapper for the [Odnoklassniki social network API](http://apiok.ru/).
|
5
5
|
|
6
|
-
|
6
|
+
At the moment, it is just a simple wrapper for GET and POST requests for Odnoklassniki API.
|
7
7
|
|
8
|
-
This gem widely used
|
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
|
+
<a href="https://amplifr.com/?utm_source=odnoklassniki-gem">
|
11
|
+
<img src="https://amplifr.com/logo.png" alt="Amplifr" width="162" height="162">
|
12
|
+
</a>
|
9
13
|
|
10
14
|
<a href="https://evilmartians.com/?utm_source=odnoklassniki-gem">
|
11
15
|
<img src="https://evilmartians.com/badges/sponsored-by-evil-martians.svg" alt="Sponsored by Evil Martians" width="236" height="54">
|
@@ -13,17 +17,27 @@ This gem widely used in [Amplifr](https://amplifr.com) and currently being devel
|
|
13
17
|
|
14
18
|
## Installation
|
15
19
|
|
20
|
+
You can install the gem via RubyGems:
|
21
|
+
|
22
|
+
```
|
23
|
+
gem install odnoklassniki
|
16
24
|
```
|
17
|
-
|
25
|
+
|
26
|
+
Or by using Bundler: put
|
27
|
+
|
28
|
+
```ruby
|
29
|
+
gem 'odnoklassniki'
|
18
30
|
```
|
19
31
|
|
32
|
+
in your `Gemfile`.
|
33
|
+
|
20
34
|
## Usage
|
21
35
|
|
22
|
-
To use
|
36
|
+
To use Odnoklassniki API methods you should have "[VALUABLE ACCESS](http://apiok.ru/wiki/display/api/Authorization+OAuth+2.0)" to Odnoklassniki.
|
23
37
|
|
24
38
|
### Configuration
|
25
39
|
|
26
|
-
|
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`
|
27
41
|
|
28
42
|
```ruby
|
29
43
|
Odnoklassniki.configure do |c|
|
@@ -33,17 +47,17 @@ Odnoklassniki.configure do |c|
|
|
33
47
|
end
|
34
48
|
```
|
35
49
|
|
36
|
-
Or you can create
|
50
|
+
Or you can create a `Config` object and feed it to the `Odnoklassniki` module:
|
37
51
|
|
38
52
|
```ruby
|
39
53
|
config = Odnoklassniki::Config.configure do |c|
|
40
|
-
...
|
54
|
+
# ...
|
41
55
|
end
|
42
56
|
|
43
57
|
Odnoklassniki.config = config
|
44
58
|
```
|
45
59
|
|
46
|
-
Also, when
|
60
|
+
Also, when creating a new `Odnoklassniki::Client`, you can pass along all required (or missing from the configuration step) options right there:
|
47
61
|
|
48
62
|
```ruby
|
49
63
|
Odnoklassniki::Client.new(access_token: 'your token', client_id: 'your client id')
|
@@ -54,22 +68,22 @@ Odnoklassniki::Client.new(access_token: 'your token', client_id: 'your client id
|
|
54
68
|
```ruby
|
55
69
|
client = Odnoklassniki::Client.new(access_token: token)
|
56
70
|
|
57
|
-
new_token = client.refresh_token! # This method will be called
|
58
|
-
# for each client before performing request
|
71
|
+
new_token = client.refresh_token! # This method will be called automatically just once
|
72
|
+
# for each client before performing the request
|
59
73
|
|
60
74
|
client.get('friends.get')
|
61
75
|
client.get('friends/get')
|
62
76
|
client.get('api/friends/get')
|
63
77
|
client.get('/api/friends/get')
|
64
|
-
# All
|
78
|
+
# NOTE: All GET requests above are identical!
|
65
79
|
|
66
80
|
client.post('mediatopic.post', type: 'USER_STATUS', attachment: attachment)
|
67
81
|
```
|
68
82
|
|
69
|
-
### Error
|
83
|
+
### Error Handling
|
70
84
|
|
71
|
-
|
72
|
-
So there is a wrapper for
|
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:
|
73
87
|
|
74
88
|
```ruby
|
75
89
|
begin
|
@@ -79,8 +93,9 @@ rescue Odnoklassniki::Error::ClientError => e
|
|
79
93
|
end
|
80
94
|
```
|
81
95
|
|
82
|
-
Also there
|
83
|
-
@sferik's twitter gem.
|
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.
|
84
99
|
|
85
100
|
## TODO
|
86
101
|
|
@@ -99,8 +114,8 @@ Also there are bunch of client/server error classes which structure was grateful
|
|
99
114
|
|
100
115
|
* @gazay
|
101
116
|
|
102
|
-
Special thanks to @
|
117
|
+
Special thanks to [@strech](https://github.com/strech), [@igas](https://github.com/igas).
|
103
118
|
|
104
119
|
## License
|
105
120
|
|
106
|
-
The MIT License
|
121
|
+
[The MIT License](https://github.com/gazay/odnoklassniki/blob/master/LICENSE)
|
data/lib/odnoklassniki/client.rb
CHANGED
@@ -11,12 +11,12 @@ module Odnoklassniki
|
|
11
11
|
@refreshed = false
|
12
12
|
end
|
13
13
|
|
14
|
-
def get(method, params={})
|
15
|
-
request_method(:get, method, params)
|
14
|
+
def get(method, params={}, &block)
|
15
|
+
request_method(:get, method, params, block)
|
16
16
|
end
|
17
17
|
|
18
|
-
def post(method, params={})
|
19
|
-
request_method(:post, method, params)
|
18
|
+
def post(method, params={}, &block)
|
19
|
+
request_method(:post, method, params, block)
|
20
20
|
end
|
21
21
|
|
22
22
|
def refresh_token!
|
@@ -53,9 +53,11 @@ module Odnoklassniki
|
|
53
53
|
}
|
54
54
|
end
|
55
55
|
|
56
|
-
def request_method(http_method, method, params)
|
56
|
+
def request_method(http_method, method, params, block)
|
57
57
|
method, params = fallback(method) if method.is_a?(Hash)
|
58
|
-
request.send(http_method, method_path(method), params)
|
58
|
+
response = request.send(http_method, method_path(method), params)
|
59
|
+
response = block.call response if block
|
60
|
+
response
|
59
61
|
end
|
60
62
|
|
61
63
|
def request
|
@@ -40,7 +40,11 @@ module Odnoklassniki
|
|
40
40
|
def respond(response)
|
41
41
|
parsed_body = \
|
42
42
|
begin
|
43
|
-
|
43
|
+
if response.body.nil? || response.body == ''
|
44
|
+
return response.body
|
45
|
+
else
|
46
|
+
MultiJson.load(response.body)
|
47
|
+
end
|
44
48
|
rescue MultiJson::DecodeError
|
45
49
|
#Есть случаи отдачи кривого JSON от одноклассников
|
46
50
|
gsubed = response.body.
|
@@ -0,0 +1,97 @@
|
|
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
|
@@ -0,0 +1,117 @@
|
|
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
|
+
|
@@ -0,0 +1,18 @@
|
|
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
|
@@ -0,0 +1,18 @@
|
|
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
|
metadata
CHANGED
@@ -1,14 +1,14 @@
|
|
1
1
|
--- !ruby/object:Gem::Specification
|
2
2
|
name: odnoklassniki
|
3
3
|
version: !ruby/object:Gem::Version
|
4
|
-
version: 0.0.
|
4
|
+
version: 0.0.2
|
5
5
|
platform: ruby
|
6
6
|
authors:
|
7
7
|
- gazay
|
8
8
|
autorequire:
|
9
9
|
bindir: bin
|
10
10
|
cert_chain: []
|
11
|
-
date:
|
11
|
+
date: 2016-06-22 00:00:00.000000000 Z
|
12
12
|
dependencies:
|
13
13
|
- !ruby/object:Gem::Dependency
|
14
14
|
name: faraday
|
@@ -215,6 +215,11 @@ files:
|
|
215
215
|
- lib/odnoklassniki/connection.rb
|
216
216
|
- lib/odnoklassniki/error.rb
|
217
217
|
- lib/odnoklassniki/request.rb
|
218
|
+
- lib/odnoklassniki/rest/mediatopic.rb
|
219
|
+
- lib/odnoklassniki/rest/mediatopic/content.rb
|
220
|
+
- lib/odnoklassniki/rest/mediatopic/photoalbum.rb
|
221
|
+
- lib/odnoklassniki/rest/user.rb
|
222
|
+
- lib/odnoklassniki/utils.rb
|
218
223
|
- lib/odnoklassniki/version.rb
|
219
224
|
- odnoklassniki.gemspec
|
220
225
|
- test/lib/odnoklassniki/client_test.rb
|
@@ -248,7 +253,7 @@ required_rubygems_version: !ruby/object:Gem::Requirement
|
|
248
253
|
version: '0'
|
249
254
|
requirements: []
|
250
255
|
rubyforge_project: odnoklassniki
|
251
|
-
rubygems_version: 2.
|
256
|
+
rubygems_version: 2.5.1
|
252
257
|
signing_key:
|
253
258
|
specification_version: 4
|
254
259
|
summary: Ruby wrapper for Odnoklassniki API
|