mirror of
https://github.com/spaam/svtplay-dl.git
synced 2024-11-24 04:05:39 +01:00
120 lines
4.7 KiB
Python
120 lines
4.7 KiB
Python
import datetime
|
|
import logging
|
|
import re
|
|
import uuid
|
|
from urllib.parse import urlparse
|
|
|
|
from svtplay_dl.error import ServiceError
|
|
from svtplay_dl.fetcher.hls import hlsparse
|
|
from svtplay_dl.service import OpenGraphThumbMixin
|
|
from svtplay_dl.service import Service
|
|
from svtplay_dl.subtitle import subtitle
|
|
|
|
|
|
class Plutotv(Service, OpenGraphThumbMixin):
|
|
supported_domains = ["pluto.tv"]
|
|
urlreg = r"/on-demand/(movies|series)/([^/]+)(/season/\d+/episode/([^/]+))?"
|
|
urlreg2 = r"/on-demand/(movies|series)/([^/]+)(/episode/([^/]+))?"
|
|
|
|
def get(self):
|
|
self.data = self.get_urldata()
|
|
parse = urlparse(self.url)
|
|
|
|
urlmatch = re.search(self.urlreg, parse.path)
|
|
if not urlmatch:
|
|
yield ServiceError("Can't find what video it is or live is not supported")
|
|
return
|
|
|
|
self.slug = urlmatch.group(2)
|
|
episodename = urlmatch.group(4)
|
|
if episodename is None:
|
|
urlmatch = re.search(self.urlreg2, parse.path)
|
|
if not urlmatch:
|
|
yield ServiceError("Can't find what video it is or live is not supported")
|
|
return
|
|
self.slug = urlmatch.group(2)
|
|
episodename = urlmatch.group(4)
|
|
self._janson()
|
|
HLSplaylist = None
|
|
|
|
for vod in self.janson["VOD"]:
|
|
self.output["title"] = vod["name"]
|
|
if "seasons" in vod:
|
|
for season in vod["seasons"]:
|
|
if "episodes" in season:
|
|
for episode in season["episodes"]:
|
|
if episode["_id"] == episodename:
|
|
self.output["season"] = season["number"]
|
|
self.output["episodename"] = episode["name"]
|
|
for stich in episode["stitched"]["paths"]:
|
|
if stich["type"] == "hls":
|
|
HLSplaylist = f"{self.mediaserver}{stich['path']}?{self.stitcherParams}"
|
|
if self.http.request("get", HLSplaylist).status_code < 400:
|
|
break
|
|
|
|
if not HLSplaylist:
|
|
yield ServiceError("Can't find video info")
|
|
return
|
|
|
|
playlists = hlsparse(
|
|
self.config,
|
|
self.http.request("get", HLSplaylist, headers={"Authorization": f"Bearer {self.sessionToken}"}),
|
|
HLSplaylist,
|
|
self.output,
|
|
filter=True,
|
|
)
|
|
|
|
for playlist in playlists:
|
|
if self.config.get("subtitle") and isinstance(playlist, subtitle):
|
|
logging.warning("Subtitles are no longer supported for pluto.tv")
|
|
continue
|
|
yield playlist
|
|
|
|
def find_all_episodes(self, options):
|
|
episodes = []
|
|
self.data = self.get_urldata()
|
|
parse = urlparse(self.url)
|
|
urlmatch = re.search(self.urlreg, parse.path)
|
|
if urlmatch is None:
|
|
logging.error("Can't find what video it is or live is not supported")
|
|
return episodes
|
|
if urlmatch.group(1) != "series":
|
|
return episodes
|
|
self.slug = urlmatch.group(2)
|
|
self._janson()
|
|
|
|
match = re.search(r"^/([^\/]+)/", parse.path)
|
|
language = match.group(1)
|
|
|
|
for vod in self.janson["VOD"]:
|
|
if "seasons" in vod:
|
|
for season in vod["seasons"]:
|
|
seasonnr = season["number"]
|
|
if "episodes" in season:
|
|
for episode in season["episodes"]:
|
|
episodes.append(f"https://pluto.tv/{language}/on-demand/series/{self.slug}/season/{seasonnr}/episode/{episode['_id']}")
|
|
return episodes
|
|
|
|
def _janson(self) -> None:
|
|
self.appversion = re.search('appVersion" content="([^"]+)"', self.data)
|
|
self.query = {
|
|
"appName": "web",
|
|
"appVersion": self.appversion.group(1) if self.appversion else "na",
|
|
"deviceVersion": "119.0.0",
|
|
"deviceModel": "web",
|
|
"deviceMake": "firefox",
|
|
"deviceType": "web",
|
|
"clientID": uuid.uuid1(),
|
|
"clientModelNumber": "1.0.0",
|
|
"seriesIDs": self.slug,
|
|
"serverSideAds": "false",
|
|
"constraints": "",
|
|
"drmCapabilities": "widevine%3AL3",
|
|
"clientTime": datetime.datetime.utcnow().strftime("%Y-%m-%dT%H:%M:%SZ"),
|
|
}
|
|
res = self.http.request("get", "https://boot.pluto.tv/v4/start", params=self.query)
|
|
self.janson = res.json()
|
|
self.mediaserver = self.janson["servers"]["stitcher"]
|
|
self.stitcherParams = self.janson["stitcherParams"]
|
|
self.sessionToken = self.janson["sessionToken"]
|