KekikStream 2.4.2__py3-none-any.whl → 2.4.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- KekikStream/Core/Extractor/ExtractorBase.py +3 -2
- KekikStream/Core/HTMLHelper.py +134 -40
- KekikStream/Core/Plugin/PluginBase.py +3 -2
- KekikStream/Extractors/CloseLoad.py +30 -54
- KekikStream/Extractors/ContentX.py +27 -72
- KekikStream/Extractors/DonilasPlay.py +33 -77
- KekikStream/Extractors/DzenRu.py +10 -24
- KekikStream/Extractors/ExPlay.py +20 -38
- KekikStream/Extractors/Filemoon.py +19 -45
- KekikStream/Extractors/HDMomPlayer.py +24 -56
- KekikStream/Extractors/HDPlayerSystem.py +13 -31
- KekikStream/Extractors/HotStream.py +14 -32
- KekikStream/Extractors/JFVid.py +3 -24
- KekikStream/Extractors/JetTv.py +21 -34
- KekikStream/Extractors/MailRu.py +11 -29
- KekikStream/Extractors/MixPlayHD.py +15 -28
- KekikStream/Extractors/MixTiger.py +17 -40
- KekikStream/Extractors/MolyStream.py +17 -21
- KekikStream/Extractors/Odnoklassniki.py +28 -104
- KekikStream/Extractors/PeaceMakerst.py +18 -45
- KekikStream/Extractors/PixelDrain.py +8 -16
- KekikStream/Extractors/PlayerFilmIzle.py +22 -41
- KekikStream/Extractors/RapidVid.py +21 -35
- KekikStream/Extractors/SetPlay.py +18 -43
- KekikStream/Extractors/SibNet.py +7 -17
- KekikStream/Extractors/Sobreatsesuyp.py +23 -45
- KekikStream/Extractors/TRsTX.py +23 -53
- KekikStream/Extractors/TurboImgz.py +7 -14
- KekikStream/Extractors/VCTPlay.py +10 -28
- KekikStream/Extractors/VidHide.py +10 -31
- KekikStream/Extractors/VidMoly.py +65 -99
- KekikStream/Extractors/VidMoxy.py +16 -27
- KekikStream/Extractors/VidPapi.py +24 -54
- KekikStream/Extractors/VideoSeyred.py +19 -40
- KekikStream/Extractors/Videostr.py +42 -99
- KekikStream/Extractors/Vidoza.py +8 -15
- KekikStream/Extractors/YildizKisaFilm.py +13 -31
- KekikStream/Plugins/BelgeselX.py +63 -69
- KekikStream/Plugins/DiziBox.py +16 -36
- KekikStream/Plugins/DiziMom.py +37 -129
- KekikStream/Plugins/DiziPal.py +71 -164
- KekikStream/Plugins/DiziYou.py +44 -152
- KekikStream/Plugins/Dizilla.py +18 -44
- KekikStream/Plugins/FilmBip.py +10 -24
- KekikStream/Plugins/FilmEkseni.py +12 -32
- KekikStream/Plugins/FilmMakinesi.py +24 -77
- KekikStream/Plugins/FilmModu.py +11 -18
- KekikStream/Plugins/Filmatek.py +13 -39
- KekikStream/Plugins/Full4kizle.py +33 -133
- KekikStream/Plugins/FullHDFilm.py +23 -93
- KekikStream/Plugins/FullHDFilmizlesene.py +10 -29
- KekikStream/Plugins/HDFilmCehennemi.py +27 -66
- KekikStream/Plugins/JetFilmizle.py +19 -20
- KekikStream/Plugins/KultFilmler.py +16 -50
- KekikStream/Plugins/RecTV.py +47 -85
- KekikStream/Plugins/SelcukFlix.py +29 -47
- KekikStream/Plugins/SetFilmIzle.py +28 -84
- KekikStream/Plugins/SezonlukDizi.py +27 -59
- KekikStream/Plugins/Sinefy.py +37 -100
- KekikStream/Plugins/SinemaCX.py +12 -18
- KekikStream/Plugins/Sinezy.py +11 -12
- KekikStream/Plugins/SuperFilmGeldi.py +8 -13
- KekikStream/Plugins/UgurFilm.py +14 -14
- KekikStream/Plugins/Watch32.py +42 -74
- KekikStream/Plugins/YabanciDizi.py +33 -87
- {kekikstream-2.4.2.dist-info → kekikstream-2.4.4.dist-info}/METADATA +1 -1
- kekikstream-2.4.4.dist-info/RECORD +93 -0
- kekikstream-2.4.2.dist-info/RECORD +0 -93
- {kekikstream-2.4.2.dist-info → kekikstream-2.4.4.dist-info}/WHEEL +0 -0
- {kekikstream-2.4.2.dist-info → kekikstream-2.4.4.dist-info}/entry_points.txt +0 -0
- {kekikstream-2.4.2.dist-info → kekikstream-2.4.4.dist-info}/licenses/LICENSE +0 -0
- {kekikstream-2.4.2.dist-info → kekikstream-2.4.4.dist-info}/top_level.txt +0 -0
KekikStream/Extractors/SibNet.py
CHANGED
|
@@ -6,22 +6,12 @@ class SibNet(ExtractorBase):
|
|
|
6
6
|
name = "SibNet"
|
|
7
7
|
main_url = "https://video.sibnet.ru"
|
|
8
8
|
|
|
9
|
-
async def extract(self, url, referer=None) -> ExtractResult:
|
|
10
|
-
|
|
11
|
-
self.httpx.headers.update({"Referer": referer})
|
|
9
|
+
async def extract(self, url: str, referer: str = None) -> ExtractResult:
|
|
10
|
+
self.httpx.headers.update({"Referer": referer or url})
|
|
12
11
|
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
resp = await self.httpx.get(url)
|
|
13
|
+
path = HTMLHelper(resp.text).regex_first(r'player\.src\(\[\{src: "([^\"]+)"')
|
|
14
|
+
if not path:
|
|
15
|
+
raise ValueError(f"SibNet: Video yolu bulunamadı. {url}")
|
|
15
16
|
|
|
16
|
-
|
|
17
|
-
if not m3u_suffix:
|
|
18
|
-
raise ValueError("m3u bağlantısı bulunamadı.")
|
|
19
|
-
|
|
20
|
-
m3u_link = f"{self.main_url}{m3u_suffix}"
|
|
21
|
-
|
|
22
|
-
return ExtractResult(
|
|
23
|
-
name = self.name,
|
|
24
|
-
url = m3u_link,
|
|
25
|
-
referer = url,
|
|
26
|
-
subtitles = []
|
|
27
|
-
)
|
|
17
|
+
return ExtractResult(name=self.name, url=f"{self.main_url}{path}", referer=url)
|
|
@@ -7,53 +7,31 @@ class Sobreatsesuyp(ExtractorBase):
|
|
|
7
7
|
name = "Sobreatsesuyp"
|
|
8
8
|
main_url = "https://sobreatsesuyp.com"
|
|
9
9
|
|
|
10
|
-
async def extract(self, url, referer=None) -> ExtractResult:
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
async def extract(self, url: str, referer: str = None) -> list[ExtractResult] | ExtractResult:
|
|
11
|
+
ref = referer or self.main_url
|
|
12
|
+
self.httpx.headers.update({"Referer": ref})
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
resp = await self.httpx.get(url)
|
|
15
|
+
path = HTMLHelper(resp.text).regex_first(r'file":"([^\"]+)')
|
|
16
|
+
if not path:
|
|
17
|
+
raise ValueError(f"Sobreatsesuyp: File path bulunamadı. {url}")
|
|
16
18
|
|
|
17
|
-
|
|
18
|
-
if
|
|
19
|
-
raise ValueError("File not found in response.")
|
|
19
|
+
post_resp = await self.httpx.post(f"{self.main_url}/{path.replace('\\', '')}")
|
|
20
|
+
data_list = post_resp.json()[1:] if isinstance(post_resp.json(), list) else []
|
|
20
21
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
post_istek = await self.httpx.post(post_link)
|
|
25
|
-
post_istek.raise_for_status()
|
|
26
|
-
|
|
27
|
-
try:
|
|
28
|
-
post_json = json.loads(post_istek.text)
|
|
29
|
-
except json.JSONDecodeError as hata:
|
|
30
|
-
raise ValueError("Failed to parse JSON response.") from hata
|
|
31
|
-
|
|
32
|
-
video_data_list = post_json[1:] if isinstance(post_json, list) else []
|
|
33
|
-
|
|
34
|
-
all_results = []
|
|
35
|
-
|
|
36
|
-
for item in video_data_list:
|
|
22
|
+
results = []
|
|
23
|
+
for item in data_list:
|
|
37
24
|
title = item.get("title")
|
|
38
25
|
file = item.get("file")
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
referer = self.main_url,
|
|
52
|
-
subtitles = []
|
|
53
|
-
)
|
|
54
|
-
)
|
|
55
|
-
|
|
56
|
-
if not all_results:
|
|
57
|
-
raise ValueError("No videos found in response.")
|
|
58
|
-
|
|
59
|
-
return all_results[0] if len(all_results) == 1 else all_results
|
|
26
|
+
if title and file:
|
|
27
|
+
playlist_resp = await self.httpx.post(f"{self.main_url}/playlist/{file.lstrip('/')}.txt")
|
|
28
|
+
results.append(ExtractResult(
|
|
29
|
+
name = f"{self.name} - {title}",
|
|
30
|
+
url = playlist_resp.text,
|
|
31
|
+
referer = self.main_url
|
|
32
|
+
))
|
|
33
|
+
|
|
34
|
+
if not results:
|
|
35
|
+
raise ValueError(f"Sobreatsesuyp: Video bulunamadı. {url}")
|
|
36
|
+
|
|
37
|
+
return results[0] if len(results) == 1 else results
|
KekikStream/Extractors/TRsTX.py
CHANGED
|
@@ -7,61 +7,31 @@ class TRsTX(ExtractorBase):
|
|
|
7
7
|
name = "TRsTX"
|
|
8
8
|
main_url = "https://trstx.org"
|
|
9
9
|
|
|
10
|
-
async def extract(self, url, referer=None) -> list[ExtractResult]:
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
async def extract(self, url: str, referer: str = None) -> list[ExtractResult] | ExtractResult:
|
|
11
|
+
ref = referer or self.main_url
|
|
12
|
+
self.httpx.headers.update({"Referer": ref})
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
resp = await self.httpx.get(url)
|
|
15
|
+
path = HTMLHelper(resp.text).regex_first(r'file":"([^\"]+)')
|
|
16
|
+
if not path:
|
|
17
|
+
raise ValueError(f"TRsTX: File path bulunamadı. {url}")
|
|
16
18
|
|
|
17
|
-
|
|
18
|
-
if
|
|
19
|
-
raise ValueError("File not found in response.")
|
|
19
|
+
post_resp = await self.httpx.post(f"{self.main_url}/{path.replace('\\', '')}")
|
|
20
|
+
data_list = post_resp.json()[1:] if isinstance(post_resp.json(), list) else []
|
|
20
21
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
post_istek = await self.httpx.post(post_link)
|
|
25
|
-
post_istek.raise_for_status()
|
|
26
|
-
|
|
27
|
-
try:
|
|
28
|
-
post_json = json.loads(post_istek.text)
|
|
29
|
-
except json.JSONDecodeError as hata:
|
|
30
|
-
raise ValueError("Failed to parse JSON response.") from hata
|
|
31
|
-
|
|
32
|
-
video_data_list = post_json[1:] if isinstance(post_json, list) else []
|
|
33
|
-
|
|
34
|
-
video_links = set()
|
|
35
|
-
all_results = []
|
|
36
|
-
|
|
37
|
-
for item in video_data_list:
|
|
22
|
+
results = []
|
|
23
|
+
for item in data_list:
|
|
38
24
|
title = item.get("title")
|
|
39
25
|
file = item.get("file")
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
video_links.add(video_data)
|
|
54
|
-
|
|
55
|
-
all_results.append(
|
|
56
|
-
ExtractResult(
|
|
57
|
-
name = f"{self.name} - {title}",
|
|
58
|
-
url = video_data,
|
|
59
|
-
referer = self.main_url,
|
|
60
|
-
subtitles = []
|
|
61
|
-
)
|
|
62
|
-
)
|
|
63
|
-
|
|
64
|
-
if not all_results:
|
|
65
|
-
raise ValueError("No videos found in response.")
|
|
66
|
-
|
|
67
|
-
return all_results[0] if len(all_results) == 1 else all_results
|
|
26
|
+
if title and file:
|
|
27
|
+
playlist_resp = await self.httpx.post(f"{self.main_url}/playlist/{file.lstrip('/')}.txt")
|
|
28
|
+
results.append(ExtractResult(
|
|
29
|
+
name = f"{self.name} - {title}",
|
|
30
|
+
url = playlist_resp.text,
|
|
31
|
+
referer = self.main_url
|
|
32
|
+
))
|
|
33
|
+
|
|
34
|
+
if not results:
|
|
35
|
+
raise ValueError(f"TRsTX: Video bulunamadı. {url}")
|
|
36
|
+
|
|
37
|
+
return results[0] if len(results) == 1 else results
|
|
@@ -6,19 +6,12 @@ class TurboImgz(ExtractorBase):
|
|
|
6
6
|
name = "TurboImgz"
|
|
7
7
|
main_url = "https://turbo.imgz.me"
|
|
8
8
|
|
|
9
|
-
async def extract(self, url, referer=None) -> ExtractResult:
|
|
10
|
-
|
|
11
|
-
self.httpx.headers.update({"Referer": referer})
|
|
9
|
+
async def extract(self, url: str, referer: str = None) -> ExtractResult:
|
|
10
|
+
self.httpx.headers.update({"Referer": referer or url})
|
|
12
11
|
|
|
13
|
-
|
|
14
|
-
|
|
12
|
+
resp = await self.httpx.get(url)
|
|
13
|
+
v_url = HTMLHelper(resp.text).regex_first(r'file: "(.*)",')
|
|
14
|
+
if not v_url:
|
|
15
|
+
raise ValueError(f"TurboImgz: Video bulunamadı. {url}")
|
|
15
16
|
|
|
16
|
-
|
|
17
|
-
return ExtractResult(
|
|
18
|
-
name = self.name,
|
|
19
|
-
url = video,
|
|
20
|
-
referer = referer or self.main_url,
|
|
21
|
-
subtitles = []
|
|
22
|
-
)
|
|
23
|
-
else:
|
|
24
|
-
raise ValueError("File not found in response.")
|
|
17
|
+
return ExtractResult(name=self.name, url=v_url, referer=referer or self.main_url)
|
|
@@ -7,35 +7,17 @@ class VCTPlay(ExtractorBase):
|
|
|
7
7
|
name = "VCTPlay"
|
|
8
8
|
main_url = "https://vctplay.site"
|
|
9
9
|
|
|
10
|
-
async def extract(self, url, referer=None) -> ExtractResult:
|
|
11
|
-
|
|
12
|
-
|
|
10
|
+
async def extract(self, url: str, referer: str = None) -> ExtractResult:
|
|
11
|
+
v_id = url.split("/")[-1].split("?")[0]
|
|
12
|
+
params = parse_qs(urlparse(url).query)
|
|
13
|
+
part_key = params.get("partKey", [""])[0].lower()
|
|
13
14
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
|
|
17
|
-
if "?" in video_id:
|
|
18
|
-
video_id = video_id.split("?")[0]
|
|
19
|
-
|
|
20
|
-
# Manifests URL oluştur
|
|
21
|
-
master_url = f"{self.main_url}/manifests/{video_id}/master.txt"
|
|
22
|
-
|
|
23
|
-
# partKey'den isim belirle
|
|
24
|
-
parsed = urlparse(url)
|
|
25
|
-
params = parse_qs(parsed.query)
|
|
26
|
-
part_key = params.get("partKey", [""])[0]
|
|
27
|
-
|
|
28
|
-
name_suffix = ""
|
|
29
|
-
if "turkcedublaj" in part_key.lower():
|
|
30
|
-
name_suffix = "Dublaj"
|
|
31
|
-
elif "turkcealtyazi" in part_key.lower():
|
|
32
|
-
name_suffix = "Altyazı"
|
|
33
|
-
|
|
34
|
-
display_name = f"{self.name} - {name_suffix}" if name_suffix else self.name
|
|
15
|
+
suffix = ""
|
|
16
|
+
if "turkcedublaj" in part_key: suffix = "Dublaj"
|
|
17
|
+
elif "turkcealtyazi" in part_key: suffix = "Altyazı"
|
|
35
18
|
|
|
36
19
|
return ExtractResult(
|
|
37
|
-
name
|
|
38
|
-
url
|
|
39
|
-
referer
|
|
40
|
-
subtitles = []
|
|
20
|
+
name = f"{self.name} - {suffix}" if suffix else self.name,
|
|
21
|
+
url = f"{self.main_url}/manifests/{v_id}/master.txt",
|
|
22
|
+
referer = f"{self.main_url}/"
|
|
41
23
|
)
|
|
@@ -25,46 +25,26 @@ class VidHide(ExtractorBase):
|
|
|
25
25
|
return url.replace("/f/", "/v/")
|
|
26
26
|
|
|
27
27
|
async def extract(self, url: str, referer: str = None) -> ExtractResult:
|
|
28
|
-
# Dinamik base URL kullan
|
|
29
28
|
base_url = self.get_base_url(url)
|
|
30
|
-
|
|
31
|
-
if referer:
|
|
32
|
-
self.httpx.headers.update({"Referer": referer})
|
|
33
|
-
|
|
34
29
|
self.httpx.headers.update({
|
|
35
|
-
"
|
|
36
|
-
"
|
|
37
|
-
"Sec-Fetch-Site" : "cross-site",
|
|
38
|
-
"Origin" : base_url,
|
|
30
|
+
"Referer" : referer or base_url,
|
|
31
|
+
"Origin" : base_url,
|
|
39
32
|
})
|
|
40
33
|
|
|
41
34
|
embed_url = self.get_embed_url(url)
|
|
42
35
|
istek = await self.httpx.get(embed_url)
|
|
43
|
-
|
|
36
|
+
sel = HTMLHelper(istek.text)
|
|
44
37
|
|
|
45
|
-
|
|
46
|
-
if "eval(function" in
|
|
38
|
+
unpacked = ""
|
|
39
|
+
if "eval(function" in istek.text:
|
|
47
40
|
try:
|
|
48
|
-
unpacked = Packer.unpack(
|
|
49
|
-
|
|
50
|
-
script = unpacked.split("var links")[1]
|
|
51
|
-
else:
|
|
52
|
-
script = unpacked
|
|
53
|
-
except Exception:
|
|
41
|
+
unpacked = Packer.unpack(istek.text)
|
|
42
|
+
except:
|
|
54
43
|
pass
|
|
55
44
|
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
m3u8_url = None
|
|
60
|
-
if script:
|
|
61
|
-
# m3u8 urls could be prefixed by 'file:', 'hls2:' or 'hls4:', so we just match ':'
|
|
62
|
-
m3u8_url = HTMLHelper(script).regex_first(r':\s*"([^\"]*?m3u8[^\"]*?)"')
|
|
45
|
+
content = unpacked or istek.text
|
|
46
|
+
m3u8_url = HTMLHelper(content).regex_first(r'[:"]\s*["\']([^"\']+\.m3u8[^"\']*)["\']')
|
|
63
47
|
|
|
64
|
-
if not m3u8_url:
|
|
65
|
-
# Fallback direct search in response if unpacking failed or structure changed
|
|
66
|
-
m3u8_url = HTMLHelper(response).regex_first(r'file:"(.*?\.m3u8.*?)"')
|
|
67
|
-
|
|
68
48
|
if not m3u8_url:
|
|
69
49
|
raise ValueError(f"VidHide: Video URL bulunamadı. {url}")
|
|
70
50
|
|
|
@@ -72,6 +52,5 @@ class VidHide(ExtractorBase):
|
|
|
72
52
|
name = self.name,
|
|
73
53
|
url = self.fix_url(m3u8_url),
|
|
74
54
|
referer = f"{base_url}/",
|
|
75
|
-
user_agent = self.httpx.headers.get("User-Agent", "")
|
|
76
|
-
subtitles = []
|
|
55
|
+
user_agent = self.httpx.headers.get("User-Agent", "")
|
|
77
56
|
)
|
|
@@ -9,7 +9,7 @@ class VidMoly(ExtractorBase):
|
|
|
9
9
|
main_url = "https://vidmoly.to"
|
|
10
10
|
|
|
11
11
|
# Birden fazla domain destekle
|
|
12
|
-
supported_domains = ["vidmoly.to", "vidmoly.me", "vidmoly.net"]
|
|
12
|
+
supported_domains = ["vidmoly.to", "vidmoly.me", "vidmoly.net", "vidmoly.biz"]
|
|
13
13
|
|
|
14
14
|
def can_handle_url(self, url: str) -> bool:
|
|
15
15
|
return any(domain in url for domain in self.supported_domains)
|
|
@@ -18,112 +18,78 @@ class VidMoly(ExtractorBase):
|
|
|
18
18
|
if referer:
|
|
19
19
|
self.httpx.headers.update({"Referer": referer})
|
|
20
20
|
|
|
21
|
-
self.httpx.headers.update({
|
|
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
|
-
"answer" : answer_val,
|
|
48
|
-
"ts" : ts_val,
|
|
49
|
-
"nonce" : nonce_val,
|
|
50
|
-
"ctok" : ctok_val
|
|
51
|
-
},
|
|
52
|
-
follow_redirects=True
|
|
53
|
-
)
|
|
54
|
-
|
|
21
|
+
self.httpx.headers.update({"Sec-Fetch-Dest" : "iframe"})
|
|
22
|
+
|
|
23
|
+
# Domain normalleştirme
|
|
24
|
+
url = url.replace(".me", ".net").replace(".to", ".net")
|
|
25
|
+
|
|
26
|
+
resp = await self.httpx.get(url, follow_redirects=True)
|
|
27
|
+
sel = HTMLHelper(resp.text)
|
|
28
|
+
|
|
29
|
+
# "Select number" kontrolü (Bot koruması)
|
|
30
|
+
if "Select number" in resp.text:
|
|
31
|
+
op_val = sel.select_attr("input[name='op']", "value")
|
|
32
|
+
file_code_val = sel.select_attr("input[name='file_code']", "value")
|
|
33
|
+
answer_val = sel.select_text("div.vhint b")
|
|
34
|
+
ts_val = sel.select_attr("input[name='ts']", "value")
|
|
35
|
+
nonce_val = sel.select_attr("input[name='nonce']", "value")
|
|
36
|
+
ctok_val = sel.select_attr("input[name='ctok']", "value")
|
|
37
|
+
|
|
38
|
+
resp = await self.httpx.post(url, data={
|
|
39
|
+
"op" : op_val,
|
|
40
|
+
"file_code" : file_code_val,
|
|
41
|
+
"answer" : answer_val,
|
|
42
|
+
"ts" : ts_val,
|
|
43
|
+
"nonce" : nonce_val,
|
|
44
|
+
"ctok" : ctok_val
|
|
45
|
+
}, follow_redirects=True)
|
|
46
|
+
sel = HTMLHelper(resp.text)
|
|
55
47
|
|
|
56
48
|
# Altyazı kaynaklarını ayrıştır
|
|
57
49
|
subtitles = []
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
subtitle_data = self._add_marks(subtitle_data, "kind")
|
|
50
|
+
if sub_str := sel.regex_first(r"tracks:\s*\[(.*?)\]", flags=re.DOTALL):
|
|
51
|
+
sub_data = self._add_marks(sub_str, "file")
|
|
52
|
+
sub_data = self._add_marks(sub_data, "label")
|
|
53
|
+
sub_data = self._add_marks(sub_data, "kind")
|
|
63
54
|
|
|
64
55
|
with contextlib.suppress(json.JSONDecodeError):
|
|
65
|
-
|
|
56
|
+
sub_sources = json.loads(f"[{sub_data}]")
|
|
66
57
|
subtitles = [
|
|
67
|
-
Subtitle(
|
|
68
|
-
|
|
69
|
-
url = self.fix_url(sub.get("file")),
|
|
70
|
-
)
|
|
71
|
-
for sub in subtitle_sources
|
|
72
|
-
if sub.get("kind") == "captions"
|
|
58
|
+
Subtitle(name=sub.get("label"), url=self.fix_url(sub.get("file")))
|
|
59
|
+
for sub in sub_sources if sub.get("kind") == "captions"
|
|
73
60
|
]
|
|
74
61
|
|
|
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
|
-
if file_match := resp_sec.regex_first(r'file\s*:\s*["\']([^"\']+\.m3u8[^"\']*)["\']'):
|
|
107
|
-
return ExtractResult(
|
|
108
|
-
name = self.name,
|
|
109
|
-
url = file_match,
|
|
110
|
-
referer = self.main_url,
|
|
111
|
-
subtitles = subtitles
|
|
112
|
-
)
|
|
113
|
-
|
|
114
|
-
# Fallback 2: Herhangi bir file (m3u8 olma şartı olmadan ama tercihen)
|
|
115
|
-
if file_match := resp_sec.regex_first(r'file\s*:\s*["\']([^"\']+)["\']'):
|
|
116
|
-
url_candidate = file_match
|
|
117
|
-
# Resim dosyalarını hariç tut
|
|
118
|
-
if not url_candidate.endswith(('.jpg', '.png', '.jpeg')):
|
|
119
|
-
return ExtractResult(
|
|
120
|
-
name = self.name,
|
|
121
|
-
url = url_candidate,
|
|
122
|
-
referer = self.main_url,
|
|
123
|
-
subtitles = subtitles
|
|
124
|
-
)
|
|
125
|
-
|
|
126
|
-
raise ValueError("Video URL bulunamadı.")
|
|
62
|
+
# Video URL Bulma
|
|
63
|
+
video_url = None
|
|
64
|
+
if "#EXTM3U" in resp.text:
|
|
65
|
+
for line in resp.text.splitlines():
|
|
66
|
+
if line.strip().startswith("http"):
|
|
67
|
+
video_url = line.strip().replace('"', '').replace("'", "")
|
|
68
|
+
break
|
|
69
|
+
|
|
70
|
+
if not video_url:
|
|
71
|
+
if src_str := sel.regex_first(r"sources:\s*\[(.*?)\],", flags=re.DOTALL):
|
|
72
|
+
vid_data = self._add_marks(src_str, "file")
|
|
73
|
+
with contextlib.suppress(json.JSONDecodeError):
|
|
74
|
+
vid_sources = json.loads(f"[{vid_data}]")
|
|
75
|
+
for source in vid_sources:
|
|
76
|
+
if source.get("file"):
|
|
77
|
+
video_url = source.get("file")
|
|
78
|
+
break
|
|
79
|
+
|
|
80
|
+
if not video_url:
|
|
81
|
+
video_url = sel.regex_first(r'file\s*:\s*["\']([^"\']+\.m3u8[^"\']*)["\']') or \
|
|
82
|
+
sel.regex_first(r'file\s*:\s*["\']([^"\']+\.mp4[^"\']*)["\']')
|
|
83
|
+
|
|
84
|
+
if not video_url:
|
|
85
|
+
raise ValueError(f"VidMoly: Video URL bulunamadı. {url}")
|
|
86
|
+
|
|
87
|
+
return ExtractResult(
|
|
88
|
+
name = self.name,
|
|
89
|
+
url = video_url,
|
|
90
|
+
referer = f"{self.get_base_url(url)}/",
|
|
91
|
+
subtitles = subtitles
|
|
92
|
+
)
|
|
127
93
|
|
|
128
94
|
def _add_marks(self, text: str, field: str) -> str:
|
|
129
95
|
"""
|
|
@@ -7,42 +7,31 @@ class VidMoxy(ExtractorBase):
|
|
|
7
7
|
name = "VidMoxy"
|
|
8
8
|
main_url = "https://vidmoxy.com"
|
|
9
9
|
|
|
10
|
-
async def extract(self, url, referer=None) -> ExtractResult:
|
|
10
|
+
async def extract(self, url: str, referer: str = None) -> ExtractResult:
|
|
11
11
|
if referer:
|
|
12
12
|
self.httpx.headers.update({"Referer": referer})
|
|
13
13
|
|
|
14
|
-
|
|
15
|
-
|
|
14
|
+
resp = await self.httpx.get(url)
|
|
15
|
+
sel = HTMLHelper(resp.text)
|
|
16
16
|
|
|
17
|
-
subtitles
|
|
18
|
-
|
|
19
|
-
|
|
17
|
+
subtitles = []
|
|
18
|
+
for s_url, s_lang in sel.regex_all(r'captions","file":"([^\"]+)","label":"([^\"]+)"'):
|
|
19
|
+
decoded_lang = s_lang.encode().decode('unicode_escape')
|
|
20
|
+
subtitles.append(Subtitle(name=decoded_lang, url=s_url.replace("\\", "")))
|
|
20
21
|
|
|
21
|
-
|
|
22
|
-
|
|
23
|
-
|
|
22
|
+
hex_data = sel.regex_first(r'file": "(.*)",')
|
|
23
|
+
if not hex_data:
|
|
24
|
+
eval_data = sel.regex_first(r'\};\s*(eval\(function[\s\S]*?)var played = \d+;')
|
|
25
|
+
if eval_data:
|
|
26
|
+
unpacked = Packer.unpack(Packer.unpack(eval_data))
|
|
27
|
+
hex_data = HTMLHelper(unpacked).regex_first(r'file":"(.*)","label')
|
|
24
28
|
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
sub_lang.replace("\\u0131", "ı")
|
|
28
|
-
.replace("\\u0130", "İ")
|
|
29
|
-
.replace("\\u00fc", "ü")
|
|
30
|
-
.replace("\\u00e7", "ç")
|
|
31
|
-
)
|
|
32
|
-
subtitles.append(Subtitle(name=decoded_lang, url=sub_url.replace("\\", "")))
|
|
33
|
-
|
|
34
|
-
escaped_hex = HTMLHelper(istek.text).regex_first(r'file": "(.*)",')
|
|
35
|
-
if not escaped_hex:
|
|
36
|
-
eval_jwsetup = HTMLHelper(istek.text).regex_first(r'\};\s*(eval\(function[\s\S]*?)var played = \d+;')
|
|
37
|
-
jwsetup = Packer.unpack(Packer.unpack(eval_jwsetup)) if eval_jwsetup else None
|
|
38
|
-
if jwsetup:
|
|
39
|
-
escaped_hex = HTMLHelper(jwsetup).regex_first(r'file":"(.*)","label')
|
|
40
|
-
|
|
41
|
-
m3u_link = HexCodec.decode(escaped_hex)
|
|
29
|
+
if not hex_data:
|
|
30
|
+
raise ValueError(f"VidMoxy: Hex data bulunamadı. {url}")
|
|
42
31
|
|
|
43
32
|
return ExtractResult(
|
|
44
33
|
name = self.name,
|
|
45
|
-
url =
|
|
34
|
+
url = HexCodec.decode(hex_data),
|
|
46
35
|
referer = self.main_url,
|
|
47
36
|
subtitles = subtitles
|
|
48
37
|
)
|