Compare commits
7 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| 9adb7d18c0 | |||
| 73da57a4f7 | |||
| 261d3c5532 | |||
| 91e55502f6 | |||
| 26846a02b5 | |||
| f2ed289c70 | |||
| 8b9109396a |
@@ -22,6 +22,7 @@ import support
|
||||
import interface
|
||||
sys.modules["interface"] = interface
|
||||
|
||||
from subliminal.cli import MutexLock
|
||||
from subzero.constants import OS_PLEX_USERAGENT, PERSONAL_MEDIA_IDENTIFIER
|
||||
from interface.menu import *
|
||||
from support.plex_media import media_to_videos, get_media_item_ids, scan_videos
|
||||
@@ -40,8 +41,9 @@ def Start():
|
||||
HTTP.CacheTime = 0
|
||||
HTTP.Headers['User-agent'] = OS_PLEX_USERAGENT
|
||||
|
||||
# configured cache to be in memory as per https://github.com/Diaoul/subliminal/issues/303
|
||||
subliminal.region.configure('dogpile.cache.memory')
|
||||
subliminal.region.configure('dogpile.cache.dbm', expiration_time=datetime.timedelta(days=30),
|
||||
arguments={'filename': os.path.join(config.data_items_path, 'subzero.dbm'),
|
||||
'lock_factory': MutexLock})
|
||||
|
||||
# clear expired intents
|
||||
intent = get_intent()
|
||||
|
||||
@@ -804,6 +804,10 @@ def AdvancedMenu(randomize=None, header=None, message=None):
|
||||
key=Callback(ResetStorage, key="ignore", randomize=timestamp()),
|
||||
title=pad_title("Reset the plugin's internal ignorelist storage"),
|
||||
))
|
||||
oc.add(DirectoryObject(
|
||||
key=Callback(InvalidateCache, randomize=timestamp()),
|
||||
title=pad_title("Invalidate Sub-Zero metadata caches (subliminal)"),
|
||||
))
|
||||
return oc
|
||||
|
||||
|
||||
@@ -940,3 +944,14 @@ def DownloadLogs():
|
||||
zip_archive.close()
|
||||
|
||||
return ZipObject(buff.getvalue())
|
||||
|
||||
|
||||
@route(PREFIX + '/invalidatecache')
|
||||
def InvalidateCache(randomize=None):
|
||||
from subliminal.cache import region
|
||||
region.invalidate()
|
||||
return AdvancedMenu(
|
||||
randomize=timestamp(),
|
||||
header='Success',
|
||||
message='Cache invalidated'
|
||||
)
|
||||
|
||||
@@ -42,6 +42,8 @@ class Config(object):
|
||||
plugin_log_path = None
|
||||
server_log_path = None
|
||||
app_support_path = None
|
||||
data_path = None
|
||||
data_items_path = None
|
||||
universal_plex_token = None
|
||||
is_development = False
|
||||
|
||||
@@ -84,6 +86,8 @@ class Config(object):
|
||||
self.full_version = u"%s %s" % (PLUGIN_NAME, self.version)
|
||||
self.set_log_paths()
|
||||
self.app_support_path = Core.app_support_path
|
||||
self.data_path = getattr(Data, "_core").storage.data_path
|
||||
self.data_items_path = os.path.join(self.data_path, "DataItems")
|
||||
self.universal_plex_token = self.get_universal_plex_token()
|
||||
|
||||
self.set_plugin_mode()
|
||||
|
||||
@@ -56,7 +56,7 @@ def find_subtitles(part):
|
||||
global_folders.append(global_subtitle_folder)
|
||||
|
||||
# normalize all paths
|
||||
paths = [os.path.normpath(os.path.realpath(helpers.unicodize(path))) for path in paths]
|
||||
paths = [os.path.normpath(helpers.unicodize(path)) for path in paths]
|
||||
|
||||
# We start by building a dictionary of files to their absolute paths. We also need to know
|
||||
# the number of media files that are actually present, in case the found local media asset
|
||||
|
||||
+1
-1
@@ -32,7 +32,7 @@
|
||||
|
||||
<h1>Sub-Zero for Plex</h1><i>Subtitles done right</i>
|
||||
|
||||
Version 2.0.0.0 DEV #6
|
||||
Version 2.0.0.0 DEV #7
|
||||
|
||||
Originally based on @bramwalet's awesome <a href="https://github.com/bramwalet/Subliminal.bundle">Subliminal.bundle</a>
|
||||
|
||||
|
||||
@@ -1,9 +1,11 @@
|
||||
# coding=utf-8
|
||||
|
||||
import importlib
|
||||
import subliminal
|
||||
|
||||
# patch subliminal's subtitle and provider base
|
||||
from .subtitle import PatchedSubtitle
|
||||
from .providers import Provider
|
||||
from .http import RetryingSession
|
||||
subliminal.subtitle.Subtitle = PatchedSubtitle
|
||||
|
||||
@@ -13,34 +15,15 @@ except ValueError:
|
||||
# already registered
|
||||
pass
|
||||
|
||||
# inject our requests.Session wrapper for automatic retry
|
||||
subliminal.providers.addic7ed.Session = RetryingSession
|
||||
subliminal.providers.podnapisi.Session = RetryingSession
|
||||
subliminal.providers.tvsubtitles.Session = RetryingSession
|
||||
subliminal.providers.opensubtitles.Session = RetryingSession
|
||||
subliminal.providers.legendastv.Session = RetryingSession
|
||||
subliminal.providers.napiprojekt.Session = RetryingSession
|
||||
subliminal.providers.shooter.Session = RetryingSession
|
||||
subliminal.providers.subscenter.Session = RetryingSession
|
||||
|
||||
from subliminal.providers.addic7ed import Addic7edSubtitle
|
||||
from subliminal.providers.podnapisi import PodnapisiSubtitle
|
||||
from subliminal.providers.tvsubtitles import TVsubtitlesSubtitle
|
||||
from subliminal.providers.opensubtitles import OpenSubtitlesSubtitle
|
||||
from subliminal.providers.legendastv import LegendasTVSubtitle
|
||||
from subliminal.providers.napiprojekt import NapiProjektSubtitle
|
||||
from subliminal.providers.shooter import ShooterSubtitle
|
||||
from subliminal.providers.subscenter import SubsCenterSubtitle
|
||||
|
||||
# add our patched base classes
|
||||
setattr(Addic7edSubtitle, "__bases__", (PatchedSubtitle,))
|
||||
setattr(PodnapisiSubtitle, "__bases__", (PatchedSubtitle,))
|
||||
setattr(TVsubtitlesSubtitle, "__bases__", (PatchedSubtitle,))
|
||||
setattr(OpenSubtitlesSubtitle, "__bases__", (PatchedSubtitle,))
|
||||
setattr(LegendasTVSubtitle, "__bases__", (PatchedSubtitle,))
|
||||
setattr(NapiProjektSubtitle, "__bases__", (PatchedSubtitle,))
|
||||
setattr(ShooterSubtitle, "__bases__", (PatchedSubtitle,))
|
||||
setattr(SubsCenterSubtitle, "__bases__", (PatchedSubtitle,))
|
||||
for name in ("Addic7ed", "Podnapisi", "TVsubtitles", "OpenSubtitles", "LegendasTV", "NapiProjekt", "Shooter",
|
||||
"SubsCenter"):
|
||||
mod = importlib.import_module("subliminal.providers.%s" % name.lower())
|
||||
setattr(getattr(mod, "%sSubtitle" % name), "__bases__", (PatchedSubtitle,))
|
||||
setattr(getattr(mod, "%sProvider" % name), "__bases__", (Provider,))
|
||||
|
||||
# inject our requests.Session wrapper for automatic retry
|
||||
setattr(mod, "Session", RetryingSession)
|
||||
|
||||
from .core import scan_video, search_external_subtitles, list_all_subtitles, save_subtitles, refine
|
||||
from .score import compute_score
|
||||
|
||||
@@ -1,2 +1,7 @@
|
||||
# coding=utf-8
|
||||
|
||||
from subliminal.providers import Provider as _Provider
|
||||
|
||||
|
||||
class Provider(_Provider):
|
||||
hash_verifiable = False
|
||||
|
||||
@@ -15,6 +15,8 @@ logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
class OpenSubtitlesSubtitle(_OpenSubtitlesSubtitle):
|
||||
hash_verifiable = True
|
||||
|
||||
def __init__(self, language, hearing_impaired, page_link, subtitle_id, matched_by, movie_kind, hash, movie_name,
|
||||
movie_release_name, movie_year, movie_imdb_id, series_season, series_episode, query_parameters,
|
||||
filename, encoding, fps):
|
||||
@@ -54,6 +56,7 @@ class OpenSubtitlesSubtitle(_OpenSubtitlesSubtitle):
|
||||
class OpenSubtitlesProvider(ProviderRetryMixin, _OpenSubtitlesProvider):
|
||||
only_foreign = True
|
||||
subtitle_class = OpenSubtitlesSubtitle
|
||||
hash_verifiable = True
|
||||
|
||||
def __init__(self, username=None, password=None, use_tag_search=False, only_foreign=False):
|
||||
if username is not None and password is None or username is None and password is not None:
|
||||
|
||||
@@ -40,19 +40,22 @@ def compute_score(matches, subtitle, video, hearing_impaired=None):
|
||||
movie_hash_valid_if = {"video_codec", "format"}
|
||||
|
||||
# on hash match, discard everything else
|
||||
if 'hash' in matches:
|
||||
# hash is error-prone, try to fix that
|
||||
hash_valid_if = episode_hash_valid_if if is_episode else movie_hash_valid_if
|
||||
if subtitle.hash_verifiable:
|
||||
if 'hash' in matches:
|
||||
# hash is error-prone, try to fix that
|
||||
hash_valid_if = episode_hash_valid_if if is_episode else movie_hash_valid_if
|
||||
|
||||
if hash_valid_if <= set(matches):
|
||||
# series, season and episode matched, hash is valid
|
||||
logger.debug('Using valid hash, as %s are correct (%r) and (%r)', hash_valid_if, matches, video)
|
||||
matches &= {'hash', 'hearing_impaired'}
|
||||
else:
|
||||
# no match, invalidate hash
|
||||
logger.debug('Ignoring hash as other matches are wrong (missing: %r) and (%r)', hash_valid_if - matches,
|
||||
video)
|
||||
matches -= {"hash"}
|
||||
if hash_valid_if <= set(matches):
|
||||
# series, season and episode matched, hash is valid
|
||||
logger.debug('Using valid hash, as %s are correct (%r) and (%r)', hash_valid_if, matches, video)
|
||||
matches &= {'hash', 'hearing_impaired'}
|
||||
else:
|
||||
# no match, invalidate hash
|
||||
logger.debug('Ignoring hash as other matches are wrong (missing: %r) and (%r)', hash_valid_if - matches,
|
||||
video)
|
||||
matches -= {"hash"}
|
||||
elif 'hash' in matches:
|
||||
logger.debug('Hash not verifiable for this provider. Keeping it')
|
||||
|
||||
# handle equivalent matches
|
||||
if is_episode:
|
||||
|
||||
@@ -16,6 +16,7 @@ class PatchedSubtitle(Subtitle):
|
||||
storage_path = None
|
||||
release_info = None
|
||||
matches = None
|
||||
hash_verifiable = False
|
||||
|
||||
def __repr__(self):
|
||||
return '<%s %r [%s]>' % (
|
||||
|
||||
Reference in New Issue
Block a user