lifestream 0.1.0

Sign up to get free protection for your applications and to get access to all the features.
data/README ADDED
File without changes
data/Rakefile ADDED
@@ -0,0 +1,77 @@
1
+ require 'rubygems'
2
+ require 'rake'
3
+
4
+ require(File.join(File.dirname(__FILE__), 'lib', 'lifestream'))
5
+
6
+ begin
7
+ require 'jeweler'
8
+ Jeweler::Tasks.new do |gem|
9
+ gem.name = "lifestream"
10
+ gem.summary = %Q{downloads and parses lifestream information from sources like facebook and twitter}
11
+ gem.email = "adamhunter@me.com"
12
+ gem.homepage = "http://github.com/adamhunter/lifestream"
13
+ gem.authors = ["Adam Hunter"]
14
+ #gem.rubyforge_project = "lifestream"
15
+ gem.files = FileList["[A-Z]*", "{lib,test}/**/*"]
16
+
17
+ #gem.add_dependency('httparty', '0.4.3')
18
+
19
+ gem.add_development_dependency('thoughtbot-shoulda', '>= 2.10.1')
20
+ gem.add_development_dependency('jnunemaker-matchy', '0.4.0')
21
+ gem.add_development_dependency('mocha', '0.9.4')
22
+ gem.add_development_dependency('redgreen', '1.0.0')
23
+ end
24
+
25
+ Jeweler::RubyforgeTasks.new do |rubyforge|
26
+ rubyforge.doc_task = "rdoc"
27
+ end
28
+ rescue LoadError
29
+ puts "Jeweler not available. Install it with: sudo gem install technicalpickles-jeweler -s http://gems.github.com"
30
+ end
31
+
32
+ require 'rake/testtask'
33
+ Rake::TestTask.new(:test) do |test|
34
+ test.libs << 'lib' << 'test'
35
+ test.pattern = 'test/**/*_test.rb'
36
+ test.verbose = false
37
+ end
38
+
39
+ begin
40
+ require 'rcov/rcovtask'
41
+ Rcov::RcovTask.new do |test|
42
+ test.libs << 'test'
43
+ test.pattern = 'test/**/*_test.rb'
44
+ test.verbose = true
45
+ end
46
+ rescue LoadError
47
+ task :rcov do
48
+ abort "RCov is not available. In order to run rcov, you must: sudo gem install spicycode-rcov"
49
+ end
50
+ end
51
+
52
+
53
+ task :default => :test
54
+
55
+ require 'rake/rdoctask'
56
+ Rake::RDocTask.new do |rdoc|
57
+ if File.exist?('VERSION.yml')
58
+ config = YAML.load(File.read('VERSION.yml'))
59
+ version = "#{config[:major]}.#{config[:minor]}.#{config[:patch]}"
60
+ else
61
+ version = ""
62
+ end
63
+
64
+ rdoc.rdoc_dir = 'rdoc'
65
+ rdoc.title = "lifestream #{version}"
66
+ rdoc.rdoc_files.include('README*')
67
+ rdoc.rdoc_files.include('lib/**/*.rb')
68
+ end
69
+
70
+ namespace :lifestream do
71
+
72
+ desc "Generate lifestream.yml file"
73
+ task :configure do
74
+
75
+ end
76
+
77
+ end
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.1.0
data/lib/lifestream.rb ADDED
@@ -0,0 +1,55 @@
1
+ require 'rubygems'
2
+ require 'erb'
3
+
4
+ module Lifestream
5
+
6
+ # Provides configurability to Lifestream. There are a number of options available, such as:
7
+ # * whiny: Will raise an error if Lifestream cannot process a given feed.
8
+ # Defaults to true
9
+ # * config: Path to the lifestream.yml file that contains the feeds to download.
10
+ # Defaults to gem location, you will probably want to set this
11
+ def self.options
12
+ @options ||= {
13
+ :config => File.join(File.expand_path(File.dirname(__FILE__)), '..', 'lifestream.yml'),
14
+ :whiny => true
15
+ }
16
+ end
17
+
18
+ # Generates a Lifestream::Stream which contains all the channels
19
+ # with their branches parsed from the feeds in the lifestream.yml file,
20
+ # ordered by their published_at date.
21
+ def self.run(preload = false)
22
+ lifestream = Lifestream::Stream.new
23
+ ensure_configuration_exists
24
+
25
+ feeds = YAML.load(File.open(options[:config]))
26
+ feeds.each_pair do |name, options|
27
+ klass = Lifestream::Channel.const_get(options['format'])
28
+ channel = klass.new(name, options['url'])
29
+ channel.branches if preload
30
+ lifestream.channels << channel
31
+ end
32
+ lifestream
33
+ end
34
+
35
+ protected
36
+
37
+ def self.ensure_configuration_exists
38
+ raise Lifestream::NoConfiguration.new("You must provide a configuration file") unless File.exists?(options[:config])
39
+ end
40
+
41
+ class NoConfiguration < StandardError; end
42
+
43
+ end
44
+
45
+ directory = File.expand_path(File.dirname(__FILE__))
46
+
47
+ # yes most of these are all named after parts of a stream
48
+ # http://en.wikipedia.org/wiki/Stream#Parts_of_a_stream
49
+ require File.join(directory, 'lifestream', 'branch')
50
+ require File.join(directory, 'lifestream', 'channel')
51
+ require File.join(directory, 'lifestream', 'channel', 'rss2')
52
+ require File.join(directory, 'lifestream', 'request')
53
+ require File.join(directory, 'lifestream', 'source')
54
+ require File.join(directory, 'lifestream', 'stream')
55
+
@@ -0,0 +1,11 @@
1
+ module Lifestream
2
+ class Branch
3
+
4
+ attr_accessor :published_at, :title, :body
5
+
6
+ def initialize published_at, title, body = nil
7
+ @published_at, @title, @body = published_at, title, body
8
+ end
9
+
10
+ end
11
+ end
@@ -0,0 +1,55 @@
1
+ module Lifestream
2
+ class Channel
3
+
4
+ attr_accessor :name, :branches, :raw_text, :feed
5
+
6
+ def initialize name, url
7
+ @name, @branches, @request = name, [], Lifestream::Request.new(url)
8
+ end
9
+
10
+ def branches
11
+ create_branches if @branches.empty?
12
+ @branches
13
+ end
14
+
15
+ protected
16
+
17
+ def download
18
+ response = @request.get
19
+ raise unless response.kind_of?(Net::HTTPSuccess)
20
+ @raw_data = response.body
21
+ rescue => e
22
+ Lifestream::Channel::DownloadError.new("The URL #{@request.url} failed to download") if Lifestream.options[:whiny]
23
+ end
24
+
25
+ def create_branches
26
+ download
27
+ parse
28
+ feed_to_a.each do |item|
29
+ @branches << to_branch(item)
30
+ end
31
+ end
32
+
33
+ def parse
34
+ raise_method_error :parse
35
+ end
36
+
37
+ def feed_to_a
38
+ raise_method_error :feed_to_a
39
+ end
40
+
41
+ def to_branch
42
+ raise_method_error :to_branch
43
+ end
44
+
45
+ private
46
+
47
+ def raise_method_error method
48
+ raise Lifestream::Channel::MethodError, "Method `#{method}` must be overriden in the child class"
49
+ end
50
+
51
+ class MethodError < StandardError; end
52
+ class DownloadError < StandardError; end
53
+
54
+ end
55
+ end
@@ -0,0 +1,26 @@
1
+ require 'rss/1.0'
2
+ require 'rss/2.0'
3
+
4
+ module Lifestream
5
+ class Channel::Rss2 < Lifestream::Channel
6
+
7
+ protected
8
+
9
+ def parse
10
+ @feed = RSS::Parser.parse(@raw_data, false)
11
+ rescue => e
12
+ raise Lifestream::Channel::Rss2::MalformedFeed.new("The feed from #{@url} could not be parsed") if Lifestream.options[:whiny]
13
+ end
14
+
15
+ def feed_to_a
16
+ @feed.items || []
17
+ end
18
+
19
+ def to_branch(branch)
20
+ Lifestream::Branch.new(branch.pubDate, branch.title, branch.description)
21
+ end
22
+
23
+ class MalformedFeed < StandardError; end
24
+
25
+ end
26
+ end
@@ -0,0 +1,42 @@
1
+ module Lifestream
2
+ class Request
3
+
4
+ attr_accessor :url, :max_redirects
5
+
6
+ def initialize(url, options = {})
7
+ @url = url
8
+ options[:max_redirects] ||= 5
9
+ @max_redirects = options[:max_redirects]
10
+ end
11
+
12
+ def get(url = @url)
13
+ check_max_redirects
14
+ url, request = build_request(url)
15
+ response = Net::HTTP.start(url.host, url.port) do |http|
16
+ http.request(request)
17
+ end
18
+ if response.kind_of?(Net::HTTPRedirection)
19
+ @redirect += 1
20
+ get(response.header['location'])
21
+ else
22
+ response
23
+ end
24
+ end
25
+
26
+ protected
27
+
28
+ def build_request(url)
29
+ url = URI.parse(url)
30
+ request = Net::HTTP::Get.new("#{url.path}?#{url.query}", {'User-Agent' => 'Gecko'})
31
+ return url, request
32
+ end
33
+
34
+ def check_max_redirects
35
+ @redirect ||= 0
36
+ raise TooManyRedirects if @redirect > @max_redirects
37
+ end
38
+
39
+ class TooManyRedirects < StandardError; end
40
+
41
+ end
42
+ end
@@ -0,0 +1,13 @@
1
+ module Lifestream
2
+ class Source
3
+
4
+ # TODO: Implement this
5
+ def self.configure
6
+ yaml = ERB.new <<-EOF
7
+
8
+ EOF
9
+ yaml.result
10
+ end
11
+
12
+ end
13
+ end
@@ -0,0 +1,20 @@
1
+ module Lifestream
2
+ class Stream
3
+
4
+ attr_accessor :channels
5
+
6
+ def initialize channels = []
7
+ @channels = channels
8
+ end
9
+
10
+ def branches
11
+ @branches ||= []
12
+ return @branches unless @branches.empty?
13
+ @channels.each do |channel|
14
+ channel.branches.each { |b| @branches << b }
15
+ end
16
+ @branches.sort { |a,b| a.published_at <=> b.published_at }.reverse
17
+ end
18
+
19
+ end
20
+ end
@@ -0,0 +1,9 @@
1
+ facebook :
2
+ url : http://www.facebook.com/feeds/status.php?id=778750315&viewer=778750315&key=110b5987c2&format=rss20
3
+ format : Rss2
4
+ pandora :
5
+ url : http://feeds.pandora.com/feeds/people/ah125i/favorites.xml
6
+ format : Rss2
7
+ twitter :
8
+ url : http://twitter.com/statuses/user_timeline/15344521.rss
9
+ format : Rss2
File without changes
File without changes
File without changes
@@ -0,0 +1,16 @@
1
+ require 'test_helper'
2
+
3
+ class StreamTest < Test::Unit::TestCase
4
+
5
+ context "A Lifestream::Stream instance" do
6
+
7
+ setup { @lifestream = Lifestream.run }
8
+
9
+ should "return its branches in descending chronological order" do
10
+ @lifestream.branches.should_not be_nil
11
+ @lifestream.branches[0].published_at.should > @lifestream.branches[1].published_at
12
+ end
13
+
14
+ end
15
+
16
+ end
@@ -0,0 +1,28 @@
1
+ require 'test_helper'
2
+
3
+ class LifestreamTest < Test::Unit::TestCase
4
+
5
+ context "The Lifestream module" do
6
+
7
+ should "create a Lifestream::Stream instance with all of its channels and branches" do
8
+ @lifestream = Lifestream::run
9
+ @lifestream.channels.size.should == 3
10
+ @lifestream.channels.each { |c| c.should_not be_nil }
11
+ @lifestream.channels.each { |c| c.should be_a(Lifestream::Channel::Rss2) }
12
+ @lifestream.channels.each do |c|
13
+ c.branches.each { |b| b.should_not be_nil }
14
+ c.branches.each { |b| b.should be_a(Lifestream::Branch) }
15
+ end
16
+ end
17
+
18
+ should "set the configuration file to the provided path" do
19
+ original_path = Lifestream.options[:config]
20
+ test_config_path = 'some/config'
21
+ Lifestream.options[:config] = test_config_path
22
+ Lifestream.options[:config].should == test_config_path
23
+ Lifestream.options[:config] = original_path
24
+ end
25
+
26
+ end
27
+
28
+ end
@@ -0,0 +1,39 @@
1
+ require 'test/unit'
2
+ require 'rubygems'
3
+
4
+ gem 'thoughtbot-shoulda', '>= 2.10.1'
5
+ gem 'jnunemaker-matchy', '0.4.0'
6
+ gem 'mocha', '0.9.7'
7
+ gem 'redgreen', '>= 1.0.0'
8
+
9
+ require 'shoulda'
10
+ require 'matchy'
11
+ require 'mocha'
12
+ require 'fakeweb'
13
+ require 'redgreen' unless ENV['TM_FILENAME']
14
+
15
+ directory = File.expand_path(File.dirname(__FILE__))
16
+
17
+ require File.join(directory, '..', 'lib', 'lifestream')
18
+
19
+ Lifestream.options[:config] = 'lifestream.yml'
20
+
21
+ class Test::Unit::TestCase
22
+
23
+ custom_matcher :be_nil do |receiver, matcher, args|
24
+ matcher.positive_failure_message = "Expected #{receiver} to be nil but it wasn't"
25
+ matcher.negative_failure_message = "Expected #{receiver} not to be nil but it was"
26
+ receiver.nil?
27
+ end
28
+
29
+ custom_matcher :be_a do |receiver, matcher, args|
30
+ receiver.class == args[0]
31
+ end
32
+
33
+ custom_matcher :be_empty do |receiver, matcher, args|
34
+ matcher.positive_failure_message = "Expected #{receiver} to be empty but it wasn't"
35
+ matcher.negative_failure_message = "Expected #{receiver} not to be empty but it was"
36
+ receiver.empty?
37
+ end
38
+
39
+ end
metadata ADDED
@@ -0,0 +1,115 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: lifestream
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Adam Hunter
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+
12
+ date: 2009-10-03 00:00:00 -04:00
13
+ default_executable:
14
+ dependencies:
15
+ - !ruby/object:Gem::Dependency
16
+ name: thoughtbot-shoulda
17
+ type: :development
18
+ version_requirement:
19
+ version_requirements: !ruby/object:Gem::Requirement
20
+ requirements:
21
+ - - ">="
22
+ - !ruby/object:Gem::Version
23
+ version: 2.10.1
24
+ version:
25
+ - !ruby/object:Gem::Dependency
26
+ name: jnunemaker-matchy
27
+ type: :development
28
+ version_requirement:
29
+ version_requirements: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - "="
32
+ - !ruby/object:Gem::Version
33
+ version: 0.4.0
34
+ version:
35
+ - !ruby/object:Gem::Dependency
36
+ name: mocha
37
+ type: :development
38
+ version_requirement:
39
+ version_requirements: !ruby/object:Gem::Requirement
40
+ requirements:
41
+ - - "="
42
+ - !ruby/object:Gem::Version
43
+ version: 0.9.4
44
+ version:
45
+ - !ruby/object:Gem::Dependency
46
+ name: redgreen
47
+ type: :development
48
+ version_requirement:
49
+ version_requirements: !ruby/object:Gem::Requirement
50
+ requirements:
51
+ - - "="
52
+ - !ruby/object:Gem::Version
53
+ version: 1.0.0
54
+ version:
55
+ description:
56
+ email: adamhunter@me.com
57
+ executables: []
58
+
59
+ extensions: []
60
+
61
+ extra_rdoc_files:
62
+ - README
63
+ files:
64
+ - README
65
+ - Rakefile
66
+ - VERSION
67
+ - lib/lifestream.rb
68
+ - lib/lifestream/branch.rb
69
+ - lib/lifestream/channel.rb
70
+ - lib/lifestream/channel/rss2.rb
71
+ - lib/lifestream/request.rb
72
+ - lib/lifestream/source.rb
73
+ - lib/lifestream/stream.rb
74
+ - test/lifestream.yml
75
+ - test/lifestream/branch_test.rb
76
+ - test/lifestream/channel_test.rb
77
+ - test/lifestream/source_test.rb
78
+ - test/lifestream/stream_test.rb
79
+ - test/lifestream_test.rb
80
+ - test/test_helper.rb
81
+ has_rdoc: true
82
+ homepage: http://github.com/adamhunter/lifestream
83
+ licenses: []
84
+
85
+ post_install_message:
86
+ rdoc_options:
87
+ - --charset=UTF-8
88
+ require_paths:
89
+ - lib
90
+ required_ruby_version: !ruby/object:Gem::Requirement
91
+ requirements:
92
+ - - ">="
93
+ - !ruby/object:Gem::Version
94
+ version: "0"
95
+ version:
96
+ required_rubygems_version: !ruby/object:Gem::Requirement
97
+ requirements:
98
+ - - ">="
99
+ - !ruby/object:Gem::Version
100
+ version: "0"
101
+ version:
102
+ requirements: []
103
+
104
+ rubyforge_project:
105
+ rubygems_version: 1.3.5
106
+ signing_key:
107
+ specification_version: 3
108
+ summary: downloads and parses lifestream information from sources like facebook and twitter
109
+ test_files:
110
+ - test/lifestream/branch_test.rb
111
+ - test/lifestream/channel_test.rb
112
+ - test/lifestream/source_test.rb
113
+ - test/lifestream/stream_test.rb
114
+ - test/lifestream_test.rb
115
+ - test/test_helper.rb