google-ads-googleads 0.1.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.
Files changed (150) hide show
  1. checksums.yaml +7 -0
  2. data/ChangeLog +2 -0
  3. data/README.md +107 -0
  4. data/Rakefile +7 -0
  5. data/googleads_config.rb +10 -0
  6. data/lib/google/ads/googleads.rb +25 -0
  7. data/lib/google/ads/googleads/config.rb +42 -0
  8. data/lib/google/ads/googleads/errors.rb +40 -0
  9. data/lib/google/ads/googleads/field_mask_util.rb +159 -0
  10. data/lib/google/ads/googleads/googleads_client.rb +177 -0
  11. data/lib/google/ads/googleads/patches.rb +45 -0
  12. data/lib/google/ads/googleads/path_lookup_util.rb +84 -0
  13. data/lib/google/ads/googleads/proto_lookup_util.rb +249 -0
  14. data/lib/google/ads/googleads/v0/common/ad_pb.rb +80 -0
  15. data/lib/google/ads/googleads/v0/common/bidding_pb.rb +71 -0
  16. data/lib/google/ads/googleads/v0/common/criteria_pb.rb +25 -0
  17. data/lib/google/ads/googleads/v0/common/custom_parameter_pb.rb +24 -0
  18. data/lib/google/ads/googleads/v0/common/metrics_pb.rb +65 -0
  19. data/lib/google/ads/googleads/v0/common/policy_pb.rb +24 -0
  20. data/lib/google/ads/googleads/v0/common/value_pb.rb +28 -0
  21. data/lib/google/ads/googleads/v0/enums/ad_group_ad_status_pb.rb +29 -0
  22. data/lib/google/ads/googleads/v0/enums/ad_group_criterion_status_pb.rb +29 -0
  23. data/lib/google/ads/googleads/v0/enums/ad_group_status_pb.rb +29 -0
  24. data/lib/google/ads/googleads/v0/enums/ad_group_type_pb.rb +27 -0
  25. data/lib/google/ads/googleads/v0/enums/ad_network_type_pb.rb +31 -0
  26. data/lib/google/ads/googleads/v0/enums/ad_serving_optimization_status_pb.rb +31 -0
  27. data/lib/google/ads/googleads/v0/enums/ad_type_pb.rb +32 -0
  28. data/lib/google/ads/googleads/v0/enums/advertising_channel_sub_type_pb.rb +28 -0
  29. data/lib/google/ads/googleads/v0/enums/advertising_channel_type_pb.rb +27 -0
  30. data/lib/google/ads/googleads/v0/enums/bid_source_pb.rb +29 -0
  31. data/lib/google/ads/googleads/v0/enums/bidding_strategy_type_pb.rb +36 -0
  32. data/lib/google/ads/googleads/v0/enums/budget_delivery_method_pb.rb +28 -0
  33. data/lib/google/ads/googleads/v0/enums/budget_status_pb.rb +28 -0
  34. data/lib/google/ads/googleads/v0/enums/campaign_serving_status_pb.rb +31 -0
  35. data/lib/google/ads/googleads/v0/enums/campaign_status_pb.rb +29 -0
  36. data/lib/google/ads/googleads/v0/enums/criterion_type_pb.rb +27 -0
  37. data/lib/google/ads/googleads/v0/enums/day_of_week_pb.rb +33 -0
  38. data/lib/google/ads/googleads/v0/enums/device_pb.rb +29 -0
  39. data/lib/google/ads/googleads/v0/enums/google_ads_field_category_pb.rb +30 -0
  40. data/lib/google/ads/googleads/v0/enums/google_ads_field_data_type_pb.rb +36 -0
  41. data/lib/google/ads/googleads/v0/enums/keyword_match_type_pb.rb +29 -0
  42. data/lib/google/ads/googleads/v0/enums/page_one_promoted_strategy_goal_pb.rb +28 -0
  43. data/lib/google/ads/googleads/v0/enums/quality_score_bucket_pb.rb +29 -0
  44. data/lib/google/ads/googleads/v0/enums/slot_pb.rb +32 -0
  45. data/lib/google/ads/googleads/v0/errors/ad_customizer_error_pb.rb +31 -0
  46. data/lib/google/ads/googleads/v0/errors/ad_error_pb.rb +154 -0
  47. data/lib/google/ads/googleads/v0/errors/ad_group_ad_error_pb.rb +34 -0
  48. data/lib/google/ads/googleads/v0/errors/ad_group_criterion_error_pb.rb +63 -0
  49. data/lib/google/ads/googleads/v0/errors/ad_group_error_pb.rb +38 -0
  50. data/lib/google/ads/googleads/v0/errors/ad_sharing_error_pb.rb +29 -0
  51. data/lib/google/ads/googleads/v0/errors/adx_error_pb.rb +27 -0
  52. data/lib/google/ads/googleads/v0/errors/authentication_error_pb.rb +47 -0
  53. data/lib/google/ads/googleads/v0/errors/authorization_error_pb.rb +30 -0
  54. data/lib/google/ads/googleads/v0/errors/bidding_error_pb.rb +46 -0
  55. data/lib/google/ads/googleads/v0/errors/bidding_strategy_error_pb.rb +30 -0
  56. data/lib/google/ads/googleads/v0/errors/campaign_budget_error_pb.rb +40 -0
  57. data/lib/google/ads/googleads/v0/errors/campaign_criterion_error_pb.rb +36 -0
  58. data/lib/google/ads/googleads/v0/errors/campaign_error_pb.rb +60 -0
  59. data/lib/google/ads/googleads/v0/errors/collection_size_error_pb.rb +28 -0
  60. data/lib/google/ads/googleads/v0/errors/criterion_error_pb.rb +106 -0
  61. data/lib/google/ads/googleads/v0/errors/date_error_pb.rb +34 -0
  62. data/lib/google/ads/googleads/v0/errors/date_range_error_pb.rb +31 -0
  63. data/lib/google/ads/googleads/v0/errors/distinct_error_pb.rb +28 -0
  64. data/lib/google/ads/googleads/v0/errors/errors_pb.rb +154 -0
  65. data/lib/google/ads/googleads/v0/errors/feed_attribute_reference_error_pb.rb +29 -0
  66. data/lib/google/ads/googleads/v0/errors/field_mask_error_pb.rb +30 -0
  67. data/lib/google/ads/googleads/v0/errors/function_error_pb.rb +42 -0
  68. data/lib/google/ads/googleads/v0/errors/function_parsing_error_pb.rb +37 -0
  69. data/lib/google/ads/googleads/v0/errors/id_error_pb.rb +27 -0
  70. data/lib/google/ads/googleads/v0/errors/image_error_pb.rb +63 -0
  71. data/lib/google/ads/googleads/v0/errors/internal_error_pb.rb +28 -0
  72. data/lib/google/ads/googleads/v0/errors/list_operation_error_pb.rb +28 -0
  73. data/lib/google/ads/googleads/v0/errors/media_bundle_error_pb.rb +48 -0
  74. data/lib/google/ads/googleads/v0/errors/media_error_pb.rb +50 -0
  75. data/lib/google/ads/googleads/v0/errors/multiplier_error_pb.rb +38 -0
  76. data/lib/google/ads/googleads/v0/errors/mutate_error_pb.rb +31 -0
  77. data/lib/google/ads/googleads/v0/errors/new_resource_creation_error_pb.rb +29 -0
  78. data/lib/google/ads/googleads/v0/errors/not_empty_error_pb.rb +27 -0
  79. data/lib/google/ads/googleads/v0/errors/null_error_pb.rb +27 -0
  80. data/lib/google/ads/googleads/v0/errors/operation_access_denied_error_pb.rb +35 -0
  81. data/lib/google/ads/googleads/v0/errors/operator_error_pb.rb +27 -0
  82. data/lib/google/ads/googleads/v0/errors/query_error_pb.rb +72 -0
  83. data/lib/google/ads/googleads/v0/errors/quota_error_pb.rb +28 -0
  84. data/lib/google/ads/googleads/v0/errors/range_error_pb.rb +28 -0
  85. data/lib/google/ads/googleads/v0/errors/region_code_error_pb.rb +27 -0
  86. data/lib/google/ads/googleads/v0/errors/request_error_pb.rb +41 -0
  87. data/lib/google/ads/googleads/v0/errors/resource_access_denied_error_pb.rb +27 -0
  88. data/lib/google/ads/googleads/v0/errors/resource_count_limit_exceeded_error_pb.rb +33 -0
  89. data/lib/google/ads/googleads/v0/errors/setting_error_pb.rb +43 -0
  90. data/lib/google/ads/googleads/v0/errors/string_format_error_pb.rb +28 -0
  91. data/lib/google/ads/googleads/v0/errors/string_length_error_pb.rb +28 -0
  92. data/lib/google/ads/googleads/v0/errors/url_field_error_pb.rb +70 -0
  93. data/lib/google/ads/googleads/v0/resources/ad_group_ad_pb.rb +28 -0
  94. data/lib/google/ads/googleads/v0/resources/ad_group_criterion_pb.rb +64 -0
  95. data/lib/google/ads/googleads/v0/resources/ad_group_pb.rb +38 -0
  96. data/lib/google/ads/googleads/v0/resources/bidding_strategy_pb.rb +36 -0
  97. data/lib/google/ads/googleads/v0/resources/campaign_budget_pb.rb +32 -0
  98. data/lib/google/ads/googleads/v0/resources/campaign_criterion_pb.rb +32 -0
  99. data/lib/google/ads/googleads/v0/resources/campaign_pb.rb +70 -0
  100. data/lib/google/ads/googleads/v0/resources/customer_pb.rb +29 -0
  101. data/lib/google/ads/googleads/v0/resources/google_ads_field_pb.rb +38 -0
  102. data/lib/google/ads/googleads/v0/resources/keyword_view_pb.rb +22 -0
  103. data/lib/google/ads/googleads/v0/services/ad_group_ad_service_client.rb +262 -0
  104. data/lib/google/ads/googleads/v0/services/ad_group_ad_service_client_config.json +36 -0
  105. data/lib/google/ads/googleads/v0/services/ad_group_ad_service_pb.rb +47 -0
  106. data/lib/google/ads/googleads/v0/services/ad_group_ad_service_services_pb.rb +51 -0
  107. data/lib/google/ads/googleads/v0/services/ad_group_criterion_service_client.rb +262 -0
  108. data/lib/google/ads/googleads/v0/services/ad_group_criterion_service_client_config.json +36 -0
  109. data/lib/google/ads/googleads/v0/services/ad_group_criterion_service_pb.rb +47 -0
  110. data/lib/google/ads/googleads/v0/services/ad_group_criterion_service_services_pb.rb +51 -0
  111. data/lib/google/ads/googleads/v0/services/ad_group_service_client.rb +262 -0
  112. data/lib/google/ads/googleads/v0/services/ad_group_service_client_config.json +36 -0
  113. data/lib/google/ads/googleads/v0/services/ad_group_service_pb.rb +47 -0
  114. data/lib/google/ads/googleads/v0/services/ad_group_service_services_pb.rb +51 -0
  115. data/lib/google/ads/googleads/v0/services/bidding_strategy_service_client.rb +263 -0
  116. data/lib/google/ads/googleads/v0/services/bidding_strategy_service_client_config.json +36 -0
  117. data/lib/google/ads/googleads/v0/services/bidding_strategy_service_pb.rb +47 -0
  118. data/lib/google/ads/googleads/v0/services/bidding_strategy_service_services_pb.rb +52 -0
  119. data/lib/google/ads/googleads/v0/services/campaign_budget_service_client.rb +263 -0
  120. data/lib/google/ads/googleads/v0/services/campaign_budget_service_client_config.json +36 -0
  121. data/lib/google/ads/googleads/v0/services/campaign_budget_service_pb.rb +47 -0
  122. data/lib/google/ads/googleads/v0/services/campaign_budget_service_services_pb.rb +52 -0
  123. data/lib/google/ads/googleads/v0/services/campaign_criterion_service_client.rb +262 -0
  124. data/lib/google/ads/googleads/v0/services/campaign_criterion_service_client_config.json +36 -0
  125. data/lib/google/ads/googleads/v0/services/campaign_criterion_service_pb.rb +47 -0
  126. data/lib/google/ads/googleads/v0/services/campaign_criterion_service_services_pb.rb +51 -0
  127. data/lib/google/ads/googleads/v0/services/campaign_service_client.rb +262 -0
  128. data/lib/google/ads/googleads/v0/services/campaign_service_client_config.json +36 -0
  129. data/lib/google/ads/googleads/v0/services/campaign_service_pb.rb +47 -0
  130. data/lib/google/ads/googleads/v0/services/campaign_service_services_pb.rb +51 -0
  131. data/lib/google/ads/googleads/v0/services/credentials.rb +33 -0
  132. data/lib/google/ads/googleads/v0/services/customer_service_client.rb +214 -0
  133. data/lib/google/ads/googleads/v0/services/customer_service_client_config.json +31 -0
  134. data/lib/google/ads/googleads/v0/services/customer_service_pb.rb +24 -0
  135. data/lib/google/ads/googleads/v0/services/customer_service_services_pb.rb +49 -0
  136. data/lib/google/ads/googleads/v0/services/google_ads_field_service_client.rb +285 -0
  137. data/lib/google/ads/googleads/v0/services/google_ads_field_service_client_config.json +36 -0
  138. data/lib/google/ads/googleads/v0/services/google_ads_field_service_pb.rb +36 -0
  139. data/lib/google/ads/googleads/v0/services/google_ads_field_service_services_pb.rb +51 -0
  140. data/lib/google/ads/googleads/v0/services/google_ads_service_client.rb +242 -0
  141. data/lib/google/ads/googleads/v0/services/google_ads_service_client_config.json +31 -0
  142. data/lib/google/ads/googleads/v0/services/google_ads_service_pb.rb +72 -0
  143. data/lib/google/ads/googleads/v0/services/google_ads_service_services_pb.rb +49 -0
  144. data/lib/google/ads/googleads/v0/services/keyword_view_service_client.rb +216 -0
  145. data/lib/google/ads/googleads/v0/services/keyword_view_service_client_config.json +31 -0
  146. data/lib/google/ads/googleads/v0/services/keyword_view_service_pb.rb +24 -0
  147. data/lib/google/ads/googleads/v0/services/keyword_view_service_services_pb.rb +49 -0
  148. data/lib/google/ads/googleads/version.rb +25 -0
  149. data/lib/google/ads/googleads/wrapper_util.rb +48 -0
  150. metadata +248 -0
checksums.yaml ADDED
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA256:
3
+ metadata.gz: 786e9754852be58af6ed81928f5c2eb75784d4d24090479912ad3dd376a57d57
4
+ data.tar.gz: 21ef46bf2d76bc7085ca8ed1f2b6a63eb4becf92d61c0a8d970f926156c3cf4d
5
+ SHA512:
6
+ metadata.gz: 55349a21aad338d63dcce98df2511a4372e7f36a00a9d25b74f83feba241c074579a29b22061ccb013afad1184e68737f1cd76b3167802fd80c482eda9fb1793
7
+ data.tar.gz: '0178da13bafbfd1c9b61e684397d76e2d02065f3ba53f2fd5345cc1d6f0a0ab29b30a8bdb0bbd70185515ea3875996b00824f6a97c9a73134746f541f32d055c'
data/ChangeLog ADDED
@@ -0,0 +1,2 @@
1
+ 0.1.0:
2
+ - Initial release with support for Google Ads API V0.
data/README.md ADDED
@@ -0,0 +1,107 @@
1
+ # Google Ads Client Library for Ruby
2
+
3
+ `google-ads-googleads` uses [Google API extensions][google-gax] to provide an
4
+ easy-to-use client library for the [Google Ads API][].
5
+
6
+ [google-gax]: https://github.com/googleapis/gax-ruby
7
+ [Google Ads API]: https://developers.google.com/google-ads/api
8
+
9
+ # Documentation for Users
10
+
11
+ ## Getting started
12
+
13
+ `google-ads-googleads` will allow you to connect to the
14
+ [Google Ads API][] and access all its methods.
15
+
16
+ In order to achieve so you need to set up authentication as well as install the
17
+ library locally.
18
+
19
+ ## Installation
20
+
21
+ Install this library using gem:
22
+
23
+ $ [sudo] gem install google-ads-googleads
24
+
25
+ Alternatively, if you prefer not to or can't use the hosted gem on RubyGems, you
26
+ can download the gem from the [Releases][] page and install it from the local
27
+ file:
28
+
29
+ $ [sudo] gem install google-ads-googleads-[version].gem
30
+
31
+ Or you can build it yourself from the source. After cloning the GitHub repo,
32
+ navigate to the `google-ads-ruby` folder and run:
33
+
34
+ $ rake build
35
+ $ gem install pkg/google-ads-googleads-[version].gem
36
+
37
+ [Releases]: https://github.com/googleads/google-ads-ruby/releases
38
+
39
+ ## Set Up Authentication
40
+
41
+ To authenticate your API calls, you need to specify your client ID, client
42
+ secret, refresh token, and developer token to the library in one of a few ways.
43
+
44
+ If you don't have a client ID or client secret yet, please see the
45
+ [Authorization guide][] to get those set up. Once you have those, the Ruby
46
+ library can help you use those to generate a refresh token.
47
+
48
+ See and run the [Authentication example][] to generate your refresh token.
49
+ Once this is generated, you can provide it to the library in a few different
50
+ ways.
51
+
52
+ The simplest is to copy the [adwords_config.rb][] to your home directory and
53
+ simply modify it to include the client ID, client secret, and refresh token.
54
+ The library will automatically read it from the home directory if instantiated
55
+ with no arguments:
56
+
57
+ adwords = Google::Ads::Googleads::GoogleadsClient.new
58
+
59
+ Alternatively, if you prefer to keep the file elsewhere, you can instantiate the
60
+ library by passing the path to where you keep this file:
61
+
62
+ adwords = Google::Ads::Googleads::GoogleadsClient.new('path/to/file.rb')
63
+
64
+ If you prefer not to store this information in a file at all, and would rather
65
+ pass the information programmatically at runtime, you can accomplish that this
66
+ way:
67
+
68
+ adwords = Google::Ads::Googleads::GoogleadsClient.new do |config|
69
+ config.client_id = 'INSERT_CLIENT_ID_HERE'
70
+ config.client_secret = 'INSERT_CLIENT_SECRET_HERE'
71
+ config.refresh_token = 'INSERT_REFRESH_TOKEN_HERE'
72
+ config.developer_token = 'INSERT_DEVELOPER_TOKEN_HERE'
73
+ end
74
+
75
+ You can also modify these properties after instantiation by using the
76
+ `configure` method on the `AdwordsClient`, using the same structure as above.
77
+
78
+ [Authorization guide]: https://developers.google.com/google-ads/api/docs/oauth/
79
+ [Authentication example]: https://github.com/googleads/google-ads-ruby/blob/master/examples/authentication/authenticate_in_standalone_application.rb
80
+ [adwords_config.rb]: https://github.com/googleads/google-ads-ruby/blob/master/googleads_config.rb
81
+
82
+ ## Usage
83
+
84
+ To include the gem in your code:
85
+
86
+ require 'google/ads/googleads'
87
+
88
+ To fetch a specific service, for example CampaignService:
89
+
90
+ adwords = Google::Ads::Googleads::GoogleadsClient.new
91
+ campaign_service = adwords.service(:Campaign)
92
+
93
+ See the provided [examples][] for more detailed demonstrations of how to use the
94
+ library.
95
+
96
+ [examples]: https://github.com/googleads/google-ads-ruby/blob/master/examples
97
+
98
+ # Authors
99
+
100
+ Author:
101
+
102
+ - Danial Klimkin
103
+ - Michael Cloonan
104
+
105
+ Maintainer:
106
+
107
+ - Michael Cloonan
data/Rakefile ADDED
@@ -0,0 +1,7 @@
1
+ # -*- ruby -*-
2
+ require 'bundler/gem_tasks'
3
+ require 'rake/testtask'
4
+
5
+ Rake::TestTask.new do |t|
6
+ t.test_files = FileList['test/**/test_*.rb']
7
+ end
@@ -0,0 +1,10 @@
1
+ # This is an example configuration file for the Google Ads API Ruby client
2
+ # library.
3
+ # Please fill in the required fields and copy it to your home directory.
4
+
5
+ Google::Ads::Googleads::Config.new do |c|
6
+ c.client_id = 'INSERT_CLIENT_ID_HERE'
7
+ c.client_secret = 'INSERT_CLIENT_SECRET_HERE'
8
+ c.refresh_token = 'INSERT_REFRESH_TOKEN_HERE'
9
+ c.developer_token = 'INSERT_DEVELOPER_TOKEN_HERE'
10
+ end
@@ -0,0 +1,25 @@
1
+ # Encoding: utf-8
2
+ #
3
+ # Copyright:: Copyright 2017, Google Inc. All Rights Reserved.
4
+ #
5
+ # License:: Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # http://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or
14
+ # implied.
15
+ # See the License for the specific language governing permissions and
16
+ # limitations under the License.
17
+
18
+ require 'google/ads/googleads/googleads_client'
19
+
20
+ module Google
21
+ module Ads
22
+ module Googleads
23
+ end
24
+ end
25
+ end
@@ -0,0 +1,42 @@
1
+ # Encoding: utf-8
2
+ #
3
+ # Copyright 2018 Google LLC
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # https://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ #
17
+ # Configuration setup for and storage for the API.
18
+
19
+ module Google
20
+ module Ads
21
+ module Googleads
22
+ class Config
23
+ attr_accessor :refresh_token
24
+ attr_accessor :client_id
25
+ attr_accessor :client_secret
26
+ attr_accessor :developer_token
27
+
28
+ def initialize(&block)
29
+ @refresh_token = nil
30
+ @client_id = nil
31
+ @client_secret = nil
32
+ @developer_token = nil
33
+ yield self if block_given?
34
+ end
35
+
36
+ def configure(&block)
37
+ yield self
38
+ end
39
+ end
40
+ end
41
+ end
42
+ end
@@ -0,0 +1,40 @@
1
+ # Encoding: utf-8
2
+ #
3
+ # Copyright 2018 Google LLC
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # https://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ #
17
+ # File for all errors that will be used by the Google Ads API Library.
18
+
19
+ module Google
20
+ module Ads
21
+ module Googleads
22
+ module Errors
23
+
24
+ # Generic error class for non-specific errors.
25
+ class Error < ::StandardError
26
+ end
27
+
28
+ # Raised when encountering an API-specific error, such as an entity
29
+ # not found or a malformed query.
30
+ class GoogleAdsError < Error
31
+ attr_reader :failure
32
+
33
+ def initialize(failure)
34
+ @failure = failure
35
+ end
36
+ end
37
+ end
38
+ end
39
+ end
40
+ end
@@ -0,0 +1,159 @@
1
+ # Encoding: utf-8
2
+ #
3
+ # Copyright 2018 Google LLC
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # https://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ #
17
+ # Utility for constructing field masks, which are necessary for update
18
+ # operations.
19
+
20
+ require "google/protobuf"
21
+
22
+ module Google
23
+ module Ads
24
+ module Googleads
25
+ # Utility for constructing FieldMask objects.
26
+ #
27
+ # Copied from C# implementation courtesy of jonskeet@google.com
28
+ class FieldMaskUtil
29
+ # Construct a field mask containing any changes to the object made
30
+ # in the given block.
31
+ #
32
+ # Example:
33
+ #
34
+ # obj = MyObject.new
35
+ # obj.some_property = 1
36
+ #
37
+ # mask = FieldMaskUtil.with obj do
38
+ # obj.other_property = 2
39
+ # end
40
+ #
41
+ # # the mask will contain the changed property "other_property"
42
+ # api_client.mutate obj, mask
43
+ #
44
+ # @param obj [Object] the object to watch
45
+ # @yield block used for determining changes to the object
46
+ # @return [Google::Protobuf::FieldMask] the computed mask
47
+ def self.with(obj)
48
+ raise 'nil cannot be compared' if obj.nil?
49
+ original = obj.class.decode(obj.class.encode(obj))
50
+ yield
51
+ compare original, obj
52
+ end
53
+
54
+ # Construct a field mask containing any fields set on the given object.
55
+ #
56
+ # Example:
57
+ #
58
+ # obj = MyObject.new
59
+ # obj.some_property = 1
60
+ # obj.other_property = 2
61
+ #
62
+ # mask = FieldMaskUtil.all_set_fields_of obj
63
+ #
64
+ # # the mask will contain the present properties "some_property" and
65
+ # # "other_property"
66
+ # api_client.mutate obj, mask
67
+ #
68
+ # @param obj [Object] the object to watch
69
+ # return [Google::Protobuf::FieldMask] the computed mask
70
+ def self.all_set_fields_of(obj)
71
+ new_instance = obj.class.new
72
+ compare_obj(Google::Protobuf::FieldMask.new, '', new_instance, obj)
73
+ end
74
+
75
+ # Creates Google::Protobuf::FieldMask objects based on the
76
+ # difference between two objects.
77
+ #
78
+ # @param original
79
+ # @param modified
80
+ # @return [Google::Protobuf::FieldMask] the computed mask
81
+ def self.compare(original, modified)
82
+ raise 'nil cannot be compared' if original.nil? || modified.nil?
83
+ raise 'objects of different types cannot be compared' if original.class != modified.class
84
+ compare_obj(Google::Protobuf::FieldMask.new, '', original, modified)
85
+ end
86
+
87
+ def self.compare_obj(mask, current_field, original, modified)
88
+ descriptor = original.class.descriptor
89
+
90
+ descriptor.entries.each do |field|
91
+ field_path = get_path current_field, field.name
92
+
93
+ # extract values
94
+ original_value = original[field.name]
95
+ modified_value = modified[field.name]
96
+
97
+ if is_repeated?(original_value) || is_repeated?(modified_value)
98
+ # repeated fields - must match exactly or add the field
99
+ mask.paths << field_path unless original_value == modified_value
100
+ else
101
+ case field.type
102
+ when :message
103
+ if original_value != modified_value
104
+ # wrappers - do not include the .value part of the path
105
+ if is_wrapper? [original_value, modified_value]
106
+ mask.paths << field_path
107
+ elsif original_value.nil?
108
+ # new message, make a blank instance and then compare
109
+ # against it
110
+ original_value = modified[field.name].class.new
111
+ compare_obj mask, field_path, original_value, modified_value
112
+ elsif modified_value.nil?
113
+ # just emit the deleted field name
114
+ mask.paths << field_path
115
+ else
116
+ compare_obj mask, field_path, original_value, modified_value
117
+ end
118
+ end
119
+ else # primitive types
120
+ mask.paths << field_path unless original_value == modified_value
121
+ end
122
+ end
123
+ end
124
+
125
+ mask
126
+ end
127
+
128
+ # Construts path string
129
+ def self.get_path(path, field)
130
+ path.nil? || path == '' ? field : "#{path}.#{field}"
131
+ end
132
+
133
+ WRAPPER_TYPES = [Google::Protobuf::DoubleValue,
134
+ Google::Protobuf::FloatValue,
135
+ Google::Protobuf::Int64Value,
136
+ Google::Protobuf::UInt64Value,
137
+ Google::Protobuf::Int32Value,
138
+ Google::Protobuf::UInt32Value,
139
+ Google::Protobuf::BoolValue,
140
+ Google::Protobuf::StringValue,
141
+ Google::Protobuf::BytesValue].freeze
142
+
143
+ # Checks if the object is a wrapper type
144
+ def self.is_wrapper?(obj)
145
+ obj = [obj] unless obj.is_a?(Array)
146
+ obj.any? { |x| WRAPPER_TYPES.count { |klass| klass == x.class } > 0 }
147
+ end
148
+
149
+ # Checks if the object is a repeated field
150
+ def self.is_repeated?(obj)
151
+ obj.is_a?(Google::Protobuf::RepeatedField)
152
+ end
153
+
154
+ private_class_method :compare_obj, :get_path, :is_wrapper?,
155
+ :is_repeated?
156
+ end
157
+ end
158
+ end
159
+ end
@@ -0,0 +1,177 @@
1
+ # Encoding: utf-8
2
+ #
3
+ # Copyright 2018 Google LLC
4
+ #
5
+ # Licensed under the Apache License, Version 2.0 (the "License");
6
+ # you may not use this file except in compliance with the License.
7
+ # You may obtain a copy of the License at
8
+ #
9
+ # https://www.apache.org/licenses/LICENSE-2.0
10
+ #
11
+ # Unless required by applicable law or agreed to in writing, software
12
+ # distributed under the License is distributed on an "AS IS" BASIS,
13
+ # WITHOUT WARRANTIES OR CONDITIONS OF ANY KIND, either express or implied.
14
+ # See the License for the specific language governing permissions and
15
+ # limitations under the License.
16
+ #
17
+ # Googleads client class to configure settings and fetch services.
18
+
19
+ require 'googleauth'
20
+
21
+ require 'google/ads/googleads/patches'
22
+ require 'google/ads/googleads/config'
23
+ require 'google/ads/googleads/field_mask_util'
24
+ require 'google/ads/googleads/wrapper_util'
25
+ require 'google/ads/googleads/proto_lookup_util'
26
+ require 'google/ads/googleads/path_lookup_util'
27
+
28
+ require 'google/ads/googleads/errors'
29
+ require 'google/ads/googleads/v0/errors/errors_pb'
30
+
31
+ require 'google/gax'
32
+
33
+ module Google
34
+ module Ads
35
+ module Googleads
36
+ class GoogleadsClient
37
+ API_VERSION = :V0
38
+
39
+ DEFAULT_CONFIG_FILENAME = 'googleads_config.rb'
40
+
41
+ def initialize(config_path = nil, &block)
42
+ if block_given?
43
+ @config = Google::Ads::Googleads::Config.new
44
+
45
+ yield @config
46
+ else
47
+ if config_path.nil?
48
+ config_path = File.join(ENV['HOME'], DEFAULT_CONFIG_FILENAME)
49
+ end
50
+
51
+ unless File.exist?(config_path)
52
+ raise ArgumentError,
53
+ sprintf('No configuration file found at location "%s"',
54
+ config_path)
55
+ end
56
+ file = File.read(config_path)
57
+
58
+ eval_result = eval(file, binding, config_path)
59
+ unless eval_result.instance_of?(Google::Ads::Googleads::Config)
60
+ raise ArgumentError, sprintf(
61
+ 'Configuration file did not produce expected type ' +
62
+ 'Google::Ads::Googleads::Config, got "%s" instead',
63
+ eval_result.class
64
+ )
65
+ end
66
+ @config = eval_result
67
+ end
68
+ @proto_lookup_util =
69
+ Google::Ads::Googleads::ProtoLookupUtil.new(API_VERSION)
70
+ @path_lookup_util =
71
+ Google::Ads::Googleads::PathLookupUtil.new(@proto_lookup_util)
72
+ end
73
+
74
+ def configure(&block)
75
+ yield @config
76
+ end
77
+
78
+ # Return a service for the provided entity type. For example, passing
79
+ # :Campaign will return an instantiated CampaignServiceClient.
80
+ #
81
+ # Raises ArgumentError if no service can be found for the provided type.
82
+ def service(name)
83
+ service_path = ENV['GOOGLEADS_SERVICE_PATH']
84
+
85
+ class_to_return = @proto_lookup_util.service(name)
86
+ unless service_path.nil? || service_path.empty?
87
+ class_to_return = Class.new(class_to_return) do
88
+ const_set('SERVICE_ADDRESS', service_path.freeze)
89
+ end
90
+ end
91
+
92
+ return class_to_return.new(
93
+ credentials: get_updater_proc(),
94
+ metadata: {:"developer-token" => @config.developer_token},
95
+ exception_transformer: ERROR_TRANSFORMER
96
+ )
97
+ end
98
+
99
+ # Return a resource or common entity for the provided entity type. For
100
+ # example, passing :Campaign will return an instantiated Campaign.
101
+ #
102
+ # Raises ArgumentError if no entity can be found for the provided type.
103
+ def resource(name)
104
+ @proto_lookup_util.resource(name).new
105
+ end
106
+
107
+ # Return an operation for the provided entity type. For example, passing
108
+ # :Campaign will return an instantiated CampaignOperation.
109
+ #
110
+ # Raises ArgumentError if no entity can be found for the provided type.
111
+ def operation(name)
112
+ @proto_lookup_util.operation(name).new
113
+ end
114
+
115
+ # Return a reference to the enum class for the provided enum type. For
116
+ # example, passing :CampaignStatus will return a reference to the
117
+ # CampaignStatusEnum.
118
+ #
119
+ # Raises ArgumentError if no enum can be found for the provided type.
120
+ def enum(name)
121
+ @proto_lookup_util.enum(name)
122
+ end
123
+
124
+ # Returns a reference to the FieldMaskUtil class for ease of access.
125
+ def field_mask()
126
+ Google::Ads::Googleads::FieldMaskUtil
127
+ end
128
+
129
+ # Returns a reference to the WrapperUtil class for ease of access.
130
+ def wrapper()
131
+ Google::Ads::Googleads::WrapperUtil
132
+ end
133
+
134
+ # Returns a reference to the PathLookupUtil to generate resource names.
135
+ def path()
136
+ @path_lookup_util
137
+ end
138
+
139
+ private
140
+
141
+ ERROR_TRANSFORMER = Proc.new do |gax_error|
142
+ begin
143
+ gax_error.status_details.each do |failure|
144
+ # If there is an underlying GoogleAdsFailure, throw that one.
145
+ if failure.is_a?(
146
+ Google::Ads::Googleads::V0::Errors::GoogleAdsFailure)
147
+ raise Google::Ads::Googleads::Errors::GoogleAdsError.new(
148
+ failure)
149
+ end
150
+ end
151
+ rescue Google::Ads::Googleads::Errors::GoogleAdsError
152
+ # If we raised this, bubble it out.
153
+ raise
154
+ rescue NoMethodError
155
+ # Sometimes status_details is just a String; in that case, we should
156
+ # just raise the original exception.
157
+ end
158
+ # If we don't find an error of the correct type, or if we run into an
159
+ # error while processing, just throw the original.
160
+ raise gax_error
161
+ end
162
+
163
+ # Provides the service a method by which to obtain an access token to
164
+ # authenticate API requests.
165
+ def get_updater_proc()
166
+ return Signet::OAuth2::Client.new(
167
+ token_credential_uri: 'https://www.googleapis.com/oauth2/v3/token',
168
+ client_id: @config.client_id,
169
+ client_secret: @config.client_secret,
170
+ refresh_token: @config.refresh_token,
171
+ scope: ['https://www.googleapis.com/auth/adwords']
172
+ ).updater_proc
173
+ end
174
+ end
175
+ end
176
+ end
177
+ end