|
21 | 21 | r"https?://(?:www\.)?mitele\.es/directo/(?P<channel>[\w-]+)"
|
22 | 22 | ))
|
23 | 23 | class Mitele(Plugin):
|
24 |
| - caronte_url = "https://caronte.mediaset.es/delivery/channel/mmc/{channel}/mtweb" |
25 |
| - gbx_url = "https://mab.mediaset.es/1.0.0/get?oid=mtmw&eid=%2Fapi%2Fmtmw%2Fv2%2Fgbx%2Fmtweb%2Flive%2Fmmc%2F{channel}" |
| 24 | + URL_CARONTE = "https://caronte.mediaset.es/delivery/channel/mmc/{channel}/mtweb" |
| 25 | + URL_GBX = "https://mab.mediaset.es/1.0.0/get" |
26 | 26 |
|
27 |
| - error_schema = validate.Schema({"code": int}) |
28 |
| - caronte_schema = validate.Schema(validate.parse_json(), validate.any( |
29 |
| - { |
30 |
| - "cerbero": validate.url(), |
31 |
| - "bbx": validate.text, |
32 |
| - "dls": [{ |
33 |
| - "lid": validate.all(int, validate.transform(validate.text)), |
34 |
| - "format": validate.any("hls", "dash", "smooth"), |
35 |
| - "stream": validate.url(), |
36 |
| - validate.optional("assetKey"): validate.text, |
37 |
| - "drm": bool, |
38 |
| - }], |
39 |
| - }, |
40 |
| - error_schema, |
41 |
| - )) |
42 |
| - gbx_schema = validate.Schema( |
43 |
| - validate.parse_json(), |
44 |
| - {"gbx": validate.text}, |
45 |
| - validate.get("gbx") |
46 |
| - ) |
47 |
| - cerbero_schema = validate.Schema( |
48 |
| - validate.parse_json(), |
49 |
| - validate.any( |
50 |
| - validate.all( |
51 |
| - {"tokens": {validate.text: {"cdn": validate.text}}}, |
52 |
| - validate.get("tokens") |
53 |
| - ), |
54 |
| - error_schema, |
55 |
| - ) |
56 |
| - ) |
57 |
| - token_errors = { |
58 |
| - 4038: "User has no privileges" |
| 27 | + TOKEN_ERRORS = { |
| 28 | + 4038: "User has no privileges", |
59 | 29 | }
|
60 | 30 |
|
61 | 31 | def _get_streams(self):
|
62 | 32 | channel = self.match.group("channel")
|
63 | 33 |
|
64 |
| - pdata = self.session.http.get(self.caronte_url.format(channel=channel), |
65 |
| - acceptable_status=(200, 403, 404), |
66 |
| - schema=self.caronte_schema) |
67 |
| - gbx = self.session.http.get(self.gbx_url.format(channel=channel), |
68 |
| - schema=self.gbx_schema) |
69 |
| - |
| 34 | + pdata = self.session.http.get( |
| 35 | + self.URL_CARONTE.format(channel=channel), |
| 36 | + acceptable_status=(200, 403, 404), |
| 37 | + schema=validate.Schema( |
| 38 | + validate.parse_json(), |
| 39 | + validate.any( |
| 40 | + {"code": int}, |
| 41 | + { |
| 42 | + "cerbero": validate.url(), |
| 43 | + "bbx": validate.text, |
| 44 | + "dls": validate.all( |
| 45 | + [{ |
| 46 | + "drm": bool, |
| 47 | + "format": validate.text, |
| 48 | + "stream": validate.url(), |
| 49 | + "lid": validate.all(int, validate.transform(validate.text)), |
| 50 | + validate.optional("assetKey"): validate.text, |
| 51 | + }], |
| 52 | + validate.filter(lambda obj: obj["format"] == "hls") |
| 53 | + ), |
| 54 | + }, |
| 55 | + ), |
| 56 | + ), |
| 57 | + ) |
70 | 58 | if "code" in pdata:
|
71 |
| - log.error("error getting pdata: {}".format(pdata["code"])) |
| 59 | + log.error("Error getting pdata: {0}".format(pdata['code'])) |
72 | 60 | return
|
73 | 61 |
|
74 |
| - tokens = self.session.http.post(pdata["cerbero"], |
75 |
| - acceptable_status=(200, 403, 404), |
76 |
| - json={"bbx": pdata["bbx"], "gbx": gbx}, |
77 |
| - headers={"origin": "https://www.mitele.es"}, |
78 |
| - schema=self.cerbero_schema) |
| 62 | + gbx = self.session.http.get( |
| 63 | + self.URL_GBX, |
| 64 | + params={ |
| 65 | + "oid": "mtmw", |
| 66 | + "eid": "/api/mtmw/v2/gbx/mtweb/live/mmc/{0}".format(channel), |
| 67 | + }, |
| 68 | + schema=validate.Schema( |
| 69 | + validate.parse_json(), |
| 70 | + {"gbx": validate.text}, |
| 71 | + validate.get("gbx"), |
| 72 | + ), |
| 73 | + ) |
79 | 74 |
|
| 75 | + tokens = self.session.http.post( |
| 76 | + pdata["cerbero"], |
| 77 | + acceptable_status=(200, 403, 404), |
| 78 | + json={ |
| 79 | + "bbx": pdata["bbx"], |
| 80 | + "gbx": gbx, |
| 81 | + }, |
| 82 | + headers={"origin": "https://www.mitele.es"}, |
| 83 | + schema=validate.Schema( |
| 84 | + validate.parse_json(), |
| 85 | + validate.any( |
| 86 | + {"code": int}, |
| 87 | + validate.all( |
| 88 | + {"tokens": {validate.text: {"cdn": validate.text}}}, |
| 89 | + validate.get("tokens") |
| 90 | + ), |
| 91 | + ), |
| 92 | + ), |
| 93 | + ) |
80 | 94 | if "code" in tokens:
|
81 |
| - log.error("Could not get stream tokens: {} ({})".format(tokens["code"], |
82 |
| - self.token_errors.get(tokens["code"], "unknown error"))) |
| 95 | + tokenerrors = self.TOKEN_ERRORS.get(tokens["code"], "unknown error") |
| 96 | + log.error("Could not get stream tokens: {0} ({1})".format(tokens['code'], tokenerrors)) |
83 | 97 | return
|
84 | 98 |
|
85 |
| - list_urls = [] |
| 99 | + urls = set() |
86 | 100 | for stream in pdata["dls"]:
|
87 | 101 | if stream["drm"]:
|
88 | 102 | log.warning("Stream may be protected by DRM")
|
89 |
| - else: |
90 |
| - sformat = stream.get("format") |
91 |
| - log.debug("Stream: {} ({})".format(stream["stream"], sformat or "n/a")) |
92 |
| - cdn_token = tokens.get(stream["lid"], {}).get("cdn", "") |
93 |
| - qsd = parse_qsd(cdn_token) |
94 |
| - if sformat == "hls": |
95 |
| - list_urls.append(update_qsd(stream["stream"], qsd)) |
96 |
| - |
97 |
| - if not list_urls: |
98 |
| - return |
| 103 | + continue |
| 104 | + cdn_token = tokens.get(stream["lid"], {}).get("cdn", "") |
| 105 | + qsd = parse_qsd(cdn_token) |
| 106 | + urls.add(update_qsd(stream["stream"], qsd, quote_via=lambda string, *_, **__: string)) |
99 | 107 |
|
100 |
| - for url in list(set(list_urls)): |
| 108 | + for url in urls: |
101 | 109 | for s in HLSStream.parse_variant_playlist(self.session, url, name_fmt="{pixels}_{bitrate}").items():
|
102 | 110 | yield s
|
103 | 111 |
|
|
0 commit comments