tmdb_client 1.0.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.
- checksums.yaml +7 -0
- data/CHANGELOG.md +63 -0
- data/LICENSE +21 -0
- data/README.md +305 -0
- data/lib/tmdb/certification.rb +24 -0
- data/lib/tmdb/change.rb +21 -0
- data/lib/tmdb/client.rb +164 -0
- data/lib/tmdb/collection.rb +27 -0
- data/lib/tmdb/company.rb +23 -0
- data/lib/tmdb/config.rb +71 -0
- data/lib/tmdb/configuration.rb +36 -0
- data/lib/tmdb/credit.rb +11 -0
- data/lib/tmdb/discover.rb +15 -0
- data/lib/tmdb/errors.rb +83 -0
- data/lib/tmdb/find.rb +44 -0
- data/lib/tmdb/genre.rb +21 -0
- data/lib/tmdb/job.rb +13 -0
- data/lib/tmdb/keyword.rb +15 -0
- data/lib/tmdb/movie.rb +117 -0
- data/lib/tmdb/network.rb +19 -0
- data/lib/tmdb/object.rb +138 -0
- data/lib/tmdb/page.rb +140 -0
- data/lib/tmdb/person.rb +55 -0
- data/lib/tmdb/resource.rb +90 -0
- data/lib/tmdb/review.rb +11 -0
- data/lib/tmdb/search.rb +43 -0
- data/lib/tmdb/tv/episode.rb +62 -0
- data/lib/tmdb/tv/season.rb +54 -0
- data/lib/tmdb/tv.rb +108 -0
- data/lib/tmdb/version.rb +5 -0
- data/lib/tmdb_client.rb +72 -0
- metadata +105 -0
data/lib/tmdb/page.rb
ADDED
|
@@ -0,0 +1,140 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module TMDb
|
|
4
|
+
# One page of a paginated TMDb response.
|
|
5
|
+
#
|
|
6
|
+
# Every paginated endpoint in this gem returns a Page, where the old gem
|
|
7
|
+
# returned a different envelope class per endpoint (`Tmdb::Result` for
|
|
8
|
+
# searches, `Tmdb::Discover` for discover, `Tmdb::Movie` for `Movie.popular`)
|
|
9
|
+
# and left walking the pages entirely to the caller.
|
|
10
|
+
#
|
|
11
|
+
# page = TMDb::Search.movie('blade runner')
|
|
12
|
+
# page.results # => [TMDb::Object, ...]
|
|
13
|
+
# page.total_pages # => 3
|
|
14
|
+
# page.map(&:title) # Enumerable over the results
|
|
15
|
+
#
|
|
16
|
+
# page.each_page { |p| ... } # lazily fetches page 2, 3, ...
|
|
17
|
+
# page.auto_paginate { |movie| } # lazily walks every result
|
|
18
|
+
#
|
|
19
|
+
# Envelope keys that are not part of the pagination contract (`dates` on
|
|
20
|
+
# `/movie/now_playing`, `id` on `/movie/{id}/changes`) stay readable through
|
|
21
|
+
# `meta`, and directly on the page itself.
|
|
22
|
+
class Page
|
|
23
|
+
include Enumerable
|
|
24
|
+
|
|
25
|
+
ENVELOPE_KEYS = %i[page total_pages total_results results].freeze
|
|
26
|
+
|
|
27
|
+
attr_reader :results, :page, :total_pages, :total_results, :meta
|
|
28
|
+
|
|
29
|
+
def initialize(page: nil, total_pages: nil, total_results: nil, results: [], meta: {}, &fetcher)
|
|
30
|
+
@results = results.freeze
|
|
31
|
+
@page = (page || 1).to_i
|
|
32
|
+
@total_pages = (total_pages || 1).to_i
|
|
33
|
+
@total_results = (total_results || @results.size).to_i
|
|
34
|
+
@meta = Object.new(meta)
|
|
35
|
+
@fetcher = fetcher
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def each(&block)
|
|
39
|
+
return enum_for(:each) unless block
|
|
40
|
+
|
|
41
|
+
@results.each(&block)
|
|
42
|
+
self
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def size
|
|
46
|
+
@results.size
|
|
47
|
+
end
|
|
48
|
+
alias length size
|
|
49
|
+
|
|
50
|
+
def empty?
|
|
51
|
+
@results.empty?
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def first_page?
|
|
55
|
+
page <= 1
|
|
56
|
+
end
|
|
57
|
+
|
|
58
|
+
def last_page?
|
|
59
|
+
page >= total_pages
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
def next_page
|
|
63
|
+
last_page? ? nil : page + 1
|
|
64
|
+
end
|
|
65
|
+
|
|
66
|
+
def previous_page
|
|
67
|
+
first_page? ? nil : page - 1
|
|
68
|
+
end
|
|
69
|
+
|
|
70
|
+
# Fetches an arbitrary page of the same query. Raises rather than lying when
|
|
71
|
+
# this page was built by hand (a test double, say) and has no query behind it.
|
|
72
|
+
def fetch_page(number)
|
|
73
|
+
raise Error, 'This page was not built from a request, so it cannot fetch another' unless @fetcher
|
|
74
|
+
|
|
75
|
+
@fetcher.call(number)
|
|
76
|
+
end
|
|
77
|
+
|
|
78
|
+
def fetch_next_page
|
|
79
|
+
next_page && fetch_page(next_page)
|
|
80
|
+
end
|
|
81
|
+
|
|
82
|
+
# Yields this page, then each following one, fetching as it goes. TMDb caps
|
|
83
|
+
# pagination at 500 pages; walking to the end of a large result set is a lot
|
|
84
|
+
# of requests, so this stays explicit rather than happening behind `each`.
|
|
85
|
+
def each_page
|
|
86
|
+
return enum_for(:each_page) unless block_given?
|
|
87
|
+
|
|
88
|
+
current = self
|
|
89
|
+
|
|
90
|
+
loop do
|
|
91
|
+
yield current
|
|
92
|
+
break if current.last_page?
|
|
93
|
+
|
|
94
|
+
current = current.fetch_next_page
|
|
95
|
+
break if current.nil?
|
|
96
|
+
end
|
|
97
|
+
|
|
98
|
+
self
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
# Every result from this page on, across page boundaries.
|
|
102
|
+
def auto_paginate(&block)
|
|
103
|
+
return enum_for(:auto_paginate) unless block
|
|
104
|
+
|
|
105
|
+
each_page { |current| current.results.each(&block) }
|
|
106
|
+
end
|
|
107
|
+
|
|
108
|
+
def to_h
|
|
109
|
+
meta.to_h.merge(
|
|
110
|
+
page: page, total_pages: total_pages, total_results: total_results, results: results.map(&:to_h)
|
|
111
|
+
)
|
|
112
|
+
end
|
|
113
|
+
|
|
114
|
+
def ==(other)
|
|
115
|
+
other.is_a?(Page) && to_h == other.to_h
|
|
116
|
+
end
|
|
117
|
+
alias eql? ==
|
|
118
|
+
|
|
119
|
+
def hash
|
|
120
|
+
[self.class, to_h].hash
|
|
121
|
+
end
|
|
122
|
+
|
|
123
|
+
def inspect
|
|
124
|
+
"#<TMDb::Page page=#{page}/#{total_pages} total_results=#{total_results} results=#{size}>"
|
|
125
|
+
end
|
|
126
|
+
|
|
127
|
+
private
|
|
128
|
+
|
|
129
|
+
def method_missing(name, *args, &block)
|
|
130
|
+
return super unless args.empty? && block.nil?
|
|
131
|
+
return super unless meta.respond_to?(name)
|
|
132
|
+
|
|
133
|
+
meta.public_send(name)
|
|
134
|
+
end
|
|
135
|
+
|
|
136
|
+
def respond_to_missing?(name, include_private = false)
|
|
137
|
+
meta.respond_to?(name, include_private) || super
|
|
138
|
+
end
|
|
139
|
+
end
|
|
140
|
+
end
|
data/lib/tmdb/person.rb
ADDED
|
@@ -0,0 +1,55 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module TMDb
|
|
4
|
+
class Person < Resource
|
|
5
|
+
def detail(id, filters = {})
|
|
6
|
+
object("/person/#{id}", filters)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def movie_credits(id, filters = {})
|
|
10
|
+
object("/person/#{id}/movie_credits", filters)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def tv_credits(id, filters = {})
|
|
14
|
+
object("/person/#{id}/tv_credits", filters)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def combined_credits(id, filters = {})
|
|
18
|
+
object("/person/#{id}/combined_credits", filters)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def external_ids(id, filters = {})
|
|
22
|
+
object("/person/#{id}/external_ids", filters)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def images(id, filters = {})
|
|
26
|
+
object("/person/#{id}/images", filters)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def profiles(id, filters = {})
|
|
30
|
+
list("/person/#{id}/images", :profiles, filters)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def tagged_images(id, filters = {})
|
|
34
|
+
page("/person/#{id}/tagged_images", filters)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def translations(id, filters = {})
|
|
38
|
+
list("/person/#{id}/translations", :translations, filters)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def changes(id, filters = {})
|
|
42
|
+
list("/person/#{id}/changes", :changes, filters)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def popular(filters = {})
|
|
46
|
+
page('/person/popular', filters)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def latest(filters = {})
|
|
50
|
+
object('/person/latest', filters)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
expose_class_methods
|
|
54
|
+
end
|
|
55
|
+
end
|
|
@@ -0,0 +1,90 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module TMDb
|
|
4
|
+
# Base for the endpoint classes.
|
|
5
|
+
#
|
|
6
|
+
# Each subclass is a thin map from a method to a TMDb path; the wrapping is
|
|
7
|
+
# uniform, so a subclass only ever says which path, which JSON key, and
|
|
8
|
+
# whether the answer is one object, a list, or a page.
|
|
9
|
+
#
|
|
10
|
+
# Every public instance method is also exposed as a class method backed by the
|
|
11
|
+
# default client, so both of these work:
|
|
12
|
+
#
|
|
13
|
+
# TMDb::Movie.detail(550) # default client
|
|
14
|
+
# TMDb::Movie.new(other_client).detail(550) # an explicit one
|
|
15
|
+
#
|
|
16
|
+
# Every method takes an optional trailing `filters` Hash, merged into the
|
|
17
|
+
# query string. That is how `language:`, `append_to_response:`, `page:` and
|
|
18
|
+
# the rest are passed, and a filter always beats the client's own default.
|
|
19
|
+
class Resource
|
|
20
|
+
attr_reader :client
|
|
21
|
+
|
|
22
|
+
def initialize(client = nil)
|
|
23
|
+
@client = client || TMDb.client
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
class << self
|
|
27
|
+
private
|
|
28
|
+
|
|
29
|
+
def expose_class_methods
|
|
30
|
+
public_instance_methods(false).each do |name|
|
|
31
|
+
singleton_class.define_method(name) do |*args, **kwargs, &block|
|
|
32
|
+
new.public_send(name, *args, **kwargs, &block)
|
|
33
|
+
end
|
|
34
|
+
end
|
|
35
|
+
end
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
private
|
|
39
|
+
|
|
40
|
+
def fetch(path, filters = {})
|
|
41
|
+
client.get(path, filters)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
# One object.
|
|
45
|
+
def object(path, filters = {})
|
|
46
|
+
Object.new(fetch(path, filters))
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
# A bare Array living under `key` in the response body.
|
|
50
|
+
def list(path, key, filters = {})
|
|
51
|
+
objects(fetch(path, filters)[key])
|
|
52
|
+
end
|
|
53
|
+
|
|
54
|
+
def objects(entries)
|
|
55
|
+
case entries
|
|
56
|
+
when ::Array then entries.map { |entry| Object.new(entry) }
|
|
57
|
+
when nil then []
|
|
58
|
+
else [Object.new(entries)]
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
|
|
62
|
+
# A paginated envelope. The returned Page can fetch its own following pages,
|
|
63
|
+
# reusing these filters with the page number swapped out.
|
|
64
|
+
def page(path, filters = {}, key: :results)
|
|
65
|
+
filters = normalize(filters)
|
|
66
|
+
fetcher = nil
|
|
67
|
+
fetcher = lambda do |number|
|
|
68
|
+
body = fetch(path, number.nil? ? filters : filters.merge(page: number))
|
|
69
|
+
build_page(body, key, &fetcher)
|
|
70
|
+
end
|
|
71
|
+
|
|
72
|
+
fetcher.call(nil)
|
|
73
|
+
end
|
|
74
|
+
|
|
75
|
+
def build_page(body, key = :results, &)
|
|
76
|
+
Page.new(
|
|
77
|
+
page: body[:page],
|
|
78
|
+
total_pages: body[:total_pages],
|
|
79
|
+
total_results: body[:total_results],
|
|
80
|
+
results: objects(body[key]),
|
|
81
|
+
meta: body.except(*Page::ENVELOPE_KEYS, key),
|
|
82
|
+
&
|
|
83
|
+
)
|
|
84
|
+
end
|
|
85
|
+
|
|
86
|
+
def normalize(filters)
|
|
87
|
+
(filters || {}).to_h.transform_keys(&:to_sym)
|
|
88
|
+
end
|
|
89
|
+
end
|
|
90
|
+
end
|
data/lib/tmdb/review.rb
ADDED
data/lib/tmdb/search.rb
ADDED
|
@@ -0,0 +1,43 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module TMDb
|
|
4
|
+
class Search < Resource
|
|
5
|
+
def movie(query, filters = {})
|
|
6
|
+
search('/search/movie', query, filters)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def tv(query, filters = {})
|
|
10
|
+
search('/search/tv', query, filters)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def person(query, filters = {})
|
|
14
|
+
search('/search/person', query, filters)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def multi(query, filters = {})
|
|
18
|
+
search('/search/multi', query, filters)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def company(query, filters = {})
|
|
22
|
+
search('/search/company', query, filters)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def collection(query, filters = {})
|
|
26
|
+
search('/search/collection', query, filters)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def keyword(query, filters = {})
|
|
30
|
+
search('/search/keyword', query, filters)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
expose_class_methods
|
|
34
|
+
|
|
35
|
+
private
|
|
36
|
+
|
|
37
|
+
# themoviedb-api merged the query into the caller's own filters hash with
|
|
38
|
+
# `merge!`, quietly mutating it. This does not.
|
|
39
|
+
def search(path, query, filters)
|
|
40
|
+
page(path, normalize(filters).merge(query: query))
|
|
41
|
+
end
|
|
42
|
+
end
|
|
43
|
+
end
|
|
@@ -0,0 +1,62 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module TMDb
|
|
4
|
+
class TV
|
|
5
|
+
class Episode < Resource
|
|
6
|
+
def detail(id, season_number, episode_number, filters = {})
|
|
7
|
+
object(path(id, season_number, episode_number), filters)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def credits(id, season_number, episode_number, filters = {})
|
|
11
|
+
object("#{path(id, season_number, episode_number)}/credits", filters)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def cast(id, season_number, episode_number, filters = {})
|
|
15
|
+
list("#{path(id, season_number, episode_number)}/credits", :cast, filters)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def crew(id, season_number, episode_number, filters = {})
|
|
19
|
+
list("#{path(id, season_number, episode_number)}/credits", :crew, filters)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def guest_stars(id, season_number, episode_number, filters = {})
|
|
23
|
+
list("#{path(id, season_number, episode_number)}/credits", :guest_stars, filters)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def external_ids(id, season_number, episode_number, filters = {})
|
|
27
|
+
object("#{path(id, season_number, episode_number)}/external_ids", filters)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def images(id, season_number, episode_number, filters = {})
|
|
31
|
+
object("#{path(id, season_number, episode_number)}/images", filters)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
# An episode's images are stills, so this is the one the API actually has.
|
|
35
|
+
def stills(id, season_number, episode_number, filters = {})
|
|
36
|
+
list("#{path(id, season_number, episode_number)}/images", :stills, filters)
|
|
37
|
+
end
|
|
38
|
+
alias posters stills
|
|
39
|
+
|
|
40
|
+
def videos(id, season_number, episode_number, filters = {})
|
|
41
|
+
list("#{path(id, season_number, episode_number)}/videos", :results, filters)
|
|
42
|
+
end
|
|
43
|
+
|
|
44
|
+
def translations(id, season_number, episode_number, filters = {})
|
|
45
|
+
list("#{path(id, season_number, episode_number)}/translations", :translations, filters)
|
|
46
|
+
end
|
|
47
|
+
|
|
48
|
+
# Addressed by the episode's own TMDb id.
|
|
49
|
+
def changes(episode_id, filters = {})
|
|
50
|
+
list("/tv/episode/#{episode_id}/changes", :changes, filters)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
expose_class_methods
|
|
54
|
+
|
|
55
|
+
private
|
|
56
|
+
|
|
57
|
+
def path(id, season_number, episode_number)
|
|
58
|
+
"/tv/#{id}/season/#{season_number}/episode/#{episode_number}"
|
|
59
|
+
end
|
|
60
|
+
end
|
|
61
|
+
end
|
|
62
|
+
end
|
|
@@ -0,0 +1,54 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module TMDb
|
|
4
|
+
class TV
|
|
5
|
+
class Season < Resource
|
|
6
|
+
def detail(id, season_number, filters = {})
|
|
7
|
+
object("/tv/#{id}/season/#{season_number}", filters)
|
|
8
|
+
end
|
|
9
|
+
|
|
10
|
+
def credits(id, season_number, filters = {})
|
|
11
|
+
object("/tv/#{id}/season/#{season_number}/credits", filters)
|
|
12
|
+
end
|
|
13
|
+
|
|
14
|
+
def cast(id, season_number, filters = {})
|
|
15
|
+
list("/tv/#{id}/season/#{season_number}/credits", :cast, filters)
|
|
16
|
+
end
|
|
17
|
+
|
|
18
|
+
def crew(id, season_number, filters = {})
|
|
19
|
+
list("/tv/#{id}/season/#{season_number}/credits", :crew, filters)
|
|
20
|
+
end
|
|
21
|
+
|
|
22
|
+
def aggregate_credits(id, season_number, filters = {})
|
|
23
|
+
object("/tv/#{id}/season/#{season_number}/aggregate_credits", filters)
|
|
24
|
+
end
|
|
25
|
+
|
|
26
|
+
def external_ids(id, season_number, filters = {})
|
|
27
|
+
object("/tv/#{id}/season/#{season_number}/external_ids", filters)
|
|
28
|
+
end
|
|
29
|
+
|
|
30
|
+
def images(id, season_number, filters = {})
|
|
31
|
+
object("/tv/#{id}/season/#{season_number}/images", filters)
|
|
32
|
+
end
|
|
33
|
+
|
|
34
|
+
def posters(id, season_number, filters = {})
|
|
35
|
+
list("/tv/#{id}/season/#{season_number}/images", :posters, filters)
|
|
36
|
+
end
|
|
37
|
+
|
|
38
|
+
def videos(id, season_number, filters = {})
|
|
39
|
+
list("/tv/#{id}/season/#{season_number}/videos", :results, filters)
|
|
40
|
+
end
|
|
41
|
+
|
|
42
|
+
def translations(id, season_number, filters = {})
|
|
43
|
+
list("/tv/#{id}/season/#{season_number}/translations", :translations, filters)
|
|
44
|
+
end
|
|
45
|
+
|
|
46
|
+
# Addressed by the season's own TMDb id, not by series + season number.
|
|
47
|
+
def changes(season_id, filters = {})
|
|
48
|
+
list("/tv/season/#{season_id}/changes", :changes, filters)
|
|
49
|
+
end
|
|
50
|
+
|
|
51
|
+
expose_class_methods
|
|
52
|
+
end
|
|
53
|
+
end
|
|
54
|
+
end
|
data/lib/tmdb/tv.rb
ADDED
|
@@ -0,0 +1,108 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
module TMDb
|
|
4
|
+
class TV < Resource
|
|
5
|
+
def detail(id, filters = {})
|
|
6
|
+
object("/tv/#{id}", filters)
|
|
7
|
+
end
|
|
8
|
+
|
|
9
|
+
def alternative_titles(id, filters = {})
|
|
10
|
+
list("/tv/#{id}/alternative_titles", :results, filters)
|
|
11
|
+
end
|
|
12
|
+
|
|
13
|
+
def credits(id, filters = {})
|
|
14
|
+
object("/tv/#{id}/credits", filters)
|
|
15
|
+
end
|
|
16
|
+
|
|
17
|
+
def cast(id, filters = {})
|
|
18
|
+
list("/tv/#{id}/credits", :cast, filters)
|
|
19
|
+
end
|
|
20
|
+
|
|
21
|
+
def crew(id, filters = {})
|
|
22
|
+
list("/tv/#{id}/credits", :crew, filters)
|
|
23
|
+
end
|
|
24
|
+
|
|
25
|
+
def content_ratings(id, filters = {})
|
|
26
|
+
list("/tv/#{id}/content_ratings", :results, filters)
|
|
27
|
+
end
|
|
28
|
+
|
|
29
|
+
def external_ids(id, filters = {})
|
|
30
|
+
object("/tv/#{id}/external_ids", filters)
|
|
31
|
+
end
|
|
32
|
+
|
|
33
|
+
def images(id, filters = {})
|
|
34
|
+
object("/tv/#{id}/images", filters)
|
|
35
|
+
end
|
|
36
|
+
|
|
37
|
+
def backdrops(id, filters = {})
|
|
38
|
+
list("/tv/#{id}/images", :backdrops, filters)
|
|
39
|
+
end
|
|
40
|
+
|
|
41
|
+
def posters(id, filters = {})
|
|
42
|
+
list("/tv/#{id}/images", :posters, filters)
|
|
43
|
+
end
|
|
44
|
+
|
|
45
|
+
def logos(id, filters = {})
|
|
46
|
+
list("/tv/#{id}/images", :logos, filters)
|
|
47
|
+
end
|
|
48
|
+
|
|
49
|
+
def keywords(id, filters = {})
|
|
50
|
+
list("/tv/#{id}/keywords", :results, filters)
|
|
51
|
+
end
|
|
52
|
+
|
|
53
|
+
def videos(id, filters = {})
|
|
54
|
+
list("/tv/#{id}/videos", :results, filters)
|
|
55
|
+
end
|
|
56
|
+
|
|
57
|
+
def translations(id, filters = {})
|
|
58
|
+
list("/tv/#{id}/translations", :translations, filters)
|
|
59
|
+
end
|
|
60
|
+
|
|
61
|
+
def watch_providers(id, filters = {})
|
|
62
|
+
object("/tv/#{id}/watch/providers", filters)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
def changes(id, filters = {})
|
|
66
|
+
list("/tv/#{id}/changes", :changes, filters)
|
|
67
|
+
end
|
|
68
|
+
|
|
69
|
+
def similar(id, filters = {})
|
|
70
|
+
page("/tv/#{id}/similar", filters)
|
|
71
|
+
end
|
|
72
|
+
|
|
73
|
+
def recommendations(id, filters = {})
|
|
74
|
+
page("/tv/#{id}/recommendations", filters)
|
|
75
|
+
end
|
|
76
|
+
|
|
77
|
+
def reviews(id, filters = {})
|
|
78
|
+
page("/tv/#{id}/reviews", filters)
|
|
79
|
+
end
|
|
80
|
+
|
|
81
|
+
def latest(filters = {})
|
|
82
|
+
object('/tv/latest', filters)
|
|
83
|
+
end
|
|
84
|
+
|
|
85
|
+
def on_the_air(filters = {})
|
|
86
|
+
page('/tv/on_the_air', filters)
|
|
87
|
+
end
|
|
88
|
+
|
|
89
|
+
def airing_today(filters = {})
|
|
90
|
+
page('/tv/airing_today', filters)
|
|
91
|
+
end
|
|
92
|
+
|
|
93
|
+
def top_rated(filters = {})
|
|
94
|
+
page('/tv/top_rated', filters)
|
|
95
|
+
end
|
|
96
|
+
|
|
97
|
+
def popular(filters = {})
|
|
98
|
+
page('/tv/popular', filters)
|
|
99
|
+
end
|
|
100
|
+
|
|
101
|
+
expose_class_methods
|
|
102
|
+
end
|
|
103
|
+
|
|
104
|
+
# themoviedb-api nested the season and episode endpoints under a `Tv` module
|
|
105
|
+
# while the series lived on a `TV` class. Both spellings resolve here, so
|
|
106
|
+
# `TMDb::Tv::Season` and `TMDb::TV::Season` are the same class.
|
|
107
|
+
Tv = TV
|
|
108
|
+
end
|
data/lib/tmdb/version.rb
ADDED
data/lib/tmdb_client.rb
ADDED
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# frozen_string_literal: true
|
|
2
|
+
|
|
3
|
+
require 'json'
|
|
4
|
+
|
|
5
|
+
require 'faraday'
|
|
6
|
+
require 'faraday/retry'
|
|
7
|
+
|
|
8
|
+
require_relative 'tmdb/version'
|
|
9
|
+
require_relative 'tmdb/errors'
|
|
10
|
+
require_relative 'tmdb/object'
|
|
11
|
+
require_relative 'tmdb/page'
|
|
12
|
+
require_relative 'tmdb/config'
|
|
13
|
+
require_relative 'tmdb/client'
|
|
14
|
+
require_relative 'tmdb/resource'
|
|
15
|
+
require_relative 'tmdb/certification'
|
|
16
|
+
require_relative 'tmdb/change'
|
|
17
|
+
require_relative 'tmdb/collection'
|
|
18
|
+
require_relative 'tmdb/company'
|
|
19
|
+
require_relative 'tmdb/configuration'
|
|
20
|
+
require_relative 'tmdb/credit'
|
|
21
|
+
require_relative 'tmdb/discover'
|
|
22
|
+
require_relative 'tmdb/find'
|
|
23
|
+
require_relative 'tmdb/genre'
|
|
24
|
+
require_relative 'tmdb/job'
|
|
25
|
+
require_relative 'tmdb/keyword'
|
|
26
|
+
require_relative 'tmdb/movie'
|
|
27
|
+
require_relative 'tmdb/network'
|
|
28
|
+
require_relative 'tmdb/person'
|
|
29
|
+
require_relative 'tmdb/review'
|
|
30
|
+
require_relative 'tmdb/search'
|
|
31
|
+
require_relative 'tmdb/tv'
|
|
32
|
+
require_relative 'tmdb/tv/season'
|
|
33
|
+
require_relative 'tmdb/tv/episode'
|
|
34
|
+
|
|
35
|
+
# A Ruby client for The Movie Database (TMDb) v3 API.
|
|
36
|
+
#
|
|
37
|
+
# TMDb.configure do |config|
|
|
38
|
+
# config.api_key = ENV['TMDB_API_KEY']
|
|
39
|
+
# config.language = 'es'
|
|
40
|
+
# end
|
|
41
|
+
#
|
|
42
|
+
# TMDb::Movie.detail(550, append_to_response: 'credits')
|
|
43
|
+
module TMDb
|
|
44
|
+
class << self
|
|
45
|
+
# The settings the default client is built from.
|
|
46
|
+
def config
|
|
47
|
+
@config ||= Config.new
|
|
48
|
+
end
|
|
49
|
+
|
|
50
|
+
def configure
|
|
51
|
+
yield(config)
|
|
52
|
+
# The client caches its own copy of the config and its connection, so it
|
|
53
|
+
# has to be rebuilt when the settings behind it change.
|
|
54
|
+
@client = nil
|
|
55
|
+
|
|
56
|
+
config
|
|
57
|
+
end
|
|
58
|
+
|
|
59
|
+
# The shared client every `TMDb::Movie.detail`-style class method goes
|
|
60
|
+
# through. Assign your own to swap it wholesale.
|
|
61
|
+
def client
|
|
62
|
+
@client ||= Client.new(config)
|
|
63
|
+
end
|
|
64
|
+
|
|
65
|
+
attr_writer :client
|
|
66
|
+
|
|
67
|
+
def reset!
|
|
68
|
+
@config = nil
|
|
69
|
+
@client = nil
|
|
70
|
+
end
|
|
71
|
+
end
|
|
72
|
+
end
|