1# -*- coding: utf-8 -*-
2import io
3import logging
4import os
5
6from zipfile import ZipFile, is_zipfile
7from requests import Session
8from guessit import guessit
9
10from subliminal import Movie
11from subliminal.subtitle import SUBTITLE_EXTENSIONS, fix_line_ending
12from subliminal_patch.exceptions import APIThrottled
13from subliminal_patch.providers import Provider
14from subliminal_patch.subtitle import Subtitle, guess_matches
15from subzero.language import Language
16
17logger = logging.getLogger(__name__)
18
19SERVER_URL = "https://www.subsynchro.com/include/ajax/subMarin.php"
20PAGE_URL = "https://www.subsynchro.com"
21
22
23class SubsynchroSubtitle(Subtitle):
24    provider_name = "subsynchro"
25    hash_verifiable = False
26
27    def __init__(
28        self,
29        language,
30        release_info,
31        filename,
32        download_url,
33        file_type,
34        matches,
35    ):
36        super(SubsynchroSubtitle, self).__init__(
37            language, hearing_impaired=False, page_link=download_url
38        )
39        self.download_url = download_url
40        self.language = language
41        self.file_type = file_type
42        self.release_info = release_info
43        self.filename = filename
44        self.release_info = (
45            release_info if len(release_info) > len(filename) else filename
46        )
47        self.found_matches = matches
48
49    @property
50    def id(self):
51        return self.download_url
52
53    def get_matches(self, video):
54        self.found_matches |= guess_matches(
55            video,
56            guessit(
57                self.filename,
58            ),
59        )
60        self.found_matches |= guess_matches(
61            video,
62            guessit(
63                self.release_info,
64            ),
65        )
66        return self.found_matches
67
68
69class SubsynchroProvider(Provider):
70    """Subsynchro Provider"""
71
72    languages = {Language.fromalpha2(l) for l in ["fr"]}
73    language_list = list(languages)
74    video_types = (Movie,)
75
76    def initialize(self):
77        self.session = Session()
78        self.session.headers = {"User-Agent": "Bazarr", "Referer": PAGE_URL}
79
80    def terminate(self):
81        self.session.close()
82
83    def query(self, languages, video):
84        language = self.language_list[0]
85
86        params = {"title": video.title, "year": video.year}
87
88        logger.debug("Searching subtitles from params: %s", params)
89
90        result = self.session.get(SERVER_URL, params=params, timeout=10)
91        result.raise_for_status()
92
93        subtitles = []
94        results = result.json() or {}
95
96        status_ = results.get("status")
97
98        if status_ != 200:
99            logger.debug(f"No subtitles found (status {status_})")
100            return subtitles
101
102        for i in results.get("data", []):
103            matches = set()
104            if any(
105                video.title.lower() in title.lower()
106                for title in (i.get("titre", "n/a"), i.get("titre_original", "n/a"))
107            ):
108                # Year is already set on query
109                matches.update(["title", "year"])
110
111            subtitles.append(
112                SubsynchroSubtitle(
113                    language,
114                    i.get("release", "n/a"),
115                    i.get("filename", "n/a"),
116                    i.get("telechargement"),
117                    i.get("fichier"),
118                    matches,
119                )
120            )
121        return subtitles
122
123    def list_subtitles(self, video, languages):
124        return self.query(languages, video)
125
126    def get_file(self, archive):
127        for name in archive.namelist():
128            if os.path.split(name)[-1].startswith("."):
129                continue
130
131            if not name.lower().endswith(SUBTITLE_EXTENSIONS):
132                continue
133
134            logger.debug(f"Returning from archive: {name}")
135            return archive.read(name)
136
137        raise APIThrottled("Can not find the subtitle in the zip file")
138
139    def download_subtitle(self, subtitle):
140        logger.debug(f"Downloading subtitle {subtitle.download_url}")
141
142        response = self.session.get(
143            subtitle.download_url, allow_redirects=True, timeout=10
144        )
145        response.raise_for_status()
146
147        stream = io.BytesIO(response.content)
148        if is_zipfile(stream):
149            logger.debug("Zip file found")
150            subtitle_ = self.get_file(ZipFile(stream))
151            subtitle.content = fix_line_ending(subtitle_)
152        else:
153            raise APIThrottled(f"Unknown file type: {subtitle.download_url}")
154