pluto 1.0.1 → 1.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/lib/pluto/fetcher.rb DELETED
@@ -1,292 +0,0 @@
1
- module Pluto
2
-
3
-
4
- class Fetcher
5
-
6
- include LogUtils::Logging
7
-
8
- include Models # for easy convenience access for Activity etc.
9
-
10
- def initialize
11
- @worker = ::Fetcher::Worker.new
12
- end
13
-
14
- def debug=(value) @debug = value; end
15
- def debug?() @debug || false; end
16
-
17
-
18
- def fetch_feed( url )
19
- response = @worker.get( url )
20
-
21
- ## if debug?
22
- puts "http status #{response.code} #{response.message}"
23
-
24
- puts "http header - server: #{response.header['server']} - #{response.header['server'].class.name}"
25
- puts "http header - etag: #{response.header['etag']} - #{response.header['etag'].class.name}"
26
- puts "http header - last-modified: #{response.header['last-modified']} - #{response.header['last-modified'].class.name}"
27
- ## end
28
-
29
- xml = response.body
30
-
31
- ###
32
- # NB: Net::HTTP will NOT set encoding UTF-8 etc.
33
- # will mostly be ASCII
34
- # - try to change encoding to UTF-8 ourselves
35
- logger.debug "xml.encoding.name (before): #{xml.encoding.name}"
36
-
37
- #####
38
- # NB: ASCII-8BIT == BINARY == Encoding Unknown; Raw Bytes Here
39
-
40
- ## NB:
41
- # for now "hardcoded" to utf8 - what else can we do?
42
- # - note: force_encoding will NOT change the chars only change the assumed encoding w/o translation
43
- xml = xml.force_encoding( Encoding::UTF_8 )
44
- logger.debug "xml.encoding.name (after): #{xml.encoding.name}"
45
-
46
- xml
47
- end
48
-
49
-
50
- def feed_by_rec( feed_rec )
51
- # simple feed fetcher; use for debugging (only/mostly)
52
- # -- will NOT change db records in any way
53
-
54
- feed_url = feed_rec.feed_url
55
- feed_key = feed_rec.key
56
-
57
- feed_xml = fetch_feed( feed_url )
58
-
59
- logger.debug "feed_xml:"
60
- logger.debug feed_xml[ 0..500 ] # get first 500 chars
61
-
62
- # if opts.verbose? # also write a copy to disk
63
- if debug?
64
- logger.debug "saving feed to >./#{feed_key}.xml<..."
65
- File.open( "./#{feed_key}.xml", 'w' ) do |f|
66
- f.write( feed_xml )
67
- end
68
- end
69
-
70
- puts "Before parsing feed >#{feed_key}<..."
71
-
72
- ## fix/todo: check for feed.nil? -> error parsing!!!
73
- # or throw exception
74
- feed = FeedUtils::Parser.parse( feed_xml )
75
- end
76
-
77
-
78
- def feed_by_rec_if_modified( feed_rec ) # try smart http update; will update db records
79
- feed_url = feed_rec.feed_url
80
- feed_key = feed_rec.key
81
-
82
- ### todo/fix: normalize/unifiy feed_url
83
- ## - same in fetcher - use shared utitlity method or similar
84
-
85
- @worker.use_cache = true
86
- @worker.cache[ feed_url ] = {
87
- 'etag' => feed_rec.http_etag,
88
- 'last-modified' => feed_rec.http_last_modified
89
- }
90
-
91
- begin
92
- response = @worker.get( feed_url )
93
- rescue SocketError => e
94
- ## catch socket error for unknown domain names (e.g. pragdave.blogs.pragprog.com)
95
- ### will result in SocketError -- getaddrinfo: Name or service not known
96
- puts "*** error: fetching feed '#{feed_key}' - #{e.to_s}"
97
- Activity.create!( text: "*** error: fetching feed '#{feed_key}' - #{e.to_s}" )
98
-
99
- ### todo/fix: update feed rec in db
100
- @worker.use_cache = false # fix/todo: restore old use_cache setting instead of false
101
- return nil
102
- end
103
-
104
- @worker.use_cache = false # fix/todo: restore old use_cache setting instead of false
105
-
106
- if response.code == '304' # not modified (conditional GET - e.g. using etag/last-modified)
107
- puts "OK - fetching feed '#{feed_key}' - HTTP status #{response.code} #{response.message}"
108
- puts "no change; request returns not modified (304); skipping parsing feed"
109
- return nil # no updates available; nothing to do
110
- end
111
-
112
- feed_fetched = Time.now
113
-
114
- if response.code != '200' # note Net::HTTP response.code is a string in ruby
115
-
116
- puts "*** error: fetching feed '#{feed_key}' - HTTP status #{response.code} #{response.message}"
117
-
118
- feed_attribs = {
119
- http_code: response.code.to_i,
120
- http_server: response.header[ 'server' ],
121
- http_etag: nil,
122
- http_last_modified: nil,
123
- body: nil,
124
- md5: nil,
125
- fetched: feed_fetched
126
- }
127
- feed_rec.update_attributes!( feed_attribs )
128
-
129
- ## add log error activity -- in future add to error log - better - why? why not?
130
- Activity.create!( text: "*** error: fetching feed '#{feed_key}' - HTTP status #{response.code} #{response.message}" )
131
-
132
- return nil # sorry; no feed for parsing available
133
- end
134
-
135
- puts "OK - fetching feed '#{feed_key}' - HTTP status #{response.code} #{response.message}"
136
-
137
- feed_xml = response.body
138
- ###
139
- # NB: Net::HTTP will NOT set encoding UTF-8 etc.
140
- # will mostly be ASCII
141
- # - try to change encoding to UTF-8 ourselves
142
- logger.debug "feed_xml.encoding.name (before): #{feed_xml.encoding.name}"
143
-
144
- #####
145
- # NB: ASCII-8BIT == BINARY == Encoding Unknown; Raw Bytes Here
146
-
147
- ## NB:
148
- # for now "hardcoded" to utf8 - what else can we do?
149
- # - note: force_encoding will NOT change the chars only change the assumed encoding w/o translation
150
- feed_xml = feed_xml.force_encoding( Encoding::UTF_8 )
151
- logger.debug "feed_xml.encoding.name (after): #{feed_xml.encoding.name}"
152
-
153
- ## check for md5 hash for response.body
154
-
155
- last_feed_md5 = feed_rec.md5
156
- feed_md5 = Digest::MD5.hexdigest( feed_xml )
157
-
158
- if last_feed_md5 && last_feed_md5 == feed_md5
159
- # not all servers handle conditional gets, so while not much can be
160
- # done about the bandwidth, but if the response body is identical
161
- # the downstream processing (parsing, caching, ...) can be avoided.
162
- # - thanks to planet mars -fido.rb for the idea, cheers.
163
-
164
- puts "no change; md5 digests match; skipping parsing feed"
165
- return nil # no updates available; nothing to do
166
- end
167
-
168
- feed_attribs = {
169
- http_code: response.code.to_i,
170
- http_server: response.header[ 'server' ],
171
- http_etag: response.header[ 'etag' ],
172
- http_last_modified: response.header[ 'last-modified' ], ## note: last_modified header gets stored as plain text (not datetime)
173
- body: feed_xml,
174
- md5: feed_md5,
175
- fetched: feed_fetched
176
- }
177
-
178
- ## if debug?
179
- puts "http header - server: #{response.header['server']} - #{response.header['server'].class.name}"
180
- puts "http header - etag: #{response.header['etag']} - #{response.header['etag'].class.name}"
181
- puts "http header - last-modified: #{response.header['last-modified']} - #{response.header['last-modified'].class.name}"
182
- ## end
183
-
184
- feed_rec.update_attributes!( feed_attribs )
185
-
186
- logger.debug "feed_xml:"
187
- logger.debug feed_xml[ 0..300 ] # get first 300 chars
188
-
189
- puts "Before parsing feed >#{feed_key}<..."
190
-
191
- ### move to feedutils
192
- ### logger.debug "using stdlib RSS::VERSION #{RSS::VERSION}"
193
-
194
- ## fix/todo: check for feed.nil? -> error parsing!!!
195
- # or throw exception
196
- feed = FeedUtils::Parser.parse( feed_xml )
197
- end
198
-
199
-
200
- def site_by_rec_if_modified( site_rec ) # try smart http update; will update db records
201
- site_url = site_rec.url
202
- site_key = site_rec.key
203
-
204
- ### todo/fix: normalize/unifiy feed_url
205
- ## - same in fetcher - use shared utitlity method or similar
206
-
207
- @worker.use_cache = true
208
- @worker.cache[ site_url ] = {
209
- 'etag' => site_rec.http_etag,
210
- 'last-modified' => site_rec.http_last_modified
211
- }
212
-
213
- response = @worker.get( site_url )
214
- @worker.use_cache = false # fix/todo: restore old use_cache setting instead of false
215
-
216
- if response.code == '304' # not modified (conditional GET - e.g. using etag/last-modified)
217
- puts "OK - fetching site '#{site_key}' - HTTP status #{response.code} #{response.message}"
218
- puts "no change; request returns not modified (304); skipping parsing site config"
219
- return nil # no updates available; nothing to do
220
- end
221
-
222
- site_fetched = Time.now
223
-
224
- if response.code != '200' # note Net::HTTP response.code is a string in ruby
225
-
226
- puts "*** error: fetching site '#{site_key}' - HTTP status #{response.code} #{response.message}"
227
-
228
- site_attribs = {
229
- http_code: response.code.to_i,
230
- http_server: response.header[ 'server' ],
231
- http_etag: nil,
232
- http_last_modified: nil,
233
- body: nil,
234
- md5: nil,
235
- fetched: feed_fetched
236
- }
237
- site_rec.update_attributes!( site_attribs )
238
-
239
- ## add log error activity -- in future add to error log - better - why? why not?
240
- Activity.create!( text: "*** error: fetching site '#{site_key}' - HTTP status #{response.code} #{response.message}" )
241
-
242
- return nil # sorry; no feed for parsing available
243
- end
244
-
245
- puts "OK - fetching site '#{site_key}' - HTTP status #{response.code} #{response.message}"
246
-
247
- site_text = response.body
248
-
249
- ###
250
- # NB: Net::HTTP will NOT set encoding UTF-8 etc.
251
- # will mostly be ASCII
252
- # - try to change encoding to UTF-8 ourselves
253
- logger.debug "site_text.encoding.name (before): #{site_text.encoding.name}"
254
-
255
- #####
256
- # NB: ASCII-8BIT == BINARY == Encoding Unknown; Raw Bytes Here
257
-
258
- ## NB:
259
- # for now "hardcoded" to utf8 - what else can we do?
260
- # - note: force_encoding will NOT change the chars only change the assumed encoding w/o translation
261
- site_text = site_text.force_encoding( Encoding::UTF_8 )
262
- logger.debug "site_text.encoding.name (after): #{site_text.encoding.name}"
263
-
264
- site_attribs = {
265
- http_code: response.code.to_i,
266
- http_server: response.header[ 'server' ],
267
- http_etag: response.header[ 'etag' ],
268
- http_last_modified: response.header[ 'last-modified' ], ## note: last_modified header gets stored as plain text (not datetime)
269
- fetched: site_fetched
270
- }
271
-
272
- ## if debug?
273
- puts "http header - server: #{response.header['server']} - #{response.header['server'].class.name}"
274
- puts "http header - etag: #{response.header['etag']} - #{response.header['etag'].class.name}"
275
- puts "http header - last-modified: #{response.header['last-modified']} - #{response.header['last-modified'].class.name}"
276
- ## end
277
-
278
- site_rec.update_attributes!( site_attribs )
279
-
280
- ## logger.debug "site_text:"
281
- ## logger.debug site_text[ 0..300 ] # get first 300 chars
282
-
283
-
284
- puts "Before parsing site config >#{site_key}<..."
285
-
286
- # assume ini format for now
287
- site_config = INI.load( site_text )
288
- end
289
-
290
- end # class Fetcher
291
-
292
- end # module Pluto
@@ -1,81 +0,0 @@
1
- module Pluto
2
-
3
- class Formatter
4
-
5
- include LogUtils::Logging
6
-
7
- include Models
8
- include ManifestHelper
9
-
10
- include TextUtils::DateHelper # e.g. lets us use time_ago_in_words
11
- include TextUtils::HypertextHelper # e.g. lets us use link_to, strip_tags, sanitize, textify, etc.
12
-
13
- def initialize( opts, config )
14
- @opts = opts
15
- @config = config
16
- end
17
-
18
- attr_reader :opts, :config, :site
19
-
20
-
21
- def run( arg )
22
- ### remove - always use make( site_key )
23
- ## fix: change arg to planet_key or just key or similar
24
- # todo: rename run to some less generic - merge/build/etc. ??
25
-
26
- site_key = arg
27
- site_key = site_key.downcase.gsub('.ini','').gsub('.yml','') # remove .ini|.yml extension if present
28
-
29
- manifest_name = opts.manifest
30
- output_path = opts.output_path
31
-
32
- make_for(site_key, manifest_name, output_path )
33
- end
34
-
35
-
36
- def make_for( site_key, manifest_name, output_path )
37
-
38
- ## fix: remove reference to opts
39
- ## - e.g. now still used for auto-installer
40
-
41
- manifest_name = manifest_name.downcase.gsub('.txt', '' ) # remove .txt if present
42
-
43
- logger.debug "manifest=#{manifest_name}"
44
-
45
- # check for matching manifests
46
- manifests = installed_template_manifests.select { |m| m[0] == manifest_name+'.txt' }
47
-
48
- if manifests.empty?
49
-
50
- ### try - autodownload
51
- puts "*** template pack '#{manifest_name}' not found; trying auto-install..."
52
-
53
- Installer.new( opts ).install( manifest_name )
54
-
55
- ### try again
56
-
57
- # check for matching manifests
58
- manifests = installed_template_manifests.select { |m| m[0] == manifest_name+'.txt' }
59
-
60
- if manifests.empty?
61
- puts "*** error: unknown template pack '#{manifest_name}'; use pluto ls to list installed template packs"
62
- exit 2
63
- end
64
- end
65
-
66
- manifestsrc = manifests[0][1]
67
- pakpath = output_path
68
-
69
- @site = Site.find_by_key( site_key )
70
- if @site.nil?
71
- puts "*** warn: no site with key '#{site_key}' found; using untitled site record"
72
- @site = Site.new
73
- @site.title = 'Planet Untitled'
74
- end
75
-
76
- Pakman::Templater.new.merge_pak( manifestsrc, pakpath, binding, site_key )
77
- end
78
-
79
- end # class Formatter
80
-
81
- end # module Pluto
@@ -1,58 +0,0 @@
1
- module Pluto
2
-
3
- class Installer
4
-
5
- ### fix: remove opts, use config (wrapped!!)
6
-
7
- include LogUtils::Logging
8
-
9
- def initialize( opts )
10
- @opts = opts
11
- end
12
-
13
- attr_reader :opts
14
-
15
-
16
- def install( shortcut_or_source )
17
-
18
- logger.debug "fetch >#{shortcut_or_source}<"
19
-
20
- ## check for builtin shortcut (assume no / or \)
21
- if shortcut_or_source.index( '/' ).nil? && shortcut_or_source.index( '\\' ).nil?
22
- shortcut = shortcut_or_source
23
- sources = opts.map_fetch_shortcut( shortcut )
24
-
25
- if sources.empty?
26
- puts "** Error: No mapping found for shortcut '#{shortcut}'."
27
- return
28
- end
29
- puts " Mapping fetch shortcut '#{shortcut}' to: #{sources.join(',')}"
30
- else
31
- sources = [shortcut_or_source] # pass arg through unmapped
32
- end
33
-
34
- sources.each do |source|
35
- install_template( source )
36
- end
37
-
38
- end # method run
39
-
40
-
41
- def install_template( src )
42
- # src = 'http://github.com/geraldb/slideshow/raw/d98e5b02b87ee66485431b1bee8fb6378297bfe4/code/templates/fullerscreen.txt'
43
- # src = 'http://github.com/geraldb/sandbox/raw/13d4fec0908fbfcc456b74dfe2f88621614b5244/s5blank/s5blank.txt'
44
- uri = URI.parse( src )
45
- logger.debug "scheme: #{uri.scheme}, host: #{uri.host}, port: #{uri.port}, path: #{uri.path}"
46
-
47
- pakname = File.basename( uri.path ).downcase.gsub('.txt','')
48
- pakpath = File.expand_path( "#{opts.config_path}/#{pakname}" )
49
-
50
- logger.debug "packname >#{pakname}<"
51
- logger.debug "pakpath >#{pakpath}<"
52
-
53
- Pakman::Fetcher.new.fetch_pak( src, pakpath )
54
- end
55
-
56
- end # class Installer
57
-
58
- end # module Pluto
data/lib/pluto/lister.rb DELETED
@@ -1,42 +0,0 @@
1
- module Pluto
2
-
3
- class Lister
4
-
5
- include LogUtils::Logging
6
-
7
- include ManifestHelper
8
-
9
- def initialize( opts )
10
- @opts = opts
11
- end
12
-
13
- attr_reader :opts
14
-
15
- def list
16
- home = Env.home
17
- ## replace home w/ ~ (to make out more readable (shorter))
18
- ## e.g. use gsub( home, '~' )
19
-
20
- puts ''
21
- puts 'Installed template packs in search path'
22
-
23
- installed_template_manifest_patterns.each_with_index do |pattern,i|
24
- puts " [#{i+1}] #{pattern.gsub(home,'~')}"
25
- end
26
- puts ' include:'
27
-
28
- manifests = installed_template_manifests
29
- if manifests.empty?
30
- puts " -- none --"
31
- else
32
- manifests.each do |manifest|
33
- pakname = manifest[0].gsub('.txt','')
34
- manifestpath = manifest[1].gsub(home,'~')
35
- puts "%16s (%s)" % [pakname,manifestpath]
36
- end
37
- end
38
- end # method list
39
-
40
- end # class Lister
41
-
42
- end # module Pluto