Compare commits
14 Commits
2.6.4.2864
...
2.6.4.2881
| Author | SHA1 | Date | |
|---|---|---|---|
| 734e0f7128 | |||
| 4c76439f4e | |||
| 2488d4db53 | |||
| 565987faff | |||
| e14402c6a0 | |||
| ccfc40f6fc | |||
| d69a331b87 | |||
| 01fd66c35a | |||
| 73b33fe697 | |||
| 9e730a2b85 | |||
| 6395b0e945 | |||
| 79d16b98f1 | |||
| b770a40150 | |||
| 20952b5c26 |
@@ -1,4 +1,14 @@
|
||||
|
||||
2.6.4.2859
|
||||
- core: fix thread.lock error (only affected the history menu, not the actual functionality)
|
||||
- core: fix audio-based conditional subtitle decision making; fixes #592
|
||||
- core: massively improve metadata subtitle storage
|
||||
- providers: opensubtitles: skip non-forced results when searching for forced
|
||||
- providers: podnapisi: skip non-forced results when searching for forced
|
||||
- submod: common: correctly pad music symbols on either side
|
||||
|
||||
|
||||
|
||||
2.6.4.2834
|
||||
- core: add option to use custom (Google, Cloudflare) DNS to resolve provider hosts in problematic countries; fixes #547
|
||||
- core: add support for downloading subtitles only when the audio streams don't match (any?) configured languages; fixes #519
|
||||
|
||||
@@ -121,7 +121,7 @@ def agent_extract_embedded(video_part_map):
|
||||
for requested_language in config.lang_list:
|
||||
embedded_subs = stored_subs.get_by_provider(plexapi_part.id, requested_language, "embedded")
|
||||
current = stored_subs.get_any(plexapi_part.id, requested_language) or \
|
||||
requested_language in scanned_video.subtitle_languages
|
||||
requested_language in scanned_video.external_subtitle_languages
|
||||
|
||||
if not embedded_subs:
|
||||
stream_data = get_embedded_subtitle_streams(plexapi_part, requested_language=requested_language)
|
||||
|
||||
@@ -276,6 +276,41 @@ def replace_item(obj, key, replace_value):
|
||||
return obj
|
||||
|
||||
|
||||
def check_connections():
|
||||
# debug drone
|
||||
if "sonarr" in config.refiner_settings or "radarr" in config.refiner_settings:
|
||||
Log.Debug("Checking connections ...")
|
||||
log_buffer = []
|
||||
try:
|
||||
from subliminal_patch.refiners.drone import SonarrClient, RadarrClient
|
||||
log_buffer.append(["----- Connections -----"])
|
||||
for key, cls in [("sonarr", SonarrClient), ("radarr", RadarrClient)]:
|
||||
if key in config.refiner_settings:
|
||||
cname = key.capitalize()
|
||||
try:
|
||||
status = cls(**config.refiner_settings[key]).status(timeout=5)
|
||||
except HTTPError, e:
|
||||
if e.response.status_code == 401:
|
||||
log_buffer.append(("%s: NOT WORKING - BAD API KEY", cname))
|
||||
else:
|
||||
log_buffer.append(("%s: NOT WORKING - %s", cname, traceback.format_exc()))
|
||||
except:
|
||||
log_buffer.append(("%s: NOT WORKING - %s", cname, traceback.format_exc()))
|
||||
else:
|
||||
if status and status["version"]:
|
||||
log_buffer.append(("%s: OK - %s", cname, status["version"]))
|
||||
else:
|
||||
log_buffer.append(("%s: NOT WORKING - %s", cname))
|
||||
except:
|
||||
log_buffer.append(("Something went really wrong when evaluating Sonarr/Radarr: %s", traceback.format_exc()))
|
||||
finally:
|
||||
Core.log.setLevel(logging.DEBUG)
|
||||
for entry in log_buffer:
|
||||
Log.Debug(*entry)
|
||||
|
||||
Core.log.setLevel(logging.getLevelName(Prefs["log_level"]))
|
||||
|
||||
|
||||
@route(PREFIX + '/ValidatePrefs', enforce_route=True)
|
||||
def ValidatePrefs():
|
||||
Core.log.setLevel(logging.DEBUG)
|
||||
@@ -362,30 +397,7 @@ def ValidatePrefs():
|
||||
"subtitles.save.filesystem", ]:
|
||||
Log.Debug("Pref.%s: %s", attr, Prefs[attr])
|
||||
|
||||
# debug drone
|
||||
if "sonarr" in config.refiner_settings or "radarr" in config.refiner_settings:
|
||||
Log.Debug("----- Connections -----")
|
||||
try:
|
||||
from subliminal_patch.refiners.drone import SonarrClient, RadarrClient
|
||||
for key, cls in [("sonarr", SonarrClient), ("radarr", RadarrClient)]:
|
||||
if key in config.refiner_settings:
|
||||
cname = key.capitalize()
|
||||
try:
|
||||
status = cls(**config.refiner_settings[key]).status()
|
||||
except HTTPError, e:
|
||||
if e.response.status_code == 401:
|
||||
Log.Debug("%s: NOT WORKING - BAD API KEY", cname)
|
||||
else:
|
||||
Log.Debug("%s: NOT WORKING - %s", cname, traceback.format_exc())
|
||||
except:
|
||||
Log.Debug("%s: NOT WORKING - %s", cname, traceback.format_exc())
|
||||
else:
|
||||
if status and status["version"]:
|
||||
Log.Debug("%s: OK - %s", cname, status["version"])
|
||||
else:
|
||||
Log.Debug("%s: NOT WORKING - %s", cname)
|
||||
except:
|
||||
Log.Debug("Something went really wrong when evaluating Sonarr/Radarr: %s", traceback.format_exc())
|
||||
Thread.Create(check_connections)
|
||||
|
||||
# fixme: check existance of and os access of logs
|
||||
Log.Debug("----- Environment -----")
|
||||
|
||||
@@ -817,7 +817,10 @@ class Config(object):
|
||||
|
||||
def get_provider_settings(self):
|
||||
os_use_https = self.advanced.providers.opensubtitles.use_https \
|
||||
if self.advanced.providers.opensubtitles.use_https != None else True
|
||||
if self.advanced.providers.opensubtitles.use_https is not None else True
|
||||
|
||||
os_skip_wrong_fps = self.advanced.providers.opensubtitles.skip_wrong_fps \
|
||||
if self.advanced.providers.opensubtitles.skip_wrong_fps is not None else True
|
||||
|
||||
provider_settings = {'addic7ed': {'username': Prefs['provider.addic7ed.username'],
|
||||
'password': Prefs['provider.addic7ed.password'],
|
||||
@@ -831,6 +834,7 @@ class Config(object):
|
||||
'is_vip': cast_bool(Prefs['provider.opensubtitles.is_vip']),
|
||||
'use_ssl': os_use_https,
|
||||
'timeout': self.advanced.providers.opensubtitles.timeout or 15,
|
||||
'skip_wrong_fps': os_skip_wrong_fps,
|
||||
},
|
||||
'podnapisi': {
|
||||
'only_foreign': self.forced_only,
|
||||
|
||||
@@ -274,6 +274,8 @@ def get_item_hints(data):
|
||||
"title": data["original_title"] or data["series"],
|
||||
}
|
||||
)
|
||||
if hints["title"]:
|
||||
hints["title"] = hints["title"].replace(":", "")
|
||||
return hints
|
||||
|
||||
|
||||
|
||||
+2
-2
@@ -13,7 +13,7 @@
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>2.6.4.2864</string>
|
||||
<string>2.6.4.2881</string>
|
||||
<key>PlexFrameworkVersion</key>
|
||||
<string>2</string>
|
||||
<key>PlexPluginClass</key>
|
||||
@@ -32,7 +32,7 @@
|
||||
|
||||
<h1>Sub-Zero for Plex</h1><i>Subtitles done right</i>
|
||||
|
||||
Version 2.6.4.2864
|
||||
Version 2.6.4.2881
|
||||
|
||||
Originally based on @bramwalet's awesome <a href="https://github.com/bramwalet/Subliminal.bundle">Subliminal.bundle</a>
|
||||
|
||||
|
||||
@@ -514,8 +514,7 @@ def scan_video(path, dont_use_actual_file=False, hints=None, providers=None, ski
|
||||
|
||||
# guess
|
||||
hints["single_value"] = True
|
||||
if video_type == "movie":
|
||||
hints["expected_title"] = [hints["title"]]
|
||||
hints["expected_title"] = [hints["title"]]
|
||||
|
||||
guessed_result = guessit(guess_from, options=hints)
|
||||
logger.debug('GuessIt found: %s', json.dumps(guessed_result, cls=GuessitEncoder, indent=4, ensure_ascii=False))
|
||||
|
||||
@@ -31,10 +31,17 @@ custom_resolver.nameservers = ['8.8.8.8', '1.1.1.1']
|
||||
|
||||
|
||||
class CertifiSession(Session):
|
||||
timeout = 10
|
||||
|
||||
def __init__(self):
|
||||
super(CertifiSession, self).__init__()
|
||||
self.verify = pem_file
|
||||
|
||||
def request(self, *args, **kwargs):
|
||||
if kwargs.get('timeout') is None:
|
||||
kwargs['timeout'] = self.timeout
|
||||
return super(CertifiSession, self).request(*args, **kwargs)
|
||||
|
||||
|
||||
class RetryingSession(CertifiSession):
|
||||
proxied_functions = ("get", "post")
|
||||
|
||||
@@ -33,8 +33,9 @@ def fix_inconsistent_naming(title):
|
||||
:rtype: str
|
||||
|
||||
"""
|
||||
return _fix_inconsistent_naming(title, {"DC's Legends of Tomorrow": "Legends of Tomorrow",
|
||||
"Marvel's Jessica Jones": "Jessica Jones"})
|
||||
return _fix_inconsistent_naming(title, {"Stargate Origins": "Stargate: Origins",
|
||||
"Marvel's Agents of S.H.I.E.L.D.": "Marvels+Agents+of+S.H.I.E.L.D",
|
||||
"Mayans M.C.": "Mayans MC"}, True )
|
||||
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
@@ -89,7 +90,7 @@ class HosszupuskaSubtitle(Subtitle):
|
||||
def get_matches(self, video):
|
||||
matches = set()
|
||||
# series
|
||||
if video.series and sanitize(self.series) == sanitize(video.series):
|
||||
if video.series and ( sanitize(self.series) == sanitize(fix_inconsistent_naming(video.series)) or sanitize(self.series) == sanitize(video.series)):
|
||||
matches.add('series')
|
||||
# season
|
||||
if video.season and self.season == video.season:
|
||||
@@ -150,7 +151,7 @@ class HosszupuskaProvider(Provider, ProviderSubtitleArchiveMixin):
|
||||
seasona = "%02d" % season
|
||||
episodea = "%02d" % episode
|
||||
series = fix_inconsistent_naming(series)
|
||||
seriesa = series.replace(' ', '+').replace('\'', '')
|
||||
seriesa = series.replace(' ', '+')
|
||||
|
||||
# get the episode page
|
||||
logger.info('Getting the page for episode %s', episode)
|
||||
|
||||
@@ -63,12 +63,12 @@ class DroneAPIClient(object):
|
||||
out[key] = quote(value)
|
||||
return out
|
||||
|
||||
def get(self, endpoint, **params):
|
||||
def get(self, endpoint, requests_kwargs=None, **params):
|
||||
url = urljoin(self.api_url, endpoint)
|
||||
params = self.build_params(params)
|
||||
|
||||
# perform the request
|
||||
r = self.session.get(url, params=params)
|
||||
r = self.session.get(url, params=params, **(requests_kwargs or {}))
|
||||
r.raise_for_status()
|
||||
|
||||
# get the response as json
|
||||
@@ -79,8 +79,8 @@ class DroneAPIClient(object):
|
||||
return j
|
||||
return []
|
||||
|
||||
def status(self):
|
||||
return self.get("system/status")
|
||||
def status(self, **kwargs):
|
||||
return self.get("system/status", requests_kwargs=kwargs)
|
||||
|
||||
def update_video(self, video, scene_name):
|
||||
"""
|
||||
|
||||
@@ -35,11 +35,12 @@ def sanitize(string, ignore_characters=None, default_characters={'-', ':', '(',
|
||||
return string.strip().lower()
|
||||
|
||||
|
||||
def fix_inconsistent_naming(title, inconsistent_titles_dict=None):
|
||||
def fix_inconsistent_naming(title, inconsistent_titles_dict=None, no_sanitize=False):
|
||||
"""Fix titles with inconsistent naming using dictionary and sanitize them.
|
||||
|
||||
:param str title: original title.
|
||||
:param dict inconsistent_titles_dict: dictionary of titles with inconsistent naming.
|
||||
:param bool no_sanitize: indication to not sanitize title.
|
||||
:return: new title.
|
||||
:rtype: str
|
||||
|
||||
@@ -54,5 +55,9 @@ def fix_inconsistent_naming(title, inconsistent_titles_dict=None):
|
||||
pattern = re.compile('|'.join(re.escape(key) for key in inconsistent_titles_dict.keys()))
|
||||
title = pattern.sub(lambda x: inconsistent_titles_dict[x.group()], title)
|
||||
|
||||
if no_sanitize:
|
||||
return title
|
||||
else:
|
||||
return sanitize(title)
|
||||
# return fixed and sanitized title
|
||||
return sanitize(title)
|
||||
return title
|
||||
|
||||
@@ -12,6 +12,7 @@ class Video(Video_):
|
||||
hints = None
|
||||
season_fully_aired = None
|
||||
audio_languages = None
|
||||
external_subtitle_languages = None
|
||||
|
||||
def __init__(self, name, format=None, release_group=None, resolution=None, video_codec=None, audio_codec=None,
|
||||
imdb_id=None, hashes=None, size=None, subtitle_languages=None, audio_languages=None):
|
||||
@@ -22,3 +23,4 @@ class Video(Video_):
|
||||
self.plexapi_metadata = {}
|
||||
self.hints = {}
|
||||
self.audio_languages = audio_languages or set()
|
||||
self.external_subtitle_languages = set()
|
||||
|
||||
@@ -33,6 +33,7 @@ def set_existing_languages(video, video_info, external_subtitles=False, embedded
|
||||
if external_subtitles:
|
||||
# |= is update, thanks plex
|
||||
video.subtitle_languages.update(external_langs_found)
|
||||
video.external_subtitle_languages.update(external_langs_found)
|
||||
|
||||
else:
|
||||
# did we already download subtitles for this?
|
||||
|
||||
@@ -44,6 +44,9 @@ Don't expect support if you mess this up.
|
||||
"enabled_for": ["series", "movies"],
|
||||
"use_https": true,
|
||||
"timeout": 15,
|
||||
// skip subtitles with a mismatched FPS value; might lead to more results when disabled
|
||||
// but also to more false-positives
|
||||
"skip_wrong_fps": true,
|
||||
},
|
||||
"podnapisi": {
|
||||
"enabled_for": ["series", "movies"],
|
||||
|
||||
@@ -84,6 +84,12 @@ the.vbm, mmgoodnow, Vertig0ne, thliu78, tattoomees, ostman, count_confucius, ehe
|
||||
|
||||
## Changelog
|
||||
|
||||
2.6.4.2881
|
||||
- core: extract embedded: fix automatic extraction not actually writing the subtitles to disk under certain circumstances; fixes #598
|
||||
- core: sonarr/radarr: don't block the main thread while checking connectivity; fixes #597
|
||||
- providers: hosszupuska: fix inconsistent series naming (thanks @morpheus133)
|
||||
- providers: opensubtitles: add advanced setting to optionally not skip subtitles with wrong FPS; fixes #578
|
||||
|
||||
2.6.4.2864
|
||||
- core: scanning: don't fail on metadata subtitles with bad language code; fixes #596
|
||||
- providers: legendastv, napiprojekt, subscenter, tvsubtitles: fix "No language to search for" issue; fixes #596
|
||||
@@ -91,16 +97,6 @@ the.vbm, mmgoodnow, Vertig0ne, thliu78, tattoomees, ostman, count_confucius, ehe
|
||||
- menu: advanced: add skip next search all recently missing subtitles entry
|
||||
|
||||
|
||||
2.6.4.2859
|
||||
- core: fix thread.lock error (only affected the history menu, not the actual functionality)
|
||||
- core: fix audio-based conditional subtitle decision making; fixes #592
|
||||
- core: massively improve metadata subtitle storage
|
||||
- providers: opensubtitles: skip non-forced results when searching for forced
|
||||
- providers: podnapisi: skip non-forced results when searching for forced
|
||||
- submod: common: correctly pad music symbols on either side
|
||||
|
||||
|
||||
|
||||
[older changes](CHANGELOG.md)
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user