tvdbr 0.0.1
Sign up to get free protection for your applications and to get access to all the features.
- data/.gitignore +3 -0
- data/Gemfile +4 -0
- data/Gemfile.lock +27 -0
- data/README +70 -0
- data/Rakefile +2 -0
- data/examples/demo.rb +41 -0
- data/lib/tvdbr/client.rb +123 -0
- data/lib/tvdbr/data_set.rb +79 -0
- data/lib/tvdbr/episode.rb +17 -0
- data/lib/tvdbr/series.rb +36 -0
- data/lib/tvdbr/version.rb +3 -0
- data/lib/tvdbr.rb +6 -0
- data/spec/.gitkeep +0 -0
- data/tvdbr.gemspec +23 -0
- metadata +123 -0
data/.gitignore
ADDED
data/Gemfile
ADDED
data/Gemfile.lock
ADDED
@@ -0,0 +1,27 @@
|
|
1
|
+
PATH
|
2
|
+
remote: .
|
3
|
+
specs:
|
4
|
+
tvdbr (0.0.1)
|
5
|
+
activesupport
|
6
|
+
hashie
|
7
|
+
httparty
|
8
|
+
|
9
|
+
GEM
|
10
|
+
remote: http://rubygems.org/
|
11
|
+
specs:
|
12
|
+
activesupport (3.0.3)
|
13
|
+
crack (0.1.8)
|
14
|
+
hashie (0.4.0)
|
15
|
+
httparty (0.6.1)
|
16
|
+
crack (= 0.1.8)
|
17
|
+
rake (0.8.7)
|
18
|
+
|
19
|
+
PLATFORMS
|
20
|
+
ruby
|
21
|
+
|
22
|
+
DEPENDENCIES
|
23
|
+
activesupport
|
24
|
+
hashie
|
25
|
+
httparty
|
26
|
+
rake
|
27
|
+
tvdbr!
|
data/README
ADDED
@@ -0,0 +1,70 @@
|
|
1
|
+
# 1. Associate our media with tvdb
|
2
|
+
# 2. Iterate through and search episodes (backfill missing episodes, backfill better screenshots)
|
3
|
+
# 3. Update rake task, daily => get all the updates, reference the changes => propogate to our data (new episodes, new shows)
|
4
|
+
|
5
|
+
# rake tvdb:populate => associate media to tvdb and backfill missing episodes and show info
|
6
|
+
|
7
|
+
Media.tvdb_id_is_null.find_each do |media|
|
8
|
+
tvdb_match = tvdb.fetch_series_from_data(:title => media.title, :starring => media.starring)
|
9
|
+
# Update media info and/or associate media to tvdb (ref_id) and change source
|
10
|
+
media.update_attributes(:source => "Tvdb", :tvdb_id => tvdb_match.id)
|
11
|
+
tvdb_match.episodes.each do |tvdb_episode|
|
12
|
+
episode = media.episodes.where(:episode => tvdb_episode.episode_num, :season => tvdb_episode.season_num)
|
13
|
+
# Update or create episode from the information from tvdb
|
14
|
+
end
|
15
|
+
end
|
16
|
+
|
17
|
+
# rake tvdb:daily => update database to sync with new shows and episodes on a daily task (attach existing show)
|
18
|
+
|
19
|
+
tvdb.each_updated_series(:since => 1.day.ago) do |tvdb_series|
|
20
|
+
puts "#{series.id} - #{series.title}"
|
21
|
+
media = Media.where(:ref_id => tvdb_series.id).first
|
22
|
+
# Update information from the new data?
|
23
|
+
end
|
24
|
+
|
25
|
+
tvdb.each_updated_episode(:since => 1.day.ago) do |tvdb_episode|
|
26
|
+
media = Media.where(:ref_id => tvdb_series.seriesid).first
|
27
|
+
episode = Episode.where(:season => tvdb_episode.season_num, :episode => tvdb_episode.episode_num).first
|
28
|
+
# Update or create episode information based on the new data.
|
29
|
+
end
|
30
|
+
|
31
|
+
== Initial Database Processing
|
32
|
+
|
33
|
+
- Get the current server time
|
34
|
+
a. Retrieve http://www.thetvdb.com/api/Updates.php?type=none. (Time.now.to_i) [1295299577]
|
35
|
+
b. Store this value for later use (denoted as <previoustime> for rest of example).
|
36
|
+
|
37
|
+
- Loop through and look up each series id
|
38
|
+
a. Retrieve http://www.thetvdb.com/api/GetSeries.php?seriesname=<series name from your database>
|
39
|
+
b. Optionally present results to user so they can select the match they want.
|
40
|
+
c. Store this series id in a table in your database.
|
41
|
+
|
42
|
+
- Get base information for each series
|
43
|
+
a. Retrieve <mirrorpath_zip>/api/<apikey>/series/<seriesid>/all/<language>.zip and extract <language>.xml and banners.xml.
|
44
|
+
b. Process the XML data in <language>.xml and store all <Series> data.
|
45
|
+
c. Download each series banner in banners.xml and prompt the user to see which they want to keep.
|
46
|
+
Note: Make sure you record <id> from each series, since it's returned in updates as <Series>.
|
47
|
+
|
48
|
+
- Get base information for each episode
|
49
|
+
a. Use <language>.xml from step 3 to find and store the data associated with your episode.
|
50
|
+
b. Use <filename> from results in step above to download the episode image from <mirrorpath_banners>/banners/<filename>.
|
51
|
+
Note: Make sure you record <id> from each episode, since it's returned in updates as <Episode>.
|
52
|
+
|
53
|
+
== Future Database Processing
|
54
|
+
|
55
|
+
These steps are used to keep your database current with the latest information.
|
56
|
+
|
57
|
+
- Get a list of all series and episode updates
|
58
|
+
a. Retrieve http://www.thetvdb.com/api/Updates.php?type=all&time=<previoustime>.
|
59
|
+
b. Process the returned XML and loop through each series (<seriesid>) and episode (<episodeid>) entry.
|
60
|
+
|
61
|
+
- Update each series in the update XML
|
62
|
+
a. Retrieve <mirrorpath_xml>/api/<apikey>/series/<seriesid>/<language>.xml.
|
63
|
+
b. Process XML data and use to replace information in local database.
|
64
|
+
|
65
|
+
- Update each episode in the update XML
|
66
|
+
a. Retrieve <mirrorpath_xml>/api/<apikey>/episodes/<episodeid>/<language>.xml.
|
67
|
+
b. Process XML data and use to replace information in local database.
|
68
|
+
|
69
|
+
- Record <previoustime> for next update
|
70
|
+
a. Using the XML from step 2, store <Time> as <previoustime> and use for your next call to Updates.php.
|
data/Rakefile
ADDED
data/examples/demo.rb
ADDED
@@ -0,0 +1,41 @@
|
|
1
|
+
require 'rubygems'
|
2
|
+
require 'tvdbr'
|
3
|
+
|
4
|
+
tvdb = Tvdbr::Client.new('YOUR_API_KEY')
|
5
|
+
|
6
|
+
# Fetch series based on title and starring
|
7
|
+
series_wrong = tvdb.fetch_series_from_data(:title => "Dexter",
|
8
|
+
:starring => "Adewale Akinnuoye-Agbaje, Sam Anderson, Naveen Andrews, L. Scott Caldwell, Nestor Carbonell, François Chau, Henry Ian Cusick, Jeremy Davies, Emilie de Ravin, Michael Emerson, Jeff Fahey, Fionnula Flanagan, Matthew Fox, Jorge Garcia, Maggie Grace, Josh Holloway, Malcolm David Kelley, Daniel Dae Kim, Yunjin Kim, Ken Leung, Evangeline Lilly, Rebecca Mader, Elizabeth Mitchell, Dominic Monaghan, Terry O'Quinn, Harold Perrineau, Zuleikha Robinson, Michelle Rodriguez, Kiele Sanchez,Rodrigo Santoro, Ian Somerhalder, John Terry, Sonya Walger, Cynthia Watros")
|
9
|
+
puts "Wrong Match: #{series_wrong.inspect}"
|
10
|
+
|
11
|
+
# Fetch series based on title and starring
|
12
|
+
series_right = tvdb.fetch_series_from_data(:title => "Lost",
|
13
|
+
:starring => "Adewale Akinnuoye-Agbaje, Sam Anderson, Naveen Andrews, L. Scott Caldwell, Nestor Carbonell, François Chau, Henry Ian Cusick, Jeremy Davies, Emilie de Ravin, Michael Emerson, Jeff Fahey, Fionnula Flanagan, Matthew Fox, Jorge Garcia, Maggie Grace, Josh Holloway, Malcolm David Kelley, Daniel Dae Kim, Yunjin Kim, Ken Leung, Evangeline Lilly, Rebecca Mader, Elizabeth Mitchell, Dominic Monaghan, Terry O'Quinn, Harold Perrineau, Zuleikha Robinson, Michelle Rodriguez, Kiele Sanchez,Rodrigo Santoro, Ian Somerhalder, John Terry, Sonya Walger, Cynthia Watros")
|
14
|
+
puts "Right Match: #{series_right.inspect}"
|
15
|
+
|
16
|
+
puts "\n\n"
|
17
|
+
series = series_right
|
18
|
+
puts series.title + " (" + series.categories.join(", ") + ")"
|
19
|
+
puts series.synopsis
|
20
|
+
puts series.starring.join(", ")
|
21
|
+
puts series.poster
|
22
|
+
puts series.release_date.inspect
|
23
|
+
|
24
|
+
# Fetch episodes for a series
|
25
|
+
puts "\nEpisodes:\n\n"
|
26
|
+
series.episodes.each do |e|
|
27
|
+
puts e.name + " (S#{e.season_num}E#{e.episode_num})"
|
28
|
+
end
|
29
|
+
|
30
|
+
# # Fetch series updates since given timestamp
|
31
|
+
# results = tvdb.find_updates_since(2.hours.ago)
|
32
|
+
# puts "\n\nUpdated series since 2 hours ago: #{results[:series].size} series\n\n"
|
33
|
+
# tvdb.each_updated_series(:since => 2.hours.ago) do |series|
|
34
|
+
# puts "#{series.id} - #{series.title}"
|
35
|
+
# end
|
36
|
+
#
|
37
|
+
# # Fetch episode udpates since given timestamp
|
38
|
+
# puts "Updated episodes since 2 hours ago: #{results[:episodes].size} episodes\n\n"
|
39
|
+
# tvdb.each_updated_episode(:since => 2.hours.ago) do |episode|
|
40
|
+
# puts "#{episode.id} - #{episode.name} - #{episode.seriesid}"
|
41
|
+
# end
|
data/lib/tvdbr/client.rb
ADDED
@@ -0,0 +1,123 @@
|
|
1
|
+
require 'httparty' unless defined?(HTTParty)
|
2
|
+
|
3
|
+
module Tvdbr
|
4
|
+
class Client
|
5
|
+
include HTTParty
|
6
|
+
format :xml
|
7
|
+
base_uri "http://www.thetvdb.com/api/"
|
8
|
+
|
9
|
+
# Creates an instance of the TVDB interface
|
10
|
+
# Tvdb.new('some_key')
|
11
|
+
def initialize(api_key)
|
12
|
+
@api_key = api_key
|
13
|
+
check_api_key!
|
14
|
+
end
|
15
|
+
|
16
|
+
# Fetches a series object based on the given attributes hash
|
17
|
+
# tvdb.fetch_series_from_data(:title => "Dexter", :kind => "TvShow", :starring => "xxxx, xxxx")
|
18
|
+
# => { "SeriesName" => "Dexter", ... } or nil
|
19
|
+
#
|
20
|
+
def fetch_series_from_data(options={})
|
21
|
+
return self.find_series_by_title(options[:title]) if options[:starring].nil?
|
22
|
+
series_results = self.find_all_series_by_title(options[:title])
|
23
|
+
expected_actors = options[:starring].split(",")
|
24
|
+
series_results.find { |series| series.actor_match?(expected_actors) }
|
25
|
+
end
|
26
|
+
|
27
|
+
# Yields the block for every updated series
|
28
|
+
# tvdb.each_updated_series(:since => 1.day.ago) { |s| Media.find_by_tvdb_id(s.id).title = s.title }
|
29
|
+
def each_updated_series(options={}, &block)
|
30
|
+
updates = self.find_updates_since(options[:since])
|
31
|
+
updates[:series].each do |series_id|
|
32
|
+
series = Series.new(self, self.find_series_by_id(series_id))
|
33
|
+
block.call(series)
|
34
|
+
end
|
35
|
+
end
|
36
|
+
|
37
|
+
# Yields the block for every updated episode
|
38
|
+
# tvdb.each_updated_episode(:since => 1.day.ago) { |s| Episode.find_by_tvdb_id(s.id).title = s.title }
|
39
|
+
def each_updated_episode(options={}, &block)
|
40
|
+
updates = self.find_updates_since(options[:since])
|
41
|
+
updates[:episodes].each do |episode_id|
|
42
|
+
episode = Episode.new(self, self.find_episode_by_id(episode_id))
|
43
|
+
block.call(episode)
|
44
|
+
end
|
45
|
+
end
|
46
|
+
|
47
|
+
# Returns all series matching the given title
|
48
|
+
# tvdb.find_all_series_by_title("Dexter")
|
49
|
+
# => [{ "SeriesName" => "Dexter", ... }, ...]
|
50
|
+
def find_all_series_by_title(title)
|
51
|
+
result = self.class.get("/GetSeries.php", :query => { :seriesname => title, :language => "en" })['Data']
|
52
|
+
return [] if result.blank? || result['Series'].blank?
|
53
|
+
result = result['Series'].is_a?(Array) ? result['Series'] : [result['Series']]
|
54
|
+
result.first(5).map { |s| Series.new(self, self.find_series_by_id(s['seriesid'])) }
|
55
|
+
end
|
56
|
+
|
57
|
+
# Returns the first series returned for a title
|
58
|
+
# tvdb.find_series_by_title("Dexter")
|
59
|
+
# => { "SeriesName" => "Dexter", ... }
|
60
|
+
#
|
61
|
+
def find_series_by_title(title)
|
62
|
+
self.find_all_series_by_title(title).first
|
63
|
+
end
|
64
|
+
|
65
|
+
# Returns series data for a given series_id
|
66
|
+
# tvdb.find_series_by_id(1234, :all => true)
|
67
|
+
# tvdb.find_series_by_id(1234, :dataset => true)
|
68
|
+
# => { "SeriesName" => "Dexter", ... }
|
69
|
+
def find_series_by_id(series_id, options={})
|
70
|
+
series_url = "/series/#{series_id}"
|
71
|
+
series_url << "/all" if options[:all]
|
72
|
+
result = self.get_with_key(series_url)['Data']
|
73
|
+
return result if options[:all]
|
74
|
+
return Series.new(self, result["Series"]) if options[:dataset]
|
75
|
+
result["Series"]
|
76
|
+
end
|
77
|
+
|
78
|
+
# Returns Episode data for a given episode id
|
79
|
+
# tvdb.find_episode_by_id(12345)
|
80
|
+
# => { "EpisodeName" => "..." }
|
81
|
+
def find_episode_by_id(episode_id, options={})
|
82
|
+
episode_url = "/episodes/#{episode_id}"
|
83
|
+
result = self.get_with_key(episode_url)['Data']
|
84
|
+
return Episode.new(self, result["Episode"]) if options[:dataset]
|
85
|
+
result["Episode"]
|
86
|
+
end
|
87
|
+
|
88
|
+
# Returns the list of TVDB mirror_urls
|
89
|
+
# => ["http://thetvdb.com", ...]
|
90
|
+
def mirror_urls
|
91
|
+
Array(self.get_with_key('/mirrors.xml')['Mirrors']['Mirror']['mirrorpath'])
|
92
|
+
end
|
93
|
+
|
94
|
+
# Returns a list of series and episode updates since given time
|
95
|
+
# tvdb.find_updates_since(1.day.ago)
|
96
|
+
# => { :series }
|
97
|
+
# {"Time"=>"1295300137", "Series"=>["70386", "70500", "70522", "70566", "70591", "70726", "70730", "70761", "70851", "70994", "71035", "71179", "71355",
|
98
|
+
#{ }"71383", "71394", "71470", "71489", "71493", "71635", "71649", "71663", "71753", "71788", "71991", "72023", "72073", "222571", "72158", "72164",
|
99
|
+
#{ }"72201", "72218", "72227", "72229", "72231", "72233", "72235", "72301", "72368", "72382", "72449", "72467", "72476", "72514", "72546", "153021", "72614", "72675", "72716", "72745", "82812", "72888", "72922", "72955", "72963", "80348", "73014", "73028", "73029", "73141", "222641", "73244", "73255", "207621", "73265", "73388", "73444", "73507", "73508", "73534", "73545", "73546", "73587", "73641", "73696", "73704", "73730", "73739", "83004", "73741", "73762", "73776", "73787", "73800", "73838", "73871", "73888", "73902", "73918", "73965", "74156", "74205", "74285", "74340", "74379", "164221", "74523", "74550", "74608", "74670", "74697", "74709", "74730", "74806", "74814", "74843", "74852", "74875", "74897", "74948", "74992", "219931", "75062", "75138", "75164", "75299", "75340", "75382", "75397", "75450", "75457", "75532", "75579", "75669", "75682", "75692", "75710", "124561", "75719", "75734", "75760", "75897", "75931", "75978", "82467", "76107", "76168", "76177", "76290", "180791", "76354", "76355", "76360", "76385", "163531", "76421", "76568", "76575", "76648", "76738", "76746", "76772", "76813", "76846", "76857", "76924", "77098", "77244", "77398", "77526", "77537", "77544", "77623", "219821", "77772", "77811", "126301", "77847", "77996", "78056", "222821", "78131", "78224", "85075", "78261", "78310", "78442", "78490", "78527", "78581", "78650", "78733", "78804", "84352", "78817", "78833", "78875", "78890", "78901", "209551", "78923", "78929", "78939", "78949", "79022", "79089", "79114", "79126", "80392", "163851", "79168", "79169", "79175", "72108", "79182", "109411", "79203", "79212", "79216", "107931", "79251", "79261", "79262", "82459", "79317", "79330", "82881", "79334", "79335", "79337", "79349", "79352", "79488", "79501", "79506", "79507", "79511", "79525", "79567", "79572", "79696", "79809", "79676", "80128", "222701", "79824", "79834", "79842", "85358", "79899", "79890", "79925", "80033", "80115", "80159", "80207", "80198", "80231", "80273", "80270", "80301", "80389", "80310", "80330", "80337", "80349", "80367", "80379", "80411", "80442", "80494", "102241", "80529", "80542", "80547", "80608", "80680", "80732", "80846", "80976", "80988", "80995", "81148", "81074", "81161", "222601", "81189", "93651", "81213", "81230", "81253", "221561", "221481", "81335", "81346", "81400", "81797", "81385", "81386", "81394", "222801", "222811", "222831", "81445", "81831", "81578", "95441", "81751", "81841", "81869", "81955", "81950", "82046", "85186", "82038", "82083", "82066", "82339", "82184", "82283", "82213", "82422", "82480", "82493", "82696", "82620", "82613", "138551", "82716", "82825", "103121", "83098", "83115", "83123", "83214", "83237", "83268", "83292", "83322", "83462", "83558", "83602", "83610", "83616", "83742", "109061", "83929", "84021", "84024", "84238", "84358", "84458", "84600", "84676", "84879", "84912", "84947", "85040", "85523", "85539", "222711", "222621", "222631", "222651", "222661", "88031", "91171", "91311", "94971", "92411", "93221", "93991", "213491", "94121", "94541", "94571", "94801", "94991", "95011", "95021", "95451", "95491", "95731", "95761", "97281", "97401", "97731", "98411", "100071", "164541", "101181", "102441", "109931", "112621", "113471", "114701", "114851", "114921", "116861", "117411", "118021", "118421", "222131", "119761", "120431", "123581", "124051", "127021", "127401", "128141", "128171", "129261", "131561", "132941", "133251", "133461", "133861", "134241", "134321", "134511", "136621", "163561", "163581", "137031", "138531", "140141", "142101", "142581", "142961", "145191", "145231", "145951", "146711", "146911", "148151", "149731", "154431", "158661", "158411", "159791", "160671", "161461", "161511", "163431", "163671", "164301", "164401", "164951", "164981", "183971", "165591", "165841", "165851", "166361", "166981", "168941", "171241", "174501", "172501", "173821", "174921", "175861", "176941", "178201", "180831", "181011", "182061", "182661", "188201", "186911", "187071", "190531", "220661", "219391", "192171", "192601", "193131", "194031", "194051", "194541", "199051", "194751", "195161", "195611", "196921", "197021", "197271", "200301", "201481", "201991", "203261", "203411", "206011", "207391", "207701", "208231", "208291", "209671", "211391", "212421", "212571", "213721", "214921", "216181", "217331", "217661", "217961", "218191", "218891", "218991", "219131", "219701", "219771", "220141", "220621", "220551", "220571", "221001", "221771", "221801", "222671", "222681", "222581", "222561", "222691", "222721", "222731", "222741", "222751", "222761", "222771", "222781", "222791"], "Episode"=>["3411341", "6112", "6113", "6114", "6115", "6116", "6117", "6118", "6119", "6120", "6121", "6122", "6123", "6124", "6125", "6126", "6127", "6128", "6131", "6132", "6133", "6134", "6135", "6136", "6137", "6138", "6139", "6140", "6141", "6142", "6143", "6144", "6145", "6146", "6147", "6148", "6149", "6150", "6151", "6152", "19486", "19487", "19488", "19489", "19490", "19491", "19492", "19493", "19494", "19495", "19496", "19497", "19498", "19499", "19500", "19501", "19502", "19503", "19504", "19505", "19506", "19507", "19508", "19509", "19510", "19511", "19512", "19513", "19514", "19515", "19516", "19517", "19518", "19519", "19520", "19521", "19522", "19523", "19524", "19525", "19526", "19527", "19528", "19529", "19530", "19531", "19532", "19533", "19534", "19535", "19536", "19537", "19538", "19539", "19540", "19541", "19542", "19543", "19544", "19545", "19546", "19547", "19548", "19549", "19550", "19551", "19552", "19553", "19554", "19555", "19556", "19557", "19558", "19559", "19560", "19561", "19562", "19563", "19564", "19565", "19566", "19567", "19568", "19569", "19570", "19571", "19572", "19573", "19574", "19575", "19576", "19577", "19578", "19579", "19580", "19581", "19582", "19583", "19584", "19585", "19586", "19587", "19588", "19589", "19590", "19591", "19592", "19593", "19594", "19595", "19596", "78538", "85905", "85906", "85907", "85908", "85909", "85910", "85911", "85912", "85913", "85914", "85916", "85917", "85918", "85919", "85920", "85921", "85922", "85923", "85924", "87055", "87056", "87057", "87058", "87059", "87060", "87061", "87062", "87063", "87064", "87065", "87066", "87067", "87068", "87069", "87070", "87071", "87072", "87073", "87074", "87075", "87076", "87077", "87078", "87081", "87082", "87083", "87084", "87085", "87086", "87087", "87088", "87089", "87090", "87091", "87092", "87093", "87094", "87095", "87096", "87097", "87098", "87099", "87100", "87101", "87102", "87103", "87104", "87130", "87132", "87133", "87134", "87135", "87136", "87137", "87138", "87139", "87140", "87141", "87142", "87143", "87144", "87145", "87146", "87147", "87148", "87150", "87151", "87152", "87153", "87154", "87155", "87156", "87157", "87158", "87159", "87160", "87161", "87162", "87163", "87164", "87165", "87167", "87168", "87169", "87170", "87172", "87173", "87175", "87176", "93515", "93516", "93517", "93518", "93519", "93520", "93521", "93522", "93523", "93524", "93525", "93526", "93527", "93528", "93529", "93530", "93531", "93532", "93533", "93534", "93535", "93536", "93537", "104003", "104004", "104005", "104099", "104100", "104101", "104102", "104103", "104104", "104105", "104106", "104107", "104108", "104109", "104111", "104112", "104113", "104114", "104115", "104116", "104117", "104118", "104119", "104120", "104121", "104122", "117690", "117691", "2275781", "131481", "131482", "131483", "131484", "131485", "131486", "131487", "131488", "131489", "131490", "131491", "131492", "131493", "131494", "131495", "131496", "147906", "147908", "151219", "159329", "159330", "165527", "165531", "165533", "165544", "165545", "165549", "165551", "165552", "165554", "165555", "165556", "165557", "165558", "165559", "165560", "165561", "165562", "165563", "165564", "165565", "175245", "175246", "175247", "175248", "175249", "175332", "175333", "175335", "175337", "175339", "175340", "200336", "200337", "200338", "200339", "200340", "200341", "200342", "383455", "383456", "3490541", "214197", "214198", "214200", "3088411", "214219", "789101", "228957", "228958", "228959", "228960", "228961", "228962", "228963", "228964", "228965", "228966", "228967", "228969", "228970", "228971", "228972", "228973", "228974", "228975", "228976", "228977", "228978", "228979", "228980", "228981", "228982", "228983", "228984", "228985", "228986", "228987", "228988", "228989", "228990", "228991", "228992", "228993", "228994", "228995", "228996", "228997", "228998", "228999", "229000", "229001", "229002", "229003", "229004", "229005", "229006", "229007", "229008", "229009", "229010", "229011", "229012", "229013", "229014", "229015", "229016", "229017", "229018", "229019", "229020", "229021", "229022", "229023", "229024", "229025", "229026", "229027", "229028", "229029", "229030", "229031", "229032", "229033", "229034", "229035", "229036", "229037", "229038", "229039", "229040", "229041", "229042", "229043", "229044", "229045", "229046", "229047", "229048", "229049", "229050", "229051", "229052", "229053", "229054", "229055", "229056", "229057", "229058", "229059", "229060", "229061", "229062", "2588861", "229065", "229066", "229067", "235252", "248787", "248788", "2226501", "277955", "277956", "277957", "277958", "277959", "277960", "277961", "277962", "277963", "277964", "277965", "285172", "285173", "285174", "285175", "297130", "297131", "297132", "297133", "297134", "2562291", "299427", "299428", "299429", "299430", "299431", "299432", "299433", "299600", "299602", "299603", "299604", "315500", "315501", "3406411", "304964", "304965", "304966", "304967", "304968", "324294", "315503", "315504", "315505", "315506", "315507", "315508", "315509", "315510", "2428991", "328515", "328516", "328517", "328518", "328519", "328520", "328521", "328522", "328523", "328524", "328611", "328612", "328613", "328614", "328615", "328616", "328617", "328618", "328619", "328620", "328621", "328622", "328623", "328624", "328625", "329990", "329991", "329992", "329993", "333410", "333608", "333609", "1543481", "1543491", "1543501", "339789", "339791", "339792", "339805", "339814", "348267", "348268", "348270", "349232", "349233", "349235", "349236", "349238", "353644", "353645", "353646", "353647", "353648", "392706", "392707", "392708", "369273", "369857", "371998", "377868", "377869", "392140", "392139", "391671", "383603", "385744", "386664", "386673", "388126", "388260", "403429", "403430", "403431", "405995", "412351", "412482", "3489821", "3489801", "413385", "413386", "413387", "413388", "438912", "440482", "440483", "446898", "3489811", "450261", "450271", "450281", "450291", "450301", "450311", "450321", "466681", "480481", "480471", "480461", "480491", "480501", "529461", "529481", "529491", "529531", "529541", "529571", "529591", "529601", "529611", "582801", "582811", "582831", "582841", "3469021", "641491", "641501", "641511", "641521", "641531", "641541", "641551", "641561", "641571", "641581", "641591", "641601", "641611", "695171", "705231", "705261", "705271", "705281", "705301", "705311", "3489791", "738671", "3490561", "3489931", "3489941", "3489951", "797321", "863841", "863851", "2502511", "2502521", "2502531", "918261", "918271", "2420141", "960411", "970951", "3488721", "1007721", "1122641", "1046501", "1046511", "1046521", "1046811", "1056501", "1069101", "1073491", "1073501", "1073511", "1079401", "1079411", "1129781", "1129801", "1129811", "1129831", "1133991", "1147201", "1147211", "1147231", "1156901", "1163221", "1164561", "1164571", "1177551", "1229221", "1229231", "1265811", "1265821", "1280491", "3488781", "3488771", "3488751", "3488761", "3488741", "1347941", "1347961", "1347971", "1347981", "1348101", "1348111", "1348121", "1348131", "1348141", "1348151", "1348161", "1348191", "1348201", "1348211", "1370101", "1370111", "3107001", "1475281", "1475291", "1475301", "1475271", "1475241", "1475251", "1475261", "1475311", "1475321", "1880471", "1880481", "1531721", "1531731", "1531761", "1531771", "1531781", "1531791", "1531801", "1531811", "1531821", "1531831", "1558861", "2944761", "1582181", "1601751", "2468781", "2468771", "1776961", "2459641", "2459651", "2459661", "2459671", "1824261", "1824331", "1824351", "1880511", "2457931", "2457901", "2457911", "2457921", "2457891", "1928631", "1928641", "1928651", "1928661", "1945411", "2012221", "2012231", "2105931", "2184331", "2184341", "2184351", "2202411", "2211571", "2226481", "2226491", "2226511", "2226521", "2226531", "2226561", "2226571", "2226581", "2226591", "2226601", "2226611", "2237101", "2237111", "2240091", "2241791", "2278921", "2305441", "2305461", "2305471", "2305481", "2314931", "2452271", "2366081", "2588931", "2613201", "2669741", "2669751", "2669761", "2669771", "2669781", "2669791", "2669801", "2669811", "2681211", "2698111", "2698131", "2724061", "2738291", "2738301", "2738311", "2750571", "2756371", "2796281", "2831181", "2831191", "2831201", "2831211", "2831221", "2831231", "2831241", "2831291", "2845721", "2831791", "2845751", "2845761", "2845771", "2875941", "2875951", "2875961", "2875971", "2875981", "2875991", "2876001", "2876011", "2876021", "2876031", "2876041", "2876051", "2876061", "2876071", "2876081", "2876091", "2876101", "2876111", "2876121", "2876131", "2876141", "2876151", "2876161", "2876171", "2902281", "2902291", "2902301", "2902311", "2902321", "2902331", "2902341", "2903101", "2905171", "2922911", "3489781", "2925151", "2925161", "2925171", "2925181", "2925191", "2925201", "2925211", "2925221", "2925231", "2925241", "2925251", "2925261", "2925271", "2925281", "2925291", "2925301", "2925411", "2932181", "2932141", "2932151", "2932161", "2932171", "2932191", "2932201", "2932211", "2932221", "2932231", "2932241", "2932251", "2932261", "2932271", "2932281", "2932291", "2932301", "2932311", "2932321", "2932331", "2943401", "2943411", "2943421", "2943431", "2943441", "2943451", "2943461", "2943471", "2961101", "2961661", "2969781", "2992001", "2996021", "3011261", "3011271", "3012721", "3018351", "3030521", "3054391", "3061861", "3061871", "3485271", "3071831", "3071881", "3071891", "3071901", "3071911", "3073051", "3073821", "3073831", "3073841", "3073851", "3073871", "3086011", "3097861", "3489921", "3489901", "3105081", "3107271", "3107281", "3109321", "3109331", "3109341", "3109351", "3109361", "3110601", "3111451", "3112871", "3125421", "3125431", "3135911", "3140901", "3140911", "3148661", "3148671", "3149091", "3150521", "3155731", "3155741", "3155751", "3162261", "3192901", "3198471", "3201471", "3204501", "3213821", "3215561", "3234881", "3235071"]}
|
100
|
+
def find_updates_since(time)
|
101
|
+
@_updated_results ||= {}
|
102
|
+
stamp = time.to_i # Get timestamp
|
103
|
+
result = @_updated_results[stamp] ||= self.class.get("/Updates.php?type=all&time=#{stamp}")['Items']
|
104
|
+
{ :series => result['Series'].map(&:to_i), :episodes => result['Episode'].map(&:to_i), :time => result['Time'] }
|
105
|
+
end
|
106
|
+
|
107
|
+
protected
|
108
|
+
|
109
|
+
# Returns the given xml as a hash appending the api_key to the url
|
110
|
+
# tvdb.get_with_key("/some/url", :query => { :foo => "bar" })
|
111
|
+
def get_with_key(*args)
|
112
|
+
args[0] = "/#{@api_key}/" + args[0]
|
113
|
+
self.class.get(*args)
|
114
|
+
end
|
115
|
+
|
116
|
+
# Checks if the api key works by retrieving mirrors
|
117
|
+
def check_api_key!
|
118
|
+
self.mirror_urls
|
119
|
+
rescue
|
120
|
+
raise "Please check your TVDB API Key!"
|
121
|
+
end
|
122
|
+
end
|
123
|
+
end
|
@@ -0,0 +1,79 @@
|
|
1
|
+
require 'Hashie' unless defined?(Hashie)
|
2
|
+
|
3
|
+
module Tvdbr
|
4
|
+
class DataSet < Hashie::Mash
|
5
|
+
attr_reader :parent
|
6
|
+
|
7
|
+
## INSTANCE METHODS ##
|
8
|
+
|
9
|
+
# Tvdb::DataSet.new(self, { :foo => "bar" })
|
10
|
+
def initialize(parent, *args)
|
11
|
+
@parent = parent
|
12
|
+
args[0] = normalize_keys(args[0]) if args[0].is_a?(Hash)
|
13
|
+
super(*args)
|
14
|
+
end
|
15
|
+
|
16
|
+
# Outputs: <#Tvdb::Series actors="..." added=nil added_by=nil>
|
17
|
+
def inspect
|
18
|
+
ret = "<##{self.class.to_s}"
|
19
|
+
self.keys.sort.each do |key|
|
20
|
+
ret << " #{key}=#{self[key].inspect}"
|
21
|
+
end
|
22
|
+
ret << ">"
|
23
|
+
ret
|
24
|
+
end
|
25
|
+
|
26
|
+
## CLASS METHODS ##
|
27
|
+
|
28
|
+
# Aliases the original propery to the new method name
|
29
|
+
# alias_property :old, :new
|
30
|
+
def self.alias_property(original, name)
|
31
|
+
define_method(name) { self.send(original) }
|
32
|
+
end
|
33
|
+
|
34
|
+
# Turns a property "a | b | c" => ['a', 'b', 'c']
|
35
|
+
# listify :lista, :listb
|
36
|
+
def self.listify(*attrs)
|
37
|
+
attrs.each do |a|
|
38
|
+
define_method(a) { self[a] ? self[a][1..-1].split("|").map(&:strip) : [] }
|
39
|
+
end
|
40
|
+
end
|
41
|
+
|
42
|
+
# Turns a property into a date object
|
43
|
+
# dateify :release_date
|
44
|
+
def self.dateify(*attrs)
|
45
|
+
attrs.each do |a|
|
46
|
+
define_method(a) { Time.parse(self[a]) if self[a] }
|
47
|
+
end
|
48
|
+
end
|
49
|
+
|
50
|
+
# Turns a relative image link to a full tvdb link url
|
51
|
+
# absolutize :file_name
|
52
|
+
def self.absolutize(*attrs)
|
53
|
+
attrs.each do |a|
|
54
|
+
define_method(a) { File.join("http://www.thetvdb.com/banners/", self[a]) if self[a] }
|
55
|
+
end
|
56
|
+
end
|
57
|
+
|
58
|
+
private
|
59
|
+
|
60
|
+
# Translates all keys to lowercase and to a symbol
|
61
|
+
# => [:foo => "bar", ...]
|
62
|
+
def normalize_keys(hash)
|
63
|
+
hash.inject({}) do |options, (key, value)|
|
64
|
+
options[(underscore(key) rescue key) || key] = value
|
65
|
+
options
|
66
|
+
end
|
67
|
+
end
|
68
|
+
|
69
|
+
def underscore(camel_cased_word)
|
70
|
+
word = camel_cased_word.to_s.dup
|
71
|
+
word.gsub!(/::/, '/')
|
72
|
+
word.gsub!(/([A-Z]+)([A-Z][a-z])/,'\1_\2')
|
73
|
+
word.gsub!(/([a-z\d])([A-Z])/,'\1_\2')
|
74
|
+
word.tr!("-", "_")
|
75
|
+
word.downcase!
|
76
|
+
word
|
77
|
+
end
|
78
|
+
end
|
79
|
+
end
|
@@ -0,0 +1,17 @@
|
|
1
|
+
module Tvdbr
|
2
|
+
# {:combined_episodenumber=>"14", :imdb_id=>nil, :episode_number=>"14", :absolute_number=>nil, :first_aired=>"2010-05-04",
|
3
|
+
# :dvd_episodenumber=>nil, :episode_name=>"The Candidate", :rating=>"7.9", :filename=>"episodes/73739/1685171.jpg", :director=>"Jack Bender",
|
4
|
+
# :seasonid=>"66871", :writer=>"|Elizabeth Sarnoff|Jim Galasso|", :dvd_chapter=>nil, :production_code=>nil, :combined_season=>"6", :season_number=>"6",
|
5
|
+
# :dvd_season=>nil, :language=>"en", :dvd_discid=>nil, :lastupdated=>"1277153526",
|
6
|
+
# :overview=>"...", :id=>"1685171", :ep_img_flag=>"2", :rating_count=>"187", :seriesid=>"73739", :guest_stars=>nil}
|
7
|
+
class Episode < DataSet
|
8
|
+
alias_property :episode_name, :name
|
9
|
+
alias_property :episode_number, :episode_num
|
10
|
+
alias_property :season_number, :season_num
|
11
|
+
alias_property :overview, :description
|
12
|
+
alias_property :first_aired, :original_air_date
|
13
|
+
dateify :first_aired
|
14
|
+
listify :writer
|
15
|
+
absolutize :filename
|
16
|
+
end
|
17
|
+
end
|
data/lib/tvdbr/series.rb
ADDED
@@ -0,0 +1,36 @@
|
|
1
|
+
module Tvdbr
|
2
|
+
# { "ContentRating"=>"TV-MA", "Status"=>"Continuing", "Airs_Time"=>"9:00 PM", "FirstAired"=>"2006-10-01", "Runtime"=>"60",
|
3
|
+
# "banner"=>"graphical/79349-g7.jpg", "poster"=>"posters/79349-2.jpg", "id"=>"79349", "Genre"=>"|Action and Adventure|Drama|",
|
4
|
+
# "Network"=>"Showtime", "Overview"=>"...", "addedBy"=>nil, "lastupdated"=>"1295047217", "IMDB_ID"=>"tt0773262",
|
5
|
+
# "Language"=>"en", "SeriesName"=>"Dexter", "Rating"=>"9.3", "fanart"=>"fanart/original/79349-16.jpg",
|
6
|
+
# "Actors"=>"|Michael C. Hall|Julie Benz|", "Airs_DayOfWeek"=>"Sunday",
|
7
|
+
# "zap2it_id"=>"SH859795", "RatingCount"=>"678", "SeriesID"=>"62683" }
|
8
|
+
class Series < DataSet
|
9
|
+
alias_property :series_name, :title
|
10
|
+
alias_property :overview, :synopsis
|
11
|
+
alias_property :actors, :starring
|
12
|
+
alias_property :genre, :categories
|
13
|
+
alias_property :first_aired, :release_date
|
14
|
+
listify :genre, :actors
|
15
|
+
dateify :first_aired
|
16
|
+
absolutize :fanart, :poster, :banner
|
17
|
+
|
18
|
+
def episodes
|
19
|
+
episode_data = self.parent.find_series_by_id(self.id, :all => true)
|
20
|
+
return [] unless episode_data && episode_data['Episode']
|
21
|
+
episode_data['Episode'].map { |e| Episode.new(self, e) if e && e.is_a?(Hash) }.compact
|
22
|
+
end
|
23
|
+
|
24
|
+
# Returns true if the series matches the given actors
|
25
|
+
# actors = ['x', 'y', 'z']
|
26
|
+
# series.actor_match?(actors) => true
|
27
|
+
def actor_match?(actors)
|
28
|
+
expected_actors = actors.map { |a| a.downcase.strip.gsub(/[\.\-\s\']/, '') }
|
29
|
+
normalized_actors = self.actors.map { |a| a.downcase.strip.gsub(/[\.\-\s\']/, '') }
|
30
|
+
# puts "1: #{self.inspect} - #{self.title} - #{normalized_actors.inspect} - #{expected_actors.inspect}"
|
31
|
+
# puts "2: " + (normalized_actors & expected_actors).inspect
|
32
|
+
normalized_actors.is_a?(Array) && expected_actors.is_a?(Array) &&
|
33
|
+
(normalized_actors & expected_actors).size > 1
|
34
|
+
end
|
35
|
+
end
|
36
|
+
end
|
data/lib/tvdbr.rb
ADDED
data/spec/.gitkeep
ADDED
File without changes
|
data/tvdbr.gemspec
ADDED
@@ -0,0 +1,23 @@
|
|
1
|
+
# -*- encoding: utf-8 -*-
|
2
|
+
$:.push File.expand_path("../lib", __FILE__)
|
3
|
+
require "tvdbr/version"
|
4
|
+
|
5
|
+
Gem::Specification.new do |s|
|
6
|
+
s.name = "tvdbr"
|
7
|
+
s.version = Tvdbr::VERSION
|
8
|
+
s.platform = Gem::Platform::RUBY
|
9
|
+
s.authors = ["Miso", "Nathan Esquenazi"]
|
10
|
+
s.email = ["nesquena@gmail.com"]
|
11
|
+
s.homepage = "https://github.com/bazaarlabs/tvdbr"
|
12
|
+
s.summary = %q{Use the TVDB API from Ruby}
|
13
|
+
s.description = %q{Utilize the TVDB API from Ruby to fetch shows, track updates to the tvdb and sync your media database}
|
14
|
+
s.rubyforge_project = "tvdbr"
|
15
|
+
s.files = `git ls-files`.split("\n")
|
16
|
+
s.test_files = `git ls-files -- {test,spec,features}/*`.split("\n")
|
17
|
+
s.executables = `git ls-files -- bin/*`.split("\n").map{ |f| File.basename(f) }
|
18
|
+
s.require_paths = ["lib"]
|
19
|
+
|
20
|
+
s.add_dependency "hashie"
|
21
|
+
s.add_dependency "httparty"
|
22
|
+
s.add_development_dependency "rake"
|
23
|
+
end
|
metadata
ADDED
@@ -0,0 +1,123 @@
|
|
1
|
+
--- !ruby/object:Gem::Specification
|
2
|
+
name: tvdbr
|
3
|
+
version: !ruby/object:Gem::Version
|
4
|
+
hash: 29
|
5
|
+
prerelease: false
|
6
|
+
segments:
|
7
|
+
- 0
|
8
|
+
- 0
|
9
|
+
- 1
|
10
|
+
version: 0.0.1
|
11
|
+
platform: ruby
|
12
|
+
authors:
|
13
|
+
- Miso
|
14
|
+
- Nathan Esquenazi
|
15
|
+
autorequire:
|
16
|
+
bindir: bin
|
17
|
+
cert_chain: []
|
18
|
+
|
19
|
+
date: 2011-01-17 00:00:00 -08:00
|
20
|
+
default_executable:
|
21
|
+
dependencies:
|
22
|
+
- !ruby/object:Gem::Dependency
|
23
|
+
name: hashie
|
24
|
+
prerelease: false
|
25
|
+
requirement: &id001 !ruby/object:Gem::Requirement
|
26
|
+
none: false
|
27
|
+
requirements:
|
28
|
+
- - ">="
|
29
|
+
- !ruby/object:Gem::Version
|
30
|
+
hash: 3
|
31
|
+
segments:
|
32
|
+
- 0
|
33
|
+
version: "0"
|
34
|
+
type: :runtime
|
35
|
+
version_requirements: *id001
|
36
|
+
- !ruby/object:Gem::Dependency
|
37
|
+
name: httparty
|
38
|
+
prerelease: false
|
39
|
+
requirement: &id002 !ruby/object:Gem::Requirement
|
40
|
+
none: false
|
41
|
+
requirements:
|
42
|
+
- - ">="
|
43
|
+
- !ruby/object:Gem::Version
|
44
|
+
hash: 3
|
45
|
+
segments:
|
46
|
+
- 0
|
47
|
+
version: "0"
|
48
|
+
type: :runtime
|
49
|
+
version_requirements: *id002
|
50
|
+
- !ruby/object:Gem::Dependency
|
51
|
+
name: rake
|
52
|
+
prerelease: false
|
53
|
+
requirement: &id003 !ruby/object:Gem::Requirement
|
54
|
+
none: false
|
55
|
+
requirements:
|
56
|
+
- - ">="
|
57
|
+
- !ruby/object:Gem::Version
|
58
|
+
hash: 3
|
59
|
+
segments:
|
60
|
+
- 0
|
61
|
+
version: "0"
|
62
|
+
type: :development
|
63
|
+
version_requirements: *id003
|
64
|
+
description: Utilize the TVDB API from Ruby to fetch shows, track updates to the tvdb and sync your media database
|
65
|
+
email:
|
66
|
+
- nesquena@gmail.com
|
67
|
+
executables: []
|
68
|
+
|
69
|
+
extensions: []
|
70
|
+
|
71
|
+
extra_rdoc_files: []
|
72
|
+
|
73
|
+
files:
|
74
|
+
- .gitignore
|
75
|
+
- Gemfile
|
76
|
+
- Gemfile.lock
|
77
|
+
- README
|
78
|
+
- Rakefile
|
79
|
+
- examples/demo.rb
|
80
|
+
- lib/tvdbr.rb
|
81
|
+
- lib/tvdbr/client.rb
|
82
|
+
- lib/tvdbr/data_set.rb
|
83
|
+
- lib/tvdbr/episode.rb
|
84
|
+
- lib/tvdbr/series.rb
|
85
|
+
- lib/tvdbr/version.rb
|
86
|
+
- spec/.gitkeep
|
87
|
+
- tvdbr.gemspec
|
88
|
+
has_rdoc: true
|
89
|
+
homepage: https://github.com/bazaarlabs/tvdbr
|
90
|
+
licenses: []
|
91
|
+
|
92
|
+
post_install_message:
|
93
|
+
rdoc_options: []
|
94
|
+
|
95
|
+
require_paths:
|
96
|
+
- lib
|
97
|
+
required_ruby_version: !ruby/object:Gem::Requirement
|
98
|
+
none: false
|
99
|
+
requirements:
|
100
|
+
- - ">="
|
101
|
+
- !ruby/object:Gem::Version
|
102
|
+
hash: 3
|
103
|
+
segments:
|
104
|
+
- 0
|
105
|
+
version: "0"
|
106
|
+
required_rubygems_version: !ruby/object:Gem::Requirement
|
107
|
+
none: false
|
108
|
+
requirements:
|
109
|
+
- - ">="
|
110
|
+
- !ruby/object:Gem::Version
|
111
|
+
hash: 3
|
112
|
+
segments:
|
113
|
+
- 0
|
114
|
+
version: "0"
|
115
|
+
requirements: []
|
116
|
+
|
117
|
+
rubyforge_project: tvdbr
|
118
|
+
rubygems_version: 1.3.7
|
119
|
+
signing_key:
|
120
|
+
specification_version: 3
|
121
|
+
summary: Use the TVDB API from Ruby
|
122
|
+
test_files:
|
123
|
+
- spec/.gitkeep
|