wcc-rss-notificator 0.1.0

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
data/README.md ADDED
@@ -0,0 +1,36 @@
1
+ wcc-rss-notificator
2
+ ===================
3
+
4
+ This adds Atom feed support to [wcc](https://github.com/cmur2/wcc) encapsulated
5
+ in a separate gem.
6
+
7
+ Note: Currently there is only one feed for all users/recipients.
8
+
9
+ What you need to add to your conf.yml:
10
+
11
+ conf:
12
+ [...]
13
+ # enable rss plugin
14
+ rss: {}
15
+
16
+ recipients:
17
+ [...]
18
+ - me:
19
+ [...]
20
+ # write updates to Atom feed
21
+ - rss:
22
+ # wcc needs write permission on this file/directory:
23
+ #file: <cache.d>/atom.xml
24
+ # mandatory option! - this allows you to use different
25
+ # (or same) databases for each recipient
26
+ db_name: me
27
+ # wcc will keep the N newest entries in your feed
28
+ #num_keep: 1000
29
+ feed:
30
+ # mandatory option! - Note that this is *NOT* your feed's
31
+ # url or something, this should be just an unique identifier:
32
+ id: http://www.example.com/my-feed/
33
+ #title: Your cool feed
34
+ #subtitle: About things
35
+ #link: # this now should be the feed's url
36
+ #alternate_link: # this may be a websites url (favicon comes from here)
@@ -0,0 +1,93 @@
1
+ <style type="text/css">
2
+ .msg {
3
+ font-size: 0.98em;
4
+ }
5
+
6
+ .diff {
7
+ font-size: 12px;
8
+ font-family: 'Bitstream Vera Sans Mono','Courier',monospace;
9
+ }
10
+
11
+ .diff ul {
12
+ list-style: none;
13
+ display: table;
14
+ padding: 0;
15
+ margin: 0.5em 0 0 0.5em;
16
+ border: 1px solid #CCCCCC;
17
+ }
18
+
19
+ .diff li {
20
+ padding: 0;
21
+ display: table-row;
22
+ margin: 0;
23
+ background: #f8f8ff;
24
+ }
25
+
26
+ .diff .new, .diff .old {
27
+ color: #999;
28
+ }
29
+
30
+ .diff .ins {
31
+ background: #dfd;
32
+ }
33
+
34
+ .diff .ins .x {
35
+ background: #8f8;
36
+ margin: 0;
37
+ padding: 0;
38
+ }
39
+
40
+ .diff .del {
41
+ background: #fdd;
42
+ }
43
+
44
+ .diff .del .x {
45
+ background: #faa;
46
+ margin: 0;
47
+ padding: 0;
48
+ }
49
+
50
+ .diff .range {
51
+ background: #eaf2f5;
52
+ color: #999;
53
+ }
54
+
55
+ .diff .other {
56
+ }
57
+ </style>
58
+
59
+ <% if data.diff.nil? %>
60
+ <div class="msg">
61
+ Checked <a href="<%= data.site.uri.to_s %>"><%= data.site.uri.to_s %></a> the first time so no diff was possible.
62
+ </div>
63
+ <% else %>
64
+ <div class="msg">
65
+ Change at <a href="<%= data.site.uri.to_s %>"><%= data.site.uri.to_s %></a> - diff follows:
66
+ </div>
67
+ <div class="diff">
68
+ <ul>
69
+ <% for o in data.diff.di %>
70
+ <% if o.status == :new %>
71
+ <li class="new">+++<%= o.text %></li>
72
+ <% elsif o.status == :old %>
73
+ <li class="old">---<%= o.text %></li>
74
+ <% elsif o.status == :range %>
75
+ <li class="range">@@<%= o.text %></li>
76
+ <% elsif o.status == :ins %>
77
+ <li class="ins">+&nbsp;<%= o.html_hilite_text('x').lstrip %></li>
78
+ <% elsif o.status == :del %>
79
+ <li class="del">-&nbsp;<%= o.html_hilite_text('x').lstrip %></li>
80
+ <% else %>
81
+ <li class="other">&nbsp;&nbsp;<%= o.text.substring(1).lstrip %></li>
82
+ <% end %>
83
+ <% end %>
84
+ </ul>
85
+ </div>
86
+ <div>
87
+ nHunks: <%= data.diff.nhunks %>,
88
+ nIns: <%= data.diff.ninsertions %>,
89
+ nDel: <%= data.diff.ndeletions %>,
90
+ nLinesC: <%= data.diff.nlinesc %>,
91
+ nCharsC: <%= data.diff.ncharsc %>
92
+ </div>
93
+ <% end %>
@@ -0,0 +1 @@
1
+ <%= data.site.uri.host %> changed
@@ -0,0 +1,162 @@
1
+
2
+ require 'rss/maker'
3
+ require 'socket' # only for getting hostname
4
+ require 'yaml'
5
+
6
+ class RSSNotificator
7
+ @@tpl = {}
8
+ @@shutdown_hooks = []
9
+
10
+ # TODO: can we hook into --clean?
11
+
12
+ def initialize(opts)
13
+ @dirty = false
14
+ if opts.is_a?(Hash)
15
+ @file = opts['file'] || WCC::Conf.file("atom.xml")
16
+ @db_name = opts['db_name']
17
+ @num_keep = opts['num_keep'] || 1000
18
+ @feed = {}
19
+ if opts['feed'].is_a?(Hash)
20
+ @feed = {
21
+ :title => opts['feed']['title'] || "wcc Updates Feed - #{Socket.gethostname}",
22
+ :subtitle => opts['feed']['subtitle'] || "The newest changes to your watched sites.",
23
+ :link => opts['feed']['link'],
24
+ :alt_link => opts['feed']['alternate_link'],
25
+ :id => opts['feed']['id']
26
+ }
27
+ end
28
+ if @feed[:id].nil?
29
+ raise ArgumentError, "Missing atom feed ID!"
30
+ end
31
+ if @db_name.nil?
32
+ raise ArgumentError, "Missing db name for atom feed!"
33
+ end
34
+ else
35
+ raise ArgumentError, "No options given for 'rss:' way of a recipient! Need at least db name and feed id."
36
+ end
37
+ @@shutdown_hooks << self
38
+ end
39
+
40
+ def get_feeddb
41
+ if @feeddb.nil?
42
+ feeddb_file = WCC::Conf.file("feed-db-#{@db_name}.yml")
43
+ WCC.logger.debug "Loading feed-db '#{@db_name}' from file '#{feeddb_file}'"
44
+ if not File.exists?(feeddb_file)
45
+ WCC.logger.warn "Feed-db '#{@db_name}' does not exist, will create it on save in '#{feeddb_file}'"
46
+ @feeddb = {'feed' => []}
47
+ else
48
+ # may be false if file is empty
49
+ @feeddb = YAML.load_file(feeddb_file)
50
+ if not @feeddb.is_a?(Hash)
51
+ WCC.logger.warn "Feed-db '#{@db_name}' is corrupt, will overwrite it on save"
52
+ @feeddb = {'feed' => []}
53
+ end
54
+ end
55
+ end
56
+ @feeddb
57
+ end
58
+
59
+ def notify!(data)
60
+ title = self.class.get_tpl(:title, 'rss-title.plain.erb').result(binding)
61
+ # remove trailing whitespace introduced by template
62
+ title.strip!
63
+ content = self.class.get_tpl(:content, 'rss-content.html.erb').result(binding)
64
+ id = "#{@feed['id']}item/#{Time.now.to_f}"
65
+
66
+ # append entries to class variable (not thread safe)
67
+ @dirty = true
68
+ feed = get_feeddb['feed']
69
+ feed.insert 0, {
70
+ 'title' => title,
71
+ #'description' => '', # summary
72
+ 'content' => content,
73
+ 'link' => data.site.uri.to_s,
74
+ 'id' => id,
75
+ 'updated' => Time.now.to_s
76
+ }
77
+ end
78
+
79
+ def shut_down
80
+ return unless @dirty
81
+
82
+ WCC.logger.debug "Writing feed-db '#{@db_name}' to file"
83
+
84
+ feeddb_file = WCC::Conf.file("feed-db-#{@db_name}.yml")
85
+ feeddb = get_feeddb
86
+ # auto-purge
87
+ feeddb['feed'] = feeddb['feed'].slice(0, @num_keep)
88
+ File.open(feeddb_file, 'w+') do |f| YAML.dump(feeddb, f) end
89
+
90
+ WCC.logger.info "Generating feed '#{@file}'..."
91
+
92
+ content = RSS::Maker.make('atom') do |m|
93
+ m.channel.title = @feed[:title]
94
+ m.channel.subtitle = @feed[:subtitle]
95
+ m.channel.author = "web change checker (aka wcc) #{WCC::VERSION}"
96
+ if not @feed[:link].nil?
97
+ m.channel.links.new_link do |li|
98
+ li.rel = "self"
99
+ li.type = "application/atom+xml"
100
+ li.href = @feed[:link]
101
+ end
102
+ end
103
+ if not @feed[:alternate_link].nil?
104
+ m.channel.links.new_link do |li|
105
+ li.rel = "alternate"
106
+ li.type = "text/html"
107
+ li.href = @feed[:alternate_link]
108
+ end
109
+ end
110
+ m.channel.id = @feed[:id]
111
+ m.channel.updated = Time.now.to_s
112
+ m.items.do_sort = true # sort items by date
113
+
114
+ # feeddb-hash to atom
115
+ feeddb['feed'].each do |e|
116
+ m.items.new_item do |i|
117
+ i.title = e['title']
118
+ #i.description = e['description']
119
+ i.content.content = e['content']
120
+ i.content.type = "html"
121
+ i.author = "wcc"
122
+ if not e['link'].nil?
123
+ i.links.new_link do |li|
124
+ li.rel = "alternate"
125
+ li.type = "text/html"
126
+ li.href = e['link']
127
+ end
128
+ end
129
+ i.id = e['id']
130
+ i.updated = e['updated']
131
+ end
132
+ end
133
+ end
134
+
135
+ File.open(@file, 'w+') do |f| f.write(content.to_s) end
136
+ end
137
+
138
+ def self.parse_conf(conf); {} end
139
+
140
+ def self.shut_down
141
+ @@shutdown_hooks.each do |s| s.shut_down end
142
+ end
143
+
144
+ def self.get_tpl(id, name)
145
+ if @@tpl[id].nil?
146
+ @@tpl[id] = WCC::Prog.load_template(name)
147
+ if @@tpl[id].nil?
148
+ src_path = Pathname.new(__FILE__) + "../../assets/template.d/#{name}"
149
+ t = File.open(src_path, 'r') { |f| f.read }
150
+ WCC::Prog.save_template(name, t)
151
+ # retry load
152
+ @@tpl[id] = WCC::Prog.load_template(name)
153
+ end
154
+ if @@tpl[id].nil?
155
+ @@tpl[id] = ERB.new("ERROR LOADING TEMPLATE '#{name}'!", 0, "<>")
156
+ end
157
+ end
158
+ @@tpl[id]
159
+ end
160
+ end
161
+
162
+ WCC::Notificators.map "rss", RSSNotificator
metadata ADDED
@@ -0,0 +1,68 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: wcc-rss-notificator
3
+ version: !ruby/object:Gem::Version
4
+ hash: 27
5
+ prerelease:
6
+ segments:
7
+ - 0
8
+ - 1
9
+ - 0
10
+ version: 0.1.0
11
+ platform: ruby
12
+ authors:
13
+ - Christian Nicolai
14
+ autorequire:
15
+ bindir: bin
16
+ cert_chain: []
17
+
18
+ date: 2012-03-25 00:00:00 Z
19
+ dependencies: []
20
+
21
+ description:
22
+ email: chrnicolai@gmail.com
23
+ executables: []
24
+
25
+ extensions: []
26
+
27
+ extra_rdoc_files: []
28
+
29
+ files:
30
+ - assets/template.d/rss-content.html.erb
31
+ - assets/template.d/rss-title.plain.erb
32
+ - lib/wcc-rss-notificator.rb
33
+ - README.md
34
+ homepage: https://github.com/cmur2/wcc-rss-notificator
35
+ licenses: []
36
+
37
+ post_install_message:
38
+ rdoc_options: []
39
+
40
+ require_paths:
41
+ - lib
42
+ required_ruby_version: !ruby/object:Gem::Requirement
43
+ none: false
44
+ requirements:
45
+ - - ">="
46
+ - !ruby/object:Gem::Version
47
+ hash: 3
48
+ segments:
49
+ - 0
50
+ version: "0"
51
+ required_rubygems_version: !ruby/object:Gem::Requirement
52
+ none: false
53
+ requirements:
54
+ - - ">="
55
+ - !ruby/object:Gem::Version
56
+ hash: 3
57
+ segments:
58
+ - 0
59
+ version: "0"
60
+ requirements: []
61
+
62
+ rubyforge_project: wcc-rss-notificator
63
+ rubygems_version: 1.8.6
64
+ signing_key:
65
+ specification_version: 3
66
+ summary: RSS feed notificator plugin for wcc
67
+ test_files: []
68
+