hulu-show 0.1.0 → 0.2.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.
data/README.md ADDED
@@ -0,0 +1,51 @@
1
+ # hulu-show
2
+
3
+ Hulu::Show fetches all episodes for the current season of a specified show.
4
+
5
+ ## Show attributes:
6
+
7
+ :network,
8
+ :title,
9
+ :genre,
10
+ :description,
11
+ :errors,
12
+ :episodes,
13
+ :url
14
+
15
+ ## Episode attributes:
16
+
17
+ :title,
18
+ :episode,
19
+ :running_time,
20
+ :air_date,
21
+ :season,
22
+ :url,
23
+ :beaconid,
24
+ :thumbnail_url,
25
+ :embed_html
26
+
27
+ ## Usage
28
+
29
+ `gem install hulu-show`
30
+
31
+ `require 'hulu/show'`
32
+
33
+ `burn_notice = Hulu::Show.new('Burn Notice')`
34
+
35
+ #<Hulu::Show:0x007f972a04f740 @title="Burn Notice", @episodes=[#<Hulu::Episode:0x007f972a02c7b8 @episode="13", @title="Damned If You Do", @url="http://www.hulu.com/watch/296648/burn-notice-damned-if-you-do?c=Action-and-Adventure#x-4,cEpisodes,1,0", @beaconid="296648", @running_time="43:09", @air_date="11/03/2011", @embed_html="<object width=\"512\" height=\"296\"><param name=\"movie\" value=\"http://www.hulu.com/embed/c96sZQru3w567PP7t3cGZQ\"></param><param name=\"flashvars\" value=\"ap=1\"></param><embed src=\"http://www.hulu.com/embed/c96sZQru3w567PP7t3cGZQ\" type=\"application/x-shockwave-flash\" width=\"512\" height=\"296\" flashvars=\"ap=1\"></embed></object>", @thumbnail_url="http://thumbnails.hulu.com/8/60000008/60000008_145x80_generated.jpg">], @doc=nil, @errors=[], @network="USA", @genre="Action and Adventure", @description="A \"burned\" spy returns to Miami where he uses his special ops training to help those in need, and bring justice against the men who wrongly burned him.", @url="http://www.hulu.com/burn-notice">
36
+
37
+ ## Retrieve show episodes
38
+
39
+ `burn_notice.episodes`
40
+
41
+ [#<Hulu::Episode:0x007f961a02be00 @episode="13", @title="Damned If You Do", @url="http://www.hulu.com/watch/296648/burn-notice-damned-if-you-do?c=Action-and-Adventure#x-4,cEpisodes,1,0", @beaconid="296648", @running_time="43:09", @air_date="11/03/2011", @embed_html="<object width=\"512\" height=\"296\"><param name=\"movie\" value=\"http://www.hulu.com/embed/c96sZQru3w567PP7t3cGZQ\"></param><param name=\"flashvars\" value=\"ap=1\"></param><embed src=\"http://www.hulu.com/embed/c96sZQru3w567PP7t3cGZQ\" type=\"application/x-shockwave-flash\" width=\"512\" height=\"296\" flashvars=\"ap=1\"></embed></object>", @thumbnail_url="http://thumbnails.hulu.com/8/60000008/60000008_145x80_generated.jpg">]
42
+
43
+
44
+ ## Retrieve multiple shows with their episodes at one time.
45
+
46
+ `Hulu.shows(['Burn Notice', 'Warehouse 13'])`
47
+
48
+
49
+ Copyright (c) 2011 Craig Williams. See LICENSE.txt for
50
+ further details.
51
+
data/VERSION CHANGED
@@ -1 +1 @@
1
- 0.1.0
1
+ 0.2.0
data/hulu-show.gemspec CHANGED
@@ -5,16 +5,16 @@
5
5
 
6
6
  Gem::Specification.new do |s|
7
7
  s.name = "hulu-show"
8
- s.version = "0.1.0"
8
+ s.version = "0.2.0"
9
9
 
10
10
  s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
11
11
  s.authors = ["Craig Williams"]
12
- s.date = "2011-11-25"
12
+ s.date = "2011-11-27"
13
13
  s.description = "Really, that is about it. For each show, Hulu::Show will return an array of Episode objects with details about the episode."
14
14
  s.email = "cwilliams.allancraig@gmail.com"
15
15
  s.extra_rdoc_files = [
16
16
  "LICENSE.txt",
17
- "README.rdoc"
17
+ "README.md"
18
18
  ]
19
19
  s.files = [
20
20
  ".document",
@@ -23,7 +23,7 @@ Gem::Specification.new do |s|
23
23
  "Gemfile",
24
24
  "Gemfile.lock",
25
25
  "LICENSE.txt",
26
- "README.rdoc",
26
+ "README.md",
27
27
  "Rakefile",
28
28
  "VERSION",
29
29
  "hulu-show.gemspec",
@@ -31,9 +31,14 @@ Gem::Specification.new do |s|
31
31
  "lib/hulu/show.rb",
32
32
  "lib/hulu/show/base.rb",
33
33
  "lib/hulu/show/episode.rb",
34
+ "notes.txt",
35
+ "spec/hulu/base_spec.rb",
36
+ "spec/hulu/episode_spec.rb",
34
37
  "spec/hulu/show_spec.rb",
35
38
  "spec/spec_helper.rb",
36
- "spec/support/vcr_cassettes/burn_notice.yml"
39
+ "spec/support/vcr_cassettes/additional_attributes.yml",
40
+ "spec/support/vcr_cassettes/burn_notice.yml",
41
+ "spec/support/vcr_cassettes/non_existent_show.yml"
37
42
  ]
38
43
  s.homepage = "http://github.com/CraigWilliams/hulu-show"
39
44
  s.licenses = ["BSD"]
data/lib/hulu/show.rb CHANGED
@@ -1,21 +1,53 @@
1
+ # encoding: utf-8
2
+
1
3
  require 'hulu/show/base'
2
4
  require 'hulu/show/episode'
3
5
 
4
6
  class Hulu::Show < Hulu::Base
5
- attr_accessor :name
7
+ attr_accessor :network,
8
+ :title,
9
+ :genre,
10
+ :description,
11
+ :errors,
12
+ :episodes,
13
+ :url
6
14
 
7
- def initialize(name)
8
- @name = name
15
+ def initialize(title)
16
+ @title = title
9
17
  @episodes = []
18
+ @doc = Hulu.query(@title)
19
+ @errors = []
20
+
21
+ if error_404
22
+ @errors << "404: Show not found"
23
+ return
24
+ end
25
+
26
+ parse_show_details
27
+ parse_episodes
28
+ set_url
29
+
30
+ @doc = nil
31
+ end
32
+
33
+ def set_url
34
+ @url = "#{Hulu::BASE_URI}/#{Hulu::Base.prepare_name(@title)}"
35
+ end
36
+
37
+ def error_404
38
+ error = @doc.css('.fixed-lg .section .gr').text.strip
39
+ error =~ /404/ ? true : false
10
40
  end
11
41
 
12
- def episodes
13
- doc = Hulu.query(self.name)
14
- parse_episodes(doc)
42
+ def parse_show_details
43
+ details = @doc.css(".fixed-lg.container .section.details .relative .info")
44
+ @network = details[0].text.strip
45
+ @genre = details[2].text.split('|').first.gsub(/\302\240/, ' ').strip
46
+ @description = details[3].text.strip
15
47
  end
16
48
 
17
- def parse_episodes(doc)
18
- episodes = doc.css("#show-expander table")
49
+ def parse_episodes
50
+ episodes = @doc.css("#show-expander table")
19
51
 
20
52
  episodes.each_with_index do |episode, i|
21
53
  # There are several tables under the show-expander
@@ -27,7 +59,6 @@ class Hulu::Show < Hulu::Base
27
59
  end
28
60
  end
29
61
  end
30
- @episodes
31
62
  end
32
63
 
33
64
  end
@@ -29,4 +29,12 @@ module Hulu
29
29
  show_name = Hulu::Base.prepare_name(show_name)
30
30
  Hulu::Fetcher::Page.get("#{BASE_URI}/#{show_name}")
31
31
  end
32
+
33
+ def self.shows(titles)
34
+ shows = []
35
+ titles.each do |title|
36
+ shows << Hulu::Show.new(title)
37
+ end
38
+ shows
39
+ end
32
40
  end
@@ -3,15 +3,29 @@ class Hulu::Episode < Hulu::Base
3
3
  :episode,
4
4
  :running_time,
5
5
  :air_date,
6
- :season
7
-
6
+ :season,
7
+ :url,
8
+ :beaconid,
9
+ :thumbnail_url,
10
+ :embed_html
11
+
8
12
  def initialize
9
13
  yield self if block_given?
14
+
15
+ set_additional_attributes
16
+ end
17
+
18
+ def set_additional_attributes
19
+ info = additional_attributes
20
+ @embed_html = info['html']
21
+ @thumbnail_url = info['thumbnail_url']
10
22
  end
11
23
 
12
24
  def process(episode)
13
- @episode = episode.css('td.c0').text.strip
14
- @title = episode.css('td.c1 a').text.strip
25
+ @episode = episode.css('td.c0').text.strip rescue ''
26
+ @title = episode.css('td.c1 a').text.strip rescue ''
27
+ @url = episode.css('td.c1 a').attr('href').text.strip rescue ''
28
+ @beaconid = episode.css('td.c1 a').attr('beaconid').text.strip rescue ''
15
29
  parse_running_time(episode)
16
30
  end
17
31
 
@@ -20,11 +34,16 @@ class Hulu::Episode < Hulu::Base
20
34
 
21
35
  if run_time.include?(':')
22
36
  @running_time = run_time
23
- @air_date = episode.css('td.c4').text.strip
37
+ @air_date = episode.css('td.c4').text.strip rescue ''
24
38
  else
25
- @running_time = episode.css('td.c4').text.strip
26
- @air_date = episode.css('td.c5').text.strip
39
+ @running_time = episode.css('td.c4').text.strip rescue ''
40
+ @air_date = episode.css('td.c5').text.strip rescue ''
27
41
  end
28
42
  end
29
43
 
44
+ def additional_attributes
45
+ url = "http://www.hulu.com/api/oembed.json?url=http://www.hulu.com/watch/#{@beaconid}/#{Hulu::Base.prepare_name(@title)}"
46
+ Hulu::Fetcher::Page.get(url).parsed_response
47
+ end
48
+
30
49
  end
data/notes.txt ADDED
@@ -0,0 +1,25 @@
1
+ #==============================================================
2
+ # Fetching more data about a show
3
+ #==============================================================
4
+ # http://www.hulu.com/api/oembed.json?url=http://www.hulu.com/watch/20807/late-night-with-conan-obrien-wed-may-21-2008
5
+ # http://www.hulu.com/api/oembed.json?url=http://www.hulu.com/watch/261293/burn-notice-mind-games
6
+
7
+ {
8
+ "thumbnail_width": 145,
9
+ "type": "video",
10
+ "title": "Shadows (Warehouse 13)",
11
+ "embed_url": "http://www.hulu.com/embed/Gp_eWf7PQr697Ol0j7OfEg",
12
+ "thumbnail_height": 80,
13
+ "height": 296,
14
+ "provider_name": "Hulu",
15
+ "width": 512,
16
+ "html": "<object width=\"512\" height=\"296\"><param name=\"movie\" value=\"http://www.hulu.com/embed/Gp_eWf7PQr697Ol0j7OfEg\"></param><param name=\"flashvars\" value=\"ap=1\"></param><embed src=\"http://www.hulu.com/embed/Gp_eWf7PQr697Ol0j7OfEg\" type=\"application/x-shockwave-flash\" width=\"512\" height=\"296\" flashvars=\"ap=1\"></embed></object>",
17
+ "provider_url": "http://www.hulu.com/",
18
+ "duration": 2584.25,
19
+ "version": "1.0",
20
+ "cache_age": 3600,
21
+ "air_date": "Mon Sep 12 00:00:00 UTC 2011",
22
+ "thumbnail_url": "http://thumbnails.hulu.com/188/40038188/40038188_145x80_generated.jpg",
23
+ "author_name": "Syfy"
24
+ }
25
+
@@ -0,0 +1,13 @@
1
+ require 'spec_helper'
2
+
3
+ describe Hulu do
4
+
5
+ it "returns an array of shows" do
6
+ titles = ['Burn Notice', 'Warehouse 13', 'Terra Nova']
7
+ shows = Hulu.shows(titles)
8
+
9
+ shows.count.should == 3
10
+ # shows.first.episodes.first.title.should == 'What'
11
+ end
12
+
13
+ end
@@ -0,0 +1,18 @@
1
+ require 'spec_helper'
2
+
3
+ describe Hulu::Episode do
4
+
5
+ before { VCR.insert_cassette('additional_attributes') }
6
+ after { VCR.eject_cassette }
7
+
8
+ it "episode can fetch additional attributes" do
9
+ episode = Hulu::Episode.new do |episode|
10
+ episode.beaconid = '296648'
11
+ episode.title = 'Damned If You Do'
12
+ episode.additional_attributes
13
+ end
14
+
15
+ episode.thumbnail_url.should == "http://thumbnails.hulu.com/8/60000008/60000008_145x80_generated.jpg"
16
+ episode.embed_html.should_not be_nil
17
+ end
18
+ end
@@ -1,37 +1,93 @@
1
+ # encoding: utf-8
2
+
3
+ require 'json'
4
+
1
5
  require 'spec_helper'
2
6
 
3
7
  describe Hulu::Show do
4
- let(:burn_notice_erb) {
5
- {
6
- title: 'Burn baby burn',
7
- running_time: '43:09',
8
- air_date: '11/03/2011',
9
- episode: '13'
8
+
9
+ context "When show is found" do
10
+ let(:burn_notice_erb) {
11
+ {
12
+ title: 'Burn baby burn',
13
+ running_time: '43:09',
14
+ air_date: '11/03/2011',
15
+ episode: '13',
16
+ network: 'USA',
17
+ genre: '<b><a href=\"http://www.hulu.com/genres/Action-and-Adventure\"
18
+ class=\"show-title\">Action and Adventure</a>&nbsp;&nbsp;|&nbsp;&nbsp;<a href=\"http://www.hulu.com/genres/Drama\"
19
+ class=\"show-title\">Drama</a></b>',
20
+ description: "A &quot;burned&quot; spy returns to Miami where he uses his special ops training to help those in need, and bring justice against the men who wrongly burned him."
21
+ }
10
22
  }
11
- }
12
23
 
13
- it "should know it's name" do
14
- Hulu::Show.new('Bones').name.should == 'Bones'
15
- end
24
+ let(:additional_attributes) {
25
+ {
26
+ "thumbnail_width" => 145,
27
+ "type" => "video",
28
+ "title" => "Shadows (Warehouse 13)",
29
+ "embed_url" => "http://www.hulu.com/embed/Gp_eWf7PQr697Ol0j7OfEg",
30
+ "thumbnail_height" => 80,
31
+ "height" => 296,
32
+ "provider_name" => "Hulu",
33
+ "width" => 512,
34
+ "html" => "<object width=\"512\" height=\"296\"><param name=\"movie\" value=\"http://www.hulu.com/embed/Gp_eWf7PQr697Ol0j7OfEg\"></param><param name=\"flashvars\" value=\"ap=1\"></param><embed src=\"http://www.hulu.com/embed/Gp_eWf7PQr697Ol0j7OfEg\" type=\"application/x-shockwave-flash\" width=\"512\" height=\"296\" flashvars=\"ap=1\"></embed></object>",
35
+ "provider_url" => "http://www.hulu.com/",
36
+ "duration" => 2584.25,
37
+ "version" => "1.0",
38
+ "cache_age" => 3600,
39
+ "air_date" => "Mon Sep 12 00:00:00 UTC 2011",
40
+ "thumbnail_url" => "http://thumbnails.hulu.com/188/40038188/40038188_145x80_generated.jpg",
41
+ "author_name" => "Syfy"
42
+ }
43
+ }
44
+
45
+ before do
46
+ Hulu::Episode.any_instance.stub(:additional_attributes).and_return(additional_attributes)
47
+ VCR.insert_cassette('burn_notice', erb: burn_notice_erb)
48
+ end
49
+
50
+ after { VCR.eject_cassette }
51
+
52
+ it "show attributes should be set" do
53
+ show = Hulu::Show.new('Burn Notice')
54
+ show.title.should == 'Burn Notice'
55
+ show.network.should == 'USA'
56
+ show.genre.should == 'Action and Adventure'
57
+ show.description.should == "A \"burned\" spy returns to Miami where he uses his special ops training to help those in need, and bring justice against the men who wrongly burned him."
58
+ show.url == "http://www.hulu.com/burn-notice"
59
+ end
16
60
 
17
- it "created episodes with correct attributes" do
18
- VCR.use_cassette('burn_notice', erb: burn_notice_erb) do
61
+ it "episodes return correct attributes" do
19
62
  episodes = Hulu::Show.new('Burn Notice').episodes
20
63
  episode = episodes.first
21
64
 
22
- episode.title.should == 'Burn baby burn'
65
+ episode.title.should == 'Burn baby burn'
23
66
  episode.running_time.should == '43:09'
24
- episode.air_date.should == '11/03/2011'
25
- episode.episode.should == '13'
67
+ episode.air_date.should == '11/03/2011'
68
+ episode.episode.should == '13'
69
+ episode.url == "http://www.hulu.com/watch/296648/burn-notice-damned-if-you-do#x-4,cEpisodes,1,0"
70
+ episode.beaconid == '296648'
71
+
72
+ # additional_attributes
73
+ episode.thumbnail_url.should == "http://thumbnails.hulu.com/188/40038188/40038188_145x80_generated.jpg"
26
74
  end
27
- end
28
75
 
29
- it "has the correct number of episodes" do
30
- VCR.use_cassette('burn_notice', erb: burn_notice_erb) do
76
+ it "has the correct number of episodes" do
31
77
  episodes = Hulu::Show.new('Burn Notice').episodes
32
-
33
78
  episodes.count.should == 1
34
79
  end
80
+
81
+ end
82
+
83
+ context "When show not found" do
84
+ before { VCR.insert_cassette('non_existent_show') }
85
+ after { VCR.eject_cassette }
86
+
87
+ it "contains an error when show not found" do
88
+ show = Hulu::Show.new("Non-existent show")
89
+ show.errors.should include("404: Show not found")
90
+ end
35
91
  end
36
92
 
37
93
  end
data/spec/spec_helper.rb CHANGED
@@ -11,8 +11,9 @@ Dir["#{File.dirname(__FILE__)}/support/**/*.rb"].each {|f| require f}
11
11
  VCR.config do |c|
12
12
  c.cassette_library_dir = 'spec/support/vcr_cassettes'
13
13
  c.stub_with :fakeweb
14
+ c.allow_http_connections_when_no_cassette = true
14
15
  end
15
16
 
16
17
  RSpec.configure do |config|
17
18
  config.extend VCR::RSpec::Macros
18
- end
19
+ end
@@ -0,0 +1,33 @@
1
+ ---
2
+ - !ruby/struct:VCR::HTTPInteraction
3
+ request: !ruby/struct:VCR::Request
4
+ method: :get
5
+ uri: http://www.hulu.com:80/api/oembed.json?url=http://www.hulu.com/watch/296648/damned-if-you-do
6
+ body:
7
+ headers:
8
+ response: !ruby/struct:VCR::Response
9
+ status: !ruby/struct:VCR::ResponseStatus
10
+ code: 200
11
+ message: OK
12
+ headers:
13
+ server:
14
+ - nginx
15
+ content-type:
16
+ - application/json; charset=utf-8
17
+ status:
18
+ - 200 OK
19
+ x-ua-compatible:
20
+ - IE=EmulateIE9; IE=EmulateIE7
21
+ content-length:
22
+ - '803'
23
+ cache-control:
24
+ - max-age=3544
25
+ date:
26
+ - Sat, 26 Nov 2011 23:08:44 GMT
27
+ body: ! '{"author_name":"USA","type":"video","thumbnail_width":145,"thumbnail_height":80,"title":"Damned
28
+ If You Do (Burn Notice)","width":512,"provider_name":"Hulu","embed_url":"http://www.hulu.com/embed/c96sZQru3w567PP7t3cGZQ","version":"1.0","duration":2589.67,"height":296,"provider_url":"http://www.hulu.com/","air_date":"Thu
29
+ Nov 03 00:00:00 UTC 2011","html":"<object width=\"512\" height=\"296\"><param
30
+ name=\"movie\" value=\"http://www.hulu.com/embed/c96sZQru3w567PP7t3cGZQ\"></param><param
31
+ name=\"flashvars\" value=\"ap=1\"></param><embed src=\"http://www.hulu.com/embed/c96sZQru3w567PP7t3cGZQ\"
32
+ type=\"application/x-shockwave-flash\" width=\"512\" height=\"296\" flashvars=\"ap=1\"></embed></object>","cache_age":3600,"thumbnail_url":"http://thumbnails.hulu.com/8/60000008/60000008_145x80_generated.jpg"}'
33
+ http_version: '1.1'