From c59d6bd52ab8a912812282d15ff5bcbfd6ea4b2d Mon Sep 17 00:00:00 2001 From: Jason Lyu Date: Thu, 14 Dec 2023 05:53:06 +0800 Subject: [PATCH] Improve: update inner logic (#16) --- Contents/Code/__init__.py | 78 +++++++++++++++++-------------------- Contents/Code/api_client.py | 2 +- Contents/Code/utils.py | 44 ++++++++++++++++++++- 3 files changed, 79 insertions(+), 45 deletions(-) diff --git a/Contents/Code/__init__.py b/Contents/Code/__init__.py index 3cc9b48..6a263bc 100644 --- a/Contents/Code/__init__.py +++ b/Contents/Code/__init__.py @@ -1,9 +1,9 @@ # -*- coding: utf-8 -*- -from api_client import api, MovieSearchResult -from constants import * # import all constants +import utils +from api_client import api +from constants import * from provider_id import ProviderID -from utils import parse_list, parse_table, table_substitute, has_chinese_subtitle try: # Python 2 from urllib import unquote @@ -90,12 +90,6 @@ def get_review_image(rating): if not rating or float(rating) >= 6.0 \ else 'rottentomatoes://image.review.rotten' - @staticmethod - def get_media_attributes(obj, attr, fn=lambda x: x): - if not hasattr(obj, 'all_parts'): - return () - return [fn(getattr(part, attr)) for part in obj.all_parts() if hasattr(part, attr)] - @staticmethod def get_actor_image_url(name): @@ -148,7 +142,7 @@ def translate_text(text, lang, fallback=None): return translated_text engine = Prefs[KEY_TRANSLATION_ENGINE] - params = parse_table(Prefs[KEY_TRANSLATION_ENGINE_PARAMETERS], origin_key=True) + params = utils.parse_table(Prefs[KEY_TRANSLATION_ENGINE_PARAMETERS], origin_key=True) try: translated_text = api.translate(q=text, to=lang, engine=engine, @@ -181,7 +175,7 @@ def translate_reviews(self, reviews, lang): def search(self, results, media, lang, manual=False): position = None - search_results = [] # type: list[MovieSearchResult] + search_results = [] # issued by scanning or auto match if (not manual or media.openSubtitlesHash) \ @@ -204,7 +198,7 @@ def search(self, results, media, lang, manual=False): # apply movie provider filter if Prefs[KEY_ENABLE_MOVIE_PROVIDER_FILTER]: - movie_provider_filter = parse_list(Prefs[KEY_MOVIE_PROVIDER_FILTER]) + movie_provider_filter = utils.parse_list(Prefs[KEY_MOVIE_PROVIDER_FILTER]) if movie_provider_filter: search_results = [i for i in search_results if i.provider.upper() in movie_provider_filter] @@ -258,8 +252,8 @@ def update(self, metadata, media, lang, force=False): # Detect Chinese Subtitles chinese_subtitle_on = False - for filename in self.get_media_attributes(media, 'file'): - if has_chinese_subtitle(filename): + for filename in (p.file for p in utils.extra_media_parts(media)): + if utils.has_chinese_subtitle(filename): chinese_subtitle_on = True m.genres.append(CHINESE_SUBTITLE) Log.Debug('Chinese subtitle detected for {filename}' @@ -271,12 +265,14 @@ def update(self, metadata, media, lang, force=False): self.convert_to_real_actor_names(m) if Prefs[KEY_ENABLE_ACTOR_SUBSTITUTION] and Prefs[KEY_ACTOR_SUBSTITUTION]: - m.actors = table_substitute(parse_table(Prefs[KEY_ACTOR_SUBSTITUTION], - sep='\n', b64=True), m.actors) + m.actors = utils.table_substitute( + utils.parse_table(Prefs[KEY_ACTOR_SUBSTITUTION], + sep='\n', b64=True), m.actors) if Prefs[KEY_ENABLE_GENRE_SUBSTITUTION] and Prefs[KEY_GENRE_SUBSTITUTION]: - m.genres = table_substitute(parse_table(Prefs[KEY_GENRE_SUBSTITUTION], - sep='\n', b64=True), m.genres) + m.genres = utils.table_substitute( + utils.parse_table(Prefs[KEY_GENRE_SUBSTITUTION], + sep='\n', b64=True), m.genres) # Translate Info if Prefs[KEY_TRANSLATION_MODE] != TRANSLATION_MODE_DISABLED: @@ -327,12 +323,29 @@ def update(self, metadata, media, lang, force=False): if m.runtime: metadata.duration = m.runtime * 60 * 1000 # millisecond - # Clear ratings + # Chapters + metadata.chapters.clear() + chapter_min_duration = 10 * 60 * 1000 # 10 minutes + chapter_gen_interval = 5 * 60 * 1000 # 5 minutes + # only generate chapters for media with single file + durations = [int(p.duration) for p in utils.extra_media_parts(media) + if int(p.duration) > 0] + if Prefs[KEY_ENABLE_CHAPTERS] and len(durations) == 1 \ + and durations[0] > chapter_min_duration: + duration = durations[0] + for i, offset in enumerate(range(0, duration, chapter_gen_interval)): + start, end = offset, offset + chapter_gen_interval + chapter = metadata.chapters.new() + chapter.title = 'Chapter {i}'.format(i=(i + 1)) + chapter.start_time_offset = start + chapter.end_time_offset = end if end < duration else duration + + # Clear Ratings metadata.rating = 0.0 metadata.audience_rating = 0.0 metadata.rating_image = None metadata.audience_rating_image = None - # Clear reviews + # Clear Reviews metadata.reviews.clear() # Ratings & Reviews if Prefs[KEY_ENABLE_RATINGS] and m.score: @@ -357,31 +370,10 @@ def update(self, metadata, media, lang, force=False): _ = review.title # title is never used # Audience Rating - scores = float(0) - totals = int(0) - for i in reviews: - if i.score > 0: - scores += i.score - totals += 1 - metadata.audience_rating = (scores / totals) * 2 + scores = [i for i in reviews if i.score > 0] + metadata.audience_rating = utils.average(scores) * 2 metadata.audience_rating_image = self.get_audience_rating_image(metadata.audience_rating) - # Chapters - metadata.chapters.clear() - # only generate chapters for the first video file - durations = self.get_media_attributes(media, 'duration', fn=int) - if Prefs[KEY_ENABLE_CHAPTERS] and len(durations) > 0 \ - and durations[0] > 10 * 60 * 1000: - duration = durations[0] - interval = 5 * 60 * 1000 # every 5 minutes - for i, offset in enumerate(range(0, duration, interval)): - start, end = offset, offset + interval - chapter = metadata.chapters.new() - chapter.title = 'Chapter {i}'.format(i=(i + 1)) - chapter.start_time_offset = start - chapter.end_time_offset = (end if end < duration - else duration) - # Director metadata.directors.clear() if Prefs[KEY_ENABLE_DIRECTORS] and m.director: diff --git a/Contents/Code/api_client.py b/Contents/Code/api_client.py index 8b67dc8..e4e9879 100644 --- a/Contents/Code/api_client.py +++ b/Contents/Code/api_client.py @@ -1,6 +1,6 @@ # -*- coding: utf-8 -*- -from constants import DEFAULT_USER_AGENT, KEY_API_SERVER, KEY_API_TOKEN +from constants import * from utils import parse_date try: # Python 2 diff --git a/Contents/Code/utils.py b/Contents/Code/utils.py index 369f673..52d8208 100644 --- a/Contents/Code/utils.py +++ b/Contents/Code/utils.py @@ -4,7 +4,16 @@ from base64 import b64decode from datetime import datetime -from constants import * # import all +from constants import * + + +def average(a): + x = 0.0 + if not a: + return x + for i in a: + x = x + i + return x / len(a) def parse_date(s): @@ -77,3 +86,36 @@ def has_external_chinese_subtitle(video_name, *filenames): def has_chinese_subtitle(video_name): return has_embedded_chinese_subtitle(video_name) or \ has_external_chinese_subtitle(video_name) + + +def extra_media_parts(obj): + if not hasattr(obj, 'all_parts'): + return () + return [part for part in obj.all_parts() + if hasattr(part, 'file') and hasattr(part, 'duration')] + + +def extra_media_durations(obj): + parts = extra_media_parts(obj) + + # single file version + if len(parts) == 1: + return {parts[0].file: int(parts[0].duration)} + + # multi-disk file match + r = re.compile(r'-\s*(cd|disc|disk|dvd|pt|part)(\d+)$', re.IGNORECASE) + + durations = {} + for part in parts: + if int(part.duration) > 0: + name, ext = os.path.splitext(part.file) + + if r.search(name): + key = re.sub(r'\d+$', '', name) + ext + else: + key = name + ext + + durations.setdefault(key, 0) + durations[key] = durations[key] + int(part.duration) + + return durations