hooloo 0.1.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.
@@ -0,0 +1,7 @@
1
+ ---
2
+ SHA1:
3
+ metadata.gz: 39d4abb265b95abb7dc3edf473919c1dad719f93
4
+ data.tar.gz: dcfc2b375cc68713ae2fd538d34e9f69ab053c17
5
+ SHA512:
6
+ metadata.gz: f0ec5088f15b34cd31cf53131eed3c633530ee404cfe32eba319e5992a00fc734d349df2fb1466693743af56e08175217bbd536d3612d1fd59d786bc860e56a7
7
+ data.tar.gz: a9d2b1e575b509efcf11b7520bafd892b6081d4c42e874a9536e3498d138d3ad9e2f10168062de489381e65855f2af19d62227d92ed788b3145bb538a244779c
@@ -0,0 +1,22 @@
1
+ *.gem
2
+ *.rbc
3
+ .bundle
4
+ .config
5
+ .yardoc
6
+ Gemfile.lock
7
+ InstalledFiles
8
+ _yardoc
9
+ coverage
10
+ doc/
11
+ lib/bundler/man
12
+ pkg
13
+ rdoc
14
+ spec/reports
15
+ test/tmp
16
+ test/version_tmp
17
+ tmp
18
+ *.bundle
19
+ *.so
20
+ *.o
21
+ *.a
22
+ mkmf.log
@@ -0,0 +1,10 @@
1
+ language: ruby
2
+ rvm:
3
+ - 1.9.3
4
+ - 2.0.0
5
+ - 2.1.2
6
+ - jruby-19mode
7
+ script: bundle exec rake test
8
+ addons:
9
+ code_climate:
10
+ repo_token: f8aaf329b9e3e6ae1d8b23eba7a257e5a1376a852281e12e0a178982539887f7
data/Gemfile ADDED
@@ -0,0 +1,4 @@
1
+ source 'https://rubygems.org'
2
+
3
+ # Specify your gem's dependencies in hulu-api-ruby.gemspec
4
+ gemspec
data/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ The MIT License (MIT)
2
+
3
+ Copyright (c) 2014 Peter Lejeck
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
@@ -0,0 +1,9 @@
1
+ hooloo
2
+ ======
3
+ [![Travis CI](http://img.shields.io/travis/NuckChorris/hooloo.svg?style=flat)](https://travis-ci.org/NuckChorris/hooloo)
4
+ [![CodeClimate](http://img.shields.io/codeclimate/github/NuckChorris/hooloo.svg?style=flat)](https://codeclimate.com/github/NuckChorris/hooloo)
5
+ [![Coverage](http://img.shields.io/codeclimate/coverage/github/NuckChorris/hooloo.svg?style=flat)](https://codeclimate.com/github/NuckChorris/hooloo)
6
+ [![RubyGems](http://img.shields.io/gem/v/hooloo.svg?style=flat)](https://rubygems.org/gems/hooloo)
7
+ [![Gittip](http://img.shields.io/gittip/NuckChorris.svg?style=flat)](https://www.gittip.com/NuckChorris/)
8
+
9
+ Unofficial client for the Hulu "hidden" API
@@ -0,0 +1,8 @@
1
+ require 'bundler/gem_tasks'
2
+ require 'rake/testtask'
3
+
4
+ Rake::TestTask.new do |t|
5
+ rm_rf 'coverage/'
6
+ t.pattern = 'spec/**/*_spec.rb'
7
+ t.libs << 'spec'
8
+ end
@@ -0,0 +1,34 @@
1
+ # coding: utf-8
2
+ lib = File.expand_path('../lib', __FILE__)
3
+ $LOAD_PATH.unshift(lib) unless $LOAD_PATH.include?(lib)
4
+ require 'hooloo/version'
5
+
6
+ Gem::Specification.new do |spec|
7
+ spec.name = "hooloo"
8
+ spec.version = Hooloo::VERSION
9
+ spec.authors = ["Peter Lejeck"]
10
+ spec.email = ["me@plejeck.com"]
11
+ spec.summary = %q{Unofficial Client for the Hulu "Hidden" API}
12
+ spec.description = <<-DESC
13
+ Based on the magic of APIs, we are now capable of connecting to Hulu and retrieving their data for
14
+ use in other applications. A warning to ye who dare use this, however: Hulu does not guarantee
15
+ this API's stability, so it's possible (even likely) that your applications may break at any time.
16
+
17
+ This library is based on the work of {hulu-php-library}[https://github.com/adammagana/hulu-php-library],
18
+ an unofficial PHP client for this same API.
19
+ DESC
20
+ spec.homepage = "http://github.com/nuckchorris/hooloo/"
21
+ spec.license = "MIT"
22
+
23
+ spec.files = `git ls-files -z`.split("\x0")
24
+ spec.test_files = spec.files.grep(%r{^(test|spec|features)/})
25
+ spec.require_paths = ["lib"]
26
+
27
+ spec.add_dependency 'multi_json', '~> 1.0'
28
+
29
+ spec.add_development_dependency "bundler", "~> 1.6"
30
+ spec.add_development_dependency "rake"
31
+ spec.add_development_dependency "codeclimate-test-reporter"
32
+ spec.add_development_dependency "fakeweb"
33
+ spec.add_development_dependency "httplog"
34
+ end
@@ -0,0 +1,12 @@
1
+ # There has to be a better answer to solving dependencies than this odd order
2
+ # Can we hoist the classes somehow?
3
+
4
+ require 'hooloo/hooloo'
5
+ require 'hooloo/mozart_hash'
6
+ require 'hooloo/version'
7
+ require 'hooloo/rollup'
8
+ require 'hooloo/genre'
9
+ require 'hooloo/video'
10
+ require 'hooloo/company'
11
+ require 'hooloo/show'
12
+ #require 'hooloo/search'
@@ -0,0 +1,9 @@
1
+ # Represents a publisher of videos on Hulu
2
+ class Hooloo::Company < Hooloo::MozartHash
3
+ # Provides a list of all companies on Hulu
4
+ #
5
+ # @param args [Hash] (see Hooloo#request)
6
+ def self.list(args={})
7
+ Hooloo.request('companies', args)['data'].map { |x| new x['company'] }
8
+ end
9
+ end
@@ -0,0 +1,23 @@
1
+ class Hooloo::Genre < Hooloo::MozartHash
2
+ def initialize(obj)
3
+ super
4
+ if obj.is_a? String
5
+ @obj = {canonical_name: obj}
6
+ else
7
+ @obj = obj
8
+ end
9
+ end
10
+ def shows(args={items_per_page: 10, position: 0})
11
+ args.merge!({genre: canonical_name})
12
+ Hooloo.request('shows', args)['data'].map { |x| Hooloo::Show.new x['show'] }
13
+ end
14
+ # List all genres known to Hulu
15
+ #
16
+ # @param args [Hash] (see Hooloo#request)
17
+ # @return [Array<Hooloo::Genre>] List of genres
18
+ def self.list(args={})
19
+ Hooloo.request("shows/genres")['data'].map do |item|
20
+ Hooloo::Genre.new(item['genre'])
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,37 @@
1
+ require 'uri'
2
+ require 'open-uri'
3
+ require 'multi_json'
4
+
5
+ class Hooloo
6
+ class << self
7
+ def auto_cast(obj)
8
+ # TODO: Automatically cast an object received from Mozart into the corresponding Ruby Class
9
+ end
10
+ def hulu_uri
11
+ URI("http://www.hulu.com/")
12
+ end
13
+ def api_uri
14
+ hulu_uri + '/mozart/v1.h2o/'
15
+ end
16
+ def request_uri(path, query={})
17
+ uri = api_uri + path
18
+ uri.query = URI.encode_www_form({
19
+ access_token: tokens["API"]
20
+ }.merge(query))
21
+ uri
22
+ end
23
+ def request(*args)
24
+ # TODO: check if we get 403'd and request a new token
25
+ MultiJson.load open(request_uri(*args)).read
26
+ end
27
+ def tokens
28
+ @tokens or begin
29
+ @tokens = Hash[open(hulu_uri).read.scan(/([A-Z]+)_DONUT = '([a-zA-Z0-9\-_\/]+)';$/)]
30
+ end
31
+ end
32
+ def tokens!
33
+ @tokens = nil
34
+ tokens
35
+ end
36
+ end
37
+ end
@@ -0,0 +1,51 @@
1
+ class Hooloo::MozartHash
2
+ class << self
3
+ def field_mapping(fields)
4
+ fields = [fields] unless fields.is_a? Array
5
+ fields.map do |field|
6
+ if field.is_a?(Hash)
7
+ arr = field.to_a[0]
8
+ [arr[0], arr[1].to_s]
9
+ else
10
+ [field, field.to_s]
11
+ end
12
+ end
13
+ end
14
+ def date(*mappings)
15
+ field_mapping(mappings).each do |field, mapping|
16
+ define_method(field) { Date.iso8601(@obj[mapping.to_s]) }
17
+ end
18
+ end
19
+ def bool(*mappings)
20
+ field_mapping(mappings).each do |field, mapping|
21
+ define_method(field.to_s + '?') { @obj[mapping] }
22
+ end
23
+ end
24
+ def cast(klass, mappings, opts={map_array: true, map: false})
25
+ field_mapping(mappings).each do |field, mapping|
26
+ define_method(field) do
27
+ if opts[:map] || (@obj[mapping].is_a?(Array) && opts[:map_array])
28
+ @obj[mapping].map { |x| klass.new(x) }
29
+ else
30
+ klass.new @obj[mapping]
31
+ end
32
+ end
33
+ end
34
+ end
35
+ private :field_mapping
36
+ end
37
+ def initialize(o)
38
+ @obj = o
39
+ end
40
+ # Honestly, we should generate methods when we initially parse the Hash
41
+ # instead of doing this crap in method_missing. I'll do that later.
42
+ def method_missing(method)
43
+ @obj[method.to_s]
44
+ end
45
+ def respond_to?(method)
46
+ @obj.has_key? method.to_s or super
47
+ end
48
+ def inspect
49
+ "#<%s:%014x>" % [self.class.name, object_id]
50
+ end
51
+ end
@@ -0,0 +1,5 @@
1
+ # I have no idea what a rollup is, honestly
2
+ class Hooloo::Rollup < Hooloo::MozartHash
3
+ def butts
4
+ end
5
+ end
@@ -0,0 +1,24 @@
1
+ class Hooloo::Show < Hooloo::MozartHash
2
+ def self.popular_today(args={limit: 10, position: 0})
3
+ args.merge!({sort: 'popular_today'})
4
+ Hooloo.request('shows', args)['data'].map { |x| new x['show'] }
5
+ end
6
+ def initialize(id)
7
+ super
8
+ if id.is_a? Fixnum
9
+ @obj = Hooloo.request("shows/#{id}")['data'][0]['show']
10
+ elsif id.is_a? Hash
11
+ @obj = id
12
+ end
13
+ end
14
+ def videos(season=1)
15
+ Hooloo.request("shows/#{id}/episodes", {
16
+ items_per_page: 128,
17
+ season_number: season
18
+ })['data'].map { |x| Hooloo::Video.new x['video'] }
19
+ end
20
+ bool :embed_permitted, :has_captions
21
+ date :cache_time
22
+ cast Hooloo::Company, :company
23
+ cast Hooloo::Rollup, {rollups: :show_rollups}, {map: true}
24
+ end
@@ -0,0 +1,3 @@
1
+ class Hooloo
2
+ VERSION = "0.1.0"
3
+ end
@@ -0,0 +1,17 @@
1
+ class Hooloo::Video < Hooloo::MozartHash
2
+ # @param id [Fixnum]
3
+ def initialize(id)
4
+ super
5
+ if id.is_a? Fixnum
6
+ @obj = Hooloo.request("videos/#{id}")['data'][0]['video']
7
+ end
8
+ end
9
+ def copyright
10
+ @obj['copyright'].split(',').map(&:strip)
11
+ end
12
+ date :available_at, :cache_time, :original_premiere_date, :released_at
13
+ bool :embed_permitted, :has_captions, :has_hd, :is_auth_valid, :is_expiring, :is_html5_enabled,
14
+ :is_mature, :is_subscriber_only, :is_web_only
15
+ cast Float, :duration
16
+ cast URI, :thumbnail_url
17
+ end
@@ -0,0 +1,14 @@
1
+ require 'spec_helper'
2
+ require 'hooloo'
3
+
4
+ describe Hooloo::Company do
5
+ it 'should list all companies' do
6
+ Hooloo::Company.list.must_be_instance_of Array
7
+ Hooloo::Company.list.each { |x| x.must_be_instance_of Hooloo::Company }
8
+ end
9
+ it 'should get a company by id' do
10
+ skip 'Apparently there is a different system for this'
11
+ co = Hooloo::Company.new 151
12
+ co.must_be_instance_of Hooloo::Company
13
+ end
14
+ end
@@ -0,0 +1,20 @@
1
+ require 'spec_helper'
2
+ require 'hooloo/genre'
3
+
4
+ describe Hooloo::Genre do
5
+ describe 'List All' do
6
+ let(:genres) { Hooloo::Genre.list }
7
+ it 'should convert genre list to Genre objects' do
8
+ genres.each { |x| x.must_be_instance_of Hooloo::Genre }
9
+ end
10
+ end
11
+ describe 'Shows List' do
12
+ let(:genre) { Hooloo::Genre.new 'anime' }
13
+ it 'should return multiple shows' do
14
+ genre.shows.length.must_be :>, 0
15
+ end
16
+ it 'should convert shows to Show objects' do
17
+ genre.shows.each { |x| x.must_be_instance_of Hooloo::Show }
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,15 @@
1
+ require 'spec_helper'
2
+ require 'hooloo'
3
+
4
+ describe Hooloo do
5
+ it 'should fetch three tokens' do
6
+ Hooloo.tokens.length.must_equal 3
7
+ end
8
+ it 'should cache the tokens in memory' do
9
+ tokens = Hooloo.tokens
10
+ Hooloo.tokens.must_equal tokens
11
+ end
12
+ it 'should refresh tokens when we tell it to' do
13
+ Hooloo.tokens!.length.must_equal 3
14
+ end
15
+ end
@@ -0,0 +1,26 @@
1
+ require 'spec_helper'
2
+ require 'hooloo/mozart_hash'
3
+
4
+ describe Hooloo::MozartHash do
5
+ let(:symphony) do
6
+ symphony = Class.new(Hooloo::MozartHash) do
7
+ bool :is_test
8
+ date :date_field
9
+ end
10
+ symphony.new('is_test' => true, 'normal_field' => 'stuff', 'date_field' => '2012-10-05T17:00:00Z')
11
+ end
12
+ it 'should respond properly to bool method' do
13
+ symphony.must_respond_to :is_test?
14
+ symphony.is_test?.must_equal true
15
+ end
16
+ it 'should respond properly to date method' do
17
+ symphony.date_field.must_be_instance_of Date
18
+ end
19
+ it 'should respond properly from hash implicitly' do
20
+ symphony.must_respond_to :normal_field
21
+ symphony.normal_field.must_equal 'stuff'
22
+ end
23
+ it 'should leave off @obj from the inspect method' do
24
+ symphony.inspect.wont_match(/@obj/)
25
+ end
26
+ end
@@ -0,0 +1,23 @@
1
+ require 'spec_helper'
2
+ require 'hooloo/show'
3
+
4
+ describe Hooloo::Show do
5
+ describe 'Popular Today' do
6
+ let(:shows) { Hooloo::Show.popular_today }
7
+ it 'should retrieve popular_today' do
8
+ shows.length.must_equal 10
9
+ end
10
+ end
11
+ describe 'Loading' do
12
+ let(:show) { Hooloo::Show.new 11876 }
13
+ it 'should convert company to a Company object' do
14
+ show.company.must_be_instance_of Hooloo::Company
15
+ end
16
+ it 'should convert rollups to Rollup objects' do
17
+ show.rollups.each { |x| x.must_be_instance_of Hooloo::Rollup }
18
+ end
19
+ it 'should convert videos to Video objects' do
20
+ show.videos.each { |x| x.must_be_instance_of Hooloo::Video }
21
+ end
22
+ end
23
+ end
@@ -0,0 +1,10 @@
1
+ require 'spec_helper'
2
+ require 'hooloo/video'
3
+
4
+ describe Hooloo::Video do
5
+ let(:video) { Hooloo::Video.new 407993 }
6
+ it 'should split the copyright field on commas' do
7
+ video.copyright.must_be_instance_of Array
8
+ video.copyright.must_include "Reki Kawahara"
9
+ end
10
+ end
@@ -0,0 +1,5 @@
1
+ require 'minitest/spec'
2
+ require 'codeclimate-test-reporter'
3
+ require 'minitest/autorun'
4
+
5
+ CodeClimate::TestReporter.start
metadata ADDED
@@ -0,0 +1,164 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: hooloo
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.1.0
5
+ platform: ruby
6
+ authors:
7
+ - Peter Lejeck
8
+ autorequire:
9
+ bindir: bin
10
+ cert_chain: []
11
+ date: 2014-08-10 00:00:00.000000000 Z
12
+ dependencies:
13
+ - !ruby/object:Gem::Dependency
14
+ name: multi_json
15
+ requirement: !ruby/object:Gem::Requirement
16
+ requirements:
17
+ - - ~>
18
+ - !ruby/object:Gem::Version
19
+ version: '1.0'
20
+ type: :runtime
21
+ prerelease: false
22
+ version_requirements: !ruby/object:Gem::Requirement
23
+ requirements:
24
+ - - ~>
25
+ - !ruby/object:Gem::Version
26
+ version: '1.0'
27
+ - !ruby/object:Gem::Dependency
28
+ name: bundler
29
+ requirement: !ruby/object:Gem::Requirement
30
+ requirements:
31
+ - - ~>
32
+ - !ruby/object:Gem::Version
33
+ version: '1.6'
34
+ type: :development
35
+ prerelease: false
36
+ version_requirements: !ruby/object:Gem::Requirement
37
+ requirements:
38
+ - - ~>
39
+ - !ruby/object:Gem::Version
40
+ version: '1.6'
41
+ - !ruby/object:Gem::Dependency
42
+ name: rake
43
+ requirement: !ruby/object:Gem::Requirement
44
+ requirements:
45
+ - - '>='
46
+ - !ruby/object:Gem::Version
47
+ version: '0'
48
+ type: :development
49
+ prerelease: false
50
+ version_requirements: !ruby/object:Gem::Requirement
51
+ requirements:
52
+ - - '>='
53
+ - !ruby/object:Gem::Version
54
+ version: '0'
55
+ - !ruby/object:Gem::Dependency
56
+ name: codeclimate-test-reporter
57
+ requirement: !ruby/object:Gem::Requirement
58
+ requirements:
59
+ - - '>='
60
+ - !ruby/object:Gem::Version
61
+ version: '0'
62
+ type: :development
63
+ prerelease: false
64
+ version_requirements: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ - !ruby/object:Gem::Dependency
70
+ name: fakeweb
71
+ requirement: !ruby/object:Gem::Requirement
72
+ requirements:
73
+ - - '>='
74
+ - !ruby/object:Gem::Version
75
+ version: '0'
76
+ type: :development
77
+ prerelease: false
78
+ version_requirements: !ruby/object:Gem::Requirement
79
+ requirements:
80
+ - - '>='
81
+ - !ruby/object:Gem::Version
82
+ version: '0'
83
+ - !ruby/object:Gem::Dependency
84
+ name: httplog
85
+ requirement: !ruby/object:Gem::Requirement
86
+ requirements:
87
+ - - '>='
88
+ - !ruby/object:Gem::Version
89
+ version: '0'
90
+ type: :development
91
+ prerelease: false
92
+ version_requirements: !ruby/object:Gem::Requirement
93
+ requirements:
94
+ - - '>='
95
+ - !ruby/object:Gem::Version
96
+ version: '0'
97
+ description: |
98
+ Based on the magic of APIs, we are now capable of connecting to Hulu and retrieving their data for
99
+ use in other applications. A warning to ye who dare use this, however: Hulu does not guarantee
100
+ this API's stability, so it's possible (even likely) that your applications may break at any time.
101
+
102
+ This library is based on the work of {hulu-php-library}[https://github.com/adammagana/hulu-php-library],
103
+ an unofficial PHP client for this same API.
104
+ email:
105
+ - me@plejeck.com
106
+ executables: []
107
+ extensions: []
108
+ extra_rdoc_files: []
109
+ files:
110
+ - .gitignore
111
+ - .travis.yml
112
+ - Gemfile
113
+ - LICENSE
114
+ - README.md
115
+ - Rakefile
116
+ - hooloo.gemspec
117
+ - lib/hooloo.rb
118
+ - lib/hooloo/company.rb
119
+ - lib/hooloo/genre.rb
120
+ - lib/hooloo/hooloo.rb
121
+ - lib/hooloo/mozart_hash.rb
122
+ - lib/hooloo/rollup.rb
123
+ - lib/hooloo/show.rb
124
+ - lib/hooloo/version.rb
125
+ - lib/hooloo/video.rb
126
+ - spec/hooloo/company_spec.rb
127
+ - spec/hooloo/genre_spec.rb
128
+ - spec/hooloo/hooloo_spec.rb
129
+ - spec/hooloo/mozart_hash_spec.rb
130
+ - spec/hooloo/show_spec.rb
131
+ - spec/hooloo/video_spec.rb
132
+ - spec/spec_helper.rb
133
+ homepage: http://github.com/nuckchorris/hooloo/
134
+ licenses:
135
+ - MIT
136
+ metadata: {}
137
+ post_install_message:
138
+ rdoc_options: []
139
+ require_paths:
140
+ - lib
141
+ required_ruby_version: !ruby/object:Gem::Requirement
142
+ requirements:
143
+ - - '>='
144
+ - !ruby/object:Gem::Version
145
+ version: '0'
146
+ required_rubygems_version: !ruby/object:Gem::Requirement
147
+ requirements:
148
+ - - '>='
149
+ - !ruby/object:Gem::Version
150
+ version: '0'
151
+ requirements: []
152
+ rubyforge_project:
153
+ rubygems_version: 2.0.5
154
+ signing_key:
155
+ specification_version: 4
156
+ summary: Unofficial Client for the Hulu "Hidden" API
157
+ test_files:
158
+ - spec/hooloo/company_spec.rb
159
+ - spec/hooloo/genre_spec.rb
160
+ - spec/hooloo/hooloo_spec.rb
161
+ - spec/hooloo/mozart_hash_spec.rb
162
+ - spec/hooloo/show_spec.rb
163
+ - spec/hooloo/video_spec.rb
164
+ - spec/spec_helper.rb