refactor(MY5): Change endpoints to android
- The old method of fetching hmac keys from javascript has been removed, along with the github that hosted them. - The required cert is included in the code itself and not needed separately
This commit is contained in:
parent
fcc87ac317
commit
62d226671d
@ -1,24 +1,22 @@
|
||||
from __future__ import annotations
|
||||
|
||||
import base64
|
||||
import hashlib
|
||||
import hmac
|
||||
import json
|
||||
import re
|
||||
import tempfile
|
||||
import os
|
||||
from collections.abc import Generator
|
||||
from datetime import datetime
|
||||
from typing import Any, Union
|
||||
from urllib.parse import urlparse, urlunparse
|
||||
|
||||
import click
|
||||
import requests
|
||||
from click import Context
|
||||
from Crypto.Cipher import AES
|
||||
from Crypto.Util.Padding import unpad
|
||||
from devine.core.manifests.dash import DASH
|
||||
from devine.core.search_result import SearchResult
|
||||
from devine.core.service import Service
|
||||
from devine.core.titles import Episode, Movie, Movies, Series
|
||||
from devine.core.tracks import Chapter, Tracks
|
||||
from devine.core.utils.sslciphers import SSLCiphers
|
||||
from pywidevine.cdm import Cdm as WidevineCdm
|
||||
|
||||
|
||||
@ -26,7 +24,6 @@ class MY5(Service):
|
||||
"""
|
||||
\b
|
||||
Service code for Channel 5's My5 streaming service (https://channel5.com).
|
||||
Credit to @Diazole(https://github.com/Diazole/my5-dl) for solving the hmac.
|
||||
|
||||
\b
|
||||
Author: stabbedbybrick
|
||||
@ -61,9 +58,7 @@ class MY5(Service):
|
||||
self.title = title
|
||||
super().__init__(ctx)
|
||||
|
||||
self.gist = self.session.get(
|
||||
self.config["endpoints"]["gist"].format(timestamp=datetime.now().timestamp())
|
||||
).json()
|
||||
self.session.headers.update({"user-agent": self.config["user_agent"]})
|
||||
|
||||
def search(self) -> Generator[SearchResult, None, None]:
|
||||
params = {
|
||||
@ -173,32 +168,30 @@ class MY5(Service):
|
||||
|
||||
# Service specific functions
|
||||
|
||||
def decrypt_data(self, media: str) -> dict:
|
||||
key = base64.b64decode(self.gist["key"])
|
||||
|
||||
r = self.session.get(media)
|
||||
if not r.ok:
|
||||
raise ConnectionError(r.json().get("message"))
|
||||
|
||||
content = r.json()
|
||||
|
||||
iv = base64.urlsafe_b64decode(content["iv"])
|
||||
data = base64.urlsafe_b64decode(content["data"])
|
||||
|
||||
cipher = AES.new(key=key, iv=iv, mode=AES.MODE_CBC)
|
||||
decrypted_data = unpad(cipher.decrypt(data), AES.block_size)
|
||||
return json.loads(decrypted_data)
|
||||
|
||||
def get_playlist(self, asset_id: str) -> tuple:
|
||||
secret = self.gist["hmac"]
|
||||
session = self.session
|
||||
for prefix in ("https://", "http://"):
|
||||
session.mount(prefix, SSLCiphers())
|
||||
|
||||
timestamp = datetime.now().timestamp()
|
||||
vod = self.config["endpoints"]["vod"].format(id=asset_id, timestamp=f"{timestamp}")
|
||||
sig = hmac.new(base64.b64decode(secret), vod.encode(), hashlib.sha256)
|
||||
auth = base64.urlsafe_b64encode(sig.digest()).decode()
|
||||
vod += f"&auth={auth}"
|
||||
cert_binary = base64.b64decode(self.config["certificate"])
|
||||
with tempfile.NamedTemporaryFile(delete=False, suffix=".pem") as cert_file:
|
||||
cert_file.write(cert_binary)
|
||||
cert_path = cert_file.name
|
||||
try:
|
||||
r = session.get(url=self.config["endpoints"]["auth"].format(title_id=asset_id), cert=cert_path)
|
||||
except requests.RequestException as e:
|
||||
if "Max retries exceeded" in str(e):
|
||||
raise ConnectionError(
|
||||
"Permission denied. If you're behind a VPN/proxy, you might be blocked"
|
||||
)
|
||||
else:
|
||||
raise ConnectionError(f"Failed to request assets: {str(e)}")
|
||||
finally:
|
||||
os.remove(cert_path)
|
||||
|
||||
data = self.decrypt_data(vod)
|
||||
data = r.json()
|
||||
if not data.get("assets"):
|
||||
raise ValueError(f"Could not find asset: {data}")
|
||||
|
||||
asset = [x for x in data["assets"] if x["drm"] == "widevine"][0]
|
||||
rendition = asset["renditions"][0]
|
||||
|
@ -1,8 +1,38 @@
|
||||
user_agent: Dalvik/2.1.0 (Linux; U; Android 14; SM-S901B Build/UP1A.231005.007)
|
||||
|
||||
endpoints:
|
||||
base: https://corona.channel5.com
|
||||
gist: https://gist.githubusercontent.com/stabbedbybrick/8726c719721eac50a28f7bc3c94f18e9/raw/s.txt?={timestamp}
|
||||
content: https://corona.channel5.com/shows/{show}.json?platform=my5desktop
|
||||
episodes: https://corona.channel5.com/shows/{show}/episodes.json?platform=my5desktop
|
||||
single: https://corona.channel5.com/shows/{show}/seasons/{season}/episodes/{episode}.json?platform=my5desktop
|
||||
vod: https://cassie.channel5.com/api/v2/media/my5desktopng/{id}.json?timestamp={timestamp}
|
||||
content: https://corona.channel5.com/shows/{show}.json?platform=my5android
|
||||
episodes: https://corona.channel5.com/shows/{show}/episodes.json?platform=my5android
|
||||
single: https://corona.channel5.com/shows/{show}/seasons/{season}/episodes/{episode}.json?platform=my5android
|
||||
auth: https://cassie-auth.channel5.com/api/v2/media/my5androidhydradash/{title_id}.json
|
||||
search: https://corona.channel5.com/shows/search.json
|
||||
|
||||
certificate: |
|
||||
LS0tLS1CRUdJTiBDRVJUSUZJQ0FURS0tLS0tDQpNSUlDdXpDQ0FpU2dBd0lCQWdJRVhMU1BGVEFOQmdrcWhraUc5dzBCQVFVRkFE
|
||||
QmxNUXN3Q1FZRFZRUUdFd0pIDQpRakVWTUJNR0ExVUVCd3dNUkdWbVlYVnNkQ0JEYVhSNU1SSXdFQVlEVlFRS0RBbERhR0Z1Ym1W
|
||||
c0lEVXhEekFODQpCZ05WQkFzTUJrTmhjM05wWlRFYU1CZ0dBMVVFQXd3UlEyRnpjMmxsSUUxbFpHbGhJRUYxZEdnd0hoY05NVGt3
|
||||
DQpOREUxTVRRd016QXhXaGNOTWprd05ERTFNVFF3TXpBeFdqQ0JqakVMTUFrR0ExVUVCaE1DUjBJeEVqQVFCZ05WDQpCQW9NQ1VO
|
||||
b1lXNXVaV3dnTlRFWE1CVUdBMVVFQ3d3T1EyRnpjMmxsSUdOc2FXVnVkSE14VWpCUUJnTlZCQU1NDQpTVU5oYzNOcFpTQlRaV3ht
|
||||
TFhOcFoyNWxaQ0JEWlhKMGFXWnBZMkYwWlNCbWIzSWdUWGsxSUVGdVpISnZhV1FnDQpUbVY0ZENCSFpXNGdZMnhwWlc1MElERTFO
|
||||
VFV6TXpZNU9ERXdnWjh3RFFZSktvWklodmNOQVFFQkJRQURnWTBBDQpNSUdKQW9HQkFNbVVTSHFCZ3pwbThXelVHZ2VDSWZvSTI3
|
||||
QlovQmNmWktpbnl5dXFNVlpDNXRLaUtaRWpydFV4DQpoMXFVcDJSSkN3Ui9RcENPQ2RQdFhzMENzekZvd1ByTlY4RHFtUXZqbzY5
|
||||
dlhvTEM3c2RLUjQ1cEFUQU8vY3JLDQorTUFPUXo1VWEyQ1ZrYnY1SCtaMVhWWndqbm1qNGJHZEJHM005b0NzQlVqTEh0bm1nQSty
|
||||
QWdNQkFBR2pUakJNDQpNQjBHQTFVZERnUVdCQlNVVUhrY3JKNUVkVTVWM2ZJbXQra1ljdkdnZFRBTEJnTlZIUThFQkFNQ0E3Z3dD
|
||||
UVlEDQpWUjBUQkFJd0FEQVRCZ05WSFNVRUREQUtCZ2dyQmdFRkJRY0RBakFOQmdrcWhraUc5dzBCQVFVRkFBT0JnUUFpDQpHNi84
|
||||
OUFEaDhEOUs0OXZjeklMQ2pqbGh6bG5US09GM2l1Um0vSjZYaWtxY3RxSDF0a01na0FXcHAwQldBRm9IDQpJbU5WSEtKdTRnZXgy
|
||||
cEtLejNqOVlRNG5EWENQVTdVb0N2aDl5TTNYT0RITWZRT01sZkRtMU9GZkh2QkJvSHNVDQpHSE9EQTkwQi8xcU0xSlFaZzBOVjZi
|
||||
UllrUytCOWdtSFI4dXhtZktrL0E9PQ0KLS0tLS1FTkQgQ0VSVElGSUNBVEUtLS0tLQ0KLS0tLS1CRUdJTiBQUklWQVRFIEtFWS0t
|
||||
LS0tDQpNSUlDZHdJQkFEQU5CZ2txaGtpRzl3MEJBUUVGQUFTQ0FtRXdnZ0pkQWdFQUFvR0JBTW1VU0hxQmd6cG04V3pVDQpHZ2VD
|
||||
SWZvSTI3QlovQmNmWktpbnl5dXFNVlpDNXRLaUtaRWpydFV4aDFxVXAyUkpDd1IvUXBDT0NkUHRYczBDDQpzekZvd1ByTlY4RHFt
|
||||
UXZqbzY5dlhvTEM3c2RLUjQ1cEFUQU8vY3JLK01BT1F6NVVhMkNWa2J2NUgrWjFYVlp3DQpqbm1qNGJHZEJHM005b0NzQlVqTEh0
|
||||
bm1nQStyQWdNQkFBRUNnWUFjTVY4SnN6OTFWWnlDaWcreDZTTnpZdlhHDQo3bTd4bFBSeEdqYXlQclZ6eVJ1YmJnNitPKzFoNS9G
|
||||
MFc4SWxwb21oOFdLUDhTMnl0RXBFQmhLbDRHN001WXdqDQp0SCtCVXFNMTNjbFdiQkxuQTZMT2RVeEVDTVhIUktjdHk5UE52UlJQ
|
||||
cU9aV0YycDc5U1BFdFY5Q2o1SXNaVUdNDQpRcHYybk5oN1M2MUZGRVRuSVFKQkFPTXJNd2tnOGQzbksyS0lnVUNrcEtCRHlGTUJj
|
||||
UXN0NG82VkxvVjNjenBwDQpxMW5FWGx4WnduMFh6Ni9GVjRWdTZYTjJLLzQxL2pCeWdTUlFXa05YVThNQ1FRRGpLYXVpdE1UajBM
|
||||
ajU3QkJ3DQppNkNON0VFeUJSSkZaVGRSMDM4ZzkxSEFoUkVXVWpuQ0Vrc1UwcTl4TUNOdnM3OFN4RmQ1ODg5RUJQTnd1RDdvDQor
|
||||
NTM1QWtFQTNwVTNYbHh2WUhQZktKNkR0cWtidlFSdFJoZUZnZVNsdGZzcUtCQVFVVTIwWFRKeEdwL0FWdjE3DQp1OGZxcDQwekpM
|
||||
VEhDa0F4SFpzME9qYVpHcDU0TFFKQWJtM01iUjA1ZFpINnlpdlMxaE5hYW9QR01iMjdZeGJRDQpMS3dHNmd5d3BrbEp4RE1XdHR4
|
||||
VHVYeXVJdlVHMVA5cFRJTThEeUhSeVR3cTU4bjVjeU1XYVFKQkFMVFRwZkVtDQoxdWhCeUd0NEtab3dYM2dhREpVZGU0ZjBwN3Ry
|
||||
RFZGcExDNVJYcVVBQXNBQ2pzTHNYaEFadlovUEEwUDBiU2hmDQp4cUFRa2lnYmNKRXdxdjQ9DQotLS0tLUVORCBQUklWQVRFIEtF
|
||||
WS0tLS0t
|
Loading…
Reference in New Issue
Block a user