KekikStream 2.5.7__py3-none-any.whl → 2.5.9__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.
Potentially problematic release.
This version of KekikStream might be problematic. Click here for more details.
- KekikStream/CLI/__pycache__/pypi_kontrol.cpython-314.pyc +0 -0
- KekikStream/Core/Extractor/__pycache__/ExtractorBase.cpython-314.pyc +0 -0
- KekikStream/Core/Extractor/__pycache__/ExtractorLoader.cpython-314.pyc +0 -0
- KekikStream/Core/Extractor/__pycache__/ExtractorManager.cpython-314.pyc +0 -0
- KekikStream/Core/Extractor/__pycache__/ExtractorModels.cpython-314.pyc +0 -0
- KekikStream/Core/Extractor/__pycache__/YTDLPCache.cpython-314.pyc +0 -0
- KekikStream/Core/Media/__pycache__/MediaHandler.cpython-314.pyc +0 -0
- KekikStream/Core/Media/__pycache__/MediaManager.cpython-314.pyc +0 -0
- KekikStream/Core/Plugin/__pycache__/PluginBase.cpython-314.pyc +0 -0
- KekikStream/Core/Plugin/__pycache__/PluginLoader.cpython-314.pyc +0 -0
- KekikStream/Core/Plugin/__pycache__/PluginManager.cpython-314.pyc +0 -0
- KekikStream/Core/Plugin/__pycache__/PluginModels.cpython-314.pyc +0 -0
- KekikStream/Core/UI/__pycache__/UIManager.cpython-314.pyc +0 -0
- KekikStream/Core/__pycache__/HTMLHelper.cpython-314.pyc +0 -0
- KekikStream/Core/__pycache__/__init__.cpython-314.pyc +0 -0
- KekikStream/Extractors/HotStream.py +7 -2
- KekikStream/Extractors/StreamWish.py +80 -0
- KekikStream/Extractors/VidHide.py +46 -44
- KekikStream/Extractors/VidStack.py +88 -0
- KekikStream/Extractors/__pycache__/Abstream.cpython-314.pyc +0 -0
- KekikStream/Extractors/__pycache__/CloseLoad.cpython-314.pyc +0 -0
- KekikStream/Extractors/__pycache__/ContentX.cpython-314.pyc +0 -0
- KekikStream/Extractors/__pycache__/DonilasPlay.cpython-314.pyc +0 -0
- KekikStream/Extractors/__pycache__/DzenRu.cpython-314.pyc +0 -0
- KekikStream/Extractors/__pycache__/ExPlay.cpython-314.pyc +0 -0
- KekikStream/Extractors/__pycache__/Filemoon.cpython-314.pyc +0 -0
- KekikStream/Extractors/__pycache__/HDMomPlayer.cpython-314.pyc +0 -0
- KekikStream/Extractors/__pycache__/HDPlayerSystem.cpython-314.pyc +0 -0
- KekikStream/Extractors/__pycache__/HotStream.cpython-314.pyc +0 -0
- KekikStream/Extractors/__pycache__/JFVid.cpython-314.pyc +0 -0
- KekikStream/Extractors/__pycache__/JetTv.cpython-314.pyc +0 -0
- KekikStream/Extractors/__pycache__/JetV.cpython-314.pyc +0 -0
- KekikStream/Extractors/__pycache__/LuciferPlays.cpython-314.pyc +0 -0
- KekikStream/Extractors/__pycache__/MailRu.cpython-314.pyc +0 -0
- KekikStream/Extractors/__pycache__/MixPlayHD.cpython-314.pyc +0 -0
- KekikStream/Extractors/__pycache__/MixTiger.cpython-314.pyc +0 -0
- KekikStream/Extractors/__pycache__/MolyStream.cpython-314.pyc +0 -0
- KekikStream/Extractors/__pycache__/Odnoklassniki.cpython-314.pyc +0 -0
- KekikStream/Extractors/__pycache__/PeaceMakerst.cpython-314.pyc +0 -0
- KekikStream/Extractors/__pycache__/PixelDrain.cpython-314.pyc +0 -0
- KekikStream/Extractors/__pycache__/PlayerFilmIzle.cpython-314.pyc +0 -0
- KekikStream/Extractors/__pycache__/RapidVid.cpython-314.pyc +0 -0
- KekikStream/Extractors/__pycache__/SetPlay.cpython-314.pyc +0 -0
- KekikStream/Extractors/__pycache__/SetPrime.cpython-314.pyc +0 -0
- KekikStream/Extractors/__pycache__/SibNet.cpython-314.pyc +0 -0
- KekikStream/Extractors/__pycache__/Sobreatsesuyp.cpython-314.pyc +0 -0
- KekikStream/Extractors/__pycache__/StreamWish.cpython-314.pyc +0 -0
- KekikStream/Extractors/__pycache__/TRsTX.cpython-314.pyc +0 -0
- KekikStream/Extractors/__pycache__/TauVideo.cpython-314.pyc +0 -0
- KekikStream/Extractors/__pycache__/TurboImgz.cpython-314.pyc +0 -0
- KekikStream/Extractors/__pycache__/TurkeyPlayer.cpython-314.pyc +0 -0
- KekikStream/Extractors/__pycache__/VCTPlay.cpython-314.pyc +0 -0
- KekikStream/Extractors/__pycache__/Veev.cpython-314.pyc +0 -0
- KekikStream/Extractors/__pycache__/VidBiz.cpython-314.pyc +0 -0
- KekikStream/Extractors/__pycache__/VidHide.cpython-314.pyc +0 -0
- KekikStream/Extractors/__pycache__/VidMoly.cpython-314.pyc +0 -0
- KekikStream/Extractors/__pycache__/VidMoxy.cpython-314.pyc +0 -0
- KekikStream/Extractors/__pycache__/VidPapi.cpython-314.pyc +0 -0
- KekikStream/Extractors/__pycache__/VidStack.cpython-314.pyc +0 -0
- KekikStream/Extractors/__pycache__/VideoSeyred.cpython-314.pyc +0 -0
- KekikStream/Extractors/__pycache__/Videostr.cpython-314.pyc +0 -0
- KekikStream/Extractors/__pycache__/Vidoza.cpython-314.pyc +0 -0
- KekikStream/Extractors/__pycache__/Vtbe.cpython-314.pyc +0 -0
- KekikStream/Extractors/__pycache__/YTDLP.cpython-314.pyc +0 -0
- KekikStream/Extractors/__pycache__/YildizKisaFilm.cpython-314.pyc +0 -0
- KekikStream/Extractors/__pycache__/Zeus.cpython-314.pyc +0 -0
- KekikStream/Plugins/DDizi.py +176 -0
- KekikStream/Plugins/RealFilmIzle.py +94 -0
- KekikStream/Plugins/ShowFlix.py +211 -0
- KekikStream/Plugins/__pycache__/BelgeselX.cpython-314.pyc +0 -0
- KekikStream/Plugins/__pycache__/DDizi.cpython-314.pyc +0 -0
- KekikStream/Plugins/__pycache__/DiziBox.cpython-314.pyc +0 -0
- KekikStream/Plugins/__pycache__/DiziMom.cpython-314.pyc +0 -0
- KekikStream/Plugins/__pycache__/DiziPal.cpython-314.pyc +0 -0
- KekikStream/Plugins/__pycache__/DiziYou.cpython-314.pyc +0 -0
- KekikStream/Plugins/__pycache__/Dizilla.cpython-314.pyc +0 -0
- KekikStream/Plugins/__pycache__/FilmBip.cpython-314.pyc +0 -0
- KekikStream/Plugins/__pycache__/FilmEkseni.cpython-314.pyc +0 -0
- KekikStream/Plugins/__pycache__/FilmMakinesi.cpython-314.pyc +0 -0
- KekikStream/Plugins/__pycache__/FilmModu.cpython-314.pyc +0 -0
- KekikStream/Plugins/__pycache__/Filmatek.cpython-314.pyc +0 -0
- KekikStream/Plugins/__pycache__/FilmciBaba.cpython-314.pyc +0 -0
- KekikStream/Plugins/__pycache__/FullHDFilmizlesene.cpython-314.pyc +0 -0
- KekikStream/Plugins/__pycache__/HDFilm.cpython-314.pyc +0 -0
- KekikStream/Plugins/__pycache__/HDFilmCehennemi.cpython-314.pyc +0 -0
- KekikStream/Plugins/__pycache__/JetFilmizle.cpython-314.pyc +0 -0
- KekikStream/Plugins/__pycache__/KultFilmler.cpython-314.pyc +0 -0
- KekikStream/Plugins/__pycache__/RealFilmIzle.cpython-314.pyc +0 -0
- KekikStream/Plugins/__pycache__/RecTV.cpython-314.pyc +0 -0
- KekikStream/Plugins/__pycache__/RoketDizi.cpython-314.pyc +0 -0
- KekikStream/Plugins/__pycache__/SelcukFlix.cpython-314.pyc +0 -0
- KekikStream/Plugins/__pycache__/SetFilmIzle.cpython-314.pyc +0 -0
- KekikStream/Plugins/__pycache__/SezonlukDizi.cpython-314.pyc +0 -0
- KekikStream/Plugins/__pycache__/ShowFlix.cpython-314.pyc +0 -0
- KekikStream/Plugins/__pycache__/SineWix.cpython-314.pyc +0 -0
- KekikStream/Plugins/__pycache__/Sinefy.cpython-314.pyc +0 -0
- KekikStream/Plugins/__pycache__/SinemaCX.cpython-314.pyc +0 -0
- KekikStream/Plugins/__pycache__/Sinezy.cpython-314.pyc +0 -0
- KekikStream/Plugins/__pycache__/SuperFilmIzle.cpython-314.pyc +0 -0
- KekikStream/Plugins/__pycache__/UgurFilm.cpython-314.pyc +0 -0
- KekikStream/Plugins/__pycache__/Watch32.cpython-314.pyc +0 -0
- KekikStream/Plugins/__pycache__/YabanciDizi.cpython-314.pyc +0 -0
- {kekikstream-2.5.7.dist-info → kekikstream-2.5.9.dist-info}/METADATA +1 -1
- kekikstream-2.5.9.dist-info/RECORD +200 -0
- kekikstream-2.5.7.dist-info/RECORD +0 -100
- {kekikstream-2.5.7.dist-info → kekikstream-2.5.9.dist-info}/WHEEL +0 -0
- {kekikstream-2.5.7.dist-info → kekikstream-2.5.9.dist-info}/entry_points.txt +0 -0
- {kekikstream-2.5.7.dist-info → kekikstream-2.5.9.dist-info}/licenses/LICENSE +0 -0
- {kekikstream-2.5.7.dist-info → kekikstream-2.5.9.dist-info}/top_level.txt +0 -0
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
2
|
|
|
3
3
|
from KekikStream.Core import ExtractorBase, ExtractResult, HTMLHelper
|
|
4
|
-
from Kekik.Sifreleme
|
|
4
|
+
from Kekik.Sifreleme import AESManager
|
|
5
5
|
import contextlib
|
|
6
6
|
|
|
7
7
|
class HotStream(ExtractorBase):
|
|
@@ -24,4 +24,9 @@ class HotStream(ExtractorBase):
|
|
|
24
24
|
if not m3u8_url:
|
|
25
25
|
raise ValueError(f"HotStream: Video linki bulunamadı. {url}")
|
|
26
26
|
|
|
27
|
-
return ExtractResult(
|
|
27
|
+
return ExtractResult(
|
|
28
|
+
name = self.name,
|
|
29
|
+
url = self.fix_url(m3u8_url),
|
|
30
|
+
referer = url,
|
|
31
|
+
user_agent = self.httpx.headers.get("User-Agent")
|
|
32
|
+
)
|
|
@@ -0,0 +1,80 @@
|
|
|
1
|
+
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
|
+
|
|
3
|
+
from KekikStream.Core import ExtractorBase, ExtractResult, HTMLHelper
|
|
4
|
+
from Kekik.Sifreleme import Packer
|
|
5
|
+
from contextlib import suppress
|
|
6
|
+
|
|
7
|
+
class StreamWish(ExtractorBase):
|
|
8
|
+
name = "StreamWish"
|
|
9
|
+
main_url = "https://streamwish.to"
|
|
10
|
+
|
|
11
|
+
supported_domains = [
|
|
12
|
+
"streamwish.to", "streamwish.site", "streamwish.xyz", "streamwish.com",
|
|
13
|
+
"embedwish.com", "mwish.pro", "dwish.pro", "wishembed.pro", "wishembed.com",
|
|
14
|
+
"kswplayer.info", "wishfast.top", "sfastwish.com", "strwish.xyz", "strwish.com",
|
|
15
|
+
"flaswish.com", "awish.pro", "obeywish.com", "jodwish.com", "swhoi.com",
|
|
16
|
+
"multimovies.cloud", "uqloads.xyz", "doodporn.xyz", "cdnwish.com", "asnwish.com",
|
|
17
|
+
"nekowish.my.id", "neko-stream.click", "swdyu.com", "wishonly.site", "playerwish.com",
|
|
18
|
+
"streamhls.to", "hlswish.com"
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
def can_handle_url(self, url: str) -> bool:
|
|
22
|
+
return any(domain in url for domain in self.supported_domains)
|
|
23
|
+
|
|
24
|
+
def resolve_embed_url(self, url: str) -> str:
|
|
25
|
+
# Kotlin: /f/ -> /, /e/ -> /
|
|
26
|
+
if "/f/" in url:
|
|
27
|
+
return url.replace("/f/", "/")
|
|
28
|
+
if "/e/" in url:
|
|
29
|
+
return url.replace("/e/", "/")
|
|
30
|
+
return url
|
|
31
|
+
|
|
32
|
+
async def extract(self, url: str, referer: str = None) -> ExtractResult:
|
|
33
|
+
base_url = self.get_base_url(url)
|
|
34
|
+
embed_url = self.resolve_embed_url(url)
|
|
35
|
+
istek = await self.httpx.get(
|
|
36
|
+
url = embed_url,
|
|
37
|
+
headers = {
|
|
38
|
+
"Accept" : "*/*",
|
|
39
|
+
"Connection" : "keep-alive",
|
|
40
|
+
"Referer" : f"{base_url}/",
|
|
41
|
+
"Origin" : f"{base_url}/",
|
|
42
|
+
"User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36"
|
|
43
|
+
},
|
|
44
|
+
follow_redirects=True
|
|
45
|
+
)
|
|
46
|
+
text = istek.text
|
|
47
|
+
|
|
48
|
+
unpacked = ""
|
|
49
|
+
# Eval script bul
|
|
50
|
+
if eval_match := HTMLHelper(text).regex_first(r'(eval\s*\(\s*function[\s\S]+?)<\/script>'):
|
|
51
|
+
with suppress(Exception):
|
|
52
|
+
unpacked = Packer.unpack(eval_match)
|
|
53
|
+
|
|
54
|
+
content = unpacked or text
|
|
55
|
+
sel = HTMLHelper(content)
|
|
56
|
+
|
|
57
|
+
# Regex: file:\s*"(.*?m3u8.*?)"
|
|
58
|
+
m3u8_url = sel.regex_first(r'file:\s*["\']([^"\']+\.m3u8[^"\']*)["\']')
|
|
59
|
+
|
|
60
|
+
if not m3u8_url:
|
|
61
|
+
# Fallback to sources: Kotlin mantığı
|
|
62
|
+
m3u8_url = sel.regex_first(r'sources:\s*\[\s*{\s*file:\s*["\']([^"\']+)["\']')
|
|
63
|
+
|
|
64
|
+
if not m3u8_url:
|
|
65
|
+
# p,a,c,k,e,d içinde olabilir
|
|
66
|
+
m3u8_url = sel.regex_first(r'["\'](https?://[^"\']+\.m3u8[^"\']*)["\']')
|
|
67
|
+
|
|
68
|
+
if not m3u8_url:
|
|
69
|
+
# t.r.u.e pattern fallback
|
|
70
|
+
m3u8_url = sel.regex_first(r'file\s*:\s*["\']([^"\']+)["\']')
|
|
71
|
+
|
|
72
|
+
if not m3u8_url:
|
|
73
|
+
raise ValueError(f"StreamWish: m3u8 bulunamadı. {url}")
|
|
74
|
+
|
|
75
|
+
return ExtractResult(
|
|
76
|
+
name = self.name,
|
|
77
|
+
url = self.fix_url(m3u8_url),
|
|
78
|
+
referer = f"{base_url}/",
|
|
79
|
+
user_agent = self.httpx.headers.get("User-Agent", "")
|
|
80
|
+
)
|
|
@@ -2,6 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
from KekikStream.Core import ExtractorBase, ExtractResult, Subtitle, HTMLHelper
|
|
4
4
|
from Kekik.Sifreleme import Packer
|
|
5
|
+
from contextlib import suppress
|
|
5
6
|
import re
|
|
6
7
|
|
|
7
8
|
class VidHide(ExtractorBase):
|
|
@@ -17,7 +18,7 @@ class VidHide(ExtractorBase):
|
|
|
17
18
|
"kinoger.be",
|
|
18
19
|
"smoothpre.com",
|
|
19
20
|
"dhtpre.com",
|
|
20
|
-
"peytonepre.com"
|
|
21
|
+
"peytonepre.com",
|
|
21
22
|
]
|
|
22
23
|
|
|
23
24
|
def can_handle_url(self, url: str) -> bool:
|
|
@@ -37,69 +38,70 @@ class VidHide(ExtractorBase):
|
|
|
37
38
|
|
|
38
39
|
async def extract(self, url: str, referer: str = None) -> ExtractResult:
|
|
39
40
|
base_url = self.get_base_url(url)
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
41
|
+
name = "EarnVids" if any(x in base_url for x in ["smoothpre.com", "dhtpre.com", "peytonepre.com"]) else self.name
|
|
42
|
+
|
|
43
|
+
# Kotlin Headers
|
|
44
|
+
headers = {
|
|
45
|
+
"Sec-Fetch-Dest" : "empty",
|
|
46
|
+
"Sec-Fetch-Mode" : "cors",
|
|
47
|
+
"Sec-Fetch-Site" : "cross-site",
|
|
48
|
+
"Origin" : f"{base_url}/",
|
|
49
|
+
"Referer" : referer or f"{base_url}/",
|
|
50
|
+
}
|
|
51
|
+
|
|
45
52
|
embed_url = self.get_embed_url(url)
|
|
46
|
-
istek = await self.httpx.get(embed_url, follow_redirects=True)
|
|
53
|
+
istek = await self.httpx.get(embed_url, headers=headers, follow_redirects=True)
|
|
47
54
|
text = istek.text
|
|
48
55
|
|
|
49
56
|
# Silinmiş dosya kontrolü
|
|
50
|
-
if "File is no longer available"
|
|
51
|
-
raise ValueError(f"
|
|
57
|
+
if any(x in text for x in ["File is no longer available", "File Not Found", "Video silinmiş"]):
|
|
58
|
+
raise ValueError(f"{name}: Video silinmiş. {url}")
|
|
52
59
|
|
|
53
60
|
# JS Redirect Kontrolü (OneUpload vb.)
|
|
54
61
|
if js_redirect := HTMLHelper(text).regex_first(r"window\.location\.replace\(['\"]([^'\"]+)['\"]\)") or \
|
|
55
62
|
HTMLHelper(text).regex_first(r"window\.location\.href\s*=\s*['\"]([^'\"]+)['\"]"):
|
|
56
|
-
# Redirect url'i al
|
|
57
63
|
target_url = js_redirect
|
|
58
|
-
# Bazen path relative olabilir ama genelde full url
|
|
59
64
|
if not target_url.startswith("http"):
|
|
60
|
-
|
|
61
|
-
target_url = self.fix_url(target_url) # fix_url base'e göre düzeltebilir mi? ExtractorBase.fix_url genelde şema ekler.
|
|
62
|
-
pass
|
|
65
|
+
target_url = self.fix_url(target_url)
|
|
63
66
|
|
|
64
|
-
# Yeniden istek at
|
|
65
67
|
istek = await self.httpx.get(target_url, headers={"Referer": embed_url}, follow_redirects=True)
|
|
66
68
|
text = istek.text
|
|
67
69
|
|
|
68
70
|
sel = HTMLHelper(text)
|
|
69
71
|
|
|
70
72
|
unpacked = ""
|
|
71
|
-
# Eval script bul
|
|
73
|
+
# Eval script bul
|
|
72
74
|
if eval_match := sel.regex_first(r'(eval\s*\(\s*function[\s\S]+?)<\/script>'):
|
|
73
|
-
|
|
75
|
+
with suppress(Exception):
|
|
74
76
|
unpacked = Packer.unpack(eval_match)
|
|
75
77
|
if "var links" in unpacked:
|
|
76
78
|
unpacked = unpacked.split("var links")[1]
|
|
77
|
-
except:
|
|
78
|
-
pass
|
|
79
79
|
|
|
80
80
|
content = unpacked or text
|
|
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
|
-
|
|
81
|
+
|
|
82
|
+
# Kotlin Exact Regex: :\s*"(.*?m3u8.*?)"
|
|
83
|
+
m3u8_matches = re.findall(r':\s*["\']([^"\']+\.m3u8[^"\']*)["\']', content)
|
|
84
|
+
|
|
85
|
+
results = []
|
|
86
|
+
for m3u8_url in m3u8_matches:
|
|
87
|
+
results.append(ExtractResult(
|
|
88
|
+
name = name,
|
|
89
|
+
url = self.fix_url(m3u8_url),
|
|
90
|
+
referer = f"{base_url}/",
|
|
91
|
+
user_agent = self.httpx.headers.get("User-Agent", "")
|
|
92
|
+
))
|
|
93
|
+
|
|
94
|
+
if not results:
|
|
95
|
+
# Fallback for non-m3u8 or different patterns
|
|
96
|
+
if m3u8_url := sel.regex_first(r'sources:\s*\[\s*\{\s*file:\s*"([^"]+)"'):
|
|
97
|
+
results.append(ExtractResult(
|
|
98
|
+
name = name,
|
|
99
|
+
url = self.fix_url(m3u8_url),
|
|
100
|
+
referer = f"{base_url}/",
|
|
101
|
+
user_agent = self.httpx.headers.get("User-Agent", "")
|
|
102
|
+
))
|
|
103
|
+
|
|
104
|
+
if not results:
|
|
105
|
+
raise ValueError(f"{name}: Video URL bulunamadı. {url}")
|
|
106
|
+
|
|
107
|
+
return results[0] if len(results) == 1 else results
|
|
@@ -0,0 +1,88 @@
|
|
|
1
|
+
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
|
+
|
|
3
|
+
from KekikStream.Core import ExtractorBase, ExtractResult, Subtitle
|
|
4
|
+
from Crypto.Cipher import AES
|
|
5
|
+
from Crypto.Util import Padding
|
|
6
|
+
import re
|
|
7
|
+
|
|
8
|
+
class VidStack(ExtractorBase):
|
|
9
|
+
name = "VidStack"
|
|
10
|
+
main_url = "https://vidstack.io"
|
|
11
|
+
requires_referer = True
|
|
12
|
+
|
|
13
|
+
supported_domains = [
|
|
14
|
+
"vidstack.io", "server1.uns.bio", "upns.one"
|
|
15
|
+
]
|
|
16
|
+
|
|
17
|
+
def can_handle_url(self, url: str) -> bool:
|
|
18
|
+
return any(domain in url for domain in self.supported_domains)
|
|
19
|
+
|
|
20
|
+
def decrypt_aes(self, input_hex: str, key: str, iv: str) -> str:
|
|
21
|
+
try:
|
|
22
|
+
cipher = AES.new(key.encode('utf-8'), AES.MODE_CBC, iv.encode('utf-8'))
|
|
23
|
+
raw_data = bytes.fromhex(input_hex)
|
|
24
|
+
decrypted = cipher.decrypt(raw_data)
|
|
25
|
+
unpadded = Padding.unpad(decrypted, AES.block_size)
|
|
26
|
+
return unpadded.decode('utf-8')
|
|
27
|
+
except Exception as e:
|
|
28
|
+
# print(f"DEBUG VidStack: {iv} -> {e}") # Debugging
|
|
29
|
+
return None
|
|
30
|
+
|
|
31
|
+
async def extract(self, url: str, referer: str = None) -> ExtractResult | list[ExtractResult]:
|
|
32
|
+
headers = {"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:134.0) Gecko/20100101 Firefox/134.0"}
|
|
33
|
+
|
|
34
|
+
# Hash ve Base URL çıkarma
|
|
35
|
+
hash_val = url.split("#")[-1].split("/")[-1]
|
|
36
|
+
base_url = self.get_base_url(url)
|
|
37
|
+
|
|
38
|
+
# API İsteği
|
|
39
|
+
api_url = f"{base_url}/api/v1/video?id={hash_val}"
|
|
40
|
+
istek = await self.httpx.get(api_url, headers=headers)
|
|
41
|
+
|
|
42
|
+
# Bazen yanıt tırnak içinde gelebilir, temizleyelim
|
|
43
|
+
encoded_data = istek.text.strip().strip('"')
|
|
44
|
+
|
|
45
|
+
# AES Çözme
|
|
46
|
+
key = "kiemtienmua911ca"
|
|
47
|
+
ivs = ["1234567890oiuytr", "0123456789abcdef"]
|
|
48
|
+
|
|
49
|
+
decrypted_text = None
|
|
50
|
+
for iv in ivs:
|
|
51
|
+
decrypted_text = self.decrypt_aes(encoded_data, key, iv)
|
|
52
|
+
if decrypted_text and '"source":' in decrypted_text:
|
|
53
|
+
break
|
|
54
|
+
|
|
55
|
+
if not decrypted_text:
|
|
56
|
+
# Hata mesajını daha detaylı verelim (debug için tırnaklanmış hali)
|
|
57
|
+
raise ValueError(f"VidStack: AES çözme başarısız. {url} | Response: {istek.text[:50]}...")
|
|
58
|
+
|
|
59
|
+
# m3u8 ve Alt yazı çıkarma
|
|
60
|
+
# Kotlin'de "source":"(.*?)" regex'i kullanılıyor
|
|
61
|
+
m3u8_url = re.search(r'["\']source["\']\s*:\s*["\']([^"\']+)["\']', decrypted_text)
|
|
62
|
+
if m3u8_url:
|
|
63
|
+
m3u8_url = m3u8_url.group(1).replace("\\/", "/")
|
|
64
|
+
else:
|
|
65
|
+
raise ValueError(f"VidStack: m3u8 bulunamadı. {url}")
|
|
66
|
+
|
|
67
|
+
subtitles = []
|
|
68
|
+
# Kotlin: "subtitle":\{(.*?)\}
|
|
69
|
+
subtitle_section = re.search(r'["\']subtitle["\']\s*:\s*\{(.*?)\}', decrypted_text)
|
|
70
|
+
if subtitle_section:
|
|
71
|
+
section = subtitle_section.group(1)
|
|
72
|
+
# Regex: "([^"]+)":\s*"([^"]+)"
|
|
73
|
+
matches = re.finditer(r'["\']([^"\']+)["\']\s*:\s*["\']([^"\']+)["\']', section)
|
|
74
|
+
for match in matches:
|
|
75
|
+
lang = match.group(1)
|
|
76
|
+
raw_path = match.group(2).split("#")[0]
|
|
77
|
+
if raw_path:
|
|
78
|
+
path = raw_path.replace("\\/", "/")
|
|
79
|
+
sub_url = f"{self.main_url}{path}"
|
|
80
|
+
subtitles.append(Subtitle(name=lang, url=self.fix_url(sub_url)))
|
|
81
|
+
|
|
82
|
+
return ExtractResult(
|
|
83
|
+
name = self.name,
|
|
84
|
+
url = self.fix_url(m3u8_url),
|
|
85
|
+
referer = url,
|
|
86
|
+
user_agent = headers["User-Agent"],
|
|
87
|
+
subtitles = subtitles
|
|
88
|
+
)
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|
|
Binary file
|