yandex-api-direct 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.document +5 -0
- data/Gemfile +20 -0
- data/LICENSE.txt +20 -0
- data/README.markdown +163 -0
- data/Rakefile +35 -0
- data/VERSION +1 -0
- data/lib/yandex-api-direct.rb +69 -0
- data/lib/yandex-api-direct/yandex_object.rb +131 -0
- data/lib/yandex-api-direct/yandex_objects/campaign.rb +39 -0
- data/lib/yandex-api-direct/yandex_objects/campaign_param.rb +17 -0
- data/lib/yandex-api-direct/yandex_objects/campaign_stats.rb +25 -0
- data/lib/yandex-api-direct/yandex_objects/client.rb +38 -0
- data/lib/yandex-api-direct/yandex_objects/generic.rb +23 -0
- data/test/fixtures/yandex_campaign_params.json +103 -0
- data/test/fixtures/yandex_campaign_stats.json +52 -0
- data/test/fixtures/yandex_get_campaigns_list.json +61 -0
- data/test/fixtures/yandex_get_client_info.json +18 -0
- data/test/fixtures/yandex_get_client_list.json +34 -0
- data/test/fixtures/yandex_object_valid_responce.json +15 -0
- data/test/models.rb +5 -0
- data/test/test_helper.rb +50 -0
- data/test/test_yandex-api.rb +36 -0
- data/test/yandex-api-direct/test_campaign.rb +68 -0
- data/test/yandex-api-direct/test_campaign_params.rb +32 -0
- data/test/yandex-api-direct/test_campaign_stats.rb +35 -0
- data/test/yandex-api-direct/test_client.rb +113 -0
- data/test/yandex-api-direct/test_generic.rb +47 -0
- data/test/yandex-api-direct/test_yandex_object.rb +131 -0
- metadata +233 -0
data/.document
ADDED
data/Gemfile
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
source "http://rubygems.org"
|
2
|
+
|
3
|
+
#Oauth Doorman for getting access to oauth 2
|
4
|
+
gem "oauth_doorman", :git => "https://github.com/Ataxo/oauth_doorman.git"
|
5
|
+
gem "activesupport"
|
6
|
+
gem "hashr"
|
7
|
+
|
8
|
+
group :development do
|
9
|
+
gem 'shoulda-context'
|
10
|
+
gem "mocha"
|
11
|
+
gem "turn"
|
12
|
+
gem "sdoc" # sdoc -N .
|
13
|
+
gem "bundler"
|
14
|
+
gem "jeweler"
|
15
|
+
gem "ansi"
|
16
|
+
gem "simplecov"
|
17
|
+
gem "sinatra"
|
18
|
+
gem 'colorize'
|
19
|
+
gem "webmock"
|
20
|
+
end
|
data/LICENSE.txt
ADDED
@@ -0,0 +1,20 @@
|
|
1
|
+
Copyright (c) 2012 Ondrej Bartas
|
2
|
+
|
3
|
+
Permission is hereby granted, free of charge, to any person obtaining
|
4
|
+
a copy of this software and associated documentation files (the
|
5
|
+
"Software"), to deal in the Software without restriction, including
|
6
|
+
without limitation the rights to use, copy, modify, merge, publish,
|
7
|
+
distribute, sublicense, and/or sell copies of the Software, and to
|
8
|
+
permit persons to whom the Software is furnished to do so, subject to
|
9
|
+
the following conditions:
|
10
|
+
|
11
|
+
The above copyright notice and this permission notice shall be
|
12
|
+
included in all copies or substantial portions of the Software.
|
13
|
+
|
14
|
+
THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
15
|
+
EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
16
|
+
MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
17
|
+
NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
18
|
+
LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
19
|
+
OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
20
|
+
WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
data/README.markdown
ADDED
@@ -0,0 +1,163 @@
|
|
1
|
+
# Yandex-API-Direct
|
2
|
+
|
3
|
+
Accessing Yandex API and work with campaigns and statistics
|
4
|
+
|
5
|
+
## Instalation
|
6
|
+
|
7
|
+
Just in console
|
8
|
+
|
9
|
+
``` ruby
|
10
|
+
gem install yandex-api-direct
|
11
|
+
```
|
12
|
+
|
13
|
+
Or put into Gemfile
|
14
|
+
|
15
|
+
``` ruby
|
16
|
+
gem "yandex-api-direct"
|
17
|
+
```
|
18
|
+
|
19
|
+
and somewhere before use (not rails - they will require gem automaticaly)
|
20
|
+
``` ruby
|
21
|
+
require "yandex-api-direct"
|
22
|
+
```
|
23
|
+
|
24
|
+
## Initialization
|
25
|
+
|
26
|
+
Setup your config values by calling YandexApiDirect.config = {}
|
27
|
+
|
28
|
+
``` ruby
|
29
|
+
YandexApiDirect.config = {
|
30
|
+
locale: "en"
|
31
|
+
application_id: "YOUR APPLICATION ID"
|
32
|
+
login: "FILL LOGIN OF USER"
|
33
|
+
access_token: "FILL ACCESS TOKEN FOR USER"
|
34
|
+
}
|
35
|
+
```
|
36
|
+
|
37
|
+
Get application_id by registering your application at https://oauth.yandex.com/client/new
|
38
|
+
(full doc at: http://api.yandex.com/oauth/doc/dg/tasks/register-client.xml)
|
39
|
+
|
40
|
+
If you need to get Oauth token you will also need application password (also listed on registration page).
|
41
|
+
|
42
|
+
## Working with Gem
|
43
|
+
|
44
|
+
You can access Main classes: Client, Campaign, CampaignParam, CampaignStats
|
45
|
+
|
46
|
+
### How one class works
|
47
|
+
|
48
|
+
Main classes are inherited from [Hashr](https://github.com/svenfuchs/hashr) and includes [YandexObject](https://github.com/Ataxo/yandex-api-direct/blob/master/lib/yandex-api-direct/yandex_object.rb)
|
49
|
+
This combination will provide very easy acces to all returned values from API.
|
50
|
+
|
51
|
+
``` ruby
|
52
|
+
# Find some objects:
|
53
|
+
campaigns = YandexApiDirect::Campaign.find
|
54
|
+
# you got [ <Campaign:..>, ... ] and choose first one
|
55
|
+
campaign = campaigns.first
|
56
|
+
# then you can ask for something
|
57
|
+
campaign.name #=> "Campaign"
|
58
|
+
campaign.campaign_id #=> 123456
|
59
|
+
campaign.clicks #=> 123
|
60
|
+
```
|
61
|
+
|
62
|
+
Arguments from api is hash, this hash is saved by hashr directly into instance.
|
63
|
+
Keys from API are underscored for using as normal methods not `campaign.Name` instead of this use: `campaign.name`
|
64
|
+
**Instance is still Hash, you can do all stuf like with normal hash.**
|
65
|
+
|
66
|
+
### Find
|
67
|
+
``` ruby
|
68
|
+
#you can pass arguments to find as hash: [GetClientsList](http://api.yandex.com/direct/doc/reference/GetClientsList.xml)
|
69
|
+
YandexApiDirect::Client.find
|
70
|
+
#=> [ <Client:..>, ... ]
|
71
|
+
|
72
|
+
#you can pass argument as array of logins (optional for agencies): [GetCampaignsList](http://api.yandex.com/direct/doc/reference/GetCampaignsList.xml)
|
73
|
+
YandexApiDirect::Campaign.find
|
74
|
+
#=> [ <Campaign:..>, ... ]
|
75
|
+
|
76
|
+
#you can pass arguments to find as hash: [GetCampaignParams](http://api.yandex.com/direct/doc/reference/GetCampaignParams.xml)
|
77
|
+
YandexApiDirect::CampaignParams.find
|
78
|
+
#=> [ <CampaignParams:..>, ... ]
|
79
|
+
|
80
|
+
#you can pass arguments to find as hash: [GetSummaryStat](http://api.yandex.com/direct/doc/reference/GetSummaryStat.xml)
|
81
|
+
YandexApiDirect::CampaignStats.find
|
82
|
+
#=> [ <CampaignStats:..>, ... ]
|
83
|
+
```
|
84
|
+
|
85
|
+
### Arguments for methods
|
86
|
+
|
87
|
+
All arguments you will pass into params are automatically camelized, because Yandex API takes only Camelcased attribute names:
|
88
|
+
``` ruby
|
89
|
+
# Example:
|
90
|
+
campaign.campaign_stats start_date: Date.today
|
91
|
+
# will transform inside of method into
|
92
|
+
{ :"StartDate" => Date.today }
|
93
|
+
```
|
94
|
+
If you will implement your own methods, you can use built in method in YandexObject `camelize_keys(hash)`
|
95
|
+
|
96
|
+
### Hierarchy
|
97
|
+
|
98
|
+
Yandex uses this hierarchy and gem follows it
|
99
|
+
* Client
|
100
|
+
* Campaign
|
101
|
+
* CampaignParams
|
102
|
+
* CampaignStats
|
103
|
+
|
104
|
+
``` ruby
|
105
|
+
#get first Client
|
106
|
+
client = Client.find.first
|
107
|
+
|
108
|
+
#get all client campaign
|
109
|
+
campaigns = client.campaigns
|
110
|
+
|
111
|
+
campaign = campaigns.first
|
112
|
+
|
113
|
+
#get campaign statistics
|
114
|
+
campaign.campaign_stats start_date: Date.today-8, end_date: Date.today-1
|
115
|
+
#=> [<CampaingStats:..>, ...]
|
116
|
+
#get campaign params
|
117
|
+
campaign.campaign_params
|
118
|
+
#=> <CampaingParams:... > - not array but directly one object (campaign can have only one params!)
|
119
|
+
```
|
120
|
+
|
121
|
+
### Flexibility
|
122
|
+
|
123
|
+
There is a class YandexApiDirect::Generic which provides class method get
|
124
|
+
has two parameters
|
125
|
+
* method name - underscored
|
126
|
+
* args (optional) - should be hash or array
|
127
|
+
|
128
|
+
``` ruby
|
129
|
+
YandexApiDirect::Generic.get "get_clients_info"
|
130
|
+
#=> will return hash containing client info (Only one item returned)
|
131
|
+
|
132
|
+
YandexApiDirect::Generic.get "get_clients_list"
|
133
|
+
#=> will return array containing hashes of client info (More items returned)
|
134
|
+
```
|
135
|
+
By this you can call all methods without writing more code.
|
136
|
+
|
137
|
+
## Sandbox/Production enviroments
|
138
|
+
|
139
|
+
Yandex api allows you to use sandbox for testing purposes: [Yandex Sandbox](http://api.yandex.com/direct/doc/concepts/sandbox.xml)
|
140
|
+
|
141
|
+
In your test helper write down
|
142
|
+
``` ruby
|
143
|
+
YandexApiDirect.url "sandbox" #or if you like symbols :sandbox :-)
|
144
|
+
#or for directly saying to use production
|
145
|
+
YandexApiDirect.url "production" #or if you like symbols :production :-)
|
146
|
+
```
|
147
|
+
This will set url of Yandex to sandbox or production.
|
148
|
+
If you will not set url it will use ENV['RACK_ENV'] or ENV['RAILS_ENV'] == "test" it will use "sandbox" as default, all other environments (including development) will have sa default setted "production"
|
149
|
+
|
150
|
+
## Contributing to redis-model-extension
|
151
|
+
|
152
|
+
* Check out the latest master to make sure the feature hasn't been implemented or the bug hasn't been fixed yet.
|
153
|
+
* Check out the issue tracker to make sure someone already hasn't requested it and/or contributed it.
|
154
|
+
* Fork the project.
|
155
|
+
* Start a feature/bugfix branch.
|
156
|
+
* Commit and push until you are happy with your contribution.
|
157
|
+
* Make sure to add tests for it. This is important so I don't break it in a future version unintentionally.
|
158
|
+
* Please try not to mess with the Rakefile, version, or history. If you want to have your own version, or is otherwise necessary, that is fine, but please isolate to its own commit so I can cherry-pick around it.
|
159
|
+
|
160
|
+
## Copyright
|
161
|
+
|
162
|
+
Copyright (c) 2012 Ondrej Bartas. See LICENSE.txt for
|
163
|
+
further details.
|
data/Rakefile
ADDED
@@ -0,0 +1,35 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'rubygems'
|
4
|
+
require 'bundler'
|
5
|
+
begin
|
6
|
+
Bundler.setup(:default, :development)
|
7
|
+
rescue Bundler::BundlerError => e
|
8
|
+
$stderr.puts e.message
|
9
|
+
$stderr.puts "Run `bundle install` to install missing gems"
|
10
|
+
exit e.status_code
|
11
|
+
end
|
12
|
+
require 'rake'
|
13
|
+
|
14
|
+
require 'jeweler'
|
15
|
+
Jeweler::Tasks.new do |gem|
|
16
|
+
# gem is a Gem::Specification... see http://docs.rubygems.org/read/chapter/20 for more options
|
17
|
+
gem.name = "yandex-api-direct"
|
18
|
+
gem.homepage = "http://github.com/Ataxo/yandex-api-direct"
|
19
|
+
gem.license = "MIT"
|
20
|
+
gem.summary = %Q{Accessing Yandex Direct API and work with campaigns and statistics}
|
21
|
+
gem.description = %Q{Use JSON api on Yandex api side and automatically manages access token refresh}
|
22
|
+
gem.email = "ondrej@bartas.cz"
|
23
|
+
gem.authors = ["Ondrej Bartas"]
|
24
|
+
# dependencies defined in Gemfile
|
25
|
+
end
|
26
|
+
Jeweler::RubygemsDotOrgTasks.new
|
27
|
+
|
28
|
+
require 'rake/testtask'
|
29
|
+
Rake::TestTask.new(:test) do |test|
|
30
|
+
test.libs << 'lib' << 'test'
|
31
|
+
test.pattern = 'test/**/test_*.rb'
|
32
|
+
test.verbose = true
|
33
|
+
end
|
34
|
+
|
35
|
+
task :default => :test
|
data/VERSION
ADDED
@@ -0,0 +1 @@
|
|
1
|
+
0.0.1
|
@@ -0,0 +1,69 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
|
3
|
+
require 'active_support/inflector'
|
4
|
+
require 'active_support/inflector/inflections'
|
5
|
+
require 'active_support/core_ext/hash/keys'
|
6
|
+
require 'hashr'
|
7
|
+
|
8
|
+
module YandexApiDirect
|
9
|
+
|
10
|
+
URLS = {
|
11
|
+
production: "https://soap.direct.yandex.ru/json-api/v4/", #production url
|
12
|
+
sandbox: "https://api-sandbox.direct.yandex.ru/json-api/v4/" #sandbox url
|
13
|
+
}
|
14
|
+
# Return current environment
|
15
|
+
# Uses RACK_ENV and RAILS_ENV - if not set any default is used "development"
|
16
|
+
def self.env
|
17
|
+
["test"].include?(ENV['RACK_ENV'] || ENV['RAILS_ENV'] || "development") ? :sandbox : :production
|
18
|
+
end
|
19
|
+
|
20
|
+
# Get URL for all requests to Yandex api
|
21
|
+
# * without parameter - Choose url by ENV
|
22
|
+
# * with parameter
|
23
|
+
# * * "test" - choose sandbox
|
24
|
+
# * * other - choose production
|
25
|
+
def self.url environment = nil
|
26
|
+
if environment
|
27
|
+
@url = URLS[environment.to_sym]
|
28
|
+
elsif @url
|
29
|
+
@url
|
30
|
+
else
|
31
|
+
@url = URLS[env]
|
32
|
+
end
|
33
|
+
end
|
34
|
+
|
35
|
+
# default config for Yandex API
|
36
|
+
# * locale (language of api response)
|
37
|
+
# * * "uk" - Ukraine
|
38
|
+
# * * "ru" - Russian
|
39
|
+
# * * "en" - English
|
40
|
+
def self.default_config
|
41
|
+
{
|
42
|
+
locale: "uk",
|
43
|
+
application_id: "",
|
44
|
+
login: "",
|
45
|
+
access_token: "",
|
46
|
+
}
|
47
|
+
end
|
48
|
+
|
49
|
+
@config = default_config
|
50
|
+
|
51
|
+
# Set config values
|
52
|
+
def self.config= conf
|
53
|
+
@config = default_config.merge!(conf)
|
54
|
+
end
|
55
|
+
|
56
|
+
# Get config for requset params build
|
57
|
+
def self.config
|
58
|
+
@config
|
59
|
+
end
|
60
|
+
end
|
61
|
+
|
62
|
+
#require yandex objects
|
63
|
+
require 'yandex-api-direct/yandex_object'
|
64
|
+
require 'yandex-api-direct/yandex_objects/generic'
|
65
|
+
require 'yandex-api-direct/yandex_objects/client'
|
66
|
+
require 'yandex-api-direct/yandex_objects/campaign'
|
67
|
+
require 'yandex-api-direct/yandex_objects/campaign_param'
|
68
|
+
require 'yandex-api-direct/yandex_objects/campaign_stats'
|
69
|
+
|
@@ -0,0 +1,131 @@
|
|
1
|
+
# encoding: utf-8
|
2
|
+
require 'net/http'
|
3
|
+
require 'json'
|
4
|
+
require 'active_support'
|
5
|
+
|
6
|
+
module YandexApiDirect
|
7
|
+
|
8
|
+
# Problem with connection
|
9
|
+
class YandexConnectionError < Exception; end
|
10
|
+
# Problem with request params
|
11
|
+
class YandexMethodError < Exception; end
|
12
|
+
# generic error
|
13
|
+
class YandexError < Exception; end
|
14
|
+
# Problem with authorization
|
15
|
+
class YandexAuthorizationError < Exception; end
|
16
|
+
|
17
|
+
# Globalize all same functions into one module
|
18
|
+
# This will enable easier implementation
|
19
|
+
# of Yandex objects
|
20
|
+
module YandexObject
|
21
|
+
extend ActiveSupport::Concern
|
22
|
+
|
23
|
+
#include methods into class
|
24
|
+
included do
|
25
|
+
include YandexObjectInstance
|
26
|
+
include YandexObjectCallMethod
|
27
|
+
extend YandexObjectCallMethod
|
28
|
+
extend YandexObjectClass
|
29
|
+
end
|
30
|
+
|
31
|
+
# Class methods for Yandex objects
|
32
|
+
module YandexObjectClass
|
33
|
+
|
34
|
+
end
|
35
|
+
|
36
|
+
# Instance methods for Yandex objects
|
37
|
+
module YandexObjectInstance
|
38
|
+
|
39
|
+
# Change Camelized keys of hash to underscored keys
|
40
|
+
def underscore_keys(hash)
|
41
|
+
return nil unless hash
|
42
|
+
hash.inject({}){|result, (key, value)|
|
43
|
+
new_key = key.to_s.underscore.to_sym
|
44
|
+
new_value = case value
|
45
|
+
when Hash then underscore_keys(value)
|
46
|
+
else value
|
47
|
+
end
|
48
|
+
result[new_key] = new_value
|
49
|
+
result
|
50
|
+
}
|
51
|
+
end
|
52
|
+
|
53
|
+
#fix input arguments
|
54
|
+
def initialize args = {}
|
55
|
+
super underscore_keys(args)
|
56
|
+
end
|
57
|
+
end
|
58
|
+
|
59
|
+
# Call method to Yandex API
|
60
|
+
module YandexObjectCallMethod
|
61
|
+
#Call method perform call to yandex api
|
62
|
+
# * method name (string|symbol) - method name defined by yandex api
|
63
|
+
# * param (optional) - params defined by yandex api
|
64
|
+
def call_method method_name, param = nil
|
65
|
+
payload = {
|
66
|
+
method: method_name.camelize,
|
67
|
+
locale: YandexApiDirect.config[:locale],
|
68
|
+
login: YandexApiDirect.config[:login],
|
69
|
+
application_id: YandexApiDirect.config[:application_id],
|
70
|
+
token: YandexApiDirect.config[:access_token],
|
71
|
+
}
|
72
|
+
payload[:param] = param if param
|
73
|
+
|
74
|
+
# get url
|
75
|
+
url = URI.parse(YandexApiDirect.url)
|
76
|
+
|
77
|
+
# set new post request with JSON content type
|
78
|
+
request = Net::HTTP::Post.new(url.path, initheader = {'Content-Type' =>'application/json'})
|
79
|
+
|
80
|
+
# set payload to post body
|
81
|
+
request.body = payload.to_json
|
82
|
+
|
83
|
+
# create new connection to yandex
|
84
|
+
http = Net::HTTP.new(url.host, url.port)
|
85
|
+
|
86
|
+
# set use SSL
|
87
|
+
http.use_ssl = true
|
88
|
+
http.verify_mode = OpenSSL::SSL::VERIFY_NONE
|
89
|
+
|
90
|
+
# send request
|
91
|
+
response = http.request(request)
|
92
|
+
|
93
|
+
# no problem with connection
|
94
|
+
if response.code.to_i == 200
|
95
|
+
#parse respose JSON body into hash
|
96
|
+
resp = JSON.parse(response.body).symbolize_keys
|
97
|
+
|
98
|
+
# if there is no error_code
|
99
|
+
unless resp.has_key?(:error_code)
|
100
|
+
return resp
|
101
|
+
else # error code
|
102
|
+
case resp[:error_code]
|
103
|
+
when 53 then raise YandexAuthorizationError, "Got error from Yandex API, error code: #{resp[:error_code]} | #{resp[:error_str]} (#{resp[:error_detail]})"
|
104
|
+
when 55 then raise YandexMethodError, "Got error from Yandex API, error code: #{resp[:error_code]} | #{resp[:error_str]} (#{resp[:error_detail]})"
|
105
|
+
else raise YandexError, "Got error from Yandex API, error code: #{resp[:error_code]} | #{resp[:error_str]} (#{resp[:error_detail]})"
|
106
|
+
end
|
107
|
+
end
|
108
|
+
else
|
109
|
+
# Request responce is not valid (errors: 404, 500, etc.)
|
110
|
+
raise YandexConnectionError, "Problem with connection to Yandex API, status code: #{response.code} \n content body: #{response.body}"
|
111
|
+
end
|
112
|
+
end
|
113
|
+
|
114
|
+
# Change Camelized keys of hash to camelized keys
|
115
|
+
def camelize_keys(hash)
|
116
|
+
return nil unless hash
|
117
|
+
return hash if hash.is_a?(Array)
|
118
|
+
hash.inject({}){|result, (key, value)|
|
119
|
+
new_key = key.to_s.camelize.gsub(/(Ids|Id|Fio)/) { |r| r.upcase }.to_sym
|
120
|
+
new_value = case value
|
121
|
+
when Hash then camelize_keys(value)
|
122
|
+
else value
|
123
|
+
end
|
124
|
+
result[new_key] = new_value
|
125
|
+
result
|
126
|
+
}
|
127
|
+
end
|
128
|
+
end
|
129
|
+
|
130
|
+
end
|
131
|
+
end
|