KekikStream 1.7.1__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/Core/Extractor/ExtractorBase.py +13 -7
- 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 +44 -26
- KekikStream/Core/Media/MediaManager.py +0 -3
- KekikStream/Core/Plugin/PluginBase.py +21 -9
- KekikStream/Core/Plugin/PluginLoader.py +11 -7
- KekikStream/Core/Plugin/PluginModels.py +25 -26
- KekikStream/Core/__init__.py +1 -0
- KekikStream/Extractors/CloseLoad.py +4 -5
- KekikStream/Extractors/ContentX.py +4 -6
- 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 +3 -4
- KekikStream/Extractors/MixPlayHD.py +2 -3
- KekikStream/Extractors/MixTiger.py +57 -0
- KekikStream/Extractors/MolyStream.py +5 -5
- KekikStream/Extractors/Odnoklassniki.py +7 -7
- KekikStream/Extractors/{OkRuHTTP.py → Odnoklassniki_.py} +5 -1
- KekikStream/Extractors/PeaceMakerst.py +4 -5
- KekikStream/Extractors/{HDStreamAble.py → PeaceMakerst_.py} +1 -1
- KekikStream/Extractors/PixelDrain.py +1 -2
- KekikStream/Extractors/PlayerFilmIzle.py +62 -0
- KekikStream/Extractors/RapidVid.py +2 -3
- KekikStream/Extractors/RapidVid_.py +7 -0
- KekikStream/Extractors/SetPlay.py +57 -0
- KekikStream/Extractors/SetPrime.py +45 -0
- KekikStream/Extractors/SibNet.py +2 -3
- KekikStream/Extractors/Sobreatsesuyp.py +4 -5
- KekikStream/Extractors/TRsTX.py +4 -5
- KekikStream/Extractors/TauVideo.py +2 -3
- KekikStream/Extractors/TurboImgz.py +2 -3
- KekikStream/Extractors/TurkeyPlayer.py +34 -0
- KekikStream/Extractors/VidHide.py +72 -0
- KekikStream/Extractors/VidMoly.py +4 -5
- KekikStream/Extractors/{VidMolyMe.py → VidMoly_.py} +1 -1
- KekikStream/Extractors/VidMoxy.py +2 -3
- KekikStream/Extractors/VidPapi.py +89 -0
- KekikStream/Extractors/VideoSeyred.py +3 -4
- KekikStream/Extractors/YTDLP.py +177 -0
- KekikStream/Extractors/YildizKisaFilm.py +41 -0
- KekikStream/Plugins/DiziBox.py +18 -23
- KekikStream/Plugins/DiziPal.py +16 -16
- KekikStream/Plugins/DiziYou.py +48 -23
- KekikStream/Plugins/Dizilla.py +47 -32
- KekikStream/Plugins/FilmBip.py +145 -0
- KekikStream/Plugins/FilmMakinesi.py +6 -8
- KekikStream/Plugins/FilmModu.py +9 -9
- KekikStream/Plugins/FullHDFilm.py +164 -0
- KekikStream/Plugins/FullHDFilmizlesene.py +4 -8
- KekikStream/Plugins/HDFilmCehennemi.py +15 -19
- KekikStream/Plugins/JetFilmizle.py +67 -49
- KekikStream/Plugins/KultFilmler.py +219 -0
- KekikStream/Plugins/RecTV.py +18 -22
- KekikStream/Plugins/RoketDizi.py +232 -0
- KekikStream/Plugins/SelcukFlix.py +309 -0
- KekikStream/Plugins/SezonlukDizi.py +12 -13
- KekikStream/Plugins/SineWix.py +8 -12
- 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 +7 -11
- KekikStream/__init__.py +34 -24
- KekikStream/requirements.txt +3 -4
- kekikstream-2.0.2.dist-info/METADATA +309 -0
- kekikstream-2.0.2.dist-info/RECORD +82 -0
- 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-1.7.1.dist-info/METADATA +0 -109
- kekikstream-1.7.1.dist-info/RECORD +0 -63
- {kekikstream-1.7.1.dist-info → kekikstream-2.0.2.dist-info}/WHEEL +0 -0
- {kekikstream-1.7.1.dist-info → kekikstream-2.0.2.dist-info}/entry_points.txt +0 -0
- {kekikstream-1.7.1.dist-info → kekikstream-2.0.2.dist-info}/licenses/LICENSE +0 -0
- {kekikstream-1.7.1.dist-info → kekikstream-2.0.2.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,40 @@
|
|
|
1
|
+
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
|
+
|
|
3
|
+
from KekikStream.Extractors.ContentX import ContentX
|
|
4
|
+
|
|
5
|
+
# DPlayer82 Family - https://dplayer82.site subdomains
|
|
6
|
+
class SNDPlayer(ContentX):
|
|
7
|
+
name = "SNDPlayer"
|
|
8
|
+
main_url = "https://sn.dplayer82.site"
|
|
9
|
+
|
|
10
|
+
class FourDPlayer(ContentX):
|
|
11
|
+
name = "FourDPlayer"
|
|
12
|
+
main_url = "https://four.dplayer82.site"
|
|
13
|
+
|
|
14
|
+
class ORGDPlayer(ContentX):
|
|
15
|
+
name = "ORGDPlayer"
|
|
16
|
+
main_url = "https://org.dplayer82.site"
|
|
17
|
+
|
|
18
|
+
# Hotlinger
|
|
19
|
+
class Hotlinger(ContentX):
|
|
20
|
+
name = "Hotlinger"
|
|
21
|
+
main_url = "https://hotlinger.com"
|
|
22
|
+
|
|
23
|
+
# Pichive Family
|
|
24
|
+
class Pichive(ContentX):
|
|
25
|
+
name = "Pichive"
|
|
26
|
+
main_url = "https://pichive.me"
|
|
27
|
+
|
|
28
|
+
class FourPichive(ContentX):
|
|
29
|
+
name = "FourPichive"
|
|
30
|
+
main_url = "https://four.pichive.me"
|
|
31
|
+
|
|
32
|
+
# PlayRu Family
|
|
33
|
+
class FourPlayRu(ContentX):
|
|
34
|
+
name = "FourPlayRu"
|
|
35
|
+
main_url = "https://four.playru.net"
|
|
36
|
+
|
|
37
|
+
# CX Family
|
|
38
|
+
class FourCX(ContentX):
|
|
39
|
+
name = "FourCX"
|
|
40
|
+
main_url = "https://four.contentx.me"
|
|
@@ -0,0 +1,38 @@
|
|
|
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 DzenRu(ExtractorBase):
|
|
7
|
+
name = "DzenRu"
|
|
8
|
+
main_url = "https://dzen.ru"
|
|
9
|
+
|
|
10
|
+
async def extract(self, url, referer=None) -> ExtractResult:
|
|
11
|
+
video_key = url.split("/")[-1]
|
|
12
|
+
video_url = f"{self.main_url}/embed/{video_key}"
|
|
13
|
+
|
|
14
|
+
if referer:
|
|
15
|
+
self.httpx.headers.update({"Referer": referer})
|
|
16
|
+
|
|
17
|
+
istek = await self.httpx.get(video_url)
|
|
18
|
+
istek.raise_for_status()
|
|
19
|
+
|
|
20
|
+
# okcdn.ru linklerini bul
|
|
21
|
+
matches = re.findall(r'https://vd\d+\.okcdn\.ru/\?[^"\'\\\s]+', istek.text)
|
|
22
|
+
|
|
23
|
+
if not matches:
|
|
24
|
+
raise ValueError("DzenRu video link not found")
|
|
25
|
+
|
|
26
|
+
# Benzersiz linkleri al, son kaliteyi kullan
|
|
27
|
+
unique_links = list(set(matches))
|
|
28
|
+
best_link = unique_links[-1] if unique_links else None
|
|
29
|
+
|
|
30
|
+
if not best_link:
|
|
31
|
+
raise ValueError("No valid video URL found")
|
|
32
|
+
|
|
33
|
+
return ExtractResult(
|
|
34
|
+
name = self.name,
|
|
35
|
+
url = best_link,
|
|
36
|
+
referer = self.main_url,
|
|
37
|
+
subtitles = []
|
|
38
|
+
)
|
|
@@ -0,0 +1,53 @@
|
|
|
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
|
+
from urllib.parse import urlparse, parse_qs
|
|
6
|
+
|
|
7
|
+
class ExPlay(ExtractorBase):
|
|
8
|
+
name = "ExPlay"
|
|
9
|
+
main_url = "https://explay.store"
|
|
10
|
+
|
|
11
|
+
async def extract(self, url, referer=None) -> ExtractResult:
|
|
12
|
+
ext_ref = referer or ""
|
|
13
|
+
|
|
14
|
+
# URL parsing for partKey
|
|
15
|
+
parsed = urlparse(url)
|
|
16
|
+
params = parse_qs(parsed.query)
|
|
17
|
+
part_key = params.get("partKey", [""])[0]
|
|
18
|
+
clean_url = url.split("?partKey=")[0]
|
|
19
|
+
|
|
20
|
+
if referer:
|
|
21
|
+
self.httpx.headers.update({"Referer": referer})
|
|
22
|
+
|
|
23
|
+
istek = await self.httpx.get(clean_url)
|
|
24
|
+
istek.raise_for_status()
|
|
25
|
+
|
|
26
|
+
# videoUrl çıkar
|
|
27
|
+
video_url_match = re.search(r'videoUrl":"([^",]+)"', istek.text)
|
|
28
|
+
if not video_url_match:
|
|
29
|
+
raise ValueError("videoUrl not found")
|
|
30
|
+
video_url = video_url_match[1].replace("\\", "")
|
|
31
|
+
|
|
32
|
+
# videoServer çıkar
|
|
33
|
+
video_server_match = re.search(r'videoServer":"([^",]+)"', istek.text)
|
|
34
|
+
if not video_server_match:
|
|
35
|
+
raise ValueError("videoServer not found")
|
|
36
|
+
video_server = video_server_match[1]
|
|
37
|
+
|
|
38
|
+
# title çıkar
|
|
39
|
+
title_match = re.search(r'title":"([^",]+)"', istek.text)
|
|
40
|
+
title = title_match[1].split(".")[-1] if title_match else "Unknown"
|
|
41
|
+
|
|
42
|
+
if part_key and "turkce" in part_key.lower():
|
|
43
|
+
title = part_key # Or nicer formatting like SetPlay
|
|
44
|
+
|
|
45
|
+
# M3U8 link oluştur
|
|
46
|
+
m3u_link = f"{self.main_url}{video_url}?s={video_server}"
|
|
47
|
+
|
|
48
|
+
return ExtractResult(
|
|
49
|
+
name = f"{self.name} - {title}",
|
|
50
|
+
url = m3u_link,
|
|
51
|
+
referer = clean_url,
|
|
52
|
+
subtitles = []
|
|
53
|
+
)
|
|
@@ -0,0 +1,60 @@
|
|
|
1
|
+
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
|
+
|
|
3
|
+
from KekikStream.Core import ExtractorBase, ExtractResult
|
|
4
|
+
from Kekik.Sifreleme import Packer
|
|
5
|
+
import re
|
|
6
|
+
|
|
7
|
+
class FirePlayer(ExtractorBase):
|
|
8
|
+
name = "FirePlayer"
|
|
9
|
+
main_url = "https://Player.filmizle.in"
|
|
10
|
+
|
|
11
|
+
def can_handle_url(self, url: str) -> bool:
|
|
12
|
+
return "filmizle.in" in url or "fireplayer" in url.lower()
|
|
13
|
+
|
|
14
|
+
async def extract(self, url: str, referer: str = None) -> ExtractResult:
|
|
15
|
+
if not referer:
|
|
16
|
+
referer = "https://sinezy.site/"
|
|
17
|
+
|
|
18
|
+
headers = {
|
|
19
|
+
"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",
|
|
20
|
+
"Referer": referer
|
|
21
|
+
}
|
|
22
|
+
|
|
23
|
+
istek = await self.httpx.get(url, headers=headers)
|
|
24
|
+
|
|
25
|
+
# Unpack usage similar to VidMoxy / suggestion
|
|
26
|
+
# Find the packed code block
|
|
27
|
+
match = re.search(r'(eval\(function\(p,a,c,k,e,d\)[\s\S]+?)\s*</script>', istek.text)
|
|
28
|
+
if match:
|
|
29
|
+
packed_code = match.group(1)
|
|
30
|
+
unpacked = Packer.unpack(packed_code)
|
|
31
|
+
else:
|
|
32
|
+
unpacked = istek.text
|
|
33
|
+
|
|
34
|
+
# Normalize escaped slashes
|
|
35
|
+
unpacked = unpacked.replace(r"\/", "/")
|
|
36
|
+
|
|
37
|
+
video_url = None
|
|
38
|
+
|
|
39
|
+
# Look for .mp4 or .m3u8 urls directly first
|
|
40
|
+
url_match = re.search(r'(https?://[^"\'\s]+\.(?:mp4|m3u8))', unpacked)
|
|
41
|
+
if url_match:
|
|
42
|
+
video_url = url_match.group(1)
|
|
43
|
+
|
|
44
|
+
if not video_url:
|
|
45
|
+
# Fallback: find all 'file': '...' and pick best
|
|
46
|
+
files = re.findall(r'file\s*:\s*["\']([^"\']+)["\']', unpacked)
|
|
47
|
+
for f in files:
|
|
48
|
+
if f.strip() and not f.endswith(".jpg") and not f.endswith(".png") and not f.endswith(".vtt"):
|
|
49
|
+
video_url = f
|
|
50
|
+
break
|
|
51
|
+
|
|
52
|
+
if not video_url:
|
|
53
|
+
raise ValueError("Could not find video URL in unpacked content")
|
|
54
|
+
|
|
55
|
+
return ExtractResult(
|
|
56
|
+
name = self.name,
|
|
57
|
+
url = video_url,
|
|
58
|
+
referer = url,
|
|
59
|
+
user_agent = headers.get("User-Agent", "")
|
|
60
|
+
)
|
|
@@ -0,0 +1,41 @@
|
|
|
1
|
+
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
|
+
|
|
3
|
+
from KekikStream.Core import ExtractorBase, ExtractResult
|
|
4
|
+
|
|
5
|
+
class HDPlayerSystem(ExtractorBase):
|
|
6
|
+
name = "HDPlayerSystem"
|
|
7
|
+
main_url = "https://hdplayersystem.com"
|
|
8
|
+
|
|
9
|
+
async def extract(self, url, referer=None) -> ExtractResult:
|
|
10
|
+
ext_ref = referer or ""
|
|
11
|
+
|
|
12
|
+
if "video/" in url:
|
|
13
|
+
vid_id = url.split("video/")[-1]
|
|
14
|
+
else:
|
|
15
|
+
vid_id = url.split("?data=")[-1]
|
|
16
|
+
|
|
17
|
+
post_url = f"{self.main_url}/player/index.php?data={vid_id}&do=getVideo"
|
|
18
|
+
|
|
19
|
+
response = await self.httpx.post(
|
|
20
|
+
url = post_url,
|
|
21
|
+
data = {"hash": vid_id, "r": ext_ref},
|
|
22
|
+
headers = {
|
|
23
|
+
"Referer" : ext_ref,
|
|
24
|
+
"Content-Type" : "application/x-www-form-urlencoded; charset=UTF-8",
|
|
25
|
+
"X-Requested-With" : "XMLHttpRequest"
|
|
26
|
+
}
|
|
27
|
+
)
|
|
28
|
+
response.raise_for_status()
|
|
29
|
+
|
|
30
|
+
video_data = response.json()
|
|
31
|
+
m3u_link = video_data.get("securedLink")
|
|
32
|
+
|
|
33
|
+
if not m3u_link:
|
|
34
|
+
raise ValueError("securedLink not found in response")
|
|
35
|
+
|
|
36
|
+
return ExtractResult(
|
|
37
|
+
name = self.name,
|
|
38
|
+
url = m3u_link,
|
|
39
|
+
referer = url,
|
|
40
|
+
subtitles = []
|
|
41
|
+
)
|
|
@@ -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, Subtitle
|
|
4
|
+
import re, json
|
|
5
|
+
|
|
6
|
+
class JetTv(ExtractorBase):
|
|
7
|
+
name = "JetTv"
|
|
8
|
+
main_url = "https://jetv.xyz"
|
|
9
|
+
|
|
10
|
+
async def extract(self, url: str, referer: str = None) -> ExtractResult:
|
|
11
|
+
istek = await self.httpx.get(url)
|
|
12
|
+
document = istek.text
|
|
13
|
+
|
|
14
|
+
# 1. Yöntem: API üzerinden alma
|
|
15
|
+
master_url = ""
|
|
16
|
+
final_ref = f"{self.main_url}/"
|
|
17
|
+
|
|
18
|
+
if "id=" in url:
|
|
19
|
+
vid_id = url.split("id=")[-1]
|
|
20
|
+
api_url = f"https://jetv.xyz/apollo/get_video.php?id={vid_id}"
|
|
21
|
+
try:
|
|
22
|
+
# Referer olarak video sayfasının kendisi gönderilmeli
|
|
23
|
+
api_resp = await self.httpx.get(api_url, headers={"Referer": url})
|
|
24
|
+
api_json = api_resp.json()
|
|
25
|
+
|
|
26
|
+
if api_json.get("success"):
|
|
27
|
+
master_url = api_json.get("masterUrl", "")
|
|
28
|
+
final_ref = api_json.get("referrerUrl") or final_ref
|
|
29
|
+
except Exception:
|
|
30
|
+
pass
|
|
31
|
+
|
|
32
|
+
# 2. Yöntem: Regex Fallback
|
|
33
|
+
if not master_url:
|
|
34
|
+
if match := re.search(r"file: '([^']*)'", document, re.IGNORECASE):
|
|
35
|
+
master_url = match.group(1)
|
|
36
|
+
|
|
37
|
+
if not master_url:
|
|
38
|
+
raise ValueError(f"JetTv: Video kaynağı bulunamadı. {url}")
|
|
39
|
+
|
|
40
|
+
return ExtractResult(
|
|
41
|
+
name = self.name,
|
|
42
|
+
url = master_url,
|
|
43
|
+
referer = final_ref,
|
|
44
|
+
subtitles = []
|
|
45
|
+
)
|
KekikStream/Extractors/MailRu.py
CHANGED
|
@@ -11,9 +11,9 @@ class MailRuExtractor(ExtractorBase):
|
|
|
11
11
|
video_meta_url = f"{self.main_url}/+/video/meta/{vid_id}"
|
|
12
12
|
|
|
13
13
|
if referer:
|
|
14
|
-
self.
|
|
14
|
+
self.httpx.headers.update({"Referer": referer})
|
|
15
15
|
|
|
16
|
-
istek = await self.
|
|
16
|
+
istek = await self.httpx.get(video_meta_url)
|
|
17
17
|
istek.raise_for_status()
|
|
18
18
|
|
|
19
19
|
video_key = istek.cookies.get("video_key")
|
|
@@ -34,6 +34,5 @@ class MailRuExtractor(ExtractorBase):
|
|
|
34
34
|
name = self.name,
|
|
35
35
|
url = video_url,
|
|
36
36
|
referer = self.main_url,
|
|
37
|
-
headers = {"Cookie": f"video_key={video_key}"},
|
|
38
37
|
subtitles = []
|
|
39
|
-
)
|
|
38
|
+
)
|
|
@@ -10,9 +10,9 @@ class MixPlayHD(ExtractorBase):
|
|
|
10
10
|
|
|
11
11
|
async def extract(self, url, referer=None) -> ExtractResult:
|
|
12
12
|
if referer:
|
|
13
|
-
self.
|
|
13
|
+
self.httpx.headers.update({"Referer": referer})
|
|
14
14
|
|
|
15
|
-
istek = await self.
|
|
15
|
+
istek = await self.httpx.get(url)
|
|
16
16
|
istek.raise_for_status()
|
|
17
17
|
|
|
18
18
|
be_player_match = re.search(r"bePlayer\('([^']+)',\s*'(\{[^\}]+\})'\);", istek.text)
|
|
@@ -36,7 +36,6 @@ class MixPlayHD(ExtractorBase):
|
|
|
36
36
|
name = self.name,
|
|
37
37
|
url = video_url_match[1],
|
|
38
38
|
referer = self.main_url,
|
|
39
|
-
headers = {},
|
|
40
39
|
subtitles = []
|
|
41
40
|
)
|
|
42
41
|
else:
|
|
@@ -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
|
+
|
|
5
|
+
class MixTiger(ExtractorBase):
|
|
6
|
+
name = "MixTiger"
|
|
7
|
+
main_url = "https://www.mixtiger.com"
|
|
8
|
+
|
|
9
|
+
async def extract(self, url, referer=None) -> ExtractResult:
|
|
10
|
+
ext_ref = referer or ""
|
|
11
|
+
post_url = f"{url}?do=getVideo"
|
|
12
|
+
vid_id = url.split("video/")[-1] if "video/" in url else ""
|
|
13
|
+
|
|
14
|
+
response = await self.httpx.post(
|
|
15
|
+
url = post_url,
|
|
16
|
+
data = {"hash": vid_id, "r": ext_ref, "s": ""},
|
|
17
|
+
headers = {
|
|
18
|
+
"Referer" : ext_ref,
|
|
19
|
+
"Content-Type" : "application/x-www-form-urlencoded; charset=UTF-8",
|
|
20
|
+
"X-Requested-With" : "XMLHttpRequest"
|
|
21
|
+
}
|
|
22
|
+
)
|
|
23
|
+
response.raise_for_status()
|
|
24
|
+
|
|
25
|
+
video_data = response.json()
|
|
26
|
+
|
|
27
|
+
# videoSrc varsa doğrudan kullan
|
|
28
|
+
if video_data.get("videoSrc"):
|
|
29
|
+
m3u_link = video_data["videoSrc"]
|
|
30
|
+
# videoSources listesi varsa son elemanı al
|
|
31
|
+
elif video_data.get("videoSources"):
|
|
32
|
+
sources = video_data["videoSources"]
|
|
33
|
+
m3u_link = sources[-1].get("file") if sources else None
|
|
34
|
+
else:
|
|
35
|
+
m3u_link = None
|
|
36
|
+
|
|
37
|
+
if not m3u_link:
|
|
38
|
+
raise ValueError("Video URL not found in response")
|
|
39
|
+
|
|
40
|
+
# Recursive extraction check
|
|
41
|
+
try:
|
|
42
|
+
from KekikStream.Core.Extractor.ExtractorManager import ExtractorManager
|
|
43
|
+
# Import inside method to avoid circular dependency
|
|
44
|
+
manager = ExtractorManager()
|
|
45
|
+
if nested_extractor := manager.find_extractor(m3u_link):
|
|
46
|
+
# Use recursive extraction
|
|
47
|
+
return await nested_extractor.extract(m3u_link, referer=final_referer)
|
|
48
|
+
except Exception:
|
|
49
|
+
# If recursion fails, fallback to standard result
|
|
50
|
+
pass
|
|
51
|
+
|
|
52
|
+
return ExtractResult(
|
|
53
|
+
name = self.name,
|
|
54
|
+
url = m3u_link,
|
|
55
|
+
referer = None if "disk.yandex" in m3u_link else ext_ref,
|
|
56
|
+
subtitles = []
|
|
57
|
+
)
|
|
@@ -26,9 +26,9 @@ class MolyStream(ExtractorBase):
|
|
|
26
26
|
]
|
|
27
27
|
|
|
28
28
|
return ExtractResult(
|
|
29
|
-
name
|
|
30
|
-
url
|
|
31
|
-
referer
|
|
32
|
-
|
|
33
|
-
subtitles
|
|
29
|
+
name = self.name,
|
|
30
|
+
url = video,
|
|
31
|
+
referer = video.replace("/sheila", ""),
|
|
32
|
+
user_agent = "Mozilla/5.0 (X11; Linux x86_64; rv:101.0) Gecko/20100101 Firefox/101.0",
|
|
33
|
+
subtitles = subtitles
|
|
34
34
|
)
|
|
@@ -20,7 +20,7 @@ class Odnoklassniki(ExtractorBase):
|
|
|
20
20
|
"Origin" : self.main_url,
|
|
21
21
|
"User-Agent" : "Mozilla/5.0 (X11; Linux x86_64; rv:101.0) Gecko/20100101 Firefox/101.0",
|
|
22
22
|
}
|
|
23
|
-
self.
|
|
23
|
+
self.httpx.headers.update(headers)
|
|
24
24
|
|
|
25
25
|
try:
|
|
26
26
|
istek = await self.fetch_with_redirects(url)
|
|
@@ -82,18 +82,18 @@ class Odnoklassniki(ExtractorBase):
|
|
|
82
82
|
best_video = f"https:{best_video}"
|
|
83
83
|
|
|
84
84
|
return ExtractResult(
|
|
85
|
-
name
|
|
86
|
-
url
|
|
87
|
-
referer
|
|
88
|
-
|
|
89
|
-
subtitles
|
|
85
|
+
name = self.name,
|
|
86
|
+
url = best_video,
|
|
87
|
+
referer = referer,
|
|
88
|
+
user_agent = headers.get("User-Agent", None),
|
|
89
|
+
subtitles = []
|
|
90
90
|
)
|
|
91
91
|
|
|
92
92
|
async def fetch_with_redirects(self, url, max_redirects=5):
|
|
93
93
|
"""Yönlendirmeleri takip eden bir fonksiyon"""
|
|
94
94
|
redirects = 0
|
|
95
95
|
while redirects < max_redirects:
|
|
96
|
-
istek = await self.
|
|
96
|
+
istek = await self.httpx.get(url, follow_redirects=False)
|
|
97
97
|
|
|
98
98
|
if istek.status_code not in [301, 302]:
|
|
99
99
|
break # Yönlendirme yoksa çık
|
|
@@ -9,14 +9,14 @@ class PeaceMakerst(ExtractorBase):
|
|
|
9
9
|
|
|
10
10
|
async def extract(self, url, referer=None) -> ExtractResult:
|
|
11
11
|
if referer:
|
|
12
|
-
self.
|
|
12
|
+
self.httpx.headers.update({"Referer": referer})
|
|
13
13
|
|
|
14
|
-
self.
|
|
14
|
+
self.httpx.headers.update({
|
|
15
15
|
"Content-Type" : "application/x-www-form-urlencoded; charset=UTF-8",
|
|
16
16
|
"X-Requested-With" : "XMLHttpRequest"
|
|
17
17
|
})
|
|
18
18
|
|
|
19
|
-
response = await self.
|
|
19
|
+
response = await self.httpx.post(
|
|
20
20
|
url = f"{url}?do=getVideo",
|
|
21
21
|
data = {
|
|
22
22
|
"hash" : url.split("video/")[-1],
|
|
@@ -33,7 +33,7 @@ class PeaceMakerst(ExtractorBase):
|
|
|
33
33
|
teve2_id = re.search(r"teve2\.com\.tr\\\/embed\\\/(\d+)", response_text)[1]
|
|
34
34
|
teve2_url = f"https://www.teve2.com.tr/action/media/{teve2_id}"
|
|
35
35
|
|
|
36
|
-
teve2_response = await self.
|
|
36
|
+
teve2_response = await self.httpx.get(teve2_url, headers={"Referer": f"https://www.teve2.com.tr/embed/{teve2_id}"})
|
|
37
37
|
teve2_response.raise_for_status()
|
|
38
38
|
teve2_json = teve2_response.json()
|
|
39
39
|
|
|
@@ -53,6 +53,5 @@ class PeaceMakerst(ExtractorBase):
|
|
|
53
53
|
name = self.name,
|
|
54
54
|
url = m3u_link,
|
|
55
55
|
referer = url,
|
|
56
|
-
headers = {},
|
|
57
56
|
subtitles = []
|
|
58
57
|
)
|
|
@@ -9,7 +9,7 @@ class PixelDrain(ExtractorBase):
|
|
|
9
9
|
|
|
10
10
|
async def extract(self, url, referer=None) -> ExtractResult:
|
|
11
11
|
if referer:
|
|
12
|
-
self.
|
|
12
|
+
self.httpx.headers.update({"Referer": referer})
|
|
13
13
|
|
|
14
14
|
pixel_id_match = re.search(r"/u/([^/?]+)|([^\/]+)(?=\?download)", url)
|
|
15
15
|
if not pixel_id_match:
|
|
@@ -23,6 +23,5 @@ class PixelDrain(ExtractorBase):
|
|
|
23
23
|
name = f"{self.name} - {pixel_id}",
|
|
24
24
|
url = download_link,
|
|
25
25
|
referer = referer_link,
|
|
26
|
-
headers = {},
|
|
27
26
|
subtitles = []
|
|
28
27
|
)
|
|
@@ -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
|
+
)
|
|
@@ -10,9 +10,9 @@ class RapidVid(ExtractorBase):
|
|
|
10
10
|
|
|
11
11
|
async def extract(self, url, referer=None) -> ExtractResult:
|
|
12
12
|
if referer:
|
|
13
|
-
self.
|
|
13
|
+
self.httpx.headers.update({"Referer": referer})
|
|
14
14
|
|
|
15
|
-
istek = await self.
|
|
15
|
+
istek = await self.httpx.get(url)
|
|
16
16
|
istek.raise_for_status()
|
|
17
17
|
|
|
18
18
|
subtitles = []
|
|
@@ -49,7 +49,6 @@ class RapidVid(ExtractorBase):
|
|
|
49
49
|
name = self.name,
|
|
50
50
|
url = decoded_url,
|
|
51
51
|
referer = self.main_url,
|
|
52
|
-
headers = {},
|
|
53
52
|
subtitles = subtitles
|
|
54
53
|
)
|
|
55
54
|
|
|
@@ -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
|
+
)
|