def initialize(self): self.fs_encoding = get_viable_encoding() self.version = self.get_version() self.full_version = u"%s %s" % (PLUGIN_NAME, self.version) self.set_plugin_mode() self.set_plugin_lock() self.lang_list = self.get_lang_list() self.subtitle_destination_folder = self.get_subtitle_destination_folder( ) self.providers = self.get_providers() self.provider_settings = self.get_provider_settings() self.max_recent_items_per_library = int_or_default( Prefs["scheduler.max_recent_items_per_library"], 2000) self.sections = list(Plex["library"].sections()) self.missing_permissions = [] self.ignore_sz_files = cast_bool(Prefs["subtitles.ignore_fs"]) self.ignore_paths = self.parse_ignore_paths() self.enabled_sections = self.check_enabled_sections() self.permissions_ok = self.check_permissions() self.notify_executable = self.check_notify_executable() self.enforce_encoding = cast_bool(Prefs['subtitles.enforce_encoding']) self.chmod = self.check_chmod() self.forced_only = cast_bool(Prefs["subtitles.only_foreign"]) self.initialized = True
def check_permissions(self): if not cast_bool(Prefs["subtitles.save.filesystem"]) or not cast_bool( Prefs["check_permissions"]): return True self.missing_permissions = [] use_ignore_fs = Prefs["subtitles.ignore_fs"] all_permissions_ok = True for section in self.sections: if section.key not in self.enabled_sections: continue title = section.title for location in section: path_str = location.path if isinstance(path_str, unicode): path_str = path_str.encode(self.fs_encoding) if use_ignore_fs: # check whether we've got an ignore file inside the section path if self.is_physically_ignored(path_str): continue if self.is_path_ignored(path_str): # is the path in our ignored paths setting? continue # section not ignored, check for write permissions if not check_write_permissions(path_str): # not enough permissions self.missing_permissions.append((title, location.path)) all_permissions_ok = False return all_permissions_ok
def save_subtitles(scanned_video_part_map, downloaded_subtitles, mode="a", bare_save=False, mods=None, set_current=True): """ :param set_current: save the subtitle as the current one :param scanned_video_part_map: :param downloaded_subtitles: :param mode: :param bare_save: don't trigger anything; don't store information :param mods: enabled mods :return: """ meta_fallback = False save_successful = False # big fixme: scanned_video_part_map isn't needed to the current extent. rewrite. if mods: for video, video_subtitles in downloaded_subtitles.items(): if not video_subtitles: continue for subtitle in video_subtitles: Log.Info("Applying mods: %s to %s", mods, subtitle) subtitle.mods = mods subtitle.plex_media_fps = video.fps storage = "metadata" save_to_fs = cast_bool(Prefs['subtitles.save.filesystem']) if save_to_fs: storage = "filesystem" if set_current: if save_to_fs: try: Log.Debug("Using filesystem as subtitle storage") save_subtitles_to_file(downloaded_subtitles) except OSError: if cast_bool(Prefs["subtitles.save.metadata_fallback"]): meta_fallback = True storage = "metadata" else: raise else: save_successful = True if not save_to_fs or meta_fallback: if meta_fallback: Log.Debug("Using metadata as subtitle storage, because filesystem storage failed") else: Log.Debug("Using metadata as subtitle storage") save_successful = save_subtitles_to_metadata(scanned_video_part_map, downloaded_subtitles) if not bare_save and save_successful and config.notify_executable: notify_executable(config.notify_executable, scanned_video_part_map, downloaded_subtitles, storage) if (not bare_save and save_successful) or not set_current: store_subtitle_info(scanned_video_part_map, downloaded_subtitles, storage, mode=mode, set_current=set_current) return save_successful
def get_provider_settings(self): os_use_https = self.advanced.providers.opensubtitles.use_https \ if self.advanced.providers.opensubtitles.use_https != None else True provider_settings = { 'addic7ed': { 'username': Prefs['provider.addic7ed.username'], 'password': Prefs['provider.addic7ed.password'], 'use_random_agents': cast_bool(Prefs['provider.addic7ed.use_random_agents1']), }, 'opensubtitles': { 'username': Prefs['provider.opensubtitles.username'], 'password': Prefs['provider.opensubtitles.password'], 'use_tag_search': self.exact_filenames, 'only_foreign': self.forced_only, 'is_vip': cast_bool(Prefs['provider.opensubtitles.is_vip']), 'use_ssl': os_use_https, 'timeout': self.advanced.providers.opensubtitles.timeout or 15 }, 'podnapisi': { 'only_foreign': self.forced_only, }, 'legendastv': { 'username': Prefs['provider.legendastv.username'], 'password': Prefs['provider.legendastv.password'], } } return provider_settings
def get_provider_settings(self): provider_settings = { 'addic7ed': { 'username': Prefs['provider.addic7ed.username'], 'password': Prefs['provider.addic7ed.password'], 'use_random_agents': cast_bool(Prefs['provider.addic7ed.use_random_agents']), }, 'opensubtitles': { 'username': Prefs['provider.opensubtitles.username'], 'password': Prefs['provider.opensubtitles.password'], 'use_tag_search': self.exact_filenames, 'only_foreign': self.forced_only, 'is_vip': cast_bool(Prefs['provider.opensubtitles.is_vip']) }, 'podnapisi': { 'only_foreign': self.forced_only, }, 'legendastv': { 'username': Prefs['provider.legendastv.username'], 'password': Prefs['provider.legendastv.password'], } } return provider_settings
def get_provider_settings(self): provider_settings = { 'addic7ed': { 'username': Prefs['provider.addic7ed.username'], 'password': Prefs['provider.addic7ed.password'], 'use_random_agents': cast_bool(Prefs['provider.addic7ed.use_random_agents']), }, 'opensubtitles': { 'username': Prefs['provider.opensubtitles.username'], 'password': Prefs['provider.opensubtitles.password'], 'use_tag_search': cast_bool(Prefs['provider.opensubtitles.use_tags']), 'only_foreign': cast_bool(Prefs['subtitles.only_foreign']) }, 'podnapisi': { 'only_foreign': cast_bool(Prefs['subtitles.only_foreign']) }, 'legendastv': { 'username': Prefs['provider.legendastv.username'], 'password': Prefs['provider.legendastv.password'], }, } return provider_settings
def get_provider_settings(self): os_use_https = self.advanced.providers.opensubtitles.get( "use_https", True) os_skip_wrong_fps = self.advanced.providers.opensubtitles.get( "skip_wrong_fps", True) provider_settings = { 'addic7ed': { 'username': Prefs['provider.addic7ed.username'], 'password': Prefs['provider.addic7ed.password'], 'is_vip': cast_bool(Prefs['provider.addic7ed.is_vip']), }, 'opensubtitles': { 'username': Prefs['provider.opensubtitles.username'], 'password': Prefs['provider.opensubtitles.password'], 'use_tag_search': self.exact_filenames, 'only_foreign': self.forced_only, 'also_foreign': self.forced_also, '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, 'also_foreign': self.forced_also, }, 'titlovi': { 'username': Prefs['provider.titlovi.username'], 'password': Prefs['provider.titlovi.password'], }, 'napisy24': { 'username': Prefs['provider.napisy24.username'], 'password': Prefs['provider.napisy24.password'], }, 'subscene': { 'only_foreign': self.forced_only, 'username': Prefs['provider.subscene.username'], 'password': Prefs['provider.subscene.password'], }, 'legendastv': { 'username': Prefs['provider.legendastv.username'], 'password': Prefs['provider.legendastv.password'], }, 'assrt': { 'token': Prefs['provider.assrt.token'], }, 'ktuvit': { 'username': Prefs['provider.ktuvit.username'], 'password': Prefs['provider.ktuvit.password'], }, } return provider_settings
def get_providers(self): providers = { 'opensubtitles': cast_bool(Prefs['provider.opensubtitles.enabled']), # 'thesubdb': Prefs['provider.thesubdb.enabled'], 'podnapisi': cast_bool(Prefs['provider.podnapisi.enabled']), 'titlovi': cast_bool(Prefs['provider.titlovi.enabled']), 'addic7ed': cast_bool(Prefs['provider.addic7ed.enabled']), 'tvsubtitles': cast_bool(Prefs['provider.tvsubtitles.enabled']), 'legendastv': cast_bool(Prefs['provider.legendastv.enabled']), 'napiprojekt': cast_bool(Prefs['provider.napiprojekt.enabled']), 'shooter': cast_bool(Prefs['provider.shooter.enabled']), 'subscenter': False, } # ditch non-forced-subtitles-reporting providers if self.forced_only: providers["addic7ed"] = False providers["tvsubtitles"] = False providers["legendastv"] = False providers["napiprojekt"] = False providers["shooter"] = False providers["titlovi"] = False providers["subscenter"] = False return filter(lambda prov: providers[prov], providers)
def save_subtitles_to_file(subtitles): fld_custom = Prefs["subtitles.save.subFolder.Custom"].strip() \ if Prefs["subtitles.save.subFolder.Custom"] else None for video, video_subtitles in subtitles.items(): if not video_subtitles: continue fld = None if fld_custom or Prefs["subtitles.save.subFolder"] != "current folder": # specific subFolder requested, create it if it doesn't exist fld_base = os.path.split(video.name)[0] if fld_custom: if fld_custom.startswith("/"): # absolute folder fld = fld_custom else: fld = os.path.join(fld_base, fld_custom) else: fld = os.path.join(fld_base, Prefs["subtitles.save.subFolder"]) fld = force_unicode(fld) if not os.path.exists(fld): os.makedirs(fld) subliminal.api.save_subtitles( video, video_subtitles, directory=fld, single=cast_bool(Prefs['subtitles.only_one']), encode_with=force_utf8 if config.enforce_encoding else None, chmod=config.chmod, forced_tag=config.forced_only, path_decoder=force_unicode) return True
def match_ietf_language(s): language_match = re.match(".+\.([^\.]+)$" if not helpers.cast_bool(Prefs["subtitles.language.ietf_display"]) else IETF_MATCH, s) if language_match and len(language_match.groups()) == 1: language = language_match.groups()[0] return language return s
def get_provider_settings(self): os_use_https = self.advanced.providers.opensubtitles.use_https \ 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'], }, 'opensubtitles': {'username': Prefs['provider.opensubtitles.username'], 'password': Prefs['provider.opensubtitles.password'], 'use_tag_search': self.exact_filenames, 'only_foreign': self.forced_only, 'also_foreign': self.forced_also, '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, 'also_foreign': self.forced_also, }, 'subscene': { 'only_foreign': self.forced_only, }, 'legendastv': {'username': Prefs['provider.legendastv.username'], 'password': Prefs['provider.legendastv.password'], }, 'assrt': {'token': Prefs['provider.assrt.token'], } } return provider_settings
def get_providers(self): providers = { 'opensubtitles': cast_bool(Prefs['provider.opensubtitles.enabled']), #'thesubdb': Prefs['provider.thesubdb.enabled'], 'podnapisi': cast_bool(Prefs['provider.podnapisi.enabled']), 'addic7ed': cast_bool(Prefs['provider.addic7ed.enabled']), 'tvsubtitles': cast_bool(Prefs['provider.tvsubtitles.enabled']) } # ditch non-forced-subtitles-reporting providers if cast_bool(Prefs['subtitles.only_foreign']): providers["addic7ed"] = False providers["tvsubtitles"] = False return filter(lambda prov: providers[prov], providers)
def match_ietf_language(s): language_match = re.match(".+\.([^\.]+)$" if not helpers.cast_bool(Prefs["subtitles.language.ietf"]) else IETF_MATCH, s) if language_match and len(language_match.groups()) == 1: language = language_match.groups()[0] return language return s
def initialize(self): self.libraries_root = os.path.abspath( os.path.join(get_root_path(), "..")) self.init_libraries() self.fs_encoding = get_viable_encoding() self.plugin_info = self.get_plugin_info() self.is_development = self.get_dev_mode() self.version = self.get_version() 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.plex_token = os.environ.get("PLEXTOKEN", self.universal_plex_token) os.environ["SZ_USER_AGENT"] = self.get_user_agent() self.providers = self.get_providers() self.set_plugin_mode() self.set_plugin_lock() self.set_activity_modes() self.lang_list = self.get_lang_list() self.subtitle_destination_folder = self.get_subtitle_destination_folder( ) self.subtitle_formats = self.get_subtitle_formats() self.forced_only = cast_bool(Prefs["subtitles.only_foreign"]) self.provider_settings = self.get_provider_settings() self.max_recent_items_per_library = int_or_default( Prefs["scheduler.max_recent_items_per_library"], 2000) self.sections = list(Plex["library"].sections()) self.missing_permissions = [] self.ignore_sz_files = cast_bool(Prefs["subtitles.ignore_fs"]) self.ignore_paths = self.parse_ignore_paths() self.enabled_sections = self.check_enabled_sections() self.permissions_ok = self.check_permissions() self.notify_executable = self.check_notify_executable() self.remove_hi = cast_bool(Prefs['subtitles.remove_hi']) self.fix_ocr = cast_bool(Prefs['subtitles.fix_ocr']) self.fix_common = cast_bool(Prefs['subtitles.fix_common']) self.colors = Prefs['subtitles.colors'] if Prefs[ 'subtitles.colors'] != "don't change" else None self.chmod = self.check_chmod() self.exotic_ext = cast_bool(Prefs["subtitles.scan.exotic_ext"]) self.treat_und_as_first = cast_bool( Prefs["subtitles.language.treat_und_as_first"]) self.ext_match_strictness = self.determine_ext_sub_strictness() self.default_mods = self.get_default_mods() self.debug_mods = cast_bool(Prefs['log_debug_mods']) self.subtitles_save_to = Prefs['subtitles.save.filesystem'] self.no_refresh = os.environ.get("SZ_NO_REFRESH", False) self.initialized = True
def get_subtitle_destination_folder(self): if not Prefs["subtitles.save.filesystem"]: return fld_custom = Prefs["subtitles.save.subFolder.Custom"].strip() if cast_bool( Prefs["subtitles.save.subFolder.Custom"]) else None return fld_custom or ( Prefs["subtitles.save.subFolder"] if Prefs["subtitles.save.subFolder"] != "current folder" else None)
def subtitle_helpers(filename): filename = helpers.unicodize(filename) helper_classes = [DefaultSubtitleHelper] if helpers.cast_bool(Prefs["subtitles.scan.exotic_ext"]): helper_classes.insert(0, VobSubSubtitleHelper) for cls in helper_classes: if cls.is_helper_for(filename): return cls(filename) return None
def init_subliminal_patches(self): # configure custom subtitle destination folders for scanning pre-existing subs Log.Debug("Patching subliminal ...") dest_folder = self.subtitle_destination_folder subliminal_patch.patch_video.CUSTOM_PATHS = [dest_folder ] if dest_folder else [] subliminal_patch.patch_video.INCLUDE_EXOTIC_SUBS = cast_bool( Prefs["subtitles.scan.exotic_ext"]) subliminal_patch.patch_provider_pool.DOWNLOAD_TRIES = int( Prefs['subtitles.try_downloads']) subliminal.video.Episode.scores["addic7ed_boost"] = int( Prefs['provider.addic7ed.boost_by'])
def parse_rename_mode(self): # fixme: exact_filenames should be determined via callback combined with info about the current video # (original_name) mode = str(Prefs["media_rename1"]) self.refiner_settings = {} if cast_bool(Prefs['use_file_info_file']): self.refiner_settings["file_info_file"] = True self.exact_filenames = True if mode == "none of the above": return elif mode == "Symlink to original file": self.refiner_settings["symlinks"] = True self.exact_filenames = True return elif mode == "I keep the original filenames": self.exact_filenames = True return if mode in ("Filebot", "Sonarr/Radarr/Filebot"): self.refiner_settings["filebot"] = True if mode in ("Sonarr/Radarr (fill api info below)", "Sonarr/Radarr/Filebot"): if Prefs["drone_api.sonarr.url"] and Prefs[ "drone_api.sonarr.api_key"]: self.refiner_settings["sonarr"] = { "base_url": Prefs["drone_api.sonarr.url"], "api_key": Prefs["drone_api.sonarr.api_key"], } if self.advanced.refiners.sonarr: self.refiner_settings["sonarr"].update( self.advanced.refiners.sonarr) self.exact_filenames = True if Prefs["drone_api.radarr.url"] and Prefs[ "drone_api.radarr.api_key"]: self.refiner_settings["radarr"] = { "base_url": Prefs["drone_api.radarr.url"], "api_key": Prefs["drone_api.radarr.api_key"] } if self.advanced.refiners.radarr: self.refiner_settings["radarr"].update( self.advanced.refiners.radarr) self.exact_filenames = True
def save_subtitles_to_file(subtitles, tags=None): for video, video_subtitles in subtitles.items(): if not video_subtitles: continue if not isinstance(video, types.StringTypes): file_path = video.name else: file_path = video fld = get_target_folder(file_path) subliminal_save_subtitles(file_path, video_subtitles, directory=fld, single=cast_bool(Prefs['subtitles.only_one']), chmod=config.chmod, path_decoder=force_unicode, debug_mods=config.debug_mods, formats=config.subtitle_formats, tags=tags) return True
def get_subtitle_sub_dir(self): """ :return: folder, is_absolute """ if not cast_bool(Prefs['subtitles.save.filesystem']): return None, None if Prefs["subtitles.save.subFolder.Custom"]: return Prefs["subtitles.save.subFolder.Custom"], os.path.isabs(Prefs["subtitles.save.subFolder.Custom"]) if Prefs["subtitles.save.subFolder"] == "current folder": return ".", False return Prefs["subtitles.save.subFolder"], False
def check_permissions(self): if not cast_bool(Prefs["subtitles.save.filesystem"]) or not cast_bool(Prefs["check_permissions"]): return True self.missing_permissions = [] use_include_exclude_fs = self.include_exclude_sz_files all_permissions_ok = True for section in self.sections: if section.key not in self.enabled_sections: continue title = section.title for location in section: path_str = location.path if isinstance(path_str, unicode): path_str = path_str.encode(self.fs_encoding) if not os.path.exists(path_str): continue if use_include_exclude_fs: # check whether we've got an ignore file inside the section path if not self.is_physically_wanted(path_str): continue if not self.is_path_wanted(path_str): # is the path in our ignored paths setting? continue # section not ignored, check for write permissions if not check_write_permissions(path_str): # not enough permissions self.missing_permissions.append((title, location.path)) all_permissions_ok = False return all_permissions_ok
def parse_rename_mode(self): # fixme: exact_filenames should be determined via callback combined with info about the current video # (original_name) mode = str(Prefs["media_rename1"]) self.refiner_settings = {} if cast_bool(Prefs['use_file_info_file']): self.refiner_settings["file_info_file"] = True self.exact_filenames = True if mode == "none of the above": return elif mode == "Symlink to original file": self.refiner_settings["symlinks"] = True self.exact_filenames = True return elif mode == "I keep the original filenames": self.exact_filenames = True return if mode in ("Filebot", "Sonarr/Radarr/Filebot"): self.refiner_settings["filebot"] = True if mode in ("Sonarr/Radarr (fill api info below)", "Sonarr/Radarr/Filebot"): if Prefs["drone_api.sonarr.url"] and Prefs["drone_api.sonarr.api_key"]: self.refiner_settings["sonarr"] = { "base_url": Prefs["drone_api.sonarr.url"], "api_key": Prefs["drone_api.sonarr.api_key"], } if self.advanced.refiners.sonarr: self.refiner_settings["sonarr"].update(self.advanced.refiners.sonarr) self.exact_filenames = True if Prefs["drone_api.radarr.url"] and Prefs["drone_api.radarr.api_key"]: self.refiner_settings["radarr"] = { "base_url": Prefs["drone_api.radarr.url"], "api_key": Prefs["drone_api.radarr.api_key"] } if self.advanced.refiners.radarr: self.refiner_settings["radarr"].update(self.advanced.refiners.radarr) self.exact_filenames = True
def provider_pool(self): if cast_bool(Prefs['providers.multithreading']): return subliminal_patch.core.SZAsyncProviderPool return subliminal_patch.core.SZProviderPool
def get_providers(self, media_type="series"): providers = { 'opensubtitles': cast_bool(Prefs['provider.opensubtitles.enabled']), # 'thesubdb': Prefs['provider.thesubdb.enabled'], 'podnapisi': cast_bool(Prefs['provider.podnapisi.enabled']), 'titlovi': cast_bool(Prefs['provider.titlovi.enabled']), 'addic7ed': cast_bool(Prefs['provider.addic7ed.enabled']), 'tvsubtitles': cast_bool(Prefs['provider.tvsubtitles.enabled']), 'legendastv': cast_bool(Prefs['provider.legendastv.enabled']), 'napiprojekt': cast_bool(Prefs['provider.napiprojekt.enabled']), 'hosszupuska': cast_bool(Prefs['provider.hosszupuska.enabled']), 'shooter': False, 'subscene': cast_bool(Prefs['provider.subscene.enabled']), 'argenteam': cast_bool(Prefs['provider.argenteam.enabled']), 'subscenter': False, } providers_by_prefs = copy.deepcopy(providers) # disable subscene for movies by default if media_type == "movies": providers["subscene"] = False # ditch non-forced-subtitles-reporting providers if self.forced_only: providers["addic7ed"] = False providers["tvsubtitles"] = False providers["legendastv"] = False providers["napiprojekt"] = False providers["shooter"] = False providers["hosszupuska"] = False providers["titlovi"] = False providers["argenteam"] = False if not self.unrar and providers["legendastv"]: providers["legendastv"] = False Log.Info("Disabling LegendasTV, because UnRAR wasn't found") # advanced settings if media_type and self.advanced.providers: for provider, data in self.advanced.providers.iteritems(): if provider not in providers or not providers_by_prefs[ provider]: continue if data["enabled_for"] is not None: providers[provider] = media_type in data["enabled_for"] if "provider_throttle" not in Dict: Dict["provider_throttle"] = {} changed = False for provider, enabled in dict(providers).iteritems(): reason, until, throttle_desc = Dict["provider_throttle"].get( provider, (None, None, None)) if reason: now = datetime.datetime.now() if now < until: Log.Info("Not using %s until %s, because of: %s", provider, until.strftime("%y/%m/%d %H:%M"), reason) providers[provider] = False else: Log.Info("Using %s again after %s, (disabled because: %s)", provider, throttle_desc, reason) del Dict["provider_throttle"][provider] changed = True if changed: Dict.Save() return filter(lambda prov: providers[prov], providers)
def initialize(self): self.libraries_root = os.path.abspath( os.path.join(get_root_path(), "..")) self.init_libraries() if is_windows_special_path: Log.Warn( "The Plex metadata folder is residing inside a folder with special characters. " "Multithreading and playback activities will be disabled.") self.fs_encoding = get_viable_encoding() self.plugin_info = self.get_plugin_info() self.is_development = self.get_dev_mode() self.version = self.get_version() 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.plex_token = os.environ.get("PLEXTOKEN", self.universal_plex_token) subzero.constants.DEFAULT_TIMEOUT = lib.DEFAULT_TIMEOUT = self.pms_request_timeout = \ min(cast_int(Prefs['pms_request_timeout'], 15), 45) self.low_impact_mode = cast_bool(Prefs['low_impact_mode']) self.new_style_cache = cast_bool(Prefs['new_style_cache']) self.pack_cache_dir = self.get_pack_cache_dir() self.advanced = self.get_advanced_config() os.environ["SZ_USER_AGENT"] = self.get_user_agent() self.setup_proxies() self.set_plugin_mode() self.set_plugin_lock() self.set_activity_modes() self.parse_rename_mode() self.subtitle_destination_folder = self.get_subtitle_destination_folder( ) self.subtitle_formats = self.get_subtitle_formats() self.forced_only = cast_bool(Prefs["subtitles.only_foreign"]) self.max_recent_items_per_library = int_or_default( Prefs["scheduler.max_recent_items_per_library"], 2000) self.sections = list(Plex["library"].sections()) self.missing_permissions = [] self.ignore_sz_files = cast_bool(Prefs["subtitles.ignore_fs"]) self.ignore_paths = self.parse_ignore_paths() self.enabled_sections = self.check_enabled_sections() self.permissions_ok = self.check_permissions() self.notify_executable = self.check_notify_executable() self.remove_hi = cast_bool(Prefs['subtitles.remove_hi']) self.remove_tags = cast_bool(Prefs['subtitles.remove_tags']) self.fix_ocr = cast_bool(Prefs['subtitles.fix_ocr']) self.fix_common = cast_bool(Prefs['subtitles.fix_common']) self.reverse_rtl = cast_bool(Prefs['subtitles.reverse_rtl']) self.colors = Prefs['subtitles.colors'] if Prefs[ 'subtitles.colors'] != "don't change" else None self.chmod = self.check_chmod() self.exotic_ext = cast_bool(Prefs["subtitles.scan.exotic_ext"]) self.treat_und_as_first = cast_bool( Prefs["subtitles.language.treat_und_as_first"]) self.subtitle_sub_dir = self.get_subtitle_sub_dir() self.ext_match_strictness = self.determine_ext_sub_strictness() self.default_mods = self.get_default_mods() self.debug_mods = cast_bool(Prefs['log_debug_mods']) self.no_refresh = os.environ.get("SZ_NO_REFRESH", False) self.plex_transcoder = self.get_plex_transcoder() self.only_one = cast_bool(Prefs['subtitles.only_one']) self.embedded_auto_extract = cast_bool( Prefs["subtitles.embedded.autoextract"]) self.ietf_as_alpha3 = cast_bool( Prefs["subtitles.language.ietf_normalize"]) self.initialized = True
def find_subtitles(part): lang_sub_map = {} part_filename = helpers.unicodize(part.file) part_basename = os.path.splitext(os.path.basename(part_filename))[0] use_filesystem = helpers.cast_bool(Prefs["subtitles.save.filesystem"]) paths = [os.path.dirname(part_filename)] if use_filesystem else [] global_subtitle_folder = None global_folders = [] if use_filesystem: # Check for local subtitles subdirectory sub_dir_base = paths[0] sub_dir_list = [] if Prefs["subtitles.save.subFolder"] != "current folder": # got selected subfolder sub_dir_list.append( os.path.join(sub_dir_base, Prefs["subtitles.save.subFolder"])) sub_dir_custom = Prefs["subtitles.save.subFolder.Custom"].strip() \ if Prefs["subtitles.save.subFolder.Custom"] else None if sub_dir_custom: # got custom subfolder sub_dir_custom = os.path.normpath(sub_dir_custom) if os.path.isdir(sub_dir_custom) and os.path.isabs(sub_dir_custom): # absolute folder sub_dir_list.append(sub_dir_custom) global_folders.append(sub_dir_custom) else: # relative folder fld = os.path.join(sub_dir_base, sub_dir_custom) sub_dir_list.append(fld) for sub_dir in sub_dir_list: if os.path.isdir(sub_dir): paths.append(sub_dir) # Check for a global subtitle location global_subtitle_folder = os.path.join(Core.app_support_path, 'Subtitles') if os.path.exists(global_subtitle_folder): paths.append(global_subtitle_folder) global_folders.append(global_subtitle_folder) # normalize all paths paths = [ os.path.normpath(os.path.realpath(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 # is limited to a single instance per media file. # file_paths = {} total_media_files = 0 media_files = [] for path in paths: for file_path_listing in os.listdir(path.encode( sz_config.fs_encoding)): # When using os.listdir with a unicode path, it will always return a string using the # NFD form. However, we internally are using the form NFC and therefore need to convert # it to allow correct regex / comparisons to be performed. # file_path_listing = helpers.unicodize(file_path_listing) if os.path.isfile( os.path.join(path, file_path_listing).encode( sz_config.fs_encoding)): file_paths[file_path_listing.lower()] = os.path.join( path, file_path_listing) # If we've found an actual media file, we should record it. (root, ext) = os.path.splitext(file_path_listing) if ext.lower()[1:] in config.VIDEO_EXTS: total_media_files += 1 # collect found media files media_files.append(root) # cleanup any leftover subtitle if no associated media file was found if helpers.cast_bool(Prefs["subtitles.autoclean"]): for path in paths: # we can't housekeep the global subtitle folders as we don't know about *all* media files # in a library; skip them skip_path = False for fld in global_folders: if path.startswith(fld): Log.Info("Skipping housekeeping of folder: %s", path) skip_path = True break if skip_path: continue for file_path_listing in os.listdir( path.encode(sz_config.fs_encoding)): file_path_listing = helpers.unicodize(file_path_listing) enc_fn = os.path.join(path, file_path_listing).encode( sz_config.fs_encoding) if os.path.isfile(enc_fn): (root, ext) = os.path.splitext(file_path_listing) # it's a subtitle file if ext.lower()[1:] in config.SUBTITLE_EXTS: # get fn without forced/default/normal tag split_tag = root.rsplit(".", 1) if len(split_tag) > 1 and split_tag[1].lower() in [ 'forced', 'normal', 'default' ]: root = split_tag[0] # get associated media file name without language sub_fn = subtitlehelpers.ENDSWITH_LANGUAGECODE_RE.sub( "", root) # subtitle basename and basename without possible language tag not found in collected # media files? kill. if root not in media_files and sub_fn not in media_files: Log.Info("Removing leftover subtitle: %s", os.path.join(path, file_path_listing)) try: os.remove(enc_fn) except (OSError, IOError): Log.Error("Removing failed") Log('Looking for subtitle media in %d paths with %d media files.', len(paths), total_media_files) Log('Paths: %s', ", ".join([helpers.unicodize(p) for p in paths])) for file_path in file_paths.values(): local_filename = os.path.basename(file_path) bn, ext = os.path.splitext(local_filename) local_basename = helpers.unicodize(bn) # get fn without forced/default/normal tag split_tag = local_basename.rsplit(".", 1) if len(split_tag) > 1 and split_tag[1].lower() in [ 'forced', 'normal', 'default' ]: local_basename = split_tag[0] # split off possible language tag local_basename2 = local_basename.rsplit('.', 1)[0] filename_matches_part = local_basename == part_basename or local_basename2 == part_basename filename_contains_part = part_basename in local_basename if not ext.lower()[1:] in config.SUBTITLE_EXTS: continue # if the file is located within the global subtitle folders and its name doesn't match exactly, ignore it if global_folders and not filename_matches_part: skip_path = False for fld in global_folders: if file_path.startswith(fld): skip_path = True break if skip_path: continue # determine whether to pick up the subtitle based on our match strictness elif not filename_matches_part: if sz_config.ext_match_strictness == "strict" or ( sz_config.ext_match_strictness == "loose" and not filename_contains_part): Log.Debug("%s doesn't match %s, skipping" % (helpers.unicodize(local_filename), helpers.unicodize(part_basename))) continue subtitle_helper = subtitlehelpers.subtitle_helpers(file_path) if subtitle_helper is not None: local_lang_map = subtitle_helper.process_subtitles(part) for new_language, subtitles in local_lang_map.items(): # Add the possible new language along with the located subtitles so that we can validate them # at the end... # if not lang_sub_map.has_key(new_language): lang_sub_map[new_language] = [] lang_sub_map[ new_language] = lang_sub_map[new_language] + subtitles # add known metadata subs to our sub list if not use_filesystem: for language, sub_list in subtitlehelpers.get_subtitles_from_metadata( part).iteritems(): if sub_list: if language not in lang_sub_map: lang_sub_map[language] = [] lang_sub_map[language] = lang_sub_map[language] + sub_list # Now whack subtitles that don't exist anymore. for language in lang_sub_map.keys(): part.subtitles[language].validate_keys(lang_sub_map[language]) # Now whack the languages that don't exist anymore. for language in list( set(part.subtitles.keys()) - set(lang_sub_map.keys())): part.subtitles[language].validate_keys({})
def initialize(self): self.libraries_root = os.path.abspath(os.path.join(get_root_path(), "..")) self.init_libraries() if is_windows_special_path: Log.Warn("The Plex metadata folder is residing inside a folder with special characters. " "Multithreading and playback activities will be disabled.") self.fs_encoding = get_viable_encoding() self.plugin_info = self.get_plugin_info() self.is_development = self.get_dev_mode() self.version = self.get_version() 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.plex_token = os.environ.get("PLEXTOKEN", self.universal_plex_token) self.new_style_cache = cast_bool(Prefs['new_style_cache']) self.pack_cache_dir = self.get_pack_cache_dir() try: self.migrate_prefs() except: Log.Exception("Catastrophic failure when running prefs migration") subzero.constants.DEFAULT_TIMEOUT = lib.DEFAULT_TIMEOUT = self.pms_request_timeout = \ min(cast_int(Prefs['pms_request_timeout'], 15), 45) self.low_impact_mode = cast_bool(Prefs['low_impact_mode']) self.advanced = self.get_advanced_config() self.debug_i18n = self.advanced.debug_i18n os.environ["SZ_USER_AGENT"] = self.get_user_agent() os.environ["ANTICAPTCHA_ACCOUNT_KEY"] = self.anticaptcha_token = str(Prefs["anticaptcha.api_key"]) or "" acs = str(Prefs["anticaptcha.service"]) if acs and acs != "none": os.environ["ANTICAPTCHA_CLASS"] = self.anticaptcha_cls = acs self.has_anticaptcha = self.anticaptcha_token and self.anticaptcha_cls self.setup_proxies() self.set_plugin_mode() self.set_plugin_lock() self.set_activity_modes() self.parse_rename_mode() self.normal_subs = Prefs["subtitles.when"] != "Never" self.forced_also = self.normal_subs and Prefs["subtitles.when_forced"] != "Never" self.forced_only = not self.normal_subs and Prefs["subtitles.when_forced"] != "Never" self.include = \ Prefs["subtitles.include_exclude_mode"] == "disable SZ for all items by default, use include lists" self.subtitle_destination_folder = self.get_subtitle_destination_folder() self.subtitle_formats = self.get_subtitle_formats() self.max_recent_items_per_library = int_or_default(Prefs["scheduler.max_recent_items_per_library"], 2000) self.sections = list(Plex["library"].sections()) self.missing_permissions = [] self.include_exclude_sz_files = cast_bool(Prefs["subtitles.include_exclude_fs"]) self.include_exclude_paths = self.parse_include_exclude_paths() self.enabled_sections = self.check_enabled_sections() self.permissions_ok = self.check_permissions() self.notify_executable = self.check_notify_executable() self.remove_hi = cast_bool(Prefs['subtitles.remove_hi']) self.remove_tags = cast_bool(Prefs['subtitles.remove_tags']) self.fix_ocr = cast_bool(Prefs['subtitles.fix_ocr']) self.fix_common = cast_bool(Prefs['subtitles.fix_common']) self.fix_upper = cast_bool(Prefs['subtitles.fix_only_uppercase']) self.reverse_rtl = cast_bool(Prefs['subtitles.reverse_rtl']) self.colors = Prefs['subtitles.colors'] if Prefs['subtitles.colors'] != "don't change" else None self.chmod = self.check_chmod() self.exotic_ext = cast_bool(Prefs["subtitles.scan.exotic_ext"]) self.treat_und_as_first = cast_bool(Prefs["subtitles.language.treat_und_as_first"]) self.subtitle_sub_dir = self.get_subtitle_sub_dir() self.ext_match_strictness = self.determine_ext_sub_strictness() self.default_mods = self.get_default_mods() self.debug_mods = cast_bool(Prefs['log_debug_mods']) self.no_refresh = os.environ.get("SZ_NO_REFRESH", False) self.plex_transcoder = self.get_plex_transcoder() self.only_one = cast_bool(Prefs['subtitles.only_one']) self.any_language_is_enough = Prefs['subtitles.any_language_is_enough'] self.embedded_auto_extract = cast_bool(Prefs["subtitles.embedded.autoextract"]) self.ietf_as_alpha3 = cast_bool(Prefs["subtitles.language.ietf_normalize"]) self.use_custom_dns = self.parse_custom_dns() self.initialized = True
def find_subtitles(part, ignore_parts_cleanup=None): lang_sub_map = {} ignore_parts_cleanup = ignore_parts_cleanup or [] part_filename = helpers.unicodize(part.file) part_basename = os.path.splitext(os.path.basename(part_filename))[0] use_filesystem = helpers.cast_bool(Prefs["subtitles.save.filesystem"]) sub_dir_custom = Prefs["subtitles.save.subFolder.Custom"].strip() \ if Prefs["subtitles.save.subFolder.Custom"] else None use_sub_subfolder = Prefs["subtitles.save.subFolder"] != "current folder" and not sub_dir_custom autoclean = helpers.cast_bool(Prefs["subtitles.autoclean"]) sub_subfolder = None paths = [os.path.dirname(part_filename)] if use_filesystem else [] global_folders = [] if use_filesystem: # Check for local subtitles subdirectory sub_dir_base = paths[0] sub_dir_list = [] if use_sub_subfolder: # got selected subfolder sub_subfolder = os.path.join(sub_dir_base, Prefs["subtitles.save.subFolder"]) sub_dir_list.append(sub_subfolder) sub_subfolder = os.path.normpath(helpers.unicodize(sub_subfolder)) if sub_dir_custom: # got custom subfolder sub_dir_custom = os.path.normpath(sub_dir_custom) if os.path.isdir(sub_dir_custom) and os.path.isabs(sub_dir_custom): # absolute folder sub_dir_list.append(sub_dir_custom) global_folders.append(sub_dir_custom) else: # relative folder fld = os.path.join(sub_dir_base, sub_dir_custom) sub_dir_list.append(fld) for sub_dir in sub_dir_list: if os.path.isdir(sub_dir): paths.append(sub_dir) # Check for a global subtitle location global_subtitle_folder = os.path.join(Core.app_support_path, 'Subtitles') if os.path.exists(global_subtitle_folder): paths.append(global_subtitle_folder) global_folders.append(global_subtitle_folder) # normalize all 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 # is limited to a single instance per media file. # file_paths = {} total_media_files = 0 media_files = [] for path in paths: for file_path_listing in os.listdir(path.encode(sz_config.fs_encoding)): # When using os.listdir with a unicode path, it will always return a string using the # NFD form. However, we internally are using the form NFC and therefore need to convert # it to allow correct regex / comparisons to be performed. # file_path_listing = helpers.unicodize(file_path_listing) if os.path.isfile(os.path.join(path, file_path_listing).encode(sz_config.fs_encoding)): file_paths[file_path_listing.lower()] = os.path.join(path, file_path_listing) # If we've found an actual media file, we should record it. (root, ext) = os.path.splitext(file_path_listing) if ext.lower()[1:] in config.VIDEO_EXTS: total_media_files += 1 # collect found media files media_files.append(root) # cleanup any leftover subtitle if no associated media file was found if autoclean and ignore_parts_cleanup: Log.Info("Skipping housekeeping of: %s", paths) if use_filesystem and autoclean and not ignore_parts_cleanup: for path in paths: # only housekeep in sub_subfolder if sub_subfolder is used if use_sub_subfolder and path != sub_subfolder and not sz_config.advanced.thorough_cleaning: continue # we can't housekeep the global subtitle folders as we don't know about *all* media files # in a library; skip them skip_path = False for fld in global_folders: if path.startswith(fld): Log.Info("Skipping housekeeping of folder: %s", path) skip_path = True break if skip_path: continue for file_path_listing in os.listdir(path.encode(sz_config.fs_encoding)): file_path_listing = helpers.unicodize(file_path_listing) enc_fn = os.path.join(path, file_path_listing).encode(sz_config.fs_encoding) if os.path.isfile(enc_fn): (root, ext) = os.path.splitext(file_path_listing) # it's a subtitle file if ext.lower()[1:] in config.SUBTITLE_EXTS_BASE: # get fn without forced/default/normal tag split_tag = root.rsplit(".", 1) if len(split_tag) > 1 and split_tag[1].lower() in SECONDARY_TAGS: root = split_tag[0] # get associated media file name without language sub_fn = subtitlehelpers.ENDSWITH_LANGUAGECODE_RE.sub("", root) # subtitle basename and basename without possible language tag not found in collected # media files? kill. if root not in media_files and sub_fn not in media_files: Log.Info("Removing leftover subtitle: %s", os.path.join(path, file_path_listing)) try: os.remove(enc_fn) except (OSError, IOError): Log.Error("Removing failed") Log('Looking for subtitle media in %d paths with %d media files.', len(paths), total_media_files) Log('Paths: %s', ", ".join([helpers.unicodize(p) for p in paths])) for file_path in file_paths.values(): local_filename = os.path.basename(file_path) bn, ext = os.path.splitext(local_filename) local_basename = helpers.unicodize(bn) # get fn without forced/default/normal tag split_tag = local_basename.rsplit(".", 1) has_additional_tag = False if len(split_tag) > 1 and split_tag[1].lower() in SECONDARY_TAGS: local_basename = split_tag[0] has_additional_tag = True # split off possible language tag local_basename2 = local_basename.rsplit('.', 1)[0] filename_matches_part = local_basename == part_basename or local_basename2 == part_basename filename_contains_part = part_basename in local_basename if not ext.lower()[1:] in config.SUBTITLE_EXTS: continue # if the file is located within the global subtitle folders and its name doesn't match exactly, ignore it if global_folders and not filename_matches_part: skip_path = False for fld in global_folders: if file_path.startswith(fld): skip_path = True break if skip_path: continue # determine whether to pick up the subtitle based on our match strictness if not filename_matches_part: if sz_config.ext_match_strictness == "strict" or ( sz_config.ext_match_strictness == "loose" and not filename_contains_part): # Log.Debug("%s doesn't match %s, skipping" % (helpers.unicodize(local_filename), # helpers.unicodize(part_basename))) continue subtitle_helper = subtitlehelpers.subtitle_helpers(file_path) if subtitle_helper is not None: local_lang_map = subtitle_helper.process_subtitles(part) for new_language, subtitles in local_lang_map.items(): # Add the possible new language along with the located subtitles so that we can validate them # at the end... # if not lang_sub_map.has_key(new_language): lang_sub_map[new_language] = [] lang_sub_map[new_language] = lang_sub_map[new_language] + subtitles # add known metadata subs to our sub list if not use_filesystem: for language, sub_list in subtitlehelpers.get_subtitles_from_metadata(part).iteritems(): if sub_list: if language not in lang_sub_map: lang_sub_map[language] = [] lang_sub_map[language] = lang_sub_map[language] + sub_list # Now whack subtitles that don't exist anymore. for language in lang_sub_map.keys(): part.subtitles[language].validate_keys(lang_sub_map[language]) # Now whack the languages that don't exist anymore. for language in list(set(part.subtitles.keys()) - set(lang_sub_map.keys())): part.subtitles[language].validate_keys({})
def providers_by_prefs(self): return {'opensubtitles': cast_bool(Prefs['provider.opensubtitles.enabled']), # 'thesubdb': Prefs['provider.thesubdb.enabled'], 'podnapisi': cast_bool(Prefs['provider.podnapisi.enabled']), 'titlovi': cast_bool(Prefs['provider.titlovi.enabled']), 'addic7ed': cast_bool(Prefs['provider.addic7ed.enabled']) and self.has_anticaptcha, 'tvsubtitles': cast_bool(Prefs['provider.tvsubtitles.enabled']), 'legendastv': cast_bool(Prefs['provider.legendastv.enabled']), 'napiprojekt': cast_bool(Prefs['provider.napiprojekt.enabled']), 'hosszupuska': cast_bool(Prefs['provider.hosszupuska.enabled']), 'supersubtitles': cast_bool(Prefs['provider.supersubtitles.enabled']), 'shooter': False, 'subscene': cast_bool(Prefs['provider.subscene.enabled']), 'argenteam': cast_bool(Prefs['provider.argenteam.enabled']), 'subscenter': False, 'assrt': cast_bool(Prefs['provider.assrt.enabled']), }
def process_subtitles(self, part): lang_sub_map = {} if not os.path.exists(self.filename): return lang_sub_map basename = os.path.basename(self.filename) (file, ext) = os.path.splitext(self.filename) # Remove the initial '.' from the extension ext = ext[1:] forced = '' default = '' split_tag = file.rsplit('.', 1) if len(split_tag) > 1 and split_tag[1].lower() in ['forced', 'normal', 'default', 'embedded', 'custom']: file = split_tag[0] # don't do anything with 'normal', we don't need it if 'forced' == split_tag[1].lower(): forced = '1' if 'default' == split_tag[1].lower(): default = '1' # Attempt to extract the language from the filename (e.g. Avatar (2009).eng) # IETF support thanks to # https://github.com/hpsbranco/LocalMedia.bundle/commit/4fad9aefedece78a1fa96401304351347f644369 language = Locale.Language.Match(match_ietf_language(file)) # skip non-SRT if wanted if not helpers.cast_bool(Prefs["subtitles.scan.exotic_ext"]) and ext not in ["srt", "ass", "ssa", "vtt"]: return lang_sub_map codec = None format = None if ext in ['txt', 'sub']: try: file_contents = Core.storage.load(self.filename) lines = [line.strip() for line in file_contents.splitlines(True)] if re.match('^\{[0-9]+\}\{[0-9]*\}', lines[1]): format = 'microdvd' elif re.match('^[0-9]{1,2}:[0-9]{2}:[0-9]{2}[:=,]', lines[1]): format = 'txt' elif '[SUBTITLE]' in lines[1]: format = 'subviewer' else: Log("The subtitle file does not have a known format, skipping... : " + self.filename) return lang_sub_map except: Log("An error occurred while attempting to parse the subtitle file, skipping... : " + self.filename) return lang_sub_map if codec is None and ext in ['ass', 'ssa', 'smi', 'srt', 'psb', 'vtt']: codec = ext.replace('ass', 'ssa') if format is None: format = codec Log('Found subtitle file: ' + self.filename + ' language: ' + language + ' codec: ' + str( codec) + ' format: ' + str(format) + ' default: ' + default + ' forced: ' + forced) part.subtitles[language][basename] = Proxy.LocalFile(self.filename, codec=codec, format=format, default=default, forced=forced) lang_sub_map[language] = [basename] return lang_sub_map