feedbook 0.9.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.
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