automatic 12.2.1

Sign up to get free protection for your applications and to get access to all the features.
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
+