class Feedbook::Listener
Public Class Methods
Load feeds from serialized YAML file. @param [String] path to YAML file with serialized objects
@return [Array] Array of feeds with archived posts
# File lib/feedbook/listener.rb, line 72 def self.load_feeds_archive(path) print 'Reading feeds from file... ' if File.exist? path puts 'completed.' YAML::load(File.read(path)) else puts 'canceled. File does not exist.' [] end end
Single run of loop for listening for changes in RSS feeds and notifies about updates @param feed [Feedbook::Feed] requested feed to be observed (hash with feed and posts)
@return [NilClass] nil
# File lib/feedbook/listener.rb, line 104 def self.observe_and_notify(feed) new_posts = feed[:feed].fetch difference = Comparers::PostsComparer.get_new_posts(feed[:posts], new_posts) if difference.empty? puts 'No new posts found.' else puts "#{difference.size} new posts found." print 'Started sending notifications... ' end difference.each do |post| feed[:feed].notifications.each do |notification| notification.notify(post) end end unless difference.empty? puts 'completed.' end feed[:posts] = new_posts feed end
Saves feeds into serialized YAML file @param path [String] path to file @param feeds [Array] Array with feeds to be saved
@return [NilClass] nil
# File lib/feedbook/listener.rb, line 89 def self.save_feeds_archive(path, feeds) print 'Saving feeds to file... ' File.open(path, 'w') do |f| f.write YAML::dump(feeds) end puts 'completed.' end
Starts listening on feeds and notifies if there is new post. @param path [String] configuration file path @param plugins_path [String] plugins directory path
# File lib/feedbook/listener.rb, line 15 def self.start(path, plugins_path) handle_exceptions do feeds, configuration = initialize_listener(path, plugins_path) print 'Fetching feeds for the first use... ' observed_feeds = feeds.map do |feed| { feed: feed, posts: feed.fetch } end puts 'completed.' puts 'Listener started...' every configuration.interval do puts 'Fetching feeds...' observed_feeds.each do |feed| observe_and_notify(feed) end end end end
Starts listening on feeds and notifies if there is new post (offline mode). @param path [String] configuration file path @param plugins_path [String] plugins directory path
# File lib/feedbook/listener.rb, line 42 def self.start_offline(path, archive_path, plugins_path) handle_exceptions do feeds, configuration = initialize_listener(path, plugins_path) observed_feeds = load_feeds_archive(archive_path) if observed_feeds.blank? print 'Fetching feeds for the first use... ' observed_feeds = feeds.map do |feed| { feed: feed, posts: feed.fetch } end puts 'completed.' end puts 'Fetching feeds...' observed_feeds.each do |feed| observe_and_notify(feed) end save_feeds_archive(archive_path, observed_feeds) end end
Private Class Methods
Handle exceptions rescued from given block
# File lib/feedbook/listener.rb, line 134 def self.handle_exceptions yield if block_given? rescue Errors::InvalidFeedUrlError abort 'feed url collection is not valid (contains empty or invalid urls)' rescue Errors::InvalidIntervalFormatError abort 'interval value in configuration is not valid (should be in format: "(Number)(TimeType)" where TimeType is s, m, h or d)' rescue Errors::InvalidVariablesFormatError abort 'invalid variables format in configuration (should be a key-value pairs)' rescue Errors::NoConfigurationFileError => e abort "configuration file could not be loaded: #{e.message}" rescue Errors::NotifierConfigurationError => e abort "notifier #{e.notifier} has invalid configuration (#{e.message})." rescue Errors::ParseFeedError => e p "feed on #{e.url} could not be parsed because of fetching/parsing error." rescue Errors::TemplateSyntaxError abort "one of your templates in configuration file is not valid." end
Initializes listener configuration, loads plugins and notifiers. @param path [String] config file path @param plugins_path [String] plugins directory path
@return [[Array, Feedbook::Configuration
]] feeds and Configuration
instance
# File lib/feedbook/listener.rb, line 157 def self.initialize_listener(path, plugins_path) print "Loading configuration from file #{path}... " feeds, configuration = load_configuration(path) feeds.each { |feed| feed.valid? } puts 'completed.' Feedbook::PluginsManager.load_plugins(plugins_path) puts 'Loading notifiers... ' configuration.load_notifiers puts 'completed.' [feeds, configuration] end
Load configuration from given path @param path [String] configuration file path
@return [[Array, Feedbook::Configuration
]] feeds and Configuration
instance @raise [Feedbook::Errors::NoConfigurationFileError] if path to config file is invalid of configuration file is missing
# File lib/feedbook/listener.rb, line 177 def self.load_configuration(path) config = YAML.load_file(path) feeds = config.fetch('feeds', []).map do |feed| Feed.new( urls: feed['url'], variables: feed['variables'], notifications: feed['notifications'] ) end configuration_hash = config.fetch('configuration', {}) configuration = Configuration.new(configuration_hash) [feeds, configuration] rescue Errno::ENOENT => e raise Errors::NoConfigurationFileError.new(e) end