sem4r 0.1.1 → 0.1.2

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 (199) hide show
  1. data/Gemfile +11 -0
  2. data/Gemfile.lock +36 -0
  3. data/README.rdoc +30 -0
  4. data/Rakefile +15 -12
  5. data/VERSION.yml +1 -1
  6. data/examples_blog/2009-11-29-hello-world.rb +0 -1
  7. data/examples_sem4r/01_get_account.rb +1 -1
  8. data/examples_sem4r/02_get_info.rb +6 -2
  9. data/examples_sem4r/03_list_ad.rb +1 -1
  10. data/examples_sem4r/04_list_keywords.rb +1 -1
  11. data/examples_sem4r/05_request_report.rb +1 -2
  12. data/examples_sem4r/05_request_report_2010.rb +19 -4
  13. data/examples_sem4r/06_create_campaigns.rb +1 -1
  14. data/examples_sem4r/07_create_campaigns_block.rb +1 -1
  15. data/examples_sem4r/07_create_campaigns_simple.rb +1 -1
  16. data/examples_sem4r/08_ad_params.rb +1 -1
  17. data/examples_sem4r/09_targeting_idea.rb +1 -1
  18. data/examples_sem4r/10_get_location.rb +1 -1
  19. data/examples_sem4r/11_submit_bulk_job.rb +1 -1
  20. data/examples_sem4r/12_list_bulk_job.rb +1 -1
  21. data/examples_sem4r/30_prune_empty_adgroup.rb +1 -1
  22. data/examples_sem4r/31_empty_accounts.rb +1 -1
  23. data/examples_sem4r/example_helper.rb +5 -10
  24. data/lib/sem4r/account.rb +3 -306
  25. data/lib/sem4r/ad_group/ad_group.rb +16 -14
  26. data/lib/sem4r/ad_group/ad_group_bids.rb +11 -10
  27. data/lib/sem4r/ad_group/ad_group_service.rb +5 -5
  28. data/lib/sem4r/ad_group_ad/ad_group_ad.rb +1 -1
  29. data/lib/sem4r/ad_group_ad/ad_group_ad_service.rb +5 -5
  30. data/lib/sem4r/ad_group_ad/ad_group_mobile_ad.rb +9 -9
  31. data/lib/sem4r/ad_group_ad/ad_group_text_ad.rb +9 -9
  32. data/lib/sem4r/ad_group_criterion/ad_group_criterion.rb +6 -6
  33. data/lib/sem4r/ad_group_criterion/ad_group_criterion_bids.rb +5 -6
  34. data/lib/sem4r/ad_group_criterion/ad_group_criterion_operations.rb +0 -1
  35. data/lib/sem4r/ad_group_criterion/ad_group_criterion_service.rb +4 -4
  36. data/lib/sem4r/ad_group_criterion/criterion.rb +3 -3
  37. data/lib/sem4r/ad_group_criterion/criterion_keyword.rb +3 -3
  38. data/lib/sem4r/ad_group_criterion/criterion_placement.rb +2 -2
  39. data/lib/sem4r/ad_param/ad_param.rb +3 -3
  40. data/lib/sem4r/ad_param/ad_param_service.rb +5 -5
  41. data/lib/sem4r/adwords.rb +1 -0
  42. data/lib/sem4r/api_counters.rb +1 -0
  43. data/lib/sem4r/base.rb +1 -0
  44. data/lib/sem4r/bulk_mutate_job/bulk_mutate_job.rb +2 -2
  45. data/lib/sem4r/bulk_mutate_job/bulk_mutate_job_account_extension.rb +59 -0
  46. data/lib/sem4r/bulk_mutate_job/bulk_mutate_job_service.rb +5 -5
  47. data/lib/sem4r/campaign/campaign.rb +10 -10
  48. data/lib/sem4r/campaign/campaign_account_extension.rb +87 -0
  49. data/lib/sem4r/campaign/campaign_service.rb +6 -6
  50. data/lib/sem4r/campaign_target/campaign_target_service.rb +22 -22
  51. data/lib/sem4r/cli/cli_command.rb +1 -0
  52. data/lib/sem4r/cli/cli_common_args.rb +10 -3
  53. data/lib/sem4r/cli/cli_helpers.rb +1 -0
  54. data/lib/sem4r/cli/cli_sem.rb +1 -0
  55. data/lib/sem4r/cli/{cli_download_report.rb → commands/cli_download_report.rb} +2 -1
  56. data/lib/sem4r/cli/{cli_ideas.rb → commands/cli_ideas.rb} +1 -0
  57. data/lib/sem4r/cli/{cli_commands.rb → commands/cli_info.rb} +3 -23
  58. data/lib/sem4r/cli/{cli_list_ads.rb → commands/cli_list_ads.rb} +1 -0
  59. data/lib/sem4r/cli/commands/cli_list_campaign.rb +35 -0
  60. data/lib/sem4r/cli/commands/cli_list_client.rb +36 -0
  61. data/lib/sem4r/cli/{cli_list_keywords.rb → commands/cli_list_keywords.rb} +1 -0
  62. data/lib/sem4r/cli/commands/cli_list_report.rb +34 -0
  63. data/lib/sem4r/cli/commands/cli_repdef.rb +109 -0
  64. data/lib/sem4r/cli/commands/cli_report.rb +78 -0
  65. data/lib/sem4r/cli/{cli_request_report.rb → commands/cli_request_report.rb} +1 -0
  66. data/lib/sem4r/credentials.rb +1 -0
  67. data/lib/sem4r/extensions.rb +22 -1
  68. data/lib/sem4r/geo_location/geo_location_account_extension.rb +43 -0
  69. data/lib/sem4r/geo_location/geo_location_service.rb +4 -4
  70. data/lib/sem4r/info/info_account_extension.rb +48 -0
  71. data/lib/sem4r/info/info_selector.rb +108 -0
  72. data/lib/sem4r/info/info_service.rb +11 -66
  73. data/lib/sem4r/{common/operation.rb → operation.rb} +3 -1
  74. data/lib/sem4r/report_definition/report_definition.rb +75 -15
  75. data/lib/sem4r/report_definition/report_definition_account_extension.rb +79 -0
  76. data/lib/sem4r/report_definition/report_definition_operation.rb +3 -1
  77. data/lib/sem4r/report_definition/report_definition_service.rb +7 -7
  78. data/lib/sem4r/report_definition/report_field.rb +57 -0
  79. data/lib/sem4r/sem4r_error.rb +1 -0
  80. data/lib/sem4r/services/http_connector.rb +93 -0
  81. data/lib/sem4r/services/service.rb +1 -1
  82. data/lib/sem4r/services/soap_call.rb +27 -5
  83. data/lib/sem4r/services/soap_connector.rb +2 -147
  84. data/lib/sem4r/services/soap_dumper.rb +105 -0
  85. data/lib/sem4r/services/soap_message_v13.rb +15 -9
  86. data/lib/sem4r/services/{soap_message_v2009.rb → soap_message_v2010.rb} +26 -12
  87. data/lib/sem4r/targeting_idea/targeting_idea.rb +16 -11
  88. data/lib/sem4r/targeting_idea/targeting_idea_account_extension.rb +52 -0
  89. data/lib/sem4r/targeting_idea/targeting_idea_selector.rb +36 -10
  90. data/lib/sem4r/targeting_idea/targeting_idea_service.rb +5 -5
  91. data/lib/sem4r/v13_account/account_account_extension.rb +103 -0
  92. data/lib/sem4r/v13_account/billing_address.rb +10 -21
  93. data/lib/sem4r/v13_report/report.rb +8 -8
  94. data/lib/sem4r/v13_report/report_account_extension.rb +63 -0
  95. data/lib/sem4r/v13_report/report_job.rb +1 -1
  96. data/lib/sem4r.rb +27 -6
  97. data/lib/sem4r_cli.rb +4 -6
  98. data/lib/{sem4r → soap_helpers}/soap_attributes.rb +105 -13
  99. data/sem4r.gemspec +229 -190
  100. data/spec/{aggregates_spec_helper.rb → aggregates_rspec_helper.rb} +0 -0
  101. data/spec/build_fixtures.rb +84 -0
  102. data/spec/rspec_hash.rb +66 -0
  103. data/spec/{spec_helper.rb → rspec_helper.rb} +4 -2
  104. data/spec/rspec_matchers.rb +102 -0
  105. data/spec/rspec_sem4r_helper.rb +88 -0
  106. data/spec/sem4r/account_spec.rb +3 -4
  107. data/spec/sem4r/ad_group/ad_group_bids_spec.rb +4 -3
  108. data/spec/sem4r/ad_group/ad_group_service_spec.rb +8 -7
  109. data/spec/sem4r/ad_group/ad_group_spec.rb +5 -4
  110. data/spec/{fixtures/services/ad_group → sem4r/ad_group/fixtures}/get-first-req.xml +0 -0
  111. data/spec/{fixtures/services/ad_group → sem4r/ad_group/fixtures}/get-first-res.xml +0 -0
  112. data/spec/{fixtures/services/ad_group → sem4r/ad_group/fixtures}/get-manual-cpm-bids-req.xml +0 -0
  113. data/spec/{fixtures/services/ad_group → sem4r/ad_group/fixtures}/get-manual-cpm-bids-res.xml +0 -0
  114. data/spec/{fixtures/services/ad_group → sem4r/ad_group/fixtures}/mutate_add-req.xml +0 -0
  115. data/spec/{fixtures/services/ad_group → sem4r/ad_group/fixtures}/mutate_add-res.xml +0 -0
  116. data/spec/sem4r/ad_group_ad/ad_group_ad_operation_spec.rb +3 -3
  117. data/spec/sem4r/ad_group_ad/ad_group_ad_service_spec.rb +6 -5
  118. data/spec/sem4r/ad_group_ad/ad_group_ad_spec.rb +6 -5
  119. data/spec/{fixtures/services/ad_group_ad → sem4r/ad_group_ad/fixtures}/get_mobile_ad-req.xml +0 -0
  120. data/spec/{fixtures/services/ad_group_ad → sem4r/ad_group_ad/fixtures}/get_mobile_ad-res.xml +0 -0
  121. data/spec/{fixtures/services/ad_group_ad → sem4r/ad_group_ad/fixtures}/get_text_ad-req.xml +0 -0
  122. data/spec/{fixtures/services/ad_group_ad → sem4r/ad_group_ad/fixtures}/get_text_ad-res.xml +0 -0
  123. data/spec/{fixtures/services/ad_group_ad → sem4r/ad_group_ad/fixtures}/mutate_add_mobile_ad-req.xml +0 -0
  124. data/spec/{fixtures/services/ad_group_ad → sem4r/ad_group_ad/fixtures}/mutate_add_mobile_ad-res.xml +0 -0
  125. data/spec/{fixtures/services/ad_group_ad → sem4r/ad_group_ad/fixtures}/mutate_add_text_ad-req.xml +0 -0
  126. data/spec/{fixtures/services/ad_group_ad → sem4r/ad_group_ad/fixtures}/mutate_add_text_ad-res.xml +0 -0
  127. data/spec/{fixtures/services/ad_group_ad → sem4r/ad_group_ad/fixtures}/mutate_add_two_criterions-req.xml +0 -0
  128. data/spec/{fixtures/services/ad_group_ad → sem4r/ad_group_ad/fixtures}/mutate_add_two_criterions-res.xml +0 -0
  129. data/spec/sem4r/ad_group_criterion/ad_group_criterion_bids_spec.rb +5 -4
  130. data/spec/sem4r/ad_group_criterion/ad_group_criterion_service_spec.rb +6 -5
  131. data/spec/sem4r/ad_group_criterion/ad_group_criterion_spec.rb +6 -5
  132. data/spec/sem4r/ad_group_criterion/criterion_spec.rb +5 -4
  133. data/spec/{fixtures/services/ad_group_criterion → sem4r/ad_group_criterion/fixtures}/get-req.xml +0 -0
  134. data/spec/{fixtures/services/ad_group_criterion → sem4r/ad_group_criterion/fixtures}/get-res.xml +0 -0
  135. data/spec/{fixtures/services/ad_group_criterion → sem4r/ad_group_criterion/fixtures}/mutate_add_criterion_keyword-req.xml +0 -0
  136. data/spec/{fixtures/services/ad_group_criterion → sem4r/ad_group_criterion/fixtures}/mutate_add_criterion_keyword-res.xml +0 -0
  137. data/spec/{fixtures/services/ad_group_criterion → sem4r/ad_group_criterion/fixtures}/mutate_add_criterion_placement-req.xml +0 -0
  138. data/spec/{fixtures/services/ad_group_criterion → sem4r/ad_group_criterion/fixtures}/mutate_add_criterion_placement-res.xml +0 -0
  139. data/spec/{fixtures/services/ad_group_criterion → sem4r/ad_group_criterion/fixtures}/mutate_add_negative_keyword-req.xml +0 -0
  140. data/spec/{fixtures/services/ad_group_criterion → sem4r/ad_group_criterion/fixtures}/mutate_add_negative_keyword-res.xml +0 -0
  141. data/spec/sem4r/ad_param/ad_param_service_spec.rb +6 -5
  142. data/spec/sem4r/ad_param/ad_param_spec.rb +3 -2
  143. data/spec/{fixtures/services/ad_param → sem4r/ad_param/fixtures}/mutate_set-req.xml +0 -0
  144. data/spec/{fixtures/services/ad_param → sem4r/ad_param/fixtures}/mutate_set-res.xml +0 -0
  145. data/spec/sem4r/adwords_spec.rb +1 -1
  146. data/spec/sem4r/bulk_mutate_job/bulk_mutate_job_service_spec.rb +6 -5
  147. data/spec/sem4r/bulk_mutate_job/bulk_mutate_job_spec.rb +4 -3
  148. data/spec/{fixtures/services/bulk_mutate_job → sem4r/bulk_mutate_job/fixtures}/get-req.xml +0 -0
  149. data/spec/{fixtures/services/bulk_mutate_job → sem4r/bulk_mutate_job/fixtures}/get-res.xml +0 -0
  150. data/spec/{fixtures/services/bulk_mutate_job → sem4r/bulk_mutate_job/fixtures}/mutate-req.xml +0 -0
  151. data/spec/{fixtures/services/bulk_mutate_job → sem4r/bulk_mutate_job/fixtures}/mutate-res.xml +0 -0
  152. data/spec/sem4r/bulk_mutate_job/job_operation_spec.rb +3 -2
  153. data/spec/sem4r/campaign/campaign_service_spec.rb +8 -7
  154. data/spec/sem4r/campaign/campaign_spec.rb +3 -2
  155. data/spec/{fixtures/services/campaign → sem4r/campaign/fixtures}/get-req.xml +0 -0
  156. data/spec/{fixtures/services/campaign → sem4r/campaign/fixtures}/get-res.xml +0 -0
  157. data/spec/{fixtures/services/campaign → sem4r/campaign/fixtures}/mutate_add-req.xml +0 -0
  158. data/spec/{fixtures/services/campaign → sem4r/campaign/fixtures}/mutate_add-res.xml +0 -0
  159. data/spec/sem4r/cli/cli_spec.rb +2 -3
  160. data/spec/sem4r/credentials_spec.rb +1 -1
  161. data/spec/sem4r/info/account_info_extension_spec.rb +51 -0
  162. data/spec/sem4r/info/fixtures/get_unit_count-req.xml +34 -0
  163. data/spec/sem4r/info/fixtures/get_unit_count-res.xml +27 -0
  164. data/spec/sem4r/nokogiri_parsing_spec.rb +105 -0
  165. data/spec/{fixtures/services/report_definition → sem4r/report_definition/fixtures}/mutate_add-req.xml +0 -0
  166. data/spec/{fixtures/services/report_definition → sem4r/report_definition/fixtures}/mutate_add-req_orig.xml +0 -0
  167. data/spec/sem4r/report_definition/report_definition_service_spec.rb +5 -3
  168. data/spec/sem4r/report_definition/report_definition_spec.rb +6 -3
  169. data/spec/sem4r/rexml_parsing_spec.rb +22 -22
  170. data/spec/sem4r/services/service_spec.rb +2 -1
  171. data/spec/sem4r/services/soap_call_spec.rb +6 -5
  172. data/spec/sem4r/services/soap_message_v13_spec.rb +5 -11
  173. data/spec/{fixtures/services/targeting_idea → sem4r/targeting_idea/fixtures}/get-req-all-options.xml +0 -0
  174. data/spec/{fixtures/services/targeting_idea → sem4r/targeting_idea/fixtures}/get-req.xml +9 -11
  175. data/spec/sem4r/targeting_idea/fixtures/get-res.xml +2276 -0
  176. data/spec/sem4r/targeting_idea/targeting_idea_selector_spec.rb +30 -11
  177. data/spec/sem4r/targeting_idea/targeting_idea_service_spec.rb +4 -3
  178. data/spec/sem4r/targeting_idea/targeting_idea_spec.rb +5 -4
  179. data/spec/sem4r/v13_account/account_account_extension_spec.rb +47 -0
  180. data/spec/sem4r/v13_account/account_service_spec.rb +6 -5
  181. data/spec/sem4r/v13_account/billing_address_spec.rb +40 -0
  182. data/spec/{fixtures/services/v13_account → sem4r/v13_account/fixtures}/get_account_info-req.xml +0 -0
  183. data/spec/{fixtures/services/v13_account → sem4r/v13_account/fixtures}/get_account_info-res.xml +0 -0
  184. data/spec/{fixtures/services/v13_account → sem4r/v13_account/fixtures}/get_client_accounts-req.xml +0 -0
  185. data/spec/{fixtures/services/v13_account → sem4r/v13_account/fixtures}/get_client_accounts-res.xml +0 -0
  186. data/spec/{fixtures/services/v13_report → sem4r/v13_report/fixtures}/get_all_jobs-req.xml +0 -0
  187. data/spec/{fixtures/services/v13_report → sem4r/v13_report/fixtures}/get_all_jobs-res.xml +2 -2
  188. data/spec/{fixtures/services/v13_report → sem4r/v13_report/fixtures}/schedule_report_job-req.xml +0 -0
  189. data/spec/{fixtures/services/v13_report → sem4r/v13_report/fixtures}/schedule_report_job-res.xml +0 -0
  190. data/spec/sem4r/v13_report/report_service_spec.rb +13 -11
  191. data/spec/sem4r/v13_report/report_spec.rb +4 -3
  192. data/spec/sem4r_stubs.rb +182 -0
  193. data/spec/soap_helpers/soap_attributes_spec.rb +129 -0
  194. metadata +225 -125
  195. data/spec/fixtures/services/info/get_unit_count-req.xml +0 -30
  196. data/spec/fixtures/services/info/get_unit_count-res.xml +0 -29
  197. data/spec/fixtures/services/targeting_idea/get-res.xml +0 -3601
  198. data/spec/sem4r/soap_attributes_spec.rb +0 -116
  199. data/spec/sem4r_spec_helper.rb +0 -353
@@ -28,7 +28,52 @@ module Sem4r
28
28
 
29
29
  attr_reader :id
30
30
 
31
- g_accessor :name
31
+ enum :ReportTypes, [
32
+ :KEYWORDS_PERFORMANCE_REPORT,
33
+ :AD_PERFORMANCE_REPORT,
34
+ :URL_PERFORMANCE_REPORT,
35
+ :ADGROUP_PERFORMANCE_REPORT,
36
+ :CAMPAIGN_PERFORMANCE_REPORT,
37
+ :ACCOUNT_PERFORMANCE_REPORT,
38
+ :SEARCH_QUERY_PERFORMANCE_REPORT,
39
+ :MANAGED_PLACEMENTS_PERFORMANCE_REPORT,
40
+ :AUTOMATIC_PLACEMENTS_PERFORMANCE_REPORT,
41
+ :CAMPAIGN_NEGATIVE_KEYWORDS_PERFORMANCE_REPORT,
42
+ :CAMPAIGN_NEGATIVE_PLACEMENTS_PERFORMANCE_REPORT,
43
+ ]
44
+
45
+ enum :DateRangeTypes, [
46
+ :TODAY,
47
+ :YESTERDAY,
48
+ :LAST_7_DAYS,
49
+ :LAST_WEEK,
50
+ :LAST_14_DAYS,
51
+ :LAST_30_DAYS,
52
+ :LAST_BUSINESS_WEEK,
53
+ :THIS_MONTH,
54
+ :LAST_MONTH,
55
+ :ALL_TIME,
56
+ :CUSTOM_DATE,
57
+ ]
58
+
59
+ enum :DownloadFormatTypes, [
60
+ :CSVFOREXCEL,
61
+ :CSV,
62
+ :TSV,
63
+ :XML,
64
+ :GZIPPED_CSV,
65
+ :GZIPPED_XML
66
+ ]
67
+
68
+ g_accessor :name, { :xpath => 'reportName' }
69
+ g_accessor :type, { :xpath => 'reportType', :values_in => :ReportTypes }
70
+ g_accessor :format, { :xpath => 'downloadFormat', :values_in => :DownloadFormatTypes }
71
+
72
+ g_accessor :date_range, { :values_in => :DateRangeTypes }
73
+ g_accessor :from
74
+ g_accessor :to
75
+
76
+ g_set_accessor :field
32
77
 
33
78
  def initialize(account, name = nil, &block)
34
79
  super( account.adwords, account.credentials )
@@ -46,27 +91,44 @@ module Sem4r
46
91
  end
47
92
 
48
93
  def to_s
49
- "'#{@name}'"
94
+ "#{@id}: '#{@name}'"
50
95
  end
51
96
 
52
97
  def to_xml(tag)
53
98
  builder = Builder::XmlMarkup.new
54
99
  builder.tag!(tag) do |t|
55
- t.reportName @name
100
+
101
+ t.id @id if @id
102
+ t.reportName @name if @name
103
+ t.reportType @type if @type
104
+ t.dateRangeType @date_range if @date_range
105
+ t.downloadFormat @format if @format
106
+
107
+ #TODO: non costruire selector se il contenuto e' vuoto utile per l'operazione di delete
108
+ t.selector do |t|
109
+ fields.each { |f| t.fields f}
110
+ if from and to
111
+ t.dateRange do |t|
112
+ t.min from
113
+ t.max to
114
+ end
115
+ end
116
+ end
117
+
56
118
  end
57
119
  end
58
120
 
59
-
60
121
  ###########################################################################
61
122
 
62
123
  def self.from_element(account, el)
63
124
  new(account) do
64
- @id = el.elements["id"].text.strip.to_i
65
- name el.elements["name"].text.strip
66
- status el.elements['status'].text.strip # ACTIVE, PAUSED, DELETED
67
- serving_status el.elements['servingStatus']
68
- start_date el.elements['startDate']
69
- end_date el.elements['endDate']
125
+
126
+ @id = el.at_xpath("id").text.strip.to_i
127
+ name el.at_xpath('reportName').text.strip
128
+ type el.at_xpath('reportType').text.strip
129
+ format el.at_xpath('downloadFormat').text.strip
130
+ # start_date el.at_xpath('startDate')
131
+ # end_date el.at_xpath('endDate')
70
132
  end
71
133
  end
72
134
 
@@ -76,13 +138,11 @@ module Sem4r
76
138
 
77
139
  def save
78
140
  unless @id
79
- op = ReportDefinitionOperation.new
80
- op.add(self)
81
- puts op.to_xml "operations"
141
+ op = ReportDefinitionOperation.new.add(self)
82
142
  soap_message = service.report_definition.mutate(credentials, op.to_xml("operations"))
83
143
  add_counters( soap_message.counters )
84
- rval = REXML::XPath.first( soap_message.response, "//mutateResponse/rval")
85
- id = REXML::XPath.match( rval, "value/id" ).first
144
+ rval = soap_message.response.at_xpath("//mutateResponse/rval")
145
+ id = rval.at_xpath("id" )
86
146
  @id = id.text.strip.to_i
87
147
  end
88
148
  self
@@ -0,0 +1,79 @@
1
+ # -------------------------------------------------------------------------
2
+ # Copyright (c) 2009-2010 Sem4r sem4ruby@gmail.com
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #
23
+ # -------------------------------------------------------------------------
24
+
25
+ module Sem4r
26
+
27
+ module ReportDefinitionAccountExtension
28
+
29
+ def report_definition_delete(report_definition_id)
30
+ report_definition = ReportDefinition.new(self)
31
+ report_definition.instance_eval { @id = report_definition_id }
32
+ op = ReportDefinitionOperation.new
33
+ op.remove(report_definition)
34
+ soap_message = service.report_definition.mutate(credentials, op.to_xml("operations"))
35
+ add_counters( soap_message.counters )
36
+ end
37
+
38
+ def report_fields
39
+ soap_message = service.report_definition.report_fields(credentials)
40
+ add_counters( soap_message.counters )
41
+ els = soap_message.response.xpath("//getReportFieldsResponse/rval")
42
+ els.map do |el|
43
+ ReportField.from_element(el)
44
+ end
45
+ end
46
+
47
+ def report_definition(&block)
48
+ ReportDefinition.new(self, &block)
49
+ end
50
+
51
+ def p_report_definitions(refresh = false)
52
+ report_definitions(refresh).each do |report_definition|
53
+ puts report_definition.to_s
54
+ end
55
+ end
56
+
57
+ def report_definitions(refresh = false)
58
+ _report_definitions unless @report_definitions and !refresh
59
+ @report_definitions
60
+ end
61
+
62
+ private
63
+
64
+ def _report_definitions
65
+ soap_message = service.report_definition.get(credentials, ReportDefinitionSelector.new.to_xml)
66
+ add_counters( soap_message.counters )
67
+ els = soap_message.response.xpath("//entries")
68
+ @report_definitions = els.map do |el|
69
+ ReportDefinition.from_element(self, el)
70
+ end
71
+ end
72
+
73
+ end
74
+
75
+ class Account
76
+ include ReportDefinitionAccountExtension
77
+ end
78
+
79
+ end
@@ -25,10 +25,12 @@
25
25
  module Sem4r
26
26
  class ReportDefinitionOperation < Operation
27
27
  def initialize(&block)
28
- @operation_type = "ReportDefinitionOperation"
28
+ @operation_type = "n1:ReportDefinitionOperation"
29
+ @namespace = 'xmlns:n1="https://adwords.google.com/api/adwords/cm/v201008"'
29
30
  if block_given?
30
31
  block.arity < 1 ? instance_eval(&block) : block.call(self)
31
32
  end
33
+ self
32
34
  end
33
35
  end
34
36
  end
@@ -28,15 +28,14 @@ module Sem4r
28
28
 
29
29
  def initialize(connector)
30
30
  @connector = connector
31
- @service_namespace = "https://adwords.google.com/api/adwords/cm/v201003"
32
- @header_namespace = @service_namespace
31
+ @header_namespace = "https://adwords.google.com/api/adwords/cm/v201008"
33
32
 
34
- @sandbox_service_url = "https://adwords-sandbox.google.com/api/adwords/cm/v201003/ReportDefinitionService"
33
+ @sandbox_service_url = "https://adwords-sandbox.google.com/api/adwords/cm/v201008/ReportDefinitionService"
35
34
  end
36
35
 
37
- soap_call_v2009 :get, :mutate => false
38
- soap_call_v2009 :getReportFields, :mutate => false
39
- soap_call_v2009 :mutate
36
+ soap_call_v2010 :get, :mutate => false
37
+ soap_call_v2010 :report_fields, :mutate => false
38
+ soap_call_v2010 :mutate
40
39
 
41
40
  private
42
41
 
@@ -44,7 +43,8 @@ module Sem4r
44
43
  "<get>#{xml}</get>"
45
44
  end
46
45
 
47
- def _get_report_fields
46
+ def _report_fields
47
+ "<getReportFields><reportType>URL_PERFORMANCE_REPORT</reportType></getReportFields>"
48
48
  end
49
49
 
50
50
  def _mutate(xml)
@@ -0,0 +1,57 @@
1
+ # -------------------------------------------------------------------
2
+ # Copyright (c) 2009-2010 Sem4r sem4ruby@gmail.com
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ # -------------------------------------------------------------------
23
+
24
+ module Sem4r
25
+
26
+ class ReportField
27
+ include SoapAttributes
28
+
29
+ attrs =[
30
+ :field_name,
31
+ :display_field_name,
32
+ :xml_attribute_name,
33
+ :field_type,
34
+ :can_select,
35
+ :can_filter,
36
+ ]
37
+
38
+ attrs.each do |s|
39
+ g_accessor s
40
+ end
41
+
42
+ def initialize(&block)
43
+ if block_given?
44
+ block.arity < 1 ? instance_eval(&block) : block.call(self)
45
+ end
46
+ end
47
+
48
+ def self.from_element(*args)
49
+ _from_element(*args)
50
+ end
51
+
52
+ def to_s
53
+ "#{@field_name} #{@field_type} #{@address_line2} #{@city}"
54
+ end
55
+
56
+ end
57
+ end
@@ -1,3 +1,4 @@
1
+ # -*- coding: utf-8 -*-
1
2
  # -------------------------------------------------------------------
2
3
  # Copyright (c) 2009 Sem4r sem4ruby@gmail.com
3
4
  #
@@ -0,0 +1,93 @@
1
+ # -------------------------------------------------------------------------
2
+ # Copyright (c) 2009-2010 Sem4r sem4ruby@gmail.com
3
+ #
4
+ # Permission is hereby granted, free of charge, to any person obtaining
5
+ # a copy of this software and associated documentation files (the
6
+ # "Software"), to deal in the Software without restriction, including
7
+ # without limitation the rights to use, copy, modify, merge, publish,
8
+ # distribute, sublicense, and/or sell copies of the Software, and to
9
+ # permit persons to whom the Software is furnished to do so, subject to
10
+ # the following conditions:
11
+ #
12
+ # The above copyright notice and this permission notice shall be
13
+ # included in all copies or substantial portions of the Software.
14
+ #
15
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
16
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
17
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
18
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
19
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
20
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
21
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
22
+ #
23
+ # -------------------------------------------------------------------------
24
+
25
+ module Sem4r
26
+
27
+ class HttpConnector
28
+ begin
29
+ require 'patron'
30
+ UsePatron = false
31
+ # $stderr.puts "Using patron gems"
32
+ rescue LoadError
33
+ UsePatron = false
34
+ # $stderr.puts "Patron not found, degrade to net/https"
35
+ end
36
+
37
+ if !UsePatron
38
+ require 'net/https'
39
+ require 'uri'
40
+ # $stderr.puts "Using standard net/https"
41
+ end
42
+
43
+ def get_sess_for_host(uri)
44
+ @sessions ||= {}
45
+
46
+ if UsePatron
47
+ url = uri.scheme + "://" + uri.host
48
+ sess = @sessions[url]
49
+ unless sess
50
+ sess = Patron::Session.new
51
+ # sess.connect_timeout = 3000 #millis
52
+ sess.timeout = 12
53
+ sess.base_url = url
54
+ sess.headers['User-Agent'] = 'ruby'
55
+ @sessions[url] = sess
56
+ end
57
+ sess
58
+ else
59
+ url = uri.scheme + "://" + uri.host
60
+ sess = @sessions[url]
61
+ unless sess
62
+ sess = Net::HTTP.new(uri.host, uri.port)
63
+ sess.use_ssl = (uri.scheme == "https")
64
+ @sessions[url] = sess
65
+ end
66
+ sess
67
+ end
68
+ end
69
+
70
+ def invalidate_sess(uri)
71
+ sess = @sessions[uri.host]
72
+ if sess
73
+ # sess.close
74
+ @sessions[uri.host] = nil
75
+ end
76
+ end
77
+
78
+ def download(url, path_name)
79
+
80
+ if UsePatron
81
+ uri = URI.parse(url)
82
+ sess = get_sess_for_host(uri)
83
+ sess.get_file(uri.path, path_name)
84
+ else
85
+ require 'open-uri'
86
+ data = open(url){ |f| f.read }
87
+ File.open(path_name, "w") { |f| f.write(data) }
88
+ end
89
+
90
+ end
91
+ end
92
+
93
+ end
@@ -44,7 +44,7 @@ module Sem4r
44
44
  end
45
45
 
46
46
  ###########################################################################
47
- # services v201003
47
+ # services v2010xx
48
48
 
49
49
  %w{ ad_extension_override
50
50
  ad_group
@@ -48,8 +48,8 @@ module Sem4r
48
48
  end
49
49
  end
50
50
 
51
- def helper_call_v2009(credentials, soap_body_content)
52
- soap_message = SoapMessageV2009.new(@connector, credentials)
51
+ def helper_call_v2010(credentials, soap_body_content)
52
+ soap_message = SoapMessageV2010.new(@connector, credentials)
53
53
  soap_message.init( @header_namespace, @service_namespace )
54
54
  soap_message.body = soap_body_content
55
55
  if credentials.sandbox?
@@ -59,6 +59,16 @@ module Sem4r
59
59
  end
60
60
  end
61
61
 
62
+ def helper_call_v2010_raw(credentials, xml_message)
63
+ soap_message = SoapMessageV2010.new(@connector, credentials)
64
+ soap_message.init( @header_namespace, @service_namespace )
65
+ if credentials.sandbox?
66
+ soap_message.send_raw(@sandbox_service_url, xml_message)
67
+ else
68
+ soap_message.send_raw(@production_service_url, xml_message)
69
+ end
70
+ end
71
+
62
72
  module ClassMethods
63
73
  def soap_call(helper_version, method, options = {})
64
74
  options.assert_valid_keys(:mutate)
@@ -72,7 +82,6 @@ module Sem4r
72
82
 
73
83
  # private_method_pars = args.join(",")
74
84
  # private_method_pars = ", #{private_method_pars}" unless private_method_pars.empty?
75
-
76
85
  rubystr =<<-EOFS
77
86
  define_method :#{method.to_sym} do |*args|
78
87
  credentials = args.shift
@@ -85,14 +94,27 @@ module Sem4r
85
94
  end
86
95
  EOFS
87
96
  eval rubystr
97
+
98
+ rubystr =<<-EOFS
99
+ define_method :#{(method.to_s + "_raw").to_sym} do |*args|
100
+ credentials = args.shift
101
+ soap_message = args.shift
102
+ if #{smutate}
103
+ #{helper_version}_raw(credentials, soap_message)
104
+ else
105
+ raise "mutate methods '#{method}' cannot be called on read_only profile"
106
+ end
107
+ end
108
+ EOFS
109
+ eval rubystr
88
110
  end
89
111
 
90
112
  def soap_call_v13(method, options = {})
91
113
  soap_call("helper_call_v13", method, options)
92
114
  end
93
115
 
94
- def soap_call_v2009(method, options = {})
95
- soap_call("helper_call_v2009", method, options)
116
+ def soap_call_v2010(method, options = {})
117
+ soap_call("helper_call_v2010", method, options)
96
118
  end
97
119
  end
98
120
 
@@ -23,148 +23,6 @@
23
23
 
24
24
  module Sem4r
25
25
 
26
- class HttpConnector
27
- begin
28
- require 'patron'
29
- UsePatron = false
30
- # $stderr.puts "Using patron gems"
31
- rescue LoadError
32
- UsePatron = false
33
- # $stderr.puts "Patron not found, degrade to net/https"
34
- end
35
-
36
- if !UsePatron
37
- require 'net/https'
38
- require 'uri'
39
- # $stderr.puts "Using standard net/https"
40
- end
41
-
42
- def get_sess_for_host(uri)
43
- @sessions ||= {}
44
-
45
- if UsePatron
46
- url = uri.scheme + "://" + uri.host
47
- sess = @sessions[url]
48
- unless sess
49
- sess = Patron::Session.new
50
- # sess.connect_timeout = 3000 #millis
51
- sess.timeout = 12
52
- sess.base_url = url
53
- sess.headers['User-Agent'] = 'ruby'
54
- @sessions[url] = sess
55
- end
56
- sess
57
- else
58
- url = uri.scheme + "://" + uri.host
59
- sess = @sessions[url]
60
- unless sess
61
- sess = Net::HTTP.new(uri.host, uri.port)
62
- sess.use_ssl = (uri.scheme == "https")
63
- @sessions[url] = sess
64
- end
65
- sess
66
- end
67
- end
68
-
69
- def invalidate_sess(uri)
70
- sess = @sessions[uri.host]
71
- if sess
72
- # sess.close
73
- @sessions[uri.host] = nil
74
- end
75
- end
76
-
77
- def download(url, path_name)
78
-
79
- if UsePatron
80
- uri = URI.parse(url)
81
- sess = get_sess_for_host(uri)
82
- sess.get_file(uri.path, path_name)
83
- else
84
- require 'open-uri'
85
- data = open(url){ |f| f.read }
86
- File.open(path_name, "w") { |f| f.write(data) }
87
- end
88
-
89
- end
90
- end
91
-
92
- module SoapDumper
93
-
94
- def initialize
95
- @soap_dump = false
96
- @soap_dump_log = nil
97
- end
98
-
99
- def dump_soap_options( dump_options )
100
- @soap_dump = true
101
- @soap_dump_log = nil
102
-
103
- if dump_options[:directory]
104
- @soap_dump_dir = dump_options[:directory]
105
- else
106
- @soap_dump_log = File.open( dump_options[:file], "w" )
107
- end
108
- @soap_dump_format = false || dump_options[:format]
109
- end
110
-
111
- def dump_soap(service_url, request_xml, response_xml)
112
- return unless @soap_dump
113
-
114
- %w{email password developerToken authToken clientEmail}.each do |tag|
115
- request_xml = request_xml.gsub(/<#{tag}([^>]*)>.*<\/#{tag}>/, "<#{tag}\\1>***censured***</#{tag}>")
116
- end
117
- response_xml.gsub(/<email[^>]*>.+<\/email>/, "<email>**censured**</email>")
118
-
119
- str =""
120
- str << "<!-- Post to '#{service_url}' -->\n"
121
-
122
- if !@soap_dump_format
123
- str << request_xml
124
- else
125
- xml_document = REXML::Document.new(request_xml)
126
- f = REXML::Formatters::Pretty.new
127
- out = String.new
128
- f.write(xml_document, out)
129
- str << out
130
- end
131
- str << "\n"
132
-
133
- str << "<!-- response -->\n"
134
- if !@soap_dump_format
135
- str << response_xml
136
- else
137
- xml_document = REXML::Document.new(response_xml)
138
- f = REXML::Formatters::Pretty.new
139
- out = String.new
140
- f.write(xml_document, out)
141
- str << out
142
- end
143
- str << "\n"
144
- str << "<!-- end -->"
145
-
146
- if @soap_dump_dir
147
- service = service_url.match(/\/([^\/]*)$/)[1]
148
- filename = Time.now.strftime "%Y%m%d-%H%M%S-%L-#{service}.log.xml"
149
-
150
- if not File.directory?(@soap_dump_dir)
151
- FileUtils.mkdir_p(@soap_dump_dir)
152
- end
153
-
154
- pathname = File.join(@soap_dump_dir, filename)
155
- File.open(pathname, "w") {|f|
156
- f.puts str
157
- }
158
- else
159
- @soap_dump_log.puts str
160
- @soap_dump_log.flush
161
- end
162
- end
163
-
164
- end
165
-
166
- #################
167
-
168
26
  class SoapConnector < HttpConnector
169
27
  include SoapDumper
170
28
 
@@ -272,13 +130,10 @@ module Sem4r
272
130
  end
273
131
 
274
132
  response_xml = response.body
275
- dump_soap(service_url, soap_message, response_xml)
133
+ dump_soap_request(service_url, soap_message)
134
+ dump_soap_response(service_url, response_xml)
276
135
  response_xml
277
136
  end
278
-
279
- private
280
-
281
-
282
137
  end
283
138
 
284
139
  end