ttvdb 0.0.2 → 0.0.3
Sign up to get free protection for your applications and to get access to all the features.
- checksums.yaml +4 -4
- data/.travis.yml +5 -0
- data/README.md +22 -10
- data/Rakefile +7 -0
- data/bin/ttvdb +3 -0
- data/lib/ttvdb.rb +15 -2
- data/lib/ttvdb/cli.rb +7 -0
- data/lib/ttvdb/client.rb +25 -33
- data/lib/ttvdb/episode.rb +12 -15
- data/lib/ttvdb/match.rb +76 -0
- data/lib/ttvdb/parser.rb +99 -0
- data/lib/ttvdb/series.rb +11 -35
- data/lib/ttvdb/version.rb +1 -1
- data/spec/lib/ttvdb/client_spec.rb +40 -0
- data/spec/lib/ttvdb/episode_spec.rb +54 -0
- data/spec/lib/ttvdb/match_spec.rb +21 -0
- data/spec/lib/ttvdb/series_spec.rb +78 -0
- data/spec/lib/ttvdb_spec.rb +8 -0
- data/spec/res/episode_5_en.xml +33 -0
- data/spec/res/series_all_de.xml +2044 -0
- data/spec/res/series_all_en.xml +2044 -0
- data/spec/spec_helper.rb +2 -0
- data/ttvdb.gemspec +4 -1
- metadata +71 -5
checksums.yaml
CHANGED
@@ -1,7 +1,7 @@
|
|
1
1
|
---
|
2
2
|
SHA1:
|
3
|
-
metadata.gz:
|
4
|
-
data.tar.gz:
|
3
|
+
metadata.gz: 64f19e256a1cc6ee78fb68e18b8058f9cc452f8a
|
4
|
+
data.tar.gz: 002b47931f2199e77320ed238e997a68126b60fa
|
5
5
|
SHA512:
|
6
|
-
metadata.gz:
|
7
|
-
data.tar.gz:
|
6
|
+
metadata.gz: 1abc5a4db7d907c1b1cc84827c1da232121d594001a742ade3519a8fafc9cb1b71d5dc707fd30b782d16e0bb6826d8377fc0b8442625be76852441fc2f7886af
|
7
|
+
data.tar.gz: e3a4ead1586d3e21ede28cc75aedeb99f8f8dadf612e31847d9e9d664e2b7998283e5cc017deb261df85f21a698297d8497ee8ce0379e7c9c2c58e1fc6dd7e64
|
data/.travis.yml
ADDED
data/README.md
CHANGED
@@ -1,7 +1,14 @@
|
|
1
|
+
[![Build Status](https://travis-ci.org/lotherk/ttvdb.png?branch=master)](https://travis-ci.org/lotherk/ttvdb)
|
2
|
+
|
1
3
|
# TTVDB
|
2
4
|
|
3
5
|
This is another [TheTVDB.com](http://www.thetvdb.com) API library. The others out there didn't fit my needs (if they even worked).
|
4
6
|
|
7
|
+
Source code is available at [github](httsp://github.com/lotherk/ttvdb)
|
8
|
+
|
9
|
+
Documentation is available at [rubydoc.info](http://rubydoc.info/github/lotherk/ttvdb)
|
10
|
+
|
11
|
+
Gem is available at [rubygems.org](https://rubygems.org/gems/ttvdb)
|
5
12
|
|
6
13
|
## Installation
|
7
14
|
|
@@ -17,8 +24,19 @@ Or install it yourself as:
|
|
17
24
|
|
18
25
|
$ gem install ttvdb
|
19
26
|
|
27
|
+
From source:
|
28
|
+
|
29
|
+
$ git clone https://github.com/lotherk/ttvdb
|
30
|
+
$ cd ttvdb
|
31
|
+
$ rake build
|
32
|
+
$ gem install pkg/ttvdb-VERSION.gem
|
33
|
+
|
20
34
|
## Usage
|
21
35
|
|
36
|
+
### Using the CLI tools
|
37
|
+
|
38
|
+
|
39
|
+
### Writing Code
|
22
40
|
Require the gem
|
23
41
|
|
24
42
|
```ruby
|
@@ -31,23 +49,17 @@ Create a ```TTVDB::Client``` instance
|
|
31
49
|
client = TTVDB::Client.new(options={})
|
32
50
|
```
|
33
51
|
|
52
|
+
Where ```options``` can be:
|
53
|
+
|
34
54
|
| key | value | description
|
35
55
|
| --- | :---: | --- |
|
36
56
|
| ```:api_key``` | api key | Your TheTVDB API Key, *optional* |
|
37
57
|
| ```:api_url``` | http://www.thetvdb.com/api/ | API Url, *optional* |
|
38
58
|
| ```:language```|```en```,```de```,```fr```,... | The language code to use. Fallback is ```en```, *optional* |
|
39
59
|
|
40
|
-
Fetch series by name. Returns an array of series if result count is more than 1.
|
41
|
-
|
42
|
-
```ruby
|
43
|
-
series = client.get_series "Saber Rider"
|
44
|
-
```
|
45
|
-
|
46
|
-
Results to an array of 3 ```TTVDB::Series``` instances.
|
47
|
-
|
48
60
|
# Example
|
49
61
|
|
50
|
-
This is an example script that fetches a series by ARGV. if ARGV is an integer, it
|
62
|
+
This is an example script that fetches a series by ARGV. if ARGV is an integer, it will fetch it by its id otherwise by its name. It will then print a little overview about the series.
|
51
63
|
|
52
64
|
## Usage
|
53
65
|
```bash
|
@@ -93,7 +105,7 @@ See the ```examples/``` folder for a complete list of examples. I try to make th
|
|
93
105
|
|
94
106
|
## Contributing
|
95
107
|
|
96
|
-
1. Fork it ( http://github.com
|
108
|
+
1. Fork it ( http://github.com/lotherk/ttvdb/fork )
|
97
109
|
2. Create your feature branch (`git checkout -b my-new-feature`)
|
98
110
|
3. Commit your changes (`git commit -am 'Add some feature'`)
|
99
111
|
4. Push to the branch (`git push origin my-new-feature`)
|
data/Rakefile
CHANGED
data/bin/ttvdb
ADDED
data/lib/ttvdb.rb
CHANGED
@@ -2,11 +2,24 @@ require "rest-client"
|
|
2
2
|
require "logger"
|
3
3
|
require "xmlsimple"
|
4
4
|
require "ttvdb/version"
|
5
|
+
require "ttvdb/match"
|
5
6
|
require "ttvdb/client"
|
6
7
|
|
7
8
|
|
8
9
|
module TTVDB
|
9
|
-
def self.logger
|
10
|
-
@logger
|
10
|
+
def self.logger(output=STDOUT)
|
11
|
+
unless @logger
|
12
|
+
@logger = Logger.new(output)
|
13
|
+
@logger.formatter = proc { |severity, datetime, progname, msg|
|
14
|
+
kaller = caller[4]
|
15
|
+
file, ln, func = kaller.split(":")
|
16
|
+
_nil, func = func.split("`")
|
17
|
+
func.gsub!(/[<>']/, "")
|
18
|
+
file = File.basename(file)
|
19
|
+
"#{datetime} #{severity} #{file}:#{func}:#{ln}: #{msg}\n"
|
20
|
+
}
|
21
|
+
@logger.level = Logger::WARN
|
22
|
+
end
|
23
|
+
@logger
|
11
24
|
end
|
12
25
|
end
|
data/lib/ttvdb/cli.rb
ADDED
data/lib/ttvdb/client.rb
CHANGED
@@ -1,8 +1,9 @@
|
|
1
|
+
require 'ttvdb/parser'
|
1
2
|
require 'ttvdb/series'
|
2
3
|
require 'ttvdb/episode'
|
3
4
|
|
4
5
|
class TTVDB::Client
|
5
|
-
|
6
|
+
attr_accessor :language
|
6
7
|
|
7
8
|
def initialize(opts = {})
|
8
9
|
@opts = {
|
@@ -15,47 +16,38 @@ class TTVDB::Client
|
|
15
16
|
end
|
16
17
|
|
17
18
|
def get_series_by_id id
|
18
|
-
lookup = "series/#{id}/#{@
|
19
|
-
|
20
|
-
|
21
|
-
|
22
|
-
|
23
|
-
raise
|
24
|
-
end
|
19
|
+
lookup = "series/#{id}/#{@language}.xml"
|
20
|
+
hsh = XmlSimple.xml_in(client[lookup].get)
|
21
|
+
serie = TTVDB::Series.new(hsh["Series"][0])
|
22
|
+
serie.client = self
|
23
|
+
return serie
|
25
24
|
end
|
26
25
|
|
27
26
|
def get_series name
|
28
27
|
_client = RestClient::Resource.new("#{@opts[:api_url]}/GetSeries.php", :headers => { :params => { 'seriesname' => name, 'language' => @language }})
|
29
|
-
|
30
|
-
|
31
|
-
|
32
|
-
|
33
|
-
|
34
|
-
|
35
|
-
|
36
|
-
|
37
|
-
end
|
38
|
-
return series
|
39
|
-
rescue Exception => e
|
40
|
-
TTVDB.logger.error { "Error while fetching series: #{e.message}" }
|
41
|
-
raise
|
28
|
+
hsh = XmlSimple.xml_in(_client.get)
|
29
|
+
return [] unless hsh["Series"]
|
30
|
+
series = []
|
31
|
+
hsh["Series"].each do |s|
|
32
|
+
serie = TTVDB::Series.new(s)
|
33
|
+
next if serie.language != @language
|
34
|
+
serie.client = self
|
35
|
+
series << serie
|
42
36
|
end
|
37
|
+
return series
|
43
38
|
end
|
44
39
|
|
45
40
|
def get_episodes_by_series_id id
|
46
|
-
lookup = "series/#{id}/all/#{@
|
47
|
-
|
48
|
-
|
49
|
-
|
50
|
-
|
51
|
-
|
52
|
-
|
53
|
-
|
54
|
-
return episodes
|
55
|
-
rescue Exception => e
|
56
|
-
TTVDB.logger.error("get_episodes_by_series_id") { "Could not create hash from result: #{e.message}" }
|
57
|
-
raise
|
41
|
+
lookup = "series/#{id}/all/#{@language}.xml"
|
42
|
+
hsh = XmlSimple.xml_in(client[lookup].get)
|
43
|
+
return [] unless hsh["Episode"]
|
44
|
+
episodes = []
|
45
|
+
hsh["Episode"].each do |e|
|
46
|
+
episode = TTVDB::Episode.new(e)
|
47
|
+
episode.client = self
|
48
|
+
episodes << episode
|
58
49
|
end
|
50
|
+
episodes
|
59
51
|
end
|
60
52
|
|
61
53
|
private
|
data/lib/ttvdb/episode.rb
CHANGED
@@ -1,21 +1,18 @@
|
|
1
1
|
class TTVDB::Episode
|
2
|
-
|
3
|
-
:combined_number, :combined_season
|
2
|
+
include TTVDB::Parser
|
4
3
|
|
5
|
-
|
4
|
+
attr_reader :id, :combined_episodenumber, :combined_season,
|
5
|
+
:dvd_chapter, :dvd_discid, :dvd_episodenumber, :dvd_season,
|
6
|
+
:director, :ep_img_flag, :episode_name, :name, :episode_number,
|
7
|
+
:number, :first_aired, :guest_stars, :imdb_id, :overview,
|
8
|
+
:last_updated, :rating, :absolute_number, :season_number,
|
9
|
+
:season_id, :series_id
|
6
10
|
|
7
|
-
|
8
|
-
|
9
|
-
|
10
|
-
@
|
11
|
-
|
12
|
-
@overview = options["Overview"][0] rescue nil
|
13
|
-
@season_id = options["seasonid"][0].to_i rescue nil
|
14
|
-
@series_id = options["seriesid"][0].to_i rescue nil
|
15
|
-
@combined_number = options["Combined_episodenumber"][0].to_i rescue nil
|
16
|
-
@combined_season = options["Combined_season"][0].to_i rescue nil
|
17
|
-
@client = options[:client] rescue nil
|
18
|
-
@series = options[:series] rescue nil
|
11
|
+
attr_accessor :client, :series
|
12
|
+
|
13
|
+
def initialize(data)
|
14
|
+
@data = Hash[data.map { |k, v| [k.downcase, v] }]
|
15
|
+
parse
|
19
16
|
end
|
20
17
|
|
21
18
|
end
|
data/lib/ttvdb/match.rb
ADDED
@@ -0,0 +1,76 @@
|
|
1
|
+
require 'similar_text'
|
2
|
+
module TTVDB::Match
|
3
|
+
def match_episode filename, opts = {}
|
4
|
+
episode = nil
|
5
|
+
case opts[:filter]
|
6
|
+
when :sorted
|
7
|
+
episode = match_episode_sorted filename, opts
|
8
|
+
when :name
|
9
|
+
episode = match_episode_name filename, opts
|
10
|
+
when :regex
|
11
|
+
episode = match_episode_regex filename, opts
|
12
|
+
else
|
13
|
+
# try all
|
14
|
+
episode = match_episode_regex filename, opts rescue nil
|
15
|
+
episode ||= match_episode_name(filename, opts) rescue nil
|
16
|
+
episode ||= match_episode_regex(filename, opts) rescue nil
|
17
|
+
end
|
18
|
+
episode
|
19
|
+
end
|
20
|
+
|
21
|
+
private
|
22
|
+
def match_episode_sorted filename, opts = {}
|
23
|
+
enum = get_episode filename
|
24
|
+
return episodes[enum-1] rescue nil
|
25
|
+
end
|
26
|
+
|
27
|
+
def match_episode_name filename, opts = {}
|
28
|
+
results = []
|
29
|
+
episodes.each do |episode|
|
30
|
+
min = opts[:min]
|
31
|
+
min ||= 45
|
32
|
+
results << episode if episode.name.similar(filename) >= min
|
33
|
+
end
|
34
|
+
if results.count == 0
|
35
|
+
results = nil
|
36
|
+
elsif results.count == 1
|
37
|
+
results = results[0]
|
38
|
+
end
|
39
|
+
return results
|
40
|
+
end
|
41
|
+
|
42
|
+
def match_episode_regex filename, opts = {}
|
43
|
+
snum = get_season filename
|
44
|
+
enum = get_episode filename
|
45
|
+
seasons[snum][enum] rescue nil
|
46
|
+
end
|
47
|
+
|
48
|
+
def get_episode filename
|
49
|
+
filter_episode = [
|
50
|
+
/e(\d+)/i,
|
51
|
+
/(\d+)/i
|
52
|
+
]
|
53
|
+
filter_episode.each do |r|
|
54
|
+
m = filename.match(r)
|
55
|
+
if m
|
56
|
+
return m[1].to_i rescue nil
|
57
|
+
end
|
58
|
+
end
|
59
|
+
end
|
60
|
+
|
61
|
+
def get_season filename
|
62
|
+
filter_season = [
|
63
|
+
/s(\d+)/i,
|
64
|
+
/season.*(\d+)/i,
|
65
|
+
/staffel.*(\d+)/i,
|
66
|
+
/(\d+)x/i,
|
67
|
+
/(\d+)-/i
|
68
|
+
]
|
69
|
+
filter_season.each do |r|
|
70
|
+
m = filename.match(r)
|
71
|
+
if m
|
72
|
+
return m[1].to_i rescue nil
|
73
|
+
end
|
74
|
+
end
|
75
|
+
end
|
76
|
+
end
|
data/lib/ttvdb/parser.rb
ADDED
@@ -0,0 +1,99 @@
|
|
1
|
+
module TTVDB::Parser
|
2
|
+
attr_reader :id
|
3
|
+
|
4
|
+
MAP = {
|
5
|
+
"id" => { :map => true, :cast => :integer },
|
6
|
+
"combined_episodenumber" => { :map => true, :cast => :float },
|
7
|
+
"combined_season" => { :map => true, :cast => :integer },
|
8
|
+
"dvd_chapter" => { :map => true, :cast => :integer },
|
9
|
+
"dvd_discid" => { :map => true, :cast => :integer },
|
10
|
+
"dvd_episodenumber" => { :map => true, :cast => :float },
|
11
|
+
"dvd_season" => { :map => true, :cast => :integer },
|
12
|
+
"director" => { :map => true },
|
13
|
+
"epimgflag" => { :map => true, :cast => :integer },
|
14
|
+
"episodename" => { :map => :name },
|
15
|
+
"episodenumber" => { :map => :number, :cast => :integer },
|
16
|
+
"firstaired" => { :map => :first_aired, :cast => :time },
|
17
|
+
"gueststars" => { :map => :guest_stars, :cast => :array },
|
18
|
+
"imdb_id" => { :map => true },
|
19
|
+
"language" => { :map => true },
|
20
|
+
"overview" => { :map => true },
|
21
|
+
"productioncode" => { :map => :production_code },
|
22
|
+
"rating" => { :map => true, :cast => :float },
|
23
|
+
"ratingcount" => { :map => :rating_count, :cast => :integer },
|
24
|
+
"seasonnumber" => { :map => :season_number, :cast => :integer },
|
25
|
+
"writer" => { :map => true },
|
26
|
+
"absolute_number" => { :map => true, :cast => :integer },
|
27
|
+
"filename" => { :map => true },
|
28
|
+
"lastupdated" => { :map => :last_updated, :cast => :time_at },
|
29
|
+
"seasonid" => { :map => :season_id, :cast => :integer },
|
30
|
+
"seriesid" => { :map => :series_id, :cast => :integer },
|
31
|
+
"thumb_added" => { :map => true },
|
32
|
+
"thumb_height" => { :map => true, :cast => :integer },
|
33
|
+
"thumb_width" => { :map => true, :cast => :integer },
|
34
|
+
"actors" => { :map => true, :cast => :array },
|
35
|
+
"airs_dayofweek" => { :map => true },
|
36
|
+
"airs_time" => { :map => true },
|
37
|
+
"contentrating" => { :map => :content_rating, :cast => :float },
|
38
|
+
"genre" => { :map => true, :cast => :array },
|
39
|
+
"network" => { :map => true },
|
40
|
+
"networkid" => { :map => :network_id },
|
41
|
+
"runtime" => { :map => true, :cast => :integer },
|
42
|
+
"seriesname" => { :map => :name },
|
43
|
+
"status" => { :map => true },
|
44
|
+
"added" => { :map => true },
|
45
|
+
"added_by" => { :map => true },
|
46
|
+
"banner" => { :map => true },
|
47
|
+
"fanart" => { :map => true },
|
48
|
+
"poster" => { :map => true },
|
49
|
+
"zap2it_id" => { :map => true }
|
50
|
+
}
|
51
|
+
|
52
|
+
def parse
|
53
|
+
raise "no data to parse" unless @data
|
54
|
+
@data.each do |k, v|
|
55
|
+
k = k.downcase
|
56
|
+
v = v[0]
|
57
|
+
unless MAP.include? k
|
58
|
+
next
|
59
|
+
end
|
60
|
+
var = nil
|
61
|
+
if MAP[k][:map].is_a? TrueClass
|
62
|
+
var = k.to_sym
|
63
|
+
else
|
64
|
+
var = MAP[k][:map].to_sym
|
65
|
+
end
|
66
|
+
|
67
|
+
unless respond_to? var
|
68
|
+
next
|
69
|
+
end
|
70
|
+
k, v = map k, v
|
71
|
+
instance_variable_set("@#{k}", v)
|
72
|
+
end
|
73
|
+
@data = nil
|
74
|
+
end
|
75
|
+
|
76
|
+
private
|
77
|
+
def map k, v
|
78
|
+
case MAP[k][:cast]
|
79
|
+
when :integer
|
80
|
+
v = v.to_i rescue v
|
81
|
+
when :float
|
82
|
+
v = v.to_f rescue v
|
83
|
+
when :array
|
84
|
+
v = v.split("|").compact rescue v
|
85
|
+
when :time_at
|
86
|
+
v = Time.at(v.to_i) rescue v
|
87
|
+
when :time
|
88
|
+
v = Time.parse(v) rescue v
|
89
|
+
else
|
90
|
+
v = v
|
91
|
+
end
|
92
|
+
if MAP[k][:map].is_a? TrueClass
|
93
|
+
k = k.to_sym
|
94
|
+
else
|
95
|
+
k = MAP[k][:map].to_sym
|
96
|
+
end
|
97
|
+
[k, v]
|
98
|
+
end
|
99
|
+
end
|
data/lib/ttvdb/series.rb
CHANGED
@@ -1,49 +1,25 @@
|
|
1
1
|
class TTVDB::Series
|
2
|
+
include TTVDB::Parser
|
3
|
+
include TTVDB::Match
|
4
|
+
|
2
5
|
attr_reader :id, :actors, :airs_dayofweek, :airs_time,
|
3
6
|
:content_rating, :first_aired, :genre, :imdb_id, :language,
|
4
7
|
:network, :network_id, :overview, :rating, :rating_count,
|
5
8
|
:runtime, :series_id, :series_name, :status, :added, :added_by,
|
6
|
-
:banner, :fanart, :last_updated, :poster, :zap2it_id, :
|
9
|
+
:banner, :fanart, :last_updated, :poster, :zap2it_id, :seasons,
|
7
10
|
:name
|
8
11
|
|
9
|
-
|
12
|
+
attr_accessor :client
|
10
13
|
|
11
|
-
def initialize(data
|
12
|
-
|
13
|
-
|
14
|
-
@actors = options["Actors"][0].split("|").compact rescue []
|
15
|
-
@airs_dayofweek = options["Airs_DayOfWeek"][0] rescue nil
|
16
|
-
@airs_time = options["Airs_Time"][0] rescue nil
|
17
|
-
@content_rating = options["ContentRating"][0].to_f rescue 0
|
18
|
-
@first_aired = Time.parse(options["FirstAired"][0]) rescue nil
|
19
|
-
@genre = options["Genre"][0].split("|").compact rescue []
|
20
|
-
@imdb_id = options["IMDB_ID"][0].to_i rescue nil
|
21
|
-
@language = options["language"][0] rescue nil
|
22
|
-
@language ||= options["Language"][0] rescue "en"
|
23
|
-
@network = options["Network"][0] rescue nil
|
24
|
-
@network_id = options["NetworkID"][0] rescue nil
|
25
|
-
@overview = options["Overview"][0] rescue nil
|
26
|
-
@rating = options["Rating"][0].to_f rescue 0
|
27
|
-
@rating_count = options["RatingCount"][0] rescue 0
|
28
|
-
@runtime = options["Runtime"][0].to_i rescue nil
|
29
|
-
@runtime ||= options["runtime"][0].to_i rescue 0
|
30
|
-
@series_id = options["SeriesID"][0].to_i rescue nil
|
31
|
-
@series_name = options["SeriesName"][0] rescue nil
|
32
|
-
@name = @series_name
|
33
|
-
@status = options["Status"][0].downcase rescue nil
|
34
|
-
@added = options["added"][0] rescue nil
|
35
|
-
@added_by = options["addedBy"][0] rescue nil
|
36
|
-
@banner = options["banner"][0] rescue nil
|
37
|
-
@fanart = options["fanart"][0] rescue nil
|
38
|
-
@last_updated = Time.at(options["lastupdated"][0].to_i) rescue nil
|
39
|
-
@poster = options["poster"][0] rescue nil
|
40
|
-
@zap2it_id = options["zap2it_id"][0] rescue nil
|
41
|
-
@client = options[:client] rescue nil
|
14
|
+
def initialize(data)
|
15
|
+
@data = Hash[data.map { |k, v| [k.downcase, v] }]
|
16
|
+
parse
|
42
17
|
@seasons = {}
|
43
|
-
TTVDB.logger.debug { "Series language: #{@language}" }
|
44
|
-
fetch_episodes
|
45
18
|
end
|
46
19
|
|
20
|
+
def episodes
|
21
|
+
@episodes ||= fetch_episodes
|
22
|
+
end
|
47
23
|
|
48
24
|
private
|
49
25
|
def fetch_episodes
|