KekikStream 1.4.4__py3-none-any.whl → 2.0.2__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/CLI/pypi_kontrol.py +6 -6
- KekikStream/Core/Extractor/ExtractorBase.py +13 -12
- KekikStream/Core/Extractor/ExtractorLoader.py +25 -17
- KekikStream/Core/Extractor/ExtractorManager.py +53 -9
- KekikStream/Core/Extractor/ExtractorModels.py +5 -7
- KekikStream/Core/Extractor/YTDLPCache.py +35 -0
- KekikStream/Core/Media/MediaHandler.py +52 -31
- KekikStream/Core/Media/MediaManager.py +0 -3
- KekikStream/Core/Plugin/PluginBase.py +47 -21
- KekikStream/Core/Plugin/PluginLoader.py +11 -7
- KekikStream/Core/Plugin/PluginModels.py +25 -25
- KekikStream/Core/__init__.py +1 -0
- KekikStream/Extractors/CloseLoad.py +6 -26
- KekikStream/Extractors/ContentX_.py +40 -0
- KekikStream/Extractors/DzenRu.py +38 -0
- KekikStream/Extractors/ExPlay.py +53 -0
- KekikStream/Extractors/FirePlayer.py +60 -0
- KekikStream/Extractors/HDPlayerSystem.py +41 -0
- KekikStream/Extractors/JetTv.py +45 -0
- KekikStream/Extractors/MailRu.py +2 -4
- KekikStream/Extractors/MixTiger.py +57 -0
- KekikStream/Extractors/MolyStream.py +25 -7
- KekikStream/Extractors/Odnoklassniki.py +16 -11
- KekikStream/Extractors/{OkRuHTTP.py → Odnoklassniki_.py} +5 -1
- KekikStream/Extractors/{HDStreamAble.py → PeaceMakerst_.py} +1 -1
- KekikStream/Extractors/PixelDrain.py +0 -1
- KekikStream/Extractors/PlayerFilmIzle.py +62 -0
- KekikStream/Extractors/RapidVid.py +30 -13
- KekikStream/Extractors/RapidVid_.py +7 -0
- KekikStream/Extractors/SetPlay.py +57 -0
- KekikStream/Extractors/SetPrime.py +45 -0
- KekikStream/Extractors/SibNet.py +0 -1
- KekikStream/Extractors/TurkeyPlayer.py +34 -0
- KekikStream/Extractors/VidHide.py +72 -0
- KekikStream/Extractors/VidMoly.py +20 -19
- KekikStream/Extractors/{VidMolyMe.py → VidMoly_.py} +1 -1
- KekikStream/Extractors/VidMoxy.py +0 -1
- KekikStream/Extractors/VidPapi.py +89 -0
- KekikStream/Extractors/YTDLP.py +177 -0
- KekikStream/Extractors/YildizKisaFilm.py +41 -0
- KekikStream/Plugins/DiziBox.py +28 -16
- KekikStream/Plugins/DiziPal.py +246 -0
- KekikStream/Plugins/DiziYou.py +58 -31
- KekikStream/Plugins/Dizilla.py +97 -68
- KekikStream/Plugins/FilmBip.py +145 -0
- KekikStream/Plugins/FilmMakinesi.py +61 -52
- KekikStream/Plugins/FilmModu.py +138 -0
- KekikStream/Plugins/FullHDFilm.py +164 -0
- KekikStream/Plugins/FullHDFilmizlesene.py +38 -37
- KekikStream/Plugins/HDFilmCehennemi.py +44 -54
- KekikStream/Plugins/JetFilmizle.py +68 -42
- KekikStream/Plugins/KultFilmler.py +219 -0
- KekikStream/Plugins/RecTV.py +41 -37
- KekikStream/Plugins/RoketDizi.py +232 -0
- KekikStream/Plugins/SelcukFlix.py +309 -0
- KekikStream/Plugins/SezonlukDizi.py +16 -14
- KekikStream/Plugins/SineWix.py +39 -30
- KekikStream/Plugins/Sinefy.py +238 -0
- KekikStream/Plugins/SinemaCX.py +157 -0
- KekikStream/Plugins/Sinezy.py +146 -0
- KekikStream/Plugins/SuperFilmGeldi.py +121 -0
- KekikStream/Plugins/UgurFilm.py +10 -10
- KekikStream/__init__.py +296 -319
- KekikStream/requirements.txt +3 -4
- kekikstream-2.0.2.dist-info/METADATA +309 -0
- kekikstream-2.0.2.dist-info/RECORD +82 -0
- {kekikstream-1.4.4.dist-info → kekikstream-2.0.2.dist-info}/WHEEL +1 -1
- KekikStream/Extractors/FourCX.py +0 -7
- KekikStream/Extractors/FourPichive.py +0 -7
- KekikStream/Extractors/FourPlayRu.py +0 -7
- KekikStream/Extractors/Hotlinger.py +0 -7
- KekikStream/Extractors/OkRuSSL.py +0 -7
- KekikStream/Extractors/Pichive.py +0 -7
- KekikStream/Extractors/PlayRu.py +0 -7
- KekikStream/Helpers/Unpack.py +0 -75
- KekikStream/Plugins/Shorten.py +0 -225
- kekikstream-1.4.4.dist-info/METADATA +0 -108
- kekikstream-1.4.4.dist-info/RECORD +0 -63
- {kekikstream-1.4.4.dist-info → kekikstream-2.0.2.dist-info}/entry_points.txt +0 -0
- {kekikstream-1.4.4.dist-info → kekikstream-2.0.2.dist-info/licenses}/LICENSE +0 -0
- {kekikstream-1.4.4.dist-info → kekikstream-2.0.2.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, Subtitle
|
|
4
|
+
import re, json
|
|
5
|
+
|
|
6
|
+
class PlayerFilmIzle(ExtractorBase):
|
|
7
|
+
name = "PlayerFilmIzle"
|
|
8
|
+
main_url = "https://player.filmizle.in"
|
|
9
|
+
|
|
10
|
+
async def extract(self, url: str, referer: str = None) -> ExtractResult:
|
|
11
|
+
# Kotlin tarafında referer mainUrl olarak zorlanmış
|
|
12
|
+
ext_ref = self.main_url
|
|
13
|
+
self.httpx.headers.update({"Referer": ext_ref})
|
|
14
|
+
|
|
15
|
+
istek = await self.httpx.get(url)
|
|
16
|
+
video_req = istek.text
|
|
17
|
+
|
|
18
|
+
subtitles = []
|
|
19
|
+
if sub_match := re.search(r'playerjsSubtitle = "([^"]*)"', video_req, re.IGNORECASE):
|
|
20
|
+
sub_yakala = sub_match.group(1)
|
|
21
|
+
# Format örneği: [dil]url
|
|
22
|
+
# Kotlin kodunda: subYakala.substringAfter("]") -> url
|
|
23
|
+
# subYakala.substringBefore("]").removePrefix("[") -> lang
|
|
24
|
+
if "]" in sub_yakala:
|
|
25
|
+
sub_lang_raw, sub_url = sub_yakala.split("]", 1)
|
|
26
|
+
sub_lang = sub_lang_raw.replace("[", "")
|
|
27
|
+
subtitles.append(Subtitle(name=sub_lang, url=sub_url))
|
|
28
|
+
|
|
29
|
+
# Data yakalama: FirePlayer|DATA|...
|
|
30
|
+
data_match = re.search(r'FirePlayer\|([^|]+)\|', video_req, re.IGNORECASE)
|
|
31
|
+
data_val = data_match.group(1) if data_match else None
|
|
32
|
+
|
|
33
|
+
if not data_val:
|
|
34
|
+
raise ValueError("PlayerFilmIzle: Data bulunamadı")
|
|
35
|
+
|
|
36
|
+
url_post = f"{self.main_url}/player/index.php?data={data_val}&do=getVideo"
|
|
37
|
+
|
|
38
|
+
post_headers = {
|
|
39
|
+
"Referer": ext_ref,
|
|
40
|
+
"X-Requested-With": "XMLHttpRequest"
|
|
41
|
+
}
|
|
42
|
+
|
|
43
|
+
# Kotlin'de post data: "hash" -> data, "r" -> ""
|
|
44
|
+
post_data = {"hash": data_val, "r": ""}
|
|
45
|
+
|
|
46
|
+
response = await self.httpx.post(url_post, data=post_data, headers=post_headers)
|
|
47
|
+
get_url = response.text.replace("\\", "")
|
|
48
|
+
|
|
49
|
+
m3u8_url = ""
|
|
50
|
+
if url_yakala := re.search(r'"securedLink":"([^"]*)"', get_url, re.IGNORECASE):
|
|
51
|
+
m3u8_url = url_yakala.group(1)
|
|
52
|
+
|
|
53
|
+
if not m3u8_url:
|
|
54
|
+
raise ValueError("PlayerFilmIzle: M3U8 linki bulunamadı")
|
|
55
|
+
|
|
56
|
+
return ExtractResult(
|
|
57
|
+
name = self.name,
|
|
58
|
+
url = m3u8_url,
|
|
59
|
+
referer = ext_ref,
|
|
60
|
+
user_agent = self.httpx.headers.get("User-Agent", None),
|
|
61
|
+
subtitles = subtitles
|
|
62
|
+
)
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
from KekikStream.Core import ExtractorBase, ExtractResult, Subtitle
|
|
4
4
|
from Kekik.Sifreleme import Packer, HexCodec
|
|
5
|
-
import re
|
|
5
|
+
import re, base64
|
|
6
6
|
|
|
7
7
|
class RapidVid(ExtractorBase):
|
|
8
8
|
name = "RapidVid"
|
|
@@ -37,24 +37,41 @@ class RapidVid(ExtractorBase):
|
|
|
37
37
|
escaped_hex = extracted_value[1]
|
|
38
38
|
decoded_url = HexCodec.decode(escaped_hex)
|
|
39
39
|
else:
|
|
40
|
-
|
|
41
|
-
if not
|
|
42
|
-
raise ValueError("
|
|
40
|
+
av_encoded = re.search(r"av\('([^']+)'\)", istek.text)
|
|
41
|
+
if not av_encoded:
|
|
42
|
+
raise ValueError("AV encoding not found.")
|
|
43
43
|
|
|
44
|
-
|
|
45
|
-
extracted_value = re.search(r'file":"(.*)","label', unpacked_jwsetup)
|
|
46
|
-
if not extracted_value:
|
|
47
|
-
raise ValueError("File URL not found in unpacked JWPlayer setup.")
|
|
48
|
-
|
|
49
|
-
escaped_hex = extracted_value[1].replace("\\\\x", "")
|
|
50
|
-
decoded_url = bytes.fromhex(escaped_hex).decode("utf-8")
|
|
44
|
+
decoded_url = self.decode_secret(av_encoded[1])
|
|
51
45
|
except Exception as hata:
|
|
52
46
|
raise RuntimeError(f"Extraction failed: {hata}") from hata
|
|
53
47
|
|
|
54
|
-
await self.close()
|
|
55
48
|
return ExtractResult(
|
|
56
49
|
name = self.name,
|
|
57
50
|
url = decoded_url,
|
|
58
51
|
referer = self.main_url,
|
|
59
52
|
subtitles = subtitles
|
|
60
|
-
)
|
|
53
|
+
)
|
|
54
|
+
|
|
55
|
+
def decode_secret(self, encoded_string: str) -> str:
|
|
56
|
+
# 1. Base64 ile şifrelenmiş string ters çevrilmiş, önce geri çeviriyoruz
|
|
57
|
+
reversed_input = encoded_string[::-1]
|
|
58
|
+
|
|
59
|
+
# 2. İlk base64 çözme işlemi
|
|
60
|
+
decoded_once = base64.b64decode(reversed_input).decode("utf-8")
|
|
61
|
+
|
|
62
|
+
decrypted_chars = []
|
|
63
|
+
key = "K9L"
|
|
64
|
+
|
|
65
|
+
# 3. Key'e göre karakter kaydırma geri alınıyor
|
|
66
|
+
for index, encoded_char in enumerate(decoded_once):
|
|
67
|
+
key_char = key[index % len(key)]
|
|
68
|
+
offset = (ord(key_char) % 5) + 1 # Her karakter için dinamik offset
|
|
69
|
+
|
|
70
|
+
original_char_code = ord(encoded_char) - offset
|
|
71
|
+
decrypted_chars.append(chr(original_char_code))
|
|
72
|
+
|
|
73
|
+
# 4. Karakterleri birleştirip ikinci base64 çözme işlemini yapıyoruz
|
|
74
|
+
intermediate_string = "".join(decrypted_chars)
|
|
75
|
+
final_decoded_bytes = base64.b64decode(intermediate_string)
|
|
76
|
+
|
|
77
|
+
return final_decoded_bytes.decode("utf-8")
|
|
@@ -0,0 +1,57 @@
|
|
|
1
|
+
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
|
+
|
|
3
|
+
from KekikStream.Core import ExtractorBase, ExtractResult
|
|
4
|
+
import re
|
|
5
|
+
|
|
6
|
+
class SetPlay(ExtractorBase):
|
|
7
|
+
name = "SetPlay"
|
|
8
|
+
main_url = "https://setplay.cfd"
|
|
9
|
+
|
|
10
|
+
async def extract(self, url, referer=None) -> ExtractResult:
|
|
11
|
+
ext_ref = referer or ""
|
|
12
|
+
|
|
13
|
+
if referer:
|
|
14
|
+
self.httpx.headers.update({"Referer": referer})
|
|
15
|
+
|
|
16
|
+
istek = await self.httpx.get(url)
|
|
17
|
+
istek.raise_for_status()
|
|
18
|
+
|
|
19
|
+
# videoUrl çıkar
|
|
20
|
+
video_url_match = re.search(r'videoUrl":"([^",]+)"', istek.text)
|
|
21
|
+
if not video_url_match:
|
|
22
|
+
raise ValueError("videoUrl not found")
|
|
23
|
+
video_url = video_url_match[1].replace("\\", "")
|
|
24
|
+
|
|
25
|
+
# videoServer çıkar
|
|
26
|
+
video_server_match = re.search(r'videoServer":"([^",]+)"', istek.text)
|
|
27
|
+
if not video_server_match:
|
|
28
|
+
raise ValueError("videoServer not found")
|
|
29
|
+
video_server = video_server_match[1]
|
|
30
|
+
|
|
31
|
+
# title çıkar (opsiyonel)
|
|
32
|
+
title_match = re.search(r'title":"([^",]+)"', istek.text)
|
|
33
|
+
title_base = title_match[1].split(".")[-1] if title_match else "Unknown"
|
|
34
|
+
|
|
35
|
+
# partKey logic
|
|
36
|
+
from urllib.parse import urlparse, parse_qs
|
|
37
|
+
parsed = urlparse(url)
|
|
38
|
+
params = parse_qs(parsed.query)
|
|
39
|
+
part_key = params.get("partKey", [""])[0]
|
|
40
|
+
|
|
41
|
+
name_suffix = ""
|
|
42
|
+
if "turkcedublaj" in part_key.lower():
|
|
43
|
+
name_suffix = "Dublaj"
|
|
44
|
+
elif "turkcealtyazi" in part_key.lower():
|
|
45
|
+
name_suffix = "Altyazı"
|
|
46
|
+
else:
|
|
47
|
+
name_suffix = title_base
|
|
48
|
+
|
|
49
|
+
# M3U8 link oluştur
|
|
50
|
+
m3u_link = f"{self.main_url}{video_url}?s={video_server}"
|
|
51
|
+
|
|
52
|
+
return ExtractResult(
|
|
53
|
+
name = f"{self.name} - {name_suffix}",
|
|
54
|
+
url = m3u_link,
|
|
55
|
+
referer = url,
|
|
56
|
+
subtitles = []
|
|
57
|
+
)
|
|
@@ -0,0 +1,45 @@
|
|
|
1
|
+
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
|
+
|
|
3
|
+
from KekikStream.Core import ExtractorBase, ExtractResult
|
|
4
|
+
from urllib.parse import urlparse, parse_qs
|
|
5
|
+
import re
|
|
6
|
+
|
|
7
|
+
class SetPrime(ExtractorBase):
|
|
8
|
+
name = "SetPrime"
|
|
9
|
+
main_url = "https://setplay.site"
|
|
10
|
+
|
|
11
|
+
async def extract(self, url, referer=None) -> ExtractResult:
|
|
12
|
+
# URL parsing
|
|
13
|
+
parsed = urlparse(url)
|
|
14
|
+
params = parse_qs(parsed.query)
|
|
15
|
+
part_key = params.get("partKey", [""])[0].upper()
|
|
16
|
+
clean_url = url.split("?partKey=")[0]
|
|
17
|
+
|
|
18
|
+
# POST URL: embed?i= -> embed/get?i=
|
|
19
|
+
post_url = clean_url.replace("embed?i=", "embed/get?i=")
|
|
20
|
+
|
|
21
|
+
response = await self.httpx.post(
|
|
22
|
+
url = post_url,
|
|
23
|
+
headers = {"Referer": clean_url}
|
|
24
|
+
)
|
|
25
|
+
response.raise_for_status()
|
|
26
|
+
|
|
27
|
+
# Links parse
|
|
28
|
+
links_match = re.search(r'Links":\["([^"\]]+)"', response.text)
|
|
29
|
+
if not links_match:
|
|
30
|
+
raise ValueError("Links not found in SetPrime response")
|
|
31
|
+
|
|
32
|
+
link_suffix = links_match.group(1)
|
|
33
|
+
if not link_suffix.startswith("/"):
|
|
34
|
+
raise ValueError("Links not valid (must start with /)")
|
|
35
|
+
|
|
36
|
+
m3u_link = f"{self.main_url}{link_suffix}"
|
|
37
|
+
|
|
38
|
+
display_name = f"{self.name} - {part_key}" if part_key else self.name
|
|
39
|
+
|
|
40
|
+
return ExtractResult(
|
|
41
|
+
name = display_name,
|
|
42
|
+
url = m3u_link,
|
|
43
|
+
referer = clean_url,
|
|
44
|
+
subtitles = []
|
|
45
|
+
)
|
KekikStream/Extractors/SibNet.py
CHANGED
|
@@ -0,0 +1,34 @@
|
|
|
1
|
+
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
|
+
|
|
3
|
+
from KekikStream.Core import ExtractorBase, ExtractResult, Subtitle
|
|
4
|
+
import re, json
|
|
5
|
+
|
|
6
|
+
class TurkeyPlayer(ExtractorBase):
|
|
7
|
+
name = "TurkeyPlayer"
|
|
8
|
+
main_url = "https://watch.turkeyplayer.com/"
|
|
9
|
+
|
|
10
|
+
async def extract(self, url: str, referer: str = None) -> ExtractResult:
|
|
11
|
+
if referer:
|
|
12
|
+
self.httpx.headers.update({"Referer": referer})
|
|
13
|
+
|
|
14
|
+
istek = await self.httpx.get(url)
|
|
15
|
+
page_content = istek.text
|
|
16
|
+
|
|
17
|
+
video_json_match = re.search(r'var\s+video\s*=\s*(\{.*?\});', page_content, re.DOTALL)
|
|
18
|
+
if not video_json_match:
|
|
19
|
+
raise ValueError("TurkeyPlayer: Video JSON bulunamadı")
|
|
20
|
+
|
|
21
|
+
video_data = json.loads(video_json_match.group(1))
|
|
22
|
+
|
|
23
|
+
video_id = video_data.get("id")
|
|
24
|
+
video_md5 = video_data.get("md5")
|
|
25
|
+
|
|
26
|
+
master_url = f"https://watch.turkeyplayer.com/m3u8/8/{video_md5}/master.txt?s=1&id={video_id}&cache=1"
|
|
27
|
+
|
|
28
|
+
return ExtractResult(
|
|
29
|
+
name = self.name,
|
|
30
|
+
url = master_url,
|
|
31
|
+
referer = referer or url,
|
|
32
|
+
user_agent = self.httpx.headers.get("User-Agent", ""),
|
|
33
|
+
subtitles = []
|
|
34
|
+
)
|
|
@@ -0,0 +1,72 @@
|
|
|
1
|
+
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
|
+
|
|
3
|
+
from KekikStream.Core import ExtractorBase, ExtractResult, Subtitle
|
|
4
|
+
from Kekik.Sifreleme import Packer
|
|
5
|
+
from parsel import Selector
|
|
6
|
+
import re
|
|
7
|
+
|
|
8
|
+
class VidHide(ExtractorBase):
|
|
9
|
+
name = "VidHide"
|
|
10
|
+
main_url = "https://vidhidepro.com"
|
|
11
|
+
|
|
12
|
+
def get_embed_url(self, url: str) -> str:
|
|
13
|
+
if "/d/" in url:
|
|
14
|
+
return url.replace("/d/", "/v/")
|
|
15
|
+
elif "/download/" in url:
|
|
16
|
+
return url.replace("/download/", "/v/")
|
|
17
|
+
elif "/file/" in url:
|
|
18
|
+
return url.replace("/file/", "/v/")
|
|
19
|
+
else:
|
|
20
|
+
return url.replace("/f/", "/v/")
|
|
21
|
+
|
|
22
|
+
async def extract(self, url: str, referer: str = None) -> ExtractResult:
|
|
23
|
+
if referer:
|
|
24
|
+
self.httpx.headers.update({"Referer": referer})
|
|
25
|
+
|
|
26
|
+
self.httpx.headers.update({
|
|
27
|
+
"Sec-Fetch-Dest" : "empty",
|
|
28
|
+
"Sec-Fetch-Mode" : "cors",
|
|
29
|
+
"Sec-Fetch-Site" : "cross-site",
|
|
30
|
+
"Origin" : self.main_url,
|
|
31
|
+
})
|
|
32
|
+
|
|
33
|
+
embed_url = self.get_embed_url(url)
|
|
34
|
+
istek = await self.httpx.get(embed_url)
|
|
35
|
+
response = istek.text
|
|
36
|
+
|
|
37
|
+
script = None
|
|
38
|
+
if "eval(function" in response:
|
|
39
|
+
try:
|
|
40
|
+
unpacked = Packer.unpack(response)
|
|
41
|
+
if "var links" in unpacked:
|
|
42
|
+
script = unpacked.split("var links")[1]
|
|
43
|
+
else:
|
|
44
|
+
script = unpacked
|
|
45
|
+
except Exception:
|
|
46
|
+
pass
|
|
47
|
+
|
|
48
|
+
if not script:
|
|
49
|
+
if matches := re.search(r'sources:\s*(\[.*?\])', response, re.DOTALL):
|
|
50
|
+
script = matches.group(1)
|
|
51
|
+
|
|
52
|
+
m3u8_url = None
|
|
53
|
+
if script:
|
|
54
|
+
# m3u8 urls could be prefixed by 'file:', 'hls2:' or 'hls4:', so we just match ':'
|
|
55
|
+
if match := re.search(r':\s*"([^"]*?m3u8[^"]*?)"', script):
|
|
56
|
+
m3u8_url = match.group(1)
|
|
57
|
+
|
|
58
|
+
if not m3u8_url:
|
|
59
|
+
# Fallback direct search in response if unpacking failed or structure changed
|
|
60
|
+
if match := re.search(r'file:"(.*?\.m3u8.*?)"', response):
|
|
61
|
+
m3u8_url = match.group(1)
|
|
62
|
+
|
|
63
|
+
if not m3u8_url:
|
|
64
|
+
raise ValueError(f"VidHide: Video URL bulunamadı. {url}")
|
|
65
|
+
|
|
66
|
+
return ExtractResult(
|
|
67
|
+
name = self.name,
|
|
68
|
+
url = self.fix_url(m3u8_url),
|
|
69
|
+
referer = f"{self.main_url}/",
|
|
70
|
+
user_agent = self.httpx.headers.get("User-Agent", ""),
|
|
71
|
+
subtitles = []
|
|
72
|
+
)
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
# ! https://github.com/recloudstream/cloudstream/blob/master/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/Vidmoly.kt
|
|
3
3
|
|
|
4
4
|
from KekikStream.Core import ExtractorBase, ExtractResult, Subtitle
|
|
5
|
-
import
|
|
5
|
+
from parsel import Selector
|
|
6
|
+
import re, contextlib, json
|
|
6
7
|
|
|
7
8
|
class VidMoly(ExtractorBase):
|
|
8
9
|
name = "VidMoly"
|
|
@@ -13,29 +14,30 @@ class VidMoly(ExtractorBase):
|
|
|
13
14
|
self.httpx.headers.update({"Referer": referer})
|
|
14
15
|
|
|
15
16
|
self.httpx.headers.update({
|
|
16
|
-
"User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
|
|
17
17
|
"Sec-Fetch-Dest" : "iframe",
|
|
18
18
|
})
|
|
19
19
|
|
|
20
20
|
if self.main_url.endswith(".me"):
|
|
21
|
-
self.main_url = self.main_url.replace(".me", ".
|
|
22
|
-
url
|
|
21
|
+
self.main_url = self.main_url.replace(".me", ".net")
|
|
22
|
+
url = url.replace(".me", ".net")
|
|
23
23
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
24
|
+
response = await self.httpx.get(url)
|
|
25
|
+
if "Select number" in response.text:
|
|
26
|
+
secici = Selector(response.text)
|
|
27
|
+
response = await self.httpx.post(
|
|
28
|
+
url = url,
|
|
29
|
+
data = {
|
|
30
|
+
"op" : secici.css("input[name='op']::attr(value)").get(),
|
|
31
|
+
"file_code" : secici.css("input[name='file_code']::attr(value)").get(),
|
|
32
|
+
"answer" : secici.css("div.vhint b::text").get(),
|
|
33
|
+
"ts" : secici.css("input[name='ts']::attr(value)").get(),
|
|
34
|
+
"nonce" : secici.css("input[name='nonce']::attr(value)").get(),
|
|
35
|
+
"ctok" : secici.css("input[name='ctok']::attr(value)").get()
|
|
36
|
+
}
|
|
37
|
+
)
|
|
28
38
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
attempts += 1
|
|
32
|
-
response = await self.httpx.get(embed_url)
|
|
33
|
-
response.raise_for_status()
|
|
34
|
-
|
|
35
|
-
script_match = re.search(r"sources:\s*\[(.*?)\],", response.text, re.DOTALL)
|
|
36
|
-
script_content = script_match[1] if script_match else None
|
|
37
|
-
if not script_content:
|
|
38
|
-
await asyncio.sleep(0.5)
|
|
39
|
+
script_match = re.search(r"sources:\s*\[(.*?)\],", response.text, re.DOTALL)
|
|
40
|
+
script_content = script_match[1] if script_match else None
|
|
39
41
|
|
|
40
42
|
if not script_content:
|
|
41
43
|
raise ValueError("Gerekli script bulunamadı.")
|
|
@@ -74,7 +76,6 @@ class VidMoly(ExtractorBase):
|
|
|
74
76
|
if not video_url:
|
|
75
77
|
raise ValueError("Video URL bulunamadı.")
|
|
76
78
|
|
|
77
|
-
await self.close()
|
|
78
79
|
return ExtractResult(
|
|
79
80
|
name = self.name,
|
|
80
81
|
url = video_url,
|
|
@@ -0,0 +1,89 @@
|
|
|
1
|
+
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
|
+
|
|
3
|
+
from KekikStream.Core import ExtractorBase, ExtractResult, Subtitle
|
|
4
|
+
import re
|
|
5
|
+
|
|
6
|
+
class VidPapi(ExtractorBase):
|
|
7
|
+
name = "VidApi"
|
|
8
|
+
main_url = "https://vidpapi.xyz"
|
|
9
|
+
|
|
10
|
+
async def extract(self, url, referer=None) -> ExtractResult:
|
|
11
|
+
ext_ref = referer or ""
|
|
12
|
+
|
|
13
|
+
# URL parsing
|
|
14
|
+
if "video/" in url:
|
|
15
|
+
vid_id = url.split("video/")[-1]
|
|
16
|
+
else:
|
|
17
|
+
vid_id = url.split("?data=")[-1]
|
|
18
|
+
|
|
19
|
+
# 1. Altyazıları çek
|
|
20
|
+
sub_url = f"{self.main_url}/player/index.php?data={vid_id}"
|
|
21
|
+
sub_headers = {
|
|
22
|
+
"Content-Type" : "application/x-www-form-urlencoded; charset=UTF-8",
|
|
23
|
+
"X-Requested-With" : "XMLHttpRequest",
|
|
24
|
+
"User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:137.0) Gecko/20100101 Firefox/137.0",
|
|
25
|
+
"Referer" : ext_ref or "https://kultfilmler.pro/"
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
subtitles = []
|
|
29
|
+
try:
|
|
30
|
+
sub_istek = await self.httpx.post(
|
|
31
|
+
url = sub_url,
|
|
32
|
+
headers = sub_headers,
|
|
33
|
+
data = {"hash": vid_id, "r": "https://kultfilmler.pro/"}
|
|
34
|
+
)
|
|
35
|
+
|
|
36
|
+
subtitle_match = re.search(r'var playerjsSubtitle = "([^"]*)"', sub_istek.text, re.IGNORECASE)
|
|
37
|
+
if subtitle_match and subtitle_match.group(1):
|
|
38
|
+
raw_subs = subtitle_match.group(1)
|
|
39
|
+
|
|
40
|
+
found_subs = re.findall(r'\[(.*?)\](.*?)(?:,|$)', raw_subs)
|
|
41
|
+
for lang, sub_link in found_subs:
|
|
42
|
+
lang = lang.strip()
|
|
43
|
+
if "Türkçe" in lang:
|
|
44
|
+
lang_code = "tr"
|
|
45
|
+
lang_name = "Turkish"
|
|
46
|
+
elif "İngilizce" in lang:
|
|
47
|
+
lang_code = "en"
|
|
48
|
+
lang_name = "English"
|
|
49
|
+
else:
|
|
50
|
+
lang_code = lang[:2].lower()
|
|
51
|
+
lang_name = lang
|
|
52
|
+
|
|
53
|
+
subtitles.append(Subtitle(
|
|
54
|
+
name = lang_name,
|
|
55
|
+
url = sub_link.strip()
|
|
56
|
+
))
|
|
57
|
+
|
|
58
|
+
except Exception as e:
|
|
59
|
+
pass
|
|
60
|
+
|
|
61
|
+
# 2. Videoyu çek
|
|
62
|
+
video_url = f"{self.main_url}/player/index.php?data={vid_id}&do=getVideo"
|
|
63
|
+
video_headers = sub_headers.copy()
|
|
64
|
+
|
|
65
|
+
response = await self.httpx.post(
|
|
66
|
+
url = video_url,
|
|
67
|
+
headers = video_headers,
|
|
68
|
+
data = {"hash": vid_id, "r": "https://kultfilmler.pro/"}
|
|
69
|
+
)
|
|
70
|
+
response.raise_for_status()
|
|
71
|
+
|
|
72
|
+
try:
|
|
73
|
+
video_data = response.json()
|
|
74
|
+
except Exception:
|
|
75
|
+
return None
|
|
76
|
+
|
|
77
|
+
stream_url = video_data.get("securedLink")
|
|
78
|
+
if not stream_url or not stream_url.strip():
|
|
79
|
+
stream_url = video_data.get("videoSource")
|
|
80
|
+
|
|
81
|
+
if not stream_url:
|
|
82
|
+
raise ValueError("No video link found in VidPapi response")
|
|
83
|
+
|
|
84
|
+
return ExtractResult(
|
|
85
|
+
name = self.name,
|
|
86
|
+
url = stream_url,
|
|
87
|
+
referer = ext_ref or self.main_url,
|
|
88
|
+
subtitles = subtitles
|
|
89
|
+
)
|