]> git.ipfire.org Git - thirdparty/tvheadend.git/commitdiff
fanart: Pass programme title language to grabber so it can use it.
authorE.Smith <31170571+azlm8t@users.noreply.github.com>
Fri, 5 Oct 2018 01:11:13 +0000 (02:11 +0100)
committerJaroslav Kysela <perex@perex.cz>
Mon, 8 Oct 2018 12:01:16 +0000 (14:01 +0200)
lib/py/tvh/tv_meta_tmdb.py
lib/py/tvh/tv_meta_tvdb.py
support/tvhmeta

index 936b6277eb7223028b09204c88c00b6993fa469d..e01f8b3c8a9efae40590c95f11b0deffa3dc082a 100755 (executable)
@@ -25,7 +25,7 @@ def get_capabilities():
     return {
         "name": "tv_meta_tmdb",
         "version": "0.1",
-        "description": "Grab movie details from TMDB.",
+        "description": "Grab movie/tv details from TMDB.",
         "supports_tv": True,
         "supports_movie": True,
         "required_config" : {
@@ -47,7 +47,7 @@ class Tv_meta_tmdb(object):
       self.poster_size = "w342" if 'poster-size' not in args else args["poster-size"]
       # Fanart sizes: w300, w780, w1280, original
       self.fanart_size = "original" if 'poster-size' not in args else args["fanart-size"]
-      self.languages = "en"
+      self.languages = None
       if 'languages' in args and args["languages"] is not None:
           self.languages = args["languages"]
 
@@ -86,8 +86,8 @@ class Tv_meta_tmdb(object):
   def _search_tv(self, title, year, lang = "en"):
       return self._search_common(title, year, lang, "search/tv", "first_air_date_year")
 
-  def _search_all_languages_common(self, title, year, cb):
-      for lang in self.languages.split(","):
+  def _search_all_languages_common(self, title, year, language, cb):
+      for lang in language.split(","):
           try:
               res = cb(title, year, lang)
               if res:
@@ -97,17 +97,17 @@ class Tv_meta_tmdb(object):
               pass
       return None
 
-  def _search_movie_all_languages(self, title, year):
-      return self._search_all_languages_common(title, year, self._search_movie)
+  def _search_movie_all_languages(self, title, year, language):
+      return self._search_all_languages_common(title, year, language, self._search_movie)
 
-  def _search_tv_all_languages(self, title, year):
-      return self._search_all_languages_common(title, year, self._search_tv)
+  def _search_tv_all_languages(self, title, year, language):
+      return self._search_all_languages_common(title, year, language, self._search_tv)
 
-  def _search_all_languages(self, title, year, cb1, cb2):
-      res = cb1(title, year)
+  def _search_all_languages(self, title, year, language, cb1, cb2):
+      res = cb1(title, year, language)
       if res is None and cb2 is not None:
           logging.debug("Trying again with other type")
-          res = cb2(title, year)
+          res = cb2(title, year, language)
       return res
 
 
@@ -115,6 +115,12 @@ class Tv_meta_tmdb(object):
     logging.debug("Fetching with details %s " % args);
     title = args["title"]
     year = args["year"]
+    if self.languages:          # User override
+        language = self.languages
+    elif "language" in args:
+        language = args["language"]
+    else:
+        language = "en"
     type = "movie" if 'type' not in args else args["type"]
 
     if title is None:
@@ -126,9 +132,9 @@ class Tv_meta_tmdb(object):
     # tv show instead.  We don't do the opposite for tv shows since
     # they never get identified as a movie due to season and episode.
     if type is None or type == 'movie':
-        res = self._search_all_languages(title, year, self._search_movie_all_languages, self._search_tv_all_languages)
+        res = self._search_all_languages(title, year, language, self._search_movie_all_languages, self._search_tv_all_languages)
     else:
-        res = self._search_all_languages(title, year, self._search_tv_all_languages,  None)
+        res = self._search_all_languages(title, year, language, self._search_tv_all_languages,  None)
     logging.debug(res)
     if res is None or len(res) == 0:
         logging.info("Could not find any match for %s" % title);
index 59da74877317ef7c5cade65c3a0e518405814d16..64bf96d77b3d786e637da6a17ef89a66ba138846 100755 (executable)
@@ -34,7 +34,7 @@ def get_capabilities():
     return {
         "name": "tv_meta_tvdb",
         "version": "0.1",
-        "description": "Grab movie details from TVDB.",
+        "description": "Grab tv details from TVDB.",
         "supports_tv": True,
         "supports_movie": False,
         "required_config" : {
@@ -44,6 +44,20 @@ def get_capabilities():
 
 
 
+class AcceptLanguage(object):
+    """Add a language to the session headers and remove after scope."""
+    def __init__(self, session, language):
+        self.session = session
+        self.language = language
+
+    def __enter__(self):
+        self.session.headers.update({'Accept-Language': self.language})
+        return self
+
+    def __exit__(self, exc_type, exc_value, tb):
+        self.session.headers.pop('Accept-Language', None)
+
+
 class Tvdb(object):
     """Basic tvdb wrapper.
 
@@ -57,7 +71,7 @@ Exceptions are thrown to indicate data could not be retrieved.
               logging.critical("Need a tvdb-"  + arg + ". No lookup available with this module.")
               raise RuntimeError("Need a tvdb-" + arg);
 
-      self.languages = "en"
+      self.languages = None
       # 2 character language code. At time of writing, valid languages on the server are:
       # ['da', 'fi', 'nl', 'de', 'it', 'es', 'fr', 'pl', 'hu', 'el', 'tr', 'ru', 'he', 'ja', 'pt', 'zh', 'cs', 'sl', 'hr', 'ko', 'en', 'sv', 'no']
       # We accept a csv of languages.
@@ -77,8 +91,7 @@ Exceptions are thrown to indicate data could not be retrieved.
       self.auth = self._get_auth()
 
     def _get_headers(self):
-        headers = { 'Content-Type': 'application/json',
-                    'Accept-Language': self.languages }
+        headers = { 'Content-Type': 'application/json' }
         if self.auth:
             headers['Authorization'] = 'Bearer ' + self.auth
         return headers
@@ -92,13 +105,14 @@ Exceptions are thrown to indicate data could not be retrieved.
         self.session.headers.update({'Authorization' : 'Bearer ' + token})
         return token
 
-    def get_tvdbid(self, title):
+    def get_tvdbid(self, title, language = "en"):
         """Return episode tvdb id"""
-        r=self.session.get(
-            self.base_url + 'search/series',
-            timeout = self.timeout,
-            params={'name': title})
-        return r.json()['data'][0]['id']
+        with AcceptLanguage(self.session, language):
+            r=self.session.get(
+                self.base_url + 'search/series',
+                timeout = self.timeout,
+                params={'name': title})
+            return r.json()['data'][0]['id']
 
     def _get_art(self, title = None, tvdbid = None, artworkType = 'fanart'):
         if tvdbid is None:
@@ -117,17 +131,22 @@ Exceptions are thrown to indicate data could not be retrieved.
             filename = "https://thetvdb.com/banners/" + filename
         return filename
 
-    def get_fanart(self, title = None, tvdbid = None):
-        return self._get_art(title = title, tvdbid = tvdbid, artworkType = 'fanart')
+    def get_fanart(self, title = None, tvdbid = None, language = "en"):
+        with AcceptLanguage(self.session, language):
+            return self._get_art(title = title, tvdbid = tvdbid, artworkType = 'fanart')
 
-    def get_poster(self, title = None, tvdbid = None):
-        return self._get_art(title = title, tvdbid = tvdbid, artworkType = 'poster')
+    def get_poster(self, title = None, tvdbid = None, languague = "en"):
+        with AcceptLanguage(self.session, language):
+            return self._get_art(title = title, tvdbid = tvdbid, artworkType = 'poster')
 
 
 class Tv_meta_tvdb(object):
 
   def __init__(self, args):
       self.tvdb = Tvdb(args)
+      self.languages = None
+      if 'languages' in args and args["languages"] is not None:
+          self.languages = args["languages"]
 
   def fetch_details(self, args):
     logging.debug("Fetching with details %s " % args);
@@ -138,6 +157,13 @@ class Tv_meta_tvdb(object):
         logging.critical("Need a title");
         raise RuntimeError("Need a title");
 
+    if self.languages is not None:
+        language = self.languages
+    elif "language" in args:
+        language = args["language"]
+    else:
+        language = "en"
+
     tvdbid = None
     query = title
 
@@ -145,13 +171,13 @@ class Tv_meta_tvdb(object):
     if year is not None:
         query = query + " (%s)" % year
         try:
-            tvdbid = self.tvdb.get_tvdbid(query)
+            tvdbid = self.tvdb.get_tvdbid(query, language)
         except:
             pass
 
     if tvdbid is None:
         try:
-            tvdbid = self.tvdb.get_tvdbid(title)
+            tvdbid = self.tvdb.get_tvdbid(title, language)
         except:
             logging.info("Could not find any matching episode for " + title);
             raise LookupError("Could not find match for " + title);
@@ -159,12 +185,12 @@ class Tv_meta_tvdb(object):
     poster = fanart = None
     #  We don't want failure to process one image to affect the other.
     try:
-        poster = self.tvdb.get_poster(tvdbid = tvdbid)
+        poster = self.tvdb.get_poster(tvdbid = tvdbid, language=language)
     except Exception:
         pass
 
     try:
-        fanart = self.tvdb.get_fanart(tvdbid = tvdbid)
+        fanart = self.tvdb.get_fanart(tvdbid = tvdbid, language=language)
     except:
         pass
 
index 898866a5cb7a644f0451621cefc557cda65d3927..ae205fee9c22f7e27311a388b5e2f6317d65c1b4 100755 (executable)
@@ -162,6 +162,55 @@ class TvhMeta(object):
     replace = self.request("api/idnode/save", new_data)
     return replace
 
+  def _lang3_to_lang2(self, lang3):
+    """Convert from ISO 639-2 (3 letter code) + region to ISO 639-1 (2 letter code)"""
+    # This is taken from tvh_locale.c, but "_" is replaced with "-" on the mapped side.
+    iso_map = {
+    "ach":    "ach",
+    "ady":    "ady",
+    "ara":    "ar",
+    "bul":    "bg",
+    "cze":    "cs",
+    "dan":    "da",
+    "ger":    "de",
+    "eng":    "en-US",
+    "eng_GB": "en-GB",
+    "eng_US": "en-US",
+    "spa":    "es",
+    "est":    "et",
+    "per":    "fa",
+    "fin":    "fi",
+    "fre":    "fr",
+    "heb":    "he",
+    "hrv":    "hr",
+    "hun":    "hu",
+    "ita":    "it",
+    "kor":    "ko",
+    "lav":    "lv",
+    "lit":    "lt",
+    "dut":    "nl",
+    "nor":    "no",
+    "pol":    "pl",
+    "por":    "pt",
+    "rum":    "ro",
+    "rus":    "ru",
+    "slv":    "sl",
+    "slo":    "sk",
+    "srp":    "sr",
+    "alb":    "sq",
+    "swe":    "sv",
+    "tur":    "tr",
+    "ukr":    "uk",
+    "chi":    "zh",
+    "chi_CN": "zh-Hans",
+    }
+    try:
+      return iso_map[lang]
+    except:
+      # No mapping. Return "English" as default.
+      return "en"
+
+
   def fetch_and_persist_artwork(self, uuid, force_refresh, modules_movie, modules_tv):
     """Fetch artwork for the given uuid."""
     data = urlencode(
@@ -269,6 +318,7 @@ class TvhMeta(object):
               type = "movie"
             art = obj.fetch_details({
               "title": title,
+              "language": self._lang3_to_lang2(lang),
               "year": year,
               "type": type,
               "episode_disp": episode_disp, # @todo Need to break this out in to season/episode, maybe subtitle too.