From 074b54685aea41816b0454059f9a6fd249c30c2b Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Morav=C4=8D=C3=ADk=2C=20Marian?= Date: Sat, 23 May 2020 19:04:37 +0200 Subject: [PATCH 1/4] Small fix for Pos-processing log output --- bazarr/get_subtitle.py | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/bazarr/get_subtitle.py b/bazarr/get_subtitle.py index 920576f8d..8de7bc5ab 100644 --- a/bazarr/get_subtitle.py +++ b/bazarr/get_subtitle.py @@ -234,7 +234,7 @@ def download_subtitle(path, language, audio_language, hi, forced, providers, pro if not use_pp_threshold or (use_pp_threshold and percent_score < pp_threshold): postprocessing(command, path) - logging.debug("BAZARR Using post-processing command {}".format(command + path)) + logging.debug("BAZARR Using post-processing command: {}".format(command)) else: logging.debug("BAZARR post-processing skipped because subtitles score isn't below this " "threshold value: " + str(pp_threshold) + "%") From 08aa8cae0a816e90b3f9e2aa2296c7917b59f958 Mon Sep 17 00:00:00 2001 From: Mr-Quin Date: Sat, 23 May 2020 13:32:47 -0700 Subject: [PATCH 2/4] change isascii to isalnum --- libs/subliminal_patch/providers/assrt.py | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/libs/subliminal_patch/providers/assrt.py b/libs/subliminal_patch/providers/assrt.py index eab6bfc04..10ad2609a 100644 --- a/libs/subliminal_patch/providers/assrt.py +++ b/libs/subliminal_patch/providers/assrt.py @@ -126,13 +126,13 @@ class AssrtProvider(Provider): keywords = [] if isinstance(video, Movie): if video.title: - title = "".join(e for e in video.title if e.isascii()) + title = "".join(e for e in video.title if e.isalnum()) keywords.append(title) if video.year: keywords.append(str(video.year)) elif isinstance(video, Episode): if video.series: - series = "".join(e for e in video.series if e.isascii()) + series = "".join(e for e in video.series if e.isalnum()) keywords.append(series) if video.season and video.episode: keywords.append('S%02dE%02d' % (video.season, video.episode)) From 91cc6b35c918eba79003c52a0b83fca588f0887d Mon Sep 17 00:00:00 2001 From: josdion Date: Sun, 24 May 2020 13:02:34 +0300 Subject: [PATCH 3/4] fix a compatibility issue with guessit 3, added cache support - remove allowed_countries parameter when call guessit as it's not necessary now and in the way which it's used, it throw an exception in guessit 3 - add downloaded subtitle files to the cache - check subtitle notes for additional inforamtion about the release --- libs/subliminal_patch/providers/subssabbz.py | 32 +++++++++++++------ libs/subliminal_patch/providers/subsunacs.py | 32 +++++++++++++------ libs/subliminal_patch/providers/yavkanet.py | 33 ++++++++++++++------ 3 files changed, 67 insertions(+), 30 deletions(-) diff --git a/libs/subliminal_patch/providers/subssabbz.py b/libs/subliminal_patch/providers/subssabbz.py index 66edc1c4f..3c095bcff 100644 --- a/libs/subliminal_patch/providers/subssabbz.py +++ b/libs/subliminal_patch/providers/subssabbz.py @@ -4,19 +4,22 @@ import logging import re import io import os +import codecs +from hashlib import sha1 from random import randint from bs4 import BeautifulSoup from zipfile import ZipFile, is_zipfile from rarfile import RarFile, is_rarfile from requests import Session from guessit import guessit +from dogpile.cache.api import NO_VALUE from subliminal_patch.providers import Provider from subliminal_patch.subtitle import Subtitle from subliminal_patch.utils import sanitize, fix_inconsistent_naming -from subliminal.utils import sanitize_release_group from subliminal.subtitle import guess_matches from subliminal.video import Episode, Movie from subliminal.subtitle import fix_line_ending +from subliminal.cache import region from subzero.language import Language from .utils import FIRST_THOUSAND_OR_SO_USER_AGENTS as AGENT_LIST @@ -62,6 +65,7 @@ class SubsSabBzSubtitle(Subtitle): def make_picklable(self): self.content = None + self._is_valid = False return self def get_matches(self, video): @@ -70,14 +74,15 @@ class SubsSabBzSubtitle(Subtitle): video_filename = video.name video_filename = os.path.basename(video_filename) video_filename, _ = os.path.splitext(video_filename) - video_filename = sanitize_release_group(video_filename) + video_filename = re.sub(r'\[\w+\]$', '', video_filename).strip().upper() subtitle_filename = self.filename subtitle_filename = os.path.basename(subtitle_filename) subtitle_filename, _ = os.path.splitext(subtitle_filename) - subtitle_filename = sanitize_release_group(subtitle_filename) + subtitle_filename = re.sub(r'\[\w+\]$', '', subtitle_filename).strip().upper() - if video_filename == subtitle_filename: + if ((video_filename == subtitle_filename) or + (self.single_file is True and video_filename in self.notes.upper())): matches.add('hash') if video.year and self.year == video.year: @@ -87,8 +92,8 @@ class SubsSabBzSubtitle(Subtitle): if video.imdb_id and self.imdb_id == video.imdb_id: matches.add('imdb_id') - matches |= guess_matches(video, guessit(self.title, {'type': self.type, 'allowed_countries': [None]})) - matches |= guess_matches(video, guessit(self.filename, {'type': self.type, 'allowed_countries': [None]})) + matches |= guess_matches(video, guessit(self.title, {'type': self.type})) + matches |= guess_matches(video, guessit(self.filename, {'type': self.type})) return matches @@ -193,6 +198,7 @@ class SubsSabBzProvider(Provider): s.year = year s.uploader = uploader s.imdb_id = imdb_id + s.single_file = True if len(sub) == 1 and num_cds == 1 else False subtitles = subtitles + sub return subtitles @@ -223,10 +229,16 @@ class SubsSabBzProvider(Provider): def download_archive_and_add_subtitle_files(self, link, language, video, fps, num_cds): logger.info('Downloading subtitle %r', link) - request = self.session.get(link, headers={ - 'Referer': 'http://subs.sab.bz/index.php?' - }) - request.raise_for_status() + cache_key = sha1(link.encode("utf-8")).digest() + request = region.get(cache_key) + if request is NO_VALUE: + request = self.session.get(link, headers={ + 'Referer': 'http://subs.sab.bz/index.php?' + }) + request.raise_for_status() + region.set(cache_key, request) + else: + logger.info('Cache file: %s', codecs.encode(cache_key, 'hex_codec').decode('utf-8')) archive_stream = io.BytesIO(request.content) if is_rarfile(archive_stream): diff --git a/libs/subliminal_patch/providers/subsunacs.py b/libs/subliminal_patch/providers/subsunacs.py index b4edc1af1..a8af6a4b9 100644 --- a/libs/subliminal_patch/providers/subsunacs.py +++ b/libs/subliminal_patch/providers/subsunacs.py @@ -4,19 +4,22 @@ import logging import re import io import os +import codecs +from hashlib import sha1 from random import randint from bs4 import BeautifulSoup from zipfile import ZipFile, is_zipfile from rarfile import RarFile, is_rarfile from requests import Session from guessit import guessit +from dogpile.cache.api import NO_VALUE from subliminal_patch.providers import Provider from subliminal_patch.subtitle import Subtitle from subliminal_patch.utils import sanitize, fix_inconsistent_naming -from subliminal.utils import sanitize_release_group from subliminal.subtitle import guess_matches from subliminal.video import Episode, Movie from subliminal.subtitle import fix_line_ending +from subliminal.cache import region from subzero.language import Language from .utils import FIRST_THOUSAND_OR_SO_USER_AGENTS as AGENT_LIST @@ -61,6 +64,7 @@ class SubsUnacsSubtitle(Subtitle): def make_picklable(self): self.content = None + self._is_valid = False return self def get_matches(self, video): @@ -69,21 +73,22 @@ class SubsUnacsSubtitle(Subtitle): video_filename = video.name video_filename = os.path.basename(video_filename) video_filename, _ = os.path.splitext(video_filename) - video_filename = sanitize_release_group(video_filename) + video_filename = re.sub(r'\[\w+\]$', '', video_filename).strip().upper() subtitle_filename = self.filename subtitle_filename = os.path.basename(subtitle_filename) subtitle_filename, _ = os.path.splitext(subtitle_filename) - subtitle_filename = sanitize_release_group(subtitle_filename) + subtitle_filename = re.sub(r'\[\w+\]$', '', subtitle_filename).strip().upper() - if video_filename == subtitle_filename: + if ((video_filename == subtitle_filename) or + (self.single_file is True and video_filename in self.notes.upper())): matches.add('hash') if video.year and self.year == video.year: matches.add('year') - matches |= guess_matches(video, guessit(self.title, {'type': self.type, 'allowed_countries': [None]})) - matches |= guess_matches(video, guessit(self.filename, {'type': self.type, 'allowed_countries': [None]})) + matches |= guess_matches(video, guessit(self.title, {'type': self.type})) + matches |= guess_matches(video, guessit(self.filename, {'type': self.type})) return matches @@ -192,6 +197,7 @@ class SubsUnacsProvider(Provider): s.year = year s.rating = rating s.uploader = uploader + s.single_file = True if len(sub) == 1 and num_cds == 1 else False subtitles = subtitles + sub return subtitles @@ -227,10 +233,16 @@ class SubsUnacsProvider(Provider): def download_archive_and_add_subtitle_files(self, link, language, video, fps, num_cds): logger.info('Downloading subtitle %r', link) - request = self.session.get(link, headers={ - 'Referer': 'https://subsunacs.net/search.php' - }) - request.raise_for_status() + cache_key = sha1(link.encode("utf-8")).digest() + request = region.get(cache_key) + if request is NO_VALUE: + request = self.session.get(link, headers={ + 'Referer': 'https://subsunacs.net/search.php' + }) + request.raise_for_status() + region.set(cache_key, request) + else: + logger.info('Cache file: %s', codecs.encode(cache_key, 'hex_codec').decode('utf-8')) archive_stream = io.BytesIO(request.content) if is_rarfile(archive_stream): diff --git a/libs/subliminal_patch/providers/yavkanet.py b/libs/subliminal_patch/providers/yavkanet.py index 42029634e..70a8ad830 100644 --- a/libs/subliminal_patch/providers/yavkanet.py +++ b/libs/subliminal_patch/providers/yavkanet.py @@ -1,21 +1,25 @@ # -*- coding: utf-8 -*- from __future__ import absolute_import import logging +import re import io import os +import codecs +from hashlib import sha1 from random import randint from bs4 import BeautifulSoup from zipfile import ZipFile, is_zipfile from rarfile import RarFile, is_rarfile from requests import Session from guessit import guessit +from dogpile.cache.api import NO_VALUE from subliminal_patch.providers import Provider from subliminal_patch.subtitle import Subtitle from subliminal_patch.utils import sanitize -from subliminal.utils import sanitize_release_group from subliminal.subtitle import guess_matches from subliminal.video import Episode, Movie from subliminal.subtitle import fix_line_ending +from subliminal.cache import region from subzero.language import Language from .utils import FIRST_THOUSAND_OR_SO_USER_AGENTS as AGENT_LIST @@ -44,6 +48,7 @@ class YavkaNetSubtitle(Subtitle): def make_picklable(self): self.content = None + self._is_valid = False return self def get_matches(self, video): @@ -52,21 +57,22 @@ class YavkaNetSubtitle(Subtitle): video_filename = video.name video_filename = os.path.basename(video_filename) video_filename, _ = os.path.splitext(video_filename) - video_filename = sanitize_release_group(video_filename) + video_filename = re.sub(r'\[\w+\]$', '', video_filename).strip().upper() subtitle_filename = self.filename subtitle_filename = os.path.basename(subtitle_filename) subtitle_filename, _ = os.path.splitext(subtitle_filename) - subtitle_filename = sanitize_release_group(subtitle_filename) + subtitle_filename = re.sub(r'\[\w+\]$', '', subtitle_filename).strip().upper() - if video_filename == subtitle_filename: + if ((video_filename == subtitle_filename) or + (self.single_file is True and video_filename in self.notes.upper())): matches.add('hash') if video.year and self.year == video.year: matches.add('year') - matches |= guess_matches(video, guessit(self.title, {'type': self.type, 'allowed_countries': [None]})) - matches |= guess_matches(video, guessit(self.filename, {'type': self.type, 'allowed_countries': [None]})) + matches |= guess_matches(video, guessit(self.title, {'type': self.type})) + matches |= guess_matches(video, guessit(self.filename, {'type': self.type})) return matches @@ -157,6 +163,7 @@ class YavkaNetProvider(Provider): s.notes = notes s.year = year s.uploader = uploader + s.single_file = True if len(sub) == 1 else False subtitles = subtitles + sub return subtitles @@ -187,10 +194,16 @@ class YavkaNetProvider(Provider): def download_archive_and_add_subtitle_files(self, link, language, video, fps): logger.info('Downloading subtitle %r', link) - request = self.session.get(link, headers={ - 'Referer': 'http://yavka.net/subtitles.php' - }) - request.raise_for_status() + cache_key = sha1(link.encode("utf-8")).digest() + request = region.get(cache_key) + if request is NO_VALUE: + request = self.session.get(link, headers={ + 'Referer': 'http://yavka.net/subtitles.php' + }) + request.raise_for_status() + region.set(cache_key, request) + else: + logger.info('Cache file: %s', codecs.encode(cache_key, 'hex_codec').decode('utf-8')) archive_stream = io.BytesIO(request.content) if is_rarfile(archive_stream): From 7e304001b62a0d6c68c06c8c9283b4e55a233d32 Mon Sep 17 00:00:00 2001 From: Smaarn Date: Sun, 24 May 2020 11:45:28 +0200 Subject: [PATCH 4/4] Rework on child process management. When receiving the SIGTERM signal, swallow it and terminate latest created child process Catch ChildProcessError (occurs when child process is terminated by the current python script on mac os x) --- bazarr.py | 10 +++++++++- 1 file changed, 9 insertions(+), 1 deletion(-) diff --git a/bazarr.py b/bazarr.py index 594154e13..a3e17189a 100644 --- a/bazarr.py +++ b/bazarr.py @@ -2,6 +2,7 @@ import os import platform +import signal import subprocess import sys import time @@ -37,11 +38,18 @@ def end_child_process(ep): except: pass +def terminate_child_process(ep): + try: + ep.terminate() + except: + pass + def start_bazarr(): script = [sys.executable, "-u", os.path.normcase(os.path.join(dir_name, 'bazarr', 'main.py'))] + sys.argv[1:] ep = subprocess.Popen(script, stdout=None, stderr=None, stdin=subprocess.DEVNULL) atexit.register(end_child_process, ep=ep) + signal.signal(signal.SIGTERM, lambda signal_no, frame: terminate_child_process(ep)) def check_status(): @@ -92,6 +100,6 @@ if __name__ == '__main__': else: os.wait() time.sleep(1) - except (KeyboardInterrupt, SystemExit): + except (KeyboardInterrupt, SystemExit, ChildProcessError): print('Bazarr exited.') sys.exit(0)