wcc 2.1.0 → 2.2.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.
data/README.md CHANGED
@@ -2,11 +2,11 @@ web change checker
2
2
  ==================
3
3
 
4
4
  This is a powerful ruby program to track changes of websites and get notified via mail on
5
- change with configurable scope of adresses per website. All mails contain a unified diff
5
+ change with configurable scope of addresses per website. All mails contain a unified diff
6
6
  from old content to new content so minor changes produce only few lines of text even on large sites.
7
7
 
8
8
  Since version 2.0 wcc has a completely rewritten notification system so emails are now only *one*
9
- way to recieve notifications - the currently supported other are XMPP/Jabber and the Syslog.
9
+ way to receive notifications - the currently supported other are XMPP/Jabber and the syslog.
10
10
  These changes are reflected in 'conf.yml' as well so take care of migrating it (that basically
11
11
  means to create a *recipients* section and update your site entries from *emails* to *notify*).
12
12
 
data/doc/Filters.md CHANGED
@@ -8,23 +8,23 @@ to notify the user (by email) or not.
8
8
  These Proc blocks get registered using `Filter.add` with a given ID (a
9
9
  string, not a :symbol to prevent some problems).
10
10
 
11
- wcc provides an autoloading mechanism that loads all ruby files contained in
11
+ wcc provides an auto-loading mechanism that loads all ruby files contained in
12
12
  a specific directory - the *filter.d* - via `require`. The filter file
13
13
  should contain some bootstrap code that may rely only on the *Filter* class
14
14
  out of wcc:
15
15
 
16
16
  Filter.add 'my_custom_id' do |data,arguments|
17
17
  # do your filter magic here
18
- # and return a boolean
18
+ # and return a Boolean
19
19
  end
20
20
 
21
21
  The format of the `data` may change over time, currently it's a string
22
- containing all lines separated by newline of the unified diff (raw from unix
22
+ containing all lines separated by newline of the unified diff (raw from Unix
23
23
  diff). The arguments are a - possibly empty - hash directly passed in from
24
- the configuration file to parameterize the filter (e.g. ignoring all diffs
24
+ the configuration file to parametrize the filter (e.g. ignoring all diffs
25
25
  shorter than let's say 10 lines).
26
26
 
27
- The output of this filter should be boolean true or false, indicating that
27
+ The output of this filter should be Boolean true or false, indicating that
28
28
  an email should be sent or not.
29
29
 
30
30
  In the configuration file a filter is referenced like this:
data/lib/wcc/mail.rb CHANGED
@@ -84,9 +84,10 @@ module WCC
84
84
  :smtp_port => conf['smtp']['port'] || 25
85
85
  }
86
86
  elsif conf['fake_file'].is_a?(Hash)
87
+ from_mail = MailAddress.new(conf['fake_file']['from'] || "#{Etc.getlogin}@localhost")
87
88
  return {
88
89
  :mailer => 'fake_file',
89
- :from_mail => conf['fake_file']['from'] || "#{Etc.getlogin}@localhost"
90
+ :from_mail => from_mail
90
91
  }
91
92
  end
92
93
  end
data/lib/wcc/site.rb CHANGED
@@ -55,13 +55,25 @@ module WCC
55
55
  end
56
56
 
57
57
  def fetch
58
- http = Net::HTTP.new(@uri.host, @uri.port)
59
- if @uri.is_a?(URI::HTTPS)
60
- http.use_ssl = true
61
- http.verify_mode = OpenSSL::SSL::VERIFY_NONE
58
+ retrieve(@uri)
59
+ end
60
+
61
+ def fetch_redirect(new_uri)
62
+ retrieve(new_uri)
63
+ end
64
+
65
+ private
66
+
67
+ def retrieve(uri)
68
+ con = Net::HTTP.new(uri.host, uri.port)
69
+ if uri.is_a?(URI::HTTPS)
70
+ con.use_ssl = true
71
+ con.verify_mode = OpenSSL::SSL::VERIFY_NONE
62
72
  end
63
- http.start do |http|
64
- req = Net::HTTP::Get.new(@uri.request_uri)
73
+ con.start do |http|
74
+ #http.open_timeout = 20
75
+ #http.read_timeout = 60
76
+ req = Net::HTTP::Get.new(uri.request_uri)
65
77
  if @auth['type'] == 'basic'
66
78
  WCC.logger.debug "Doing basic auth"
67
79
  req.basic_auth(@auth['username'], @auth['password'])
data/lib/wcc/syslog.rb CHANGED
@@ -1,11 +1,31 @@
1
1
 
2
2
  module WCC
3
3
  class SyslogNotificator
4
- def initialize
4
+
5
+ LEVELS = ['crit', 'emerg', 'alert', 'err', 'warning', 'notice', 'info', 'debug']
6
+
7
+ def initialize(opts)
8
+ if LEVELS.include?(opts)
9
+ @prio = opts
10
+ @enable = true
11
+ else
12
+ @enable = false
13
+ raise ArgumentError, "The given priority '#{opts}' is not known, use one of: #{LEVELS.join(', ')}."
14
+ end
15
+ begin
16
+ # from ruby std lib
17
+ require 'syslog'
18
+ rescue LoadError
19
+ @enable = false
20
+ raise ArgumentError, "Won't log to syslog since your system does NOT support syslog!"
21
+ end
5
22
  end
6
23
 
24
+ # TODO: ERB template for syslog
7
25
  def notify!(data)
8
- system("logger -t '#{data.tag}' 'Change at #{data.site.uri.to_s} (tag #{data.site.id}) detected'")
26
+ Syslog.open(data.tag, Syslog::LOG_PID | Syslog::LOG_CONS) do |s|
27
+ s.send(@prio.to_sym, "Change at #{data.site.uri.to_s} (tag #{data.site.id}) detected")
28
+ end if @enable
9
29
  end
10
30
 
11
31
  def self.parse_conf(conf); {} end
data/lib/wcc/version.rb CHANGED
@@ -1,4 +1,4 @@
1
1
 
2
2
  module WCC
3
- VERSION = "2.1.0"
3
+ VERSION = "2.2.0"
4
4
  end
data/lib/wcc.rb CHANGED
@@ -104,7 +104,7 @@ module WCC
104
104
  :cache_dir => '/var/tmp/wcc',
105
105
  :tag => 'wcc',
106
106
  :filter_dir => './filter.d',
107
- :template_dir => './template.d',
107
+ :template_dir => './template.d'
108
108
  }
109
109
  end
110
110
 
@@ -211,20 +211,9 @@ module WCC
211
211
  yaml_rec[name].to_a.each do |yaml_way|
212
212
  # TODO: find options and pass them to every notificator
213
213
  if yaml_way.is_a?(Hash)
214
- prim_key = yaml_way.keys.first # and only!
215
- klass = Notificators.mappings[prim_key]
216
- if klass.nil?
217
- WCC.logger.error "Referenced notificator '#{prim_key}' not found!"
218
- else
219
- rec << klass.new(yaml_way[prim_key])
220
- end
214
+ new_notificator(name, yaml_way.keys.first, yaml_way[yaml_way.keys.first], rec)
221
215
  else
222
- klass = Notificators.mappings[yaml_way]
223
- if klass.nil?
224
- WCC.logger.error "Referenced notificator '#{yaml_way}' not found!"
225
- else
226
- rec << klass.new
227
- end
216
+ new_notificator(name, yaml_way, nil, rec)
228
217
  end
229
218
  end
230
219
  @recipients[name] = rec
@@ -289,9 +278,26 @@ module WCC
289
278
  return Conf.instance.recipients
290
279
  end
291
280
 
292
- def self.file(path = nil) File.join(self[:cache_dir], path) end
281
+ def self.file(path = nil); File.join(self[:cache_dir], path) end
293
282
  def self.simulate?; self[:simulate] end
294
283
  def self.[](key); Conf.instance[key] end
284
+
285
+ private
286
+
287
+ def new_notificator(rec_name, not_name, opts, rec_out)
288
+ klass = Notificators.mappings[not_name]
289
+ if klass.nil?
290
+ WCC.logger.error "Referenced notificator '#{not_name}' not found!"
291
+ return
292
+ end
293
+ begin
294
+ if opts.nil?; rec_out << klass.new
295
+ else rec_out << klass.new(opts)
296
+ end
297
+ rescue => ex
298
+ WCC.logger.error "Recipient '#{rec_name}' not notifiable via '#{not_name}' (skip): #{ex}"
299
+ end
300
+ end
295
301
  end
296
302
 
297
303
  class Notificators
@@ -346,8 +352,44 @@ module WCC
346
352
  WCC.logger.error "Cannot connect to #{site.uri.to_s} : #{ex.to_s}"
347
353
  return false
348
354
  end
349
- if not res.kind_of?(Net::HTTPOK)
355
+ if res.kind_of?(Net::HTTPOK)
356
+ # be happy!
357
+ elsif res.kind_of?(Net::HTTPMovedPermanently)
358
+ loc = res['Location']
359
+ if loc.nil?
360
+ WCC.logger.error "Site #{site.uri.to_s} moved permanently, skippong it - no new location given."
361
+ else
362
+ WCC.logger.error "Site #{site.uri.to_s} moved permanently to '#{loc}', skipping it - please update your conf.yml adequately!"
363
+ end
364
+ return false
365
+ elsif res.kind_of?(Net::HTTPSeeOther) or res.kind_of?(Net::HTTPTemporaryRedirect)
366
+ loc = URI.parse(res['Location'])
367
+ WCC.logger.warn "Redirect: requesting '#{loc.to_s}'"
368
+ res = site.fetch_redirect(loc)
369
+ if not res.kind_of?(Net::HTTPOK)
370
+ WCC.logger.error "Redirected site #{loc.to_s} returned #{res.code} code, skipping it."
371
+ WCC.logger.error "Headers: #{res.to_hash.inspect}"
372
+ return false
373
+ end
374
+ elsif res.kind_of?(Net::HTTPUnauthorized)
375
+ WCC.logger.error "Site #{site.uri.to_s} demands authentication for '#{res['www-authenticate']}', skipping it - consider using 'auth:' option in your conf.yml."
376
+ return false
377
+ elsif res.kind_of?(Net::HTTPNotFound)
378
+ WCC.logger.error "Site #{site.uri.to_s} not found, skipping it."
379
+ return false
380
+ elsif res.kind_of?(Net::HTTPForbidden)
381
+ WCC.logger.error "Site #{site.uri.to_s} forbids access, skipping it."
382
+ return false
383
+ elsif res.kind_of?(Net::HTTPInternalServerError)
384
+ WCC.logger.error "Site #{site.uri.to_s} has internal errors, skipping it."
385
+ return false
386
+ elsif res.kind_of?(Net::HTTPServiceUnavailable)
387
+ #retry_after = res['Retry-After']
388
+ WCC.logger.warn "Site #{site.uri.to_s} currently not available, skipping it."
389
+ return false
390
+ else
350
391
  WCC.logger.error "Site #{site.uri.to_s} returned #{res.code} code, skipping it."
392
+ WCC.logger.error "Headers: #{res.to_hash.inspect}"
351
393
  return false
352
394
  end
353
395
 
metadata CHANGED
@@ -1,13 +1,13 @@
1
1
  --- !ruby/object:Gem::Specification
2
2
  name: wcc
3
3
  version: !ruby/object:Gem::Version
4
- hash: 11
4
+ hash: 7
5
5
  prerelease:
6
6
  segments:
7
7
  - 2
8
- - 1
8
+ - 2
9
9
  - 0
10
- version: 2.1.0
10
+ version: 2.2.0
11
11
  platform: ruby
12
12
  authors:
13
13
  - Christian Nicolai
@@ -15,7 +15,7 @@ autorequire:
15
15
  bindir: bin
16
16
  cert_chain: []
17
17
 
18
- date: 2011-11-09 00:00:00 Z
18
+ date: 2011-11-24 00:00:00 Z
19
19
  dependencies:
20
20
  - !ruby/object:Gem::Dependency
21
21
  name: htmlentities