KekikStream 2.3.9__py3-none-any.whl → 2.5.4__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- KekikStream/Core/Extractor/ExtractorBase.py +3 -2
- KekikStream/Core/Extractor/ExtractorLoader.py +8 -14
- KekikStream/Core/HTMLHelper.py +120 -49
- KekikStream/Core/Plugin/PluginBase.py +35 -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.4.dist-info}/METADATA +1 -1
- kekikstream-2.5.4.dist-info/RECORD +99 -0
- {kekikstream-2.3.9.dist-info → kekikstream-2.5.4.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.4.dist-info}/entry_points.txt +0 -0
- {kekikstream-2.3.9.dist-info → kekikstream-2.5.4.dist-info}/licenses/LICENSE +0 -0
- {kekikstream-2.3.9.dist-info → kekikstream-2.5.4.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,58 @@
|
|
|
1
|
+
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
|
+
|
|
3
|
+
from KekikStream.Core import ExtractorBase, ExtractResult, HTMLHelper, Subtitle
|
|
4
|
+
from urllib.parse import quote
|
|
5
|
+
import re
|
|
6
|
+
|
|
7
|
+
class Videostr(ExtractorBase):
|
|
8
|
+
name = "Videostr"
|
|
9
|
+
main_url = "https://videostr.net"
|
|
10
|
+
|
|
11
|
+
async def extract(self, url: str, referer: str = None) -> ExtractResult:
|
|
12
|
+
v_id = url.split("?")[0].split("/")[-1]
|
|
13
|
+
headers = {"Referer": self.main_url, "X-Requested-With": "XMLHttpRequest"}
|
|
14
|
+
|
|
15
|
+
resp = await self.httpx.get(url, headers=headers)
|
|
16
|
+
sel = HTMLHelper(resp.text)
|
|
17
|
+
|
|
18
|
+
# Nonce Bulma
|
|
19
|
+
nonce = sel.regex_first(r"\b[a-zA-Z0-9]{48}\b")
|
|
20
|
+
if not nonce:
|
|
21
|
+
m = re.search(r"\b([a-zA-Z0-9]{16})\b.*?\b([a-zA-Z0-9]{16})\b.*?\b([a-zA-Z0-9]{16})\b", resp.text, re.DOTALL)
|
|
22
|
+
if m: nonce = m.group(1) + m.group(2) + m.group(3)
|
|
23
|
+
|
|
24
|
+
if not nonce:
|
|
25
|
+
raise ValueError(f"Videostr: Nonce bulunamadı. {url}")
|
|
26
|
+
|
|
27
|
+
# Kaynakları Çek
|
|
28
|
+
api_resp = await self.httpx.get(f"{self.main_url}/embed-1/v3/e-1/getSources?id={v_id}&_k={nonce}", headers=headers)
|
|
29
|
+
data = api_resp.json()
|
|
30
|
+
|
|
31
|
+
enc_file = data.get("sources", [{}])[0].get("file")
|
|
32
|
+
if not enc_file:
|
|
33
|
+
raise ValueError("Videostr: Kaynak bulunamadı.")
|
|
34
|
+
|
|
35
|
+
m3u8_url = None
|
|
36
|
+
if ".m3u8" in enc_file:
|
|
37
|
+
m3u8_url = enc_file
|
|
38
|
+
else:
|
|
39
|
+
# Decryption Flow (External Keys)
|
|
40
|
+
with contextlib.suppress(Exception):
|
|
41
|
+
key_resp = await self.httpx.get("https://raw.githubusercontent.com/yogesh-hacker/MegacloudKeys/refs/heads/main/keys.json")
|
|
42
|
+
v_key = key_resp.json().get("vidstr")
|
|
43
|
+
if v_key:
|
|
44
|
+
decode_api = "https://script.google.com/macros/s/AKfycbxHbYHbrGMXYD2-bC-C43D3njIbU-wGiYQuJL61H4vyy6YVXkybMNNEPJNPPuZrD1gRVA/exec"
|
|
45
|
+
dec_resp = await self.httpx.get(f"{decode_api}?encrypted_data={quote(enc_file)}&nonce={quote(nonce)}&secret={quote(v_key)}")
|
|
46
|
+
m3u8_url = re.search(r'"file":"(.*?)"', dec_resp.text).group(1).replace("\\/", "/")
|
|
47
|
+
|
|
48
|
+
if not m3u8_url:
|
|
49
|
+
raise ValueError(f"Videostr: Video URL bulunamadı. {url}")
|
|
50
|
+
|
|
51
|
+
subtitles = [
|
|
52
|
+
Subtitle(name=t.get("label", "Altyazı"), url=t.get("file"))
|
|
53
|
+
for t in data.get("tracks", []) if t.get("kind") in ["captions", "subtitles"]
|
|
54
|
+
]
|
|
55
|
+
|
|
56
|
+
return ExtractResult(name=self.name, url=m3u8_url, referer=f"{self.main_url}/", subtitles=subtitles)
|
|
57
|
+
|
|
58
|
+
import contextlib
|
|
@@ -0,0 +1,18 @@
|
|
|
1
|
+
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
|
+
|
|
3
|
+
from KekikStream.Core import ExtractorBase, ExtractResult, HTMLHelper
|
|
4
|
+
|
|
5
|
+
class Vidoza(ExtractorBase):
|
|
6
|
+
name = "Vidoza"
|
|
7
|
+
main_url = "https://vidoza.net"
|
|
8
|
+
|
|
9
|
+
async def extract(self, url: str, referer: str = None) -> ExtractResult:
|
|
10
|
+
self.httpx.headers.update({"Referer": referer or url})
|
|
11
|
+
|
|
12
|
+
resp = await self.httpx.get(url)
|
|
13
|
+
v_url = HTMLHelper(resp.text).select_attr("source", "src")
|
|
14
|
+
|
|
15
|
+
if not v_url:
|
|
16
|
+
raise ValueError(f"Vidoza: Video bulunamadı. {url}")
|
|
17
|
+
|
|
18
|
+
return ExtractResult(name=self.name, url=v_url, referer=url)
|
|
@@ -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, HTMLHelper
|
|
4
|
+
from Kekik.Sifreleme import Packer
|
|
5
|
+
|
|
6
|
+
class Vtbe(ExtractorBase):
|
|
7
|
+
name = "Vtbe"
|
|
8
|
+
main_url = "https://vtbe.to"
|
|
9
|
+
|
|
10
|
+
async def extract(self, url: str, referer: str = None) -> list[ExtractResult]:
|
|
11
|
+
# Iframe ise embed url'i düzeltmek gerekebilir ama genelde embed-xxxx.html formatı
|
|
12
|
+
istek = await self.httpx.get(url, headers={"Referer": referer or self.main_url})
|
|
13
|
+
text = istek.text
|
|
14
|
+
|
|
15
|
+
# Packed script bul: function(p,a,c,k,e,d)
|
|
16
|
+
packed = HTMLHelper(text).regex_first(r'(eval\s*\(\s*function[\s\S]+?)<\/script>')
|
|
17
|
+
|
|
18
|
+
if not packed:
|
|
19
|
+
raise ValueError(f"Vtbe: Packed script bulunamadı. {url}")
|
|
20
|
+
|
|
21
|
+
unpacked = ""
|
|
22
|
+
try:
|
|
23
|
+
unpacked = Packer.unpack(packed)
|
|
24
|
+
except:
|
|
25
|
+
raise ValueError("Vtbe: Unpack hatası")
|
|
26
|
+
|
|
27
|
+
# sources:[{file:"..."
|
|
28
|
+
file_url = HTMLHelper(unpacked).regex_first(r'sources:\s*\[\s*\{\s*file:\s*"([^"]+)"')
|
|
29
|
+
|
|
30
|
+
if not file_url:
|
|
31
|
+
raise ValueError("Vtbe: Video URL (file) bulunamadı")
|
|
32
|
+
|
|
33
|
+
return ExtractResult(
|
|
34
|
+
name = self.name,
|
|
35
|
+
url = self.fix_url(file_url),
|
|
36
|
+
referer = url,
|
|
37
|
+
user_agent = self.httpx.headers.get("User-Agent", "")
|
|
38
|
+
)
|
KekikStream/Extractors/YTDLP.py
CHANGED
|
@@ -151,8 +151,8 @@ class YTDLP(ExtractorBase):
|
|
|
151
151
|
ydl_opts = {
|
|
152
152
|
"quiet" : True,
|
|
153
153
|
"no_warnings" : True,
|
|
154
|
-
"extract_flat" : False,
|
|
155
|
-
"format" : "best", # En iyi kalite
|
|
154
|
+
"extract_flat" : False, # Tam bilgi al
|
|
155
|
+
"format" : "best/all", # En iyi kalite, yoksa herhangi biri
|
|
156
156
|
"no_check_certificates" : True,
|
|
157
157
|
"socket_timeout" : 3,
|
|
158
158
|
"retries" : 1
|
|
@@ -6,36 +6,18 @@ class YildizKisaFilm(ExtractorBase):
|
|
|
6
6
|
name = "YildizKisaFilm"
|
|
7
7
|
main_url = "https://yildizkisafilm.org"
|
|
8
8
|
|
|
9
|
-
async def extract(self, url, referer=None) -> ExtractResult:
|
|
10
|
-
|
|
11
|
-
|
|
12
|
-
|
|
13
|
-
|
|
14
|
-
|
|
15
|
-
|
|
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
|
-
}
|
|
9
|
+
async def extract(self, url: str, referer: str = None) -> ExtractResult:
|
|
10
|
+
ref = referer or self.main_url
|
|
11
|
+
v_id = url.split("video/")[-1] if "video/" in url else url.split("?data=")[-1]
|
|
12
|
+
|
|
13
|
+
resp = await self.httpx.post(
|
|
14
|
+
f"{self.main_url}/player/index.php?data={v_id}&do=getVideo",
|
|
15
|
+
data = {"hash": v_id, "r": ref},
|
|
16
|
+
headers = {"Referer": ref, "X-Requested-With": "XMLHttpRequest"}
|
|
27
17
|
)
|
|
28
|
-
|
|
18
|
+
|
|
19
|
+
m3u8_url = resp.json().get("securedLink")
|
|
20
|
+
if not m3u8_url:
|
|
21
|
+
raise ValueError(f"YildizKisaFilm: Video URL bulunamadı. {url}")
|
|
29
22
|
|
|
30
|
-
|
|
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 = ext_ref,
|
|
40
|
-
subtitles = []
|
|
41
|
-
)
|
|
23
|
+
return ExtractResult(name=self.name, url=m3u8_url, referer=ref)
|
|
@@ -0,0 +1,61 @@
|
|
|
1
|
+
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
|
+
|
|
3
|
+
from KekikStream.Core import ExtractorBase, ExtractResult, HTMLHelper
|
|
4
|
+
|
|
5
|
+
class Zeus(ExtractorBase):
|
|
6
|
+
name = "Zeus"
|
|
7
|
+
main_url = "https://d2rs.com"
|
|
8
|
+
|
|
9
|
+
async def extract(self, url: str, referer: str = None) -> list[ExtractResult]:
|
|
10
|
+
# Iframe içeriğini al
|
|
11
|
+
istek = await self.httpx.get(url, headers={"Referer": referer} if referer else None)
|
|
12
|
+
text = istek.text
|
|
13
|
+
|
|
14
|
+
# 'q' parametresini bul
|
|
15
|
+
# form.append("q", "...")
|
|
16
|
+
q_param = HTMLHelper(text).regex_first(r'form\.append\("q",\s*"([^"]+)"\)')
|
|
17
|
+
|
|
18
|
+
if not q_param:
|
|
19
|
+
raise ValueError(f"Zeus: 'q' parametresi bulunamadı. {url}")
|
|
20
|
+
|
|
21
|
+
# API'ye POST at
|
|
22
|
+
resp = await self.httpx.post(
|
|
23
|
+
url = "https://d2rs.com/zeus/api.php",
|
|
24
|
+
data = {"q": q_param},
|
|
25
|
+
headers = {"Referer": url}
|
|
26
|
+
)
|
|
27
|
+
|
|
28
|
+
try:
|
|
29
|
+
sources = resp.json()
|
|
30
|
+
except:
|
|
31
|
+
raise ValueError("Zeus: API yanıtı geçersiz JSON")
|
|
32
|
+
|
|
33
|
+
results = []
|
|
34
|
+
# [{"file": "...", "label": "Full HD", "type": "video/mp4"}, ...]
|
|
35
|
+
for i, source in enumerate(sources, 1):
|
|
36
|
+
file_path = source.get("file")
|
|
37
|
+
label = source.get("label") or ""
|
|
38
|
+
type_ = source.get("type", "")
|
|
39
|
+
|
|
40
|
+
if not file_path:
|
|
41
|
+
continue
|
|
42
|
+
|
|
43
|
+
full_url = f"https://d2rs.com/zeus/{file_path}"
|
|
44
|
+
|
|
45
|
+
# İsimlendirme
|
|
46
|
+
if label:
|
|
47
|
+
source_name = f"{self.name} | {label}"
|
|
48
|
+
else:
|
|
49
|
+
source_name = f"{self.name} | Kaynak {i}"
|
|
50
|
+
|
|
51
|
+
results.append(ExtractResult(
|
|
52
|
+
name = source_name,
|
|
53
|
+
url = self.fix_url(full_url),
|
|
54
|
+
referer = url,
|
|
55
|
+
user_agent = self.httpx.headers.get("User-Agent", "")
|
|
56
|
+
))
|
|
57
|
+
|
|
58
|
+
if not results:
|
|
59
|
+
raise ValueError("Zeus: Kaynak bulunamadı")
|
|
60
|
+
|
|
61
|
+
return results
|
KekikStream/Plugins/BelgeselX.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
2
|
|
|
3
|
-
from KekikStream.Core
|
|
3
|
+
from KekikStream.Core import PluginBase, MainPageResult, SearchResult, SeriesInfo, Episode, ExtractResult, HTMLHelper
|
|
4
|
+
from contextlib import suppress
|
|
4
5
|
|
|
5
6
|
class BelgeselX(PluginBase):
|
|
6
7
|
name = "BelgeselX"
|
|
@@ -34,31 +35,46 @@ class BelgeselX(PluginBase):
|
|
|
34
35
|
@staticmethod
|
|
35
36
|
def _to_title_case(text: str) -> str:
|
|
36
37
|
"""Türkçe için title case dönüşümü."""
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
)
|
|
38
|
+
if not text:
|
|
39
|
+
return ""
|
|
40
|
+
|
|
41
|
+
words = text.split()
|
|
42
|
+
new_words = []
|
|
43
|
+
|
|
44
|
+
for word in words:
|
|
45
|
+
# Önce Türkçe karakterleri koruyarak küçült
|
|
46
|
+
# İ -> i, I -> ı
|
|
47
|
+
word = word.replace("İ", "i").replace("I", "ı").lower()
|
|
48
|
+
|
|
49
|
+
# Sonra ilk harfi Türkçe kurallarına göre büyüt
|
|
50
|
+
if word:
|
|
51
|
+
if word[0] == "i":
|
|
52
|
+
word = "İ" + word[1:]
|
|
53
|
+
elif word[0] == "ı":
|
|
54
|
+
word = "I" + word[1:]
|
|
55
|
+
else:
|
|
56
|
+
word = word[0].upper() + word[1:]
|
|
57
|
+
|
|
58
|
+
new_words.append(word)
|
|
59
|
+
|
|
60
|
+
return " ".join(new_words)
|
|
41
61
|
|
|
42
62
|
async def get_main_page(self, page: int, url: str, category: str) -> list[MainPageResult]:
|
|
43
63
|
istek = self.cloudscraper.get(f"{url}{page}")
|
|
44
64
|
secici = HTMLHelper(istek.text)
|
|
45
65
|
|
|
46
66
|
results = []
|
|
47
|
-
# xpath kullanamıyoruz, en üst seviye gen-movie-contain'leri alıp içlerinden bilgileri çekelim
|
|
48
67
|
for container in secici.select("div.gen-movie-contain"):
|
|
49
|
-
# Poster için img'i container'ın içinden alalım
|
|
50
68
|
poster = secici.select_attr("div.gen-movie-img img", "src", container)
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
title = secici.select_text("div.gen-movie-info h3 a", container)
|
|
54
|
-
href = secici.select_attr("div.gen-movie-info h3 a", "href", container)
|
|
69
|
+
title = secici.select_text("div.gen-movie-info h3 a", container)
|
|
70
|
+
href = secici.select_attr("div.gen-movie-info h3 a", "href", container)
|
|
55
71
|
|
|
56
72
|
if title and href:
|
|
57
73
|
results.append(MainPageResult(
|
|
58
74
|
category = category,
|
|
59
75
|
title = self._to_title_case(title),
|
|
60
76
|
url = self.fix_url(href),
|
|
61
|
-
poster = self.fix_url(poster)
|
|
77
|
+
poster = self.fix_url(poster)
|
|
62
78
|
))
|
|
63
79
|
|
|
64
80
|
return results
|
|
@@ -70,7 +86,7 @@ class BelgeselX(PluginBase):
|
|
|
70
86
|
token_resp = self.cloudscraper.get(f"https://cse.google.com/cse.js?cx={cx}")
|
|
71
87
|
token_text = token_resp.text
|
|
72
88
|
|
|
73
|
-
secici
|
|
89
|
+
secici = HTMLHelper(token_text)
|
|
74
90
|
cse_lib = secici.regex_first(r'cselibVersion": "(.*)"')
|
|
75
91
|
cse_tok = secici.regex_first(r'cse_token": "(.*)"')
|
|
76
92
|
|
|
@@ -84,13 +100,13 @@ class BelgeselX(PluginBase):
|
|
|
84
100
|
f"&callback=google.search.cse.api9969&rurl=https%3A%2F%2Fbelgeselx.com%2F"
|
|
85
101
|
)
|
|
86
102
|
|
|
87
|
-
resp
|
|
103
|
+
resp = self.cloudscraper.get(search_url)
|
|
88
104
|
resp_text = resp.text
|
|
89
105
|
|
|
90
106
|
secici2 = HTMLHelper(resp_text)
|
|
91
|
-
titles
|
|
92
|
-
urls
|
|
93
|
-
images
|
|
107
|
+
titles = secici2.regex_all(r'"titleNoFormatting": "(.*?)"')
|
|
108
|
+
urls = secici2.regex_all(r'"url": "(.*?)"')
|
|
109
|
+
images = secici2.regex_all(r'"ogImage": "(.*?)"')
|
|
94
110
|
|
|
95
111
|
results = []
|
|
96
112
|
for i, title in enumerate(titles):
|
|
@@ -98,11 +114,9 @@ class BelgeselX(PluginBase):
|
|
|
98
114
|
poster = images[i] if i < len(images) else None
|
|
99
115
|
|
|
100
116
|
if not url_val or "diziresimleri" not in url_val:
|
|
101
|
-
# URL'den belgesel linkini oluştur
|
|
102
117
|
if poster and "diziresimleri" in poster:
|
|
103
118
|
file_name = poster.rsplit("/", 1)[-1]
|
|
104
|
-
|
|
105
|
-
file_name = secici3.regex_replace(r"\.(jpe?g|png|webp)$", "")
|
|
119
|
+
file_name = HTMLHelper(file_name).regex_replace(r"\.(jpe?g|png|webp)$", "")
|
|
106
120
|
url_val = f"{self.main_url}/belgeseldizi/{file_name}"
|
|
107
121
|
else:
|
|
108
122
|
continue
|
|
@@ -120,85 +134,91 @@ class BelgeselX(PluginBase):
|
|
|
120
134
|
istek = await self.httpx.get(url)
|
|
121
135
|
secici = HTMLHelper(istek.text)
|
|
122
136
|
|
|
123
|
-
title
|
|
124
|
-
|
|
125
|
-
poster = secici.select_attr("div.gen-tv-show-top img", "src")
|
|
126
|
-
|
|
137
|
+
title = self._to_title_case(secici.select_text("h2.gen-title"))
|
|
138
|
+
poster = secici.select_poster("div.gen-tv-show-top img")
|
|
127
139
|
description = secici.select_text("div.gen-single-tv-show-info p")
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
140
|
+
tags = [self._to_title_case(t.rsplit("/", 1)[-1].replace("-", " ")) for t in secici.select_attrs("div.gen-socail-share a[href*='belgeselkanali']", "href")]
|
|
141
|
+
|
|
142
|
+
# Meta bilgilerinden yıl ve puanı çıkar
|
|
143
|
+
meta_items = secici.select_texts("div.gen-single-meta-holder ul li")
|
|
144
|
+
year = None
|
|
145
|
+
rating = None
|
|
146
|
+
for item in meta_items:
|
|
147
|
+
if not year:
|
|
148
|
+
if y_match := secici.regex_first(r"\b((?:19|20)\d{2})\b", item):
|
|
149
|
+
year = int(y_match)
|
|
150
|
+
if not rating:
|
|
151
|
+
if r_match := secici.regex_first(r"%\s*(\d+)\s*Puan", item):
|
|
152
|
+
rating = float(r_match) / 10
|
|
153
|
+
rating = rating or None
|
|
135
154
|
|
|
136
155
|
episodes = []
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
episodes.append(Episode(
|
|
156
|
-
season = ep_season,
|
|
157
|
-
episode = ep_episode,
|
|
158
|
-
title = ep_name,
|
|
159
|
-
url = self.fix_url(ep_href)
|
|
160
|
-
))
|
|
156
|
+
for i, ep in enumerate(secici.select("div.gen-movie-contain")):
|
|
157
|
+
name = secici.select_text("div.gen-movie-info h3 a", ep)
|
|
158
|
+
href = secici.select_attr("div.gen-movie-info h3 a", "href", ep)
|
|
159
|
+
item_id = secici.select_attr("div.gen-movie-info h3 a", "id", ep)
|
|
160
|
+
if name and href:
|
|
161
|
+
s, e = secici.extract_season_episode(secici.select_text("div.gen-single-meta-holder ul li", ep))
|
|
162
|
+
# ID'yi URL'ye ekle ki load_links doğru bölümü çekebilsin
|
|
163
|
+
final_url = self.fix_url(href)
|
|
164
|
+
if item_id:
|
|
165
|
+
final_url = f"{final_url}?id={item_id}"
|
|
166
|
+
|
|
167
|
+
episodes.append(Episode(
|
|
168
|
+
season = s or 1,
|
|
169
|
+
episode = e or (i + 1),
|
|
170
|
+
title = name,
|
|
171
|
+
url = final_url
|
|
172
|
+
))
|
|
161
173
|
|
|
162
174
|
return SeriesInfo(
|
|
163
175
|
url = url,
|
|
164
|
-
poster = self.fix_url(poster)
|
|
165
|
-
title =
|
|
176
|
+
poster = self.fix_url(poster),
|
|
177
|
+
title = title,
|
|
166
178
|
description = description,
|
|
167
179
|
tags = tags,
|
|
180
|
+
year = year,
|
|
181
|
+
rating = rating,
|
|
168
182
|
episodes = episodes
|
|
169
183
|
)
|
|
170
184
|
|
|
171
185
|
async def load_links(self, url: str) -> list[ExtractResult]:
|
|
172
|
-
|
|
173
|
-
|
|
186
|
+
# URL'den ID'yi ayıkla
|
|
187
|
+
params = dict([x.split('=') for x in url.split('?')[-1].split('&')]) if '?' in url else {}
|
|
188
|
+
episode_id = params.get('id')
|
|
189
|
+
main_url = url.split('?')[0]
|
|
190
|
+
|
|
191
|
+
istek = await self.httpx.get(main_url)
|
|
192
|
+
secici = HTMLHelper(istek.text)
|
|
174
193
|
|
|
175
|
-
secici = HTMLHelper(text)
|
|
176
|
-
# fnc_addWatch div'inden data-episode ID'sini al
|
|
177
|
-
episode_id = secici.regex_first(r'<div[^>]*class=["\'][^"\']*fnc_addWatch[^"\']*["\'][^>]*data-episode=["\'](\d+)["\']')
|
|
178
194
|
if not episode_id:
|
|
179
|
-
|
|
195
|
+
episode_id = secici.regex_first(r'data-episode=["\'](\d+)["\']')
|
|
180
196
|
|
|
181
|
-
|
|
197
|
+
if not episode_id:
|
|
198
|
+
return []
|
|
182
199
|
|
|
183
|
-
iframe_resp = await self.httpx.get(
|
|
184
|
-
|
|
200
|
+
iframe_resp = await self.httpx.get(f"{self.main_url}/video/data/new4.php?id={episode_id}", headers={"Referer": main_url})
|
|
201
|
+
secici = HTMLHelper(iframe_resp.text)
|
|
185
202
|
|
|
186
|
-
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
label_matches = secici2.regex_all(r'label: "([^"]+)"')
|
|
203
|
+
links = []
|
|
204
|
+
files = secici.regex_all(r'file:"([^"]+)"')
|
|
205
|
+
labels = secici.regex_all(r'label: "([^"]+)"')
|
|
190
206
|
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
207
|
+
for i, video_url in enumerate(files):
|
|
208
|
+
quality = labels[i] if i < len(labels) else "HD"
|
|
209
|
+
name = f"{'Google' if 'google' in video_url.lower() or 'blogspot' in video_url.lower() or quality == 'FULL' else self.name} | {'1080p' if quality == 'FULL' else quality}"
|
|
194
210
|
|
|
195
|
-
|
|
196
|
-
|
|
211
|
+
# belgeselx.php redirect'ini çöz
|
|
212
|
+
if "belgeselx.php" in video_url or "belgeselx2.php" in video_url:
|
|
213
|
+
with suppress(Exception):
|
|
214
|
+
# HEAD isteği ile lokasyonu alalım
|
|
215
|
+
resp = await self.httpx.head(video_url, headers={"Referer": main_url}, follow_redirects=True)
|
|
216
|
+
video_url = str(resp.url)
|
|
197
217
|
|
|
198
218
|
links.append(ExtractResult(
|
|
199
219
|
url = video_url,
|
|
200
|
-
name =
|
|
201
|
-
referer =
|
|
220
|
+
name = name,
|
|
221
|
+
referer = main_url
|
|
202
222
|
))
|
|
203
223
|
|
|
204
224
|
return links
|
KekikStream/Plugins/DiziBox.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
2
|
|
|
3
|
-
from KekikStream.Core
|
|
4
|
-
from Kekik.Sifreleme
|
|
3
|
+
from KekikStream.Core import PluginBase, MainPageResult, SearchResult, SeriesInfo, Episode, ExtractResult, HTMLHelper
|
|
4
|
+
from Kekik.Sifreleme import CryptoJS
|
|
5
5
|
import urllib.parse, base64, contextlib, asyncio, time
|
|
6
6
|
|
|
7
7
|
class DiziBox(PluginBase):
|
|
@@ -52,8 +52,8 @@ class DiziBox(PluginBase):
|
|
|
52
52
|
|
|
53
53
|
results = []
|
|
54
54
|
for veri in secici.select("article.detailed-article"):
|
|
55
|
-
title
|
|
56
|
-
href
|
|
55
|
+
title = secici.select_text("h3 a", veri)
|
|
56
|
+
href = secici.select_attr("h3 a", "href", veri)
|
|
57
57
|
poster = secici.select_attr("img", "src", veri)
|
|
58
58
|
|
|
59
59
|
if title and href:
|
|
@@ -61,7 +61,7 @@ class DiziBox(PluginBase):
|
|
|
61
61
|
category = category,
|
|
62
62
|
title = title,
|
|
63
63
|
url = self.fix_url(href),
|
|
64
|
-
poster = self.fix_url(poster)
|
|
64
|
+
poster = self.fix_url(poster),
|
|
65
65
|
))
|
|
66
66
|
|
|
67
67
|
return results
|
|
@@ -84,7 +84,7 @@ class DiziBox(PluginBase):
|
|
|
84
84
|
results.append(SearchResult(
|
|
85
85
|
title = title,
|
|
86
86
|
url = self.fix_url(href),
|
|
87
|
-
poster = self.fix_url(poster)
|
|
87
|
+
poster = self.fix_url(poster),
|
|
88
88
|
))
|
|
89
89
|
|
|
90
90
|
return results
|
|
@@ -93,48 +93,28 @@ class DiziBox(PluginBase):
|
|
|
93
93
|
istek = await self.httpx.get(url)
|
|
94
94
|
secici = HTMLHelper(istek.text)
|
|
95
95
|
|
|
96
|
-
title
|
|
97
|
-
|
|
98
|
-
poster = secici.select_attr("div.tv-overview figure img", "src")
|
|
99
|
-
|
|
96
|
+
title = secici.select_text("div.tv-overview h1 a")
|
|
97
|
+
poster = secici.select_poster("div.tv-overview figure img")
|
|
100
98
|
description = secici.select_text("div.tv-story p")
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
tags = secici.select_all_text("a[href*='/tur/']")
|
|
107
|
-
|
|
108
|
-
# rating
|
|
109
|
-
rating_text = secici.select_text("span.label-imdb b")
|
|
110
|
-
rating = secici.regex_first(r"[\d.,]+", rating_text)
|
|
111
|
-
|
|
112
|
-
actors = secici.select_all_text("a[href*='/oyuncu/']")
|
|
99
|
+
year = secici.extract_year("a[href*='/yil/']")
|
|
100
|
+
tags = secici.select_texts("a[href*='/tur/']")
|
|
101
|
+
rating = secici.regex_first(r"[\d.,]+", secici.select_text("span.label-imdb b"))
|
|
102
|
+
actors = secici.select_texts("a[href*='/oyuncu/']")
|
|
113
103
|
|
|
114
104
|
episodes = []
|
|
115
|
-
for
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
ep_season = sezon_secici.regex_first(r"(\d+)\. ?Sezon", ep_title)
|
|
125
|
-
ep_episode = sezon_secici.regex_first(r"(\d+)\. ?Bölüm", ep_title)
|
|
126
|
-
|
|
127
|
-
if ep_title and ep_href:
|
|
128
|
-
episodes.append(Episode(
|
|
129
|
-
season = ep_season,
|
|
130
|
-
episode = ep_episode,
|
|
131
|
-
title = ep_title,
|
|
132
|
-
url = self.fix_url(ep_href),
|
|
133
|
-
))
|
|
105
|
+
for link in secici.select_attrs("div#seasons-list a", "href"):
|
|
106
|
+
r = await self.httpx.get(self.fix_url(link))
|
|
107
|
+
s_secici = HTMLHelper(r.text)
|
|
108
|
+
for bolum in s_secici.select("article.grid-box"):
|
|
109
|
+
name = s_secici.select_text("div.post-title a", bolum)
|
|
110
|
+
href = s_secici.select_attr("div.post-title a", "href", bolum)
|
|
111
|
+
if name and href:
|
|
112
|
+
s, e = s_secici.extract_season_episode(name)
|
|
113
|
+
episodes.append(Episode(season=s, episode=e, title=name, url=self.fix_url(href)))
|
|
134
114
|
|
|
135
115
|
return SeriesInfo(
|
|
136
116
|
url = url,
|
|
137
|
-
poster = self.fix_url(poster)
|
|
117
|
+
poster = self.fix_url(poster),
|
|
138
118
|
title = title,
|
|
139
119
|
description = description,
|
|
140
120
|
tags = tags,
|
|
@@ -202,13 +182,16 @@ class DiziBox(PluginBase):
|
|
|
202
182
|
istek = await self.httpx.get(url)
|
|
203
183
|
secici = HTMLHelper(istek.text)
|
|
204
184
|
|
|
205
|
-
|
|
185
|
+
# Aktif kaynağın adını bul (DBX Pro vs.)
|
|
186
|
+
current_source_name = secici.select_text("div.video-toolbar option[selected]") or self.name
|
|
187
|
+
|
|
188
|
+
results = []
|
|
206
189
|
main_iframe = secici.select_attr("div#video-area iframe", "src")
|
|
207
190
|
|
|
208
191
|
if main_iframe:
|
|
209
192
|
if decoded := await self._iframe_decode(self.name, main_iframe, url):
|
|
210
193
|
for iframe in decoded:
|
|
211
|
-
data = await self.extract(iframe)
|
|
194
|
+
data = await self.extract(iframe, name_override=current_source_name)
|
|
212
195
|
if data:
|
|
213
196
|
results.append(data)
|
|
214
197
|
|
|
@@ -229,7 +212,7 @@ class DiziBox(PluginBase):
|
|
|
229
212
|
if alt_iframe:
|
|
230
213
|
if decoded := await self._iframe_decode(alt_name, alt_iframe, url):
|
|
231
214
|
for iframe in decoded:
|
|
232
|
-
data = await self.extract(iframe,
|
|
215
|
+
data = await self.extract(iframe, name_override=alt_name)
|
|
233
216
|
if data:
|
|
234
217
|
results.append(data)
|
|
235
218
|
|