sem4r 0.1.1

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 (187) hide show
  1. data/LICENSE +22 -0
  2. data/README.rdoc +74 -0
  3. data/Rakefile +126 -0
  4. data/VERSION.yml +5 -0
  5. data/bin/sem +34 -0
  6. data/config/sem4r.example.yml +51 -0
  7. data/examples_blog/2009-11-29-hello-world.rb +12 -0
  8. data/examples_blog/2009-12-12-create-campaign.rb +29 -0
  9. data/examples_blog/2010-02-06-constants-scope.rb +8 -0
  10. data/examples_blog/2010-02-07-ad-parameters.rb +47 -0
  11. data/examples_sem4r/01_get_account.rb +37 -0
  12. data/examples_sem4r/02_get_info.rb +32 -0
  13. data/examples_sem4r/03_list_ad.rb +47 -0
  14. data/examples_sem4r/04_list_keywords.rb +54 -0
  15. data/examples_sem4r/05_request_report.rb +51 -0
  16. data/examples_sem4r/05_request_report_2010.rb +40 -0
  17. data/examples_sem4r/06_create_campaigns.rb +86 -0
  18. data/examples_sem4r/07_create_campaigns_block.rb +99 -0
  19. data/examples_sem4r/07_create_campaigns_simple.rb +65 -0
  20. data/examples_sem4r/08_ad_params.rb +70 -0
  21. data/examples_sem4r/09_targeting_idea.rb +59 -0
  22. data/examples_sem4r/10_get_location.rb +28 -0
  23. data/examples_sem4r/11_submit_bulk_job.rb +82 -0
  24. data/examples_sem4r/12_list_bulk_job.rb +29 -0
  25. data/examples_sem4r/30_prune_empty_adgroup.rb +50 -0
  26. data/examples_sem4r/31_empty_accounts.rb +40 -0
  27. data/examples_sem4r/example_helper.rb +115 -0
  28. data/lib/sem4r/account.rb +349 -0
  29. data/lib/sem4r/ad_extension_override/ad_extension_override_service.rb +30 -0
  30. data/lib/sem4r/ad_group/ad_group.rb +340 -0
  31. data/lib/sem4r/ad_group/ad_group_bids.rb +170 -0
  32. data/lib/sem4r/ad_group/ad_group_service.rb +75 -0
  33. data/lib/sem4r/ad_group/mobile_ad_image.rb +33 -0
  34. data/lib/sem4r/ad_group_ad/ad_group_ad.rb +98 -0
  35. data/lib/sem4r/ad_group_ad/ad_group_ad_operations.rb +38 -0
  36. data/lib/sem4r/ad_group_ad/ad_group_ad_service.rb +56 -0
  37. data/lib/sem4r/ad_group_ad/ad_group_mobile_ad.rb +137 -0
  38. data/lib/sem4r/ad_group_ad/ad_group_text_ad.rb +98 -0
  39. data/lib/sem4r/ad_group_criterion/ad_group_criterion.rb +144 -0
  40. data/lib/sem4r/ad_group_criterion/ad_group_criterion_bids.rb +115 -0
  41. data/lib/sem4r/ad_group_criterion/ad_group_criterion_operations.rb +35 -0
  42. data/lib/sem4r/ad_group_criterion/ad_group_criterion_service.rb +58 -0
  43. data/lib/sem4r/ad_group_criterion/criterion.rb +67 -0
  44. data/lib/sem4r/ad_group_criterion/criterion_keyword.rb +80 -0
  45. data/lib/sem4r/ad_group_criterion/criterion_placement.rb +66 -0
  46. data/lib/sem4r/ad_param/ad_param.rb +96 -0
  47. data/lib/sem4r/ad_param/ad_param_operation.rb +34 -0
  48. data/lib/sem4r/ad_param/ad_param_service.rb +59 -0
  49. data/lib/sem4r/adwords.rb +242 -0
  50. data/lib/sem4r/api_counters.rb +7 -0
  51. data/lib/sem4r/base.rb +43 -0
  52. data/lib/sem4r/bulk_mutate_job/bulk_mutate_job.rb +108 -0
  53. data/lib/sem4r/bulk_mutate_job/bulk_mutate_job_selector.rb +56 -0
  54. data/lib/sem4r/bulk_mutate_job/bulk_mutate_job_service.rb +57 -0
  55. data/lib/sem4r/bulk_mutate_job/job_operations.rb +35 -0
  56. data/lib/sem4r/campaign/campaign.rb +193 -0
  57. data/lib/sem4r/campaign/campaign_service.rb +91 -0
  58. data/lib/sem4r/campaign_criterion/campaign_criterion_service.rb +30 -0
  59. data/lib/sem4r/campaign_target/campaign_target_service.rb +30 -0
  60. data/lib/sem4r/cli/cli_command.rb +101 -0
  61. data/lib/sem4r/cli/cli_commands.rb +60 -0
  62. data/lib/sem4r/cli/cli_common_args.rb +293 -0
  63. data/lib/sem4r/cli/cli_download_report.rb +81 -0
  64. data/lib/sem4r/cli/cli_helpers.rb +57 -0
  65. data/lib/sem4r/cli/cli_ideas.rb +100 -0
  66. data/lib/sem4r/cli/cli_list_ads.rb +74 -0
  67. data/lib/sem4r/cli/cli_list_keywords.rb +76 -0
  68. data/lib/sem4r/cli/cli_request_report.rb +104 -0
  69. data/lib/sem4r/cli/cli_sem.rb +64 -0
  70. data/lib/sem4r/common/operation.rb +78 -0
  71. data/lib/sem4r/credentials.rb +86 -0
  72. data/lib/sem4r/extensions.rb +62 -0
  73. data/lib/sem4r/geo_location/geo_location_service.rb +59 -0
  74. data/lib/sem4r/info/info_service.rb +115 -0
  75. data/lib/sem4r/report_definition/report_definition.rb +104 -0
  76. data/lib/sem4r/report_definition/report_definition_operation.rb +34 -0
  77. data/lib/sem4r/report_definition/report_definition_selector.rb +31 -0
  78. data/lib/sem4r/report_definition/report_definition_service.rb +55 -0
  79. data/lib/sem4r/sem4r_error.rb +28 -0
  80. data/lib/sem4r/services/service.rb +74 -0
  81. data/lib/sem4r/services/soap_call.rb +100 -0
  82. data/lib/sem4r/services/soap_connector.rb +284 -0
  83. data/lib/sem4r/services/soap_error.rb +38 -0
  84. data/lib/sem4r/services/soap_message_v13.rb +129 -0
  85. data/lib/sem4r/services/soap_message_v2009.rb +170 -0
  86. data/lib/sem4r/soap_attributes.rb +141 -0
  87. data/lib/sem4r/targeting_idea/targeting_idea.rb +158 -0
  88. data/lib/sem4r/targeting_idea/targeting_idea_selector.rb +200 -0
  89. data/lib/sem4r/targeting_idea/targeting_idea_service.rb +51 -0
  90. data/lib/sem4r/v13_account/account_service.rb +54 -0
  91. data/lib/sem4r/v13_account/billing_address.rb +67 -0
  92. data/lib/sem4r/v13_report/report.rb +185 -0
  93. data/lib/sem4r/v13_report/report_job.rb +51 -0
  94. data/lib/sem4r/v13_report/report_service.rb +89 -0
  95. data/lib/sem4r/v13_traffic_estimator/traffic_estimator_service.rb +30 -0
  96. data/lib/sem4r.rb +142 -0
  97. data/lib/sem4r_cli.rb +40 -0
  98. data/sem4r.gemspec +247 -0
  99. data/spec/aggregates_spec_helper.rb +59 -0
  100. data/spec/fixtures/sem4r.example.yml +26 -0
  101. data/spec/fixtures/services/ad_group/get-first-req.xml +28 -0
  102. data/spec/fixtures/services/ad_group/get-first-res.xml +91 -0
  103. data/spec/fixtures/services/ad_group/get-manual-cpm-bids-req.xml +106 -0
  104. data/spec/fixtures/services/ad_group/get-manual-cpm-bids-res.xml +75 -0
  105. data/spec/fixtures/services/ad_group/mutate_add-req.xml +52 -0
  106. data/spec/fixtures/services/ad_group/mutate_add-res.xml +33 -0
  107. data/spec/fixtures/services/ad_group_ad/get_mobile_ad-req.xml +28 -0
  108. data/spec/fixtures/services/ad_group_ad/get_mobile_ad-res.xml +194 -0
  109. data/spec/fixtures/services/ad_group_ad/get_text_ad-req.xml +29 -0
  110. data/spec/fixtures/services/ad_group_ad/get_text_ad-res.xml +55 -0
  111. data/spec/fixtures/services/ad_group_ad/mutate_add_mobile_ad-req.xml +50 -0
  112. data/spec/fixtures/services/ad_group_ad/mutate_add_mobile_ad-res.xml +42 -0
  113. data/spec/fixtures/services/ad_group_ad/mutate_add_text_ad-req.xml +37 -0
  114. data/spec/fixtures/services/ad_group_ad/mutate_add_text_ad-res.xml +32 -0
  115. data/spec/fixtures/services/ad_group_ad/mutate_add_two_criterions-req.xml +83 -0
  116. data/spec/fixtures/services/ad_group_ad/mutate_add_two_criterions-res.xml +95 -0
  117. data/spec/fixtures/services/ad_group_criterion/get-req.xml +28 -0
  118. data/spec/fixtures/services/ad_group_criterion/get-res.xml +242 -0
  119. data/spec/fixtures/services/ad_group_criterion/mutate_add_criterion_keyword-req.xml +48 -0
  120. data/spec/fixtures/services/ad_group_criterion/mutate_add_criterion_keyword-res.xml +47 -0
  121. data/spec/fixtures/services/ad_group_criterion/mutate_add_criterion_placement-req.xml +35 -0
  122. data/spec/fixtures/services/ad_group_criterion/mutate_add_criterion_placement-res.xml +32 -0
  123. data/spec/fixtures/services/ad_group_criterion/mutate_add_negative_keyword-req.xml +37 -0
  124. data/spec/fixtures/services/ad_group_criterion/mutate_add_negative_keyword-res.xml +51 -0
  125. data/spec/fixtures/services/ad_param/mutate_set-req.xml +43 -0
  126. data/spec/fixtures/services/ad_param/mutate_set-res.xml +29 -0
  127. data/spec/fixtures/services/bulk_mutate_job/get-req.xml +36 -0
  128. data/spec/fixtures/services/bulk_mutate_job/get-res.xml +54 -0
  129. data/spec/fixtures/services/bulk_mutate_job/mutate-req.xml +69 -0
  130. data/spec/fixtures/services/bulk_mutate_job/mutate-res.xml +48 -0
  131. data/spec/fixtures/services/campaign/get-req.xml +37 -0
  132. data/spec/fixtures/services/campaign/get-res.xml +1986 -0
  133. data/spec/fixtures/services/campaign/mutate_add-req.xml +37 -0
  134. data/spec/fixtures/services/campaign/mutate_add-res.xml +42 -0
  135. data/spec/fixtures/services/error.xml +28 -0
  136. data/spec/fixtures/services/info/get_unit_count-req.xml +30 -0
  137. data/spec/fixtures/services/info/get_unit_count-res.xml +29 -0
  138. data/spec/fixtures/services/report_definition/mutate_add-req.xml +24 -0
  139. data/spec/fixtures/services/report_definition/mutate_add-req_orig.xml +45 -0
  140. data/spec/fixtures/services/targeting_idea/get-req-all-options.xml +57 -0
  141. data/spec/fixtures/services/targeting_idea/get-req.xml +60 -0
  142. data/spec/fixtures/services/targeting_idea/get-res.xml +3601 -0
  143. data/spec/fixtures/services/v13_account/get_account_info-req.xml +23 -0
  144. data/spec/fixtures/services/v13_account/get_account_info-res.xml +54 -0
  145. data/spec/fixtures/services/v13_account/get_client_accounts-req.xml +22 -0
  146. data/spec/fixtures/services/v13_account/get_client_accounts-res.xml +37 -0
  147. data/spec/fixtures/services/v13_report/get_all_jobs-req.xml +21 -0
  148. data/spec/fixtures/services/v13_report/get_all_jobs-res.xml +109 -0
  149. data/spec/fixtures/services/v13_report/schedule_report_job-req.xml +56 -0
  150. data/spec/fixtures/services/v13_report/schedule_report_job-res.xml +24 -0
  151. data/spec/sem4r/account_spec.rb +86 -0
  152. data/spec/sem4r/ad_group/ad_group_bids_spec.rb +67 -0
  153. data/spec/sem4r/ad_group/ad_group_service_spec.rb +66 -0
  154. data/spec/sem4r/ad_group/ad_group_spec.rb +212 -0
  155. data/spec/sem4r/ad_group_ad/ad_group_ad_operation_spec.rb +88 -0
  156. data/spec/sem4r/ad_group_ad/ad_group_ad_service_spec.rb +55 -0
  157. data/spec/sem4r/ad_group_ad/ad_group_ad_spec.rb +173 -0
  158. data/spec/sem4r/ad_group_criterion/ad_group_criterion_bids_spec.rb +60 -0
  159. data/spec/sem4r/ad_group_criterion/ad_group_criterion_service_spec.rb +55 -0
  160. data/spec/sem4r/ad_group_criterion/ad_group_criterion_spec.rb +103 -0
  161. data/spec/sem4r/ad_group_criterion/criterion_spec.rb +85 -0
  162. data/spec/sem4r/ad_param/ad_param_service_spec.rb +55 -0
  163. data/spec/sem4r/ad_param/ad_param_spec.rb +59 -0
  164. data/spec/sem4r/adwords_spec.rb +110 -0
  165. data/spec/sem4r/bulk_mutate_job/bulk_mutate_job_service_spec.rb +63 -0
  166. data/spec/sem4r/bulk_mutate_job/bulk_mutate_job_spec.rb +69 -0
  167. data/spec/sem4r/bulk_mutate_job/job_operation_spec.rb +48 -0
  168. data/spec/sem4r/campaign/campaign_service_spec.rb +66 -0
  169. data/spec/sem4r/campaign/campaign_spec.rb +105 -0
  170. data/spec/sem4r/cli/cli_spec.rb +71 -0
  171. data/spec/sem4r/credentials_spec.rb +65 -0
  172. data/spec/sem4r/report_definition/report_definition_service_spec.rb +44 -0
  173. data/spec/sem4r/report_definition/report_definition_spec.rb +105 -0
  174. data/spec/sem4r/rexml_parsing_spec.rb +103 -0
  175. data/spec/sem4r/services/service_spec.rb +36 -0
  176. data/spec/sem4r/services/soap_call_spec.rb +115 -0
  177. data/spec/sem4r/services/soap_message_v13_spec.rb +54 -0
  178. data/spec/sem4r/soap_attributes_spec.rb +116 -0
  179. data/spec/sem4r/targeting_idea/targeting_idea_selector_spec.rb +120 -0
  180. data/spec/sem4r/targeting_idea/targeting_idea_service_spec.rb +44 -0
  181. data/spec/sem4r/targeting_idea/targeting_idea_spec.rb +53 -0
  182. data/spec/sem4r/v13_account/account_service_spec.rb +60 -0
  183. data/spec/sem4r/v13_report/report_service_spec.rb +104 -0
  184. data/spec/sem4r/v13_report/report_spec.rb +79 -0
  185. data/spec/sem4r_spec_helper.rb +353 -0
  186. data/spec/spec_helper.rb +12 -0
  187. metadata +375 -0
@@ -0,0 +1,193 @@
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 Campaign < Base
27
+
28
+ enum :Statuses, [
29
+ :ACTIVE,
30
+ :PAUSED,
31
+ :DELETED
32
+ ]
33
+
34
+ enum :ServingStatues, [
35
+ :SERVING,
36
+ :NONE,
37
+ :ENDED,
38
+ :PENDING,
39
+ :SUSPENDED
40
+ ]
41
+
42
+ attr_reader :id
43
+ attr_reader :account
44
+
45
+ g_accessor :name
46
+ g_accessor :status, {:default => "PAUSED"}
47
+ g_accessor :serving_status
48
+ g_accessor :start_date
49
+ g_accessor :end_date
50
+
51
+ def initialize(account, name = nil, &block)
52
+ super( account.adwords, account.credentials )
53
+ @account = account
54
+ @ad_groups = nil
55
+ self.name = name
56
+ if block_given?
57
+ @inside_initialize = true
58
+ block.arity < 1 ? instance_eval(&block) : block.call(self)
59
+ save
60
+ end
61
+ @inside_initialize = false
62
+ end
63
+
64
+ def inside_initialize?
65
+ @inside_initialize
66
+ end
67
+
68
+ def to_s
69
+ "#{@id} '#{@name}' (#{@status})"
70
+ end
71
+
72
+ def to_xml
73
+ <<-EOS
74
+ <name>#{name}</name>
75
+ <status>#{status}</status>
76
+
77
+ <budget>
78
+ <period>DAILY</period>
79
+ <amount xsi:type="Money">
80
+ <microAmount>50000000</microAmount>
81
+ </amount>
82
+ <deliveryMethod>STANDARD</deliveryMethod>
83
+ </budget>
84
+
85
+ <biddingStrategy xsi:type="#{bidding_strategy}"></biddingStrategy>
86
+
87
+ EOS
88
+ end
89
+
90
+ ###########################################################################
91
+
92
+ def self.from_element(account, el)
93
+ new(account) do
94
+ @id = el.elements["id"].text.strip.to_i
95
+ name el.elements["name"].text.strip
96
+ status el.elements['status'].text.strip # ACTIVE, PAUSED, DELETED
97
+ serving_status el.elements['servingStatus']
98
+ start_date el.elements['startDate']
99
+ end_date el.elements['endDate']
100
+ end
101
+ end
102
+
103
+ def self.create(account, &block)
104
+ new(account, &block).save
105
+ end
106
+
107
+ def save
108
+ unless @id
109
+ soap_message = service.campaign.create(credentials, to_xml)
110
+ add_counters( soap_message.counters )
111
+ rval = REXML::XPath.first( soap_message.response, "//mutateResponse/rval")
112
+ id = REXML::XPath.match( rval, "value/id" ).first
113
+ @id = id.text.strip.to_i
114
+ end
115
+ self
116
+ end
117
+
118
+ def delete
119
+ soap_message = service.campaign.delete(credentials, @id)
120
+ add_counters( soap_message.counters )
121
+ @id = -1 # logical delete
122
+ end
123
+
124
+ ###########################################################################
125
+
126
+ def empty?
127
+ _ad_groups.empty?
128
+ end
129
+
130
+ ###########################################################################
131
+ # bidding_strategy
132
+
133
+ # ManualCPC, ManualCPM
134
+ def bidding_strategy(strategy = nil)
135
+ @bidding_strategy = strategy if strategy
136
+ @bidding_strategy ||= "ManualCPC"
137
+ @bidding_strategy
138
+ end
139
+
140
+ ###########################################################################
141
+ # ad_group management
142
+
143
+ def ad_group(name = nil, &block)
144
+ save
145
+ ad_group = AdGroup.new(self, name, &block)
146
+ ad_group.save
147
+ @ad_groups ||= []
148
+ @ad_groups.push(ad_group)
149
+ ad_group
150
+ end
151
+
152
+ def ad_groups(refresh = false, opts = {})
153
+ if refresh.respond_to?(:keys)
154
+ opts = refresh
155
+ refresh = false
156
+ end
157
+ _ad_groups unless @ad_groups and !refresh
158
+ # statuses = [:ACTIVE, :PAUSED]
159
+ # @ad_groups.select do |ad_group|
160
+ # statuses.include?(ad_group.status)
161
+ # end
162
+ @ad_groups
163
+ end
164
+
165
+ def p_ad_groups(refresh = false, opts = {})
166
+ if refresh.respond_to?(:keys)
167
+ opts = refresh
168
+ refresh = false
169
+ end
170
+ cs = ad_groups(refresh, opts)
171
+ puts "#{cs.length} ad_groups"
172
+ cs.each do |ad_group|
173
+ puts ad_group.to_s
174
+ end
175
+ self
176
+ end
177
+
178
+ private
179
+
180
+ def _ad_groups
181
+ soap_message = service.ad_group.all(credentials, @id)
182
+ add_counters( soap_message.counters )
183
+ rval = REXML::XPath.first( soap_message.response, "//getResponse/rval")
184
+ els = REXML::XPath.match( rval, "entries")
185
+ @ad_groups = els.map do |el|
186
+ AdGroup.from_element(self, el)
187
+ end
188
+ end
189
+
190
+ ###########################################################################
191
+
192
+ end
193
+ end
@@ -0,0 +1,91 @@
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 CampaignService
27
+ include SoapCall
28
+
29
+ def initialize(connector)
30
+ @connector = connector
31
+ @service_namespace = "https://adwords.google.com/api/adwords/cm/v201003"
32
+ @header_namespace = @service_namespace
33
+
34
+ @sandbox_service_url = "https://adwords-sandbox.google.com/api/adwords/cm/v201003/CampaignService"
35
+ end
36
+
37
+ soap_call_v2009 :all, :mutate => false
38
+ soap_call_v2009 :create
39
+ soap_call_v2009 :delete
40
+
41
+ private
42
+
43
+ def _all(statuses = [Campaign::ACTIVE, Campaign::PAUSED])
44
+ str = <<-EOFS
45
+ <get xmlns="#{@service_namespace}">
46
+ <selector>
47
+ EOFS
48
+ statuses.each do |s|
49
+ str += "<campaignStatuses>#{s}</campaignStatuses>"
50
+ end
51
+ str += <<-EOFS
52
+ <statsSelector>
53
+ <dateRange>
54
+ <min>20090101</min>
55
+ <max>20091231</max>
56
+ </dateRange>
57
+ </statsSelector>
58
+ </selector>
59
+ </get>
60
+ EOFS
61
+ end
62
+
63
+ def _create(xml)
64
+ <<-EOFS
65
+ <mutate xmlns="#{@service_namespace}">
66
+ <operations xsi:type="CampaignOperation">
67
+ <operator>ADD</operator>
68
+ <operand>
69
+ #{xml}
70
+ </operand>
71
+ </operations>
72
+ </mutate>
73
+ EOFS
74
+ end
75
+
76
+ def _delete(id)
77
+ <<-EOFS
78
+ <mutate xmlns="#{@service_namespace}">
79
+ <operations xsi:type="CampaignOperation">
80
+ <operator>SET</operator>
81
+ <operand>
82
+ <id>#{id}</id>
83
+ <status>DELETED</status>
84
+ </operand>
85
+ </operations>
86
+ </mutate>
87
+ EOFS
88
+ end
89
+
90
+ end
91
+ end
@@ -0,0 +1,30 @@
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
+ class CampaignCriterionService
26
+ def initialize
27
+
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,30 @@
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
+ class CampaignTargetService
26
+ def initialize
27
+
28
+ end
29
+ end
30
+ end
@@ -0,0 +1,101 @@
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 CliCommand
28
+
29
+ class << self
30
+
31
+ def inherited(base)
32
+ @command_list ||= []
33
+ @command_list << base
34
+ end
35
+
36
+ def commands
37
+ return @commands if @commands
38
+ @commands = {}
39
+ @command_list.each { |cmd| @commands[cmd.command] = cmd }
40
+ @commands
41
+ end
42
+
43
+ def split_args(argv)
44
+ idx = argv.find_index { |e| commands.key?(e) }
45
+ if idx
46
+ common_args = argv[0,idx]
47
+ command = argv[idx]
48
+ command_args = argv[idx+1..-1]
49
+ return [common_args, command, command_args]
50
+ else
51
+ return [argv, nil, nil]
52
+ end
53
+ end
54
+
55
+ def define_command(command_name, description_str, &block)
56
+
57
+ unless block_given?
58
+ raise "define_command: missing block"
59
+ end
60
+
61
+ cls = Class.new(CliCommand) do
62
+ def initialize(common_args)
63
+ @common_args = common_args
64
+ end
65
+
66
+ def opt_parser(options)
67
+ opt_parser = OptionParser.new
68
+ opt_parser.banner= "#{self.class.description}"
69
+ opt_parser.on("-h", "--help", "show this message") do
70
+ puts opt_parser
71
+ options.exit = true
72
+ end
73
+ end
74
+
75
+ define_method("parse_and_run") do |argv|
76
+ options = OpenStruct.new
77
+ opt_parser(options).parse( argv )
78
+ return false if options.exit
79
+ account = @common_args.account
80
+ unless account
81
+ puts "select an account!"
82
+ false
83
+ else
84
+ return block.call(account)
85
+ end
86
+ end
87
+ end
88
+
89
+ s = class << cls; self; end
90
+ s.class_eval do
91
+ define_method("command") { command_name }
92
+ define_method("description") { description_str }
93
+ end
94
+ cls
95
+ end
96
+
97
+ end
98
+
99
+ end
100
+
101
+ end
@@ -0,0 +1,60 @@
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
+ CliListClient = CliCommand.define_command("clients", "list clients account") do |account|
28
+ puts account.adwords.to_s
29
+ puts account.to_s
30
+ account.p_client_accounts
31
+ account.adwords.p_counters
32
+ true
33
+ end
34
+
35
+ CliListReport = CliCommand.define_command("reports", "list reports") do |account|
36
+ report(account.reports, :id, :name, :status)
37
+ account.adwords.p_counters
38
+ true
39
+ end
40
+
41
+ CliInfo = CliCommand.define_command("info", "account info") do |account|
42
+ account.p_info
43
+ items = (Account::UsageTypes - [Account::METHOD_COST]).map do |usage_type|
44
+ n = account.year_unit_cost(usage_type)
45
+ # puts "#{usage_type} -> #{n}"
46
+ OpenStruct.new(:usage_type => usage_type, :n => n)
47
+ end
48
+ report(items, :usage_type, :n)
49
+ account.adwords.p_counters
50
+ true
51
+ end
52
+
53
+ CliCampaign = CliCommand.define_command("campaigns", "list campaigns") do |account|
54
+ puts "listing campaings in #{account}"
55
+ report( account.campaigns, :id, :name, :status )
56
+ account.adwords.p_counters
57
+ true
58
+ end
59
+
60
+ end