Skip to content

HTTPS clone URL

Subversion checkout URL

You can clone with
or
.
Download ZIP
Browse files

add Seinfeld::Feed object for parsing the feeds

  • Loading branch information...
commit 78d0e78cb5cce40793a5d08b18fb3f2a39370106 1 parent d1925c6
@technoweenie technoweenie authored
View
2  .gitignore
@@ -9,4 +9,6 @@ app/config.ru
app/config.rb
app/tmp
app/*.log
+
config/database.yml
+log
View
5 Rakefile
@@ -10,6 +10,11 @@ end
desc 'Default: run specs.'
task :default => 'test'
+desc "Open an irb session preloaded with this library"
+task :console do
+ sh "irb -rubygems -r ./lib/seinfeld.rb"
+end
+
desc "cron task for keeping the CAN updated. Run once every hour."
task :cron => 'seinfeld:init' do
if Time.now.hour % 4 == 0
View
7 config/database.sample.yml
@@ -5,13 +5,8 @@ development:
username: root
password:
host: localhost
-<% if File.exist?("/var/run/mysql5/mysqld.sock") %>
- socket: /var/run/mysql5/mysqld.sock
-<% elsif File.exist? "/tmp/mysql.sock" %>
- socket: /tmp/mysql.sock
-<% end %>
test:
adapter: sqlite3
encoding: utf8
- database: :memory:
+ database: ":memory:"
View
18 lib/seinfeld.rb
@@ -3,6 +3,7 @@
$LOAD_PATH.unshift *Dir["#{dir}/../vendor/**/lib"]
require 'erb'
+require 'logger'
require 'active_record' # v3
# Gives all the AR models their own tablenamespace:
@@ -27,8 +28,16 @@ class << self
attr_reader :logger
end
+ [:Feed].each do |const|
+ autoload const, "seinfeld/#{const.to_s.underscore}"
+ end
+
def self.logger
- @logger ||= Logger.new(path_from_root(log_path))
+ @logger ||= begin
+ file = path_from_root(log_path)
+ FileUtils.mkdir_p File.dirname(file)
+ Logger.new(file)
+ end
end
# Public: Reads the database.yml config and starts up the connection to the
@@ -36,10 +45,11 @@ def self.logger
#
# Returns nothing.
def self.configure
+ Time.zone = "UTC"
path = path_from_root(db_config_path)
- yaml = ERB.new(IO.read(path).result)
- ActiveRecord::Base.configurations = YAML.load(yaml)
- ActiveRecord::Base.establish_connection
+ yaml = ERB.new(IO.read(path)).result
+ data = YAML.load(yaml)
+ ActiveRecord::Base.establish_connection data[env.to_s]
ActiveRecord::Base.logger = logger
end
View
103 lib/seinfeld/feed.rb
@@ -0,0 +1,103 @@
+require 'time'
+require 'sax-machine'
+require 'open-uri'
+
+class Seinfeld
+ class Feed
+ # A Seinfeld::Feed::Atom reference to the parsed feed.
+ attr_reader :atom
+
+ # The String GitHub account name.
+ attr_reader :login
+
+ # The String url that the atom feed was fetched from (default: :direct)
+ attr_reader :url
+
+ # Public: Downloads a user's public feed from GitHub.
+ #
+ # login - String login name from GitHub.
+ #
+ # Returns Seinfeld::Feed instance.
+ def self.fetch(login)
+ feed = nil
+ url = "http://github.com/#{login}.atom"
+ open(url) { |f| feed = new(login, f.read, url) }
+ feed
+ end
+
+ # Parses the given data with SAX Machine.
+ #
+ # data - String atom data.
+ # url - String url that was used. (default: :direct)
+ #
+ # Returns Seinfeld::Feed.
+ def initialize(login, data, url = :direct)
+ @login = login.to_s
+ @url = url
+ @atom = Atom.parse(data)
+ end
+
+ # Public: Scans the parsed atom entries and pulls out all committed days.
+ #
+ # Returns Array of unique Date objects.
+ def committed_days
+ @committed_days ||= begin
+ days = []
+ entries.each do |entry|
+ committed?(entry) && days << entry.published_date
+ end
+ days.uniq!
+ days
+ end
+ end
+
+ # Determines whether the given entry counts as a commit or not.
+ #
+ # entry - Seinfeld::Feed::AtomEntry instance.
+ #
+ # Returns true if the entry is a commit, and false if it isn't.
+ def committed?(entry)
+ return false if entry.author != @login
+ !!(entry.title.downcase =~
+ %r{^#{@login.downcase} (pushed|committed|applied fork commits|created branch)})
+ end
+
+ # Accesses each parsed atom entry.
+ #
+ # Returns an Array of Seinfeld::Feed::AtomEntry instances.
+ def entries
+ atom.entries
+ end
+
+ def inspect
+ %(#<Seinfeld::Feed:#{@url} (#{entries.size})>)
+ end
+
+ class AtomEntry
+ include SAXMachine
+ element :published
+ element :title
+ element :author, :as => :author_name
+
+ def author
+ @author ||= begin
+ author_name.strip!
+ author_name
+ end
+ end
+
+ def published_at
+ @published_at ||= Time.zone.parse(published)
+ end
+
+ def published_date
+ Date.civil(published_at.year, published_at.month, published_at.day)
+ end
+ end
+
+ class Atom
+ include SAXMachine
+ elements :entry, :as => :entries, :class => AtomEntry
+ end
+ end
+end
View
0  log/.placeholder
No changes.
View
29 test/feed_test.rb
@@ -0,0 +1,29 @@
+require File.join(File.dirname(__FILE__), "test_helper")
+
+class FeedTest < ActiveSupport::TestCase
+ data = feed_data(:simple)
+
+ setup_once do
+ @feed = Seinfeld::Feed.new :technoweenie, data
+ end
+
+ test "parses atom data" do
+ assert_kind_of Seinfeld::Feed::Atom, @feed.atom
+ end
+
+ test "parses atom entries" do
+ assert_equal 9, @feed.entries.size
+ end
+
+ test "parses entry published timestamp" do
+ assert_equal Time.zone.local(2009, 12, 19, 14, 42, 13), @feed.entries[0].published_at
+ end
+
+ test "scans for committed days" do
+ assert_equal [
+ Date.civil(2009, 12, 19),
+ Date.civil(2009, 12, 17),
+ Date.civil(2009, 12, 16),
+ Date.civil(2009, 12, 15)], @feed.committed_days
+ end
+end
View
98 test/feeds/simple.atom
@@ -0,0 +1,98 @@
+<?xml version="1.0" encoding="UTF-8"?>
+<feed xml:lang="en-US" xmlns="http://www.w3.org/2005/Atom">
+ <id>tag:github.com,2008:/technoweenie</id>
+ <link type="text/html" href="http://github.com" rel="alternate"/>
+ <link type="application/atom+xml" href="http://github.com/technoweenie.atom" rel="self"/>
+ <title>technoweenie's Activity</title>
+ <updated>2009-12-19T15:00:51-08:00</updated>
+ <entry>
+ <id>tag:github.com,2008:PushEvent/113902146</id>
+ <published>2009-12-19T14:42:13-08:00</published>
+ <updated>2009-12-19T14:42:13-08:00</updated>
+ <link type="text/html" href="http://github.com/technoweenie/faraday/commits/master" rel="alternate"/>
+ <title>technoweenie committed to master at technoweenie/faraday</title>
+ <author>
+ <name>technoweenie</name>
+ </author>
+ </entry>
+ <entry>
+ <id>tag:github.com,2008:IssuesEvent/114814260</id>
+ <published>2009-12-18T18:40:40-08:00</published>
+ <updated>2009-12-21T19:40:40-08:00</updated>
+ <link type="text/html" href="http://github.com/mxcl/homebrew/issues/240/find" rel="alternate"/>
+ <title>traviscline opened issue 240 on mxcl/homebrew</title>
+ <author>
+ <name>traviscline</name>
+ </author>
+ </entry>
+ <entry>
+ <id>tag:github.com,2008:PushEvent/113902146</id>
+ <published>2009-12-17T14:42:13-08:00</published>
+ <updated>2009-12-19T14:42:13-08:00</updated>
+ <link type="text/html" href="http://github.com/technoweenie/faraday/commits/master" rel="alternate"/>
+ <title>technoweenie pushed to master at technoweenie/faraday</title>
+ <author>
+ <name>technoweenie</name>
+ </author>
+ </entry>
+ <entry>
+ <id>tag:github.com,2008:PushEvent/113902146</id>
+ <published>2009-12-16T14:42:13-08:00</published>
+ <updated>2009-12-19T14:42:13-08:00</updated>
+ <link type="text/html" href="http://github.com/technoweenie/faraday/commits/master" rel="alternate"/>
+ <title>technoweenie applied fork commits to master at technoweenie/faraday</title>
+ <author>
+ <name>technoweenie</name>
+ </author>
+ </entry>
+ <entry>
+ <id>tag:github.com,2008:PushEvent/113902146</id>
+ <published>2009-12-15T14:42:13-08:00</published>
+ <updated>2009-12-19T14:42:13-08:00</updated>
+ <link type="text/html" href="http://github.com/technoweenie/faraday/commits/master" rel="alternate"/>
+ <title>technoweenie created branch master at technoweenie/faraday</title>
+ <author>
+ <name>technoweenie</name>
+ </author>
+ </entry>
+ <entry>
+ <id>tag:github.com,2008:PushEvent/113902146</id>
+ <published>2009-12-15T14:42:13-08:00</published>
+ <updated>2009-12-19T14:42:13-08:00</updated>
+ <link type="text/html" href="http://github.com/technoweenie/faraday/commits/master" rel="alternate"/>
+ <title>technoweenie created branch master at technoweenie/faraday</title>
+ <author>
+ <name>technoweenie</name>
+ </author>
+ </entry>
+ <entry>
+ <id>tag:github.com,2008:PushEvent/113902146</id>
+ <published>2009-12-14T14:42:13-08:00</published>
+ <updated>2009-12-19T14:42:13-08:00</updated>
+ <link type="text/html" href="http://github.com/technoweenie/faraday/commits/master" rel="alternate"/>
+ <title>technoweenie open sourced technoweenie/faraday</title>
+ <author>
+ <name>technoweenie</name>
+ </author>
+ </entry>
+ <entry>
+ <id>tag:github.com,2008:PushEvent/113902146</id>
+ <published>2009-12-13T14:42:13-08:00</published>
+ <updated>2009-12-19T14:42:13-08:00</updated>
+ <link type="text/html" href="http://github.com/technoweenie/faraday/commits/master" rel="alternate"/>
+ <title>technoweenie created branch technoweenie/faraday</title>
+ <author>
+ <name>otherguy</name>
+ </author>
+ </entry>
+ <entry>
+ <id>tag:github.com,2008:PushEvent/113902146</id>
+ <published>2009-12-13T14:42:13-08:00</published>
+ <updated>2009-12-19T14:42:13-08:00</updated>
+ <link type="text/html" href="http://github.com/technoweenie/faraday/commits/master" rel="alternate"/>
+ <title>otherguy created branch technoweenie/faraday</title>
+ <author>
+ <name>technoweenie</name>
+ </author>
+ </entry>
+</feed>
View
10 test/test_helper.rb
@@ -9,11 +9,19 @@
class ActiveSupport::TestCase
FEED_PATH = File.join(File.dirname(__FILE__), 'feeds')
- def feed_data(feed)
+ def self.feed_data(feed)
IO.read File.join(FEED_PATH, "#{feed}.atom")
end
+
+ def feed_data(feed)
+ self.class.feed_data(feed)
+ end
end
+Seinfeld.env = 'test'
+Seinfeld.configure
+Time.zone = 'Pacific Time (US & Canada)'
+
begin
require 'ruby-debug'
Debugger.start
Please sign in to comment.
Something went wrong with that request. Please try again.