sem4r 0.1.3 → 0.1.5
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.
- data/.gemtest +0 -0
- data/Gemfile +2 -22
- data/Gemfile.lock +43 -20
- data/Rakefile +4 -2
- data/bin/sem +2 -6
- data/lib/sem4r/adwords.rb +8 -142
- data/lib/sem4r/campaign/campaign_account_extension.rb +4 -5
- data/lib/sem4r/profile.rb +173 -0
- data/lib/sem4r/sem4r_utilities.rb +113 -0
- data/lib/sem4r/v13_report/report.rb +5 -0
- data/lib/sem4r/version.rb +27 -0
- data/lib/sem4r.rb +5 -26
- data/lib/sem4r_cli/cli_sem.rb +116 -170
- data/lib/sem4r_cli/commands/{cli_ads.rb → cmd_ads.rb} +4 -4
- data/lib/sem4r_cli/commands/{cli_campaign.rb → cmd_campaign.rb} +7 -7
- data/lib/sem4r_cli/commands/{cli_clients.rb → cmd_clients.rb} +4 -5
- data/lib/sem4r_cli/commands/{cli_ideas.rb → cmd_ideas.rb} +7 -5
- data/lib/sem4r_cli/commands/{cli_info.rb → cmd_info.rb} +6 -6
- data/lib/sem4r_cli/commands/{cli_job.rb → cmd_job.rb} +4 -2
- data/lib/sem4r_cli/commands/{cli_keywords.rb → cmd_keywords.rb} +4 -4
- data/lib/sem4r_cli/commands/{cli_profile.rb → cmd_profile.rb} +23 -19
- data/lib/sem4r_cli/commands/{cli_repdef.rb → cmd_repdef.rb} +6 -4
- data/lib/sem4r_cli/commands/{cli_report.rb → cmd_report.rb} +8 -6
- data/lib/sem4r_cli.rb +6 -4
- data/lib/sem4r_debug_client/client.rb +200 -0
- data/lib/sem4r_debug_client.rb +31 -0
- data/lib/sem4r_sinatra/cli_server.rb +45 -0
- data/lib/sem4r_sinatra/helpers.rb +60 -0
- data/lib/sem4r_sinatra/web_server.rb +46 -0
- data/lib/sem4r_sinatra.rb +13 -0
- data/lib/sem4r_soap/http_connector.rb +5 -6
- data/lib/sem4r_soap/soap_dumper.rb +3 -14
- data/lib/sem4r_soap/soap_service.rb +5 -5
- data/lib/sem4r_soap/soap_service_v2010.rb +2 -2
- data/lib/sem4r_soap.rb +24 -0
- data/sem4r.gemspec +75 -313
- data/spec/fixtures/password.example.yml +5 -3
- data/spec/helpers/rspec_matchers.rb +2 -19
- data/spec/helpers/rspec_sem4r_helper.rb +25 -9
- data/spec/rspec_helper.rb +7 -0
- data/spec/sem4r/ad_group/ad_group_spec.rb +2 -3
- data/spec/sem4r/ad_group_ad/fixtures/mutate_add_mobile_ad-req.xml +8 -11
- data/spec/sem4r/ad_group_criterion/fixtures/mutate_add_negative_keyword-req.xml +1 -3
- data/spec/sem4r/adwords_spec.rb +0 -5
- data/spec/sem4r/bulk_mutate_job/fixtures/get-list_job-req.xml +18 -33
- data/spec/sem4r/bulk_mutate_job/fixtures/get-list_job-res.xml +232 -416
- data/spec/sem4r/bulk_mutate_job/fixtures/mutate-add_job-req.xml +55 -104
- data/spec/sem4r/bulk_mutate_job/fixtures/mutate-add_job-res.xml +25 -47
- data/spec/sem4r/geo_location/fixtures/get-req.xml +23 -40
- data/spec/sem4r/geo_location/fixtures/get-res.xml +31 -59
- data/spec/sem4r/info/fixtures/get-req.xml +19 -32
- data/spec/sem4r/info/fixtures/get-res.xml +16 -26
- data/spec/sem4r/profiles_spec.rb +52 -0
- data/spec/sem4r/report_definition/fixtures/get-list-repdef-req.xml +13 -20
- data/spec/sem4r/report_definition/fixtures/get-list-repdef-res.xml +34 -72
- data/spec/sem4r/report_definition/fixtures/getReportFields-req.xml +13 -22
- data/spec/sem4r/report_definition/fixtures/getReportFields-res.xml +476 -1198
- data/spec/sem4r/report_definition/fixtures/mutate-add-report-req.xml +30 -61
- data/spec/sem4r/report_definition/fixtures/mutate-add-report-res.xml +31 -67
- data/spec/sem4r/report_definition/report_definition_spec.rb +1 -1
- data/spec/sem4r/v13_report/fixtures/schedule_report_job-req.xml +11 -33
- data/spec/sem4r_cli/cli_spec.rb +4 -22
- data/tasks/sem4r.rake +0 -3
- data/tasks/yard.rake +2 -2
- metadata +188 -177
- data/VERSION.yml +0 -5
- data/lib/sem4r_cli/cli_helpers.rb +0 -59
- data/lib/sem4r_cli/cli_mini_framework.rb +0 -147
- data/tasks/jeweler.rake +0 -66
data/.gemtest
ADDED
File without changes
|
data/Gemfile
CHANGED
@@ -1,22 +1,2 @@
|
|
1
|
-
source
|
2
|
-
|
3
|
-
gem "builder"
|
4
|
-
gem "nokogiri"
|
5
|
-
gem "httpclient"
|
6
|
-
gem 'highline', :require => 'highline/import'
|
7
|
-
|
8
|
-
group :development do
|
9
|
-
gem "jeweler"
|
10
|
-
gem "rake"
|
11
|
-
gem "yard"
|
12
|
-
gem "bundler" # funny!
|
13
|
-
end
|
14
|
-
|
15
|
-
group :test do
|
16
|
-
gem "differ"
|
17
|
-
gem "rspec"
|
18
|
-
end
|
19
|
-
|
20
|
-
#platforms :jruby do
|
21
|
-
# gem 'jruby-openssl'
|
22
|
-
#end
|
1
|
+
source "http://rubygems.org"
|
2
|
+
gemspec
|
data/Gemfile.lock
CHANGED
@@ -1,42 +1,65 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
sem4r (0.1.4)
|
5
|
+
builder
|
6
|
+
builder
|
7
|
+
haml
|
8
|
+
highline
|
9
|
+
httpclient
|
10
|
+
nokogiri
|
11
|
+
nokogiri
|
12
|
+
optparse-command (= 0.1.6)
|
13
|
+
signet
|
14
|
+
sinatra
|
15
|
+
|
1
16
|
GEM
|
2
17
|
remote: http://rubygems.org/
|
3
18
|
specs:
|
19
|
+
addressable (2.2.4)
|
4
20
|
builder (3.0.0)
|
5
21
|
diff-lcs (1.1.2)
|
6
|
-
differ (0.1.
|
7
|
-
|
22
|
+
differ (0.1.2)
|
23
|
+
haml (3.0.25)
|
8
24
|
highline (1.6.1)
|
9
|
-
|
10
|
-
|
11
|
-
|
12
|
-
|
13
|
-
|
25
|
+
httpadapter (0.2.1)
|
26
|
+
addressable (~> 2.2.0)
|
27
|
+
httpclient (2.1.6.1)
|
28
|
+
json (1.5.1)
|
29
|
+
json (1.5.1-java)
|
14
30
|
nokogiri (1.4.4)
|
15
31
|
nokogiri (1.4.4-java)
|
16
32
|
weakling (>= 0.0.3)
|
33
|
+
optparse-command (0.1.6)
|
34
|
+
rack (1.2.1)
|
17
35
|
rake (0.8.7)
|
18
|
-
rspec (2.
|
19
|
-
rspec-core (~> 2.
|
20
|
-
rspec-expectations (~> 2.
|
21
|
-
rspec-mocks (~> 2.
|
22
|
-
rspec-core (2.
|
23
|
-
rspec-expectations (2.
|
36
|
+
rspec (2.5.0)
|
37
|
+
rspec-core (~> 2.5.0)
|
38
|
+
rspec-expectations (~> 2.5.0)
|
39
|
+
rspec-mocks (~> 2.5.0)
|
40
|
+
rspec-core (2.5.1)
|
41
|
+
rspec-expectations (2.5.0)
|
24
42
|
diff-lcs (~> 1.1.2)
|
25
|
-
rspec-mocks (2.
|
43
|
+
rspec-mocks (2.5.0)
|
44
|
+
signet (0.2.0)
|
45
|
+
addressable (~> 2.2.1)
|
46
|
+
httpadapter (~> 0.2.0)
|
47
|
+
json (~> 1.5.0)
|
48
|
+
sinatra (1.1.3)
|
49
|
+
rack (~> 1.1)
|
50
|
+
tilt (>= 1.2.2, < 2.0)
|
51
|
+
tilt (1.2.2)
|
26
52
|
weakling (0.0.4-java)
|
27
|
-
yard (0.6.
|
53
|
+
yard (0.6.4)
|
28
54
|
|
29
55
|
PLATFORMS
|
30
56
|
java
|
31
57
|
ruby
|
32
58
|
|
33
59
|
DEPENDENCIES
|
34
|
-
|
60
|
+
bundler
|
35
61
|
differ
|
36
|
-
highline
|
37
|
-
httpclient
|
38
|
-
jeweler
|
39
|
-
nokogiri
|
40
62
|
rake
|
41
63
|
rspec
|
64
|
+
sem4r!
|
42
65
|
yard
|
data/Rakefile
CHANGED
@@ -1,9 +1,11 @@
|
|
1
1
|
require 'rubygems'
|
2
2
|
require 'rake'
|
3
3
|
|
4
|
+
require 'bundler'
|
5
|
+
Bundler::GemHelper.install_tasks
|
6
|
+
|
4
7
|
# Load tasks
|
5
8
|
Dir.glob('tasks/**/*.rake').each { |r| Rake.application.add_import r }
|
6
9
|
|
7
|
-
task :test => :
|
10
|
+
task :test => :spec
|
8
11
|
task :default => :spec
|
9
|
-
|
data/bin/sem
CHANGED
@@ -1,4 +1,4 @@
|
|
1
|
-
#!/usr/bin/env ruby
|
1
|
+
#!/usr/bin/env ruby
|
2
2
|
|
3
3
|
# -------------------------------------------------------------------------
|
4
4
|
# Copyright (c) 2009-2010 Sem4r sem4ruby@gmail.com
|
@@ -21,15 +21,11 @@
|
|
21
21
|
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
22
22
|
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
23
23
|
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
24
|
-
#
|
25
24
|
# -------------------------------------------------------------------------
|
26
25
|
|
27
26
|
require 'rubygems'
|
28
|
-
|
29
27
|
cwd = File.expand_path( File.join( File.dirname(__FILE__), "..", "lib" ) )
|
30
28
|
$:.unshift(cwd) unless $:.include?(cwd)
|
31
29
|
require 'sem4r_cli'
|
32
30
|
|
33
|
-
|
34
|
-
include Sem4rCli
|
35
|
-
exit CliSem.run
|
31
|
+
Sem4rCli::CliSem.run!
|
data/lib/sem4r/adwords.rb
CHANGED
@@ -22,7 +22,6 @@
|
|
22
22
|
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
23
23
|
# -------------------------------------------------------------------
|
24
24
|
|
25
|
-
|
26
25
|
module Sem4r
|
27
26
|
class Adwords
|
28
27
|
|
@@ -46,78 +45,6 @@ module Sem4r
|
|
46
45
|
new("production", options)
|
47
46
|
end
|
48
47
|
|
49
|
-
#
|
50
|
-
# @private
|
51
|
-
# Search configuration file in standard locations
|
52
|
-
# @return [OpenStruct] with
|
53
|
-
# :config_dir
|
54
|
-
# :config_file
|
55
|
-
# :password_file
|
56
|
-
#
|
57
|
-
def search_config
|
58
|
-
config_filename = "sem4r.yml"
|
59
|
-
password_filename = "sem4r_passwords.yml"
|
60
|
-
|
61
|
-
#
|
62
|
-
# try current directory
|
63
|
-
#
|
64
|
-
# return File.expand_path(config_filename) if File.exists?( config_filename)
|
65
|
-
|
66
|
-
#
|
67
|
-
# try ~/.sem4r/sem4r.yml
|
68
|
-
#
|
69
|
-
# require 'etc'
|
70
|
-
# homedir = Etc.getpwuid.dir
|
71
|
-
homedir = ENV['HOME']
|
72
|
-
config_filepath = File.join(homedir, ".sem4r", config_filename)
|
73
|
-
if File.exists?(config_filepath)
|
74
|
-
return OpenStruct.new(
|
75
|
-
:config_dir => File.join(homedir, ".sem4r"),
|
76
|
-
:config_file => config_filepath,
|
77
|
-
:password_file => File.join(homedir, ".sem4r", password_filename))
|
78
|
-
end
|
79
|
-
|
80
|
-
#
|
81
|
-
# try <home_sem4r>/config/sem4r
|
82
|
-
#
|
83
|
-
config_filepath = File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "config", config_filename))
|
84
|
-
if File.exists?(config_filepath)
|
85
|
-
return OpenStruct.new(
|
86
|
-
:config_dir => nil,
|
87
|
-
:config_file => config_filepath,
|
88
|
-
:password_file => nil)
|
89
|
-
end
|
90
|
-
|
91
|
-
config_filepath = File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "config", "sem4r.example.yml"))
|
92
|
-
if File.exists?(config_filepath)
|
93
|
-
return OpenStruct.new(
|
94
|
-
:config_dir => nil,
|
95
|
-
:config_file => config_filepath,
|
96
|
-
:password_file => nil)
|
97
|
-
end
|
98
|
-
|
99
|
-
OpenStruct.new(
|
100
|
-
:config_dir => nil,
|
101
|
-
:config_file => nil,
|
102
|
-
:password_file => nil)
|
103
|
-
end
|
104
|
-
|
105
|
-
#
|
106
|
-
# Return list of profile contained into config file
|
107
|
-
#
|
108
|
-
def profiles(profile_file = nil)
|
109
|
-
unless profile_file
|
110
|
-
config = search_config
|
111
|
-
unless config
|
112
|
-
raise Sem4rError, "config file 'sem4r' not found"
|
113
|
-
end
|
114
|
-
profile_file = config.config_file
|
115
|
-
end
|
116
|
-
# puts "Loaded profiles from #{profile_file}"
|
117
|
-
yaml = YAML::load(File.open(profile_file))
|
118
|
-
profiles = yaml['google_adwords']
|
119
|
-
profiles
|
120
|
-
end
|
121
48
|
end
|
122
49
|
|
123
50
|
#
|
@@ -154,23 +81,23 @@ module Sem4r
|
|
154
81
|
|
155
82
|
config_file = options.delete("config_file")
|
156
83
|
password_file = options.delete("password_file")
|
157
|
-
configure(config_file, password_file)
|
84
|
+
@config = Profile.configure(config_file, password_file)
|
158
85
|
|
159
86
|
@profile = profile.to_s
|
160
|
-
@options = load_config(@profile)
|
87
|
+
@options = Profile.load_config(@config, @profile)
|
161
88
|
@options = @options.merge(options)
|
162
89
|
elsif profile.respond_to?(:keys)
|
163
90
|
# new( {:environment=>"...", email => "..." } )
|
164
91
|
options = profile.stringify_keys
|
165
92
|
options.assert_valid_keys( *(all_keys-%w{config_file password_file}) )
|
166
|
-
configure
|
93
|
+
@config = Profile.configure
|
167
94
|
@options = options
|
168
95
|
@profile = "anonymous_" + @options["environment"]
|
169
96
|
else
|
170
97
|
# new( "sandbox" )
|
171
98
|
@profile = profile.to_s
|
172
|
-
configure
|
173
|
-
@options = load_config(@profile)
|
99
|
+
@config = Profile.configure
|
100
|
+
@options = Profile.load_config(@config, @profile)
|
174
101
|
end
|
175
102
|
if ["sandbox", "production"].include?(profile)
|
176
103
|
if @options["environment"].nil?
|
@@ -181,7 +108,7 @@ module Sem4r
|
|
181
108
|
end
|
182
109
|
end
|
183
110
|
|
184
|
-
|
111
|
+
Profile.try_to_find_in_password_file("password", @options, @config) unless @options["password"]
|
185
112
|
end
|
186
113
|
|
187
114
|
def to_s
|
@@ -192,7 +119,7 @@ module Sem4r
|
|
192
119
|
# returns profiles contained into current config file
|
193
120
|
#
|
194
121
|
def profiles
|
195
|
-
|
122
|
+
Profile.profiles @config.config_file
|
196
123
|
end
|
197
124
|
|
198
125
|
#
|
@@ -200,7 +127,7 @@ module Sem4r
|
|
200
127
|
#
|
201
128
|
def config_file
|
202
129
|
return @config.config_file if @config
|
203
|
-
@config =
|
130
|
+
@config = Profile.search_config
|
204
131
|
unless @config
|
205
132
|
puts "cannot find configuration files"
|
206
133
|
end
|
@@ -227,67 +154,6 @@ module Sem4r
|
|
227
154
|
@options["password"]=pwd
|
228
155
|
end
|
229
156
|
|
230
|
-
def try_to_find_password_in_password_file
|
231
|
-
return unless @config.password_file
|
232
|
-
return unless File.exists?(@config.password_file)
|
233
|
-
passwords = YAML.load(File.open(@config.password_file))
|
234
|
-
pass = passwords[@options["email"]]
|
235
|
-
@options["password"] = pass if pass
|
236
|
-
end
|
237
|
-
|
238
|
-
def save_passwords
|
239
|
-
if @config.password_file.nil?
|
240
|
-
raise "cannot save password"
|
241
|
-
end
|
242
|
-
puts "save password in #{@config.password_file} (security warning!)"
|
243
|
-
passwords = {}
|
244
|
-
if File.exists?(@config.password_file)
|
245
|
-
passwords = YAML.load(File.open(@config.password_file))
|
246
|
-
end
|
247
|
-
passwords[@options["email"]] = @options["password"]
|
248
|
-
File.open(@config.password_file, "w") do |f|
|
249
|
-
f.write(passwords.to_yaml)
|
250
|
-
end
|
251
|
-
end
|
252
|
-
|
253
|
-
private
|
254
|
-
|
255
|
-
#
|
256
|
-
# @private
|
257
|
-
#
|
258
|
-
# force config paths
|
259
|
-
# and the config file
|
260
|
-
#
|
261
|
-
def configure(config_file = nil, password_file = nil)
|
262
|
-
@config = Adwords.search_config
|
263
|
-
unless config_file.nil?
|
264
|
-
config_file = File.expand_path(config_file)
|
265
|
-
unless File.exists?(config_file)
|
266
|
-
raise "#{config_file} not exists"
|
267
|
-
end
|
268
|
-
@config.config_file = config_file
|
269
|
-
end
|
270
|
-
unless password_file.nil?
|
271
|
-
password_file = File.expand_path(password_file)
|
272
|
-
@config.password_file = password_file
|
273
|
-
end
|
274
|
-
@config
|
275
|
-
end
|
276
|
-
|
277
|
-
|
278
|
-
# @private
|
279
|
-
# load the configuration
|
280
|
-
def load_config(profile)
|
281
|
-
unless @config.config_file
|
282
|
-
raise Sem4rError, "config file 'sem4r' not found"
|
283
|
-
end
|
284
|
-
# puts "Loaded profiles from #{config_file}"
|
285
|
-
yaml = YAML::load(File.open(@config.config_file))
|
286
|
-
config = yaml['google_adwords'][profile]
|
287
|
-
config || {}
|
288
|
-
end
|
289
|
-
|
290
|
-
public
|
291
157
|
|
292
158
|
##########################################################################
|
293
159
|
# logging
|
@@ -1,7 +1,7 @@
|
|
1
1
|
# -*- coding: utf-8 -*-
|
2
2
|
# -------------------------------------------------------------------------
|
3
3
|
# Copyright (c) 2009-2010 Sem4r sem4ruby@gmail.com
|
4
|
-
#
|
4
|
+
#
|
5
5
|
# Permission is hereby granted, free of charge, to any person obtaining
|
6
6
|
# a copy of this software and associated documentation files (the
|
7
7
|
# "Software"), to deal in the Software without restriction, including
|
@@ -9,10 +9,10 @@
|
|
9
9
|
# distribute, sublicense, and/or sell copies of the Software, and to
|
10
10
|
# permit persons to whom the Software is furnished to do so, subject to
|
11
11
|
# the following conditions:
|
12
|
-
#
|
12
|
+
#
|
13
13
|
# The above copyright notice and this permission notice shall be
|
14
14
|
# included in all copies or substantial portions of the Software.
|
15
|
-
#
|
15
|
+
#
|
16
16
|
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
17
|
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
18
|
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
@@ -20,7 +20,6 @@
|
|
20
20
|
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
21
|
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
22
|
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
23
|
-
#
|
24
23
|
# -------------------------------------------------------------------------
|
25
24
|
|
26
25
|
module Sem4r
|
@@ -85,4 +84,4 @@ module Sem4r
|
|
85
84
|
include AccountCampaignExtension
|
86
85
|
end
|
87
86
|
|
88
|
-
end
|
87
|
+
end
|
@@ -0,0 +1,173 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
# -------------------------------------------------------------------
|
3
|
+
# Copyright (c) 2009-2010 Sem4r sem4ruby@gmail.com
|
4
|
+
#
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
# a copy of this software and associated documentation files (the
|
7
|
+
# "Software"), to deal in the Software without restriction, including
|
8
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
# the following conditions:
|
12
|
+
#
|
13
|
+
# The above copyright notice and this permission notice shall be
|
14
|
+
# included in all copies or substantial portions of the Software.
|
15
|
+
#
|
16
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
23
|
+
# -------------------------------------------------------------------
|
24
|
+
|
25
|
+
module Sem4r
|
26
|
+
|
27
|
+
class Profile
|
28
|
+
|
29
|
+
attr_reader :profile
|
30
|
+
|
31
|
+
class << self
|
32
|
+
|
33
|
+
#
|
34
|
+
# @private
|
35
|
+
# Search configuration file in standard locations
|
36
|
+
# @return [OpenStruct] with
|
37
|
+
# :config_dir
|
38
|
+
# :config_file
|
39
|
+
# :password_file
|
40
|
+
#
|
41
|
+
def search_config
|
42
|
+
config_filename = "sem4r.yml"
|
43
|
+
password_filename = "sem4r_passwords.yml"
|
44
|
+
|
45
|
+
#
|
46
|
+
# try current directory
|
47
|
+
#
|
48
|
+
# return File.expand_path(config_filename) if File.exists?( config_filename)
|
49
|
+
|
50
|
+
#
|
51
|
+
# try ~/.sem4r/sem4r.yml
|
52
|
+
#
|
53
|
+
# require 'etc'
|
54
|
+
# homedir = Etc.getpwuid.dir
|
55
|
+
homedir = ENV['HOME']
|
56
|
+
config_filepath = File.join(homedir, ".sem4r", config_filename)
|
57
|
+
if File.exists?(config_filepath)
|
58
|
+
return OpenStruct.new(
|
59
|
+
:config_dir => File.join(homedir, ".sem4r"),
|
60
|
+
:config_file => config_filepath,
|
61
|
+
:password_file => File.join(homedir, ".sem4r", password_filename))
|
62
|
+
end
|
63
|
+
|
64
|
+
#
|
65
|
+
# try <home_sem4r>/config/sem4r
|
66
|
+
#
|
67
|
+
config_filepath = File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "config", config_filename))
|
68
|
+
if File.exists?(config_filepath)
|
69
|
+
return OpenStruct.new(
|
70
|
+
:config_dir => nil,
|
71
|
+
:config_file => config_filepath,
|
72
|
+
:password_file => nil)
|
73
|
+
end
|
74
|
+
|
75
|
+
config_filepath = File.expand_path(File.join(File.dirname(__FILE__), "..", "..", "config", "sem4r.example.yml"))
|
76
|
+
if File.exists?(config_filepath)
|
77
|
+
return OpenStruct.new(
|
78
|
+
:config_dir => nil,
|
79
|
+
:config_file => config_filepath,
|
80
|
+
:password_file => nil)
|
81
|
+
end
|
82
|
+
|
83
|
+
OpenStruct.new(
|
84
|
+
:config_dir => nil,
|
85
|
+
:config_file => nil,
|
86
|
+
:password_file => nil)
|
87
|
+
end
|
88
|
+
|
89
|
+
#
|
90
|
+
# Return list of profile contained into config file
|
91
|
+
#
|
92
|
+
def profiles(profile_file = nil)
|
93
|
+
unless profile_file
|
94
|
+
config = search_config
|
95
|
+
unless config
|
96
|
+
raise Sem4rError, "config file 'sem4r' not found"
|
97
|
+
end
|
98
|
+
profile_file = config.config_file
|
99
|
+
end
|
100
|
+
# puts "Loaded profiles from #{profile_file}"
|
101
|
+
yaml = YAML::load(File.open(profile_file))
|
102
|
+
profiles = yaml['google_adwords']
|
103
|
+
profiles
|
104
|
+
end
|
105
|
+
|
106
|
+
#
|
107
|
+
# @private
|
108
|
+
#
|
109
|
+
# force config paths
|
110
|
+
# and the config file
|
111
|
+
#
|
112
|
+
def configure(config_file = nil, password_file = nil)
|
113
|
+
config = Profile.search_config
|
114
|
+
unless config_file.nil?
|
115
|
+
config_file = File.expand_path(config_file)
|
116
|
+
unless File.exists?(config_file)
|
117
|
+
raise "#{config_file} not exists"
|
118
|
+
end
|
119
|
+
config.config_file = config_file
|
120
|
+
end
|
121
|
+
unless password_file.nil?
|
122
|
+
password_file = File.expand_path(password_file)
|
123
|
+
config.password_file = password_file
|
124
|
+
end
|
125
|
+
config
|
126
|
+
end
|
127
|
+
|
128
|
+
# @private
|
129
|
+
# load the configuration
|
130
|
+
def load_config(config, profile)
|
131
|
+
unless config.config_file
|
132
|
+
raise Sem4rError, "config file 'sem4r' not found"
|
133
|
+
end
|
134
|
+
# puts "Loaded profiles from #{config_file}"
|
135
|
+
yaml = YAML::load(File.open(config.config_file))
|
136
|
+
config = yaml['google_adwords'][profile.to_s]
|
137
|
+
config || {}
|
138
|
+
end
|
139
|
+
|
140
|
+
def try_to_find_in_password_file(key, options, config)
|
141
|
+
return unless config.password_file
|
142
|
+
return unless File.exists?(config.password_file)
|
143
|
+
passwords = YAML.load(File.open(config.password_file))
|
144
|
+
t = passwords[options["email"]]
|
145
|
+
if t and t[key]
|
146
|
+
options[key] = t[key]
|
147
|
+
else
|
148
|
+
nil
|
149
|
+
end
|
150
|
+
end
|
151
|
+
|
152
|
+
def save_passwords(key, options, config)
|
153
|
+
if config.password_file.nil?
|
154
|
+
raise "no password file defined"
|
155
|
+
end
|
156
|
+
# TODO: check permission password file
|
157
|
+
puts "save password in #{config.password_file} (security warning!)"
|
158
|
+
passwords = {}
|
159
|
+
if File.exists?(config.password_file)
|
160
|
+
passwords = YAML.load(File.open(config.password_file))
|
161
|
+
end
|
162
|
+
passwords[options["email"]] ||= {}
|
163
|
+
passwords[options["email"]][key] = options[key]
|
164
|
+
File.open(config.password_file, "w") do |f|
|
165
|
+
f.write(passwords.to_yaml)
|
166
|
+
end
|
167
|
+
end
|
168
|
+
|
169
|
+
end
|
170
|
+
|
171
|
+
end
|
172
|
+
|
173
|
+
end # module Sem4r
|
@@ -0,0 +1,113 @@
|
|
1
|
+
# -*- coding: utf-8 -*-
|
2
|
+
# -------------------------------------------------------------------------
|
3
|
+
# Copyright (c) 2009-2010 Sem4r sem4ruby@gmail.com
|
4
|
+
#
|
5
|
+
# Permission is hereby granted, free of charge, to any person obtaining
|
6
|
+
# a copy of this software and associated documentation files (the
|
7
|
+
# "Software"), to deal in the Software without restriction, including
|
8
|
+
# without limitation the rights to use, copy, modify, merge, publish,
|
9
|
+
# distribute, sublicense, and/or sell copies of the Software, and to
|
10
|
+
# permit persons to whom the Software is furnished to do so, subject to
|
11
|
+
# the following conditions:
|
12
|
+
#
|
13
|
+
# The above copyright notice and this permission notice shall be
|
14
|
+
# included in all copies or substantial portions of the Software.
|
15
|
+
#
|
16
|
+
# THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
|
17
|
+
# EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
|
18
|
+
# MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
|
19
|
+
# NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
|
20
|
+
# LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
|
21
|
+
# OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
|
22
|
+
# WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
|
23
|
+
# -------------------------------------------------------------------------
|
24
|
+
|
25
|
+
module Sem4r
|
26
|
+
|
27
|
+
#def pretty_xml(xml)
|
28
|
+
# normalized = Class.new(REXML::Formatters::Pretty) do
|
29
|
+
# def write_text(node, output)
|
30
|
+
# super(node.to_s.strip, output)
|
31
|
+
# end
|
32
|
+
# end
|
33
|
+
# normalized.new(0, false).write(xml, xml_pretty='')
|
34
|
+
# xml_pretty
|
35
|
+
#end
|
36
|
+
|
37
|
+
def self.pretty_print_xml_with_rexml(xml)
|
38
|
+
# TODO: using nokogiri also for pretty print xml ?
|
39
|
+
require 'rexml/document'
|
40
|
+
begin
|
41
|
+
xml_document = REXML::Document.new(xml)
|
42
|
+
f = REXML::Formatters::Pretty.new
|
43
|
+
out = String.new
|
44
|
+
f.write(xml_document, out)
|
45
|
+
# remove xml directive
|
46
|
+
out.gsub("<?xml version.rb='1.0' encoding='UTF-8'?>", "")
|
47
|
+
rescue
|
48
|
+
# rescue RuntimeError
|
49
|
+
puts "----------------------------------"
|
50
|
+
puts xml
|
51
|
+
puts "----------------------------------"
|
52
|
+
raise
|
53
|
+
end
|
54
|
+
out
|
55
|
+
end
|
56
|
+
|
57
|
+
@_nokogiri_xsl =<<-EOFS
|
58
|
+
<xsl:stylesheet version="1.0" xmlns:xsl="http://www.w3.org/1999/XSL/Transform">
|
59
|
+
<xsl:output method="xml" encoding="UTF-8" omit-xml-declaration="yes"/>
|
60
|
+
<xsl:param name="indent-increment" select="' '"/>
|
61
|
+
|
62
|
+
<xsl:template name="newline">
|
63
|
+
<xsl:text disable-output-escaping="yes">
|
64
|
+
</xsl:text>
|
65
|
+
</xsl:template>
|
66
|
+
|
67
|
+
<xsl:template match="comment() | processing-instruction()">
|
68
|
+
<xsl:param name="indent" select="''"/>
|
69
|
+
<xsl:call-template name="newline"/>
|
70
|
+
<xsl:value-of select="$indent"/>
|
71
|
+
<xsl:copy />
|
72
|
+
</xsl:template>
|
73
|
+
|
74
|
+
<xsl:template match="text()">
|
75
|
+
<xsl:param name="indent" select="''"/>
|
76
|
+
<xsl:call-template name="newline"/>
|
77
|
+
<xsl:value-of select="$indent"/>
|
78
|
+
<xsl:value-of select="normalize-space(.)"/>
|
79
|
+
</xsl:template>
|
80
|
+
|
81
|
+
<xsl:template match="text()[normalize-space(.)='']"/>
|
82
|
+
|
83
|
+
<xsl:template match="*">
|
84
|
+
<xsl:param name="indent" select="''"/>
|
85
|
+
<xsl:call-template name="newline"/>
|
86
|
+
<xsl:value-of select="$indent"/>
|
87
|
+
<xsl:choose>
|
88
|
+
<xsl:when test="count(child::*) > 0">
|
89
|
+
<xsl:copy>
|
90
|
+
<xsl:copy-of select="@*"/>
|
91
|
+
<xsl:apply-templates select="*|text()">
|
92
|
+
<xsl:with-param name="indent" select="concat ($indent, $indent-increment)"/>
|
93
|
+
</xsl:apply-templates>
|
94
|
+
<xsl:call-template name="newline"/>
|
95
|
+
<xsl:value-of select="$indent"/>
|
96
|
+
</xsl:copy>
|
97
|
+
</xsl:when>
|
98
|
+
<xsl:otherwise>
|
99
|
+
<xsl:copy-of select="."/>
|
100
|
+
</xsl:otherwise>
|
101
|
+
</xsl:choose>
|
102
|
+
</xsl:template>
|
103
|
+
</xsl:stylesheet>
|
104
|
+
EOFS
|
105
|
+
|
106
|
+
def self.pretty_print_xml_with_nokogiri(xml)
|
107
|
+
doc = Nokogiri::XML(xml)
|
108
|
+
xslt = Nokogiri::XSLT(@_nokogiri_xsl)
|
109
|
+
out = xslt.transform(doc).root.to_xml # using root omit the xml declaration
|
110
|
+
# out.gsub(/<\?xml version.rb=('|")1.0('|") encoding=('|")UTF-8('|")\?>/, "")
|
111
|
+
end
|
112
|
+
|
113
|
+
end
|