From ad13f79d193d479b0c674a05330b97befc8445c7 Mon Sep 17 00:00:00 2001 From: Vitiko Date: Fri, 3 Mar 2023 15:51:38 -0400 Subject: [PATCH] Subf2m Provider: improve episode matching (#2081) --- libs/subliminal_patch/providers/subf2m.py | 48 ++++++++++++++++++++++- tests/subliminal_patch/test_subf2m.py | 16 +++++++- 2 files changed, 61 insertions(+), 3 deletions(-) diff --git a/libs/subliminal_patch/providers/subf2m.py b/libs/subliminal_patch/providers/subf2m.py index 2ee78899b..5d0ebcffd 100644 --- a/libs/subliminal_patch/providers/subf2m.py +++ b/libs/subliminal_patch/providers/subf2m.py @@ -5,8 +5,15 @@ import functools import logging import re import time +import ssl import urllib.parse +from urllib3 import poolmanager + +from guessit import guessit + +from requests import Session +from requests.adapters import HTTPAdapter from bs4 import BeautifulSoup as bso from guessit import guessit from requests import Session @@ -113,6 +120,20 @@ _LANGUAGE_MAP = { } +class _Adapter(HTTPAdapter): + def init_poolmanager(self, connections, maxsize, block=False): + ctx = ssl.create_default_context() + ctx.set_ciphers("DEFAULT@SECLEVEL=0") + ctx.check_hostname = False + self.poolmanager = poolmanager.PoolManager( + num_pools=connections, + maxsize=maxsize, + block=block, + ssl_version=ssl.PROTOCOL_TLS, + ssl_context=ctx, + ) + + class Subf2mProvider(Provider): provider_name = "subf2m" @@ -141,6 +162,8 @@ class Subf2mProvider(Provider): def initialize(self): self._session = Session() + self._session.mount("https://", _Adapter()) + self._session.verify = self._verify_ssl self._session.headers.update({"user-agent": "Bazarr"}) @@ -283,8 +306,11 @@ class Subf2mProvider(Provider): if not clean_text: continue - # It will return list values - guess = _memoized_episode_guess(clean_text) + # First try with the special episode matches for subf2m + guess = _get_episode_from_release(clean_text) + + if guess is None: + guess = _memoized_episode_guess(clean_text) if "season" not in guess: if "complete series" in clean_text.lower(): @@ -390,6 +416,24 @@ def _memoized_episode_guess(content): ) +_EPISODE_SPECIAL_RE = re.compile( + r"(season|s)\s*?(?P\d{,2})\s?[-−]\s?(?P\d{,2})", flags=re.IGNORECASE +) + + +def _get_episode_from_release(release: str): + match = _EPISODE_SPECIAL_RE.search(release) + if match is None: + return None + + try: + season, episode = [int(item) for item in match.group("x", "y")] + except (IndexError, ValueError): + return None + + return {"season": [season], "episode": [episode]} + + def _get_subtitle_from_item(item, language, episode_number=None): release_info = [ rel.text.strip() for rel in item.find("ul", {"class": "scrolllist"}) diff --git a/tests/subliminal_patch/test_subf2m.py b/tests/subliminal_patch/test_subf2m.py index 47a823bfc..19275d48a 100644 --- a/tests/subliminal_patch/test_subf2m.py +++ b/tests/subliminal_patch/test_subf2m.py @@ -1,5 +1,5 @@ import pytest - +from subliminal_patch.providers import subf2m from subliminal_patch.providers.subf2m import Subf2mProvider from subliminal_patch.providers.subf2m import Subf2mSubtitle from subzero.language import Language @@ -188,3 +188,17 @@ def test_download_subtitle_episode_with_title(): with Subf2mProvider() as provider: provider.download_subtitle(sub) assert sub.is_valid() + + +def test_get_episode_from_release(): + assert subf2m._get_episode_from_release( + "Vinland Saga Season 2 - 05 [Crunchyroll][Crunchyroll] Vinland Saga Season 2 - 05" + ) == {"season": [2], "episode": [5]} + + +def test_get_episode_from_release_return_none(): + assert subf2m._get_episode_from_release("Vinland Saga Season 2 - Foo") is None + + +def test_get_episode_from_release_w_empty_match_return_none(): + assert subf2m._get_episode_from_release("Vinland Saga - 02") is None