feedbook 0.9.0

Sign up to get free protection for your applications and to get access to all the features.
Files changed (51) hide show
  1. checksums.yaml +15 -0
  2. data/.gitignore +22 -0
  3. data/.rspec +3 -0
  4. data/.travis.yml +6 -0
  5. data/Gemfile +3 -0
  6. data/LICENSE.txt +22 -0
  7. data/README.md +129 -0
  8. data/Rakefile +7 -0
  9. data/bin/feedbook +73 -0
  10. data/feedbook.gemspec +35 -0
  11. data/lib/feedbook.rb +6 -0
  12. data/lib/feedbook/comparers/posts_comparer.rb +15 -0
  13. data/lib/feedbook/configuration.rb +47 -0
  14. data/lib/feedbook/errors.rb +10 -0
  15. data/lib/feedbook/errors/invalid_feed_url_error.rb +6 -0
  16. data/lib/feedbook/errors/invalid_interval_format_error.rb +6 -0
  17. data/lib/feedbook/errors/invalid_variables_format_error.rb +6 -0
  18. data/lib/feedbook/errors/no_configuration_file_error.rb +6 -0
  19. data/lib/feedbook/errors/notifier_configuration_error.rb +12 -0
  20. data/lib/feedbook/errors/notifier_notify_error.rb +12 -0
  21. data/lib/feedbook/errors/parse_feed_error.rb +11 -0
  22. data/lib/feedbook/errors/template_syntax_error.rb +6 -0
  23. data/lib/feedbook/errors/unsupported_notifier_error.rb +12 -0
  24. data/lib/feedbook/factories/notifiers_factory.rb +28 -0
  25. data/lib/feedbook/feed.rb +85 -0
  26. data/lib/feedbook/helpers/time_interval_parser.rb +38 -0
  27. data/lib/feedbook/listener.rb +122 -0
  28. data/lib/feedbook/notification.rb +62 -0
  29. data/lib/feedbook/notifiers.rb +5 -0
  30. data/lib/feedbook/notifiers/facebook_notifier.rb +44 -0
  31. data/lib/feedbook/notifiers/irc_notifier.rb +42 -0
  32. data/lib/feedbook/notifiers/mail_notifier.rb +52 -0
  33. data/lib/feedbook/notifiers/null_notifier.rb +25 -0
  34. data/lib/feedbook/notifiers/twitter_notifier.rb +49 -0
  35. data/lib/feedbook/post.rb +33 -0
  36. data/lib/feedbook/version.rb +3 -0
  37. data/spec/spec_helper.rb +30 -0
  38. data/spec/unit/lib/comparers/posts_comparer_spec.rb +13 -0
  39. data/spec/unit/lib/configuration_spec.rb +43 -0
  40. data/spec/unit/lib/factories/notifiers_factory_spec.rb +28 -0
  41. data/spec/unit/lib/feed_spec.rb +42 -0
  42. data/spec/unit/lib/helpers/time_interval_parser_spec.rb +26 -0
  43. data/spec/unit/lib/listener_spec.rb +29 -0
  44. data/spec/unit/lib/notification_spec.rb +44 -0
  45. data/spec/unit/lib/notifiers/facebook_notifier_spec.rb +34 -0
  46. data/spec/unit/lib/notifiers/irc_notifier_spec.rb +41 -0
  47. data/spec/unit/lib/notifiers/mail_notifier_spec.rb +39 -0
  48. data/spec/unit/lib/notifiers/null_notifier_spec.rb +19 -0
  49. data/spec/unit/lib/notifiers/twitter_notifier_spec.rb +36 -0
  50. data/spec/unit/lib/post_spec.rb +51 -0
  51. metadata +304 -0
@@ -0,0 +1,15 @@
1
+ ---
2
+ !binary "U0hBMQ==":
3
+ metadata.gz: !binary |-
4
+ ZDkwNWM3OWZlM2RkOTliMzFmYjk5OTJmZTU4OGYwNTQzY2YzY2NkMA==
5
+ data.tar.gz: !binary |-
6
+ MWNiMmE5Njk1MDE1MDI1ZGJlNTBkMDRhM2M4NzM3Y2ZlMzZiOWU2OA==
7
+ SHA512:
8
+ metadata.gz: !binary |-
9
+ OTFjODk5MGIwNzhmZDlmM2RiMmIxMmYxNmZiZmVmNTViNTE0MjZhNDk0ZDkx
10
+ MDY2OWQ2YWY3N2UzODE0ZWYyNGExZWNiOWI1YzliNTNiNzc1ODE3MmVmNzA1
11
+ ZTk3OTlhMGRjYzE4MjQ2MmE2ODM2NTFmYjNkZmIwNGM5YjRjNDE=
12
+ data.tar.gz: !binary |-
13
+ NjJhZmU1YTMyOGVmZDQ1ZTUyY2U5Y2U0YzdhN2JkMTYwMGFhMWM1M2Q1MjM2
14
+ MDllNTdjMjViOWQ5MTUwNjdhZmQ2MDY4YTUzYzBlNjU5MDc1Zjg5OTQ1MDBi
15
+ OGIwYTBlZmUwMmYzMzkxMGQyZWFlMzY5ZWI0NzVmZDJlZDAyMjc=
@@ -0,0 +1,22 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.bundle
19
+ *.so
20
+ *.o
21
+ *.a
22
+ mkmf.log
data/.rspec ADDED
@@ -0,0 +1,3 @@
1
+ --color
2
+ --require spec_helper
3
+ --format documentation
@@ -0,0 +1,6 @@
1
+ language: ruby
2
+ script: bundle exec rake
3
+ rvm:
4
+ - 1.9.3
5
+ - 2.0.0
6
+ - 2.1.0
data/Gemfile ADDED
@@ -0,0 +1,3 @@
1
+ source 'https://rubygems.org'
2
+
3
+ gemspec
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Maciej Paruszewski
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,129 @@
1
+ # Feedbook [![Build Status](https://travis-ci.org/pinoss/feedbook.svg?branch=master)](https://travis-ci.org/pinoss/feedbook) [![Code Climate](https://codeclimate.com/github/pinoss/feedbook.png)](https://codeclimate.com/github/pinoss/feedbook) [![Coverage Status](https://coveralls.io/repos/pinoss/feedbook/badge.png)](https://coveralls.io/r/pinoss/feedbook)
2
+
3
+ Feedbook is a simple console application that allows to notify on IRC, mail and social media (like Twitter and Facebook) about RSS/Atom updates.
4
+
5
+ ## Why?
6
+
7
+ > Automation isn’t about being lazy, it’s about being efficient.
8
+ > ~ Addy Osmani
9
+
10
+ * If you do something every day, why not to automate it?
11
+ * If you have a blog and want to notify your users on Twitter on Facebook that there is a new post, you can do it without opening your browser.
12
+
13
+ ## Main Features
14
+
15
+ * Parse feeds and notifies about new posts.
16
+ * Easy to configure.
17
+ * Fire and forget - once you have valid configuration you do not need to think about feedbook again, everything will work automatically.
18
+
19
+ ## Installation
20
+
21
+ Install gem with:
22
+
23
+ $ gem install feedbook
24
+
25
+ ## Usage
26
+
27
+ Install gem into your system:
28
+
29
+ $ gem install feedbook
30
+
31
+ Create your configuration file or take a default file and modify it:
32
+
33
+ $ feedbook init
34
+ => Created default feedbook configuration file: feedbook.yml
35
+
36
+ After you create or modify your configuration file, you need to start listening for RSS changes:
37
+
38
+ $ feedbook start
39
+ Loading configuration from file feedbook.yml... completed.
40
+ Loading notifiers...
41
+ Configuration loaded for TwitterNotifier
42
+ Configuration loaded for FacebookNotifier
43
+ completed.
44
+ Fetching feeds for the first use... completed.
45
+ Listener started...
46
+ Fetching feeds...
47
+
48
+ And Feedbook now will work and listen for changes.
49
+
50
+ ## Configuration
51
+
52
+
53
+ ```yaml
54
+ feeds:
55
+ - url: https://github.com/pinoss.atom # collection of urls (separated by space)
56
+ variables: # you can use variables defined here in your templates
57
+ default_header: Check out our new post
58
+ notifications: # notifications configuration, you need to specify type and template for each notification
59
+ - type: facebook
60
+ template: "{{ default_header }} {{ title }} by {{ author }}: {{ url }}"
61
+ - type: twitter
62
+ template: "{{ default_header }} on our blog {{ feed_url }}: {{ title }}/{{ url }}"
63
+
64
+ configuration:
65
+ interval: 5m
66
+ facebook: # Facebook OAuth token
67
+ token: SECRET_FACEBOOK_TOKEN
68
+ twitter: # Twitter token collection
69
+ consumer_key: SECRET_CONSUMER_KEY
70
+ consumer_secret: SECRET_TWITTER_CONSUMER_SECRET
71
+ access_token: SECRET_TWITTER_ACCESS_TOKEN
72
+ access_token_secret: SECRET_TWITTER_ACCESS_TOKEN_SECRET
73
+ irc: # IRC configuration
74
+ url: irc.freenode.net
75
+ port: 8001
76
+ ssl_enabled: true/false
77
+ channel: #channel
78
+ nick: feedbook_bot
79
+ mail: # Mail configuration
80
+ address: mparuszewski@feedbook.lo
81
+ port: 5870
82
+ domain: smtp.feedbook.lo
83
+ username: mparuszewski
84
+ password: your_password
85
+ authentication: plain
86
+ enable_starttls_auto: true/false
87
+
88
+ ```
89
+
90
+ ### Facebook
91
+
92
+ You need to generate your access token to use Facebook notifier, you can do that on [Graph API Explorer](https://developers.facebook.com/tools/explorer) page (click *Get access token* and select __user_status__).
93
+
94
+ ### Twitter
95
+
96
+ You need to generate your keys here, you will need 4 keys, first two you will get on [Create an application](https://apps.twitter.com/app/new) page, after you create it, go to __API Keys__ tab and click __Create my access token__ at the bottom.
97
+
98
+ ### Mail
99
+
100
+ Mail configuration is really simple, you need to specify few parameters and you will get mail notifications.
101
+
102
+ ### IRC
103
+
104
+ IRC configuration is also very simple, I think it does not require any explanations.
105
+
106
+ ## Templates
107
+
108
+ Feedbook uses Liquid for generating output. If you know Mustache it will not be a problem for you to write your template, it uses same syntax, but provides more features (like tags and helpers) - you can read about Liquid on [Liquid for Designers](https://github.com/Shopify/liquid/wiki/Liquid-for-Designers).
109
+
110
+ ## Todo
111
+
112
+ Because Feedbook is still in development there is many to do:
113
+
114
+ * add Google+ Notifier
115
+ Unfortunately Google+ does not provides API with ability to push messages to streams. Because of that I need to find a tool that will provide that feature without use of Google+.
116
+ * add links shortener (bit.ly or goo.gl) as a Liquid tag/filter
117
+ Twitter limits Tweet length to 140 characters, why not to shorten links and rescue too long message.
118
+ * add ability to add own Notifier without forking Feedbook project
119
+ I would like to give ability to users to create own Notifier plugins without any special development to Feedbook.
120
+ * add more tests
121
+ I would like to add integration tests to make sure that all features work.
122
+
123
+ ## Contributing
124
+
125
+ 1. Fork it ( https://github.com/pinoss/feedbook/fork )
126
+ 2. Create your feature branch (`git checkout -b my-new-feature`)
127
+ 3. Commit your changes (`git commit -am 'Add some feature'`)
128
+ 4. Push to the branch (`git push origin my-new-feature`)
129
+ 5. Create a new Pull Request
@@ -0,0 +1,7 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rspec/core/rake_task'
3
+
4
+ RSpec::Core::RakeTask.new(:spec)
5
+
6
+ task default: :spec
7
+
@@ -0,0 +1,73 @@
1
+ #!/usr/bin/env ruby
2
+ $LOAD_PATH.unshift(File.dirname(__FILE__) + '/../lib')
3
+
4
+ require 'gli'
5
+ require 'box'
6
+ require 'feedbook'
7
+ require 'fileutils'
8
+
9
+ include GLI::App
10
+
11
+ program_desc 'Feedbook is a simple gem and application that notifies about new posts and Atom/RSS updates on your social media sites (like Facebook and Twitter), e-mail or IRC.'
12
+
13
+ flag [:c,:config], default_value: 'feedbook.yml', desc: 'Feedbook configuration file location'
14
+
15
+ desc 'Parses feedbook.yml file for feeds and configuration and listen for changes in RSS/Atom feeds to notify about updates on social media sites'
16
+ command :start do |c|
17
+
18
+ c.action do |global_options, _, _|
19
+ Feedbook::Listener.start(global_options[:config])
20
+ end
21
+ end
22
+
23
+ desc 'Creates basic feedbook config file'
24
+ command :init do |c|
25
+ c.action do |global_options, _, _|
26
+ abort 'There is already a feedbook configuration file' if File.exist?(global_options[:config])
27
+ File.open(global_options[:config], 'w') { |f| f.write(Box::FILES['feedbook']) }
28
+ puts "=> Created default feedbook configuration file: #{global_options[:config]}"
29
+ end
30
+ end
31
+
32
+ desc 'Outputs feedbook gem version'
33
+ command :version do |c|
34
+ c.action do |global_options, _, _|
35
+ puts "feedbook version: #{Feedbook::VERSION}"
36
+ end
37
+ end
38
+
39
+ on_error do |exception|
40
+ case exception
41
+ when SystemExit
42
+ else
43
+ STDERR.puts "Error: #{exception} (#{exception.class})"
44
+ STDERR.puts exception.backtrace.join("\n")
45
+ end
46
+ false
47
+ end
48
+
49
+ exit run(ARGV)
50
+
51
+ __END__
52
+ @@ feedbook
53
+ ## Feedbook default config file, modify it!
54
+
55
+ feeds:
56
+ - url: https://github.com/pinoss.atom
57
+ variables:
58
+ default_header: Check out our new post
59
+ notifications:
60
+ - type: facebook
61
+ template: "{{ default_header }} {{ title }} by {{ author }}: {{ url }}"
62
+ - type: twitter
63
+ template: "{{ default_header }} on our blog {{ feed_url }}: {{ title }}/{{ url }}"
64
+
65
+ configuration:
66
+ interval: 5m
67
+ facebook:
68
+ token: SECRET_FACEBOOK_TOKEN
69
+ twitter:
70
+ consumer_key: SECRET_CONSUMER_KEY
71
+ consumer_secret: SECRET_TWITTER_CONSUMER_SECRET
72
+ access_token: SECRET_TWITTER_ACCESS_TOKEN
73
+ access_token_secret: SECRET_TWITTER_ACCESS_TOKEN_SECRET
@@ -0,0 +1,35 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'feedbook/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = 'feedbook'
8
+ spec.version = Feedbook::VERSION
9
+ spec.authors = ['Maciej Paruszewski']
10
+ spec.email = ['maciek.paruszewski@gmail.com']
11
+ spec.summary = %q{Feedbook}
12
+ spec.homepage = "https://github.com/pinoss/feedbook"
13
+ spec.license = "MIT"
14
+
15
+ spec.files = `git ls-files -z`.split("\x0")
16
+ spec.executables = spec.files.grep(%r{^bin/}) { |f| File.basename(f) }
17
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
18
+ spec.require_paths = ['lib']
19
+
20
+ spec.add_runtime_dependency 'feedjira', '~> 1.3'
21
+ spec.add_runtime_dependency 'gli', '~> 2.1'
22
+ spec.add_runtime_dependency 'liquid', '~> 2.6'
23
+ spec.add_runtime_dependency 'timeloop', '~> 1.0'
24
+ spec.add_runtime_dependency 'koala', '~> 1.9'
25
+ spec.add_runtime_dependency 'box', '~> 0.1'
26
+ spec.add_runtime_dependency 'twitter', '~> 5.1'
27
+ spec.add_runtime_dependency 'mail', '~> 2.6'
28
+ spec.add_runtime_dependency 'irc-notify'
29
+
30
+ spec.add_development_dependency 'bundler', '~> 1.6'
31
+ spec.add_development_dependency 'rake', '~> 10.3'
32
+ spec.add_development_dependency 'rspec'
33
+ spec.add_development_dependency 'coveralls'
34
+ spec.add_development_dependency 'pry-debugger'
35
+ end
@@ -0,0 +1,6 @@
1
+ require 'feedbook/listener'
2
+ require 'feedbook/errors'
3
+ require 'feedbook/version'
4
+
5
+ module Feedbook
6
+ end
@@ -0,0 +1,15 @@
1
+ module Feedbook
2
+ module Comparers
3
+ module PostsComparer
4
+
5
+ # Returns only posts from new posts list that does not exists in old posts list.
6
+ # @param old_posts [Array] list of old posts
7
+ # @param new_posts [Array] list of new posts
8
+ #
9
+ # @return [type] [description]
10
+ def self.get_new_posts(old_posts, new_posts)
11
+ new_posts.select { |post| old_posts.all? { |opost| opost.url != post.url } }
12
+ end
13
+ end
14
+ end
15
+ end
@@ -0,0 +1,47 @@
1
+ require 'feedbook/notifiers'
2
+ require 'feedbook/helpers/time_interval_parser'
3
+
4
+ module Feedbook
5
+ class Configuration
6
+ attr_reader :interval
7
+
8
+ INTERVAL_FORMAT = /\A(\d+)(s|m|h|d)\z/
9
+
10
+ # Initializes new Configuration object with configuration for program instance
11
+ # @param opts = {} [Hash] Hash with configuration of interval and suppliers
12
+ #
13
+ # @return [NilClass] nil
14
+ def initialize(opts = {})
15
+ @interval = Helpers::TimeIntervalParser.parse(opts.fetch(:interval, ''))
16
+ @twitter = opts.fetch(:twitter, nil)
17
+ @facebook = opts.fetch(:facebook, nil)
18
+ @irc = opts.fetch(:irc, nil)
19
+ @mail = opts.fetch(:mail, nil)
20
+ end
21
+
22
+ # Load notifiers configuration
23
+ #
24
+ # @return [NilClass] nil
25
+ def load_notifiers
26
+ unless twitter.nil?
27
+ Notifiers::TwitterNotifier.instance.load_configuration(twitter)
28
+ end
29
+
30
+ unless facebook.nil?
31
+ Notifiers::FacebookNotifier.instance.load_configuration(facebook)
32
+ end
33
+
34
+ unless irc.nil?
35
+ Notifiers::IRCNotifier.instance.load_configuration(irc)
36
+ end
37
+
38
+ unless mail.nil?
39
+ Notifiers::MailNotifier.instance.load_configuration(mail)
40
+ end
41
+ end
42
+
43
+ private
44
+ attr_reader :twitter, :facebook, :irc, :mail
45
+
46
+ end
47
+ end
@@ -0,0 +1,10 @@
1
+ require 'feedbook/errors/invalid_feed_url_error'
2
+ require 'feedbook/errors/invalid_interval_format_error'
3
+ require 'feedbook/errors/invalid_variables_format_error'
4
+ require 'feedbook/errors/no_configuration_file_error'
5
+ require 'feedbook/errors/parse_feed_error'
6
+ require 'feedbook/errors/no_configuration_file_error'
7
+ require 'feedbook/errors/template_syntax_error'
8
+ require 'feedbook/errors/unsupported_notifier_error'
9
+ require 'feedbook/errors/notifier_configuration_error'
10
+ require 'feedbook/errors/notifier_notify_error'
@@ -0,0 +1,6 @@
1
+ module Feedbook
2
+ module Errors
3
+ class InvalidFeedUrlError < StandardError
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ module Feedbook
2
+ module Errors
3
+ class InvalidIntervalFormatError < StandardError
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ module Feedbook
2
+ module Errors
3
+ class InvalidVariablesFormatError < StandardError
4
+ end
5
+ end
6
+ end
@@ -0,0 +1,6 @@
1
+ module Feedbook
2
+ module Errors
3
+ class NoConfigurationFileError < StandardError
4
+ end
5
+ end
6
+ end