KekikStream 2.3.9__py3-none-any.whl → 2.5.3__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/Extractor/ExtractorLoader.py +8 -14
- KekikStream/Core/HTMLHelper.py +120 -49
- KekikStream/Core/Plugin/PluginBase.py +30 -12
- KekikStream/Core/Plugin/PluginLoader.py +12 -14
- KekikStream/Core/Plugin/PluginManager.py +2 -2
- KekikStream/Core/Plugin/PluginModels.py +0 -3
- KekikStream/Extractors/Abstream.py +27 -0
- 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 +21 -46
- KekikStream/Extractors/HDMomPlayer.py +30 -0
- KekikStream/Extractors/HDPlayerSystem.py +13 -31
- KekikStream/Extractors/HotStream.py +27 -0
- KekikStream/Extractors/JFVid.py +3 -24
- KekikStream/Extractors/JetTv.py +21 -34
- KekikStream/Extractors/JetV.py +55 -0
- 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 +40 -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/Veev.py +145 -0
- KekikStream/Extractors/VidBiz.py +62 -0
- KekikStream/Extractors/VidHide.py +58 -30
- 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 +58 -0
- KekikStream/Extractors/Vidoza.py +18 -0
- KekikStream/Extractors/Vtbe.py +38 -0
- KekikStream/Extractors/YTDLP.py +2 -2
- KekikStream/Extractors/YildizKisaFilm.py +13 -31
- KekikStream/Extractors/Zeus.py +61 -0
- KekikStream/Plugins/BelgeselX.py +97 -77
- KekikStream/Plugins/DiziBox.py +28 -45
- KekikStream/Plugins/DiziMom.py +179 -0
- KekikStream/Plugins/DiziPal.py +95 -161
- KekikStream/Plugins/DiziYou.py +51 -147
- KekikStream/Plugins/Dizilla.py +40 -61
- KekikStream/Plugins/FilmBip.py +90 -39
- KekikStream/Plugins/FilmEkseni.py +199 -0
- KekikStream/Plugins/FilmMakinesi.py +72 -73
- KekikStream/Plugins/FilmModu.py +25 -35
- KekikStream/Plugins/Filmatek.py +184 -0
- KekikStream/Plugins/FilmciBaba.py +155 -0
- KekikStream/Plugins/FullHDFilmizlesene.py +16 -37
- KekikStream/Plugins/HDFilm.py +243 -0
- KekikStream/Plugins/HDFilmCehennemi.py +242 -189
- KekikStream/Plugins/JetFilmizle.py +101 -69
- KekikStream/Plugins/KultFilmler.py +138 -104
- KekikStream/Plugins/RecTV.py +52 -73
- KekikStream/Plugins/RoketDizi.py +18 -27
- KekikStream/Plugins/SelcukFlix.py +30 -48
- KekikStream/Plugins/SetFilmIzle.py +76 -104
- KekikStream/Plugins/SezonlukDizi.py +90 -94
- KekikStream/Plugins/Sinefy.py +195 -167
- KekikStream/Plugins/SinemaCX.py +148 -78
- KekikStream/Plugins/Sinezy.py +29 -31
- KekikStream/Plugins/SuperFilmGeldi.py +12 -17
- KekikStream/Plugins/UgurFilm.py +85 -38
- KekikStream/Plugins/Watch32.py +160 -0
- KekikStream/Plugins/YabanciDizi.py +176 -211
- {kekikstream-2.3.9.dist-info → kekikstream-2.5.3.dist-info}/METADATA +1 -1
- kekikstream-2.5.3.dist-info/RECORD +99 -0
- {kekikstream-2.3.9.dist-info → kekikstream-2.5.3.dist-info}/WHEEL +1 -1
- KekikStream/Plugins/FullHDFilm.py +0 -249
- kekikstream-2.3.9.dist-info/RECORD +0 -84
- {kekikstream-2.3.9.dist-info → kekikstream-2.5.3.dist-info}/entry_points.txt +0 -0
- {kekikstream-2.3.9.dist-info → kekikstream-2.5.3.dist-info}/licenses/LICENSE +0 -0
- {kekikstream-2.3.9.dist-info → kekikstream-2.5.3.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,62 @@
|
|
|
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
|
+
|
|
6
|
+
class VidBiz(ExtractorBase):
|
|
7
|
+
name = "VidBiz"
|
|
8
|
+
main_url = "https://videolar.biz"
|
|
9
|
+
|
|
10
|
+
async def extract(self, url: str, referer: str = None) -> list[ExtractResult]:
|
|
11
|
+
istek = await self.httpx.get(url, headers={"Referer": referer} if referer else None)
|
|
12
|
+
text = istek.text
|
|
13
|
+
|
|
14
|
+
# Eval script bul (kaken içeriyor olmalı)
|
|
15
|
+
eval_script = HTMLHelper(text).regex_first(r'(eval\(function[\s\S]+?)<\/script>') or \
|
|
16
|
+
HTMLHelper(text).regex_first(r'(eval\(function[\s\S]+)')
|
|
17
|
+
if not eval_script:
|
|
18
|
+
raise ValueError(f"VidBiz: Packed script bulunamadı. {url}")
|
|
19
|
+
|
|
20
|
+
unpacked = ""
|
|
21
|
+
try:
|
|
22
|
+
unpacked = Packer.unpack(eval_script)
|
|
23
|
+
except:
|
|
24
|
+
raise ValueError("VidBiz: Unpack hatası")
|
|
25
|
+
|
|
26
|
+
# window.kaken="..."
|
|
27
|
+
kaken = HTMLHelper(unpacked).regex_first(r'window\.kaken\s*=\s*"([^"]+)"')
|
|
28
|
+
if not kaken:
|
|
29
|
+
raise ValueError("VidBiz: Kaken token bulunamadı")
|
|
30
|
+
|
|
31
|
+
# API POST
|
|
32
|
+
# Content-Type: text/plain önemli olabilir
|
|
33
|
+
resp = await self.httpx.post(
|
|
34
|
+
url = "https://s2.videolar.biz/api/",
|
|
35
|
+
content = kaken, # data yerine content=raw string
|
|
36
|
+
headers = {"Content-Type": "text/plain", "Referer": url}
|
|
37
|
+
)
|
|
38
|
+
|
|
39
|
+
try:
|
|
40
|
+
data = resp.json()
|
|
41
|
+
except:
|
|
42
|
+
raise ValueError("VidBiz: API yanıtı JSON değil")
|
|
43
|
+
|
|
44
|
+
if data.get("status") != "ok":
|
|
45
|
+
raise ValueError(f"VidBiz: API hatası {data}")
|
|
46
|
+
|
|
47
|
+
results = []
|
|
48
|
+
for source in data.get("sources", []):
|
|
49
|
+
file_url = source.get("file")
|
|
50
|
+
label = source.get("label", "Unknown")
|
|
51
|
+
|
|
52
|
+
if not file_url:
|
|
53
|
+
continue
|
|
54
|
+
|
|
55
|
+
results.append(ExtractResult(
|
|
56
|
+
name = f"{self.name} | {label}",
|
|
57
|
+
url = self.fix_url(file_url),
|
|
58
|
+
referer = url,
|
|
59
|
+
user_agent = self.httpx.headers.get("User-Agent", "")
|
|
60
|
+
))
|
|
61
|
+
|
|
62
|
+
return results
|
|
@@ -9,7 +9,16 @@ class VidHide(ExtractorBase):
|
|
|
9
9
|
main_url = "https://vidhidepro.com"
|
|
10
10
|
|
|
11
11
|
# Birden fazla domain destekle
|
|
12
|
-
supported_domains = [
|
|
12
|
+
supported_domains = [
|
|
13
|
+
"vidhidepro.com", "vidhide.com", "rubyvidhub.com",
|
|
14
|
+
"vidhidevip.com", "vidhideplus.com", "vidhidepre.com",
|
|
15
|
+
"movearnpre.com", "oneupload.to",
|
|
16
|
+
"filelions.live", "filelions.online", "filelions.to",
|
|
17
|
+
"kinoger.be",
|
|
18
|
+
"smoothpre.com",
|
|
19
|
+
"dhtpre.com",
|
|
20
|
+
"peytonepre.com"
|
|
21
|
+
]
|
|
13
22
|
|
|
14
23
|
def can_handle_url(self, url: str) -> bool:
|
|
15
24
|
return any(domain in url for domain in self.supported_domains)
|
|
@@ -21,50 +30,70 @@ class VidHide(ExtractorBase):
|
|
|
21
30
|
return url.replace("/download/", "/v/")
|
|
22
31
|
elif "/file/" in url:
|
|
23
32
|
return url.replace("/file/", "/v/")
|
|
33
|
+
elif "/embed/" in url:
|
|
34
|
+
return url.replace("/embed/", "/v/")
|
|
24
35
|
else:
|
|
25
36
|
return url.replace("/f/", "/v/")
|
|
26
37
|
|
|
27
38
|
async def extract(self, url: str, referer: str = None) -> ExtractResult:
|
|
28
|
-
# Dinamik base URL kullan
|
|
29
39
|
base_url = self.get_base_url(url)
|
|
30
|
-
|
|
31
|
-
if referer:
|
|
32
|
-
self.httpx.headers.update({"Referer": referer})
|
|
33
|
-
|
|
34
40
|
self.httpx.headers.update({
|
|
35
|
-
"
|
|
36
|
-
"
|
|
37
|
-
"Sec-Fetch-Site" : "cross-site",
|
|
38
|
-
"Origin" : base_url,
|
|
41
|
+
"Referer" : referer or base_url,
|
|
42
|
+
"Origin" : base_url,
|
|
39
43
|
})
|
|
40
44
|
|
|
41
45
|
embed_url = self.get_embed_url(url)
|
|
42
|
-
istek = await self.httpx.get(embed_url)
|
|
43
|
-
|
|
46
|
+
istek = await self.httpx.get(embed_url, follow_redirects=True)
|
|
47
|
+
text = istek.text
|
|
48
|
+
|
|
49
|
+
# Silinmiş dosya kontrolü
|
|
50
|
+
if "File is no longer available" in text or "File Not Found" in text:
|
|
51
|
+
raise ValueError(f"VidHide: Video silinmiş. {url}")
|
|
52
|
+
|
|
53
|
+
# JS Redirect Kontrolü (OneUpload vb.)
|
|
54
|
+
if js_redirect := HTMLHelper(text).regex_first(r"window\.location\.replace\(['\"]([^'\"]+)['\"]\)") or \
|
|
55
|
+
HTMLHelper(text).regex_first(r"window\.location\.href\s*=\s*['\"]([^'\"]+)['\"]"):
|
|
56
|
+
# Redirect url'i al
|
|
57
|
+
target_url = js_redirect
|
|
58
|
+
# Bazen path relative olabilir ama genelde full url
|
|
59
|
+
if not target_url.startswith("http"):
|
|
60
|
+
# urljoin gerekebilir ama şimdilik doğrudan deneyelim veya fix_url
|
|
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
|
|
63
|
+
|
|
64
|
+
# Yeniden istek at
|
|
65
|
+
istek = await self.httpx.get(target_url, headers={"Referer": embed_url}, follow_redirects=True)
|
|
66
|
+
text = istek.text
|
|
44
67
|
|
|
45
|
-
|
|
46
|
-
|
|
68
|
+
sel = HTMLHelper(text)
|
|
69
|
+
|
|
70
|
+
unpacked = ""
|
|
71
|
+
# Eval script bul (regex ile daha sağlam)
|
|
72
|
+
if eval_match := sel.regex_first(r'(eval\s*\(\s*function[\s\S]+?)<\/script>'):
|
|
47
73
|
try:
|
|
48
|
-
unpacked = Packer.unpack(
|
|
74
|
+
unpacked = Packer.unpack(eval_match)
|
|
49
75
|
if "var links" in unpacked:
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
script = unpacked
|
|
53
|
-
except Exception:
|
|
76
|
+
unpacked = unpacked.split("var links")[1]
|
|
77
|
+
except:
|
|
54
78
|
pass
|
|
55
79
|
|
|
56
|
-
|
|
57
|
-
script = HTMLHelper(response).regex_first(r'(?s)sources:\s*(\[.*?\])')
|
|
80
|
+
content = unpacked or text
|
|
58
81
|
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
m3u8_url = HTMLHelper(script).regex_first(r':\s*"([^\"]*?m3u8[^\"]*?)"')
|
|
82
|
+
# Regex: Kotlin mantığı (: "url")
|
|
83
|
+
# Ayrıca sources: [...] mantığını da ekle
|
|
84
|
+
m3u8_url = HTMLHelper(content).regex_first(r'sources:\s*\[\s*\{\s*file:\s*"([^"]+)"')
|
|
63
85
|
|
|
64
86
|
if not m3u8_url:
|
|
65
|
-
#
|
|
66
|
-
|
|
67
|
-
|
|
87
|
+
# Genel arama (hls:, file: vb.)
|
|
88
|
+
# Kotlin Regex: :\s*"(.*?m3u8.*?)"
|
|
89
|
+
match = HTMLHelper(content).regex_first(r':\s*["\']([^"\']+\.m3u8[^"\']*)["\']')
|
|
90
|
+
if match:
|
|
91
|
+
m3u8_url = match
|
|
92
|
+
|
|
93
|
+
if not m3u8_url:
|
|
94
|
+
# Son şans: herhangi bir m3u8 linki
|
|
95
|
+
m3u8_url = HTMLHelper(content).regex_first(r'["\']([^"\']+\.m3u8[^"\']*)["\']')
|
|
96
|
+
|
|
68
97
|
if not m3u8_url:
|
|
69
98
|
raise ValueError(f"VidHide: Video URL bulunamadı. {url}")
|
|
70
99
|
|
|
@@ -72,6 +101,5 @@ class VidHide(ExtractorBase):
|
|
|
72
101
|
name = self.name,
|
|
73
102
|
url = self.fix_url(m3u8_url),
|
|
74
103
|
referer = f"{base_url}/",
|
|
75
|
-
user_agent = self.httpx.headers.get("User-Agent", "")
|
|
76
|
-
subtitles = []
|
|
104
|
+
user_agent = self.httpx.headers.get("User-Agent", "")
|
|
77
105
|
)
|
|
@@ -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"(?s)tracks:\s*\[(.*?)\]"):
|
|
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"(?s)sources:\s*\[(.*?)\],"):
|
|
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
|
)
|
|
@@ -4,84 +4,54 @@ from KekikStream.Core import ExtractorBase, ExtractResult, Subtitle, HTMLHelper
|
|
|
4
4
|
|
|
5
5
|
|
|
6
6
|
class VidPapi(ExtractorBase):
|
|
7
|
-
name = "
|
|
7
|
+
name = "VidPapi"
|
|
8
8
|
main_url = "https://vidpapi.xyz"
|
|
9
9
|
|
|
10
|
-
async def extract(self, url, referer=None) -> ExtractResult:
|
|
11
|
-
|
|
10
|
+
async def extract(self, url: str, referer: str = None) -> ExtractResult:
|
|
11
|
+
ref = referer or self.main_url
|
|
12
12
|
|
|
13
|
-
#
|
|
13
|
+
# ID tespiti
|
|
14
14
|
if "video/" in url:
|
|
15
15
|
vid_id = url.split("video/")[-1]
|
|
16
16
|
else:
|
|
17
17
|
vid_id = url.split("?data=")[-1]
|
|
18
18
|
|
|
19
|
-
|
|
20
|
-
sub_url = f"{self.main_url}/player/index.php?data={vid_id}"
|
|
21
|
-
sub_headers = {
|
|
19
|
+
headers = {
|
|
22
20
|
"Content-Type" : "application/x-www-form-urlencoded; charset=UTF-8",
|
|
23
21
|
"X-Requested-With" : "XMLHttpRequest",
|
|
24
|
-
"
|
|
25
|
-
"Referer" : ext_ref or "https://kultfilmler.pro/"
|
|
22
|
+
"Referer" : ref
|
|
26
23
|
}
|
|
27
24
|
|
|
25
|
+
# 1. Altyazıları çek
|
|
28
26
|
subtitles = []
|
|
29
27
|
try:
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
headers =
|
|
33
|
-
data = {"hash": vid_id, "r":
|
|
28
|
+
sub_resp = await self.httpx.post(
|
|
29
|
+
f"{self.main_url}/player/index.php?data={vid_id}",
|
|
30
|
+
headers = headers,
|
|
31
|
+
data = {"hash": vid_id, "r": ref}
|
|
34
32
|
)
|
|
35
|
-
|
|
36
|
-
raw_subs
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
lang = lang.strip()
|
|
41
|
-
if "Türkçe" in lang:
|
|
42
|
-
lang_code = "tr"
|
|
43
|
-
lang_name = "Turkish"
|
|
44
|
-
elif "İngilizce" in lang:
|
|
45
|
-
lang_code = "en"
|
|
46
|
-
lang_name = "English"
|
|
47
|
-
else:
|
|
48
|
-
lang_code = lang[:2].lower()
|
|
49
|
-
lang_name = lang
|
|
50
|
-
|
|
51
|
-
subtitles.append(Subtitle(
|
|
52
|
-
name = lang_name,
|
|
53
|
-
url = sub_link.strip()
|
|
54
|
-
))
|
|
55
|
-
|
|
56
|
-
except Exception as e:
|
|
33
|
+
sel = HTMLHelper(sub_resp.text)
|
|
34
|
+
if raw_subs := sel.regex_first(r'var playerjsSubtitle\s*=\s*"([^"]*)"'):
|
|
35
|
+
for lang, link in HTMLHelper(raw_subs).regex_all(r'\[(.*?)\](https?://[^\s\",]+)'):
|
|
36
|
+
subtitles.append(Subtitle(name=lang.strip(), url=link.strip()))
|
|
37
|
+
except:
|
|
57
38
|
pass
|
|
58
39
|
|
|
59
40
|
# 2. Videoyu çek
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
url = video_url,
|
|
65
|
-
headers = video_headers,
|
|
66
|
-
data = {"hash": vid_id, "r": "https://kultfilmler.pro/"}
|
|
41
|
+
resp = await self.httpx.post(
|
|
42
|
+
f"{self.main_url}/player/index.php?data={vid_id}&do=getVideo",
|
|
43
|
+
headers = headers,
|
|
44
|
+
data = {"hash": vid_id, "r": ref}
|
|
67
45
|
)
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
try:
|
|
71
|
-
video_data = response.json()
|
|
72
|
-
except Exception:
|
|
73
|
-
return None
|
|
46
|
+
data = resp.json()
|
|
74
47
|
|
|
75
|
-
stream_url =
|
|
76
|
-
if not stream_url or not stream_url.strip():
|
|
77
|
-
stream_url = video_data.get("videoSource")
|
|
78
|
-
|
|
48
|
+
stream_url = data.get("securedLink") or data.get("videoSource")
|
|
79
49
|
if not stream_url:
|
|
80
|
-
raise ValueError("
|
|
50
|
+
raise ValueError(f"VidPapi: Video URL bulunamadı. {url}")
|
|
81
51
|
|
|
82
52
|
return ExtractResult(
|
|
83
53
|
name = self.name,
|
|
84
54
|
url = stream_url,
|
|
85
|
-
referer =
|
|
55
|
+
referer = ref,
|
|
86
56
|
subtitles = subtitles
|
|
87
57
|
)
|
|
@@ -1,4 +1,4 @@
|
|
|
1
|
-
#
|
|
1
|
+
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
2
|
|
|
3
3
|
from KekikStream.Core import ExtractorBase, ExtractResult, Subtitle, HTMLHelper
|
|
4
4
|
import json
|
|
@@ -7,47 +7,26 @@ class VideoSeyred(ExtractorBase):
|
|
|
7
7
|
name = "VideoSeyred"
|
|
8
8
|
main_url = "https://videoseyred.in"
|
|
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
|
+
v_id = url.split("embed/")[1].split("?")[0]
|
|
12
|
+
if len(v_id) > 10:
|
|
13
|
+
resp = await self.httpx.get(url)
|
|
14
|
+
v_id = HTMLHelper(resp.text).regex_first(r"playlist\/(.*)\.json")
|
|
13
15
|
|
|
14
|
-
|
|
15
|
-
|
|
16
|
-
kontrol = await self.httpx.get(url)
|
|
17
|
-
kontrol.raise_for_status()
|
|
18
|
-
|
|
19
|
-
video_id = HTMLHelper(kontrol.text).regex_first(r"playlist\/(.*)\.json")
|
|
20
|
-
|
|
21
|
-
video_url = f"{self.main_url}/playlist/{video_id}.json"
|
|
22
|
-
|
|
23
|
-
response = await self.httpx.get(video_url)
|
|
24
|
-
response.raise_for_status()
|
|
25
|
-
|
|
26
|
-
try:
|
|
27
|
-
if response_list := json.loads(response.text):
|
|
28
|
-
response_data = response_list[0]
|
|
29
|
-
else:
|
|
30
|
-
raise ValueError("Empty response from VideoSeyred.")
|
|
31
|
-
|
|
32
|
-
except (json.JSONDecodeError, IndexError) as hata:
|
|
33
|
-
raise RuntimeError(f"Failed to parse response: {hata}") from hata
|
|
16
|
+
json_resp = await self.httpx.get(f"{self.main_url}/playlist/{v_id}.json")
|
|
17
|
+
data = json_resp.json()[0]
|
|
34
18
|
|
|
35
19
|
subtitles = [
|
|
36
|
-
Subtitle(name=
|
|
37
|
-
|
|
38
|
-
|
|
20
|
+
Subtitle(name=t["label"], url=self.fix_url(t["file"]))
|
|
21
|
+
for t in data.get("tracks", []) if t.get("kind") == "captions"
|
|
22
|
+
]
|
|
23
|
+
|
|
24
|
+
results = [
|
|
25
|
+
ExtractResult(name=self.name, url=self.fix_url(s["file"]), referer=self.main_url, subtitles=subtitles)
|
|
26
|
+
for s in data.get("sources", [])
|
|
39
27
|
]
|
|
40
28
|
|
|
41
|
-
if
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
referer = self.main_url,
|
|
46
|
-
subtitles = subtitles,
|
|
47
|
-
)
|
|
48
|
-
for source in response_data.get("sources", [])
|
|
49
|
-
]:
|
|
50
|
-
# En yüksek kaliteli videoyu döndür (varsayılan olarak ilk video)
|
|
51
|
-
return video_links[0] if len(video_links) == 1 else video_links
|
|
52
|
-
else:
|
|
53
|
-
raise ValueError("No video links found in the response.")
|
|
29
|
+
if not results:
|
|
30
|
+
raise ValueError(f"VideoSeyred: Video bulunamadı. {url}")
|
|
31
|
+
|
|
32
|
+
return results[0] if len(results) == 1 else results
|