forked from FairTrade/unshackle-services
Added geoblocking error on KNPY
This commit is contained in:
parent
4513b1c0d4
commit
630b2e1099
@ -269,29 +269,38 @@ class KNPY(Service):
|
|||||||
"visitorId": self._visitor_id
|
"visitorId": self._visitor_id
|
||||||
}
|
}
|
||||||
|
|
||||||
if "authorization" not in self.session.headers:
|
self.session.headers.setdefault("authorization", f"Bearer {self._jwt}")
|
||||||
self.session.headers["authorization"] = f"Bearer {self._jwt}"
|
self.session.headers.setdefault("x-version", self.API_VERSION)
|
||||||
self.session.headers["x-version"] = self.API_VERSION
|
self.session.headers.setdefault("user-agent", self.USER_AGENT)
|
||||||
self.session.headers["user-agent"] = self.USER_AGENT
|
|
||||||
|
|
||||||
r = self.session.post(
|
r = self.session.post(self.config["endpoints"]["plays"], json=play_payload)
|
||||||
self.config["endpoints"]["plays"],
|
response_json = None
|
||||||
json=play_payload,
|
try:
|
||||||
)
|
response_json = r.json()
|
||||||
|
except Exception:
|
||||||
|
pass
|
||||||
|
|
||||||
|
# Handle known errors gracefully
|
||||||
|
if r.status_code == 403:
|
||||||
|
if response_json and response_json.get("errorSubcode") == "playRegionRestricted":
|
||||||
|
self.log.error("Kanopy reports: This video is not available in your country.")
|
||||||
|
raise PermissionError(
|
||||||
|
"Playback blocked by region restriction. Try connecting through a supported country or verify your library’s access region."
|
||||||
|
)
|
||||||
|
else:
|
||||||
|
self.log.error(f"Access forbidden (HTTP 403). Response: {response_json}")
|
||||||
|
raise PermissionError("Kanopy denied access to this video. It may require a different library membership or authentication.")
|
||||||
|
|
||||||
|
# Raise for any other HTTP errors
|
||||||
r.raise_for_status()
|
r.raise_for_status()
|
||||||
play_data = r.json()
|
play_data = response_json or r.json()
|
||||||
|
|
||||||
manifest_url = None
|
manifest_url = None
|
||||||
for manifest in play_data.get("manifests", []):
|
for manifest in play_data.get("manifests", []):
|
||||||
if manifest["manifestType"] == "dash":
|
if manifest["manifestType"] == "dash":
|
||||||
manifest_relative_url = manifest["url"]
|
url = manifest["url"]
|
||||||
if manifest_relative_url.startswith("/"):
|
manifest_url = f"https://kanopy.com{url}" if url.startswith("/") else url
|
||||||
manifest_url = f"https://kanopy.com{manifest_relative_url}"
|
|
||||||
else:
|
|
||||||
manifest_url = manifest_relative_url
|
|
||||||
|
|
||||||
drm_type = manifest.get("drmType")
|
drm_type = manifest.get("drmType")
|
||||||
|
|
||||||
if drm_type == "kanopyDrm":
|
if drm_type == "kanopyDrm":
|
||||||
play_id = play_data.get("playId")
|
play_id = play_data.get("playId")
|
||||||
self.widevine_license_url = self.config["endpoints"]["widevine_license"].format(license_id=f"{play_id}-0")
|
self.widevine_license_url = self.config["endpoints"]["widevine_license"].format(license_id=f"{play_id}-0")
|
||||||
@ -311,7 +320,8 @@ class KNPY(Service):
|
|||||||
self.log.info(f"Fetching DASH manifest from: {manifest_url}")
|
self.log.info(f"Fetching DASH manifest from: {manifest_url}")
|
||||||
r = self.session.get(manifest_url)
|
r = self.session.get(manifest_url)
|
||||||
r.raise_for_status()
|
r.raise_for_status()
|
||||||
|
|
||||||
|
# Refresh headers for manifest parsing
|
||||||
self.session.headers.clear()
|
self.session.headers.clear()
|
||||||
self.session.headers.update({
|
self.session.headers.update({
|
||||||
"User-Agent": self.WIDEVINE_UA,
|
"User-Agent": self.WIDEVINE_UA,
|
||||||
@ -319,23 +329,23 @@ class KNPY(Service):
|
|||||||
"Accept-Encoding": "gzip, deflate",
|
"Accept-Encoding": "gzip, deflate",
|
||||||
"Connection": "keep-alive",
|
"Connection": "keep-alive",
|
||||||
})
|
})
|
||||||
|
|
||||||
tracks = DASH.from_text(r.text, url=manifest_url).to_tracks(language=title.language)
|
tracks = DASH.from_text(r.text, url=manifest_url).to_tracks(language=title.language)
|
||||||
|
|
||||||
for caption_data in play_data.get("captions", []):
|
for caption_data in play_data.get("captions", []):
|
||||||
lang_code = caption_data.get("language", "en")
|
lang = caption_data.get("language", "en")
|
||||||
for file_info in caption_data.get("files", []):
|
for file_info in caption_data.get("files", []):
|
||||||
if file_info.get("type") == "webvtt":
|
if file_info.get("type") == "webvtt":
|
||||||
tracks.add(Subtitle(
|
tracks.add(Subtitle(
|
||||||
id_=f"caption-{lang_code}",
|
id_=f"caption-{lang}",
|
||||||
url=file_info["url"],
|
url=file_info["url"],
|
||||||
codec=Subtitle.Codec.WebVTT,
|
codec=Subtitle.Codec.WebVTT,
|
||||||
language=Language.get(lang_code)
|
language=Language.get(lang)
|
||||||
))
|
))
|
||||||
break
|
break
|
||||||
|
|
||||||
return tracks
|
return tracks
|
||||||
|
|
||||||
|
|
||||||
def get_widevine_license(self, *, challenge: bytes, title: Title_T, track: AnyTrack) -> bytes:
|
def get_widevine_license(self, *, challenge: bytes, title: Title_T, track: AnyTrack) -> bytes:
|
||||||
if not self.widevine_license_url:
|
if not self.widevine_license_url:
|
||||||
raise ValueError("Widevine license URL was not set. Call get_tracks first.")
|
raise ValueError("Widevine license URL was not set. Call get_tracks first.")
|
||||||
@ -394,4 +404,4 @@ class KNPY(Service):
|
|||||||
# return results
|
# return results
|
||||||
|
|
||||||
def get_chapters(self, title: Title_T) -> list:
|
def get_chapters(self, title: Title_T) -> list:
|
||||||
return []
|
return []
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user