ya-api-direct 0.2.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: ce703501aca78c8a889a4882c95500b2bb419c30
4
+ data.tar.gz: 2b2be4b799ae9a28908fd44a362635f76e7cd99d
5
+ SHA512:
6
+ metadata.gz: 70218a0c73fc096cbee98e6ad145739338cf52e1f6e94143bb8c263f950a8ac781dcef3fdfff1350c57d2e1bb5642cd0c51c8f1df54331efb6875bb1f728fa02
7
+ data.tar.gz: 7431e2c5e3428697130ad840001c05157813035e4b09465e27ae015f1023ddf5ca069dcbed26e46fec02ccb631ec91757c0f3fd69b6a9412937dc06de6733a63
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2016 Alexander Teut
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.
data/README.md ADDED
@@ -0,0 +1,82 @@
1
+ # ya-api-direct
2
+ A Ruby interface to Yandex Direct API
3
+
4
+ ## Installation
5
+
6
+ Add this line to your application's Gemfile:
7
+
8
+ gem 'ya-api-direct'
9
+
10
+ And then execute:
11
+
12
+ $ bundle
13
+
14
+ Or install it yourself as:
15
+
16
+ $ gem install ya_direct_api
17
+
18
+ Test with rake:
19
+
20
+ $ rake
21
+
22
+ ## Usage
23
+
24
+ OAuth2 Yandex token is needed. Use [omniauth-yandex](https://github.com/evrone/omniauth-yandex/) to receive it. Install it according by following manual: [Rails Authentication with OAuth 2.0 and OmniAuth](https://www.sitepoint.com/rails-authentication-oauth-2-0-omniauth/).
25
+
26
+ Call methods of Yandex Direct API 5:
27
+
28
+ ```ruby
29
+ request = {
30
+ "SelectionCriteria" => {
31
+ "Types" => ["TEXT_CAMPAIGN"]
32
+ },
33
+ "FieldNames" => ["Id", "Name"],
34
+ "TextCampaignFieldNames" => ["BiddingStrategy"]
35
+ }
36
+
37
+ @direct = Ya::API::Direct::Client.new({ token: Token })
38
+ json = direct.campaigns.get request
39
+ ```
40
+
41
+ Call methods from versions 4 and 4 Live:
42
+
43
+ ```ruby
44
+ @direct = Ya::API::Direct::Client.new({ token: Token })
45
+ json = direct.v4.GetCampaignsList []
46
+ ```
47
+
48
+ All names of controllers and methods are equal to ones from Direct API help. 4 vs 4 Live is autodetected.
49
+
50
+ ## Caching
51
+
52
+ By default the client class sends request to clients. You can avoid it by turning this option off, like this:
53
+
54
+
55
+ ```ruby
56
+ @direct = Ya::API::Direct::Client.new({ token: Token, cache: false })
57
+ ```
58
+
59
+ Check [Yandex manuals](https://yandex.ru/adv/edu/direct-api/kak-ispolzovat-api-effektivno-ogranicheniya-i-rekomendatsii) for more info on caching.
60
+
61
+ Date returned with first call of caching method is stored in ``cache_timestamp`` property.
62
+
63
+ ## Units data
64
+
65
+ Units data of last request is stored in ``units_data`` property. There're 3 keys in this hash:
66
+ * ``just_used``
67
+ * ``units_left``
68
+ * ``units_limit``
69
+
70
+ ## Useful links
71
+
72
+ * [Intruduction to Yandex Direct API](https://yandex.ru/adv/edu/direct-api)
73
+ * [Yandex Direct API 5 manual](https://tech.yandex.ru/direct/doc/dg/concepts/about-docpage/)
74
+ * [Yandex Direct API 4 and 4 Live manual](https://tech.yandex.ru/direct/doc/dg-v4/concepts/About-docpage/)
75
+
76
+ ## Contributing
77
+
78
+ 1. Fork it ( http://github.com/rikkimongoose/ya-api-direct/fork )
79
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
80
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
81
+ 4. Push to the branch (`git push origin my-new-feature`)
82
+ 5. Create new Pull Request
@@ -0,0 +1,91 @@
1
+ require "ya/api/direct/constants"
2
+ require "ya/api/direct/gateway"
3
+ require "ya/api/direct/direct_service_v4"
4
+ require "ya/api/direct/direct_service_v5"
5
+ require "ya/api/direct/exception"
6
+
7
+ module Ya::API::Direct
8
+ AllowedAPIVersions = [:v5, :v4]
9
+
10
+ # Yandex Direct API client class
11
+ # @author RikkiMongoose
12
+ class Client
13
+ attr_reader :cache_timestamp, :units_data, :gateway,
14
+ :v4, :v5
15
+
16
+ # Initializes a new Client object
17
+ #
18
+ # @param config [Hash]
19
+ # @return [Ya::API::Direct::Client]
20
+ def initialize(config = {})
21
+ @config = {
22
+ token: nil,
23
+ app_id: nil,
24
+ login: '',
25
+ locale: 'en',
26
+ mode: :sandbox,
27
+ format: :json,
28
+ cache: true,
29
+ api: :v5,
30
+ ssl: true
31
+ }.merge(config)
32
+
33
+ @units_data = {
34
+ just_used: nil,
35
+ units_left: nil,
36
+ units_limit: nil
37
+ }
38
+
39
+ raise "Token can't be empty" if @config[:token].nil?
40
+ raise "Allowed Yandex Direct API versions are #{AllowedVersions}" unless AllowedAPIVersions.include? @config[:api]
41
+
42
+ @gateway = Ya::API::Direct::Gateway.new @config
43
+
44
+ init_v4
45
+ init_v5
46
+ start_cache! if @config[:cache]
47
+ yield self if block_given?
48
+ end
49
+
50
+ # Update units data.
51
+ #
52
+ # @param format [Hash] New units data values
53
+ # @return [Hash] Updated user data values
54
+ def update_units_data(units_data = {})
55
+ @units_data.merge! units_data
56
+ end
57
+
58
+ # Start caching. Executed automatically, if @congif[:cache] is true.
59
+ #
60
+ # @return [String] New timestamp value.
61
+ def start_cache!
62
+ case @config[:api]
63
+ when :v4
64
+ result = @gateway.request("GetChanges", {}, nil, :v4live)
65
+ timestamp = result[:data]['data']['Timestamp']
66
+ when :v5
67
+ result = @gateway.request("checkDictionaries", {}, "changes", :v5)
68
+ timestamp = result[:data]['result']['Timestamp']
69
+ end
70
+ @cache_timestamp = Time.parse(timestamp)
71
+ update_units_data result[:units_data]
72
+ @cache_timestamp
73
+ end
74
+
75
+ private
76
+
77
+ def init_v4
78
+ @v4 = DirectServiceV4.new self, (API_V4 + API_V4_LIVE)
79
+ end
80
+
81
+ def init_v5
82
+ @v5 = {}
83
+ API_V5.each do |service, methods|
84
+ service_item = DirectServiceV5.new(self, service, methods)
85
+ service_key = service_item.service_url
86
+ @v5[service_key] = service_item
87
+ self.class.send :define_method, service_key do @v5[service_key] end
88
+ end
89
+ end
90
+ end
91
+ end
@@ -0,0 +1,136 @@
1
+ module Ya
2
+ module API
3
+ module Direct
4
+ API_V5 = {
5
+ "Campaigns" => [
6
+ "add", "update", "delete", "suspend", "resume", "archive", "unarchive", "get"
7
+ ],
8
+ "AdGroups" => [
9
+ "add", "update", "delete", "get"
10
+ ],
11
+ "Ads" => [
12
+ "add", "update", "delete", "suspend", "resume", "archive", "unarchive", "moderate", "get"
13
+ ],
14
+ "Bids" => [
15
+ "set", "setAuto", "get"
16
+ ],
17
+ "BidModifiers" => [
18
+ "add", "delete", "get", "set", "toggle"
19
+ ],
20
+ "Campaigns" => [
21
+ "add", "update", "delete", "suspend", "resume", "archive", "unarchive", "get"
22
+ ],
23
+ "Changes" => [
24
+ "checkDictionaries", "checkCampaigns", "check"
25
+ ],
26
+ "Dictionaries" => [
27
+ "get"
28
+ ],
29
+ "DynamicTextAdTargets" => [
30
+ "add", "delete", "suspend", "resume", "get", "setBids"
31
+ ],
32
+ "Keywords" => [
33
+ "add", "update", "delete", "suspend", "resume", "get"
34
+ ],
35
+ "Sitelinks" => [
36
+ "add", "get", "delete"
37
+ ],
38
+ "VCards" => [
39
+ "add", "get", "delete"
40
+ ]
41
+ }
42
+
43
+ API_V4 = [
44
+ "GetBalance",
45
+ "GetSummaryStat",
46
+ "CreateNewReport",
47
+ "DeleteReport",
48
+ "GetReportList",
49
+
50
+ "CreateNewWordstatReport",
51
+ "DeleteWordstatReport",
52
+ "GetWordstatReport",
53
+ "GetWordstatReportList",
54
+
55
+ "GetKeywordsSuggestion",
56
+
57
+ "CreateNewForecast",
58
+ "DeleteForecastReport",
59
+ "GetForecast",
60
+ "GetForecastList",
61
+
62
+ "CreateInvoice",
63
+ "TransferMoney",
64
+ "GetCreditLimits",
65
+ "PayCampaigns",
66
+
67
+ "GetClientsUnits",
68
+ "GetSubClients",
69
+ "GetClientInfo",
70
+ "UpdateClientInfo",
71
+
72
+ "CreateNewSubclient",
73
+ "GetClientsList",
74
+
75
+ "GetRegions",
76
+ "GetRubrics",
77
+ "GetTimeZones",
78
+ "GetStatGoals",
79
+
80
+ "GetAvailableVersions",
81
+ "GetVersion",
82
+ "PingAPI",
83
+ ]
84
+
85
+
86
+ API_V4_LIVE = [
87
+ "CreateOrUpdateCampaign",
88
+ "GetCampaignsList",
89
+ "GetCampaignsListFilter",
90
+ "GetCampaignsParams",
91
+ "DeleteCampaign",
92
+
93
+ "CreateOrUpdateBanners",
94
+ "GetBanners",
95
+ "GetBannerPhrases",
96
+ "GetBannerPhrasesFilter",
97
+ "DeleteBanners",
98
+ "Keyword",
99
+
100
+ "ModerateBanners",
101
+ "ResumeBanners",
102
+ "StopBanners",
103
+ "ArchiveBanners",
104
+ "UnArchiveBanners",
105
+
106
+ "SetAutoPrice",
107
+ "UpdatePrices",
108
+
109
+ "GetBannersStat",
110
+
111
+ "ResumeCampaign",
112
+ "StopCampaign",
113
+ "ArchiveCampaign",
114
+ "UnArchiveCampaign",
115
+
116
+ "GetBannersTags",
117
+ "UpdateBannersTags",
118
+ "GetCampaignsTags",
119
+ "UpdateCampaignsTags",
120
+
121
+ "AdImage",
122
+ "AdImageAssociation",
123
+
124
+ "GetRetargetingGoals",
125
+ "RetargetingCondition",
126
+ "Retargeting",
127
+
128
+ "EnableSharedAccount",
129
+ "AccountManagement",
130
+
131
+ "GetChanges",
132
+ "GetEventsLog",
133
+ ]
134
+ end
135
+ end
136
+ end
@@ -0,0 +1,28 @@
1
+ require "ya/api/direct/constants"
2
+
3
+ module Ya::API::Direct
4
+ class DirectServiceBase
5
+ attr_reader :method_items, :version
6
+ def initialize(client, methods)
7
+ @client = client
8
+ @method_items = methods
9
+ init_methods
10
+ end
11
+
12
+ protected
13
+
14
+ def exec_request(method, request_body)
15
+ client.gateway.request method, request_body, @version
16
+ end
17
+
18
+ def init_methods
19
+ @method_items.each do |method|
20
+ self.class.send :define_method, method do |params = {}|
21
+ result = exec_request(method, params || {})
22
+ @client.update_units_data result[:units_data]
23
+ result[:data]
24
+ end
25
+ end
26
+ end
27
+ end
28
+ end
@@ -0,0 +1,16 @@
1
+ require "ya/api/direct/constants"
2
+ require "ya/api/direct/direct_service_base"
3
+
4
+ module Ya::API::Direct
5
+ class DirectServiceV4 < DirectServiceBase
6
+
7
+ def initialize(client, methods, version = :v4)
8
+ super(client, methods)
9
+ @version = version
10
+ end
11
+
12
+ def exec_request(method, request_body = {})
13
+ @client.gateway.request method, request_body, nil, (API_V4_LIVE.include?(method) ? :v4live : @version)
14
+ end
15
+ end
16
+ end
@@ -0,0 +1,19 @@
1
+ require "ya/api/direct/constants"
2
+ require "ya/api/direct/direct_service_base"
3
+
4
+ module Ya::API::Direct
5
+ class DirectServiceV5 < DirectServiceBase
6
+ attr_reader :service, :service_url
7
+
8
+ def initialize(client, service, methods)
9
+ super(client, methods)
10
+ @service = service
11
+ @service_url = service.downcase
12
+ @version = :v5
13
+ end
14
+
15
+ def exec_request(method, request_body={})
16
+ @client.gateway.request method, request_body, @service_url, @version
17
+ end
18
+ end
19
+ end
@@ -0,0 +1,17 @@
1
+ require "ya/api/direct/constants"
2
+
3
+ module Ya::API::Direct
4
+ class Exception < StandardError
5
+ attr_reader :error_detail, :error_code, :error_str
6
+
7
+ def initialize(error_detail, error_str, error_code)
8
+ @error_detail = error_detail
9
+ @error_str = error_str
10
+ @error_code = error_code
11
+ end
12
+
13
+ def to_s
14
+ "#{@error_str} : #{@error_detail} : #{@error_code}"
15
+ end
16
+ end
17
+ end
@@ -0,0 +1,59 @@
1
+ require "net/http"
2
+ require "openssl"
3
+ require "json"
4
+
5
+ require "ya/api/direct/constants"
6
+ require "ya/api/direct/url_helper"
7
+
8
+ module Ya::API::Direct
9
+ class Gateway
10
+ attr_reader :config
11
+ def initialize(config)
12
+ @config = config
13
+ end
14
+
15
+ def request(method, params, service = "", version = nil)
16
+ ver = version || (service.nil? ? :v4 : :v5)
17
+ url = UrlHelper.direct_api_url @config[:mode], ver, service
18
+ header = generate_header ver
19
+ body = generate_body method, params, ver
20
+ uri = URI.parse url
21
+ request = Net::HTTP::Post.new(uri.path, initheader = header)
22
+ request.body = body.to_json
23
+ http = Net::HTTP.new(uri.host, uri.port)
24
+ http.use_ssl = true
25
+ http.verify_mode = @config[:ssl] ? OpenSSL::SSL::VERIFY_PEER : OpenSSL::SSL::VERIFY_NONE
26
+ response = http.request(request)
27
+ if response.kind_of? Net::HTTPSuccess
28
+ UrlHelper.parse_data response
29
+ else
30
+ raise response.inspect
31
+ end
32
+ end
33
+
34
+ def generate_header(ver)
35
+ header = {}
36
+ if ver == :v5
37
+ header.merge!({
38
+ 'Client-Login' => @config[:login],
39
+ 'Accept-Language' => @config[:locale],
40
+ 'Authorization' => "Bearer %{token}" % @config
41
+ })
42
+ end
43
+ end
44
+
45
+ def generate_body(method, params, ver)
46
+ body = {
47
+ "method" => method,
48
+ "params" => params
49
+ }
50
+ if [:v4, :v4live].include? ver
51
+ body.merge!({
52
+ "locale" => @config[:locale],
53
+ "token" => @config[:token]
54
+ })
55
+ end
56
+ body
57
+ end
58
+ end
59
+ end
@@ -0,0 +1,82 @@
1
+ require "json"
2
+
3
+ require "ya/api/direct/constants"
4
+ require "ya/api/direct/exception"
5
+
6
+ module Ya::API::Direct
7
+ RegExUnits = Regexp.new /(\d+)\/(\d+)\/(\d+)/
8
+ # Static class with helping functions for url formatting.
9
+ #
10
+ # @author Rikki Mongoose
11
+ class UrlHelper
12
+ # Generate Yandex Direct API url for a call
13
+ #
14
+ # @param mode [Symbol] Direct API mode, `:sandbox` or `:production`
15
+ # @param mode [Symbol] Direct API version, `:v5` or `:v4` or `:v4live`
16
+ # @param mode [Symbol] Direct API service to use
17
+ # @return [String] Generated Yandex Direct API URL
18
+ def self.direct_api_url(mode = :sandbox, version = :v5, service = "")
19
+ format = :json
20
+ protocol = "https"
21
+ api_prefixes = {
22
+ sandbox: "api-sandbox",
23
+ production: "api"
24
+ }
25
+ api_prefix = api_prefixes[mode || :sandbox]
26
+ site = "%{api}.direct.yandex.ru" % {api: api_prefix}
27
+ api_urls = {
28
+ v4: {
29
+ json: '%{protocol}://%{site}/v4/json',
30
+ soap: '%{protocol}://%{site}/v4/soap',
31
+ wsdl: '%{protocol}://%{site}/v4/wsdl',
32
+ },
33
+ v4live: {
34
+ json: '%{protocol}://%{site}/live/v4/json',
35
+ soap: '%{protocol}://%{site}/live/v4/soap',
36
+ wsdl: '%{protocol}://%{site}/live/v4/wsdl',
37
+ },
38
+ v5: {
39
+ json: '%{protocol}://%{site}/json/v5/%{service}',
40
+ soap: '%{protocol}://%{site}/v5/%{service}',
41
+ wsdl: '%{protocol}://%{site}/v5/%{service}?wsdl',
42
+ }
43
+ }
44
+ api_urls[version][format] % {
45
+ protocol: protocol,
46
+ site: site,
47
+ service: service
48
+ }
49
+ end
50
+
51
+ # Extract Yandex Direct API units values from responce HTTP header
52
+ #
53
+ # @param responce_header [Hash] Yandex Direct API response header
54
+ # @return [Hash] Units data, extracted from header
55
+ def self.extract_response_units(response_header)
56
+ matched = RegExUnits.match response_header["Units"]
57
+ {
58
+ just_used: matched[1].to_i,
59
+ units_left: matched[2].to_i,
60
+ units_limit: matched[3].to_i
61
+ }
62
+ end
63
+
64
+ private
65
+
66
+ def self.parse_data(response)
67
+ response_body = JSON.parse(response.body)
68
+ validate_response! response_body
69
+ {
70
+ data: response_body,
71
+ units_data: self.extract_response_units(response)
72
+ }
73
+ end
74
+
75
+ def self.validate_response!(response_body)
76
+ if response_body.has_key? 'error'
77
+ response_error = response_body['error']
78
+ raise Exception.new(response_error['error_detail'], response_error['error_string'], response_error['error_code'])
79
+ end
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,49 @@
1
+ module Ya
2
+ module API
3
+ module Direct
4
+ module Version
5
+ module_function
6
+
7
+ # @return [Integer]
8
+ def major
9
+ 0
10
+ end
11
+
12
+ # @return [Integer]
13
+ def minor
14
+ 2
15
+ end
16
+
17
+ # @return [Integer]
18
+ def patch
19
+ 0
20
+ end
21
+
22
+ # @return [Integer, NilClass]
23
+ def pre
24
+ nil
25
+ end
26
+
27
+ # @return [Hash]
28
+ def to_h
29
+ {
30
+ major: major,
31
+ minor: minor,
32
+ patch: patch,
33
+ pre: pre,
34
+ }
35
+ end
36
+
37
+ # @return [Array]
38
+ def to_a
39
+ [major, minor, patch, pre].compact
40
+ end
41
+
42
+ # @return [String]
43
+ def to_s
44
+ to_a.join('.')
45
+ end
46
+ end
47
+ end
48
+ end
49
+ end
@@ -0,0 +1,18 @@
1
+ # coding: utf-8
2
+ $:.push File.expand_path("../lib", __FILE__)
3
+
4
+ require 'ya/api/direct/version'
5
+
6
+ Gem::Specification.new do |s|
7
+ s.name = 'ya-api-direct'
8
+ s.version = '0.0.1'
9
+ s.date = '2016-09-05'
10
+ s.summary = "Yandex Direct API v5"
11
+ s.description = "Ruby implementation for Yandex Direct API of versions 5, 4 and 4 Live"
12
+ s.authors = %w("Alexander Teut")
13
+ s.email = 'alexander.a.teut@gmail.com'
14
+ s.files = %w(LICENSE README.md ya-api-direct.gemspec) + Dir['lib/ya/api/direct/*.rb']
15
+ s.homepage = 'http://rubygems.org/gems/ya-api-direct'
16
+ s.license = 'MIT'
17
+ s.version = Ya::API::Direct::Version
18
+ end
metadata ADDED
@@ -0,0 +1,56 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: ya-api-direct
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.2.0
5
+ platform: ruby
6
+ authors:
7
+ - '"Alexander'
8
+ - Teut"
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2016-09-05 00:00:00.000000000 Z
13
+ dependencies: []
14
+ description: Ruby implementation for Yandex Direct API of versions 5, 4 and 4 Live
15
+ email: alexander.a.teut@gmail.com
16
+ executables: []
17
+ extensions: []
18
+ extra_rdoc_files: []
19
+ files:
20
+ - LICENSE
21
+ - README.md
22
+ - ya-api-direct.gemspec
23
+ - lib/ya/api/direct/client.rb
24
+ - lib/ya/api/direct/constants.rb
25
+ - lib/ya/api/direct/direct_service_base.rb
26
+ - lib/ya/api/direct/direct_service_v4.rb
27
+ - lib/ya/api/direct/direct_service_v5.rb
28
+ - lib/ya/api/direct/exception.rb
29
+ - lib/ya/api/direct/gateway.rb
30
+ - lib/ya/api/direct/url_helper.rb
31
+ - lib/ya/api/direct/version.rb
32
+ homepage: http://rubygems.org/gems/ya-api-direct
33
+ licenses:
34
+ - MIT
35
+ metadata: {}
36
+ post_install_message:
37
+ rdoc_options: []
38
+ require_paths:
39
+ - lib
40
+ required_ruby_version: !ruby/object:Gem::Requirement
41
+ requirements:
42
+ - - '>='
43
+ - !ruby/object:Gem::Version
44
+ version: '0'
45
+ required_rubygems_version: !ruby/object:Gem::Requirement
46
+ requirements:
47
+ - - '>='
48
+ - !ruby/object:Gem::Version
49
+ version: '0'
50
+ requirements: []
51
+ rubyforge_project:
52
+ rubygems_version: 2.0.14.1
53
+ signing_key:
54
+ specification_version: 4
55
+ summary: Yandex Direct API v5
56
+ test_files: []