Plex-Meta-Manager/modules/tvdb.py

170 lines
7.8 KiB
Python
Raw Normal View History

2021-02-24 06:42:58 +00:00
import logging, requests
2021-01-20 21:37:59 +00:00
from lxml import html
from modules import util
from modules.util import Failed
from retrying import retry
logger = logging.getLogger("Plex Meta Manager")
2021-03-30 05:50:53 +00:00
builders = [
"tvdb_list",
"tvdb_list_details",
"tvdb_movie",
"tvdb_movie_details",
"tvdb_show",
"tvdb_show_details"
]
2021-01-20 21:37:59 +00:00
class TVDbObj:
def __init__(self, tvdb_url, language, is_movie, TVDb):
tvdb_url = tvdb_url.strip()
if not is_movie and tvdb_url.startswith((TVDb.series_url, TVDb.alt_series_url, TVDb.series_id_url)):
self.media_type = "Series"
elif is_movie and tvdb_url.startswith((TVDb.movies_url, TVDb.alt_movies_url, TVDb.movie_id_url)):
self.media_type = "Movie"
else:
2021-02-24 06:44:06 +00:00
raise Failed(f"TVDb Error: {tvdb_url} must begin with {TVDb.movies_url if is_movie else TVDb.series_url}")
2021-01-20 21:37:59 +00:00
2021-05-07 19:53:54 +00:00
response = TVDb._request(tvdb_url, language)
2021-02-24 06:44:06 +00:00
results = response.xpath(f"//*[text()='TheTVDB.com {self.media_type} ID']/parent::node()/span/text()")
2021-01-20 21:37:59 +00:00
if len(results) > 0:
self.id = int(results[0])
2021-02-24 06:42:58 +00:00
elif tvdb_url.startswith(TVDb.movie_id_url):
raise Failed(f"TVDb Error: Could not find a TVDb Movie using TVDb Movie ID: {tvdb_url[len(TVDb.movie_id_url):]}")
2021-02-24 06:42:58 +00:00
elif tvdb_url.startswith(TVDb.series_id_url):
2021-02-24 06:44:06 +00:00
raise Failed(f"TVDb Error: Could not find a TVDb Series using TVDb Series ID: {tvdb_url[len(TVDb.series_id_url):]}")
2021-01-20 21:37:59 +00:00
else:
2021-02-24 06:44:06 +00:00
raise Failed(f"TVDb Error: Could not find a TVDb {self.media_type} ID at the URL {tvdb_url}")
2021-01-20 21:37:59 +00:00
2021-01-21 21:42:31 +00:00
results = response.xpath("//div[@class='change_translation_text' and @data-language='eng']/@data-title")
2021-01-20 21:37:59 +00:00
if len(results) > 0 and len(results[0]) > 0:
self.title = results[0]
else:
2021-02-24 06:44:06 +00:00
raise Failed(f"TVDb Error: Name not found from TVDb URL: {tvdb_url}")
2021-01-20 21:37:59 +00:00
2021-01-21 21:42:31 +00:00
results = response.xpath("//div[@class='row hidden-xs hidden-sm']/div/img/@src")
2021-01-20 21:37:59 +00:00
self.poster_path = results[0] if len(results) > 0 and len(results[0]) > 0 else None
2021-03-08 17:02:40 +00:00
results = response.xpath("(//h2[@class='mt-4' and text()='Backgrounds']/following::div/a/@href)[1]")
self.background_path = results[0] if len(results) > 0 and len(results[0]) > 0 else None
results = response.xpath("//div[@class='block']/div[not(@style='display:none')]/p/text()")
2021-03-08 19:53:05 +00:00
self.summary = results[0] if len(results) > 0 and len(results[0]) > 0 else None
2021-03-08 17:02:40 +00:00
2021-01-20 21:37:59 +00:00
tmdb_id = None
if is_movie:
2021-01-21 21:42:31 +00:00
results = response.xpath("//*[text()='TheMovieDB.com']/@href")
2021-01-20 21:37:59 +00:00
if len(results) > 0:
2021-04-22 23:51:03 +00:00
try:
tmdb_id = util.regex_first_int(results[0], "TMDb ID")
2021-05-09 05:37:45 +00:00
except Failed:
pass
if tmdb_id is None:
2021-01-21 21:42:31 +00:00
results = response.xpath("//*[text()='IMDB']/@href")
2021-01-20 21:37:59 +00:00
if len(results) > 0:
2021-04-22 23:51:03 +00:00
try:
2021-05-08 23:49:55 +00:00
tmdb_id = TVDb.config.Convert.imdb_to_tmdb(util.get_id_from_imdb_url(results[0]), fail=True)
2021-05-09 05:37:45 +00:00
except Failed:
pass
if tmdb_id is None:
raise Failed(f"TVDB Error: No TMDb ID found for {self.title}")
2021-01-20 21:37:59 +00:00
self.tmdb_id = tmdb_id
self.tvdb_url = tvdb_url
self.language = language
self.is_movie = is_movie
self.TVDb = TVDb
class TVDbAPI:
2021-03-05 20:33:24 +00:00
def __init__(self, config):
2021-03-02 21:41:34 +00:00
self.config = config
2021-01-20 21:37:59 +00:00
self.site_url = "https://www.thetvdb.com"
self.alt_site_url = "https://thetvdb.com"
2021-02-24 06:44:06 +00:00
self.list_url = f"{self.site_url}/lists/"
self.alt_list_url = f"{self.alt_site_url}/lists/"
self.series_url = f"{self.site_url}/series/"
self.alt_series_url = f"{self.alt_site_url}/series/"
self.movies_url = f"{self.site_url}/movies/"
self.alt_movies_url = f"{self.alt_site_url}/movies/"
self.series_id_url = f"{self.site_url}/dereferrer/series/"
self.movie_id_url = f"{self.site_url}/dereferrer/movie/"
2021-01-20 21:37:59 +00:00
2021-03-08 19:53:05 +00:00
def get_movie_or_series(self, language, tvdb_url, is_movie):
return self.get_movie(language, tvdb_url) if is_movie else self.get_series(language, tvdb_url)
def get_series(self, language, tvdb_url):
try:
tvdb_url = f"{self.series_id_url}{int(tvdb_url)}"
except ValueError:
pass
2021-01-20 21:37:59 +00:00
return TVDbObj(tvdb_url, language, False, self)
2021-03-08 19:53:05 +00:00
def get_movie(self, language, tvdb_url):
try:
tvdb_url = f"{self.movie_id_url}{int(tvdb_url)}"
except ValueError:
pass
2021-01-20 21:37:59 +00:00
return TVDbObj(tvdb_url, language, True, self)
2021-03-08 19:53:05 +00:00
def get_list_description(self, tvdb_url, language):
2021-05-07 19:53:54 +00:00
description = self._request(tvdb_url, language).xpath("//div[@class='block']/div[not(@style='display:none')]/p/text()")
2021-03-08 17:02:40 +00:00
return description[0] if len(description) > 0 and len(description[0]) > 0 else ""
2021-05-07 19:53:54 +00:00
def _ids_from_url(self, tvdb_url, language):
2021-01-20 21:37:59 +00:00
show_ids = []
movie_ids = []
tvdb_url = tvdb_url.strip()
if tvdb_url.startswith((self.list_url, self.alt_list_url)):
try:
2021-05-07 19:53:54 +00:00
items = self._request(tvdb_url, language).xpath("//div[@class='col-xs-12 col-sm-12 col-md-8 col-lg-8 col-md-pull-4']/div[@class='row']")
2021-01-20 21:37:59 +00:00
for item in items:
title = item.xpath(".//div[@class='col-xs-12 col-sm-9 mt-2']//a/text()")[0]
item_url = item.xpath(".//div[@class='col-xs-12 col-sm-9 mt-2']//a/@href")[0]
if item_url.startswith("/series/"):
2021-04-22 23:51:03 +00:00
try:
show_ids.append(self.get_series(language, f"{self.site_url}{item_url}").id)
except Failed as e:
logger.error(f"{e} for series {title}")
2021-01-20 21:37:59 +00:00
elif item_url.startswith("/movies/"):
try:
2021-03-08 19:53:05 +00:00
tmdb_id = self.get_movie(language, f"{self.site_url}{item_url}").tmdb_id
2021-04-22 23:51:03 +00:00
if tmdb_id:
movie_ids.append(tmdb_id)
else:
raise Failed(f"TVDb Error: TMDb ID not found from TVDb URL: {tvdb_url}")
2021-01-20 21:37:59 +00:00
except Failed as e:
2021-02-24 06:44:06 +00:00
logger.error(f"{e} for series {title}")
2021-01-20 21:37:59 +00:00
else:
2021-02-24 06:44:06 +00:00
logger.error(f"TVDb Error: Skipping Movie: {title}")
2021-01-20 21:37:59 +00:00
if len(show_ids) > 0 or len(movie_ids) > 0:
return movie_ids, show_ids
2021-02-24 06:44:06 +00:00
raise Failed(f"TVDb Error: No TVDb IDs found at {tvdb_url}")
2021-02-24 06:42:58 +00:00
except requests.exceptions.MissingSchema:
2021-01-20 21:37:59 +00:00
util.print_stacktrace()
2021-02-24 06:44:06 +00:00
raise Failed(f"TVDb Error: URL Lookup Failed for {tvdb_url}")
2021-01-20 21:37:59 +00:00
else:
2021-02-24 06:44:06 +00:00
raise Failed(f"TVDb Error: {tvdb_url} must begin with {self.list_url}")
2021-01-20 21:37:59 +00:00
@retry(stop_max_attempt_number=6, wait_fixed=10000)
2021-05-07 19:53:54 +00:00
def _request(self, url, language):
2021-01-21 21:42:31 +00:00
return html.fromstring(requests.get(url, headers={"Accept-Language": language}).content)
2021-01-20 21:37:59 +00:00
2021-05-09 05:37:45 +00:00
def get_items(self, method, data, language):
2021-01-20 21:37:59 +00:00
pretty = util.pretty_names[method] if method in util.pretty_names else method
show_ids = []
movie_ids = []
2021-05-09 05:37:45 +00:00
logger.info(f"Processing {pretty}: {data}")
2021-01-20 21:37:59 +00:00
if method == "tvdb_show":
2021-03-08 19:53:05 +00:00
show_ids.append(self.get_series(language, data).id)
2021-01-20 21:37:59 +00:00
elif method == "tvdb_movie":
2021-05-09 05:37:45 +00:00
movie_ids.append(self.get_movie(language, data).tmdb_id)
2021-01-20 21:37:59 +00:00
elif method == "tvdb_list":
2021-05-07 19:53:54 +00:00
tmdb_ids, tvdb_ids = self._ids_from_url(data, language)
2021-01-20 21:37:59 +00:00
movie_ids.extend(tmdb_ids)
show_ids.extend(tvdb_ids)
else:
2021-02-24 06:44:06 +00:00
raise Failed(f"TVDb Error: Method {method} not supported")
2021-05-24 03:38:46 +00:00
logger.debug("")
2021-05-09 05:37:45 +00:00
logger.debug(f"TMDb IDs Found: {movie_ids}")
logger.debug(f"TVDb IDs Found: {show_ids}")
2021-01-20 21:37:59 +00:00
return movie_ids, show_ids