mirror of https://github.com/morpheus65535/bazarr
Added support for opensubtitles.com dedicated VIP subdomain that get automatically used according to subscription status.
This commit is contained in:
parent
9f0a8d0a14
commit
95474b29db
|
@ -615,10 +615,12 @@ def save_settings(settings_items):
|
||||||
if key != settings.opensubtitlescom.username:
|
if key != settings.opensubtitlescom.username:
|
||||||
reset_providers = True
|
reset_providers = True
|
||||||
region.delete('oscom_token')
|
region.delete('oscom_token')
|
||||||
|
region.delete('oscom_server')
|
||||||
elif key == 'settings-opensubtitlescom-password':
|
elif key == 'settings-opensubtitlescom-password':
|
||||||
if key != settings.opensubtitlescom.password:
|
if key != settings.opensubtitlescom.password:
|
||||||
reset_providers = True
|
reset_providers = True
|
||||||
region.delete('oscom_token')
|
region.delete('oscom_token')
|
||||||
|
region.delete('oscom_server')
|
||||||
|
|
||||||
if key == 'settings-subscene-username':
|
if key == 'settings-subscene-username':
|
||||||
if key != settings.subscene.username:
|
if key != settings.subscene.username:
|
||||||
|
|
|
@ -154,7 +154,7 @@ class OpenSubtitlesComSubtitle(Subtitle):
|
||||||
|
|
||||||
class OpenSubtitlesComProvider(ProviderRetryMixin, Provider):
|
class OpenSubtitlesComProvider(ProviderRetryMixin, Provider):
|
||||||
"""OpenSubtitlesCom Provider"""
|
"""OpenSubtitlesCom Provider"""
|
||||||
server_url = 'https://api.opensubtitles.com/api/v1/'
|
server_hostname = 'api.opensubtitles.com'
|
||||||
|
|
||||||
languages = {Language.fromopensubtitles(lang) for lang in language_converters['szopensubtitles'].codes}
|
languages = {Language.fromopensubtitles(lang) for lang in language_converters['szopensubtitles'].codes}
|
||||||
languages.update(set(Language.rebuild(lang, forced=True) for lang in languages))
|
languages.update(set(Language.rebuild(lang, forced=True) for lang in languages))
|
||||||
|
@ -193,15 +193,24 @@ class OpenSubtitlesComProvider(ProviderRetryMixin, Provider):
|
||||||
else:
|
else:
|
||||||
self.token = region.get("oscom_token", expiration_time=TOKEN_EXPIRATION_TIME)
|
self.token = region.get("oscom_token", expiration_time=TOKEN_EXPIRATION_TIME)
|
||||||
|
|
||||||
|
if region.get("oscom_server", expiration_time=TOKEN_EXPIRATION_TIME) is NO_VALUE:
|
||||||
|
logger.debug("No cached server, we'll try to login again.")
|
||||||
|
self.login()
|
||||||
|
else:
|
||||||
|
self.server_hostname = region.get("oscom_server", expiration_time=TOKEN_EXPIRATION_TIME)
|
||||||
|
|
||||||
def terminate(self):
|
def terminate(self):
|
||||||
self.session.close()
|
self.session.close()
|
||||||
|
|
||||||
def ping(self):
|
def ping(self):
|
||||||
return self._started and (time.time() - self._started) < TOKEN_EXPIRATION_TIME
|
return self._started and (time.time() - self._started) < TOKEN_EXPIRATION_TIME
|
||||||
|
|
||||||
|
def server_url(self):
|
||||||
|
return f'https://{self.server_hostname}/api/v1/'
|
||||||
|
|
||||||
def login(self, is_retry=False):
|
def login(self, is_retry=False):
|
||||||
r = self.checked(
|
r = self.checked(
|
||||||
lambda: self.session.post(self.server_url + 'login',
|
lambda: self.session.post(self.server_url() + 'login',
|
||||||
json={"username": self.username, "password": self.password},
|
json={"username": self.username, "password": self.password},
|
||||||
allow_redirects=False,
|
allow_redirects=False,
|
||||||
timeout=30),
|
timeout=30),
|
||||||
|
@ -216,6 +225,20 @@ class OpenSubtitlesComProvider(ProviderRetryMixin, Provider):
|
||||||
log_request_response(r, non_standard=False)
|
log_request_response(r, non_standard=False)
|
||||||
region.set("oscom_token", self.token)
|
region.set("oscom_token", self.token)
|
||||||
|
|
||||||
|
try:
|
||||||
|
self.server_hostname = r.json()['base_url']
|
||||||
|
except (ValueError, JSONDecodeError):
|
||||||
|
log_request_response(r)
|
||||||
|
raise ProviderError("Cannot get server from provider login response")
|
||||||
|
else:
|
||||||
|
log_request_response(r, non_standard=False)
|
||||||
|
region.set("oscom_server", self.server_hostname)
|
||||||
|
finally:
|
||||||
|
if self.server_hostname.startswith('vip'):
|
||||||
|
self.session.headers.update({'Authorization': 'Bearer ' + self.token})
|
||||||
|
else:
|
||||||
|
self.session.headers.pop('Authorization', None)
|
||||||
|
|
||||||
@staticmethod
|
@staticmethod
|
||||||
def sanitize_external_ids(external_id):
|
def sanitize_external_ids(external_id):
|
||||||
if isinstance(external_id, str):
|
if isinstance(external_id, str):
|
||||||
|
@ -232,7 +255,7 @@ class OpenSubtitlesComProvider(ProviderRetryMixin, Provider):
|
||||||
|
|
||||||
results = self.retry(
|
results = self.retry(
|
||||||
lambda: self.checked(
|
lambda: self.checked(
|
||||||
lambda: self.session.get(self.server_url + 'features', params=parameters, timeout=30),
|
lambda: self.session.get(self.server_url() + 'features', params=parameters, timeout=30),
|
||||||
validate_json=True,
|
validate_json=True,
|
||||||
json_key_name='data'
|
json_key_name='data'
|
||||||
),
|
),
|
||||||
|
@ -300,7 +323,7 @@ class OpenSubtitlesComProvider(ProviderRetryMixin, Provider):
|
||||||
if isinstance(self.video, Episode):
|
if isinstance(self.video, Episode):
|
||||||
res = self.retry(
|
res = self.retry(
|
||||||
lambda: self.checked(
|
lambda: self.checked(
|
||||||
lambda: self.session.get(self.server_url + 'subtitles',
|
lambda: self.session.get(self.server_url() + 'subtitles',
|
||||||
params=(('ai_translated', 'exclude' if not self.include_ai_translated
|
params=(('ai_translated', 'exclude' if not self.include_ai_translated
|
||||||
else 'include'),
|
else 'include'),
|
||||||
('episode_number', self.video.episode),
|
('episode_number', self.video.episode),
|
||||||
|
@ -318,7 +341,7 @@ class OpenSubtitlesComProvider(ProviderRetryMixin, Provider):
|
||||||
else:
|
else:
|
||||||
res = self.retry(
|
res = self.retry(
|
||||||
lambda: self.checked(
|
lambda: self.checked(
|
||||||
lambda: self.session.get(self.server_url + 'subtitles',
|
lambda: self.session.get(self.server_url() + 'subtitles',
|
||||||
params=(('ai_translated', 'exclude' if not self.include_ai_translated
|
params=(('ai_translated', 'exclude' if not self.include_ai_translated
|
||||||
else 'include'),
|
else 'include'),
|
||||||
('id', title_id if title_id else None),
|
('id', title_id if title_id else None),
|
||||||
|
@ -410,7 +433,7 @@ class OpenSubtitlesComProvider(ProviderRetryMixin, Provider):
|
||||||
'Authorization': 'Bearer ' + self.token}
|
'Authorization': 'Bearer ' + self.token}
|
||||||
res = self.retry(
|
res = self.retry(
|
||||||
lambda: self.checked(
|
lambda: self.checked(
|
||||||
lambda: self.session.post(self.server_url + 'download',
|
lambda: self.session.post(self.server_url() + 'download',
|
||||||
json={'file_id': subtitle.file_id, 'sub_format': 'srt'},
|
json={'file_id': subtitle.file_id, 'sub_format': 'srt'},
|
||||||
headers=headers,
|
headers=headers,
|
||||||
timeout=30),
|
timeout=30),
|
||||||
|
@ -443,6 +466,7 @@ class OpenSubtitlesComProvider(ProviderRetryMixin, Provider):
|
||||||
def reset_token():
|
def reset_token():
|
||||||
logger.debug('Authentication failed: clearing cache and attempting to login.')
|
logger.debug('Authentication failed: clearing cache and attempting to login.')
|
||||||
region.delete("oscom_token")
|
region.delete("oscom_token")
|
||||||
|
region.delete("oscom_server")
|
||||||
return
|
return
|
||||||
|
|
||||||
def checked(self, fn, raise_api_limit=False, validate_json=False, json_key_name=None, validate_content=False,
|
def checked(self, fn, raise_api_limit=False, validate_json=False, json_key_name=None, validate_content=False,
|
||||||
|
@ -558,9 +582,12 @@ def log_request_response(response, non_standard=True):
|
||||||
if 'Authorization' in redacted_request_headers and isinstance(redacted_request_headers['Authorization'], str):
|
if 'Authorization' in redacted_request_headers and isinstance(redacted_request_headers['Authorization'], str):
|
||||||
redacted_request_headers['Authorization'] = redacted_request_headers['Authorization'][:-8]+8*'x'
|
redacted_request_headers['Authorization'] = redacted_request_headers['Authorization'][:-8]+8*'x'
|
||||||
|
|
||||||
|
if response.request.body:
|
||||||
redacted_request_body = json.loads(response.request.body)
|
redacted_request_body = json.loads(response.request.body)
|
||||||
if 'password' in redacted_request_body:
|
if 'password' in redacted_request_body:
|
||||||
redacted_request_body['password'] = 'redacted'
|
redacted_request_body['password'] = 'redacted'
|
||||||
|
else:
|
||||||
|
redacted_request_body = None
|
||||||
|
|
||||||
redacted_response_body = json.loads(response.text)
|
redacted_response_body = json.loads(response.text)
|
||||||
if 'token' in redacted_response_body and isinstance(redacted_response_body['token'], str):
|
if 'token' in redacted_response_body and isinstance(redacted_response_body['token'], str):
|
||||||
|
|
Loading…
Reference in New Issue