summaryrefslogtreecommitdiffhomepage
path: root/libs/subliminal_patch/providers/gestdown.py
blob: f668098649c56a74d9fb7d86844c04201f9a2945 (plain)
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
# -*- coding: utf-8 -*-

import logging
import time

from requests import HTTPError
from requests import Session
from subliminal_patch.core import Episode
from subliminal_patch.language import PatchedAddic7edConverter
from subliminal_patch.providers import Provider
from subliminal_patch.providers.utils import update_matches
from subliminal_patch.subtitle import Subtitle
from subzero.language import Language

logger = logging.getLogger(__name__)

_BASE_URL = "https://api.gestdown.info"


class GestdownSubtitle(Subtitle):
    provider_name = "gestdown"
    hash_verifiable = False

    def __init__(self, language, data: dict):
        super().__init__(language, hearing_impaired=data["hearingImpaired"])
        self.page_link = _BASE_URL + data["downloadUri"]
        self._id = data["subtitleId"]
        self.release_info = data["version"]
        self._matches = {"title", "series", "season", "episode"}

    def get_matches(self, video):
        update_matches(self._matches, video, self.release_info)

        return self._matches

    @property
    def id(self):
        return self._id


def _retry_on_423(method):
    def retry(self, *args, **kwargs):
        retries = 0
        while 5 > retries:
            try:
                yield from method(self, *args, **kwargs)
            except HTTPError as error:
                if error.response.status_code != 423:
                    raise

                retries += 1

                logger.debug("423 returned. Retrying in 30 seconds")
                time.sleep(30)
            else:
                break

        logger.debug("Retries limit exceeded. Ignoring query")

    return retry


class GestdownProvider(Provider):
    provider_name = "gestdown"

    video_types = (Episode,)
    subtitle_class = GestdownSubtitle

    # fmt: off
    languages = {Language('por', 'BR')} | {Language(l) for l in [
        'ara', 'aze', 'ben', 'bos', 'bul', 'cat', 'ces', 'dan', 'deu', 'ell', 'eng', 'eus', 'fas', 'fin', 'fra', 'glg',
        'heb', 'hrv', 'hun', 'hye', 'ind', 'ita', 'jpn', 'kor', 'mkd', 'msa', 'nld', 'nor', 'pol', 'por', 'ron', 'rus',
        'slk', 'slv', 'spa', 'sqi', 'srp', 'swe', 'tha', 'tur', 'ukr', 'vie', 'zho'
    ]} | {Language.fromietf(l) for l in ["sr-Latn", "sr-Cyrl"]}
    languages.update(set(Language.rebuild(l, hi=True) for l in languages))
    # fmt: on

    _converter = PatchedAddic7edConverter()

    def initialize(self):
        self._session = Session()
        self._session.headers.update({"User-Agent": "Bazarr"})

    def terminate(self):
        self._session.close()

    @_retry_on_423
    def _subtitles_search(self, video, language: Language):
        json_data = {
            "search": f"{video.series} S{video.season:02}E{video.episode:02}",
            "language": self._converter.convert(language.alpha3),
        }

        logger.debug("Post data: %s", json_data)
        response = self._session.post(f"{_BASE_URL}/subtitles/search", json=json_data)

        # TODO: implement rate limiting
        response.raise_for_status()

        matching_subtitles = response.json()["matchingSubtitles"]

        if not matching_subtitles:
            logger.debug("No episodes found for '%s' language", language)
            return None

        for subtitle_dict in matching_subtitles:
            sub = GestdownSubtitle(language, subtitle_dict)
            logger.debug("Found subtitle: %s", sub)
            yield sub

    def list_subtitles(self, video, languages):
        subtitles = []
        for language in languages:
            try:
                subtitles += self._subtitles_search(video, language)
            except HTTPError as error:
                if error.response.status_code == 404:
                    logger.debug("Couldn't find the show or its season/episode")
                    return []
                raise

        return subtitles

    def download_subtitle(self, subtitle: GestdownSubtitle):
        response = self._session.get(subtitle.page_link, allow_redirects=True)
        response.raise_for_status()
        subtitle.content = response.content