summaryrefslogtreecommitdiffhomepage
diff options
context:
space:
mode:
-rw-r--r--bazarr/app/config.py3
-rw-r--r--bazarr/app/get_providers.py3
-rw-r--r--frontend/src/pages/Settings/Providers/list.ts6
-rw-r--r--libs/subliminal_patch/providers/subf2m.py33
-rw-r--r--tests/subliminal_patch/test_subf2m.py115
5 files changed, 93 insertions, 67 deletions
diff --git a/bazarr/app/config.py b/bazarr/app/config.py
index b3840e0c4..b04ca93c3 100644
--- a/bazarr/app/config.py
+++ b/bazarr/app/config.py
@@ -169,7 +169,8 @@ defaults = {
'verify_ssl': 'True'
},
'subf2m': {
- 'verify_ssl': 'True'
+ 'verify_ssl': 'True',
+ 'user_agent': ''
},
'whisperai': {
'endpoint': 'http://127.0.0.1:9000',
diff --git a/bazarr/app/get_providers.py b/bazarr/app/get_providers.py
index 04593ea15..84a64be4d 100644
--- a/bazarr/app/get_providers.py
+++ b/bazarr/app/get_providers.py
@@ -294,7 +294,8 @@ def get_providers_auth():
'f_password': settings.karagarga.f_password,
},
'subf2m': {
- 'verify_ssl': settings.subf2m.getboolean('verify_ssl')
+ 'verify_ssl': settings.subf2m.getboolean('verify_ssl'),
+ 'user_agent': settings.subf2m.user_agent,
},
'whisperai': {
'endpoint': settings.whisperai.endpoint,
diff --git a/frontend/src/pages/Settings/Providers/list.ts b/frontend/src/pages/Settings/Providers/list.ts
index c266f5203..a6db25bf9 100644
--- a/frontend/src/pages/Settings/Providers/list.ts
+++ b/frontend/src/pages/Settings/Providers/list.ts
@@ -329,7 +329,13 @@ export const ProviderList: Readonly<ProviderInfo[]> = [
name: "Verify SSL",
defaultValue: true,
},
+ {
+ type: "text",
+ key: "user_agent",
+ name: "User-agent header",
+ },
],
+ message: "Make sure to use a unique and credible user agent.",
},
{
key: "subs4free",
diff --git a/libs/subliminal_patch/providers/subf2m.py b/libs/subliminal_patch/providers/subf2m.py
index 8a9807fff..7f8cb6bfd 100644
--- a/libs/subliminal_patch/providers/subf2m.py
+++ b/libs/subliminal_patch/providers/subf2m.py
@@ -115,6 +115,21 @@ _LANGUAGE_MAP = {
"turkish": "tur",
}
+_DEFAULT_HEADERS = {
+ "authority": "subf2m.co",
+ "accept": "text/html,application/xhtml+xml,application/xml;q=0.9,image/avif,image/webp,image/apng,*/*;q=0.8,application/signed-exchange;v=b3;q=0.7",
+ "accept-language": "en-US,en;q=0.9",
+ "referer": "https://subf2m.co",
+ "sec-ch-ua": '"Chromium";v="111", "Not(A:Brand";v="8"',
+ "sec-ch-ua-mobile": "?0",
+ "sec-ch-ua-platform": '"Unknown"',
+ "sec-fetch-dest": "document",
+ "sec-fetch-mode": "navigate",
+ "sec-fetch-site": "same-origin",
+ "sec-fetch-user": "?1",
+ "upgrade-insecure-requests": "1",
+}
+
class Subf2mProvider(Provider):
provider_name = "subf2m"
@@ -138,15 +153,25 @@ class Subf2mProvider(Provider):
video_types = (Episode, Movie)
subtitle_class = Subf2mSubtitle
- def __init__(self, verify_ssl=True):
+ def __init__(self, verify_ssl=True, user_agent=None, session_factory=None):
super().__init__()
+ if not user_agent:
+ raise ValueError("User-agent config missing")
+
+ self._user_agent = user_agent
self._verify_ssl = verify_ssl
+ self._session_factory = session_factory
def initialize(self):
- self._session = Session()
- self._session.verify = self._verify_ssl
+ if self._session_factory is not None:
+ self._session = self._session_factory()
+ else:
+ logger.debug("No session factory set. Using default requests.Session.")
+ self._session = Session()
- self._session.headers.update({"user-agent": "Bazarr"})
+ self._session.verify = self._verify_ssl
+ self._session.headers.update(_DEFAULT_HEADERS)
+ self._session.headers.update({"user-agent": self._user_agent})
def terminate(self):
self._session.close()
diff --git a/tests/subliminal_patch/test_subf2m.py b/tests/subliminal_patch/test_subf2m.py
index 19275d48a..cdf201734 100644
--- a/tests/subliminal_patch/test_subf2m.py
+++ b/tests/subliminal_patch/test_subf2m.py
@@ -5,6 +5,15 @@ from subliminal_patch.providers.subf2m import Subf2mSubtitle
from subzero.language import Language
+_U_A = "Mozilla/5.0 (Linux; Android 10; SM-G996U Build/QP1A.190711.020; wv) AppleWebKit/537.36 (KHTML, like Gecko) Version/4.0 Mobile Safari/537.36"
+
+
+def provider():
+ with Subf2mProvider(user_agent=_U_A) as provider:
+ yield provider
+
+
@pytest.mark.parametrize(
"title,year,expected_url",
[
@@ -17,14 +26,13 @@ from subzero.language import Language
("Cure", 1997, "/subtitles/cure-kyua"),
],
)
-def test_search_movie(movies, title, year, expected_url):
+def test_search_movie(provider, movies, title, year, expected_url):
movie = list(movies.values())[0]
movie.title = title
movie.year = year
- with Subf2mProvider() as provider:
- result = provider._search_movie(movie.title, movie.year)
- assert result == expected_url
+ result = provider._search_movie(movie.title, movie.year)
+ assert result == expected_url
@pytest.mark.parametrize(
@@ -42,39 +50,33 @@ def test_search_movie(movies, title, year, expected_url):
),
],
)
-def test_search_tv_show_season(series_title, season, year, expected_url):
- with Subf2mProvider() as provider:
- result = provider._search_tv_show_season(series_title, season, year)
- assert result == expected_url
+def test_search_tv_show_season(provider, series_title, season, year, expected_url):
+ result = provider._search_tv_show_season(series_title, season, year)
+ assert result == expected_url
@pytest.mark.parametrize("language", [Language.fromalpha2("en"), Language("por", "BR")])
-def test_find_movie_subtitles(language):
+def test_find_movie_subtitles(provider, language):
path = "/subtitles/dune-2021"
- with Subf2mProvider() as provider:
- for sub in provider._find_movie_subtitles(path, language):
- assert sub.language == language
+ for sub in provider._find_movie_subtitles(path, language):
+ assert sub.language == language
@pytest.mark.parametrize("language", [Language.fromalpha2("en"), Language("por", "BR")])
-def test_find_episode_subtitles(language):
+def test_find_episode_subtitles(provider, language):
path = "/subtitles/breaking-bad-first-season"
- with Subf2mProvider() as provider:
- for sub in provider._find_episode_subtitles(path, 1, 1, language):
- assert sub.language == language
+ for sub in provider._find_episode_subtitles(path, 1, 1, language):
+ assert sub.language == language
-def test_find_episode_subtitles_from_complete_series_path():
+def test_find_episode_subtitles_from_complete_series_path(provider):
path = "/subtitles/courage-the-cowardly-dog"
- with Subf2mProvider() as provider:
- for sub in provider._find_episode_subtitles(
- path, 1, 1, Language.fromalpha2("en")
- ):
- assert sub.language == Language.fromalpha2("en")
+ for sub in provider._find_episode_subtitles(path, 1, 1, Language.fromalpha2("en")):
+ assert sub.language == Language.fromalpha2("en")
-def test_list_and_download_subtitles_complete_series_pack(episodes):
+def test_list_and_download_subtitles_complete_series_pack(provider, episodes):
episode = list(episodes.values())[0]
episode.series = "Sam & Max: Freelance Police"
@@ -83,14 +85,13 @@ def test_list_and_download_subtitles_complete_series_pack(episodes):
episode.season = 1
episode.episode = 21
- with Subf2mProvider() as provider:
- subtitles = provider.list_subtitles(episode, {Language.fromalpha2("en")})
- assert subtitles
+ subtitles = provider.list_subtitles(episode, {Language.fromalpha2("en")})
+ assert subtitles
- subtitle = subtitles[0]
- provider.download_subtitle(subtitle)
+ subtitle = subtitles[0]
+ provider.download_subtitle(subtitle)
- assert subtitle.is_valid()
+ assert subtitle.is_valid()
@pytest.fixture
@@ -136,47 +137,40 @@ def test_subtitle_get_matches_episode(subtitle_episode, episodes):
assert "source" not in matches
-def test_list_subtitles_movie(movies):
- with Subf2mProvider() as provider:
- assert provider.list_subtitles(movies["dune"], {Language.fromalpha2("en")})
+def test_list_subtitles_movie(provider, movies):
+ assert provider.list_subtitles(movies["dune"], {Language.fromalpha2("en")})
-def test_list_subtitles_inexistent_movie(movies):
- with Subf2mProvider() as provider:
- assert (
- provider.list_subtitles(movies["inexistent"], {Language.fromalpha2("en")})
- == []
- )
+def test_list_subtitles_inexistent_movie(provider, movies):
+ assert (
+ provider.list_subtitles(movies["inexistent"], {Language.fromalpha2("en")}) == []
+ )
-def test_list_subtitles_episode(episodes):
- with Subf2mProvider() as provider:
- assert provider.list_subtitles(
- episodes["breaking_bad_s01e01"], {Language.fromalpha2("en")}
- )
+def test_list_subtitles_episode(provider, episodes):
+ assert provider.list_subtitles(
+ episodes["breaking_bad_s01e01"], {Language.fromalpha2("en")}
+ )
-def test_list_subtitles_inexistent_episode(episodes):
- with Subf2mProvider() as provider:
- assert (
- provider.list_subtitles(episodes["inexistent"], {Language.fromalpha2("en")})
- == []
- )
+def test_list_subtitles_inexistent_episode(provider, episodes):
+ assert (
+ provider.list_subtitles(episodes["inexistent"], {Language.fromalpha2("en")})
+ == []
+ )
-def test_download_subtitle(subtitle):
- with Subf2mProvider() as provider:
- provider.download_subtitle(subtitle)
- assert subtitle.is_valid()
+def test_download_subtitle(provider, subtitle):
+ provider.download_subtitle(subtitle)
+ assert subtitle.is_valid()
-def test_download_subtitle_episode(subtitle_episode):
- with Subf2mProvider() as provider:
- provider.download_subtitle(subtitle_episode)
- assert subtitle_episode.is_valid()
+def test_download_subtitle_episode(provider, subtitle_episode):
+ provider.download_subtitle(subtitle_episode)
+ assert subtitle_episode.is_valid()
-def test_download_subtitle_episode_with_title():
+def test_download_subtitle_episode_with_title(provider):
sub = Subf2mSubtitle(
Language.fromalpha2("en"),
"https://subf2m.co/subtitles/courage-the-cowardly-dog/english/2232402",
@@ -185,9 +179,8 @@ def test_download_subtitle_episode_with_title():
)
sub.episode_title = "Feast of the Bullfrogs"
- with Subf2mProvider() as provider:
- provider.download_subtitle(sub)
- assert sub.is_valid()
+ provider.download_subtitle(sub)
+ assert sub.is_valid()
def test_get_episode_from_release():