yandex-api-direct 0.0.1

Sign up to get free protection for your applications and to get access to all the features.
@@ -0,0 +1,5 @@
1
+ lib/**/*.rb
2
+ bin/*
3
+ -
4
+ features/**/*.feature
5
+ LICENSE.txt
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
@@ -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.
@@ -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.
@@ -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