automatic 14.12.2 → 26.08
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 +5 -5
- data/README.md +635 -83
- data/VERSION +1 -1
- data/automatic.gemspec +109 -248
- data/bin/automatic +20 -139
- data/config/feed2console.yml +10 -4
- data/config/feed2markdown.yml +41 -0
- data/doc/AI_TUTORIAL.md +518 -0
- data/doc/BASIC_DESIGN.md +516 -0
- data/doc/COPYING.LESSER +165 -0
- data/doc/DEPLOYMENT.md +824 -0
- data/doc/LICENSE.md +14 -0
- data/doc/PLUGINS.md +1875 -0
- data/doc/PLUGIN_DEVELOPMENT.md +86 -0
- data/doc/POLICY.md +857 -0
- data/doc/QUICKSTART.md +256 -0
- data/doc/RELEASING.md +381 -0
- data/doc/REQUIREMENTS.md +526 -0
- data/doc/VERSIONS +208 -0
- data/lib/automatic/cli.rb +248 -0
- data/lib/automatic/environment.rb +31 -5
- data/lib/automatic/feed_maker.rb +10 -9
- data/lib/automatic/feed_parser.rb +51 -35
- data/lib/automatic/http.rb +107 -0
- data/lib/automatic/log.rb +49 -18
- data/lib/automatic/opml.rb +3 -1
- data/lib/automatic/pipeline.rb +63 -32
- data/lib/automatic/recipe.rb +56 -17
- data/lib/automatic/version.rb +14 -1
- data/lib/automatic.rb +78 -20
- data/plugins/custom_feed/svn_log.rb +73 -32
- data/plugins/custom_feed/web.rb +348 -0
- data/plugins/filter/absolute_uri.rb +43 -27
- data/plugins/filter/accept.rb +38 -45
- data/plugins/filter/claude.rb +217 -0
- data/plugins/filter/clear.rb +12 -8
- data/plugins/filter/description_link.rb +49 -51
- data/plugins/filter/full_feed.rb +158 -52
- data/plugins/filter/gemini.rb +216 -0
- data/plugins/filter/github_feed.rb +38 -26
- data/plugins/filter/ignore.rb +33 -44
- data/plugins/filter/image.rb +36 -25
- data/plugins/filter/image_source.rb +58 -52
- data/plugins/filter/join.rb +107 -0
- data/plugins/filter/one.rb +19 -26
- data/plugins/filter/open_ai.rb +198 -0
- data/plugins/filter/rand.rb +16 -17
- data/plugins/filter/sakura_ai.rb +205 -0
- data/plugins/filter/sanitize.rb +29 -34
- data/plugins/filter/sort.rb +20 -27
- data/plugins/filter/tumblr_resize.rb +31 -23
- data/plugins/notify/ikachan.rb +86 -48
- data/plugins/provide/fluentd.rb +43 -24
- data/plugins/publish/amazon_s3.rb +73 -40
- data/plugins/publish/console.rb +19 -16
- data/plugins/publish/console_link.rb +20 -17
- data/plugins/publish/eject.rb +48 -26
- data/plugins/publish/fluentd.rb +50 -30
- data/plugins/publish/hatena_bookmark.rb +88 -71
- data/plugins/publish/instapaper.rb +69 -59
- data/plugins/publish/markdown.rb +278 -0
- data/plugins/publish/memcached.rb +35 -29
- data/plugins/store/database.rb +50 -48
- data/plugins/store/digest.rb +212 -0
- data/plugins/store/file.rb +99 -68
- data/plugins/store/full_text.rb +32 -25
- data/plugins/store/permalink.rb +18 -22
- data/plugins/subscription/feed.rb +34 -21
- data/plugins/subscription/link.rb +31 -32
- data/plugins/subscription/text.rb +32 -46
- data/plugins/subscription/tumblr.rb +55 -44
- data/plugins/subscription/xml.rb +40 -36
- metadata +108 -321
- data/Gemfile +0 -38
- data/Rakefile +0 -59
- data/doc/ChangeLog +0 -303
- data/doc/PLUGINS +0 -750
- data/doc/PLUGINS.ja +0 -753
- data/doc/README +0 -511
- data/doc/README.ja +0 -519
- data/plugins/filter/google_news.rb +0 -50
- data/plugins/publish/google_calendar.rb +0 -84
- data/plugins/publish/hipchat.rb +0 -46
- data/plugins/publish/pocket.rb +0 -45
- data/plugins/publish/twitter.rb +0 -58
- data/plugins/subscription/chan_toru.rb +0 -57
- data/plugins/subscription/g_guide.rb +0 -57
- data/plugins/subscription/pocket.rb +0 -51
- data/plugins/subscription/twitter.rb +0 -69
- data/plugins/subscription/twitter_search.rb +0 -50
- data/plugins/subscription/weather.rb +0 -33
- data/script/build +0 -84
- data/spec/fixtures/sampleFeeds.tsv +0 -1
- data/spec/fixtures/sampleFeeds2.tsv +0 -2
- data/spec/fixtures/sampleRecipe.yml +0 -24
- data/spec/lib/automatic/log_spec.rb +0 -32
- data/spec/lib/automatic/pipeline_spec.rb +0 -68
- data/spec/lib/automatic/recipe_spec.rb +0 -40
- data/spec/lib/automatic_spec.rb +0 -99
- data/spec/plugins/custom_feed/svn_log_spec.rb +0 -31
- data/spec/plugins/filter/absolute_uri_spec.rb +0 -61
- data/spec/plugins/filter/accept_spec.rb +0 -331
- data/spec/plugins/filter/clear_spec.rb +0 -49
- data/spec/plugins/filter/description_link_spec.rb +0 -138
- data/spec/plugins/filter/full_feed_spec.rb +0 -129
- data/spec/plugins/filter/github_feed_spec.rb +0 -55
- data/spec/plugins/filter/google_news_spec.rb +0 -69
- data/spec/plugins/filter/ignore_spec.rb +0 -328
- data/spec/plugins/filter/image_source_spec.rb +0 -89
- data/spec/plugins/filter/image_spec.rb +0 -65
- data/spec/plugins/filter/one_spec.rb +0 -71
- data/spec/plugins/filter/rand_spec.rb +0 -52
- data/spec/plugins/filter/sanitize_spec.rb +0 -153
- data/spec/plugins/filter/sort_spec.rb +0 -189
- data/spec/plugins/filter/tumblr_resize_spec.rb +0 -109
- data/spec/plugins/notify/ikachan_spec.rb +0 -58
- data/spec/plugins/provide/fluentd_spec.rb +0 -49
- data/spec/plugins/publish/amazon_s3_spec.rb +0 -40
- data/spec/plugins/publish/console_spec.rb +0 -30
- data/spec/plugins/publish/eject_spec.rb +0 -40
- data/spec/plugins/publish/fluentd_spec.rb +0 -40
- data/spec/plugins/publish/google_calendar_spec.rb +0 -83
- data/spec/plugins/publish/hatena_bookmark_spec.rb +0 -134
- data/spec/plugins/publish/hipchat_spec.rb +0 -69
- data/spec/plugins/publish/instapaper_spec.rb +0 -82
- data/spec/plugins/publish/memcached_spec.rb +0 -63
- data/spec/plugins/publish/pocket_spec.rb +0 -51
- data/spec/plugins/publish/twitter_spec.rb +0 -73
- data/spec/plugins/store/file_spec.rb +0 -58
- data/spec/plugins/store/full_text_spec.rb +0 -152
- data/spec/plugins/store/permalink_spec.rb +0 -206
- data/spec/plugins/subscription/chan_toru_spec.rb +0 -56
- data/spec/plugins/subscription/feed_spec.rb +0 -71
- data/spec/plugins/subscription/g_guide_spec.rb +0 -82
- data/spec/plugins/subscription/link_spec.rb +0 -72
- data/spec/plugins/subscription/pocket_spec.rb +0 -57
- data/spec/plugins/subscription/text_spec.rb +0 -84
- data/spec/plugins/subscription/tumblr_spec.rb +0 -74
- data/spec/plugins/subscription/twitter_search_spec.rb +0 -57
- data/spec/plugins/subscription/twitter_spec.rb +0 -73
- data/spec/plugins/subscription/weather_spec.rb +0 -44
- data/spec/plugins/subscription/xml_spec.rb +0 -84
- data/spec/spec_helper.rb +0 -106
- data/spec/user_dir/plugins/store/mock.rb +0 -16
- data/test/fixtures/sampleOPML.xml +0 -11
- data/test/integration/test_absoluteurl.yml +0 -25
- data/test/integration/test_activerecord.yml +0 -24
- data/test/integration/test_add_pocket.yml +0 -26
- data/test/integration/test_chan_toru.yml +0 -21
- data/test/integration/test_descriptionlink.yml +0 -21
- data/test/integration/test_fluentd.yml +0 -22
- data/test/integration/test_fulltext.yml +0 -30
- data/test/integration/test_google_news.yml +0 -21
- data/test/integration/test_googlealert.yml +0 -21
- data/test/integration/test_hatenabookmark.yml +0 -30
- data/test/integration/test_ignore.yml +0 -25
- data/test/integration/test_ignore2.yml +0 -22
- data/test/integration/test_image2local.yml +0 -33
- data/test/integration/test_instapaper.yml +0 -26
- data/test/integration/test_link2local.yml +0 -34
- data/test/integration/test_one.yml +0 -23
- data/test/integration/test_pocket.yml +0 -22
- data/test/integration/test_rand.yml +0 -21
- data/test/integration/test_sanitize.yml +0 -23
- data/test/integration/test_sort.yml +0 -36
- data/test/integration/test_svnlog.yml +0 -15
- data/test/integration/test_text2feed.yml +0 -36
- data/test/integration/test_tumblr2local.yml +0 -43
- data/test/integration/test_twitter_search.yml +0 -22
- data/test/integration/test_weather.yml +0 -19
- data/test/integration/test_xml2fluentd.yml +0 -21
- data/vendor/.gitkeep +0 -0
|
@@ -1,47 +1,46 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
|
-
# Name::
|
|
3
|
-
# Author
|
|
4
|
-
#
|
|
5
|
-
#
|
|
6
|
-
#
|
|
7
|
-
#
|
|
2
|
+
# Name:: Automatic::Plugin::Subscription::Link
|
|
3
|
+
# Author: id774 (More info: http://id774.net)
|
|
4
|
+
# Source Code:: https://github.com/id774/automaticruby
|
|
5
|
+
# License:: The GPL version 3, or LGPL version 3 (Dual License).
|
|
6
|
+
# Contact:: idnanashi@gmail.com
|
|
7
|
+
# Created:: Sep 18, 2012
|
|
8
|
+
# Updated:: Aug 15, 2026
|
|
9
|
+
# Copyright:: Copyright (c) 2012-2026 Automatic Ruby Developers.
|
|
8
10
|
|
|
9
11
|
module Automatic::Plugin
|
|
10
12
|
class SubscriptionLink
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
def initialize(config, pipeline=[])
|
|
15
|
-
@config = config
|
|
13
|
+
def initialize(config, pipeline = [])
|
|
14
|
+
@config = config || {}
|
|
16
15
|
@pipeline = pipeline
|
|
17
16
|
end
|
|
18
17
|
|
|
18
|
+
# Returns only what it fetched, discarding any incoming pipeline.
|
|
19
19
|
def run
|
|
20
|
-
@
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
begin
|
|
25
|
-
create_rss(URI::Parser.new.escape(url))
|
|
26
|
-
rescue
|
|
27
|
-
retries += 1
|
|
28
|
-
Automatic::Log.puts("error", "ErrorCount: #{retries}, Fault in parsing: #{url}")
|
|
29
|
-
sleep ||= @config['interval'].to_i
|
|
30
|
-
retry if retries <= retry_max
|
|
31
|
-
end
|
|
32
|
-
}
|
|
33
|
-
@return_feeds
|
|
20
|
+
Array(@config['urls']).each_with_object([]) do |url, feeds|
|
|
21
|
+
rss = fetch(url)
|
|
22
|
+
feeds << rss unless rss.nil?
|
|
23
|
+
end
|
|
34
24
|
end
|
|
35
25
|
|
|
36
26
|
private
|
|
37
27
|
|
|
38
|
-
def
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
@
|
|
28
|
+
def fetch(url)
|
|
29
|
+
retries = 0
|
|
30
|
+
retry_max = @config['retry'].to_i
|
|
31
|
+
begin
|
|
32
|
+
Automatic::Log.puts('info', "Parsing Link: #{url}")
|
|
33
|
+
rss = Automatic::FeedParser.parse_html(Automatic::Http.read(url))
|
|
34
|
+
sleep(@config['interval'].to_i)
|
|
35
|
+
rss
|
|
36
|
+
rescue StandardError => e
|
|
37
|
+
retries += 1
|
|
38
|
+
Automatic::Log.puts('error',
|
|
39
|
+
"ErrorCount: #{retries}, Fault in parsing: #{url}, #{e.message}")
|
|
40
|
+
return nil if retries > retry_max
|
|
41
|
+
|
|
42
|
+
sleep(@config['interval'].to_i)
|
|
43
|
+
retry
|
|
45
44
|
end
|
|
46
45
|
end
|
|
47
46
|
end
|
|
@@ -1,67 +1,53 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
|
-
# Name::
|
|
3
|
-
# Author
|
|
4
|
-
#
|
|
5
|
-
#
|
|
6
|
-
#
|
|
7
|
-
#
|
|
8
|
-
#
|
|
2
|
+
# Name:: Automatic::Plugin::Subscription::Text
|
|
3
|
+
# Author: soramugi (More info: http://soramugi.net)
|
|
4
|
+
# Source Code:: https://github.com/id774/automaticruby
|
|
5
|
+
# License:: The GPL version 3, or LGPL version 3 (Dual License).
|
|
6
|
+
# Contact:: idnanashi@gmail.com
|
|
7
|
+
# Created:: May 6, 2013
|
|
8
|
+
# Updated:: Aug 15, 2026
|
|
9
|
+
# Copyright:: Copyright (c) 2012-2026 Automatic Ruby Developers.
|
|
9
10
|
|
|
10
11
|
module Automatic::Plugin
|
|
11
12
|
class SubscriptionText
|
|
12
|
-
|
|
13
|
-
|
|
13
|
+
# Columns of a TSV row, in order. A row with fewer columns leaves the rest
|
|
14
|
+
# unset, which is what makes a one-column file of titles a valid input.
|
|
15
|
+
COLUMNS = %w[title url description author comments].freeze
|
|
16
|
+
|
|
17
|
+
def initialize(config, pipeline = [])
|
|
18
|
+
@config = config || {}
|
|
14
19
|
@pipeline = pipeline
|
|
15
|
-
@return_feeds = []
|
|
16
20
|
end
|
|
17
21
|
|
|
22
|
+
# Reaches no network, which is what makes this the plugin to test a
|
|
23
|
+
# Recipe's later half with. Any combination of the four keys may be given.
|
|
18
24
|
def run
|
|
19
|
-
|
|
20
|
-
@pipeline << Automatic::FeedMaker.create_pipeline(
|
|
25
|
+
items = titles + urls + feeds + files
|
|
26
|
+
@pipeline << Automatic::FeedMaker.create_pipeline(items) unless items.empty?
|
|
21
27
|
@pipeline
|
|
22
28
|
end
|
|
23
29
|
|
|
24
30
|
private
|
|
25
31
|
|
|
26
|
-
def
|
|
27
|
-
|
|
28
|
-
|
|
29
|
-
unless @config['titles'].nil?
|
|
30
|
-
@config['titles'].each {|title|
|
|
31
|
-
feed = {}
|
|
32
|
-
feed['title'] = title
|
|
33
|
-
@return_feeds << Automatic::FeedMaker.generate_feed(feed)
|
|
34
|
-
}
|
|
35
|
-
end
|
|
32
|
+
def titles
|
|
33
|
+
Array(@config['titles']).map { |title| Automatic::FeedMaker.generate_feed('title' => title) }
|
|
34
|
+
end
|
|
36
35
|
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
feed['url'] = url
|
|
41
|
-
@return_feeds << Automatic::FeedMaker.generate_feed(feed)
|
|
42
|
-
}
|
|
43
|
-
end
|
|
36
|
+
def urls
|
|
37
|
+
Array(@config['urls']).map { |url| Automatic::FeedMaker.generate_feed('url' => url) }
|
|
38
|
+
end
|
|
44
39
|
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
}
|
|
49
|
-
end
|
|
40
|
+
def feeds
|
|
41
|
+
Array(@config['feeds']).map { |feed| Automatic::FeedMaker.generate_feed(feed) }
|
|
42
|
+
end
|
|
50
43
|
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
feed['title'], feed['url'], feed['description'], feed['author'],
|
|
57
|
-
feed['comments'] = line.force_encoding("utf-8").strip.split("\t")
|
|
58
|
-
@return_feeds << Automatic::FeedMaker.generate_feed(feed)
|
|
59
|
-
end
|
|
60
|
-
end
|
|
61
|
-
}
|
|
44
|
+
# Tab separated, read as UTF-8, and `~` expanded.
|
|
45
|
+
def files
|
|
46
|
+
Array(@config['files']).flat_map do |path|
|
|
47
|
+
File.foreach(File.expand_path(path), encoding: 'UTF-8').map do |line|
|
|
48
|
+
Automatic::FeedMaker.generate_feed(COLUMNS.zip(line.strip.split("\t")).to_h)
|
|
62
49
|
end
|
|
63
50
|
end
|
|
64
51
|
end
|
|
65
|
-
|
|
66
52
|
end
|
|
67
53
|
end
|
|
@@ -1,59 +1,70 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
|
-
# Name::
|
|
3
|
-
# Author
|
|
4
|
-
#
|
|
5
|
-
#
|
|
6
|
-
#
|
|
7
|
-
#
|
|
2
|
+
# Name:: Automatic::Plugin::Subscription::Tumblr
|
|
3
|
+
# Author: id774 (More info: http://id774.net)
|
|
4
|
+
# Source Code:: https://github.com/id774/automaticruby
|
|
5
|
+
# License:: The GPL version 3, or LGPL version 3 (Dual License).
|
|
6
|
+
# Contact:: idnanashi@gmail.com
|
|
7
|
+
# Created:: Oct 16, 2012
|
|
8
|
+
# Updated:: Aug 15, 2026
|
|
9
|
+
# Copyright:: Copyright (c) 2012-2026 Automatic Ruby Developers.
|
|
8
10
|
|
|
9
11
|
module Automatic::Plugin
|
|
10
12
|
class SubscriptionTumblr
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
def initialize(config, pipeline=[])
|
|
14
|
-
@config = config
|
|
13
|
+
def initialize(config, pipeline = [])
|
|
14
|
+
@config = config || {}
|
|
15
15
|
@pipeline = pipeline
|
|
16
16
|
end
|
|
17
17
|
|
|
18
|
+
# Reads HTML written for a browser, so what it finds depends on the theme
|
|
19
|
+
# a given blog uses. Verify against the blog you mean to follow before
|
|
20
|
+
# putting it in cron, and set `interval`.
|
|
18
21
|
def run
|
|
19
|
-
@
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
begin
|
|
24
|
-
create_rss(url)
|
|
25
|
-
unless @config['pages'].nil?
|
|
26
|
-
@config['pages'].times {|i|
|
|
27
|
-
if i > 0
|
|
28
|
-
old_url = url + "/page/" + (i+1).to_s
|
|
29
|
-
create_rss(old_url)
|
|
30
|
-
end
|
|
31
|
-
}
|
|
32
|
-
end
|
|
33
|
-
rescue
|
|
34
|
-
retries += 1
|
|
35
|
-
Automatic::Log.puts("error", "ErrorCount: #{retries}, Fault in parsing: #{url}")
|
|
36
|
-
sleep ||= @config['interval'].to_i
|
|
37
|
-
retry if retries <= retry_max
|
|
22
|
+
Array(@config['urls']).each_with_object([]) do |url, feeds|
|
|
23
|
+
pages(url).each do |page|
|
|
24
|
+
rss = fetch(page, url)
|
|
25
|
+
feeds << rss unless rss.nil?
|
|
38
26
|
end
|
|
39
|
-
|
|
40
|
-
@return_feeds
|
|
27
|
+
end
|
|
41
28
|
end
|
|
42
29
|
|
|
43
30
|
private
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
31
|
+
|
|
32
|
+
# The blog's own page, then /page/2 and onward.
|
|
33
|
+
def pages(url)
|
|
34
|
+
count = @config['pages'].to_i
|
|
35
|
+
return [url] if count < 2
|
|
36
|
+
|
|
37
|
+
[url] + (2..count).map { |number| "#{url}/page/#{number}" }
|
|
38
|
+
end
|
|
39
|
+
|
|
40
|
+
def fetch(url, blog_url)
|
|
41
|
+
retries = 0
|
|
42
|
+
retry_max = @config['retry'].to_i
|
|
43
|
+
begin
|
|
44
|
+
Automatic::Log.puts('info', "Parsing Tumblr: #{url}")
|
|
45
|
+
rss = Automatic::FeedParser.parse_html(Automatic::Http.read(url))
|
|
46
|
+
drop_offsite_links(rss, blog_url)
|
|
47
|
+
sleep(@config['interval'].to_i)
|
|
48
|
+
rss
|
|
49
|
+
rescue StandardError => e
|
|
50
|
+
retries += 1
|
|
51
|
+
Automatic::Log.puts('error',
|
|
52
|
+
"ErrorCount: #{retries}, Fault in parsing: #{url}, #{e.message}")
|
|
53
|
+
return nil if retries > retry_max
|
|
54
|
+
|
|
55
|
+
sleep(@config['interval'].to_i)
|
|
56
|
+
retry
|
|
57
|
+
end
|
|
58
|
+
end
|
|
59
|
+
|
|
60
|
+
# A theme's page carries the blog's own posts and a great deal else. A
|
|
61
|
+
# link that leaves the blog's host is blanked rather than removed, which
|
|
62
|
+
# is the pipeline's way of saying "not applicable"; the plugins after this
|
|
63
|
+
# one skip an item whose link is nil.
|
|
64
|
+
def drop_offsite_links(rss, blog_url)
|
|
65
|
+
host = Automatic::Http.uri(blog_url).host.to_s
|
|
66
|
+
rss.items.each do |item|
|
|
67
|
+
item.link = nil unless item.link.to_s.include?(host)
|
|
57
68
|
end
|
|
58
69
|
end
|
|
59
70
|
end
|
data/plugins/subscription/xml.rb
CHANGED
|
@@ -1,53 +1,57 @@
|
|
|
1
1
|
# -*- coding: utf-8 -*-
|
|
2
|
-
# Name::
|
|
3
|
-
# Author
|
|
4
|
-
#
|
|
5
|
-
#
|
|
6
|
-
#
|
|
7
|
-
#
|
|
2
|
+
# Name:: Automatic::Plugin::Subscription::Xml
|
|
3
|
+
# Author: id774 (More info: http://id774.net)
|
|
4
|
+
# Source Code:: https://github.com/id774/automaticruby
|
|
5
|
+
# License:: The GPL version 3, or LGPL version 3 (Dual License).
|
|
6
|
+
# Contact:: idnanashi@gmail.com
|
|
7
|
+
# Created:: Jul 12, 2013
|
|
8
|
+
# Updated:: Aug 15, 2026
|
|
9
|
+
# Copyright:: Copyright (c) 2012-2026 Automatic Ruby Developers.
|
|
8
10
|
|
|
9
11
|
module Automatic::Plugin
|
|
10
12
|
class SubscriptionXml
|
|
11
|
-
require '
|
|
12
|
-
require '
|
|
13
|
-
require 'active_support/core_ext'
|
|
14
|
-
require 'active_support/deprecation'
|
|
15
|
-
require 'rss'
|
|
13
|
+
require 'active_support/core_ext/hash/conversions'
|
|
14
|
+
require 'json'
|
|
16
15
|
|
|
17
|
-
def initialize(config, pipeline=[])
|
|
18
|
-
@config
|
|
16
|
+
def initialize(config, pipeline = [])
|
|
17
|
+
@config = config || {}
|
|
19
18
|
@pipeline = pipeline
|
|
20
19
|
end
|
|
21
20
|
|
|
22
21
|
def run
|
|
23
|
-
@
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
begin
|
|
28
|
-
create_rss(URI::Parser.new.escape(url))
|
|
29
|
-
rescue
|
|
30
|
-
retries += 1
|
|
31
|
-
Automatic::Log.puts("error", "ErrorCount: #{retries}, Fault in parsing: #{url}")
|
|
32
|
-
sleep ||= @config['interval'].to_i
|
|
33
|
-
retry if retries <= retry_max
|
|
34
|
-
end
|
|
35
|
-
}
|
|
36
|
-
@return_feeds
|
|
22
|
+
Array(@config['urls']).each_with_object([]) do |url, feeds|
|
|
23
|
+
rss = fetch(url)
|
|
24
|
+
feeds << rss unless rss.nil?
|
|
25
|
+
end
|
|
37
26
|
end
|
|
38
27
|
|
|
39
28
|
private
|
|
40
29
|
|
|
41
|
-
def
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
30
|
+
def fetch(url)
|
|
31
|
+
retries = 0
|
|
32
|
+
retry_max = @config['retry'].to_i
|
|
33
|
+
begin
|
|
34
|
+
Automatic::Log.puts('info', "Parsing XML: #{url}")
|
|
35
|
+
rss = Automatic::FeedMaker.content_provide(url, document(url))
|
|
36
|
+
sleep(@config['interval'].to_i)
|
|
37
|
+
rss
|
|
38
|
+
rescue StandardError => e
|
|
39
|
+
retries += 1
|
|
40
|
+
Automatic::Log.puts('error',
|
|
41
|
+
"ErrorCount: #{retries}, Fault in parsing: #{url}, #{e.message}")
|
|
42
|
+
return nil if retries > retry_max
|
|
43
|
+
|
|
44
|
+
sleep(@config['interval'].to_i)
|
|
45
|
+
retry
|
|
50
46
|
end
|
|
51
47
|
end
|
|
48
|
+
|
|
49
|
+
# The document as plain hashes, arrays and strings. The round trip through
|
|
50
|
+
# JSON is what flattens what Hash.from_xml returns -- dates, times and
|
|
51
|
+
# ActiveSupport's own string subclasses -- into the values a consumer such
|
|
52
|
+
# as ProvideFluentd can serialize.
|
|
53
|
+
def document(url)
|
|
54
|
+
JSON.parse(Hash.from_xml(Automatic::Http.read(url)).to_json)
|
|
55
|
+
end
|
|
52
56
|
end
|
|
53
57
|
end
|