-
Notifications
You must be signed in to change notification settings - Fork 1
/
Copy pathserver.py
140 lines (102 loc) · 4.18 KB
/
server.py
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65
66
67
68
69
70
71
72
73
74
75
76
77
78
79
80
81
82
83
84
85
86
87
88
89
90
91
92
93
94
95
96
97
98
99
100
101
102
103
104
105
106
107
108
109
110
111
112
113
114
115
116
117
118
119
120
121
122
123
124
125
126
127
128
129
130
131
132
133
134
135
136
137
138
139
140
import os
import re
import json
import urllib.request
from urllib.error import URLError, HTTPError
from urllib.parse import unquote
from flask import Flask, request, render_template
from bs4 import BeautifulSoup
from waitress import serve
URL_REGEX = r"^https:\/\/(www|m).cda.pl\/video\/([^\/\s]+)"
HTTP_PROXY = os.environ.get("HTTP_PROXY")
# Init app
app = Flask(__name__, template_folder="")
app.config["SECRET_KEY"] = "#UqoQWUPB&n{:xo"
app.config["DEBUG"] = True
class FileDeletedError(Exception):
"""When video file has been deleted by the copyright owner or Administrator"""
pass
class QualityError(Exception):
"""When selected by user quality does not exist"""
pass
class PremiumOnlyError(Exception):
"""When video is only available for users with CDA Premium"""
pass
def decrypt_file(a: str):
words = ["_XDDD", "_CDA", "_ADC", "_CXD", "_QWE", "_Q5", "_IKSDE"]
# first replace very cringy joke and other bad obfuscation
for i in words:
a = a.replace(i, "")
# then apply decodeURIComponent using urllib.parse
a = unquote(a)
# store decrypted characters
b = []
for e in range(len(a)):
f = ord(a[e])
b.append(chr(33 + (f + 14) % 94) if 33 <= f and 126 >= f else chr(f))
# decrypted URL
a = "".join(b)
# more "obfuscation" to deal with
a = a.replace(".cda.mp4", "")
a = a.replace(".2cda.pl", ".cda.pl")
a = a.replace(".3cda.pl", ".cda.pl")
# return extracted file as URL to video file
return "https://" + a + ".mp4"
def extract_video(video_id: str, quality: str = None):
url = "https://www.cda.pl/video/" + video_id + ("?wersja=" + quality if quality else "")
# Trying to avoid as much trouble as possbile by "mocking" a real browser request
request = urllib.request.Request(url, headers={
"Referer": "http://www.cda.pl",
"User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:73.0) Gecko/20100101 Firefox/73.0"
})
# Set proxy to avoid crappy CDNs
if HTTP_PROXY:
request.set_proxy(HTTP_PROXY, "http")
try:
response = urllib.request.urlopen(request).read()
except HTTPError as e:
response = e.read()
except URLError as e:
raise e
# Parse HTML using BeautifulSoup4
bs4 = BeautifulSoup(response, "html.parser")
body = bs4.find("body")
for tag in body.find_all(text=True):
if tag.string == "Ten film jest dostępny dla użytkowników premium":
raise PremiumOnlyError()
elif tag.string == "Materiał został usunięty!":
raise FileDeletedError()
# Parse list of available video quality
quality_list = [tag.string for tag in body.find_all("a", {"class": "quality-btn"})]
if quality and quality not in quality_list:
raise QualityError()
title = body.find("span", {"class": "title-name"}).get_text()
player_data = json.loads(body.find("div", {"player_data": True})["player_data"])
return {
"title": title,
"src": decrypt_file(player_data["video"]["file"])
}
@app.route("/", methods=["GET", "POST"])
def index():
if request.method == "POST":
url = request.values.get("url")
quality = request.values.get("quality")
if not url.startswith("https://www.cda.pl/video/"):
render_template("index.html", error="Invalid link given.")
# Grab video id from cda.pl url
video_id = re.match(URL_REGEX, url)[2]
try:
video = extract_video(video_id, quality)
except QualityError:
video = extract_video(video_id)
except PremiumOnlyError:
return render_template("index.html", error="This video is only available for premium users with CDA Premium!")
except FileDeletedError:
return render_template("index.html", error="This video has been deleted by the copyright owner or Administrator!")
except URLError as e:
return render_template("index.html", error=e.reason)
return render_template("index.html", video=video)
else:
return render_template("index.html")
if __name__ == "__main__":
serve(app, host=os.environ.get("HOST", "127.0.0.1"), port=int(os.environ.get("PORT", "5000")))