2013-03-02 21:26:28 +01:00
|
|
|
# ex:ts=4:sw=4:sts=4:et
|
|
|
|
# -*- tab-width: 4; c-basic-offset: 4; indent-tabs-mode: nil -*-
|
2013-04-27 13:17:00 +02:00
|
|
|
# pylint has issues with urlparse: "some types could not be inferred"
|
|
|
|
# pylint: disable=E1103
|
2014-06-07 20:43:40 +02:00
|
|
|
import copy
|
2020-05-03 11:31:38 +02:00
|
|
|
import hashlib
|
2019-08-25 00:40:39 +02:00
|
|
|
import json
|
2020-05-03 11:31:38 +02:00
|
|
|
import logging
|
2019-08-25 00:40:39 +02:00
|
|
|
import re
|
2021-05-16 10:20:05 +02:00
|
|
|
from urllib.parse import parse_qs
|
2018-01-30 22:07:21 +01:00
|
|
|
from urllib.parse import urlparse
|
|
|
|
|
2019-08-25 00:40:39 +02:00
|
|
|
from svtplay_dl.error import ServiceError
|
2015-10-24 21:55:33 +02:00
|
|
|
from svtplay_dl.fetcher.hls import hlsparse
|
2021-03-05 00:41:49 +01:00
|
|
|
from svtplay_dl.fetcher.hls import M3U8
|
2019-08-25 00:40:39 +02:00
|
|
|
from svtplay_dl.service import OpenGraphThumbMixin
|
|
|
|
from svtplay_dl.service import Service
|
2014-08-31 01:20:36 +02:00
|
|
|
from svtplay_dl.subtitle import subtitle
|
2013-02-12 19:43:37 +01:00
|
|
|
|
2015-09-15 20:10:32 +02:00
|
|
|
|
2021-02-09 21:50:15 +01:00
|
|
|
country = {".se": "sv", ".dk": "da", ".no": "no"}
|
|
|
|
|
|
|
|
|
2021-05-13 22:07:39 +02:00
|
|
|
class Viafree(Service, OpenGraphThumbMixin):
|
2014-01-01 14:57:17 +01:00
|
|
|
supported_domains = [
|
2019-08-25 00:27:31 +02:00
|
|
|
"tv3play.ee",
|
|
|
|
"tv3play.lv",
|
|
|
|
"tv3play.lt",
|
|
|
|
"tvplay.lv",
|
|
|
|
"viagame.com",
|
|
|
|
"juicyplay.se",
|
|
|
|
"viafree.se",
|
|
|
|
"viafree.dk",
|
|
|
|
"viafree.no",
|
|
|
|
"viafree.fi",
|
|
|
|
"play.tv3.lt",
|
|
|
|
"tv3play.tv3.ee",
|
|
|
|
"tvplay.skaties.lv",
|
2016-10-20 19:07:56 +02:00
|
|
|
]
|
2013-01-17 00:21:47 +01:00
|
|
|
|
2015-12-26 11:46:14 +01:00
|
|
|
def get(self):
|
2020-05-03 11:31:38 +02:00
|
|
|
login = self._login()
|
|
|
|
if not login:
|
|
|
|
yield ServiceError("You need to login")
|
2014-11-01 21:10:06 +01:00
|
|
|
return
|
2018-01-30 20:11:37 +01:00
|
|
|
|
2020-05-03 11:31:38 +02:00
|
|
|
data = self.get_urldata()
|
|
|
|
match = re.search('}}}},("staticPages".*}}); windo', data)
|
|
|
|
if not match:
|
|
|
|
yield ServiceError("Cant find necessary info")
|
2014-09-11 23:51:32 +02:00
|
|
|
return
|
2021-10-18 16:23:59 +02:00
|
|
|
janson = self._jansonpage(match.group(1))
|
2020-05-03 11:31:38 +02:00
|
|
|
video = None
|
|
|
|
for play in janson["page"]["blocks"]:
|
|
|
|
if "componentName" in play and play["componentName"] == "player":
|
|
|
|
video = play
|
|
|
|
break
|
2014-12-22 17:41:40 +01:00
|
|
|
|
2020-05-03 11:31:38 +02:00
|
|
|
if not video:
|
|
|
|
yield ServiceError("Can't find video")
|
2014-11-01 21:10:06 +01:00
|
|
|
return
|
2014-06-26 21:52:32 +02:00
|
|
|
|
2020-05-03 11:31:38 +02:00
|
|
|
self._autoname(video)
|
2014-10-23 00:03:14 +02:00
|
|
|
|
2020-05-03 11:31:38 +02:00
|
|
|
if "subtitles" in video["_embedded"]["program"] and "subtitlesWebvtt" in video["_embedded"]["program"]["subtitles"]:
|
2021-03-05 00:41:49 +01:00
|
|
|
if "m3u8" in video["_embedded"]["program"]["subtitles"]["subtitlesWebvtt"]:
|
|
|
|
m3u8s = M3U8(self.http.get(video["_embedded"]["program"]["subtitles"]["subtitlesWebvtt"]).text)
|
|
|
|
yield subtitle(
|
|
|
|
copy.copy(self.config),
|
|
|
|
"wrstsegment",
|
|
|
|
video["_embedded"]["program"]["subtitles"]["subtitlesWebvtt"],
|
|
|
|
output=copy.copy(self.output),
|
|
|
|
m3u8=m3u8s,
|
|
|
|
)
|
2019-09-06 22:49:49 +02:00
|
|
|
|
2020-05-03 11:31:38 +02:00
|
|
|
res = self.http.get(video["_embedded"]["program"]["_links"]["streamLink"]["href"])
|
|
|
|
janson = res.json()
|
|
|
|
stream = janson["embedded"]["prioritizedStreams"][0]["links"]["stream"]
|
2014-05-01 17:04:08 +02:00
|
|
|
|
2021-11-10 10:34:17 +01:00
|
|
|
if video["_embedded"]["program"]["_links"]["streamLink"] and stream["href"]:
|
2021-05-16 10:20:05 +02:00
|
|
|
parse = urlparse(stream["href"])
|
|
|
|
query = parse_qs(parse.query)
|
|
|
|
query.pop("filter", None)
|
|
|
|
query = "&".join(f"{key}={val[0]}".format(key, val) for (key, val) in query.items())
|
|
|
|
hls_url = f"https://{parse.netloc}{parse.path}?{query}"
|
2021-05-16 02:22:37 +02:00
|
|
|
yield from hlsparse(
|
2020-05-03 11:31:38 +02:00
|
|
|
self.config,
|
2021-05-16 10:20:05 +02:00
|
|
|
self.http.request("get", hls_url),
|
|
|
|
hls_url,
|
2020-05-03 11:31:38 +02:00
|
|
|
output=self.output,
|
2021-02-28 22:05:15 +01:00
|
|
|
authorization=f"MTG-AT {self.token}",
|
2020-05-03 11:31:38 +02:00
|
|
|
)
|
2021-05-16 02:22:37 +02:00
|
|
|
|
2020-11-13 11:30:42 +01:00
|
|
|
if "subtitles" in janson["embedded"] and len(janson["embedded"]["subtitles"]) > 0:
|
2021-02-09 21:50:15 +01:00
|
|
|
lang = re.search(r"(\.\w\w)$", urlparse(self.url).netloc).group(1)
|
|
|
|
if lang in country:
|
|
|
|
language = country[lang]
|
|
|
|
else:
|
|
|
|
language = None
|
2021-05-22 22:59:43 +02:00
|
|
|
self.config.set("subtitle_preferred", language)
|
2021-02-09 21:50:15 +01:00
|
|
|
|
|
|
|
if not self.config.get("get_all_subtitles"):
|
|
|
|
if not language:
|
2021-05-09 21:52:46 +02:00
|
|
|
yield subtitle(copy.deepcopy(self.config), "wrst", janson["embedded"]["subtitles"][0]["link"]["href"], output=self.output)
|
2021-02-09 21:50:15 +01:00
|
|
|
else:
|
|
|
|
for i in janson["embedded"]["subtitles"]:
|
2021-05-09 21:52:46 +02:00
|
|
|
if i["data"]["language"] == language and i["data"]["sdh"] is False:
|
|
|
|
yield subtitle(copy.deepcopy(self.config), "wrst", i["link"]["href"], output=self.output)
|
2021-02-09 21:50:15 +01:00
|
|
|
|
|
|
|
else:
|
2021-05-09 21:52:46 +02:00
|
|
|
substitles = {}
|
2021-02-09 21:50:15 +01:00
|
|
|
for i in janson["embedded"]["subtitles"]:
|
2021-05-09 21:52:46 +02:00
|
|
|
substitles[(i["data"]["language"], i["data"]["sdh"])] = i["link"]["href"]
|
|
|
|
|
|
|
|
for i in substitles:
|
|
|
|
lang, shd = i
|
|
|
|
if shd:
|
|
|
|
lang = f"{lang}-shd"
|
|
|
|
yield subtitle(copy.deepcopy(self.config), "wrst", substitles[i], lang, output=copy.copy(self.output))
|
2014-01-11 23:02:47 +01:00
|
|
|
|
2018-05-21 22:56:22 +02:00
|
|
|
def find_all_episodes(self, config):
|
2017-09-08 18:59:18 +02:00
|
|
|
episodes = []
|
2020-05-03 11:31:38 +02:00
|
|
|
parse = urlparse(self.url)
|
|
|
|
data = self.get_urldata()
|
|
|
|
match = re.search('}}}},("staticPages".*}}); windo', data)
|
|
|
|
if not match:
|
|
|
|
logging.error("Cant find necessary info")
|
2021-12-18 20:18:25 +01:00
|
|
|
return episodes
|
2017-09-08 18:59:18 +02:00
|
|
|
|
2021-10-18 16:23:59 +02:00
|
|
|
janson = self._jansonpage(match.group(1))
|
2020-05-03 11:31:38 +02:00
|
|
|
seasons = []
|
2017-09-08 18:59:18 +02:00
|
|
|
|
2020-05-03 11:31:38 +02:00
|
|
|
if janson["page"]["pageType"] == "player":
|
2021-12-18 19:52:08 +01:00
|
|
|
res = self.http.get(f"{parse.scheme}://{parse.netloc}{janson['page']['blocks'][0]['_links']['back']['publicPath']}")
|
2020-05-03 11:31:38 +02:00
|
|
|
data = res.text
|
|
|
|
match = re.search('}}}},("staticPages".*}}); windo', data)
|
|
|
|
if not match:
|
|
|
|
logging.error("Cant find necessary info")
|
2021-12-18 20:18:25 +01:00
|
|
|
return episodes
|
2017-09-08 18:59:18 +02:00
|
|
|
|
2021-10-18 16:23:59 +02:00
|
|
|
janson = self._jansonpage(match.group(1))
|
2020-05-03 11:31:38 +02:00
|
|
|
|
|
|
|
for i in janson["page"]["blocks"]:
|
|
|
|
if i["slug"] == "series_header" and "seasons" in i["seriesHeader"]:
|
|
|
|
for n in i["seriesHeader"]["seasons"]:
|
|
|
|
seasons.append(n["_links"]["season"]["href"])
|
|
|
|
break
|
|
|
|
|
|
|
|
videos_tmp = []
|
|
|
|
clips = []
|
|
|
|
for season in seasons:
|
|
|
|
res = self.http.get(season)
|
|
|
|
janson = res.json()
|
|
|
|
|
|
|
|
groups = None
|
|
|
|
for i in janson["_embedded"]["viafreeBlocks"]:
|
|
|
|
if i["componentName"] == "groups":
|
|
|
|
groups = i
|
|
|
|
break
|
|
|
|
|
|
|
|
if groups:
|
|
|
|
for i in groups["_embedded"]["blocks"][0]["_embedded"]["programs"]:
|
|
|
|
if i["type"] == "episode":
|
|
|
|
if i["episode"]["episodeNumber"]:
|
|
|
|
videos_tmp.append(
|
|
|
|
[
|
2021-12-18 19:52:08 +01:00
|
|
|
int(f"{i['episode']['seasonNumber']}{i['episode']['episodeNumber']}"),
|
|
|
|
f"{parse.scheme}://{parse.netloc}{i['publicPath']}",
|
2020-12-26 13:10:56 +01:00
|
|
|
],
|
2020-05-03 11:31:38 +02:00
|
|
|
)
|
|
|
|
elif config.get("include_clips"):
|
2021-12-18 19:52:08 +01:00
|
|
|
clips.append(f"{parse.scheme}://{parse.netloc}{i['publicPath']}")
|
2020-05-03 11:31:38 +02:00
|
|
|
else:
|
2021-12-18 19:52:08 +01:00
|
|
|
episodes.append(f"{parse.scheme}://{parse.netloc}{i['publicPath']}")
|
2020-05-03 11:31:38 +02:00
|
|
|
if videos_tmp:
|
|
|
|
for i in sorted(videos_tmp, key=lambda x: x[0]):
|
|
|
|
episodes.append(i[1])
|
2017-09-08 18:59:18 +02:00
|
|
|
|
2020-05-03 11:31:38 +02:00
|
|
|
if config.get("all_last") > 0:
|
|
|
|
return episodes[-config.get("all_last") :]
|
2018-01-30 20:11:37 +01:00
|
|
|
|
2020-05-03 11:31:38 +02:00
|
|
|
if clips:
|
|
|
|
episodes.extend(clips)
|
|
|
|
|
|
|
|
return sorted(episodes)
|
2018-01-30 20:11:37 +01:00
|
|
|
|
2015-10-24 21:55:33 +02:00
|
|
|
def _autoname(self, dataj):
|
2020-05-03 11:31:38 +02:00
|
|
|
typ = dataj["_embedded"]["program"]["type"]
|
|
|
|
title = dataj["_embedded"]["program"]["title"]
|
2017-02-15 23:15:50 +01:00
|
|
|
|
2020-05-03 11:31:38 +02:00
|
|
|
vid = dataj["_embedded"]["program"]["guid"]
|
|
|
|
if re.search("-", vid): # in sports they have "-" in the id..
|
|
|
|
vid = hashlib.sha256(vid.encode("utf-8")).hexdigest()[:7]
|
|
|
|
self.output["id"] = vid
|
2017-02-11 10:19:57 +01:00
|
|
|
|
2020-05-03 11:31:38 +02:00
|
|
|
if typ == "episode":
|
|
|
|
program = dataj["_embedded"]["program"][typ]["seriesTitle"]
|
|
|
|
self.output["season"] = dataj["_embedded"]["program"][typ]["seasonNumber"]
|
|
|
|
self.output["episode"] = dataj["_embedded"]["program"][typ]["episodeNumber"]
|
|
|
|
self.output["episodename"] = title
|
|
|
|
elif typ == "clip":
|
|
|
|
program = dataj["_embedded"]["program"]["episode"]["seriesTitle"]
|
|
|
|
self.output["season"] = dataj["_embedded"]["program"]["episode"]["seasonNumber"]
|
|
|
|
self.output["episodename"] = title
|
|
|
|
else:
|
|
|
|
program = title
|
2017-02-15 23:15:50 +01:00
|
|
|
|
2018-05-13 13:06:45 +02:00
|
|
|
self.output["title"] = program
|
2018-05-31 00:16:12 +02:00
|
|
|
|
2020-05-03 11:31:38 +02:00
|
|
|
def _login(self):
|
|
|
|
res = self.http.post(
|
|
|
|
"https://viafree.mtg-api.com/identity/viafree/auth/pwd/sessions",
|
|
|
|
json={"email": self.config.get("username"), "password": self.config.get("password")},
|
|
|
|
headers={"Accept": "Application/json"},
|
|
|
|
)
|
|
|
|
|
|
|
|
if res.status_code < 400:
|
|
|
|
self.userID = res.json()["data"]["userData"]["userId"]
|
|
|
|
self.token = res.json()["data"]["accessToken"]
|
|
|
|
return True
|
|
|
|
return False
|
2021-10-18 16:23:59 +02:00
|
|
|
|
2021-10-19 21:52:19 +02:00
|
|
|
def _jansonpage(self, text):
|
2021-12-18 19:52:08 +01:00
|
|
|
return json.loads(f"{{{text.replace('undefined', 'null')}")
|