Compare commits
27 Commits
| Author | SHA1 | Date | |
|---|---|---|---|
| fa41dc3f35 | |||
| a70f9c0673 | |||
| 540a35cb0e | |||
| 1d9a2ff6fc | |||
| 01a5d71b4a | |||
| 4f11fa53cd | |||
| 8f6540118b | |||
| 089618b8a6 | |||
| 6f87037c78 | |||
| d9b36c0616 | |||
| df2bc9767c | |||
| 508810d5c7 | |||
| dc6770ecaa | |||
| 25b8702a42 | |||
| 5a5aa510c5 | |||
| 5d7777095e | |||
| 95ad5b6fbe | |||
| 9e3227ba0b | |||
| d725c87cae | |||
| 6c3bf03bc3 | |||
| 20c04f32be | |||
| 29bafc6215 | |||
| d3279ef923 | |||
| 291e210e63 | |||
| 535b1aaba9 | |||
| 48cafadbdd | |||
| 39d442c2b3 |
@@ -70,7 +70,7 @@ def Start():
|
||||
ValidatePrefs()
|
||||
Log.Debug(config.full_version)
|
||||
|
||||
if not config.permissions_ok:
|
||||
if config.initialized and not config.permissions_ok:
|
||||
Log.Error("Insufficient permissions on library folders:")
|
||||
for title, path in config.missing_permissions:
|
||||
Log.Error("Insufficient permissions on library %s, folder: %s" % (title, path))
|
||||
@@ -118,16 +118,20 @@ def agent_extract_embedded(video_part_map):
|
||||
|
||||
for plexapi_part in get_all_parts(plexapi_item):
|
||||
item_count = item_count + 1
|
||||
used_one_unknown_stream = False
|
||||
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.external_subtitle_languages
|
||||
|
||||
if not embedded_subs:
|
||||
stream_data = get_embedded_subtitle_streams(plexapi_part, requested_language=requested_language)
|
||||
stream_data = get_embedded_subtitle_streams(plexapi_part, requested_language=requested_language,
|
||||
skip_unknown=used_one_unknown_stream)
|
||||
|
||||
if stream_data:
|
||||
stream = stream_data[0]["stream"]
|
||||
if stream_data[0]["is_unknown"]:
|
||||
used_one_unknown_stream = True
|
||||
|
||||
to_extract.append(({scanned_video: part_info}, plexapi_part, str(stream.index),
|
||||
str(requested_language), not current))
|
||||
@@ -224,7 +228,7 @@ class SubZeroAgent(object):
|
||||
if config.plex_transcoder:
|
||||
agent_extract_embedded(scanned_video_part_map)
|
||||
else:
|
||||
Log.Warning("Plex Transcoder not found, can't auto extract")
|
||||
Log.Warn("Plex Transcoder not found, can't auto extract")
|
||||
|
||||
# clear missing subtitles menu data
|
||||
if not scheduler.is_task_running("MissingSubtitles"):
|
||||
|
||||
@@ -1,6 +1,8 @@
|
||||
# coding=utf-8
|
||||
|
||||
from subzero.constants import PREFIX, TITLE, ART
|
||||
import time
|
||||
|
||||
from subzero.constants import PREFIX, TITLE, ART, START_DELAY
|
||||
from support.config import config
|
||||
from support.helpers import pad_title, timestamp, df, display_language
|
||||
from support.scheduler import scheduler
|
||||
@@ -27,45 +29,56 @@ def fatality(randomize=None, force_title=None, header=None, message=None, only_r
|
||||
no_history=no_history,
|
||||
replace_parent=replace_parent, no_cache=True)
|
||||
|
||||
# always re-check permissions
|
||||
config.refresh_permissions_status()
|
||||
if config.initialized:
|
||||
# always re-check permissions
|
||||
config.refresh_permissions_status()
|
||||
|
||||
# always re-check enabled sections
|
||||
config.refresh_enabled_sections()
|
||||
# always re-check enabled sections
|
||||
config.refresh_enabled_sections()
|
||||
|
||||
if config.lock_menu and not config.pin_correct:
|
||||
oc.add(DirectoryObject(
|
||||
key=Callback(PinMenu, randomize=timestamp()),
|
||||
title=pad_title(_("Enter PIN")),
|
||||
summary=_("The owner has restricted the access to this menu. Please enter the correct pin"),
|
||||
))
|
||||
return oc
|
||||
|
||||
if not config.permissions_ok and config.missing_permissions:
|
||||
if not isinstance(config.missing_permissions, list):
|
||||
if config.lock_menu and not config.pin_correct:
|
||||
oc.add(DirectoryObject(
|
||||
key=Callback(fatality, randomize=timestamp()),
|
||||
title=pad_title(_("Insufficient permissions")),
|
||||
summary=config.missing_permissions,
|
||||
key=Callback(PinMenu, randomize=timestamp()),
|
||||
title=pad_title(_("Enter PIN")),
|
||||
summary=_("The owner has restricted the access to this menu. Please enter the correct pin"),
|
||||
))
|
||||
else:
|
||||
for title, path in config.missing_permissions:
|
||||
return oc
|
||||
|
||||
if not config.permissions_ok and config.missing_permissions:
|
||||
if not isinstance(config.missing_permissions, list):
|
||||
oc.add(DirectoryObject(
|
||||
key=Callback(fatality, randomize=timestamp()),
|
||||
title=pad_title(_("Insufficient permissions")),
|
||||
summary=_("Insufficient permissions on library %(title)s, folder: %(path)s",
|
||||
title=title,
|
||||
path=path),
|
||||
summary=config.missing_permissions,
|
||||
))
|
||||
return oc
|
||||
else:
|
||||
for title, path in config.missing_permissions:
|
||||
oc.add(DirectoryObject(
|
||||
key=Callback(fatality, randomize=timestamp()),
|
||||
title=pad_title(_("Insufficient permissions")),
|
||||
summary=_("Insufficient permissions on library %(title)s, folder: %(path)s",
|
||||
title=title,
|
||||
path=path),
|
||||
))
|
||||
return oc
|
||||
|
||||
if not config.enabled_sections:
|
||||
oc.add(DirectoryObject(
|
||||
key=Callback(fatality, randomize=timestamp()),
|
||||
title=pad_title(_("I'm not enabled!")),
|
||||
summary=_("Please enable me for some of your libraries in your server settings; currently I do nothing"),
|
||||
))
|
||||
return oc
|
||||
if not config.enabled_sections:
|
||||
oc.add(DirectoryObject(
|
||||
key=Callback(fatality, randomize=timestamp()),
|
||||
title=pad_title(_("I'm not enabled!")),
|
||||
summary=_("Please enable me for some of your libraries in your server settings; currently I do nothing"),
|
||||
))
|
||||
return oc
|
||||
else:
|
||||
if config.delay_system_queries:
|
||||
elapsed = int(START_DELAY - (time.time() - config.start_delay_elapsed))
|
||||
oc.add(DirectoryObject(
|
||||
key=Callback(fatality, randomize=timestamp()),
|
||||
title=pad_title(_("Finalizing ..."
|
||||
if elapsed <= 0 else "Initializing, please wait %s seconds ..." % elapsed)),
|
||||
summary=_("Start is delayed by %s seconds to cope with a slow PMS" % int(START_DELAY)),
|
||||
))
|
||||
return oc
|
||||
|
||||
if not only_refresh:
|
||||
if Dict["current_refresh_state"]:
|
||||
|
||||
@@ -7,6 +7,7 @@ import sys
|
||||
import rarfile
|
||||
import jstyleson
|
||||
import datetime
|
||||
import time
|
||||
|
||||
import subliminal
|
||||
import subliminal_patch
|
||||
@@ -22,7 +23,7 @@ from subliminal.cli import MutexLock
|
||||
from subzero.lib.io import FileIO, get_viable_encoding
|
||||
from subzero.lib.dict import Dicked
|
||||
from subzero.util import get_root_path
|
||||
from subzero.constants import PLUGIN_NAME, PLUGIN_IDENTIFIER, MOVIE, SHOW, MEDIA_TYPE_TO_STRING
|
||||
from subzero.constants import PLUGIN_NAME, PLUGIN_IDENTIFIER, MOVIE, SHOW, MEDIA_TYPE_TO_STRING, START_DELAY
|
||||
from subzero.prefs import get_user_prefs, update_user_prefs
|
||||
from dogpile.cache.region import register_backend as register_cache_backend
|
||||
from lib import Plex
|
||||
@@ -148,10 +149,15 @@ class Config(object):
|
||||
unrar = None
|
||||
adv_cfg_path = None
|
||||
use_custom_dns = False
|
||||
delay_system_queries = False
|
||||
|
||||
store_recently_played_amount = 40
|
||||
|
||||
initialized = False
|
||||
system_queries_done = False
|
||||
base_init_done = False
|
||||
system_queries_timer = None
|
||||
start_delay_elapsed = None
|
||||
|
||||
def initialize(self):
|
||||
self.libraries_root = os.path.abspath(os.path.join(get_root_path(), ".."))
|
||||
@@ -169,6 +175,7 @@ class Config(object):
|
||||
self.set_log_paths()
|
||||
self.app_support_path = Core.app_support_path
|
||||
self.data_path = getattr(Data, "_core").storage.data_path
|
||||
self.delay_system_queries = os.path.isfile(os.path.join(self.data_path, "delayed_start"))
|
||||
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)
|
||||
@@ -205,8 +212,25 @@ class Config(object):
|
||||
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.system_queries_done = False
|
||||
|
||||
def system_queries():
|
||||
self.enabled_sections = self.check_enabled_sections()
|
||||
self.permissions_ok = self.check_permissions()
|
||||
self.system_queries_done = True
|
||||
self.system_queries_timer = None
|
||||
if self.base_init_done:
|
||||
self.initialized = True
|
||||
|
||||
if self.delay_system_queries:
|
||||
if not self.system_queries_timer or not self.system_queries_timer.is_alive():
|
||||
Log.Info("Waiting %s seconds until querying the system endpoints of your PMS" % START_DELAY)
|
||||
Thread.CreateTimer(START_DELAY, system_queries)
|
||||
self.start_delay_elapsed = time.time()
|
||||
else:
|
||||
system_queries()
|
||||
|
||||
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'])
|
||||
@@ -228,7 +252,11 @@ class Config(object):
|
||||
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 = cast_bool(Prefs['use_custom_dns'])
|
||||
self.initialized = True
|
||||
|
||||
self.base_init_done = True
|
||||
|
||||
if self.system_queries_done:
|
||||
self.initialized = True
|
||||
|
||||
def migrate_prefs(self):
|
||||
config_version = 0 if "config_version" not in Dict else Dict["config_version"]
|
||||
@@ -988,27 +1016,37 @@ class Config(object):
|
||||
self.activity_mode = "next_episode"
|
||||
|
||||
def get_plex_transcoder(self):
|
||||
paths = []
|
||||
base_path = os.environ.get("PLEX_MEDIA_SERVER_HOME", None)
|
||||
if not base_path:
|
||||
# fall back to bundled plugins path
|
||||
bundle_path = os.environ.get("PLEXBUNDLEDPLUGINSPATH", None)
|
||||
if bundle_path:
|
||||
base_path = os.path.normpath(os.path.join(bundle_path, "..", ".."))
|
||||
if base_path:
|
||||
paths.append(base_path)
|
||||
|
||||
bundle_path = os.environ.get("PLEXBUNDLEDPLUGINSPATH", None)
|
||||
if bundle_path:
|
||||
paths.append(os.path.normpath(os.path.join(bundle_path, "..", "..")))
|
||||
|
||||
paths.append(self.app_support_path)
|
||||
|
||||
bns = []
|
||||
if sys.platform == "darwin":
|
||||
fn = os.path.join(base_path, "MacOS", "Plex Transcoder")
|
||||
bns.append(("MacOS", "Plex Transcoder"))
|
||||
elif mswindows:
|
||||
fn = os.path.join(base_path, "plextranscoder.exe")
|
||||
bns = [("plextranscoder.exe",), ("plex transcoder.exe",)]
|
||||
else:
|
||||
fn = os.path.join(base_path, "Plex Transcoder")
|
||||
bns.append(("Plex Transcoder",))
|
||||
|
||||
if os.path.isfile(fn):
|
||||
return fn
|
||||
for path in paths:
|
||||
for bn in bns:
|
||||
fn = os.path.join(path, *bn)
|
||||
|
||||
# look inside Resources folder as fallback, as well
|
||||
fn = os.path.join(base_path, "Resources", "Plex Transcoder")
|
||||
if os.path.isfile(fn):
|
||||
return fn
|
||||
if os.path.isfile(fn):
|
||||
return fn
|
||||
|
||||
# look inside Resources folder as fallback, as well
|
||||
for vbn in ("Plex Transcoder", "plextranscoder.exe", "plex transcoder.exe"):
|
||||
fn = os.path.join(path, "Resources", vbn)
|
||||
if os.path.isfile(fn):
|
||||
return fn
|
||||
|
||||
def parse_rename_mode(self):
|
||||
# fixme: exact_filenames should be determined via callback combined with info about the current video
|
||||
|
||||
@@ -12,10 +12,12 @@ import subprocess
|
||||
import sys
|
||||
from collections import OrderedDict
|
||||
|
||||
from babelfish.exceptions import LanguageError
|
||||
|
||||
import chardet
|
||||
|
||||
from bs4 import UnicodeDammit
|
||||
from subzero.language import Language
|
||||
from subzero.language import Language, language_from_stream
|
||||
from subzero.analytics import track_event
|
||||
|
||||
mswindows = (sys.platform == "win32")
|
||||
@@ -388,6 +390,11 @@ def get_language_from_stream(lang_code):
|
||||
if lang and lang != "xx":
|
||||
# Log.Debug("Found language: %r", lang)
|
||||
return Language.fromietf(lang)
|
||||
elif lang:
|
||||
try:
|
||||
return language_from_stream(lang)
|
||||
except LanguageError:
|
||||
pass
|
||||
|
||||
|
||||
def audio_streams_match_languages(video, languages):
|
||||
|
||||
@@ -174,7 +174,7 @@ def get_all_parts(plex_item):
|
||||
return parts
|
||||
|
||||
|
||||
def get_embedded_subtitle_streams(part, requested_language=None, skip_duplicate_unknown=True):
|
||||
def get_embedded_subtitle_streams(part, requested_language=None, skip_duplicate_unknown=True, skip_unknown=False):
|
||||
streams = []
|
||||
streams_unknown = []
|
||||
has_unknown = False
|
||||
@@ -208,7 +208,7 @@ def get_embedded_subtitle_streams(part, requested_language=None, skip_duplicate_
|
||||
if found_requested_language:
|
||||
break
|
||||
|
||||
if streams_unknown and not found_requested_language:
|
||||
if streams_unknown and not found_requested_language and not skip_unknown:
|
||||
streams = streams_unknown
|
||||
|
||||
return streams
|
||||
|
||||
@@ -33,7 +33,7 @@ def store_subtitle_info(scanned_video_part_map, downloaded_subtitles, storage_ty
|
||||
video_id = str(video.id)
|
||||
plex_item = get_item(video_id)
|
||||
if not plex_item:
|
||||
Log.Warning("Plex item not found: %s", video_id)
|
||||
Log.Warn("Plex item not found: %s", video_id)
|
||||
continue
|
||||
|
||||
metadata = video.plexapi_metadata
|
||||
|
||||
+2
-2
@@ -13,7 +13,7 @@
|
||||
<key>CFBundleSignature</key>
|
||||
<string>????</string>
|
||||
<key>CFBundleVersion</key>
|
||||
<string>2.6.4.2911</string>
|
||||
<string>2.6.4.2934</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.2911 DEV
|
||||
Version 2.6.4.2934 DEV
|
||||
|
||||
Originally based on @bramwalet's awesome <a href="https://github.com/bramwalet/Subliminal.bundle">Subliminal.bundle</a>
|
||||
|
||||
|
||||
@@ -56,7 +56,7 @@ class SSAStyle(object):
|
||||
self.encoding = 1 #: Charset
|
||||
|
||||
for k, v in fields.items():
|
||||
if k in self.FIELDS:
|
||||
if k in self.FIELDS and v is not None:
|
||||
setattr(self, k, v)
|
||||
else:
|
||||
raise ValueError("SSAStyle has no field named %r" % k)
|
||||
|
||||
@@ -150,7 +150,14 @@ class SubstationFormat(FormatBase):
|
||||
if format_ == "ass":
|
||||
return ass_rgba_to_color(v)
|
||||
else:
|
||||
return ssa_rgb_to_color(v)
|
||||
try:
|
||||
return ssa_rgb_to_color(v)
|
||||
except ValueError:
|
||||
try:
|
||||
return ass_rgba_to_color(v)
|
||||
except:
|
||||
return Color(255, 255, 255, 0)
|
||||
|
||||
elif f in {"bold", "underline", "italic", "strikeout"}:
|
||||
return v == "-1"
|
||||
elif f in {"borderstyle", "encoding", "marginl", "marginr", "marginv", "layer", "alphalevel"}:
|
||||
|
||||
@@ -559,13 +559,16 @@ def _search_external_subtitles(path, languages=None, only_one=False, scandir_gen
|
||||
subtitles = {}
|
||||
_scandir = _scandir_generic if scandir_generic else scandir
|
||||
for entry in _scandir(dirpath):
|
||||
if not entry.name and not scandir_generic:
|
||||
logger.debug('Could not determine the name of the file, retrying with scandir_generic')
|
||||
return _search_external_subtitles(path, languages, only_one, True)
|
||||
if not entry.is_file(follow_symlinks=False):
|
||||
continue
|
||||
|
||||
p = entry.name
|
||||
|
||||
# keep only valid subtitle filenames
|
||||
if not p.startswith(fileroot) or not p.endswith(SUBTITLE_EXTENSIONS):
|
||||
if not p.lower().startswith(fileroot.lower()) or not p.lower().endswith(SUBTITLE_EXTENSIONS):
|
||||
continue
|
||||
|
||||
p_root, p_ext = os.path.splitext(p)
|
||||
@@ -600,7 +603,7 @@ def _search_external_subtitles(path, languages=None, only_one=False, scandir_gen
|
||||
logger.error('Cannot parse language code %r', language_code)
|
||||
language = None
|
||||
|
||||
if not language and only_one:
|
||||
elif not language_code and only_one:
|
||||
language = Language.rebuild(list(languages)[0], forced=forced)
|
||||
|
||||
subtitles[p] = language
|
||||
|
||||
@@ -148,7 +148,8 @@ class ProviderSubtitleArchiveMixin(object):
|
||||
subs_fallback.append(sub_name)
|
||||
|
||||
if not matching_sub and not subs_unsure and not subs_fallback:
|
||||
raise ProviderError("None of expected subtitle found in archive")
|
||||
logger.error("None of expected subtitle found in archive")
|
||||
return
|
||||
|
||||
elif subs_unsure:
|
||||
matching_sub = subs_unsure[0]
|
||||
|
||||
@@ -11,7 +11,7 @@ from bs4 import BeautifulSoup
|
||||
from zipfile import ZipFile, is_zipfile
|
||||
from rarfile import RarFile, is_rarfile
|
||||
from babelfish import language_converters, Script
|
||||
from requests import Session
|
||||
from requests import Session, RequestException
|
||||
from guessit import guessit
|
||||
from subliminal_patch.providers import Provider
|
||||
from subliminal_patch.providers.mixins import ProviderSubtitleArchiveMixin
|
||||
@@ -25,6 +25,9 @@ from subliminal.video import Episode, Movie
|
||||
from subliminal.subtitle import fix_line_ending
|
||||
from subzero.language import Language
|
||||
|
||||
from random import randint
|
||||
from .utils import FIRST_THOUSAND_OR_SO_USER_AGENTS as AGENT_LIST
|
||||
|
||||
# parsing regex definitions
|
||||
title_re = re.compile(r'(?P<title>(?:.+(?= [Aa][Kk][Aa] ))|.+)(?:(?:.+)(?P<altitle>(?<= [Aa][Kk][Aa] ).+))?')
|
||||
lang_re = re.compile(r'(?<=flags/)(?P<lang>.{2})(?:.)(?P<script>c?)(?:.+)')
|
||||
@@ -134,8 +137,8 @@ class TitloviProvider(Provider, ProviderSubtitleArchiveMixin):
|
||||
|
||||
def initialize(self):
|
||||
self.session = Session()
|
||||
self.session.headers['User-Agent'] = 'Mozilla/5.0 (Windows; U; Windows NT 6.1; en-US; rv:1.9.2.3)' \
|
||||
'Gecko/20100401 Firefox/3.6.3 ( .NET CLR 3.5.30729)'
|
||||
logger.debug("Using random user agents")
|
||||
self.session.headers['User-Agent'] = AGENT_LIST[randint(0, len(AGENT_LIST) - 1)]
|
||||
logger.debug('User-Agent set to %s', self.session.headers['User-Agent'])
|
||||
self.session.headers['Referer'] = self.server_url
|
||||
logger.debug('Referer set to %s', self.session.headers['Referer'])
|
||||
@@ -178,7 +181,11 @@ class TitloviProvider(Provider, ProviderSubtitleArchiveMixin):
|
||||
try:
|
||||
r = self.session.get(self.search_url, params=params, timeout=10)
|
||||
r.raise_for_status()
|
||||
except RequestException as e:
|
||||
logger.exception('RequestException %s', e)
|
||||
break
|
||||
|
||||
try:
|
||||
soup = BeautifulSoup(r.content, 'lxml')
|
||||
|
||||
# number of results
|
||||
|
||||
@@ -44,11 +44,13 @@ class Subtitle(Subtitle_):
|
||||
|
||||
pack_data = None
|
||||
_guessed_encoding = None
|
||||
_is_valid = False
|
||||
|
||||
def __init__(self, language, hearing_impaired=False, page_link=None, encoding=None, mods=None):
|
||||
super(Subtitle, self).__init__(language, hearing_impaired=hearing_impaired, page_link=page_link,
|
||||
encoding=encoding)
|
||||
self.mods = mods
|
||||
self._is_valid = False
|
||||
|
||||
def __repr__(self):
|
||||
return '<%s %r [%s:%s]>' % (
|
||||
@@ -212,6 +214,9 @@ class Subtitle(Subtitle_):
|
||||
:rtype: bool
|
||||
|
||||
"""
|
||||
if self._is_valid:
|
||||
return True
|
||||
|
||||
text = self.text
|
||||
if not text:
|
||||
return False
|
||||
@@ -222,6 +227,7 @@ class Subtitle(Subtitle_):
|
||||
except Exception:
|
||||
logger.error("PySRT-parsing failed, trying pysubs2")
|
||||
else:
|
||||
self._is_valid = True
|
||||
return True
|
||||
|
||||
# something else, try to return srt
|
||||
@@ -247,6 +253,7 @@ class Subtitle(Subtitle_):
|
||||
logger.exception("Couldn't convert subtitle %s to .srt format: %s", self, traceback.format_exc())
|
||||
return False
|
||||
|
||||
self._is_valid = True
|
||||
return True
|
||||
|
||||
@classmethod
|
||||
|
||||
@@ -176,8 +176,12 @@ class Film(object):
|
||||
|
||||
content = soup.find("div", "subtitles")
|
||||
header = content.find("div", "box clearfix")
|
||||
cover = None
|
||||
|
||||
cover = header.find("div", "poster").img.get("src")
|
||||
try:
|
||||
cover = header.find("div", "poster").img.get("src")
|
||||
except AttributeError:
|
||||
pass
|
||||
|
||||
title = header.find("div", "header").h2.text[:-12].strip()
|
||||
|
||||
|
||||
@@ -15,6 +15,7 @@ ICON = 'icon-default.jpg'
|
||||
ICON_SUB = 'icon-sub.jpg'
|
||||
|
||||
DEFAULT_TIMEOUT = 15
|
||||
START_DELAY = 30.0
|
||||
|
||||
|
||||
# media types as on https://github.com/Arcanemagus/plex-api/wiki/MediaTypes
|
||||
|
||||
@@ -4,7 +4,6 @@ import types
|
||||
from babelfish.exceptions import LanguageError
|
||||
from babelfish import Language as Language_, basestr
|
||||
|
||||
|
||||
repl_map = {
|
||||
"dk": "da",
|
||||
"nld": "nl",
|
||||
|
||||
Reference in New Issue
Block a user