automatic 12.2.1

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.
Files changed (60) hide show
  1. data/Gemfile +23 -0
  2. data/README.md +109 -0
  3. data/Rakefile +42 -0
  4. data/VERSION +1 -0
  5. data/app.rb +15 -0
  6. data/automatic.gemspec +122 -0
  7. data/bin/automatic +15 -0
  8. data/config/default.yml +29 -0
  9. data/config/feed2console.yml +15 -0
  10. data/db/.gitkeep +0 -0
  11. data/doc/COPYING +674 -0
  12. data/doc/ChangeLog +17 -0
  13. data/doc/PLUGINS.ja +205 -0
  14. data/doc/README.ja +449 -0
  15. data/lib/automatic.rb +60 -0
  16. data/lib/automatic/environment.rb +8 -0
  17. data/lib/automatic/feed_parser.rb +36 -0
  18. data/lib/automatic/log.rb +24 -0
  19. data/lib/automatic/pipeline.rb +36 -0
  20. data/lib/automatic/recipe.rb +31 -0
  21. data/lib/config/validator.rb +83 -0
  22. data/plugins/custom_feed/svn_log.rb +56 -0
  23. data/plugins/filter/ignore.rb +60 -0
  24. data/plugins/filter/image.rb +47 -0
  25. data/plugins/filter/tumblr_resize.rb +40 -0
  26. data/plugins/notify/ikachan.rb +85 -0
  27. data/plugins/publish/console.rb +31 -0
  28. data/plugins/publish/google_calendar.rb +86 -0
  29. data/plugins/publish/hatena_bookmark.rb +103 -0
  30. data/plugins/store/full_text.rb +57 -0
  31. data/plugins/store/permalink.rb +47 -0
  32. data/plugins/store/store_database.rb +53 -0
  33. data/plugins/store/target_link.rb +47 -0
  34. data/plugins/subscription/feed.rb +30 -0
  35. data/script/bootstrap +117 -0
  36. data/spec/plugins/custom_feed/svn_log_spec.rb +31 -0
  37. data/spec/plugins/filter/ignore_spec.rb +37 -0
  38. data/spec/plugins/filter/image_spec.rb +55 -0
  39. data/spec/plugins/filter/tumblr_resize_spec.rb +102 -0
  40. data/spec/plugins/notify/ikachan_spec.rb +28 -0
  41. data/spec/plugins/publish/console_spec.rb +24 -0
  42. data/spec/plugins/publish/google_calendar_spec.rb +82 -0
  43. data/spec/plugins/publish/hatena_bookmark_spec.rb +36 -0
  44. data/spec/plugins/store/full_text_spec.rb +39 -0
  45. data/spec/plugins/store/permalink_spec.rb +39 -0
  46. data/spec/plugins/store/target_link_spec.rb +30 -0
  47. data/spec/plugins/subscription/feed_spec.rb +36 -0
  48. data/spec/spec_helper.rb +82 -0
  49. data/test/integration/test_activerecord.yml +24 -0
  50. data/test/integration/test_fulltext.yml +24 -0
  51. data/test/integration/test_hatenabookmark.yml +26 -0
  52. data/test/integration/test_ignore.yml +22 -0
  53. data/test/integration/test_ignore2.yml +25 -0
  54. data/test/integration/test_image2local.yml +26 -0
  55. data/test/integration/test_svnlog.yml +14 -0
  56. data/test/integration/test_tumblr2local.yml +26 -0
  57. data/utils/auto_discovery.rb +18 -0
  58. data/utils/opml_parser.rb +247 -0
  59. data/vendor/.gitkeep +0 -0
  60. metadata +205 -0
@@ -0,0 +1,28 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '../../../spec_helper')
2
+
3
+ require 'notify/ikachan'
4
+
5
+ describe Automatic::Plugin::NotifyIkachan do
6
+ paramz = {
7
+ "channels" => "#room",
8
+ "url" => "http://sample.com",
9
+ "port" => "4979",
10
+ "command" => "notice",
11
+ }
12
+ subject {
13
+ Automatic::Plugin::NotifyIkachan.new(
14
+ paramz,
15
+ AutomaticSpec.generate_pipeline {
16
+ feed { item "http://github.com", "GitHub" }
17
+ }
18
+ )
19
+ }
20
+
21
+ it "should post title and link in the feed" do
22
+ ikachan = mock("ikachan")
23
+ ikachan.should_receive(:post).with("http://github.com", "GitHub")
24
+ ikachan.should_receive(:params)
25
+ subject.instance_variable_set(:@ikachan, ikachan)
26
+ subject.run.should have(1).feed
27
+ end
28
+ end
@@ -0,0 +1,24 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '../../../spec_helper')
2
+
3
+ require 'publish/console'
4
+
5
+ describe Automatic::Plugin::PublishConsole do
6
+ before do
7
+ @pipeline = AutomaticSpec.generate_pipeline {
8
+ feed { item "http://github.com" }
9
+ }
10
+ end
11
+
12
+ subject {
13
+ Automatic::Plugin::PublishConsole.new({}, @pipeline)
14
+ }
15
+
16
+ it "should output pretty inspect of feeds" do
17
+ output = mock("output")
18
+ output.should_receive(:puts).
19
+ with("info", @pipeline[0].items[0].pretty_inspect)
20
+ subject.instance_variable_set(:@output, output)
21
+ subject.run
22
+ end
23
+ end
24
+
@@ -0,0 +1,82 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Name:: Automatic::Plugin::CustomFeed::SVNFLog
3
+ # Author:: kzgs
4
+ # Created:: Feb 26, 2012
5
+ # Updated:: Mar 3, 2012
6
+ # Copyright:: kzgs Copyright (c) 2012
7
+ # License:: Licensed under the GNU GENERAL PUBLIC LICENSE, Version 3.0.
8
+
9
+ require File.expand_path(File.dirname(__FILE__) + '../../../spec_helper')
10
+
11
+ require 'publish/google_calendar'
12
+ require 'gcalapi'
13
+
14
+ describe Automatic::Plugin::PublishGoogleCalendar do
15
+ subject {
16
+ Automatic::Plugin::PublishGoogleCalendar.new(
17
+ {"username" => "user", "password" => "pswd"},
18
+ AutomaticSpec.generate_pipeline{
19
+ feed {
20
+ item "http://github.com", "GitHub"
21
+ }
22
+ })
23
+ }
24
+
25
+ it "should post the link in the feed" do
26
+ gc = mock("gc")
27
+ gc.should_receive(:add).with("今日 GitHub")
28
+ subject.instance_variable_set(:@gc, gc)
29
+ subject.run.should have(1).feed
30
+ end
31
+ end
32
+
33
+ describe Automatic::Plugin::Googlecalendar do
34
+ describe "#add" do
35
+ context "All day events" do
36
+ specify {
37
+ set_gcal_mock(all_day_event_mock(
38
+ "花火@晴海", "", Time.mktime(2012, 8, 15)))
39
+ Automatic::Plugin::Googlecalendar.new.add("2012/8/15 花火@晴海")
40
+ }
41
+
42
+ specify {
43
+ lambda {
44
+ Automatic::Plugin::Googlecalendar.new.add("2012/2/30")
45
+ }.should raise_exception(RuntimeError, /不正な日付形式-1/)
46
+ }
47
+ end
48
+ end
49
+ end
50
+
51
+ def all_day_event_mock(title, where, date=nil)
52
+ event = mock("event")
53
+ {
54
+ :title => title,
55
+ :st => date.nil? ? nil : Time.mktime(date.year, date.month, date.day),
56
+ :en => nil,
57
+ :allday => true
58
+ }.each_pair do |key, value|
59
+ if value.nil?
60
+ event.should_receive("#{key}=".to_sym)
61
+ else
62
+ event.should_receive("#{key}=".to_sym).with(value)
63
+ end
64
+ end
65
+ event.should_receive(:st)
66
+ event.should_receive(:save!)
67
+ return event
68
+ end
69
+
70
+ def cal_mock(event_mock)
71
+ cal = mock("cal")
72
+ cal.should_receive(:create_event).and_return {
73
+ event_mock
74
+ }
75
+ return cal
76
+ end
77
+
78
+ def set_gcal_mock(event_mock)
79
+ GoogleCalendar::Calendar.stub(:new) {
80
+ cal_mock(event_mock)
81
+ }
82
+ end
@@ -0,0 +1,36 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '../../../spec_helper')
2
+
3
+ require 'publish/hatena_bookmark'
4
+
5
+ describe Automatic::Plugin::PublishHatenaBookmark do
6
+ subject {
7
+ Automatic::Plugin::PublishHatenaBookmark.new(
8
+ {"username" => "user", "password" => "pswd"},
9
+ AutomaticSpec.generate_pipeline{
10
+ feed { item "http://github.com" }
11
+ })
12
+ }
13
+
14
+ it "should post the link in the feed" do
15
+ hb = mock("hb")
16
+ hb.should_receive(:post).with("http://github.com", nil)
17
+ subject.instance_variable_set(:@hb, hb)
18
+ subject.run.should have(1).feed
19
+ end
20
+ end
21
+
22
+ describe Automatic::Plugin::HatenaBookmark do
23
+ describe "#wsse" do
24
+ subject {
25
+ Automatic::Plugin::HatenaBookmark.new.wsse("anonymous", "pswd")
26
+ }
27
+
28
+ it { should be_has_key('X-WSSE') }
29
+
30
+ specify {
31
+ subject['X-WSSE'].should match(
32
+ /^UsernameToken\sUsername="anonymous",\sPasswordDigest=".+", Nonce=".+", Created="\d{4}-\d{2}-\d{2}T\d{2}:\d{2}:\d{2}Z"/)
33
+ }
34
+ end
35
+ end
36
+
@@ -0,0 +1,39 @@
1
+
2
+ require File.expand_path(File.dirname(__FILE__) + '../../../spec_helper')
3
+
4
+ require 'store/full_text'
5
+
6
+ require 'pathname'
7
+
8
+ describe Automatic::Plugin::StoreFullText do
9
+ before do
10
+ @db_filename = "test_full_text.db"
11
+ db_path = Pathname(AutomaticSpec.db_dir).cleanpath+"#{@db_filename}"
12
+ db_path.delete if db_path.exist?
13
+ Automatic::Plugin::StoreFullText.new({"db" => @db_filename}).run
14
+ end
15
+
16
+ it "should store 1 record for the new blog entry" do
17
+ instance = Automatic::Plugin::StoreFullText.new({"db" => @db_filename},
18
+ AutomaticSpec.generate_pipeline {
19
+ feed { item "http://id774.net/blog/feed/" }
20
+ })
21
+
22
+ lambda {
23
+ instance.run.should have(1).feed
24
+ }.should change(Automatic::Plugin::Blog, :count).by(1)
25
+ end
26
+
27
+ it "should not store record for the existent blog entry" do
28
+ instance = Automatic::Plugin::StoreFullText.new({"db" => @db_filename},
29
+ AutomaticSpec.generate_pipeline {
30
+ feed { item "http://id774.net/blog/feed/" }
31
+ })
32
+
33
+ instance.run.should have(1).feed
34
+ lambda {
35
+ instance.run.should have(0).feed
36
+ }.should change(Automatic::Plugin::Blog, :count).by(0)
37
+ end
38
+ end
39
+
@@ -0,0 +1,39 @@
1
+
2
+ require File.expand_path(File.dirname(__FILE__) + '../../../spec_helper')
3
+
4
+ require 'store/permalink'
5
+
6
+ require 'pathname'
7
+
8
+ describe Automatic::Plugin::StorePermalink do
9
+ before do
10
+ @db_filename = "test_permalink.db"
11
+ db_path = Pathname(AutomaticSpec.db_dir).cleanpath+"#{@db_filename}"
12
+ db_path.delete if db_path.exist?
13
+ Automatic::Plugin::StorePermalink.new({"db" => @db_filename}).run
14
+ end
15
+
16
+ it "should store 1 record for the new link" do
17
+ instance = Automatic::Plugin::StorePermalink.new({"db" => @db_filename},
18
+ AutomaticSpec.generate_pipeline {
19
+ feed { item "http://github.com" }
20
+ })
21
+
22
+ lambda {
23
+ instance.run.should have(1).feed
24
+ }.should change(Automatic::Plugin::Permalink, :count).by(1)
25
+ end
26
+
27
+ it "should not store record for the existent link" do
28
+ instance = Automatic::Plugin::StorePermalink.new({"db" => @db_filename},
29
+ AutomaticSpec.generate_pipeline {
30
+ feed { item "http://github.com" }
31
+ })
32
+
33
+ instance.run.should have(1).feed
34
+ lambda {
35
+ instance.run.should have(0).feed
36
+ }.should change(Automatic::Plugin::Permalink, :count).by(0)
37
+ end
38
+ end
39
+
@@ -0,0 +1,30 @@
1
+ # -*- coding: utf-8 -*-
2
+ # Name:: Automatic::Plugin::CustomFeed::SVNFLog
3
+ # Author:: kzgs
4
+ # Created:: Mar 4, 2012
5
+ # Updated:: Mar 4, 2012
6
+ # Copyright:: kzgs Copyright (c) 2012
7
+ # License:: Licensed under the GNU GENERAL PUBLIC LICENSE, Version 3.0.
8
+
9
+ require File.expand_path(File.dirname(__FILE__) + '../../../spec_helper')
10
+
11
+ require 'store/target_link'
12
+
13
+ require 'tmpdir'
14
+ require 'pathname'
15
+
16
+ describe Automatic::Plugin::StoreTargetLink do
17
+ it "should store the target link" do
18
+ Dir.mktmpdir do |dir|
19
+ instance = Automatic::Plugin::StoreTargetLink.new(
20
+ { "path" => dir },
21
+ AutomaticSpec.generate_pipeline {
22
+ feed { item "http://digithoughts.com/rss" }
23
+ })
24
+
25
+ instance.run.should have(1).feed
26
+ (Pathname(dir)+"rss").should be_exist
27
+ end
28
+ end
29
+ end
30
+
@@ -0,0 +1,36 @@
1
+ require File.expand_path(File.dirname(__FILE__) + '../../../spec_helper')
2
+
3
+ require 'subscription/feed'
4
+
5
+ describe Automatic::Plugin::SubscriptionFeed do
6
+ context "with empty feeds" do
7
+ subject {
8
+ Automatic::Plugin::SubscriptionFeed.new(
9
+ { 'feeds' => [] })
10
+ }
11
+
12
+ its(:run) { should be_empty }
13
+ end
14
+
15
+ context "with feeds whose invalid URL" do
16
+ subject {
17
+ Automatic::Plugin::SubscriptionFeed.new(
18
+ { 'feeds' => ["invalid_url"] })
19
+ }
20
+
21
+ its(:run) { should be_empty }
22
+ end
23
+
24
+
25
+ context "with feeds whose valid URL" do
26
+ subject {
27
+ Automatic::Plugin::SubscriptionFeed.new(
28
+ { 'feeds' => [
29
+ "https://github.com/id774/automaticruby/commits/master.atom"]
30
+ })
31
+ }
32
+
33
+ its(:run) { should have(1).feed }
34
+ end
35
+ end
36
+
@@ -0,0 +1,82 @@
1
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'lib'))
2
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..', 'plugins'))
3
+ $LOAD_PATH.unshift(File.dirname(__FILE__))
4
+ $LOAD_PATH.unshift(File.join(File.dirname(__FILE__), '..'))
5
+
6
+ Bundler.require :test if defined?(Bundler)
7
+
8
+ if ENV['COVERAGE'] == 'on'
9
+ require 'simplecov'
10
+ require 'simplecov-rcov'
11
+ SimpleCov.formatter = SimpleCov::Formatter::RcovFormatter
12
+
13
+ SimpleCov.start do
14
+ add_filter "spec"
15
+ end
16
+ end
17
+
18
+ require 'lib/automatic'
19
+
20
+ # Requires supporting files with custom matchers and macros, etc,
21
+ # in ./support/ and its subdirectories.
22
+ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
23
+
24
+ unless /^1\.9\./ =~ RUBY_VERSION
25
+ require 'rspec'
26
+ end
27
+
28
+ RSpec.configure do |config|
29
+ config.mock_with :rspec
30
+ end
31
+
32
+ module AutomaticSpec
33
+ class << self
34
+ def generate_pipeline(&block)
35
+ pipeline_generator = StubPipelineGenerator.new
36
+ pipeline_generator.instance_eval(&block)
37
+ return pipeline_generator.feeds
38
+ end
39
+
40
+ def root_dir
41
+ return File.join(__FILE__, "../../")
42
+ end
43
+
44
+ def db_dir
45
+ return File.join(root_dir, "db")
46
+ end
47
+ end
48
+
49
+ class StubPipelineGenerator
50
+ attr_reader :feeds
51
+
52
+ def initialize
53
+ @feeds = []
54
+ end
55
+
56
+ def feed(&block)
57
+ feed_generator = StubFeedGenerator.new
58
+ feed_generator.instance_eval(&block)
59
+ @feeds << feed_generator.feed
60
+ end
61
+ end
62
+
63
+ class StubFeedGenerator
64
+ def initialize
65
+ @channel = RSS::Rss::Channel.new
66
+ end
67
+
68
+ def feed
69
+ rss = RSS::Rss.new([])
70
+ rss.instance_variable_set(:@channel, @channel)
71
+ return rss
72
+ end
73
+
74
+ def item(url, title="", description="")
75
+ itm = RSS::Rss::Channel::Item.new
76
+ itm.link = url
77
+ itm.title = title unless title.blank?
78
+ itm.instance_variable_set(:@description, description)
79
+ @channel.items << itm
80
+ end
81
+ end
82
+ end
@@ -0,0 +1,24 @@
1
+ global:
2
+ timezone: Asia/Tokyo
3
+ cache:
4
+ base: /tmp
5
+ log:
6
+ level: info
7
+
8
+ plugins:
9
+ - module: SubscriptionFeed
10
+ config:
11
+ feeds:
12
+ - http://id774.net/blog/feed/
13
+
14
+ - module: FilterIgnore
15
+ config:
16
+ exclude:
17
+ - hoge
18
+
19
+ - module: StorePermalink
20
+ config:
21
+ db: test_permalink.db
22
+
23
+ - module: PublishConsole
24
+
@@ -0,0 +1,24 @@
1
+ global:
2
+ timezone: Asia/Tokyo
3
+ cache:
4
+ base: /tmp
5
+ log:
6
+ level: info
7
+
8
+ plugins:
9
+ - module: SubscriptionFeed
10
+ config:
11
+ feeds:
12
+ - http://id774.net/blog/feed/
13
+
14
+ - module: FilterIgnore
15
+ config:
16
+ exclude:
17
+ - hoge
18
+
19
+ - module: PublishConsole
20
+
21
+ - module: StoreFullText
22
+ config:
23
+ db: blog.db
24
+