p3-tvdb 0.8.3

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: 149cb6e47827c6cfb2d12e10b7414573b258c8c1
4
+ data.tar.gz: a377047291720772786f33e31712f68428577423
5
+ SHA512:
6
+ metadata.gz: 0181f3f172466c4f37aa24afda98b76fece7ec3bdf653840f6d3fb651ee7e5f369fae2ec38c49e4c50e276f508c362d498f55d190636463ff7ead5edaa5ce9ee
7
+ data.tar.gz: 7754dca33a310fef6e2101142053234d8c5414ab7bcdab1c3826a5afc9554027910b67aa968378ce490f26252a987afef2256f24f8e3e7b0396e94eb68a4597a
@@ -0,0 +1,5 @@
1
+ README.rdoc
2
+ lib/**/*.rb
3
+ bin/*
4
+ features/**/*.feature
5
+ LICENSE
@@ -0,0 +1,5 @@
1
+ *.sw?
2
+ .DS_Store
3
+ coverage
4
+ rdoc
5
+ pkg
data/LICENSE ADDED
@@ -0,0 +1,22 @@
1
+ Copyright (c) 2014 Damir Svrtan
2
+
3
+ MIT License
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining
6
+ a copy of this software and associated documentation files (the
7
+ "Software"), to deal in the Software without restriction, including
8
+ without limitation the rights to use, copy, modify, merge, publish,
9
+ distribute, sublicense, and/or sell copies of the Software, and to
10
+ permit persons to whom the Software is furnished to do so, subject to
11
+ the following conditions:
12
+
13
+ The above copyright notice and this permission notice shall be
14
+ included in all copies or substantial portions of the Software.
15
+
16
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
17
+ EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
18
+ MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
19
+ NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
20
+ LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
21
+ OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
22
+ WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,48 @@
1
+ h1. p3-tvdb
2
+
3
+ h2. What?
4
+
5
+ Search thetvdb.com's database
6
+
7
+ h2. Install
8
+
9
+ sudo gem install p3-tvdb
10
+
11
+ h2. How?
12
+
13
+ set up the client
14
+ <code>tvdb = P3::Tvdb::Search.new("YOURAPIKEY")
15
+
16
+ search for your series
17
+ <code>results = tvdb.search('the west wing')</code>
18
+
19
+ get the series
20
+ <code>west_wing = tvdb.get_series_by_id(results["seriesid"])</code>
21
+ <code>puts west_wing.name</code>
22
+ => The West Wing
23
+
24
+ get an episode
25
+ <code>episode_22 = west_wing.get_episode(1, 22)</code>
26
+ <code>puts episode_22.name</code>
27
+ => What Kind of Day Has It Been?
28
+
29
+ get series fanart - pass in your language
30
+ <code>puts west_wing.fanart('en').first.url</code>
31
+ => http://thetvdb.com/banners/fanart/original/72521-2.jpg
32
+
33
+ get series posters
34
+ <code>puts west_wing.posters('en').first.url</code>
35
+ => http://thetvdb.com/banners/posters/72521-1.jpg
36
+
37
+ get series banners
38
+ <code>puts west_wing.series_banners('en').first.url</code>
39
+ => http://thetvdb.com/banners/graphical/189-g.jpg
40
+
41
+ get season posters
42
+ <code>puts west_wing.season_posters(2, 'en').first.url</code>
43
+ => http://thetvdb.com/banners/seasons/72521-2.jpg
44
+
45
+ h2. Thanks
46
+
47
+ Thanks to thetvdb.com for their awesome database allowing us to meta out to our hearts consent.
48
+
data/VERSION ADDED
@@ -0,0 +1 @@
1
+ 0.8.0
@@ -0,0 +1,10 @@
1
+ require 'rubygems'
2
+ require 'httparty'
3
+
4
+ directory = File.expand_path(File.dirname(__FILE__))
5
+ require File.join(directory, 'p3-tvdb', 'httparty_icebox')
6
+ require File.join(directory, 'p3-tvdb', 'search')
7
+ require File.join(directory, 'p3-tvdb', 'series')
8
+ require File.join(directory, 'p3-tvdb', 'episode')
9
+ require File.join(directory, 'p3-tvdb', 'banner')
10
+ require File.join(directory, 'p3-tvdb', 'actor')
@@ -0,0 +1,20 @@
1
+ module P3
2
+ module Tvdb
3
+ class Actor
4
+ attr_accessor :id, :name, :role, :image
5
+
6
+ def initialize(options={})
7
+ @id = options["id"]
8
+ @name = options["Name"]
9
+ @role = options["Role"]
10
+ @image = options["Image"]
11
+ end
12
+
13
+ def image_url
14
+ return nil unless @image
15
+ "http://thetvdb.com/banners/" + @image
16
+ end
17
+
18
+ end
19
+ end
20
+ end
@@ -0,0 +1,24 @@
1
+ module P3
2
+ module Tvdb
3
+ class Banner
4
+ attr_accessor :banner_type, :banner_type2, :season, :path, :thumbnail_path, :language
5
+
6
+ def initialize(options={})
7
+ @banner_type = options["BannerType"]
8
+ @banner_type2 = options["BannerType2"]
9
+ @season = options["Season"]
10
+ @path = options["BannerPath"]
11
+ @language = options["Language"]
12
+ end
13
+
14
+ def url
15
+ "http://thetvdb.com/banners/" + @path
16
+ end
17
+
18
+ def thumb_url
19
+ "http://thetvdb.com/banners/_cache/" + @path
20
+ end
21
+
22
+ end
23
+ end
24
+ end
@@ -0,0 +1,60 @@
1
+ module P3
2
+ module Tvdb
3
+ class Episode
4
+ attr_reader :client
5
+ attr_accessor :id, :season_number, :number, :name, :overview, :air_date, :thumb, :guest_stars, :director, :writer, :rating, :rating_count
6
+
7
+ def initialize(client, options={})
8
+ @client = client
9
+ @id = options["id"]
10
+ @season_number = options["SeasonNumber"]
11
+ @number = options["EpisodeNumber"]
12
+ @name = options["EpisodeName"]
13
+ @overview = options["Overview"]
14
+ @thumb = "http://thetvdb.com/banners/" + options["filename"] if options["filename"].to_s != ""
15
+ @director = options["Director"]
16
+ @writer = options["Writer"]
17
+ @series_id = options["seriesid"]
18
+ @rating_count = options["RatingCount"]
19
+ if options["GuestStars"]
20
+ @guest_stars = options["GuestStars"][1..-1].split("|")
21
+ else
22
+ @guest_stars = []
23
+ end
24
+
25
+ if options["Rating"] && options["Rating"].size > 0
26
+ @rating = options["Rating"].to_f
27
+ else
28
+ @rating = 0
29
+ end
30
+
31
+ if options["RatingCount"] && options["RatingCount"].size > 0
32
+ @rating_count = options["RatingCount"].to_f
33
+ else
34
+ @rating_count = 0
35
+ end
36
+
37
+ begin
38
+ @air_date = Date.parse(options["FirstAired"])
39
+ rescue
40
+ end
41
+ end
42
+
43
+ def series
44
+ client.get_series_by_id(@series_id)
45
+ end
46
+
47
+ def to_h
48
+ hash = {}
49
+ self.instance_variables.each do | var |
50
+ #turn episode object into hash
51
+ v = self.instance_variable_get( var )
52
+ hash[ var.to_s.gsub('@','').to_sym ] = v
53
+ end
54
+ hash.delete(:client)
55
+ return hash
56
+ end
57
+
58
+ end
59
+ end
60
+ end
@@ -0,0 +1,259 @@
1
+ # = Icebox : Caching for HTTParty
2
+ #
3
+ # Cache responses in HTTParty models [http://github.com/jnunemaker/httparty]
4
+ #
5
+ # === Usage
6
+ #
7
+ # class Foo
8
+ # include HTTParty
9
+ # include HTTParty::Icebox
10
+ # cache :store => 'file', :timeout => 600, :location => MY_APP_ROOT.join('tmp', 'cache')
11
+ # end
12
+ #
13
+ # Modeled after Martyn Loughran's APICache [http://github.com/newbamboo/api_cache]
14
+ # and Ruby On Rails's caching [http://api.rubyonrails.org/classes/ActiveSupport/Cache.html]
15
+ #
16
+ # Author: Karel Minarik [www.karmi.cz]
17
+ #
18
+ # === Notes
19
+ #
20
+ # Thanks to Amit Chakradeo to point out objects have to be stored marhalled on FS
21
+ # Thanks to Marlin Forbes to point out query parameters have to be include in the cache key
22
+ #
23
+ #
24
+
25
+ require 'logger'
26
+ require 'fileutils'
27
+ require 'tmpdir'
28
+ require 'pathname'
29
+ require 'digest/md5'
30
+
31
+ module HTTParty #:nodoc:
32
+ module Icebox
33
+
34
+ module ClassMethods
35
+
36
+ # Enable caching and set cache options
37
+ # Returns memoized cache object
38
+ #
39
+ # Following options are available, default values are in []:
40
+ #
41
+ # +store+:: Storage mechanism for cached data (memory, filesystem, your own) [memory]
42
+ # +timeout+:: Cache expiration in seconds [60]
43
+ # +logger+:: Path to logfile or logger instance [STDOUT]
44
+ #
45
+ # Any additional options are passed to the Cache constructor
46
+ #
47
+ # Usage:
48
+ #
49
+ # # Enable caching in HTTParty, in memory, for 1 minute
50
+ # cache # Use default values
51
+ #
52
+ # # Enable caching in HTTParty, on filesystem (/tmp), for 10 minutes
53
+ # cache :store => 'file', :timeout => 600, :location => '/tmp/'
54
+ #
55
+ # # Use your own cache store (see AbstractStore class below)
56
+ # cache :store => 'memcached', :timeout => 600, :server => '192.168.1.1:1001'
57
+ #
58
+ def cache(options={})
59
+ options[:store] ||= 'memory'
60
+ options[:timeout] ||= 60
61
+ logger = options[:logger]
62
+ @cache ||= Cache.new( options.delete(:store), options )
63
+ end
64
+
65
+ end
66
+
67
+ # When included, extend class with +cache+ method
68
+ # and redefine +get+ method to use cache
69
+ #
70
+ def self.included(receiver) #:nodoc:
71
+ receiver.extend ClassMethods
72
+ receiver.class_eval do
73
+
74
+ # Get reponse from network
75
+ # TODO: Why alias :new :old is not working here? Returns NoMethodError
76
+ #
77
+ def self.get_without_caching(path, options={})
78
+ perform_request Net::HTTP::Get, path, options
79
+ end
80
+
81
+ # Get response from cache, if available
82
+ #
83
+ def self.get_with_caching(path, options={})
84
+ key = path.clone
85
+ key << options[:query].to_s if defined? options[:query]
86
+
87
+ if cache.exists?(key) and not cache.stale?(key)
88
+ Cache.logger.debug "CACHE -- GET #{path}#{options[:query]}"
89
+ return cache.get(key)
90
+ else
91
+ Cache.logger.debug "/!\\ NETWORK -- GET #{path}#{options[:query]}"
92
+ response = get_without_caching(path, options)
93
+ cache.set(key, response) if response.code == 200
94
+ return response
95
+ end
96
+ end
97
+
98
+ # Redefine original HTTParty +get+ method to use cache
99
+ #
100
+ def self.get(path, options={})
101
+ self.get_with_caching(path, options)
102
+ end
103
+
104
+ end
105
+ end
106
+
107
+ # === Cache container
108
+ #
109
+ # Pass a store name ('memory', etc) to initializer
110
+ #
111
+ class Cache
112
+ attr_accessor :store
113
+
114
+ def initialize(store, options={})
115
+ self.class.logger = options[:logger]
116
+ @store = self.class.lookup_store(store).new(options)
117
+ end
118
+
119
+ def get(key); @store.get encode(key) unless stale?(key); end
120
+ def set(key, value); @store.set encode(key), value; end
121
+ def exists?(key); @store.exists? encode(key); end
122
+ def stale?(key); @store.stale? encode(key); end
123
+
124
+ def self.logger; @logger || default_logger; end
125
+ def self.default_logger; logger = ::Logger.new(STDERR); end
126
+
127
+ # Pass a filename (String), IO object, Logger instance or +nil+ to silence the logger
128
+ def self.logger=(device); @logger = device.kind_of?(::Logger) ? device : ::Logger.new(device); end
129
+
130
+ private
131
+
132
+ # Return store class based on passed name
133
+ def self.lookup_store(name)
134
+ store_name = "#{name.capitalize}Store"
135
+ return Store::const_get(store_name)
136
+ rescue NameError => e
137
+ raise Store::StoreNotFound, "The cache store '#{store_name}' was not found. Did you loaded any such class?"
138
+ end
139
+
140
+ def encode(key); Digest::MD5.hexdigest(key); end
141
+ end
142
+
143
+
144
+ # === Cache stores
145
+ #
146
+ module Store
147
+
148
+ class StoreNotFound < StandardError; end #:nodoc:
149
+
150
+ # ==== Abstract Store
151
+ # Inherit your store from this class
152
+ # *IMPORTANT*: Do not forget to call +super+ in your +initialize+ method!
153
+ #
154
+ class AbstractStore
155
+ def initialize(options={})
156
+ raise ArgumentError, "You need to set the :timeout parameter" unless options[:timeout]
157
+ @timeout = options[:timeout]
158
+ message = "Cache: Using #{self.class.to_s.split('::').last}"
159
+ message << " in location: #{options[:location]}" if options[:location]
160
+ message << " with timeout #{options[:timeout]} sec"
161
+ Cache.logger.info message unless options[:logger].nil?
162
+ return self
163
+ end
164
+ %w{set get exists? stale?}.each do |method_name|
165
+ define_method(method_name) { raise NoMethodError, "Please implement method set in your store class" }
166
+ end
167
+ end
168
+
169
+ # ===== Store objects in memory
170
+ #
171
+ Struct.new("TvdbResponse", :code, :body, :headers) { def to_s; self.body; end }
172
+ class MemoryStore < AbstractStore
173
+ def initialize(options={})
174
+ super; @store = {}; self
175
+ end
176
+ def set(key, value)
177
+ Cache.logger.info("Cache: set (#{key})")
178
+ @store[key] = [Time.now, value]; true
179
+ end
180
+ def get(key)
181
+ data = @store[key][1]
182
+ Cache.logger.info("Cache: #{data.nil? ? "miss" : "hit"} (#{key})")
183
+ data
184
+ end
185
+ def exists?(key)
186
+ !@store[key].nil?
187
+ end
188
+ def stale?(key)
189
+ return true unless exists?(key)
190
+ Time.now - created(key) > @timeout
191
+ end
192
+ private
193
+ def created(key)
194
+ @store[key][0]
195
+ end
196
+ end
197
+
198
+ # ===== Store objects on the filesystem
199
+ #
200
+ class FileStore < AbstractStore
201
+ def initialize(options={})
202
+ super
203
+ options[:location] ||= Dir::tmpdir
204
+ @path = Pathname.new( options[:location] )
205
+ FileUtils.mkdir_p( @path )
206
+ self
207
+ end
208
+ def set(key, value)
209
+ Cache.logger.info("Cache: set (#{key})")
210
+ File.open( @path.join(key), 'w' ) { |file| Marshal.dump(value, file) }
211
+ true
212
+ end
213
+ def get(key)
214
+ data = Marshal.load(File.new(@path.join(key)))
215
+ Cache.logger.info("Cache: #{data.nil? ? "miss" : "hit"} (#{key})")
216
+ data
217
+ end
218
+ def exists?(key)
219
+ File.exists?( @path.join(key) )
220
+ end
221
+ def stale?(key)
222
+ return true unless exists?(key)
223
+ Time.now - created(key) > @timeout
224
+ end
225
+ private
226
+ def created(key)
227
+ File.mtime( @path.join(key) )
228
+ end
229
+ end
230
+ end
231
+
232
+ end
233
+ end
234
+
235
+
236
+ # Major parts of this code are based on architecture of ApiCache.
237
+ # Copyright (c) 2008 Martyn Loughran
238
+ #
239
+ # Other parts are inspired by the ActiveSupport::Cache in Ruby On Rails.
240
+ # Copyright (c) 2005-2009 David Heinemeier Hansson
241
+ #
242
+ # Permission is hereby granted, free of charge, to any person obtaining
243
+ # a copy of this software and associated documentation files (the
244
+ # "Software"), to deal in the Software without restriction, including
245
+ # without limitation the rights to use, copy, modify, merge, publish,
246
+ # distribute, sublicense, and/or sell copies of the Software, and to
247
+ # permit persons to whom the Software is furnished to do so, subject to
248
+ # the following conditions:
249
+ #
250
+ # The above copyright notice and this permission notice shall be
251
+ # included in all copies or substantial portions of the Software.
252
+ #
253
+ # THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND,
254
+ # EXPRESS OR IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF
255
+ # MERCHANTABILITY, FITNESS FOR A PARTICULAR PURPOSE AND
256
+ # NONINFRINGEMENT. IN NO EVENT SHALL THE AUTHORS OR COPYRIGHT HOLDERS BE
257
+ # LIABLE FOR ANY CLAIM, DAMAGES OR OTHER LIABILITY, WHETHER IN AN ACTION
258
+ # OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, OUT OF OR IN CONNECTION
259
+ # WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE SOFTWARE.
@@ -0,0 +1,99 @@
1
+ module P3
2
+ module Tvdb
3
+ class Search
4
+ include HTTParty
5
+ include HTTParty::Icebox
6
+ attr_accessor :language
7
+
8
+ base_uri 'www.thetvdb.com/api'
9
+
10
+ def initialize(the_api_key, language = 'en', cache_options = {})
11
+ @api_key = the_api_key
12
+ @language = language
13
+
14
+ if cache_options.keys.size > 0
15
+ self.class.cache cache_options
16
+ end
17
+
18
+ end
19
+
20
+ def search(series_name)
21
+ response = self.class.get("/GetSeries.php", {:query => {:seriesname => series_name, :language => @language}}).parsed_response
22
+ return [] unless response["Data"]
23
+
24
+ case response["Data"]["Series"]
25
+ when Array
26
+ response["Data"]["Series"]
27
+ when Hash
28
+ [response["Data"]["Series"]]
29
+ else
30
+ []
31
+ end
32
+ end
33
+
34
+ def get_series_by_id(series_id, language = self.language)
35
+ response = self.class.get("/#{@api_key}/series/#{series_id}/#{language}.xml").parsed_response
36
+
37
+ if response["Data"] && response["Data"]["Series"]
38
+ Series.new(self, response["Data"]["Series"])
39
+ else
40
+ nil
41
+ end
42
+ end
43
+
44
+ def get_episode_by_id(episode_id, language = self.language)
45
+ response = self.class.get("/#{@api_key}/episodes/#{episode_id}/#{language}.xml").parsed_response
46
+ if response["Data"] && response["Data"]["Episode"]
47
+ Episode.new(self, response["Data"]["Episode"])
48
+ else
49
+ nil
50
+ end
51
+ end
52
+
53
+ def get_episode(series, season_number, episode_number, language = self.language)
54
+ response = self.class.get("/#{@api_key}/series/#{series.id}/default/#{season_number}/#{episode_number}/#{language}.xml").parsed_response
55
+ if response["Data"] && response["Data"]["Episode"]
56
+ Episode.new(self, response["Data"]["Episode"])
57
+ else
58
+ nil
59
+ end
60
+ end
61
+
62
+ def get_all_episodes(series, language = self.language)
63
+ response = self.class.get("/#{@api_key}/series/#{series.id}/all/#{language}.xml").parsed_response
64
+ return [] unless response["Data"] && response["Data"]["Episode"]
65
+ case response["Data"]["Episode"]
66
+ when Array
67
+ response["Data"]["Episode"].map{|result| Episode.new(self, result)}
68
+ when Hash
69
+ [Episode.new(response["Data"]["Episode"])]
70
+ else
71
+ []
72
+ end
73
+ end
74
+
75
+ def get_actors(series)
76
+ response = self.class.get("/#{@api_key}/series/#{series.id}/actors.xml").parsed_response
77
+ if response["Actors"] && response["Actors"]["Actor"]
78
+ response["Actors"]["Actor"].collect {|a| Actor.new(a)}
79
+ else
80
+ nil
81
+ end
82
+ end
83
+
84
+ def get_banners(series)
85
+ response = self.class.get("/#{@api_key}/series/#{series.id}/banners.xml").parsed_response
86
+ return [] unless response["Banners"] && response["Banners"]["Banner"]
87
+ case response["Banners"]["Banner"]
88
+ when Array
89
+ response["Banners"]["Banner"].map{|result| Banner.new(result)}
90
+ when Hash
91
+ [Banner.new(response["Banners"]["Banner"])]
92
+ else
93
+ []
94
+ end
95
+ end
96
+
97
+ end
98
+ end
99
+ end
@@ -0,0 +1,102 @@
1
+ module P3
2
+ module Tvdb
3
+ class Series
4
+ attr_reader :client
5
+ attr_accessor :id, :name, :overview, :seasons, :first_aired, :genres, :network, :rating, :rating_count, :runtime,
6
+ :actors, :banners, :air_time, :imdb_id, :content_rating, :status
7
+
8
+ def initialize(client, options={})
9
+ @client = client
10
+ @id = options["id"]
11
+ @name = options["SeriesName"]
12
+ @overview = options["Overview"]
13
+ @network = options["Network"]
14
+ @runtime = options["Runtime"]
15
+ @air_time = options['Airs_Time'] if options['Airs_Time']
16
+ @imdb_id = options["IMDB_ID"]
17
+ @content_rating = options["ContentRating"]
18
+ @status = options["Status"]
19
+
20
+ if options["Genre"]
21
+ @genres = options["Genre"][1..-1].split("|")
22
+ else
23
+ @genres = []
24
+ end
25
+
26
+ if options["Rating"] && options["Rating"].size > 0
27
+ @rating = options["Rating"].to_f
28
+ else
29
+ @rating = 0
30
+ end
31
+
32
+ if options["RatingCount"] && options["RatingCount"].size > 0
33
+ @rating_count = options["RatingCount"].to_f
34
+ else
35
+ @rating_count = 0
36
+ end
37
+
38
+ begin
39
+ @first_aired = Date.parse(options["FirstAired"])
40
+ rescue
41
+ end
42
+ end
43
+
44
+ def get_episode(season_number, episode_number)
45
+ client.get_episode(self, season_number, episode_number)
46
+ end
47
+
48
+ def posters(language)
49
+ banners.select{|b| b.banner_type == 'poster' && b.language == language}
50
+ end
51
+
52
+ def fanart(language)
53
+ banners.select{|b| b.banner_type == 'fanart' && b.language == language}
54
+ end
55
+
56
+ def series_banners(language)
57
+ banners.select{|b| b.banner_type == 'series' && b.language == language}
58
+ end
59
+
60
+ def season_posters(season_number, language)
61
+ banners.select{|b| b.banner_type == 'season' && b.banner_type2 == 'season' && b.season == season_number.to_s && b.language == language}
62
+ end
63
+
64
+ def seasonwide_posters(season_number, language)
65
+ banners.select{|b| b.banner_type == 'season' && b.banner_type2 == 'seasonwide' && b.season == season_number.to_s && b.language == language}
66
+ end
67
+
68
+ def banners
69
+ @banners ||= client.get_banners(self)
70
+ end
71
+
72
+ def seasons
73
+ @seasons ||= client.get_seasons(self)
74
+ end
75
+
76
+ def episodes
77
+ @episodes ||= client.get_all_episodes(self)
78
+ end
79
+
80
+ def actors
81
+ @actors ||= client.get_actors(self)
82
+ end
83
+
84
+ def season(season_number)
85
+ seasons.detect{|s| s.number == season_number}
86
+ end
87
+
88
+ def to_h
89
+ hash = {}
90
+ self.instance_variables.each do | var |
91
+ #turn episode object into hash
92
+ v = self.instance_variable_get( var )
93
+ hash[ var.to_s.gsub('@','').to_sym ] = v
94
+ end
95
+ hash.delete(:client)
96
+ hash.delete(:banners)
97
+ return hash
98
+ end
99
+
100
+ end
101
+ end
102
+ end
@@ -0,0 +1,26 @@
1
+ # Generated by jeweler
2
+ # DO NOT EDIT THIS FILE DIRECTLY
3
+ # Instead, edit Jeweler::Tasks in Rakefile, and run 'rake gemspec'
4
+ # -*- encoding: utf-8 -*-
5
+ # stub: tvdb_party 0.8.0 ruby lib
6
+
7
+ Gem::Specification.new do |s|
8
+ s.name = "p3-tvdb"
9
+ s.version = "0.8.3"
10
+
11
+ s.required_rubygems_version = Gem::Requirement.new(">= 0") if s.respond_to? :required_rubygems_version=
12
+ s.require_paths = ["lib"]
13
+ s.authors = ["Jon Maddox", "Poul Hornsleth"]
14
+ s.email = ["poulh@umich.edu"]
15
+ s.homepage = "https://github.com/poulh/p3-tvdb"
16
+ s.license = "MIT"
17
+ s.summary = "TVDB Search API"
18
+ s.description = "Search thetvdb.com's database with this api ( requires thetvdb.com registration )"
19
+ s.extra_rdoc_files = [
20
+ "LICENSE",
21
+ "README.textile"
22
+ ]
23
+ s.files = `git ls-files -z`.split("\x0")
24
+ s.add_runtime_dependency "httparty", "~> 0.13.7"
25
+ end
26
+
metadata ADDED
@@ -0,0 +1,75 @@
1
+ --- !ruby/object:Gem::Specification
2
+ name: p3-tvdb
3
+ version: !ruby/object:Gem::Version
4
+ version: 0.8.3
5
+ platform: ruby
6
+ authors:
7
+ - Jon Maddox
8
+ - Poul Hornsleth
9
+ autorequire:
10
+ bindir: bin
11
+ cert_chain: []
12
+ date: 2017-02-24 00:00:00.000000000 Z
13
+ dependencies:
14
+ - !ruby/object:Gem::Dependency
15
+ name: httparty
16
+ requirement: !ruby/object:Gem::Requirement
17
+ requirements:
18
+ - - ~>
19
+ - !ruby/object:Gem::Version
20
+ version: 0.13.7
21
+ type: :runtime
22
+ prerelease: false
23
+ version_requirements: !ruby/object:Gem::Requirement
24
+ requirements:
25
+ - - ~>
26
+ - !ruby/object:Gem::Version
27
+ version: 0.13.7
28
+ description: Search thetvdb.com's database with this api ( requires thetvdb.com registration
29
+ )
30
+ email:
31
+ - poulh@umich.edu
32
+ executables: []
33
+ extensions: []
34
+ extra_rdoc_files:
35
+ - LICENSE
36
+ - README.textile
37
+ files:
38
+ - .document
39
+ - .gitignore
40
+ - LICENSE
41
+ - README.textile
42
+ - VERSION
43
+ - lib/p3-tvdb.rb
44
+ - lib/p3-tvdb/actor.rb
45
+ - lib/p3-tvdb/banner.rb
46
+ - lib/p3-tvdb/episode.rb
47
+ - lib/p3-tvdb/httparty_icebox.rb
48
+ - lib/p3-tvdb/search.rb
49
+ - lib/p3-tvdb/series.rb
50
+ - p3-tvdb.gemspec
51
+ homepage: https://github.com/poulh/p3-tvdb
52
+ licenses:
53
+ - MIT
54
+ metadata: {}
55
+ post_install_message:
56
+ rdoc_options: []
57
+ require_paths:
58
+ - lib
59
+ required_ruby_version: !ruby/object:Gem::Requirement
60
+ requirements:
61
+ - - '>='
62
+ - !ruby/object:Gem::Version
63
+ version: '0'
64
+ required_rubygems_version: !ruby/object:Gem::Requirement
65
+ requirements:
66
+ - - '>='
67
+ - !ruby/object:Gem::Version
68
+ version: '0'
69
+ requirements: []
70
+ rubyforge_project:
71
+ rubygems_version: 2.0.14.1
72
+ signing_key:
73
+ specification_version: 4
74
+ summary: TVDB Search API
75
+ test_files: []