bing_ads_api_v9 0.0.6

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.
Files changed (56) hide show
  1. checksums.yaml +7 -0
  2. data/README.md +74 -0
  3. data/lib/ads_common_for_bing_ads.rb +47 -0
  4. data/lib/ads_common_for_bing_ads/api_config.rb +41 -0
  5. data/lib/ads_common_for_bing_ads/auth/client_login_handler.rb +161 -0
  6. data/lib/ads_common_for_bing_ads/auth/oauth2_handler.rb +33 -0
  7. data/lib/ads_common_for_bing_ads/build/savon_generator.rb +23 -0
  8. data/lib/ads_common_for_bing_ads/build/savon_registry.rb +17 -0
  9. data/lib/ads_common_for_bing_ads/parameters_validator.rb +36 -0
  10. data/lib/ads_common_for_bing_ads/savon_headers/base_header_handler.rb +13 -0
  11. data/lib/ads_common_for_bing_ads/savon_headers/client_login_header_handler.rb +24 -0
  12. data/lib/ads_common_for_bing_ads/savon_headers/oauth_header_handler.rb +31 -0
  13. data/lib/ads_common_for_bing_ads/savon_headers_base_header_handler.rb +9 -0
  14. data/lib/ads_common_for_bing_ads/savon_service.rb +143 -0
  15. data/lib/bing_ads_api.rb +215 -0
  16. data/lib/bing_ads_api/api_config.rb +164 -0
  17. data/lib/bing_ads_api/client_login_header_handler.rb +21 -0
  18. data/lib/bing_ads_api/credential_handler.rb +91 -0
  19. data/lib/bing_ads_api/errors.rb +564 -0
  20. data/lib/bing_ads_api/report_header_handler.rb +46 -0
  21. data/lib/bing_ads_api/report_utils.rb +202 -0
  22. data/lib/bing_ads_api/v8/ad_intelligence_service.rb +86 -0
  23. data/lib/bing_ads_api/v8/ad_intelligence_service_registry.rb +30 -0
  24. data/lib/bing_ads_api/v8/administration_service.rb +38 -0
  25. data/lib/bing_ads_api/v8/administration_service_registry.rb +30 -0
  26. data/lib/bing_ads_api/v8/bulk_service.rb +42 -0
  27. data/lib/bing_ads_api/v8/bulk_service_registry.rb +30 -0
  28. data/lib/bing_ads_api/v8/campaign_management_service.rb +390 -0
  29. data/lib/bing_ads_api/v8/campaign_management_service_registry.rb +30 -0
  30. data/lib/bing_ads_api/v8/customer_billing_service.rb +62 -0
  31. data/lib/bing_ads_api/v8/customer_billing_service_registry.rb +30 -0
  32. data/lib/bing_ads_api/v8/customer_management_service.rb +162 -0
  33. data/lib/bing_ads_api/v8/customer_management_service_registry.rb +30 -0
  34. data/lib/bing_ads_api/v8/notification_service.rb +38 -0
  35. data/lib/bing_ads_api/v8/notification_service_registry.rb +30 -0
  36. data/lib/bing_ads_api/v8/optimizer_service.rb +46 -0
  37. data/lib/bing_ads_api/v8/optimizer_service_registry.rb +30 -0
  38. data/lib/bing_ads_api/v8/reporting_service.rb +38 -0
  39. data/lib/bing_ads_api/v8/reporting_service_registry.rb +30 -0
  40. data/lib/bing_ads_api/v9/ad_intelligence_service.rb +86 -0
  41. data/lib/bing_ads_api/v9/ad_intelligence_service_registry.rb +30 -0
  42. data/lib/bing_ads_api/v9/bulk_service.rb +58 -0
  43. data/lib/bing_ads_api/v9/bulk_service_registry.rb +30 -0
  44. data/lib/bing_ads_api/v9/campaign_management_service.rb +298 -0
  45. data/lib/bing_ads_api/v9/campaign_management_service_registry.rb +30 -0
  46. data/lib/bing_ads_api/v9/customer_billing_service.rb +66 -0
  47. data/lib/bing_ads_api/v9/customer_billing_service_registry.rb +30 -0
  48. data/lib/bing_ads_api/v9/customer_management_service.rb +154 -0
  49. data/lib/bing_ads_api/v9/customer_management_service_registry.rb +30 -0
  50. data/lib/bing_ads_api/v9/optimizer_service.rb +62 -0
  51. data/lib/bing_ads_api/v9/optimizer_service_registry.rb +30 -0
  52. data/lib/bing_ads_api/v9/reporting_service.rb +38 -0
  53. data/lib/bing_ads_api/v9/reporting_service_registry.rb +30 -0
  54. data/lib/bing_ads_api/version.rb +5 -0
  55. data/rakefile.rb +54 -0
  56. metadata +168 -0
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 9b3aed5be42fde099fa6a30ce66e69835ed547c6
4
+ data.tar.gz: fc5b869aff5c3da8d8d319433cd56c0cff41b9a8
5
+ SHA512:
6
+ metadata.gz: c2a05c573391798cd031e405a4f9762db6cc8f823b29a9b79978b7aa70da15566f8d917797755685a88abbd52f47feda71e118a8edd94cea330051ce83fd6b9d
7
+ data.tar.gz: 18e4da0cfe5b37162539deddb1784d5e35ba49573ed8541649fb18b8e6704320dc3e24175f32d791dc810a6eed63eb524555ada0315107a86cb01070390fcd27
@@ -0,0 +1,74 @@
1
+ Bing Ads Api Client
2
+ =============
3
+
4
+ Description
5
+ -------------
6
+ A simple ruby wrapper for the Bing Ads API based on the gem "google-ads-common".
7
+
8
+ Usage
9
+ -------------
10
+
11
+ # install in your gem file
12
+ gem 'bing_ads_api', :git => 'https://github.com/arambert/bing_ads_api.git'
13
+
14
+ # initialize the client
15
+ client = BingAdsApi::Api.new(
16
+ {
17
+ :authentication => {
18
+ :method => 'ClientLogin',
19
+ :developer_token => 'DEVELOPER_TOKEN',
20
+ :user_name => 'USERNAME',
21
+ :password => 'PASSWORD',
22
+ :customer_id => 'customer_id', # may be optional for some requests
23
+ :customer_account_id => 'customer_account_id' # may be optional for some requests
24
+ },
25
+ :service => {:environment => 'PRODUCTION'},
26
+ :library => {:log_level => 'DEBUG'}
27
+ })
28
+
29
+ oauth2_client = BingAdsApi::Api.new(
30
+ {
31
+ :authentication => {
32
+ :method => 'OAUTH2',
33
+ :developer_token => Developer Token,
34
+ :oauth2_client_id: Client Id From Bing,
35
+ :oauth2_client_secret: Secret Client From Bing,
36
+ :oauth2_callback: http://myservice.com/adcenter_oauth2, #public callback
37
+ :oauth2_token => {
38
+ :access_token => Access Token,
39
+ :refresh_token => Refresh Token
40
+ }
41
+ },
42
+ :service => {:environment => 'PRODUCTION'},
43
+ :library => {:log_level => 'DEBUG'}
44
+ })
45
+
46
+ # select the service and the API version (:v8 or :v9)
47
+ administration_service = client.service(:AdministrationService, :v9)
48
+
49
+ # send your request
50
+ result = administration_service.get_assigned_quota()
51
+
52
+ # select another service
53
+ campaign_service = client.service(:CampaignManagementService, :v9)
54
+
55
+ # send another request
56
+ result = campaign_service.get_campaigns_by_account_id({:account_id => 00000})
57
+
58
+ # create a campaign
59
+ result2 = campaign_service.add_campaigns({:account_id => 00000,
60
+ :campaigns => {:campaign => [{:budget_type => "DailyBudgetWithMaximumMonthlySpend",
61
+ :conversion_tracking_enabled => false,
62
+ :daily_budget => 5,
63
+ :daylight_saving => false,
64
+ :description => "A perfect new campaign",
65
+ :monthly_budget => 50,
66
+ :name => "perfectcampaign",
67
+ :time_zone => "BrusselsCopenhagenMadridParis"}]
68
+ }
69
+ })
70
+
71
+ About the gem
72
+ -------------
73
+ The tests still have to be written.
74
+ Any help is welcome !
@@ -0,0 +1,47 @@
1
+ require 'ads_common/api'
2
+ require 'ads_common/api_config'
3
+ require 'ads_common/credential_handler'
4
+ require 'ads_common/errors'
5
+ require 'ads_common/http'
6
+ require 'ads_common/savon_service'
7
+ require 'ads_common/parameters_validator'
8
+ require 'ads_common/build/savon_generator'
9
+ require 'ads_common/build/savon_registry'
10
+ require 'ads_common/savon_headers/base_header_handler'
11
+ require 'ads_common/savon_headers/oauth_header_handler'
12
+
13
+ ####### AdsCommon Overriden for Bing Ads #########
14
+ module AdsCommonForBingAds
15
+ class Api < AdsCommon::Api; end
16
+ module ApiConfig; include AdsCommon::ApiConfig; end
17
+ class Config < AdsCommon::Config; end
18
+ class CredentialHandler < AdsCommon::CredentialHandler; end
19
+ module Errors; include AdsCommon::Errors; end
20
+ class Http < AdsCommon::Http; end
21
+ class ParametersValidator < AdsCommon::ParametersValidator; end
22
+ class ResultsExtractor < AdsCommon::ResultsExtractor; end
23
+ class SavonService < AdsCommon::SavonService; end
24
+ module Utils; include AdsCommon::Utils; end
25
+ module ApiConfig; include AdsCommon::ApiConfig; end
26
+ # Auth
27
+ module Auth
28
+ class BaseHandler < AdsCommon::Auth::BaseHandler; end
29
+ class ClientLoginHandler < AdsCommon::Auth::ClientLoginHandler; end
30
+ class OAuth2Handler < AdsCommon::Auth::OAuth2Handler; end
31
+ end
32
+ # Build
33
+ module Build
34
+ class SavonAbstractGenerator < AdsCommon::Build::SavonAbstractGenerator; end
35
+ class SavonGenerator < AdsCommon::Build::SavonGenerator; end
36
+ class SavonRegistry < AdsCommon::Build::SavonRegistry; end
37
+ class SavonRegistryGenerator < AdsCommon::Build::SavonRegistryGenerator; end
38
+ class SavonServiceGenerator < AdsCommon::Build::SavonServiceGenerator; end
39
+ end
40
+ # SavonHeaders
41
+ module SavonHeaders
42
+ class BaseHeaderHandler < AdsCommon::SavonHeaders::BaseHeaderHandler; end
43
+ class OAuthHeaderHandler < AdsCommon::SavonHeaders::OAuthHeaderHandler; end
44
+ # httpi_request_proxy is ::OAuth::RequestProxy::HTTPIRequest < OAuth::RequestProxy::Base
45
+ end
46
+
47
+ end
@@ -0,0 +1,41 @@
1
+ ####### Overriden for Bing Ads #########
2
+ AdsCommonForBingAds::ApiConfig.module_eval do
3
+ # Get the endpoint for a service on a given environment and API version.
4
+ #
5
+ # Args:
6
+ # - environment: the service environment to be used
7
+ # - version: the API version
8
+ # - service: the name of the API service
9
+ #
10
+ # Returns:
11
+ # The endpoint URL
12
+ #
13
+ def endpoint(environment, version, service)
14
+ if !address_config().nil?
15
+ address_config()[version][service][environment].to_s
16
+ else
17
+ ""
18
+ end
19
+ end
20
+ # Generates an array of WSDL URLs based on defined Services and version
21
+ # supplied. This method is used by generators to determine what service
22
+ # wrappers to generate.
23
+ #
24
+ # Args:
25
+ # - version: the API version.
26
+ #
27
+ # Returns
28
+ # hash of pairs Service => WSDL URL
29
+ #
30
+ def get_wsdls(version)
31
+ res = {}
32
+ services(version).each do |service|
33
+ if (!address_config().nil?)
34
+ path = address_config()[version][service][default_environment()].to_s
35
+ end
36
+ res[service.to_s] = path || ""
37
+ end
38
+ return res
39
+ end
40
+
41
+ end
@@ -0,0 +1,161 @@
1
+ ####### Overriden for Bing Ads #########
2
+ module AdsCommonForBingAds
3
+ module Auth
4
+
5
+ class ClientLoginHandler
6
+
7
+
8
+ # Invalidates the stored token if the user_name, password or provided auth
9
+ # token have changed.
10
+ def property_changed(prop, value)
11
+ if [:user_name, :password].include?(prop)
12
+ @token = nil
13
+ end
14
+ if :auth_token.eql?(prop)
15
+ @token = create_token_from_string(value)
16
+ end
17
+ end
18
+
19
+ # Handle specific ClientLogin errors.
20
+ def handle_error(error)
21
+ # TODO: Add support for automatically regenerating auth tokens when they
22
+ # expire.
23
+ get_logger().error(error)
24
+ raise error
25
+ end
26
+
27
+ # Returns authorization string.
28
+ def auth_string(credentials, request)
29
+ return [AUTH_PREFIX, get_token(credentials)].join
30
+ end
31
+
32
+ private
33
+
34
+ # Auxiliary method to validate the credentials for token generation.
35
+ #
36
+ # Args:
37
+ # - credentials: a hash with the credentials for the account being
38
+ # accessed
39
+ #
40
+ # Raises:
41
+ # - AdsCommonForBingAds::Errors::AuthError if validation fails
42
+ #
43
+ def validate_credentials(credentials)
44
+ if credentials.nil?
45
+ raise AdsCommonForBingAds::Errors::AuthError, 'No credentials supplied.'
46
+ end
47
+
48
+ if credentials[:auth_token].nil?
49
+ if credentials[:user_name].nil?
50
+ raise AdsCommonForBingAds::Errors::AuthError,
51
+ 'UserName address not included in credentials.'
52
+ end
53
+ if credentials[:password].nil?
54
+ raise AdsCommonForBingAds::Errors::AuthError,
55
+ 'Password not included in credentials.'
56
+ end
57
+ else
58
+ if credentials[:user_name] and credentials[:password]
59
+ get_logger().warn('Both auth_token and login credentials present' +
60
+ ', preferring auth_token.')
61
+ end
62
+ end
63
+ end
64
+
65
+ # Auxiliary method to generate an authentication token for login in via
66
+ # the ClientLogin API.
67
+ #
68
+ # Args:
69
+ # - credentials: a hash with the credentials for the account being
70
+ # accessed
71
+ #
72
+ # Returns:
73
+ # - The auth token for the account
74
+ #
75
+ # Raises:
76
+ # - AdsCommonForBingAds::Errors::AuthError if authentication fails
77
+ #
78
+ def create_token(credentials)
79
+ token = credentials.include?(:auth_token) ?
80
+ create_token_from_string(credentials[:auth_token]) :
81
+ generate_token(credentials)
82
+ return token
83
+ end
84
+
85
+ # Creates token for provided auth string. Trivial for this handler.
86
+ def create_token_from_string(token_string)
87
+ return token_string
88
+ end
89
+
90
+ # Prepares POST data for ClientLogin request.
91
+ def get_login_data(credentials)
92
+ user_name = CGI.escape(credentials[:user_name])
93
+ password = CGI.escape(credentials[:password])
94
+ service_name = @service_name
95
+ data = "accountType=%s&Email=%s&Passwd=%s&service=%s" %
96
+ [ACCOUNT_TYPE, user_name, password, service_name]
97
+ if credentials[:logintoken] and credentials[:logincaptcha]
98
+ data += "&logintoken=%s&logincaptcha=%s" %
99
+ [CGI.escape(credentials[:logintoken]),
100
+ CGI.escape(credentials[:logincaptcha])]
101
+ end
102
+ return data
103
+ end
104
+
105
+ # Generates new client login token based on credentials.
106
+ def generate_token(credentials)
107
+ validate_credentials(credentials)
108
+
109
+ url = @server + AUTH_PATH
110
+ data = get_login_data(credentials)
111
+ headers = {'Content-Type' => 'application/x-www-form-urlencoded'}
112
+
113
+ response = AdsCommonForBingAds::Http.post_response(url, data, @config, headers)
114
+ results = parse_token_text(response.body)
115
+
116
+ if response.code == 200 and results.include?('Auth')
117
+ return results['Auth']
118
+ else
119
+ handle_login_error(credentials, response, results)
120
+ end
121
+ end
122
+
123
+ # Raises relevant error based on response and parsed results.
124
+ def handle_login_error(credentials, response, results)
125
+ # Handling for known errors.
126
+ if 'CaptchaRequired'.eql?(results['Error'])
127
+ captcha_url = @server + CAPTCHA_PATH + results['CaptchaUrl']
128
+ raise AdsCommonForBingAds::Errors::CaptchaRequiredError.new(results['Error'],
129
+ results['CaptchaToken'], captcha_url, results['Url'])
130
+ end
131
+ # For other errors throwing a generic error.
132
+ error_message = "ClientLogin failed for user_name '%s': HTTP code %d." %
133
+ [credentials[:user_name], response.code]
134
+ error_str = results['Error'] || response.body
135
+ error_message += " Error: %s." % error_str if error_str
136
+ if results.include?('Info')
137
+ error_message += " Info: %s." % results['Info']
138
+ end
139
+ raise AdsCommonForBingAds::Errors::AuthError.new(error_message, error_str,
140
+ results['Info'])
141
+ end
142
+
143
+ # Extracts key-value pairs from ClientLogin server response.
144
+ #
145
+ # Args:
146
+ # - text: server response string
147
+ #
148
+ # Returns:
149
+ # Hash of key-value pairs
150
+ #
151
+ def parse_token_text(text)
152
+ return text.split("\n").inject({}) do |result, line|
153
+ key, *values = line.split('=')
154
+ result[key] = values.join('=')
155
+ result
156
+ end
157
+ end
158
+
159
+ end
160
+ end
161
+ end
@@ -0,0 +1,33 @@
1
+ ####### Overriden for Bing Ads #########
2
+ module AdsCommonForBingAds
3
+ module Auth
4
+
5
+ class OAuth2Handler
6
+
7
+ OAUTH2_CONFIG_BING = {
8
+ :authorization_uri =>
9
+ 'https://login.live.com/oauth20_authorize.srf',
10
+ :token_credential_uri =>
11
+ 'https://login.live.com/oauth20_token.srf'
12
+ }
13
+
14
+ def auth_string(credentials)
15
+ token = get_token(credentials)
16
+ token[:access_token]
17
+ end
18
+
19
+ private
20
+
21
+ def create_client(credentials)
22
+ oauth_options_bing = OAUTH2_CONFIG_BING.merge({
23
+ :client_id => credentials[:oauth2_client_id],
24
+ :client_secret => credentials[:oauth2_client_secret],
25
+ :scope => @scope,
26
+ :redirect_uri => credentials[:oauth2_callback] || DEFAULT_CALLBACK,
27
+ :state => credentials[:oauth2_state]
28
+ }).reject {|k, v| v.nil?}
29
+ return Signet::OAuth2::Client.new(oauth_options_bing)
30
+ end
31
+ end
32
+ end
33
+ end
@@ -0,0 +1,23 @@
1
+ module AdsCommonForBingAds
2
+ module Build
3
+
4
+ class SavonGenerator
5
+
6
+ private
7
+
8
+ # Generates registry file.
9
+ def write_registry(wsdl, file_name)
10
+ registry_file = create_new_file(file_name)
11
+ generator = SavonRegistryGenerator.new(@generator_args)
12
+ registry = SavonRegistry.new(wsdl, @generator_args)
13
+ generator.add_exceptions(registry.soap_exceptions)
14
+ generator.add_methods(registry.soap_methods)
15
+ generator.add_namespaces(registry.soap_namespaces)
16
+ generator.add_types(registry.soap_types)
17
+ registry_file.write(generator.generate_code())
18
+ registry_file.close
19
+ end
20
+
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,17 @@
1
+ module AdsCommonForBingAds
2
+ module Build
3
+
4
+ class SavonRegistry
5
+
6
+ # Extracts input parameters of given method as an array.
7
+ def extract_input_parameters(op_node, doc)
8
+ input_element = REXML::XPath.first(op_node, 'descendant::wsdl:input')
9
+ input_name = get_element_name(input_element)
10
+ input_fields = find_sequence_fields(input_name, doc)
11
+ return {:name => input_name.snakecase, :fields => input_fields}
12
+ end
13
+
14
+ end
15
+
16
+ end
17
+ end
@@ -0,0 +1,36 @@
1
+ module AdsCommonForBingAds
2
+
3
+ class ParametersValidator
4
+ # Validates input parameters to:
5
+ # - add parameter names;
6
+ # - resolve xsi:type where required;
7
+ # - convert some native types to XML.
8
+ def validate_args(action_name, args)
9
+ in_params = @registry.get_method_signature(action_name)[:input] # Hash like {:name=>"get_accounts_info_request", :fields=>[]}
10
+ # TODO: compare number of parameters.
11
+ args_hash = args#{in_params[:name] => deep_copy(args)}
12
+ #validate_arguments(args_hash, in_params)
13
+ return args_hash
14
+ end
15
+
16
+ private
17
+
18
+ # Validates given arguments based on provided fields list.
19
+ def validate_arguments(args_hash, fields_list, type_ns = nil)
20
+ check_extra_fields(args_hash, array_from_named_list(fields_list))
21
+ add_order_key(args_hash, fields_list)
22
+ fields_list.each do |field|
23
+ key = field[:name]
24
+ item = args_hash[key]
25
+ check_required_argument_present(item, field)
26
+ if item
27
+ item_type = get_full_type_signature(field[:type])
28
+ item_ns = field[:ns] || type_ns
29
+ key = handle_namespace_override(args_hash, key, item_ns) if item_ns
30
+ validate_arg(item, args_hash, key, item_type)
31
+ end
32
+ end
33
+ return args_hash
34
+ end
35
+ end
36
+ end