Implemented some utility functions to subliminal_patch providers to list supported languages and video types.

This commit is contained in:
morpheus65535 2021-11-09 22:55:47 -05:00
parent f8282efeb6
commit b53f8ad80a
31 changed files with 163 additions and 7 deletions

View File

@ -21,6 +21,7 @@ from bs4 import UnicodeDammit
from babelfish import LanguageReverseError
from guessit.jsonutils import GuessitEncoder
from subliminal import ProviderError, refiner_manager
from concurrent.futures import as_completed
from .extensions import provider_registry
from subliminal.exceptions import ServiceUnavailable, DownloadLimitExceeded
@ -427,6 +428,58 @@ class SZProviderPool(ProviderPool):
return downloaded_subtitles
def list_supported_languages(self):
"""List supported languages.
:return: languages supported by the providers.
:rtype: list of dicts
"""
languages = []
for name in self.providers:
# list supported languages for a single provider
try:
provider_languages = self[name].languages
except AttributeError:
logger.exception(f"{name} provider doesn't have a languages attribute")
continue
if provider_languages is None:
logger.info(f"Skipping provider {name} because it doesn't support any languages.")
continue
# add the languages for this provider
languages.append({'provider': name, 'languages': provider_languages})
return languages
def list_supported_video_types(self):
"""List supported video types.
:return: video types supported by the providers.
:rtype: tuple of video types
"""
video_types = []
for name in self.providers:
# list supported video types for a single provider
try:
provider_video_type = self[name].video_types
except AttributeError:
logger.exception(f"{name} provider doesn't have a video_types method")
continue
if provider_video_type is None:
logger.info(f"Skipping provider {name} because it doesn't support any video type.")
continue
# add the video types for this provider
video_types.append({'provider': name, 'video_types': provider_video_type})
return video_types
class SZAsyncProviderPool(SZProviderPool):
"""Subclass of :class:`ProviderPool` with asynchronous support for :meth:`~ProviderPool.list_subtitles`.
@ -474,6 +527,65 @@ class SZAsyncProviderPool(SZProviderPool):
return subtitles
def list_supported_languages(self):
"""List supported languages asynchronously.
:return: languages supported by the providers.
:rtype: list of dicts
"""
languages = []
def get_providers_languages(provider_name):
provider_languages = None
try:
provider_languages = {'provider': provider_name, 'languages': self[provider_name].languages}
except AttributeError:
logger.exception(f"{provider_name} provider doesn't have a languages attribute")
return provider_languages
with ThreadPoolExecutor(self.max_workers) as executor:
for future in as_completed([executor.submit(get_providers_languages, x) for x in self.providers]):
provider_languages = future.result()
if provider_languages is None:
continue
# add the languages for this provider
languages.append(provider_languages)
return languages
def list_supported_video_types(self):
"""List supported video types asynchronously.
:return: video types supported by the providers.
:rtype: tuple of video types
"""
video_types = []
def get_providers_video_types(provider_name):
provider_video_types = None
try:
provider_video_types = {'provider': provider_name,
'video_types': self[provider_name].video_types}
except AttributeError:
logger.exception(f"{provider_name} provider doesn't have a video_types attribute")
return provider_video_types
with ThreadPoolExecutor(self.max_workers) as executor:
for future in as_completed([executor.submit(get_providers_video_types, x) for x in self.providers]):
provider_video_types = future.result()
if provider_video_types is None:
continue
# add the languages for this provider
video_types.append(provider_video_types)
return video_types
if is_windows_special_path:
SZAsyncProviderPool = SZProviderPool
@ -758,6 +870,16 @@ def list_all_subtitles(videos, languages, **kwargs):
return listed_subtitles
def list_supported_languages(pool_class, **kwargs):
with pool_class(**kwargs) as pool:
return pool.list_supported_languages()
def list_supported_video_types(pool_class, **kwargs):
with pool_class(**kwargs) as pool:
return pool.list_supported_video_types()
def download_subtitles(subtitles, pool_class=ProviderPool, **kwargs):
"""Download :attr:`~subliminal.subtitle.Subtitle.content` of `subtitles`.

View File

@ -109,6 +109,7 @@ class AssrtSubtitle(Subtitle):
class AssrtProvider(Provider):
"""Assrt Provider."""
languages = {Language(*l) for l in supported_languages}
video_types = (Episode, Movie)
def __init__(self, token=None):
if not token:

View File

@ -72,6 +72,7 @@ class BSPlayerProvider(Provider):
'ara', 'bul', 'ces', 'dan', 'deu', 'ell', 'eng', 'fin', 'fra', 'hun', 'ita', 'jpn', 'kor', 'nld', 'pol', 'por',
'ron', 'rus', 'spa', 'swe', 'tur', 'ukr', 'zho'
]}
video_types = (Episode, Movie)
SEARCH_THROTTLE = 8
hash_verifiable = True
# fmt: on

View File

@ -54,6 +54,7 @@ class GreekSubsSubtitle(Subtitle):
class GreekSubsProvider(Provider):
"""GreekSubs Provider."""
languages = {Language('ell')}
video_types = (Episode, Movie)
server_url = 'https://greeksubs.net/'
subtitle_class = GreekSubsSubtitle

View File

@ -52,6 +52,7 @@ class GreekSubtitlesSubtitle(Subtitle):
class GreekSubtitlesProvider(Provider):
"""GreekSubtitles Provider."""
languages = {Language(l) for l in ['ell', 'eng']}
video_types = (Episode, Movie)
server_url = 'http://gr.greek-subtitles.com/'
search_url = 'search.php?name={}'
download_url = 'http://www.greeksubtitles.info/getp.php?id={:d}'

View File

@ -110,6 +110,7 @@ class KtuvitProvider(Provider):
"""Ktuvit Provider."""
languages = {Language(l) for l in ["heb"]}
video_types = (Episode, Movie)
server_url = "https://www.ktuvit.me/"
sign_in_url = "Services/MembershipService.svc/Login"
search_url = "Services/ContentProvider.svc/SearchPage_search"

View File

@ -121,6 +121,7 @@ class LegendasdivxSubtitle(Subtitle):
class LegendasdivxProvider(Provider):
"""Legendasdivx Provider."""
languages = {Language('por', 'BR')} | {Language('por')}
video_types = (Episode, Movie)
SEARCH_THROTTLE = 8
site = 'https://www.legendasdivx.pt'
headers = {

View File

@ -68,6 +68,7 @@ class LegendasTVSubtitle(_LegendasTVSubtitle):
class LegendasTVProvider(_LegendasTVProvider):
languages = {Language(*l) for l in language_converters['legendastv'].to_legendastv.keys()}
video_types = (Episode, Movie)
subtitle_class = LegendasTVSubtitle
def __init__(self, username=None, password=None, featured_only=False):

View File

@ -5,6 +5,7 @@ import logging
from subliminal.providers.napiprojekt import NapiProjektProvider as _NapiProjektProvider, \
NapiProjektSubtitle as _NapiProjektSubtitle, get_subhash
from subzero.language import Language
from subliminal.video import Episode, Movie
logger = logging.getLogger(__name__)
@ -21,6 +22,7 @@ class NapiProjektSubtitle(_NapiProjektSubtitle):
class NapiProjektProvider(_NapiProjektProvider):
languages = {Language.fromalpha2(l) for l in ['pl']}
video_types = (Episode, Movie)
subtitle_class = NapiProjektSubtitle
def query(self, language, hash):

View File

@ -12,6 +12,7 @@ from subliminal import __short_version__
from subliminal.exceptions import AuthenticationError, ConfigurationError
from subliminal.subtitle import fix_line_ending
from subzero.language import Language
from subliminal.video import Episode, Movie
logger = logging.getLogger(__name__)
@ -47,6 +48,7 @@ class Napisy24Subtitle(Subtitle):
class Napisy24Provider(Provider):
'''Napisy24 Provider.'''
languages = {Language(l) for l in ['pol']}
video_types = (Episode, Movie)
required_hash = 'napisy24'
api_url = 'http://napisy24.pl/run/CheckSubAgent.php'

View File

@ -104,6 +104,7 @@ class NekurProvider(Provider, ProviderSubtitleArchiveMixin):
"""Nekur Provider."""
subtitle_class = NekurSubtitle
languages = {Language('lva', 'LV')} | {Language.fromalpha2(l) for l in ['lv']}
video_types = (Movie,)
server_url = 'http://subtitri.nekur.net/'
search_url = server_url + 'modules/Subtitles.php'

View File

@ -140,6 +140,8 @@ class OpenSubtitlesProvider(ProviderRetryMixin, _OpenSubtitlesProvider):
languages.update(set(Language.rebuild(l, forced=True) for l in languages))
languages.update(set(Language.rebuild(l, hi=True) for l in languages))
video_types = (Episode, Movie)
def __init__(self, username=None, password=None, use_tag_search=False, only_foreign=False, also_foreign=False,
skip_wrong_fps=True, is_vip=False, use_ssl=True, timeout=15):
if any((username, password)) and not all((username, password)):

View File

@ -126,6 +126,8 @@ class OpenSubtitlesComProvider(ProviderRetryMixin, Provider):
languages = {Language.fromopensubtitles(lang) for lang in language_converters['szopensubtitles'].codes}
languages.update(set(Language.rebuild(lang, forced=True) for lang in languages))
video_types = (Episode, Movie)
def __init__(self, username=None, password=None, use_hash=True, api_key=None):
if not all((username, password)):
raise ConfigurationError('Username and password must be specified')

View File

@ -27,8 +27,7 @@ except ImportError:
except ImportError:
import xml.etree.ElementTree as etree
from babelfish import language_converters
from subliminal import Episode
from subliminal import Movie
from subliminal.video import Episode, Movie
from subliminal.providers.podnapisi import PodnapisiProvider as _PodnapisiProvider, \
PodnapisiSubtitle as _PodnapisiSubtitle
from subliminal_patch.utils import sanitize, fix_inconsistent_naming as _fix_inconsistent_naming
@ -130,6 +129,8 @@ class PodnapisiProvider(_PodnapisiProvider, ProviderSubtitleArchiveMixin):
languages.update(set(Language.rebuild(l, forced=True) for l in languages))
languages.update(set(Language.rebuild(l, hi=True) for l in languages))
video_types = (Episode, Movie)
server_url = 'https://podnapisi.net/subtitles/'
only_foreign = False
also_foreign = False

View File

@ -65,6 +65,7 @@ class RegieLiveProvider(Provider):
"""RegieLive Provider."""
languages = {Language(l) for l in ['ron']}
language = list(languages)[0]
video_types = (Episode, Movie)
SEARCH_THROTTLE = 8
def __init__(self):

View File

@ -2,6 +2,7 @@
from __future__ import absolute_import
from subliminal.providers.shooter import ShooterProvider as _ShooterProvider, ShooterSubtitle as _ShooterSubtitle
from subliminal.video import Episode, Movie
class ShooterSubtitle(_ShooterSubtitle):
@ -13,4 +14,4 @@ class ShooterSubtitle(_ShooterSubtitle):
class ShooterProvider(_ShooterProvider):
subtitle_class = ShooterSubtitle
video_types = (Episode, Movie)

View File

@ -102,6 +102,7 @@ class SoustitreseuProvider(Provider, ProviderSubtitleArchiveMixin):
"""Sous-Titres.eu Provider."""
subtitle_class = SoustitreseuSubtitle
languages = {Language(l) for l in ['fra', 'eng']}
video_types = (Episode, Movie)
server_url = 'https://www.sous-titres.eu/'
search_url = server_url + 'search.html'

View File

@ -83,6 +83,7 @@ class SubdivxSubtitlesProvider(Provider):
provider_name = "subdivx"
hash_verifiable = False
languages = {Language("spa", "MX")} | {Language.fromalpha2("es")}
video_types = (Episode, Movie)
subtitle_class = SubdivxSubtitle
server_url = "https://www.subdivx.com/"

View File

@ -21,6 +21,7 @@ from babelfish import language_converters
from guessit import guessit
from dogpile.cache.api import NO_VALUE
from subliminal import Episode, ProviderError
from subliminal.video import Episode, Movie
from subliminal.exceptions import ConfigurationError, ServiceUnavailable
from subliminal.utils import sanitize_release_group
from subliminal.cache import region
@ -124,7 +125,7 @@ class SubsceneProvider(Provider, ProviderSubtitleArchiveMixin):
languages = supported_languages
languages.update(set(Language.rebuild(l, forced=True) for l in languages))
languages.update(set(Language.rebuild(l, hi=True) for l in languages))
video_types = (Episode, Movie)
session = None
skip_wrong_fps = False
hearing_impaired_verifiable = True

View File

@ -3,7 +3,7 @@
from __future__ import absolute_import
from guessit import guessit
from subliminal.video import Episode
from subliminal.video import Episode, Movie
from subliminal.providers.subscenter import SubsCenterProvider as _SubsCenterProvider, \
SubsCenterSubtitle as _SubsCenterSubtitle
from subzero.language import Language
@ -37,7 +37,7 @@ class SubsCenterSubtitle(_SubsCenterSubtitle):
class SubsCenterProvider(_SubsCenterProvider):
languages = {Language.fromalpha2(l) for l in ['he']}
video_types = (Episode, Movie)
subtitle_class = SubsCenterSubtitle
hearing_impaired_verifiable = True
server_url = 'http://www.subscenter.info/he/'

View File

@ -122,6 +122,7 @@ class SubsSabBzProvider(Provider):
languages = {Language(l) for l in [
'bul', 'eng'
]}
video_types = (Episode, Movie)
def initialize(self):
self.session = Session()

View File

@ -120,6 +120,7 @@ class SubsUnacsProvider(Provider):
languages = {Language(l) for l in [
'bul', 'eng'
]}
video_types = (Episode, Movie)
def initialize(self):
self.session = Session()

View File

@ -124,6 +124,7 @@ class SubtitrarinoiProvider(Provider, ProviderSubtitleArchiveMixin):
subtitle_class = SubtitrarinoiSubtitle
languages = {Language(lang) for lang in ['ron']}
languages.update(set(Language.rebuild(lang, forced=True) for lang in languages))
video_types = (Episode, Movie)
server_url = 'https://www.subtitrari-noi.ro/'
api_url = server_url + 'paginare_filme.php'

View File

@ -94,6 +94,7 @@ class SubtitriIdProvider(Provider, ProviderSubtitleArchiveMixin):
"""subtitri.id.lv Provider."""
subtitle_class = SubtitriIdSubtitle
languages = {Language('lva', 'LV')} | {Language.fromalpha2(l) for l in ['lv']}
video_types = (Movie,)
server_url = 'http://subtitri.id.lv'
search_url = server_url + '/search/'

View File

@ -135,6 +135,7 @@ class TitloviSubtitle(Subtitle):
class TitloviProvider(Provider, ProviderSubtitleArchiveMixin):
subtitle_class = TitloviSubtitle
languages = {Language.fromtitlovi(l) for l in language_converters['titlovi'].codes} | {Language.fromietf('sr-Latn')}
video_types = (Episode, Movie)
api_url = 'https://kodi.titlovi.com/api/subtitles'
api_gettoken_url = api_url + '/gettoken'
api_search_url = api_url + '/search'

View File

@ -125,6 +125,7 @@ class TitrariProvider(Provider, ProviderSubtitleArchiveMixin):
subtitle_class = TitrariSubtitle
languages = {Language(lang) for lang in ['ron', 'eng']}
languages.update(set(Language.rebuild(lang, forced=True) for lang in languages))
video_types = (Episode, Movie)
api_url = 'https://www.titrari.ro/'
query_advanced_search = 'cautarepreaavansata'

View File

@ -144,6 +144,7 @@ class TitulkyProvider(Provider, ProviderSubtitleArchiveMixin):
"""Titulky.com provider"""
languages = {Language(l) for l in ['ces', 'slk']}
video_types = (Episode, Movie)
hash_verifiable = False
hearing_impaired_verifiable = False
@ -203,7 +204,7 @@ class TitulkyProvider(Provider, ProviderSubtitleArchiveMixin):
def terminate(self):
self.logout()
self.session.close()
def login(self):
logger.info("Titulky.com: Logging in")

View File

@ -10,6 +10,7 @@ from subliminal.cache import SHOW_EXPIRATION_TIME, region, EPISODE_EXPIRATION_TI
from subliminal.providers.tvsubtitles import TVsubtitlesProvider as _TVsubtitlesProvider, \
TVsubtitlesSubtitle as _TVsubtitlesSubtitle, link_re, episode_id_re
from subliminal.utils import sanitize
from subliminal.video import Episode
logger = logging.getLogger(__name__)
@ -26,6 +27,7 @@ class TVsubtitlesProvider(_TVsubtitlesProvider):
'ara', 'bul', 'ces', 'dan', 'deu', 'ell', 'eng', 'fin', 'fra', 'hun', 'ita', 'jpn', 'kor', 'nld', 'pol', 'por',
'ron', 'rus', 'spa', 'swe', 'tur', 'ukr', 'zho'
]}
video_types = (Episode,)
subtitle_class = TVsubtitlesSubtitle
@region.cache_on_arguments(expiration_time=SHOW_EXPIRATION_TIME)

View File

@ -79,6 +79,7 @@ class WizdomSubtitle(Subtitle):
class WizdomProvider(Provider):
"""Wizdom Provider."""
languages = {Language(l) for l in ['heb']}
video_types = (Episode, Movie)
server_url = 'wizdom.xyz'
_tmdb_api_key = 'a51ee051bcd762543373903de296e0a3'

View File

@ -102,6 +102,7 @@ class YavkaNetProvider(Provider):
languages = {Language(l) for l in [
'bul', 'eng', 'rus', 'spa', 'ita'
]}
video_types = (Episode, Movie)
def initialize(self):
self.session = Session()

View File

@ -84,6 +84,7 @@ class ZimukuProvider(Provider):
"""Zimuku Provider."""
languages = {Language(*l) for l in supported_languages}
video_types = (Episode, Movie)
logger.info(str(supported_languages))
server_url = "http://zimuku.org"