fix tmdbapis

This commit is contained in:
jxxghp 2023-07-29 13:09:36 +08:00
parent e4992ea574
commit d76fe5c039
37 changed files with 2660 additions and 28 deletions

View File

@ -36,6 +36,46 @@ def tmdb_season_episodes(tmdbid: int, season: int,
return episodes_info return episodes_info
@router.get("/{tmdbid}/similar", summary="类似电影/电视剧", response_model=List[schemas.MediaInfo])
def movie_similar(tmdbid: int,
mtype: str,
_: schemas.TokenPayload = Depends(verify_token)) -> Any:
"""
根据TMDBID查询类似电影
"""
mediatype = MediaType(mtype)
if mediatype == MediaType.MOVIE:
tmdbinfos = TmdbChain().movie_similar(tmdbid=tmdbid)
elif mediatype == MediaType.TV:
tmdbinfos = TmdbChain().tv_similar(tmdbid=tmdbid)
else:
return []
if not tmdbinfos:
return []
else:
return [MediaInfo(tmdb_info=tmdbinfo).to_dict() for tmdbinfo in tmdbinfos]
@router.get("/{tmdbid}/credits", summary="演员阵容", response_model=List[schemas.TmdbCast])
def movie_similar(tmdbid: int,
mtype: str,
_: schemas.TokenPayload = Depends(verify_token)) -> Any:
"""
根据TMDBID查询演员阵容
"""
mediatype = MediaType(mtype)
if mediatype == MediaType.MOVIE:
tmdbinfos = TmdbChain().movie_credits(tmdbid=tmdbid)
elif mediatype == MediaType.TV:
tmdbinfos = TmdbChain().tv_credits(tmdbid=tmdbid)
else:
return []
if not tmdbinfos:
return []
else:
return tmdbinfos
@router.get("/movies", summary="TMDB电影", response_model=List[schemas.MediaInfo]) @router.get("/movies", summary="TMDB电影", response_model=List[schemas.MediaInfo])
def tmdb_movies(sort_by: str = "popularity.desc", def tmdb_movies(sort_by: str = "popularity.desc",
with_genres: str = "", with_genres: str = "",

View File

@ -47,3 +47,31 @@ class TmdbChain(ChainBase):
:param season: :param season:
""" """
return self.run_module("tmdb_episodes", tmdbid=tmdbid, season=season) return self.run_module("tmdb_episodes", tmdbid=tmdbid, season=season)
def movie_similar(self, tmdbid: int) -> List[dict]:
"""
根据TMDBID查询类似电影
:param tmdbid: TMDBID
"""
return self.run_module("movie_similar", tmdbid=tmdbid)
def tv_similar(self, tmdbid: int) -> List[dict]:
"""
根据TMDBID查询类似电视剧
:param tmdbid: TMDBID
"""
return self.run_module("tv_similar", tmdbid=tmdbid)
def movie_credits(self, tmdbid: int) -> List[dict]:
"""
根据TMDBID查询电影演职人员
:param tmdbid: TMDBID
"""
return self.run_module("movie_credits", tmdbid=tmdbid)
def tv_credits(self, tmdbid: int) -> List[dict]:
"""
根据TMDBID查询电视剧演职人员
:param tmdbid: TMDBID
"""
return self.run_module("tv_credits", tmdbid=tmdbid)

View File

@ -9,7 +9,7 @@ from app.log import logger
from app.modules import _ModuleBase from app.modules import _ModuleBase
from app.modules.themoviedb.category import CategoryHelper from app.modules.themoviedb.category import CategoryHelper
from app.modules.themoviedb.scraper import TmdbScraper from app.modules.themoviedb.scraper import TmdbScraper
from app.modules.themoviedb.tmdb import TmdbHelper from app.modules.themoviedb.tmdbapi import TmdbHelper
from app.modules.themoviedb.tmdb_cache import TmdbCache from app.modules.themoviedb.tmdb_cache import TmdbCache
from app.schemas.types import MediaType, MediaImageType from app.schemas.types import MediaType, MediaImageType
from app.utils.system import SystemUtils from app.utils.system import SystemUtils
@ -331,3 +331,31 @@ class TheMovieDbModule(_ModuleBase):
if image_path: if image_path:
return f"https://image.tmdb.org/t/p/{image_prefix}{image_path}" return f"https://image.tmdb.org/t/p/{image_prefix}{image_path}"
return None return None
def movie_similar(self, tmdbid: int) -> List[dict]:
"""
根据TMDBID查询类似电影
:param tmdbid: TMDBID
"""
return self.tmdb.get_movie_similar(tmdbid=tmdbid)
def tv_similar(self, tmdbid: int) -> List[dict]:
"""
根据TMDBID查询类似电视剧
:param tmdbid: TMDBID
"""
return self.tmdb.get_tv_similar(tmdbid=tmdbid)
def movie_credits(self, tmdbid: int) -> List[dict]:
"""
根据TMDBID查询电影演职员表
:param tmdbid: TMDBID
"""
return self.tmdb.get_movie_credits(tmdbid=tmdbid)
def tv_credits(self, tmdbid: int) -> List[dict]:
"""
根据TMDBID查询电视剧演职员表
:param tmdbid: TMDBID
"""
return self.tmdb.get_tv_credits(tmdbid=tmdbid)

View File

@ -5,8 +5,8 @@ from urllib.parse import quote
import zhconv import zhconv
from lxml import etree from lxml import etree
from tmdbv3api import TMDb, Search, Movie, TV, Season, Episode, Discover, Trending from .tmdbv3api import TMDb, Search, Movie, TV, Season, Episode, Discover, Trending
from tmdbv3api.exceptions import TMDbException from .tmdbv3api.exceptions import TMDbException
from app.core.config import settings from app.core.config import settings
from app.log import logger from app.log import logger
@ -1045,3 +1045,59 @@ class TmdbHelper:
except Exception as e: except Exception as e:
print(str(e)) print(str(e))
return {} return {}
def get_movie_similar(self, tmdbid: int) -> List[dict]:
"""
获取电影的相似电影
"""
if not self.movie:
return []
try:
logger.info(f"正在获取相似电影:{tmdbid}...")
info = self.movie.similar(tmdbid) or {}
return info.get('results') or []
except Exception as e:
print(str(e))
return []
def get_tv_similar(self, tmdbid: int) -> List[dict]:
"""
获取电视剧的相似电视剧
"""
if not self.tv:
return []
try:
logger.info(f"正在获取相似电视剧:{tmdbid}...")
info = self.tv.similar(tmdbid) or {}
return info.get('results') or []
except Exception as e:
print(str(e))
return []
def get_movie_credits(self, tmdbid: int) -> List[dict]:
"""
获取电影的演职员列表
"""
if not self.movie:
return []
try:
logger.info(f"正在获取电影演职员:{tmdbid}...")
info = self.movie.credits(tmdbid) or {}
return info.get('cast') or []
except Exception as e:
print(str(e))
return []
def get_tv_credits(self, tmdbid: int) -> List[dict]:
"""
获取电视剧的演职员列表
"""
if not self.tv:
return []
try:
logger.info(f"正在获取电视剧演职员:{tmdbid}...")
info = self.tv.credits(tmdbid) or {}
return info.get('cast') or []
except Exception as e:
print(str(e))
return []

View File

@ -0,0 +1,25 @@
from .objs.account import Account
from .objs.auth import Authentication
from .objs.certification import Certification
from .objs.change import Change
from .objs.collection import Collection
from .objs.company import Company
from .objs.configuration import Configuration
from .objs.credit import Credit
from .objs.discover import Discover
from .objs.episode import Episode
from .objs.find import Find
from .objs.genre import Genre
from .objs.group import Group
from .objs.keyword import Keyword
from .objs.list import List
from .objs.movie import Movie
from .objs.network import Network
from .objs.person import Person
from .objs.provider import Provider
from .objs.review import Review
from .objs.search import Search
from .objs.season import Season
from .objs.trending import Trending
from .objs.tv import TV
from .tmdb import TMDb

View File

@ -0,0 +1,102 @@
# encoding: utf-8
import sys
class AsObj:
def __init__(self, json=None, key=None, dict_key=False, dict_key_name=None):
self._json = json if json else {}
self._key = key
self._dict_key = dict_key
self._dict_key_name = dict_key_name
self._obj_list = []
self._list_only = False
if isinstance(self._json, list):
self._obj_list = [AsObj(o) if isinstance(o, (dict, list)) else o for o in self._json]
self._list_only = True
elif dict_key:
self._obj_list = [
AsObj({k: v}, key=k, dict_key_name=dict_key_name) if isinstance(v, (dict, list)) else v
for k, v in self._json.items()
]
self._list_only = True
else:
for key, value in self._json.items():
if isinstance(value, (dict, list)):
if self._key and key == self._key:
final = AsObj(value, dict_key=isinstance(value, dict), dict_key_name=key)
self._obj_list = final
else:
final = AsObj(value)
else:
final = value
if dict_key_name:
setattr(self, dict_key_name, key)
setattr(self, key, final)
def _dict(self):
return {k: v for k, v in self.__dict__.items() if not k.startswith("_")}
def __delitem__(self, key):
return delattr(self, key)
def __getitem__(self, key):
if isinstance(key, int) and self._obj_list:
return self._obj_list[key]
else:
return getattr(self, key)
def __iter__(self):
return (o for o in self._obj_list) if self._obj_list else iter(self._dict())
def __len__(self):
return len(self._obj_list) if self._obj_list else len(self._dict())
def __repr__(self):
return str(self._obj_list) if self._list_only else str(self._dict())
def __setitem__(self, key, value):
return setattr(self, key, value)
def __str__(self):
return str(self._obj_list) if self._list_only else str(self._dict())
if sys.version_info >= (3, 8):
def __reversed__(self):
return reversed(self._dict())
if sys.version_info >= (3, 9):
def __class_getitem__(self, key):
return self.__dict__.__class_getitem__(key)
def __ior__(self, value):
return self._dict().__ior__(value)
def __or__(self, value):
return self._dict().__or__(value)
def copy(self):
return AsObj(self._json.copy(), key=self._key, dict_key=self._dict_key, dict_key_name=self._dict_key_name)
def get(self, key, value=None):
return self._dict().get(key, value)
def items(self):
return self._dict().items()
def keys(self):
return self._dict().keys()
def pop(self, key, value=None):
return self.__dict__.pop(key, value)
def popitem(self):
return self.__dict__.popitem()
def setdefault(self, key, value=None):
return self.__dict__.setdefault(key, value)
def update(self, entries):
return self.__dict__.update(entries)
def values(self):
return self._dict().values()

View File

@ -0,0 +1,2 @@
class TMDbException(Exception):
pass

View File

@ -0,0 +1,177 @@
import os
from ..tmdb import TMDb
from ..exceptions import TMDbException
class Account(TMDb):
_urls = {
"details": "/account",
"created_lists": "/account/%s/lists",
"favorite_movies": "/account/%s/favorite/movies",
"favorite_tv": "/account/%s/favorite/tv",
"favorite": "/account/%s/favorite",
"rated_movies": "/account/%s/rated/movies",
"rated_tv": "/account/%s/rated/tv",
"rated_episodes": "/account/%s/rated/tv/episodes",
"movie_watchlist": "/account/%s/watchlist/movies",
"tv_watchlist": "/account/%s/watchlist/tv",
"watchlist": "/account/%s/watchlist",
}
@property
def account_id(self):
if not os.environ.get("TMDB_ACCOUNT_ID"):
os.environ["TMDB_ACCOUNT_ID"] = str(self.details()["id"])
return os.environ.get("TMDB_ACCOUNT_ID")
def details(self):
"""
Get your account details.
:return:
"""
return self._request_obj(
self._urls["details"],
params="session_id=%s" % self.session_id
)
def created_lists(self, page=1):
"""
Get all of the lists created by an account. Will include private lists if you are the owner.
:param page: int
:return:
"""
return self._request_obj(
self._urls["created_lists"] % self.account_id,
params="session_id=%s&page=%s" % (self.session_id, page),
key="results"
)
def _get_list(self, url, asc_sort=True, page=1):
params = "session_id=%s&page=%s" % (self.session_id, page)
if asc_sort is False:
params += "&sort_by=created_at.desc"
return self._request_obj(
self._urls[url] % self.account_id,
params=params,
key="results"
)
def favorite_movies(self, asc_sort=True, page=1):
"""
Get the list of your favorite movies.
:param asc_sort: bool
:param page: int
:return:
"""
return self._get_list("favorite_movies", asc_sort=asc_sort, page=page)
def favorite_tv_shows(self, asc_sort=True, page=1):
"""
Get the list of your favorite TV shows.
:param asc_sort: bool
:param page: int
:return:
"""
return self._get_list("favorite_tv", asc_sort=asc_sort, page=page)
def mark_as_favorite(self, media_id, media_type, favorite=True):
"""
This method allows you to mark a movie or TV show as a favorite item.
:param media_id: int
:param media_type: str
:param favorite:bool
"""
if media_type not in ["tv", "movie"]:
raise TMDbException("Media Type should be tv or movie.")
self._request_obj(
self._urls["favorite"] % self.account_id,
params="session_id=%s" % self.session_id,
method="POST",
json={
"media_type": media_type,
"media_id": media_id,
"favorite": favorite,
}
)
def unmark_as_favorite(self, media_id, media_type):
"""
This method allows you to unmark a movie or TV show as a favorite item.
:param media_id: int
:param media_type: str
"""
self.mark_as_favorite(media_id, media_type, favorite=False)
def rated_movies(self, asc_sort=True, page=1):
"""
Get a list of all the movies you have rated.
:param asc_sort: bool
:param page: int
:return:
"""
return self._get_list("rated_movies", asc_sort=asc_sort, page=page)
def rated_tv_shows(self, asc_sort=True, page=1):
"""
Get a list of all the TV shows you have rated.
:param asc_sort: bool
:param page: int
:return:
"""
return self._get_list("rated_tv", asc_sort=asc_sort, page=page)
def rated_episodes(self, asc_sort=True, page=1):
"""
Get a list of all the TV episodes you have rated.
:param asc_sort: bool
:param page: int
:return:
"""
return self._get_list("rated_episodes", asc_sort=asc_sort, page=page)
def movie_watchlist(self, asc_sort=True, page=1):
"""
Get a list of all the movies you have added to your watchlist.
:param asc_sort: bool
:param page: int
:return:
"""
return self._get_list("movie_watchlist", asc_sort=asc_sort, page=page)
def tv_show_watchlist(self, asc_sort=True, page=1):
"""
Get a list of all the TV shows you have added to your watchlist.
:param asc_sort: bool
:param page: int
:return:
"""
return self._get_list("tv_watchlist", asc_sort=asc_sort, page=page)
def add_to_watchlist(self, media_id, media_type, watchlist=True):
"""
Add a movie or TV show to your watchlist.
:param media_id: int
:param media_type: str
:param watchlist: bool
"""
if media_type not in ["tv", "movie"]:
raise TMDbException("Media Type should be tv or movie.")
self._request_obj(
self._urls["watchlist"] % self.account_id,
"session_id=%s" % self.session_id,
method="POST",
json={
"media_type": media_type,
"media_id": media_id,
"watchlist": watchlist,
}
)
def remove_from_watchlist(self, media_id, media_type):
"""
Remove a movie or TV show from your watchlist.
:param media_id: int
:param media_type: str
"""
self.add_to_watchlist(media_id, media_type, watchlist=False)

View File

@ -0,0 +1,64 @@
from ..tmdb import TMDb
class Authentication(TMDb):
_urls = {
"create_request_token": "/authentication/token/new",
"validate_with_login": "/authentication/token/validate_with_login",
"create_session": "/authentication/session/new",
"delete_session": "/authentication/session",
}
def __init__(self, username, password):
super().__init__()
self.username = username
self.password = password
self.expires_at = None
self.request_token = self._create_request_token()
self._authorise_request_token_with_login()
self._create_session()
def _create_request_token(self):
"""
Create a temporary request token that can be used to validate a TMDb user login.
"""
response = self._request_obj(self._urls["create_request_token"])
self.expires_at = response.expires_at
return response.request_token
def _create_session(self):
"""
You can use this method to create a fully valid session ID once a user has validated the request token.
"""
response = self._request_obj(
self._urls["create_session"],
method="POST",
json={"request_token": self.request_token}
)
self.session_id = response.session_id
def _authorise_request_token_with_login(self):
"""
This method allows an application to validate a request token by entering a username and password.
"""
self._request_obj(
self._urls["validate_with_login"],
method="POST",
json={
"username": self.username,
"password": self.password,
"request_token": self.request_token,
}
)
def delete_session(self):
"""
If you would like to delete (or "logout") from a session, call this method with a valid session ID.
"""
if self.has_session:
self._request_obj(
self._urls["delete_session"],
method="DELETE",
json={"session_id": self.session_id}
)
self.session_id = ""

View File

@ -0,0 +1,22 @@
from ..tmdb import TMDb
class Certification(TMDb):
_urls = {
"movie_list": "/certification/movie/list",
"tv_list": "/certification/tv/list",
}
def movie_list(self):
"""
Get an up to date list of the officially supported movie certifications on TMDB.
:return:
"""
return self._request_obj(self._urls["movie_list"], key="certifications")
def tv_list(self):
"""
Get an up to date list of the officially supported TV show certifications on TMDB.
:return:
"""
return self._request_obj(self._urls["tv_list"], key="certifications")

View File

@ -0,0 +1,54 @@
from ..tmdb import TMDb
class Change(TMDb):
_urls = {
"movie": "/movie/changes",
"tv": "/tv/changes",
"person": "/person/changes"
}
def _change_list(self, change_type, start_date="", end_date="", page=1):
params = "page=%s" % page
if start_date:
params += "&start_date=%s" % start_date
if end_date:
params += "&end_date=%s" % end_date
return self._request_obj(
self._urls[change_type],
params=params,
key="results"
)
def movie_change_list(self, start_date="", end_date="", page=1):
"""
Get the changes for a movie. By default only the last 24 hours are returned.
You can query up to 14 days in a single query by using the start_date and end_date query parameters.
:param start_date: str
:param end_date: str
:param page: int
:return:
"""
return self._change_list("movie", start_date=start_date, end_date=end_date, page=page)
def tv_change_list(self, start_date="", end_date="", page=1):
"""
Get a list of all of the TV show ids that have been changed in the past 24 hours.
You can query up to 14 days in a single query by using the start_date and end_date query parameters.
:param start_date: str
:param end_date: str
:param page: int
:return:
"""
return self._change_list("tv", start_date=start_date, end_date=end_date, page=page)
def person_change_list(self, start_date="", end_date="", page=1):
"""
Get a list of all of the person ids that have been changed in the past 24 hours.
You can query up to 14 days in a single query by using the start_date and end_date query parameters.
:param start_date: str
:param end_date: str
:param page: int
:return:
"""
return self._change_list("person", start_date=start_date, end_date=end_date, page=page)

View File

@ -0,0 +1,33 @@
from ..tmdb import TMDb
class Collection(TMDb):
_urls = {
"details": "/collection/%s",
"images": "/collection/%s/images",
"translations": "/collection/%s/translations"
}
def details(self, collection_id):
"""
Get collection details by id.
:param collection_id: int
:return:
"""
return self._request_obj(self._urls["details"] % collection_id, key="parts")
def images(self, collection_id):
"""
Get the images for a collection by id.
:param collection_id: int
:return:
"""
return self._request_obj(self._urls["images"] % collection_id)
def translations(self, collection_id):
"""
Get the list translations for a collection by id.
:param collection_id: int
:return:
"""
return self._request_obj(self._urls["translations"] % collection_id, key="translations")

View File

@ -0,0 +1,47 @@
from ..tmdb import TMDb
class Company(TMDb):
_urls = {
"details": "/company/%s",
"alternative_names": "/company/%s/alternative_names",
"images": "/company/%s/images",
"movies": "/company/%s/movies"
}
def details(self, company_id):
"""
Get a companies details by id.
:param company_id: int
:return:
"""
return self._request_obj(self._urls["details"] % company_id)
def alternative_names(self, company_id):
"""
Get the alternative names of a company.
:param company_id: int
:return:
"""
return self._request_obj(self._urls["alternative_names"] % company_id, key="results")
def images(self, company_id):
"""
Get the alternative names of a company.
:param company_id: int
:return:
"""
return self._request_obj(self._urls["images"] % company_id, key="logos")
def movies(self, company_id, page=1):
"""
Get the movies of a company by id.
:param company_id: int
:param page: int
:return:
"""
return self._request_obj(
self._urls["movies"] % company_id,
params="page=%s" % page,
key="results"
)

View File

@ -0,0 +1,54 @@
import warnings
from ..tmdb import TMDb
class Configuration(TMDb):
_urls = {
"api_configuration": "/configuration",
"countries": "/configuration/countries",
"jobs": "/configuration/jobs",
"languages": "/configuration/languages",
"primary_translations": "/configuration/primary_translations",
"timezones": "/configuration/timezones"
}
def info(self):
warnings.warn("info method is deprecated use tmdbv3api.Configuration().api_configuration()",
DeprecationWarning)
return self.api_configuration()
def api_configuration(self):
"""
Get the system wide configuration info.
"""
return self._request_obj(self._urls["api_configuration"])
def countries(self):
"""
Get the list of countries (ISO 3166-1 tags) used throughout TMDb.
"""
return self._request_obj(self._urls["countries"])
def jobs(self):
"""
Get a list of the jobs and departments we use on TMDb.
"""
return self._request_obj(self._urls["jobs"])
def languages(self):
"""
Get the list of languages (ISO 639-1 tags) used throughout TMDb.
"""
return self._request_obj(self._urls["languages"])
def primary_translations(self):
"""
Get a list of the officially supported translations on TMDb.
"""
return self._request_obj(self._urls["primary_translations"])
def timezones(self):
"""
Get the list of timezones used throughout TMDb.
"""
return self._request_obj(self._urls["timezones"])

View File

@ -0,0 +1,15 @@
from ..tmdb import TMDb
class Credit(TMDb):
_urls = {
"details": "/credit/%s"
}
def details(self, credit_id):
"""
Get a movie or TV credit details by id.
:param credit_id: int
:return:
"""
return self._request_obj(self._urls["details"] % credit_id)

View File

@ -0,0 +1,30 @@
from ..tmdb import TMDb
try:
from urllib import urlencode
except ImportError:
from urllib.parse import urlencode
class Discover(TMDb):
_urls = {
"movies": "/discover/movie",
"tv": "/discover/tv"
}
def discover_movies(self, params):
"""
Discover movies by different types of data like average rating, number of votes, genres and certifications.
:param params: dict
:return:
"""
return self._request_obj(self._urls["movies"], urlencode(params), key="results")
def discover_tv_shows(self, params):
"""
Discover TV shows by different types of data like average rating, number of votes, genres,
the network they aired on and air dates.
:param params: dict
:return:
"""
return self._request_obj(self._urls["tv"], urlencode(params), key="results")

View File

@ -0,0 +1,157 @@
from ..tmdb import TMDb
class Episode(TMDb):
_urls = {
"details": "/tv/%s/season/%s/episode/%s",
"account_states": "/tv/%s/season/%s/episode/%s/account_states",
"changes": "/tv/episode/%s/changes",
"credits": "/tv/%s/season/%s/episode/%s/credits",
"external_ids": "/tv/%s/season/%s/episode/%s/external_ids",
"images": "/tv/%s/season/%s/episode/%s/images",
"translations": "/tv/%s/season/%s/episode/%s/translations",
"rate_tv_episode": "/tv/%s/season/%s/episode/%s/rating",
"delete_rating": "/tv/%s/season/%s/episode/%s/rating",
"videos": "/tv/%s/season/%s/episode/%s/videos",
}
def details(self, tv_id, season_num, episode_num, append_to_response="trailers,images,casts,translations"):
"""
Get the TV episode details by id.
:param tv_id: int
:param season_num: int
:param episode_num: int
:param append_to_response: str
:return:
"""
return self._request_obj(
self._urls["details"] % (tv_id, season_num, episode_num),
params="append_to_response=%s" % append_to_response
)
def account_states(self, tv_id, season_num, episode_num):
"""
Get your rating for a episode.
:param tv_id: int
:param season_num: int
:param episode_num: int
:return:
"""
return self._request_obj(
self._urls["account_states"] % (tv_id, season_num, episode_num),
params="session_id=%s" % self.session_id
)
def changes(self, episode_id, start_date=None, end_date=None, page=1):
"""
Get the changes for a TV episode. By default only the last 24 hours are returned.
You can query up to 14 days in a single query by using the start_date and end_date query parameters.
:param episode_id: int
:param start_date: str
:param end_date: str
:param page: int
:return:
"""
params = "page=%s" % page
if start_date:
params += "&start_date=%s" % start_date
if end_date:
params += "&end_date=%s" % end_date
return self._request_obj(
self._urls["changes"] % episode_id,
params=params,
key="changes"
)
def credits(self, tv_id, season_num, episode_num):
"""
Get the credits for TV season.
:param tv_id: int
:param season_num: int
:param episode_num: int
:return:
"""
return self._request_obj(self._urls["credits"] % (tv_id, season_num, episode_num))
def external_ids(self, tv_id, season_num, episode_num):
"""
Get the external ids for a TV episode.
:param tv_id: int
:param season_num: int
:param episode_num: int
:return:
"""
return self._request_obj(self._urls["external_ids"] % (tv_id, season_num, episode_num))
def images(self, tv_id, season_num, episode_num, include_image_language=None):
"""
Get the images that belong to a TV episode.
:param tv_id: int
:param season_num: int
:param episode_num: int
:param include_image_language: str
:return:
"""
return self._request_obj(
self._urls["images"] % (tv_id, season_num, episode_num),
params="include_image_language=%s" % include_image_language if include_image_language else "",
key="stills"
)
def translations(self, tv_id, season_num, episode_num):
"""
Get the translation data for an episode.
:param tv_id: int
:param season_num: int
:param episode_num: int
:return:
"""
return self._request_obj(
self._urls["translations"] % (tv_id, season_num, episode_num),
key="translations"
)
def rate_tv_episode(self, tv_id, season_num, episode_num, rating):
"""
Rate a TV episode.
:param tv_id: int
:param season_num: int
:param episode_num: int
:param rating: float
"""
self._request_obj(
self._urls["rate_tv_episode"] % (tv_id, season_num, episode_num),
params="session_id=%s" % self.session_id,
method="POST",
json={"value": rating}
)
def delete_rating(self, tv_id, season_num, episode_num):
"""
Remove your rating for a TV episode.
:param tv_id: int
:param season_num: int
:param episode_num: int
"""
self._request_obj(
self._urls["delete_rating"] % (tv_id, season_num, episode_num),
params="session_id=%s" % self.session_id,
method="DELETE"
)
def videos(self, tv_id, season_num, episode_num, include_video_language=None):
"""
Get the videos that have been added to a TV episode.
:param tv_id: int
:param season_num: int
:param episode_num: int
:param include_video_language: str
:return:
"""
params = ""
if include_video_language:
params += "&include_video_language=%s" % include_video_language
return self._request_obj(
self._urls["videos"] % (tv_id, season_num, episode_num),
params=params
)

View File

@ -0,0 +1,83 @@
from ..tmdb import TMDb
class Find(TMDb):
_urls = {
"find": "/find/%s"
}
def find(self, external_id, external_source):
"""
The find method makes it easy to search for objects in our database by an external id. For example, an IMDB ID.
:param external_id: str
:param external_source str
:return:
"""
return self._request_obj(
self._urls["find"] % external_id.replace("/", "%2F"),
params="external_source=" + external_source
)
def find_by_imdb_id(self, imdb_id):
"""
The find method makes it easy to search for objects in our database by an IMDB ID.
:param imdb_id: str
:return:
"""
return self.find(imdb_id, "imdb_id")
def find_by_tvdb_id(self, tvdb_id):
"""
The find method makes it easy to search for objects in our database by a TVDB ID.
:param tvdb_id: int
:return:
"""
return self.find(tvdb_id, "tvdb_id")
def find_by_freebase_mid(self, freebase_mid):
"""
The find method makes it easy to search for objects in our database by a Freebase MID.
:param freebase_mid: str
:return:
"""
return self.find(freebase_mid, "freebase_mid")
def find_by_freebase_id(self, freebase_id):
"""
The find method makes it easy to search for objects in our database by a Freebase ID.
:param freebase_id: str
:return:
"""
return self.find(freebase_id, "freebase_id")
def find_by_tvrage_id(self, tvrage_id):
"""
The find method makes it easy to search for objects in our database by a TVRage ID.
:param tvrage_id: str
:return:
"""
return self.find(tvrage_id, "tvrage_id")
def find_by_facebook_id(self, facebook_id):
"""
The find method makes it easy to search for objects in our database by a Facebook ID.
:param facebook_id: str
:return:
"""
return self.find(facebook_id, "facebook_id")
def find_by_instagram_id(self, instagram_id):
"""
The find method makes it easy to search for objects in our database by a Instagram ID.
:param instagram_id: str
:return:
"""
return self.find(instagram_id, "instagram_id")
def find_by_twitter_id(self, twitter_id):
"""
The find method makes it easy to search for objects in our database by a Twitter ID.
:param twitter_id: str
:return:
"""
return self.find(twitter_id, "twitter_id")

View File

@ -0,0 +1,22 @@
from ..tmdb import TMDb
class Genre(TMDb):
_urls = {
"movie_list": "/genre/movie/list",
"tv_list": "/genre/tv/list"
}
def movie_list(self):
"""
Get the list of official genres for movies.
:return:
"""
return self._request_obj(self._urls["movie_list"], key="genres")
def tv_list(self):
"""
Get the list of official genres for TV shows.
:return:
"""
return self._request_obj(self._urls["tv_list"], key="genres")

View File

@ -0,0 +1,15 @@
from ..tmdb import TMDb
class Group(TMDb):
_urls = {
"details": "/tv/episode_group/%s"
}
def details(self, group_id):
"""
Get the details of a TV episode group.
:param group_id: int
:return:
"""
return self._request_obj(self._urls["details"] % group_id, key="groups")

View File

@ -0,0 +1,24 @@
from ..tmdb import TMDb
class Keyword(TMDb):
_urls = {
"details": "/keyword/%s",
"movies": "/keyword/%s/movies"
}
def details(self, keyword_id):
"""
Get a keywords details by id.
:param keyword_id: int
:return:
"""
return self._request_obj(self._urls["details"] % keyword_id)
def movies(self, keyword_id):
"""
Get the movies of a keyword by id.
:param keyword_id: int
:return:
"""
return self._request_obj(self._urls["movies"] % keyword_id, key="results")

View File

@ -0,0 +1,96 @@
from ..tmdb import TMDb
class List(TMDb):
_urls = {
"details": "/list/%s",
"check_status": "/list/%s/item_status",
"create": "/list",
"add_movie": "/list/%s/add_item",
"remove_movie": "/list/%s/remove_item",
"clear_list": "/list/%s/clear",
"delete_list": "/list/%s",
}
def details(self, list_id):
"""
Get list details by id.
:param list_id: int
:return:
"""
return self._request_obj(self._urls["details"] % list_id, key="items")
def check_item_status(self, list_id, movie_id):
"""
You can use this method to check if a movie has already been added to the list.
:param list_id: int
:param movie_id: int
:return:
"""
return self._request_obj(self._urls["check_status"] % list_id, params="movie_id=%s" % movie_id)["item_present"]
def create_list(self, name, description):
"""
You can use this method to check if a movie has already been added to the list.
:param name: str
:param description: str
:return:
"""
return self._request_obj(
self._urls["create"],
params="session_id=%s" % self.session_id,
method="POST",
json={
"name": name,
"description": description,
"language": self.language
}
).list_id
def add_movie(self, list_id, movie_id):
"""
Add a movie to a list.
:param list_id: int
:param movie_id: int
"""
self._request_obj(
self._urls["add_movie"] % list_id,
params="session_id=%s" % self.session_id,
method="POST",
json={"media_id": movie_id}
)
def remove_movie(self, list_id, movie_id):
"""
Remove a movie from a list.
:param list_id: int
:param movie_id: int
"""
self._request_obj(
self._urls["remove_movie"] % list_id,
params="session_id=%s" % self.session_id,
method="POST",
json={"media_id": movie_id}
)
def clear_list(self, list_id):
"""
Clear all of the items from a list.
:param list_id: int
"""
self._request_obj(
self._urls["clear_list"] % list_id,
params="session_id=%s&confirm=true" % self.session_id,
method="POST"
)
def delete_list(self, list_id):
"""
Delete a list.
:param list_id: int
"""
self._request_obj(
self._urls["delete_list"] % list_id,
params="session_id=%s" % self.session_id,
method="DELETE"
)

View File

@ -0,0 +1,348 @@
import warnings
from ..tmdb import TMDb
from .find import Find
from .search import Search
class Movie(TMDb):
_urls = {
"details": "/movie/%s",
"account_states": "/movie/%s/account_states",
"alternative_titles": "/movie/%s/alternative_titles",
"changes": "/movie/%s/changes",
"credits": "/movie/%s/credits",
"external_ids": "/movie/%s/external_ids",
"images": "/movie/%s/images",
"keywords": "/movie/%s/keywords",
"lists": "/movie/%s/lists",
"recommendations": "/movie/%s/recommendations",
"release_dates": "/movie/%s/release_dates",
"reviews": "/movie/%s/reviews",
"similar": "/movie/%s/similar",
"translations": "/movie/%s/translations",
"videos": "/movie/%s/videos",
"watch_providers": "/movie/%s/watch/providers",
"rate_movie": "/movie/%s/rating",
"delete_rating": "/movie/%s/rating",
"latest": "/movie/latest",
"now_playing": "/movie/now_playing",
"popular": "/movie/popular",
"top_rated": "/movie/top_rated",
"upcoming": "/movie/upcoming",
}
def details(self, movie_id, append_to_response="videos,trailers,images,casts,translations,keywords,release_dates"):
"""
Get the primary information about a movie.
:param movie_id: int
:param append_to_response: str
:return:
"""
return self._request_obj(
self._urls["details"] % movie_id,
params="append_to_response=%s" % append_to_response
)
def account_states(self, movie_id):
"""
Grab the following account states for a session:
Movie rating, If it belongs to your watchlist, or If it belongs to your favourite list.
:param movie_id: int
:return:
"""
return self._request_obj(
self._urls["account_states"] % movie_id,
params="session_id=%s" % self.session_id
)
def alternative_titles(self, movie_id, country=None):
"""
Get all of the alternative titles for a movie.
:param movie_id: int
:param country: str
:return:
"""
return self._request_obj(
self._urls["alternative_titles"] % movie_id,
params="country=%s" % country if country else "",
key="titles"
)
def changes(self, movie_id, start_date=None, end_date=None, page=1):
"""
Get the changes for a movie. By default only the last 24 hours are returned.
You can query up to 14 days in a single query by using the start_date and end_date query parameters.
:param movie_id: int
:param start_date: str
:param end_date: str
:param page: int
:return:
"""
params = "page=%s" % page
if start_date:
params += "&start_date=%s" % start_date
if end_date:
params += "&end_date=%s" % end_date
return self._request_obj(
self._urls["changes"] % movie_id,
params=params,
key="changes"
)
def credits(self, movie_id):
"""
Get the cast and crew for a movie.
:param movie_id: int
:return:
"""
return self._request_obj(self._urls["credits"] % movie_id)
def external_ids(self, movie_id):
"""
Get the external ids for a movie.
:param movie_id: int
:return:
"""
return self._request_obj(self._urls["external_ids"] % movie_id)
def images(self, movie_id, include_image_language=None):
"""
Get the images that belong to a movie.
Querying images with a language parameter will filter the results.
If you want to include a fallback language (especially useful for backdrops)
you can use the include_image_language parameter.
This should be a comma separated value like so: include_image_language=en,null.
:param movie_id: int
:param include_image_language: str
:return:
"""
return self._request_obj(
self._urls["images"] % movie_id,
params="include_image_language=%s" % include_image_language if include_image_language else ""
)
def keywords(self, movie_id):
"""
Get the keywords associated to a movie.
:param movie_id: int
:return:
"""
return self._request_obj(
self._urls["keywords"] % movie_id,
key="keywords"
)
def lists(self, movie_id, page=1):
"""
Get a list of lists that this movie belongs to.
:param movie_id: int
:param page: int
:return:
"""
return self._request_obj(
self._urls["lists"] % movie_id,
params="page=%s" % page,
key="results"
)
def recommendations(self, movie_id, page=1):
"""
Get a list of recommended movies for a movie.
:param movie_id: int
:param page: int
:return:
"""
return self._request_obj(
self._urls["recommendations"] % movie_id,
params="page=%s" % page,
key="results"
)
def release_dates(self, movie_id):
"""
Get the release date along with the certification for a movie.
:param movie_id: int
:return:
"""
return self._request_obj(
self._urls["release_dates"] % movie_id,
key="results"
)
def reviews(self, movie_id, page=1):
"""
Get the user reviews for a movie.
:param movie_id: int
:param page: int
:return:
"""
return self._request_obj(
self._urls["reviews"] % movie_id,
params="page=%s" % page,
key="results"
)
def similar(self, movie_id, page=1):
"""
Get a list of similar movies.
:param movie_id: int
:param page: int
:return:
"""
return self._request_obj(
self._urls["similar"] % movie_id,
params="page=%s" % page,
key="results"
)
def translations(self, movie_id):
"""
Get a list of translations that have been created for a movie.
:param movie_id: int
:return:
"""
return self._request_obj(
self._urls["translations"] % movie_id,
key="translations"
)
def videos(self, movie_id, page=1):
"""
Get the videos that have been added to a movie.
:param movie_id: int
:param page: int
:return:
"""
return self._request_obj(
self._urls["videos"] % movie_id,
params="page=%s" % page,
key="results"
)
def watch_providers(self, movie_id):
"""
You can query this method to get a list of the availabilities per country by provider.
:param movie_id: int
:return:
"""
return self._request_obj(
self._urls["watch_providers"] % movie_id,
key="results"
)
def rate_movie(self, movie_id, rating):
"""
Rate a movie.
:param movie_id: int
:param rating: float
"""
self._request_obj(
self._urls["rate_movie"] % movie_id,
params="session_id=%s" % self.session_id,
method="POST",
json={"value": rating}
)
def delete_rating(self, movie_id):
"""
Remove your rating for a movie.
:param movie_id: int
"""
self._request_obj(
self._urls["delete_rating"] % movie_id,
params="session_id=%s" % self.session_id,
method="DELETE"
)
def latest(self):
"""
Get the most newly created movie. This is a live response and will continuously change.
:return:
"""
return self._request_obj(self._urls["latest"])
def now_playing(self, region=None, page=1):
"""
Get a list of movies in theatres.
:param region: str
:param page: int
:return:
"""
params = "page=%s" % page
if region:
params += "&region=%s" % region
return self._request_obj(
self._urls["now_playing"],
params=params,
key="results"
)
def popular(self, region=None, page=1):
"""
Get a list of the current popular movies on TMDb. This list updates daily.
:param region: str
:param page: int
:return:
"""
params = "page=%s" % page
if region:
params += "&region=%s" % region
return self._request_obj(
self._urls["popular"],
params=params,
key="results"
)
def top_rated(self, region=None, page=1):
"""
Get the top rated movies on TMDb.
:param region: str
:param page: int
:return:
"""
params = "page=%s" % page
if region:
params += "&region=%s" % region
return self._request_obj(
self._urls["top_rated"],
params=params,
key="results"
)
def upcoming(self, region=None, page=1):
"""
Get a list of upcoming movies in theatres.
:param region: str
:param page: int
:return:
"""
params = "page=%s" % page
if region:
params += "&region=%s" % region
return self._request_obj(
self._urls["upcoming"],
params=params,
key="results"
)
def search(self, term, page=1):
"""
Search for movies.
:param term: str
:param page: int
:return:
"""
warnings.warn("search method is deprecated use tmdbv3api.Search().movies(term)",
DeprecationWarning)
return Search().movies(term, page=page)
def external(self, external_id, external_source):
"""
The find method makes it easy to search for objects in our database by an external id. For example, an IMDB ID.
:param external_id: str
:param external_source str
:return:
"""
warnings.warn("external method is deprecated use tmdbv3api.Find().find(external_id, external_source)",
DeprecationWarning)
return Find().find(external_id, external_source)

View File

@ -0,0 +1,39 @@
from ..tmdb import TMDb
class Network(TMDb):
_urls = {
"details": "/network/%s",
"alternative_names": "/network/%s/alternative_names",
"images": "/network/%s/images"
}
def details(self, network_id):
"""
Get a networks details by id.
:param network_id: int
:return:
"""
return self._request_obj(self._urls["details"] % network_id)
def alternative_names(self, network_id):
"""
Get the alternative names of a network.
:param network_id: int
:return:
"""
return self._request_obj(
self._urls["alternative_names"] % network_id,
key="results"
)
def images(self, network_id):
"""
Get the TV network logos by id.
:param network_id: int
:return:
"""
return self._request_obj(
self._urls["images"] % network_id,
key="logos"
)

View File

@ -0,0 +1,151 @@
import warnings
from ..tmdb import TMDb
from .search import Search
class Person(TMDb):
_urls = {
"details": "/person/%s",
"changes": "/person/%s/changes",
"movie_credits": "/person/%s/movie_credits",
"tv_credits": "/person/%s/tv_credits",
"combined_credits": "/person/%s/combined_credits",
"external_ids": "/person/%s/external_ids",
"images": "/person/%s/images",
"tagged_images": "/person/%s/tagged_images",
"translations": "/person/%s/translations",
"latest": "/person/latest",
"popular": "/person/popular",
"search_people": "/search/person",
}
def details(self, person_id, append_to_response="videos,images"):
"""
Get the primary person details by id.
:param append_to_response: str
:param person_id: int
:return:
"""
return self._request_obj(
self._urls["details"] % person_id,
params="append_to_response=%s" % append_to_response
)
def changes(self, person_id, start_date=None, end_date=None, page=1):
"""
Get the changes for a person. By default only the last 24 hours are returned.
You can query up to 14 days in a single query by using the start_date and end_date query parameters.
:param person_id: int
:param start_date: str
:param end_date: str
:param page: int
:return:
"""
params = "page=%s" % page
if start_date:
params += "&start_date=%s" % start_date
if end_date:
params += "&end_date=%s" % end_date
return self._request_obj(
self._urls["changes"] % person_id,
params=params,
key="changes"
)
def movie_credits(self, person_id):
"""
Get the movie credits for a person.
:param person_id: int
:return:
"""
return self._request_obj(self._urls["movie_credits"] % person_id)
def tv_credits(self, person_id):
"""
Get the TV show credits for a person.
:param person_id: int
:return:
"""
return self._request_obj(self._urls["tv_credits"] % person_id)
def combined_credits(self, person_id):
"""
Get the movie and TV credits together in a single response.
:param person_id: int
:return:
"""
return self._request_obj(self._urls["combined_credits"] % person_id)
def external_ids(self, person_id):
"""
Get the external ids for a person. We currently support the following external sources.
IMDB ID, Facebook, Freebase MID, Freebase ID, Instagram, TVRage ID, and Twitter
:param person_id: int
:return:
"""
return self._request_obj(self._urls["external_ids"] % person_id)
def images(self, person_id):
"""
Get the images for a person.
:param person_id: int
:return:
"""
return self._request_obj(
self._urls["images"] % person_id,
key="profiles"
)
def tagged_images(self, person_id, page=1):
"""
Get the images that this person has been tagged in.
:param person_id: int
:param page: int
:return:
"""
return self._request_obj(
self._urls["tagged_images"] % person_id,
params="page=%s" % page,
key="results"
)
def translations(self, person_id):
"""
Get a list of translations that have been created for a person.
:param person_id: int
:return:
"""
return self._request_obj(
self._urls["translations"] % person_id,
key="translations"
)
def latest(self):
"""
Get the most newly created person. This is a live response and will continuously change.
:return:
"""
return self._request_obj(self._urls["latest"])
def popular(self, page=1):
"""
Get the list of popular people on TMDb. This list updates daily.
:param page: int
:return:
"""
return self._request_obj(
self._urls["popular"],
params="page=%s" % page,
key="results"
)
def search(self, term, page=1):
"""
Search for people.
:param term: string
:param page: int
:return:
"""
warnings.warn("search method is deprecated use tmdbv3api.Search().people(params)",
DeprecationWarning)
return Search().people(term, page=page)

View File

@ -0,0 +1,41 @@
from ..tmdb import TMDb
class Provider(TMDb):
_urls = {
"regions": "/watch/providers/regions", # TODO:
"movie": "/watch/providers/movie", # TODO:
"tv": "/watch/providers/tv", # TODO:
}
def available_regions(self):
"""
Returns a list of all of the countries we have watch provider (OTT/streaming) data for.
:return:
"""
return self._request_obj(
self._urls["regions"],
key="results"
)
def movie_providers(self, region=None):
"""
Returns a list of the watch provider (OTT/streaming) data we have available for movies.
:return:
"""
return self._request_obj(
self._urls["movie"],
params="watch_region=%s" % region if region else "",
key="results"
)
def tv_providers(self, region=None):
"""
Returns a list of the watch provider (OTT/streaming) data we have available for TV series.
:return:
"""
return self._request_obj(
self._urls["tv"],
params="watch_region=%s" % region if region else "",
key="results"
)

View File

@ -0,0 +1,15 @@
from ..tmdb import TMDb
class Review(TMDb):
_urls = {
"details": "/review/%s",
}
def details(self, review_id):
"""
Get the primary person details by id.
:param review_id: int
:return:
"""
return self._request_obj(self._urls["details"] % review_id)

View File

@ -0,0 +1,144 @@
from ..tmdb import TMDb
try:
from urllib import quote
except ImportError:
from urllib.parse import quote
class Search(TMDb):
_urls = {
"companies": "/search/company",
"collections": "/search/collection",
"keywords": "/search/keyword",
"movies": "/search/movie",
"multi": "/search/multi",
"people": "/search/person",
"tv_shows": "/search/tv",
}
def companies(self, term, page=1):
"""
Search for companies.
:param term: str
:param page: int
:return:
"""
return self._request_obj(
self._urls["companies"],
params="query=%s&page=%s" % (quote(term), page),
key="results"
)
def collections(self, term, page=1):
"""
Search for collections.
:param term: str
:param page: int
:return:
"""
return self._request_obj(
self._urls["collections"],
params="query=%s&page=%s" % (quote(term), page),
key="results"
)
def keywords(self, term, page=1):
"""
Search for keywords.
:param term: str
:param page: int
:return:
"""
return self._request_obj(
self._urls["keywords"],
params="query=%s&page=%s" % (quote(term), page),
key="results"
)
def movies(self, term, adult=None, region=None, year=None, release_year=None, page=1):
"""
Search for movies.
:param term: str
:param adult: bool
:param region: str
:param year: int
:param release_year: int
:param page: int
:return:
"""
params = "query=%s&page=%s" % (quote(term), page)
if adult is not None:
params += "&include_adult=%s" % "true" if adult else "false"
if region is not None:
params += "&region=%s" % quote(region)
if year is not None:
params += "&year=%s" % year
if release_year is not None:
params += "&primary_release_year=%s" % release_year
return self._request_obj(
self._urls["movies"],
params=params,
key="results"
)
def multi(self, term, adult=None, region=None, page=1):
"""
Search multiple models in a single request.
Multi search currently supports searching for movies, tv shows and people in a single request.
:param term: str
:param adult: bool
:param region: str
:param page: int
:return:
"""
params = "query=%s&page=%s" % (quote(term), page)
if adult is not None:
params += "&include_adult=%s" % "true" if adult else "false"
if region is not None:
params += "&region=%s" % quote(region)
return self._request_obj(
self._urls["multi"],
params=params,
key="results"
)
def people(self, term, adult=None, region=None, page=1):
"""
Search for people.
:param term: str
:param adult: bool
:param region: str
:param page: int
:return:
"""
params = "query=%s&page=%s" % (quote(term), page)
if adult is not None:
params += "&include_adult=%s" % "true" if adult else "false"
if region is not None:
params += "&region=%s" % quote(region)
return self._request_obj(
self._urls["people"],
params=params,
key="results"
)
def tv_shows(self, term, adult=None, release_year=None, page=1):
"""
Search for a TV show.
:param term: str
:param adult: bool
:param release_year: int
:param page: int
:return:
"""
params = "query=%s&page=%s" % (quote(term), page)
if adult is not None:
params += "&include_adult=%s" % "true" if adult else "false"
if release_year is not None:
params += "&first_air_date_year=%s" % release_year
return self._request_obj(
self._urls["tv_shows"],
params=params,
key="results"
)

View File

@ -0,0 +1,133 @@
from ..tmdb import TMDb
class Season(TMDb):
_urls = {
"details": "/tv/%s/season/%s",
"account_states": "/tv/%s/season/%s/account_states",
"aggregate_credits": "/tv/%s/season/%s/aggregate_credits",
"changes": "/tv/season/%s/changes",
"credits": "/tv/%s/season/%s/credits",
"external_ids": "/tv/%s/season/%s/external_ids",
"images": "/tv/%s/season/%s/images",
"translations": "/tv/%s/season/%s/translations",
"videos": "/tv/%s/season/%s/videos",
}
def details(self, tv_id, season_num, append_to_response="videos,trailers,images,credits,translations"):
"""
Get the TV season details by id.
:param tv_id: int
:param season_num: int
:param append_to_response: str
:return:
"""
return self._request_obj(
self._urls["details"] % (tv_id, season_num),
params="append_to_response=%s" % append_to_response
)
def account_states(self, tv_id, season_num):
"""
Get all of the user ratings for the season's episodes.
:param tv_id: int
:param season_num: int
:return:
"""
return self._request_obj(
self._urls["account_states"] % (tv_id, season_num),
params="session_id=%s" % self.session_id,
key="results"
)
def aggregate_credits(self, tv_id, season_num):
"""
Get the aggregate credits for TV season.
This call differs from the main credits call in that it does not only return the season credits,
but rather is a view of all the cast & crew for all of the episodes belonging to a season.
:param tv_id: int
:param season_num: int
:return:
"""
return self._request_obj(self._urls["aggregate_credits"] % (tv_id, season_num))
def changes(self, season_id, start_date=None, end_date=None, page=1):
"""
Get the changes for a TV season. By default only the last 24 hours are returned.
You can query up to 14 days in a single query by using the start_date and end_date query parameters.
:param season_id: int
:param start_date: str
:param end_date: str
:param page: int
:return:
"""
params = "page=%s" % page
if start_date:
params += "&start_date=%s" % start_date
if end_date:
params += "&end_date=%s" % end_date
return self._request_obj(
self._urls["changes"] % season_id,
params=params,
key="changes"
)
def credits(self, tv_id, season_num):
"""
Get the credits for TV season.
:param tv_id: int
:param season_num: int
:return:
"""
return self._request_obj(self._urls["credits"] % (tv_id, season_num))
def external_ids(self, tv_id, season_num):
"""
Get the external ids for a TV season.
:param tv_id: int
:param season_num: int
:return:
"""
return self._request_obj(self._urls["external_ids"] % (tv_id, season_num))
def images(self, tv_id, season_num, include_image_language=None):
"""
Get the images that belong to a TV season.
:param tv_id: int
:param season_num: int
:param include_image_language: str
:return:
"""
return self._request_obj(
self._urls["images"] % (tv_id, season_num),
params="include_image_language=%s" % include_image_language if include_image_language else "",
key="posters"
)
def translations(self, tv_id, season_num):
"""
Get a list of the translations that exist for a TV show.
:param tv_id: int
:param season_num: int
"""
return self._request_obj(
self._urls["translations"] % (tv_id, season_num),
key="translations"
)
def videos(self, tv_id, season_num, include_video_language=None, page=1):
"""
Get the videos that have been added to a TV show.
:param tv_id: int
:param season_num: int
:param include_video_language: str
:param page: int
:return:
"""
params = "page=%s" % page
if include_video_language:
params += "&include_video_language=%s" % include_video_language
return self._request_obj(
self._urls["videos"] % (tv_id, season_num),
params=params
)

View File

@ -0,0 +1,75 @@
from ..tmdb import TMDb
class Trending(TMDb):
_urls = {"trending": "/trending/%s/%s"}
def _trending(self, media_type="all", time_window="day", page=1):
return self._request_obj(
self._urls["trending"] % (media_type, time_window),
params="page=%s" % page
)
def all_day(self, page=1):
"""
Get all daily trending
:param page: int
:return:
"""
return self._trending(media_type="all", time_window="day", page=page)
def all_week(self, page=1):
"""
Get all weekly trending
:param page: int
:return:
"""
return self._trending(media_type="all", time_window="week", page=page)
def movie_day(self, page=1):
"""
Get movie daily trending
:param page: int
:return:
"""
return self._trending(media_type="movie", time_window="day", page=page)
def movie_week(self, page=1):
"""
Get movie weekly trending
:param page: int
:return:
"""
return self._trending(media_type="movie", time_window="week", page=page)
def tv_day(self, page=1):
"""
Get tv daily trending
:param page: int
:return:
"""
return self._trending(media_type="tv", time_window="day", page=page)
def tv_week(self, page=1):
"""
Get tv weekly trending
:param page: int
:return:
"""
return self._trending(media_type="tv", time_window="week", page=page)
def person_day(self, page=1):
"""
Get person daily trending
:param page: int
:return:
"""
return self._trending(media_type="person", time_window="day", page=page)
def person_week(self, page=1):
"""
Get person weekly trending
:param page: int
:return:
"""
return self._trending(media_type="person", time_window="week", page=page)

View File

@ -0,0 +1,334 @@
from ..tmdb import TMDb
try:
from urllib import quote
except ImportError:
from urllib.parse import quote
class TV(TMDb):
_urls = {
"details": "/tv/%s",
"account_states": "/tv/%s/account_states",
"aggregate_credits": "/tv/%s/aggregate_credits",
"alternative_titles": "/tv/%s/alternative_titles",
"changes": "/tv/%s/changes",
"content_ratings": "/tv/%s/content_ratings",
"credits": "/tv/%s/credits",
"episode_groups": "/tv/%s/episode_groups",
"external_ids": "/tv/%s/external_ids",
"images": "/tv/%s/images",
"keywords": "/tv/%s/keywords",
"recommendations": "/tv/%s/recommendations",
"reviews": "/tv/%s/reviews",
"screened_theatrically": "/tv/%s/screened_theatrically",
"similar": "/tv/%s/similar",
"translations": "/tv/%s/translations",
"videos": "/tv/%s/videos",
"watch_providers": "/tv/%s/watch/providers",
"rate_tv_show": "/tv/%s/rating",
"delete_rating": "/tv/%s/rating",
"latest": "/tv/latest",
"airing_today": "/tv/airing_today",
"on_the_air": "/tv/on_the_air",
"popular": "/tv/popular",
"top_rated": "/tv/top_rated",
}
def details(self, tv_id, append_to_response="videos,trailers,images,credits,translations"):
"""
Get the primary TV show details by id.
:param tv_id: int
:param append_to_response: str
:return:
"""
return self._request_obj(
self._urls["details"] % tv_id,
params="append_to_response=%s" % append_to_response,
)
def account_states(self, tv_id):
"""
Grab the following account states for a session:
TV show rating, If it belongs to your watchlist, or If it belongs to your favourite list.
:param tv_id: int
:return:
"""
return self._request_obj(
self._urls["account_states"] % tv_id,
params="session_id=%s" % self.session_id
)
def aggregate_credits(self, tv_id):
"""
Get the aggregate credits (cast and crew) that have been added to a TV show.
This call differs from the main credits call in that it does not return the newest season but rather,
is a view of all the entire cast & crew for all episodes belonging to a TV show.
:param tv_id: int
:return:
"""
return self._request_obj(self._urls["aggregate_credits"] % tv_id)
def alternative_titles(self, tv_id):
"""
Returns all of the alternative titles for a TV show.
:param tv_id: int
:return:
"""
return self._request_obj(
self._urls["alternative_titles"] % tv_id,
key="results"
)
def changes(self, tv_id, start_date=None, end_date=None, page=1):
"""
Get the changes for a TV show. By default only the last 24 hours are returned.
You can query up to 14 days in a single query by using the start_date and end_date query parameters.
:param tv_id: int
:param start_date: str
:param end_date: str
:param page: int
"""
params = "page=%s" % page
if start_date:
params += "&start_date=%s" % start_date
if end_date:
params += "&end_date=%s" % end_date
return self._request_obj(
self._urls["changes"] % tv_id,
params=params,
key="changes"
)
def content_ratings(self, tv_id):
"""
Get the list of content ratings (certifications) that have been added to a TV show.
:param tv_id: int
:return:
"""
return self._request_obj(
self._urls["content_ratings"] % tv_id,
key="results"
)
def credits(self, tv_id):
"""
Get the credits (cast and crew) that have been added to a TV show.
:param tv_id: int
:return:
"""
return self._request_obj(self._urls["credits"] % tv_id)
def episode_groups(self, tv_id):
"""
Get all of the episode groups that have been created for a TV show.
:param tv_id: int
:return:
"""
return self._request_obj(
self._urls["episode_groups"] % tv_id,
key="results"
)
def external_ids(self, tv_id):
"""
Get the external ids for a TV show.
:param tv_id: int
:return:
"""
return self._request_obj(self._urls["external_ids"] % tv_id)
def images(self, tv_id, include_image_language=None):
"""
Get the images that belong to a TV show.
Querying images with a language parameter will filter the results.
If you want to include a fallback language (especially useful for backdrops)
you can use the include_image_language parameter.
This should be a comma separated value like so: include_image_language=en,null.
:param tv_id: int
:param include_image_language: str
:return:
"""
return self._request_obj(
self._urls["images"] % tv_id,
params="include_image_language=%s" % include_image_language if include_image_language else ""
)
def keywords(self, tv_id):
"""
Get the keywords that have been added to a TV show.
:param tv_id: int
:return:
"""
return self._request_obj(
self._urls["keywords"] % tv_id,
key="results"
)
def recommendations(self, tv_id, page=1):
"""
Get the list of TV show recommendations for this item.
:param tv_id: int
:param page: int
:return:
"""
return self._request_obj(
self._urls["recommendations"] % tv_id,
params="page=%s" % page,
key="results"
)
def reviews(self, tv_id, page=1):
"""
Get the reviews for a TV show.
:param tv_id: int
:param page: int
:return:
"""
return self._request_obj(
self._urls["reviews"] % tv_id,
params="page=%s" % page,
key="results"
)
def screened_theatrically(self, tv_id):
"""
Get a list of seasons or episodes that have been screened in a film festival or theatre.
:param tv_id: int
:return:
"""
return self._request_obj(
self._urls["screened_theatrically"] % tv_id,
key="results"
)
def similar(self, tv_id, page=1):
"""
Get the primary TV show details by id.
:param tv_id: int
:param page: int
:return:
"""
return self._request_obj(
self._urls["similar"] % tv_id,
params="page=%s" % page,
key="results"
)
def translations(self, tv_id):
"""
Get a list of the translations that exist for a TV show.
:param tv_id: int
:return:
"""
return self._request_obj(
self._urls["translations"] % tv_id,
key="translations"
)
def videos(self, tv_id, include_video_language=None, page=1):
"""
Get the videos that have been added to a TV show.
:param tv_id: int
:param include_video_language: str
:param page: int
:return:
"""
params = "page=%s" % page
if include_video_language:
params += "&include_video_language=%s" % include_video_language
return self._request_obj(
self._urls["videos"] % tv_id,
params=params
)
def watch_providers(self, tv_id):
"""
You can query this method to get a list of the availabilities per country by provider.
:param tv_id: int
:return:
"""
return self._request_obj(
self._urls["watch_providers"] % tv_id,
key="results"
)
def rate_tv_show(self, tv_id, rating):
"""
Rate a TV show.
:param tv_id: int
:param rating: float
"""
self._request_obj(
self._urls["rate_tv_show"] % tv_id,
params="session_id=%s" % self.session_id,
method="POST",
json={"value": rating}
)
def delete_rating(self, tv_id):
"""
Remove your rating for a TV show.
:param tv_id: int
"""
self._request_obj(
self._urls["delete_rating"] % tv_id,
params="session_id=%s" % self.session_id,
method="DELETE"
)
def latest(self):
"""
Get the most newly created TV show. This is a live response and will continuously change.
:return:
"""
return self._request_obj(self._urls["latest"])
def airing_today(self, page=1):
"""
Get a list of TV shows that are airing today.
This query is purely day based as we do not currently support airing times.
:param page: int
:return:
"""
return self._request_obj(
self._urls["airing_today"],
params="page=%s" % page,
key="results"
)
def on_the_air(self, page=1):
"""
Get a list of shows that are currently on the air.
:param page:
:return:
"""
return self._request_obj(
self._urls["on_the_air"],
params="page=%s" % page,
key="results"
)
def popular(self, page=1):
"""
Get a list of the current popular TV shows on TMDb. This list updates daily.
:param page:
:return:
"""
return self._request_obj(
self._urls["popular"],
params="page=%s" % page,
key="results"
)
def top_rated(self, page=1):
"""
Get a list of the top rated TV shows on TMDb.
:param page:
:return:
"""
return self._request_obj(
self._urls["top_rated"],
params="page=%s" % page,
key="results"
)

View File

@ -0,0 +1,190 @@
# -*- coding: utf-8 -*-
import logging
import os
import time
import requests
import requests.exceptions
from .as_obj import AsObj
from .exceptions import TMDbException
from functools import lru_cache
logger = logging.getLogger(__name__)
class TMDb(object):
_session = None
TMDB_API_KEY = "TMDB_API_KEY"
TMDB_LANGUAGE = "TMDB_LANGUAGE"
TMDB_SESSION_ID = "TMDB_SESSION_ID"
TMDB_WAIT_ON_RATE_LIMIT = "TMDB_WAIT_ON_RATE_LIMIT"
TMDB_DEBUG_ENABLED = "TMDB_DEBUG_ENABLED"
TMDB_CACHE_ENABLED = "TMDB_CACHE_ENABLED"
TMDB_PROXIES = "TMDB_PROXIES"
REQUEST_CACHE_MAXSIZE = None
def __init__(self, obj_cached=True, session=None):
if self.__class__._session is None or session is not None:
self.__class__._session = requests.Session() if session is None else session
self._base = "https://api.themoviedb.org/3"
self._remaining = 40
self._reset = None
self.obj_cached = obj_cached
if os.environ.get(self.TMDB_LANGUAGE) is None:
os.environ[self.TMDB_LANGUAGE] = "en-US"
@property
def page(self):
return os.environ["page"]
@property
def total_results(self):
return os.environ["total_results"]
@property
def total_pages(self):
return os.environ["total_pages"]
@property
def api_key(self):
return os.environ.get(self.TMDB_API_KEY)
@property
def proxies(self):
proxy = os.environ.get(self.TMDB_PROXIES)
if proxy is not None:
proxy = eval(proxy)
return proxy
@proxies.setter
def proxies(self, proxies):
if proxies is not None:
os.environ[self.TMDB_PROXIES] = str(proxies)
@api_key.setter
def api_key(self, api_key):
os.environ[self.TMDB_API_KEY] = str(api_key)
@property
def language(self):
return os.environ.get(self.TMDB_LANGUAGE)
@language.setter
def language(self, language):
os.environ[self.TMDB_LANGUAGE] = language
@property
def has_session(self):
return True if os.environ.get(self.TMDB_SESSION_ID) else False
@property
def session_id(self):
if not os.environ.get(self.TMDB_SESSION_ID):
raise TMDbException("Must Authenticate to create a session run Authentication(username, password)")
return os.environ.get(self.TMDB_SESSION_ID)
@session_id.setter
def session_id(self, session_id):
os.environ[self.TMDB_SESSION_ID] = session_id
@property
def wait_on_rate_limit(self):
if os.environ.get(self.TMDB_WAIT_ON_RATE_LIMIT) == "False":
return False
else:
return True
@wait_on_rate_limit.setter
def wait_on_rate_limit(self, wait_on_rate_limit):
os.environ[self.TMDB_WAIT_ON_RATE_LIMIT] = str(wait_on_rate_limit)
@property
def debug(self):
if os.environ.get(self.TMDB_DEBUG_ENABLED) == "True":
return True
else:
return False
@debug.setter
def debug(self, debug):
os.environ[self.TMDB_DEBUG_ENABLED] = str(debug)
@property
def cache(self):
if os.environ.get(self.TMDB_CACHE_ENABLED) == "False":
return False
else:
return True
@cache.setter
def cache(self, cache):
os.environ[self.TMDB_CACHE_ENABLED] = str(cache)
@staticmethod
@lru_cache(maxsize=REQUEST_CACHE_MAXSIZE)
def cached_request(method, url, data, json, proxies):
return requests.request(method, url, data=data, json=json, proxies=proxies)
def cache_clear(self):
return self.cached_request.cache_clear()
def _request_obj(self, action, params="", call_cached=True, method="GET", data=None, json=None, key=None):
if self.api_key is None or self.api_key == "":
raise TMDbException("No API key found.")
url = "%s%s?api_key=%s&%s&language=%s" % (
self._base,
action,
self.api_key,
params,
self.language,
)
if self.cache and self.obj_cached and call_cached and method != "POST":
req = self.cached_request(method, url, data, json, self.proxies)
else:
req = self.__class__._session.request(method, url, data=data, json=json, proxies=self.proxies)
headers = req.headers
if "X-RateLimit-Remaining" in headers:
self._remaining = int(headers["X-RateLimit-Remaining"])
if "X-RateLimit-Reset" in headers:
self._reset = int(headers["X-RateLimit-Reset"])
if self._remaining < 1:
current_time = int(time.time())
sleep_time = self._reset - current_time
if self.wait_on_rate_limit:
logger.warning("Rate limit reached. Sleeping for: %d" % sleep_time)
time.sleep(abs(sleep_time))
return self._request_obj(action, params, call_cached, method, data, json, key)
else:
raise TMDbException("Rate limit reached. Try again in %d seconds." % sleep_time)
json = req.json()
if "page" in json:
os.environ["page"] = str(json["page"])
if "total_results" in json:
os.environ["total_results"] = str(json["total_results"])
if "total_pages" in json:
os.environ["total_pages"] = str(json["total_pages"])
if self.debug:
logger.info(json)
logger.info(self.cached_request.cache_info())
if "errors" in json:
raise TMDbException(json["errors"])
if "success" in json and json["success"] is False:
raise TMDbException(json["status_message"])
return AsObj(json, key=key)

View File

@ -30,3 +30,12 @@ class TmdbEpisode(BaseModel):
vote_average: Optional[float] = None vote_average: Optional[float] = None
crew: Optional[list] = [] crew: Optional[list] = []
guest_stars: Optional[list] = [] guest_stars: Optional[list] = []
class TmdbCast(BaseModel):
id: Optional[int] = None
name: Optional[str] = None
character: Optional[str] = None
profile_path: Optional[str] = None
gender: Optional[int] = None
original_name: Optional[str] = None

View File

@ -16,7 +16,6 @@ anitopy~=2.1.1
requests~=2.31.0 requests~=2.31.0
urllib3~=2.0.2 urllib3~=2.0.2
lxml~=4.9.2 lxml~=4.9.2
tmdbv3api~=1.7.7
pyquery~=2.0.0 pyquery~=2.0.0
ruamel.yaml~=0.17.31 ruamel.yaml~=0.17.31
APScheduler~=3.10.1 APScheduler~=3.10.1

View File

@ -1,7 +1,6 @@
import unittest import unittest
from tests.test_cookiecloud import CookieCloudTest from tests.test_cookiecloud import CookieCloudTest
from tests.test_doubansync import DoubanSyncTest
from tests.test_filter import FilterTest from tests.test_filter import FilterTest
from tests.test_metainfo import MetaInfoTest from tests.test_metainfo import MetaInfoTest
from tests.test_recognize import RecognizeTest from tests.test_recognize import RecognizeTest
@ -11,17 +10,15 @@ if __name__ == '__main__':
suite = unittest.TestSuite() suite = unittest.TestSuite()
# 测试过滤器 # 测试过滤器
# suite.addTest(FilterTest('test_filter')) suite.addTest(FilterTest('test_filter'))
# 测试名称识别 # 测试名称识别
suite.addTest(MetaInfoTest('test_metainfo')) suite.addTest(MetaInfoTest('test_metainfo'))
# 测试媒体识别 # 测试媒体识别
# suite.addTest(RecognizeTest('test_recognize')) suite.addTest(RecognizeTest('test_recognize'))
# 测试CookieCloud同步 # 测试CookieCloud同步
# suite.addTest(CookieCloudTest('test_cookiecloud')) suite.addTest(CookieCloudTest('test_cookiecloud'))
# 测试文件转移 # 测试文件转移
# suite.addTest(TransferTest('test_transfer')) suite.addTest(TransferTest('test_transfer'))
# 测试豆瓣同步
# suite.addTest(DoubanSyncTest('test_doubansync'))
# 运行测试 # 运行测试
runner = unittest.TextTestRunner() runner = unittest.TextTestRunner()

View File

@ -1,17 +0,0 @@
# -*- coding: utf-8 -*-
from unittest import TestCase
from app.chain.douban import DoubanChain
class DoubanSyncTest(TestCase):
def setUp(self) -> None:
pass
def tearDown(self) -> None:
pass
@staticmethod
def test_doubansync():
DoubanChain().sync()