pluto 1.0.1 → 1.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.
- checksums.yaml +7 -0
- data/HISTORY.md +3 -2
- data/Manifest.txt +1 -25
- data/README.md +8 -98
- data/Rakefile +9 -13
- data/lib/pluto.rb +7 -134
- data/lib/pluto/cli/main.rb +16 -6
- data/lib/pluto/cli/opts.rb +4 -1
- data/lib/pluto/cli/version.rb +24 -0
- metadata +79 -103
- data/.gemtest +0 -0
- data/config/pluto.index.yml +0 -23
- data/lib/pluto/activerecord.rb +0 -18
- data/lib/pluto/connecter.rb +0 -96
- data/lib/pluto/fetcher.rb +0 -292
- data/lib/pluto/formatter.rb +0 -81
- data/lib/pluto/installer.rb +0 -58
- data/lib/pluto/lister.rb +0 -42
- data/lib/pluto/manifest_helpers.rb +0 -50
- data/lib/pluto/models/activity.rb +0 -8
- data/lib/pluto/models/feed.rb +0 -127
- data/lib/pluto/models/item.rb +0 -73
- data/lib/pluto/models/site.rb +0 -19
- data/lib/pluto/models/subscription.rb +0 -14
- data/lib/pluto/models/utils.rb +0 -47
- data/lib/pluto/refresher.rb +0 -130
- data/lib/pluto/schema.rb +0 -139
- data/lib/pluto/subscriber.rb +0 -102
- data/lib/pluto/tasks/env.rake +0 -25
- data/lib/pluto/tasks/setup.rake +0 -40
- data/lib/pluto/tasks/stats.rake +0 -10
- data/lib/pluto/tasks/update.rake +0 -24
- data/lib/pluto/updater.rb +0 -50
- data/lib/pluto/version.rb +0 -4
- data/test/helper.rb +0 -18
- data/test/test_helpers.rb +0 -15
@@ -1,50 +0,0 @@
|
|
1
|
-
module Pluto
|
2
|
-
|
3
|
-
module ManifestHelper
|
4
|
-
|
5
|
-
## shared methods for handling manifest lookups
|
6
|
-
##
|
7
|
-
# note: required attribs (in host class) include:
|
8
|
-
# - opts.config_path
|
9
|
-
|
10
|
-
def installed_template_manifest_patterns
|
11
|
-
|
12
|
-
# 1) search . # that is, working/current dir
|
13
|
-
# 2) search <config_dir>
|
14
|
-
# 3) search <gem>/templates
|
15
|
-
|
16
|
-
###
|
17
|
-
# Note
|
18
|
-
# -- for now - no longer ship w/ builtin template packs
|
19
|
-
# - download on demand if needed
|
20
|
-
|
21
|
-
builtin_patterns = [
|
22
|
-
## "#{Pluto.root}/templates/*.txt"
|
23
|
-
]
|
24
|
-
config_patterns = [
|
25
|
-
## "#{File.expand_path(opts.config_path)}/*.txt",
|
26
|
-
"#{File.expand_path(opts.config_path)}/*/*.txt"
|
27
|
-
]
|
28
|
-
current_patterns = [
|
29
|
-
## "*.txt",
|
30
|
-
"*/*.txt"
|
31
|
-
]
|
32
|
-
|
33
|
-
patterns = []
|
34
|
-
patterns += current_patterns
|
35
|
-
patterns += config_patterns
|
36
|
-
patterns += builtin_patterns
|
37
|
-
end
|
38
|
-
|
39
|
-
def installed_template_manifests
|
40
|
-
excludes = [
|
41
|
-
"Manifest.txt",
|
42
|
-
"*/Manifest.txt"
|
43
|
-
]
|
44
|
-
|
45
|
-
Pakman::Finder.new.find_manifests( installed_template_manifest_patterns, excludes )
|
46
|
-
end
|
47
|
-
|
48
|
-
|
49
|
-
end # module Manifest
|
50
|
-
end # module Slideshow
|
data/lib/pluto/models/feed.rb
DELETED
@@ -1,127 +0,0 @@
|
|
1
|
-
module Pluto
|
2
|
-
module Models
|
3
|
-
|
4
|
-
class Feed < ActiveRecord::Base
|
5
|
-
self.table_name = 'feeds'
|
6
|
-
|
7
|
-
include Pluto::ActiveRecordMethods # e.g. read_attribute_w_fallbacks
|
8
|
-
|
9
|
-
has_many :items
|
10
|
-
has_many :subscriptions
|
11
|
-
has_many :sites, :through => :subscriptions
|
12
|
-
|
13
|
-
|
14
|
-
def self.latest
|
15
|
-
# note: order by first non-null datetime field
|
16
|
-
# coalesce - supported by sqlite (yes), postgres (yes)
|
17
|
-
|
18
|
-
# note: if not published, touched or built use hardcoded 1971-01-01 for now
|
19
|
-
## order( "coalesce(published,touched,built,'1971-01-01') desc" )
|
20
|
-
order( "coalesce(feeds.last_published,'1971-01-01') desc" )
|
21
|
-
end
|
22
|
-
|
23
|
-
##################################
|
24
|
-
# attribute reader aliases
|
25
|
-
#
|
26
|
-
# todo: check if we can use alias_method :name, :title - works for non-existing/on-demand-generated method too??
|
27
|
-
|
28
|
-
def name() title; end # alias for title
|
29
|
-
def description() summary; end # alias for summary -- also add descr shortcut??
|
30
|
-
def link() url; end # alias for url
|
31
|
-
def feed() feed_url; end # alias for feed_url
|
32
|
-
|
33
|
-
def url?() read_attribute(:url).present?; end
|
34
|
-
def title?() read_attribute(:title).present?; end
|
35
|
-
def title2?() read_attribute(:title2).present?; end
|
36
|
-
def feed_url?() read_attribute(:feed_url).present?; end
|
37
|
-
|
38
|
-
def url() read_attribute_w_fallbacks( :url, :auto_url ); end
|
39
|
-
def title() read_attribute_w_fallbacks( :title, :auto_title ); end
|
40
|
-
def title2() read_attribute_w_fallbacks( :title2, :auto_title2 ); end
|
41
|
-
def feed_url() read_attribute_w_fallbacks( :feed_url, :auto_feed_url ); end
|
42
|
-
|
43
|
-
|
44
|
-
def published?() read_attribute(:published).present?; end
|
45
|
-
def touched?() read_attribute(:touched).present?; end
|
46
|
-
|
47
|
-
|
48
|
-
def published
|
49
|
-
## todo/fix: use a new name - do NOT squeeze convenience lookup into existing
|
50
|
-
# db backed attribute
|
51
|
-
|
52
|
-
read_attribute_w_fallbacks(
|
53
|
-
:published,
|
54
|
-
:touched, # try touched (aka updated (ATOM))
|
55
|
-
:built # try build (aka lastBuildDate (RSS))
|
56
|
-
)
|
57
|
-
end
|
58
|
-
|
59
|
-
|
60
|
-
def debug=(value) @debug = value; end
|
61
|
-
def debug?() @debug || false; end
|
62
|
-
|
63
|
-
def save_from_struct!( data )
|
64
|
-
|
65
|
-
update_from_struct!( data )
|
66
|
-
|
67
|
-
data.items.each do |item|
|
68
|
-
|
69
|
-
item_rec = Item.find_by_guid( item.guid )
|
70
|
-
if item_rec.nil?
|
71
|
-
item_rec = Item.new
|
72
|
-
puts "** NEW | #{item.title}"
|
73
|
-
else
|
74
|
-
## todo: check if any attribs changed
|
75
|
-
puts "UPDATE | #{item.title}"
|
76
|
-
end
|
77
|
-
|
78
|
-
item_rec.debug = debug? ? true : false # pass along debug flag
|
79
|
-
item_rec.update_from_struct!( self, item )
|
80
|
-
|
81
|
-
end # each item
|
82
|
-
end
|
83
|
-
|
84
|
-
|
85
|
-
def update_from_struct!( data )
|
86
|
-
|
87
|
-
## todo: move to FeedUtils::Feed ??? why? why not??
|
88
|
-
if data.generator
|
89
|
-
generator_full = ''
|
90
|
-
generator_full << data.generator
|
91
|
-
generator_full << " @version=#{data.generator_version}" if data.generator_version
|
92
|
-
generator_full << " @uri=#{data.generator_uri}" if data.generator_uri
|
93
|
-
else
|
94
|
-
generator_full = nil
|
95
|
-
end
|
96
|
-
|
97
|
-
feed_attribs = {
|
98
|
-
format: data.format,
|
99
|
-
published: data.published,
|
100
|
-
touched: data.updated,
|
101
|
-
built: data.built,
|
102
|
-
summary: data.summary,
|
103
|
-
### todo/fix: add/use
|
104
|
-
# auto_title: ???,
|
105
|
-
# auto_url: ???,
|
106
|
-
# auto_feed_url: ???,
|
107
|
-
auto_title2: data.title2,
|
108
|
-
generator: generator_full
|
109
|
-
}
|
110
|
-
|
111
|
-
if debug?
|
112
|
-
## puts "*** dump feed_attribs:"
|
113
|
-
## pp feed_attribs
|
114
|
-
puts "*** dump feed_attribs w/ class types:"
|
115
|
-
feed_attribs.each do |key,value|
|
116
|
-
puts " #{key}: >#{value}< : #{value.class.name}"
|
117
|
-
end
|
118
|
-
end
|
119
|
-
|
120
|
-
update_attributes!( feed_attribs )
|
121
|
-
end
|
122
|
-
|
123
|
-
end # class Feed
|
124
|
-
|
125
|
-
|
126
|
-
end # module Models
|
127
|
-
end # module Pluto
|
data/lib/pluto/models/item.rb
DELETED
@@ -1,73 +0,0 @@
|
|
1
|
-
module Pluto
|
2
|
-
module Models
|
3
|
-
|
4
|
-
class Item < ActiveRecord::Base
|
5
|
-
self.table_name = 'items'
|
6
|
-
|
7
|
-
include Pluto::ActiveRecordMethods # e.g. read_attribute_w_fallbacks
|
8
|
-
|
9
|
-
belongs_to :feed
|
10
|
-
|
11
|
-
##################################
|
12
|
-
# attribute reader aliases
|
13
|
-
def name() title; end # alias for title
|
14
|
-
def description() summary; end # alias for summary -- also add descr shortcut??
|
15
|
-
def link() url; end # alias for url
|
16
|
-
|
17
|
-
def self.latest
|
18
|
-
# note: order by first non-null datetime field
|
19
|
-
# coalesce - supported by sqlite (yes), postgres (yes)
|
20
|
-
|
21
|
-
# note: if not published,touched or built_at use hardcoded 1971-01-01 for now
|
22
|
-
order( "coalesce(items.published,items.touched,'1971-01-01') desc" )
|
23
|
-
end
|
24
|
-
|
25
|
-
def published?() read_attribute(:published).present?; end
|
26
|
-
|
27
|
-
def published
|
28
|
-
## todo/fix: use a new name - do NOT squeeze convenience lookup into existing
|
29
|
-
# db backed attribute
|
30
|
-
|
31
|
-
read_attribute_w_fallbacks(
|
32
|
-
:published,
|
33
|
-
:touched # try touched (aka updated RSS/ATOM)
|
34
|
-
)
|
35
|
-
end
|
36
|
-
|
37
|
-
|
38
|
-
|
39
|
-
def debug=(value) @debug = value; end
|
40
|
-
def debug?() @debug || false; end
|
41
|
-
|
42
|
-
def update_from_struct!( feed_rec, data )
|
43
|
-
## check: new item/record? not saved? add guid
|
44
|
-
# otherwise do not add guid - why? why not?
|
45
|
-
|
46
|
-
item_attribs = {
|
47
|
-
guid: data.guid, # todo: only add for new records???
|
48
|
-
title: data.title,
|
49
|
-
url: data.url,
|
50
|
-
summary: data.summary,
|
51
|
-
content: data.content,
|
52
|
-
published: data.published,
|
53
|
-
touched: data.updated,
|
54
|
-
feed_id: feed_rec.id, # add feed_id fk_ref
|
55
|
-
fetched: feed_rec.fetched
|
56
|
-
}
|
57
|
-
|
58
|
-
if debug?
|
59
|
-
puts "*** dump item_attribs w/ class types:"
|
60
|
-
item_attribs.each do |key,value|
|
61
|
-
next if [:summary,:content].include?( key ) # skip summary n content
|
62
|
-
puts " #{key}: >#{value}< : #{value.class.name}"
|
63
|
-
end
|
64
|
-
end
|
65
|
-
|
66
|
-
update_attributes!( item_attribs )
|
67
|
-
end
|
68
|
-
|
69
|
-
end # class Item
|
70
|
-
|
71
|
-
|
72
|
-
end # module Models
|
73
|
-
end # module Pluto
|
data/lib/pluto/models/site.rb
DELETED
@@ -1,19 +0,0 @@
|
|
1
|
-
module Pluto
|
2
|
-
module Models
|
3
|
-
|
4
|
-
class Site < ActiveRecord::Base
|
5
|
-
self.table_name = 'sites'
|
6
|
-
|
7
|
-
has_many :subscriptions
|
8
|
-
has_many :feeds, :through => :subscriptions
|
9
|
-
has_many :items, :through => :feeds
|
10
|
-
|
11
|
-
##################################
|
12
|
-
# attribute reader aliases
|
13
|
-
def name() title; end # alias for title
|
14
|
-
def fetched_at() fetched; end # - legacy attrib reader -- remove!!!
|
15
|
-
|
16
|
-
end
|
17
|
-
|
18
|
-
end # module Models
|
19
|
-
end # module Pluto
|
data/lib/pluto/models/utils.rb
DELETED
@@ -1,47 +0,0 @@
|
|
1
|
-
module Pluto
|
2
|
-
module Models
|
3
|
-
|
4
|
-
class ItemCursor
|
5
|
-
|
6
|
-
def initialize( items )
|
7
|
-
@items = items
|
8
|
-
end
|
9
|
-
|
10
|
-
def each
|
11
|
-
last_published = Time.local( 1971, 1, 1 )
|
12
|
-
last_feed_id = -1 ## todo: use feed_key instead of id?? why? why not??
|
13
|
-
|
14
|
-
@items.each do |item|
|
15
|
-
|
16
|
-
item_published = item.published # cache published value ref
|
17
|
-
|
18
|
-
if last_published.year == item_published.year &&
|
19
|
-
last_published.month == item_published.month &&
|
20
|
-
last_published.day == item_published.day
|
21
|
-
new_date = false
|
22
|
-
else
|
23
|
-
new_date = true
|
24
|
-
end
|
25
|
-
|
26
|
-
## note:
|
27
|
-
# new date also **always** starts new feed
|
28
|
-
# - e.g. used for grouping within day (follows planet planet convention)
|
29
|
-
|
30
|
-
if new_date || last_feed_id != item.feed.id
|
31
|
-
new_feed = true
|
32
|
-
else
|
33
|
-
new_feed = false
|
34
|
-
end
|
35
|
-
|
36
|
-
yield( item, new_date, new_feed )
|
37
|
-
|
38
|
-
last_published = item.published
|
39
|
-
last_feed_id = item.feed.id
|
40
|
-
end
|
41
|
-
end # method each
|
42
|
-
|
43
|
-
end # class ItemCursor
|
44
|
-
|
45
|
-
|
46
|
-
end # module Models
|
47
|
-
end # module Pluto
|
data/lib/pluto/refresher.rb
DELETED
@@ -1,130 +0,0 @@
|
|
1
|
-
module Pluto
|
2
|
-
|
3
|
-
class Refresher
|
4
|
-
|
5
|
-
include LogUtils::Logging
|
6
|
-
|
7
|
-
include Models
|
8
|
-
|
9
|
-
def initialize
|
10
|
-
@worker = Fetcher.new
|
11
|
-
end
|
12
|
-
|
13
|
-
def debug=(value) @debug = value; end
|
14
|
-
def debug?() @debug || false; end
|
15
|
-
|
16
|
-
|
17
|
-
def update_sites( opts={} ) # update all site configs
|
18
|
-
if debug?
|
19
|
-
## turn on logging for sql too
|
20
|
-
ActiveRecord::Base.logger = Logger.new( STDOUT )
|
21
|
-
@worker.debug = true # also pass along worker debug flag if set
|
22
|
-
end
|
23
|
-
|
24
|
-
# -- log update activity
|
25
|
-
Activity.create!( text: "update sites (#{Site.count})" )
|
26
|
-
|
27
|
-
#### - hack - use order(:id) instead of .all - avoids rails/activerecord 4 warnings
|
28
|
-
|
29
|
-
Site.order(:id).each do |site|
|
30
|
-
update_site_worker( site ) if site.url.present? # note: only update if (source) url present
|
31
|
-
end
|
32
|
-
end
|
33
|
-
|
34
|
-
|
35
|
-
def update_feeds( opts={} ) # update all feeds
|
36
|
-
if debug?
|
37
|
-
## turn on logging for sql too
|
38
|
-
ActiveRecord::Base.logger = Logger.new( STDOUT )
|
39
|
-
@worker.debug = true # also pass along worker debug flag if set
|
40
|
-
end
|
41
|
-
|
42
|
-
# -- log update activity
|
43
|
-
Activity.create!( text: "update feeds (#{Feed.count})" )
|
44
|
-
|
45
|
-
#### - hack - use order(:id) instead of .all - avoids rails/activerecord 4 warnings
|
46
|
-
|
47
|
-
Feed.order(:id).each do |feed|
|
48
|
-
update_feed_worker( feed )
|
49
|
-
end
|
50
|
-
end
|
51
|
-
|
52
|
-
|
53
|
-
def update_feeds_for( site_key, opts={} )
|
54
|
-
if debug?
|
55
|
-
## turn on logging for sql too
|
56
|
-
ActiveRecord::Base.logger = Logger.new( STDOUT )
|
57
|
-
@worker.debug = true # also pass along worker debug flag if set
|
58
|
-
end
|
59
|
-
|
60
|
-
# -- log update activity
|
61
|
-
Activity.create!( text: "update feeds >#{site_key}<" )
|
62
|
-
|
63
|
-
site = Site.find_by_key!( site_key )
|
64
|
-
|
65
|
-
site.feeds.each do |feed|
|
66
|
-
update_feed_worker( feed )
|
67
|
-
end
|
68
|
-
|
69
|
-
end # method update_feeds
|
70
|
-
|
71
|
-
|
72
|
-
private
|
73
|
-
def update_site_worker( site_rec )
|
74
|
-
site_config = @worker.site_by_rec_if_modified( site_rec )
|
75
|
-
|
76
|
-
# on error or if http-not modified etc. skip update/processing
|
77
|
-
return if site_config.nil?
|
78
|
-
|
79
|
-
subscriber = Subscriber.new
|
80
|
-
subscriber.debug = debug? ? true : false # pass along debug flag
|
81
|
-
|
82
|
-
site_key = site_rec.key
|
83
|
-
subscriber.update_subscriptions_for( site_key, site_config )
|
84
|
-
end
|
85
|
-
|
86
|
-
|
87
|
-
def update_feed_worker( feed_rec )
|
88
|
-
feed = @worker.feed_by_rec_if_modified( feed_rec )
|
89
|
-
|
90
|
-
# on error or if http-not modified etc. skip update/processing
|
91
|
-
return if feed.nil?
|
92
|
-
|
93
|
-
## fix/todo: reload feed_red - fetched date updated etc.
|
94
|
-
## check if needed for access to fetched date
|
95
|
-
|
96
|
-
|
97
|
-
## todo/check: move feed_rec update to the end (after item updates??)
|
98
|
-
|
99
|
-
# update feed attribs e.g.
|
100
|
-
# generator
|
101
|
-
# published_at,built_at,touched_at,fetched_at
|
102
|
-
# summary,title2
|
103
|
-
|
104
|
-
## fix:
|
105
|
-
## weird rss exception error on windows w/ dates
|
106
|
-
# e.g. /lib/ruby/1.9.1/rss/rss.rb:37:in `w3cdtf': wrong number of arguments (1 for 0) (ArgumentError)
|
107
|
-
#
|
108
|
-
# move to_datetime to feedutils!! if it works
|
109
|
-
## todo: move this comments to feedutils??
|
110
|
-
|
111
|
-
|
112
|
-
feed_rec.debug = debug? ? true : false # pass along debug flag
|
113
|
-
## fix/todo: pass debug flag as opts - debug: true|false !!!!!!
|
114
|
-
feed_rec.save_from_struct!( feed ) # todo: find a better name - why? why not??
|
115
|
-
|
116
|
-
|
117
|
-
# update cached value last published for item
|
118
|
-
last_item_rec = feed_rec.items.latest.limit(1).first # note limit(1) will return relation/arrar - use first to get first element or nil from ary
|
119
|
-
if last_item_rec.present?
|
120
|
-
if last_item_rec.published?
|
121
|
-
feed_rec.update_attributes!( last_published: last_item_rec.published )
|
122
|
-
else # try touched
|
123
|
-
feed_rec.update_attributes!( last_published: last_item_rec.touched )
|
124
|
-
end
|
125
|
-
end
|
126
|
-
end # method update_feed_worker
|
127
|
-
|
128
|
-
end # class Refresher
|
129
|
-
|
130
|
-
end # module Pluto
|