mirror of
https://github.com/morpheus65535/bazarr.git
synced 2025-01-01 04:22:07 +08:00
Added Subsynchro provider
This commit is contained in:
parent
26850929a8
commit
25894c477f
4 changed files with 180 additions and 1 deletions
|
@ -64,6 +64,7 @@ If you need something that is not already part of Bazarr, feel free to create a
|
|||
* Subscene
|
||||
* Subscenter
|
||||
* Subsunacs.net
|
||||
* SubSynchro
|
||||
* subtitri.id.lv
|
||||
* Subtitulamos.tv
|
||||
* Sucha
|
||||
|
|
|
@ -160,6 +160,7 @@ export const ProviderList: Readonly<ProviderInfo[]> = [
|
|||
name: "Subsunacs.net",
|
||||
description: "Bulgarian Subtitles Provider",
|
||||
},
|
||||
{ key: "subsynchro", description: "French Subtitles Provider" },
|
||||
{
|
||||
key: "subtitri",
|
||||
name: "subtitri.id.lv",
|
||||
|
|
|
@ -3,6 +3,7 @@ from __future__ import absolute_import
|
|||
import io
|
||||
import logging
|
||||
import os
|
||||
import re
|
||||
import time
|
||||
import zipfile
|
||||
|
||||
|
@ -22,6 +23,13 @@ from subliminal_patch.subtitle import Subtitle
|
|||
from subliminal_patch.providers import Provider
|
||||
from guessit import guessit
|
||||
|
||||
|
||||
CLEAN_TITLE_RES = [
|
||||
(r"subt[ií]tulos de", ""),
|
||||
(r"´|`", "'"),
|
||||
(r" {2,}", " "),
|
||||
]
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
|
||||
|
@ -170,7 +178,7 @@ class SubdivxSubtitlesProvider(Provider):
|
|||
title_soup, body_soup = title_soups[subtitle], body_soups[subtitle]
|
||||
|
||||
# title
|
||||
title = title_soup.find("a").text.replace("Subtitulos de ", "")
|
||||
title = self._clean_title(title_soup.find("a").text)
|
||||
|
||||
# filter by year
|
||||
if video.year and str(video.year) not in title:
|
||||
|
@ -214,6 +222,17 @@ class SubdivxSubtitlesProvider(Provider):
|
|||
|
||||
raise APIThrottled("Download link not found")
|
||||
|
||||
@staticmethod
|
||||
def _clean_title(title):
|
||||
"""
|
||||
Normalize apostrophes and spaces to avoid matching problems
|
||||
(e.g. Subtitulos de Carlito´s Way -> Carlito's Way)
|
||||
"""
|
||||
for og, new in CLEAN_TITLE_RES:
|
||||
title = re.sub(og, new, title, flags=re.IGNORECASE)
|
||||
|
||||
return title
|
||||
|
||||
@staticmethod
|
||||
def _check_response(response):
|
||||
if response.status_code != 200:
|
||||
|
|
158
libs/subliminal_patch/providers/subsynchro.py
Normal file
158
libs/subliminal_patch/providers/subsynchro.py
Normal file
|
@ -0,0 +1,158 @@
|
|||
# -*- coding: utf-8 -*-
|
||||
import io
|
||||
import logging
|
||||
import os
|
||||
|
||||
from zipfile import ZipFile
|
||||
from requests import Session
|
||||
from guessit import guessit
|
||||
|
||||
from subliminal import Movie
|
||||
from subliminal.subtitle import SUBTITLE_EXTENSIONS, fix_line_ending
|
||||
from subliminal_patch.exceptions import APIThrottled
|
||||
from subliminal_patch.providers import Provider
|
||||
from subliminal_patch.subtitle import Subtitle, guess_matches
|
||||
from subzero.language import Language
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
SERVER_URL = "https://www.subsynchro.com/include/ajax/subMarin.php"
|
||||
PAGE_URL = "https://www.subsynchro.com"
|
||||
|
||||
|
||||
class SubsynchroSubtitle(Subtitle):
|
||||
provider_name = "subsynchro"
|
||||
hash_verifiable = False
|
||||
|
||||
def __init__(
|
||||
self,
|
||||
language,
|
||||
release_info,
|
||||
filename,
|
||||
download_url,
|
||||
file_type,
|
||||
matches,
|
||||
):
|
||||
super(SubsynchroSubtitle, self).__init__(
|
||||
language, hearing_impaired=False, page_link=download_url
|
||||
)
|
||||
self.download_url = download_url
|
||||
self.language = language
|
||||
self.file_type = file_type
|
||||
self.release_info = release_info
|
||||
self.filename = filename
|
||||
self.release_info = (
|
||||
release_info if len(release_info) > len(filename) else filename
|
||||
)
|
||||
self.found_matches = matches
|
||||
|
||||
@property
|
||||
def id(self):
|
||||
return self.download_url
|
||||
|
||||
def get_matches(self, video):
|
||||
self.found_matches |= guess_matches(
|
||||
video,
|
||||
guessit(
|
||||
self.filename,
|
||||
),
|
||||
)
|
||||
self.found_matches |= guess_matches(
|
||||
video,
|
||||
guessit(
|
||||
self.release_info,
|
||||
),
|
||||
)
|
||||
return self.found_matches
|
||||
|
||||
|
||||
class SubsynchroProvider(Provider):
|
||||
"""Subsynchro Provider"""
|
||||
|
||||
languages = {Language.fromalpha2(l) for l in ["fr"]}
|
||||
language_list = list(languages)
|
||||
video_types = (Movie,)
|
||||
|
||||
def initialize(self):
|
||||
self.session = Session()
|
||||
self.session.headers = {"User-Agent": "Bazarr", "Referer": PAGE_URL}
|
||||
|
||||
def terminate(self):
|
||||
self.session.close()
|
||||
|
||||
def query(self, languages, video):
|
||||
language = self.language_list[0]
|
||||
|
||||
params = {"title": video.title, "year": video.year}
|
||||
|
||||
logger.debug("Searching subtitles from params: %s", params)
|
||||
|
||||
result = self.session.get(SERVER_URL, params=params, timeout=10)
|
||||
result.raise_for_status()
|
||||
|
||||
subtitles = []
|
||||
results = result.json() or {}
|
||||
|
||||
status_ = results.get("status")
|
||||
|
||||
if status_ != 200:
|
||||
logger.debug(f"No subtitles found (status {status_})")
|
||||
return subtitles
|
||||
|
||||
for i in results.get("data", []):
|
||||
matches = set()
|
||||
if any(
|
||||
video.title.lower() in title.lower()
|
||||
for title in (i.get("titre", "n/a"), i.get("titre_original", "n/a"))
|
||||
):
|
||||
# Year is already set on query
|
||||
matches.update(["title", "year"])
|
||||
|
||||
subtitles.append(
|
||||
SubsynchroSubtitle(
|
||||
language,
|
||||
i.get("release", "n/a"),
|
||||
i.get("filename", "n/a"),
|
||||
i.get("telechargement"),
|
||||
i.get("fichier"),
|
||||
matches,
|
||||
)
|
||||
)
|
||||
return subtitles
|
||||
|
||||
def list_subtitles(self, video, languages):
|
||||
return self.query(languages, video)
|
||||
|
||||
def get_file(self, archive):
|
||||
for name in archive.namelist():
|
||||
if os.path.split(name)[-1].startswith("."):
|
||||
continue
|
||||
|
||||
if not name.lower().endswith(SUBTITLE_EXTENSIONS):
|
||||
continue
|
||||
|
||||
logger.debug(f"Returning from archive: {name}")
|
||||
return archive.read(name)
|
||||
|
||||
raise APIThrottled("Can not find the subtitle in the zip file")
|
||||
|
||||
def download_subtitle(self, subtitle):
|
||||
logger.debug(f"Downloading subtitle {subtitle.download_url}")
|
||||
|
||||
response = self.session.get(
|
||||
subtitle.download_url, allow_redirects=True, timeout=10
|
||||
)
|
||||
response.raise_for_status()
|
||||
|
||||
if subtitle.file_type.endswith(".zip"):
|
||||
logger.debug("Zip file found")
|
||||
subtitle_ = self.get_file(ZipFile(io.BytesIO(response.content)))
|
||||
|
||||
elif subtitle.file_type.endswith(".srt"):
|
||||
logger.debug("Srt file found")
|
||||
subtitle_ = response.content
|
||||
|
||||
else:
|
||||
raise APIThrottled(f"Unknown file type: {subtitle.file_type}")
|
||||
|
||||
subtitle.content = fix_line_ending(subtitle_)
|
Loading…
Reference in a new issue