Skip to content
This repository has been archived by the owner on Jan 8, 2023. It is now read-only.

Commit

Permalink
Initial commit.
Browse files Browse the repository at this point in the history
  • Loading branch information
maxim committed Dec 7, 2009
1 parent 7ae88c6 commit 8d05ac7
Show file tree
Hide file tree
Showing 13 changed files with 2,764 additions and 19 deletions.
16 changes: 0 additions & 16 deletions README.rdoc
Original file line number Diff line number Diff line change
@@ -1,17 +1 @@
= sogger

Description goes here.

== Note on Patches/Pull Requests

* Fork the project.
* Make your feature addition or bug fix.
* Add tests for it. This is important so I don't break it in a
future version unintentionally.
* Commit, do not mess with rakefile, version, or history.
(if you want to have your own version, that is fine but bump version in a commit by itself I can ignore when I pull)
* Send me a pull request. Bonus points for topic branches.

== Copyright

Copyright (c) 2009 Maxim Chernyak. See LICENSE for details.
5 changes: 4 additions & 1 deletion Rakefile
Original file line number Diff line number Diff line change
Expand Up @@ -10,7 +10,10 @@ begin
gem.email = "max@bitsonnet.com"
gem.homepage = "http://github.com/maxim/sogger"
gem.authors = ["Maxim Chernyak"]
gem.add_development_dependency "thoughtbot-shoulda", ">= 0"
gem.add_dependency "meow"
gem.add_dependency "nokogiri"
gem.add_development_dependency "shoulda"
gem.add_development_dependency "fakeweb"
# gem is a Gem::Specification... see http://www.rubygems.org/read/chapter/20 for additional settings
end
Jeweler::GemcutterTasks.new
Expand Down
7 changes: 7 additions & 0 deletions bin/sogger
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
#!/usr/bin/env ruby
require 'rubygems'
require File.expand_path(File.join(File.dirname(__FILE__), '..', 'lib', 'sogger'))

sogger = Sogger::Runner.new
puts "Press CTRL+C to stop..."
sogger.run
7 changes: 7 additions & 0 deletions lib/sogger.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,7 @@
require 'open-uri'
require 'nokogiri'
require 'meow'

require File.dirname(__FILE__) + "/sogger/question.rb"
require File.dirname(__FILE__) + "/sogger/sogger.rb"
require File.dirname(__FILE__) + "/sogger/runner.rb"
38 changes: 38 additions & 0 deletions lib/sogger/question.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,38 @@
module Sogger
class Question
include Comparable
attr_accessor :attributes

def initialize(attributes = {})
@attributes = attributes
end

def self.from_xml(xml_element)
attributes = { :title => xml_element.css('title').text,
:url => xml_element.css('id').text,
:tags => xml_element.css('category').map{|c| c['term']},
:published => DateTime.parse(xml_element.css('published').text) }
new attributes
end

def title
@attributes[:title]
end

def url
@attributes[:url]
end

def tags
@attributes[:tags]
end

def published
@attributes[:published]
end

def <=>(other)
other.published <=> published
end
end
end
61 changes: 61 additions & 0 deletions lib/sogger/runner.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,61 @@
module Sogger
class Runner
UPDATE_INTERVAL = 60
GROWL_INTERVAL = 20

def initialize
@cached_sogger = Sogger.new
@remote_sogger = Sogger.new
@questions_buffer = []
@growler = Meow.new("Sogger")
end

def run
updater = Thread.new("updater") do
while true
puts "Updater: Downloading feed..."
@remote_sogger.download_feed!

new_questions = []
unless @cached_sogger.questions.empty?
puts "Updater: Comparing feeds..."
new_questions = (@remote_sogger - @cached_sogger).questions
end

unless new_questions.empty?
puts "Updater: Adding #{new_questions.size} questions to buffer..."
@questions_buffer += new_questions
end

puts "Updater: Caching feed..."
@remote_sogger.save!

puts "Updater: Loading cached feed..."
@cached_sogger.load!

puts "Updater: Sleeping for #{UPDATE_INTERVAL} seconds..."
sleep UPDATE_INTERVAL
end
end

notifier = Thread.new("notifier") do
while true
unless @questions_buffer.empty?
puts "\nNotifier: Growling..."
growl(@questions_buffer.pop)
end

sleep GROWL_INTERVAL
end
end

[updater, notifier].map(&:join)
end

def growl(question)
@growler.notify(question.tags.join(', '), question.title) do
system "open", question.url
end
end
end
end
45 changes: 45 additions & 0 deletions lib/sogger/sogger.rb
Original file line number Diff line number Diff line change
@@ -0,0 +1,45 @@
module Sogger
class Sogger
class << self; attr_accessor :save_path end
attr_reader :raw_data

SO_FEED_URL = "http://stackoverflow.com/feeds"
DEFAULT_SAVE_PATH = "tmp/feed.xml"
self.save_path = DEFAULT_SAVE_PATH

def initialize(questions = [])
@questions = questions
end

def questions
@questions.sort
end

def download_feed!
@raw_data = open(SO_FEED_URL).read
parse_raw_data
end

def save!
File.open(self.class.save_path, "w") do |file|
file.write @raw_data
end
end

def load!
@raw_data = File.read(self.class.save_path)
parse_raw_data
end

def -(other)
newest_other = other.questions.first
Sogger.new(questions.select{|q| q < newest_other })
end

private
def parse_raw_data
@data = Nokogiri::XML(@raw_data)
@questions = @data.css('entry').map{ |e| Question.from_xml(e) }
end
end
end
Loading

0 comments on commit 8d05ac7

Please sign in to comment.