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
|
@@ -1,8 +1,8 @@
|
|
|
1
1
|
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
2
|
|
|
3
|
-
from KekikStream.Core
|
|
4
|
-
from Kekik.Sifreleme
|
|
5
|
-
import random, string
|
|
3
|
+
from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo, SeriesInfo, Episode, Subtitle, ExtractResult, HTMLHelper
|
|
4
|
+
from Kekik.Sifreleme import Packer, StreamDecoder
|
|
5
|
+
import random, string, json, asyncio, contextlib
|
|
6
6
|
|
|
7
7
|
class HDFilmCehennemi(PluginBase):
|
|
8
8
|
name = "HDFilmCehennemi"
|
|
@@ -12,20 +12,43 @@ class HDFilmCehennemi(PluginBase):
|
|
|
12
12
|
description = "Türkiye'nin en hızlı hd film izleme sitesi. Tek ve gerçek hdfilmcehennemi sitesi."
|
|
13
13
|
|
|
14
14
|
main_page = {
|
|
15
|
-
f"{main_url}"
|
|
16
|
-
f"{main_url}/yabancidiziizle-
|
|
17
|
-
f"{main_url}/
|
|
18
|
-
f"{main_url}/
|
|
19
|
-
f"{main_url}/
|
|
20
|
-
f"{main_url}/
|
|
21
|
-
f"{main_url}/
|
|
22
|
-
f"{main_url}/
|
|
23
|
-
f"{main_url}/
|
|
24
|
-
f"{main_url}/
|
|
25
|
-
f"{main_url}/
|
|
26
|
-
f"{main_url}/
|
|
27
|
-
f"{main_url}/
|
|
28
|
-
f"{main_url}/
|
|
15
|
+
f"{main_url}" : "Yeni Eklenen Filmler",
|
|
16
|
+
f"{main_url}/yabancidiziizle-5" : "Yeni Eklenen Diziler",
|
|
17
|
+
f"{main_url}/dil/turkce-dublajli-film-izleyin-5" : "Türkçe Dublaj Filmler",
|
|
18
|
+
f"{main_url}/dil/turkce-altyazili-filmleri-izleme-sitesi-3" : "Türkçe Altyazılı Filmler",
|
|
19
|
+
f"{main_url}/category/tavsiye-filmler-izle3" : "Tavsiye Filmler",
|
|
20
|
+
f"{main_url}/imdb-7-puan-uzeri-filmler-2" : "IMDB 7+ Filmler",
|
|
21
|
+
f"{main_url}/en-cok-yorumlananlar-2" : "En Çok Yorumlananlar",
|
|
22
|
+
f"{main_url}/en-cok-begenilen-filmleri-izle-4" : "En Çok Beğenilenler",
|
|
23
|
+
f"{main_url}/serifilmlerim-4" : "Seri Filmler",
|
|
24
|
+
f"{main_url}/category/nette-ilk-filmler" : "Nette İlk Filmler",
|
|
25
|
+
f"{main_url}/category/4k-film-izle-5" : "4K Filmler",
|
|
26
|
+
f"{main_url}/category/1080p-hd-film-izle-5" : "1080p Filmler",
|
|
27
|
+
f"{main_url}/category/amazon-yapimlarini-izle" : "Amazon Yapımları",
|
|
28
|
+
f"{main_url}/category/netflix-yapimlari-izle" : "Netflix Yapımları",
|
|
29
|
+
f"{main_url}/category/marvel-yapimlarini-izle-5" : "Marvel Filmleri",
|
|
30
|
+
f"{main_url}/category/dc-yapimlarini-izle-1" : "DC Filmleri",
|
|
31
|
+
f"{main_url}/tur/aile-filmleri-izleyin-7" : "Aile Filmleri",
|
|
32
|
+
f"{main_url}/tur/aksiyon-filmleri-izleyin-6" : "Aksiyon Filmleri",
|
|
33
|
+
f"{main_url}/tur/animasyon-filmlerini-izleyin-5" : "Animasyon Filmleri",
|
|
34
|
+
f"{main_url}/tur/belgesel-filmlerini-izle-2" : "Belgesel Filmleri",
|
|
35
|
+
f"{main_url}/tur/bilim-kurgu-filmlerini-izleyin-5" : "Bilim Kurgu Filmleri",
|
|
36
|
+
f"{main_url}/tur/biyografi-filmleri-izle-3" : "Biyografi Filmleri",
|
|
37
|
+
f"{main_url}/tur/dram-filmlerini-izle-2" : "Dram Filmleri",
|
|
38
|
+
f"{main_url}/tur/fantastik-filmlerini-izleyin-3" : "Fantastik Filmleri",
|
|
39
|
+
f"{main_url}/tur/gerilim-filmlerini-izle-2" : "Gerilim Filmleri",
|
|
40
|
+
f"{main_url}/tur/gizem-filmleri-izle-3" : "Gizem Filmleri",
|
|
41
|
+
f"{main_url}/tur/komedi-filmlerini-izleyin-2" : "Komedi Filmleri",
|
|
42
|
+
f"{main_url}/tur/korku-filmlerini-izle-5" : "Korku Filmleri",
|
|
43
|
+
f"{main_url}/tur/macera-filmlerini-izleyin-4" : "Macera Filmleri",
|
|
44
|
+
f"{main_url}/tur/muzik-filmlerini-izle-844" : "Müzik Filmleri",
|
|
45
|
+
f"{main_url}/tur/polisiye-filmleri-izle" : "Polisiye Filmleri",
|
|
46
|
+
f"{main_url}/tur/romantik-filmleri-izle-3" : "Romantik Filmleri",
|
|
47
|
+
f"{main_url}/tur/savas-filmleri-izle-5" : "Savaş Filmleri",
|
|
48
|
+
f"{main_url}/tur/spor-filmleri-izle-3" : "Spor Filmleri",
|
|
49
|
+
f"{main_url}/tur/suc-filmleri-izle-3" : "Suç Filmleri",
|
|
50
|
+
f"{main_url}/tur/tarih-filmleri-izle-5" : "Tarih Filmleri",
|
|
51
|
+
f"{main_url}/tur/western-filmleri-izle-3" : "Western Filmleri"
|
|
29
52
|
}
|
|
30
53
|
|
|
31
54
|
async def get_main_page(self, page: int, url: str, category: str) -> list[MainPageResult]:
|
|
@@ -34,8 +57,8 @@ class HDFilmCehennemi(PluginBase):
|
|
|
34
57
|
|
|
35
58
|
results = []
|
|
36
59
|
for veri in secici.select("div.section-content a.poster"):
|
|
37
|
-
title
|
|
38
|
-
href
|
|
60
|
+
title = secici.select_text("strong.poster-title", veri)
|
|
61
|
+
href = veri.attrs.get("href")
|
|
39
62
|
poster = secici.select_attr("img", "data-src", veri)
|
|
40
63
|
|
|
41
64
|
if title and href:
|
|
@@ -43,7 +66,7 @@ class HDFilmCehennemi(PluginBase):
|
|
|
43
66
|
category = category,
|
|
44
67
|
title = title,
|
|
45
68
|
url = self.fix_url(href),
|
|
46
|
-
poster = self.fix_url(poster)
|
|
69
|
+
poster = self.fix_url(poster),
|
|
47
70
|
))
|
|
48
71
|
|
|
49
72
|
return results
|
|
@@ -78,57 +101,37 @@ class HDFilmCehennemi(PluginBase):
|
|
|
78
101
|
istek = await self.httpx.get(url, headers = {"Referer": f"{self.main_url}/"})
|
|
79
102
|
secici = HTMLHelper(istek.text)
|
|
80
103
|
|
|
81
|
-
title
|
|
104
|
+
title = self.clean_title(secici.select_text("h1.section-title"))
|
|
105
|
+
poster = secici.select_poster("aside.post-info-poster img.lazyload")
|
|
106
|
+
description = secici.select_text("article.post-info-content > p")
|
|
107
|
+
tags = secici.select_texts("div.post-info-genres a")
|
|
108
|
+
rating = secici.select_text("div.post-info-imdb-rating span")
|
|
109
|
+
rating = rating.split("(")[0] if rating else None
|
|
110
|
+
year = secici.select_text("div.post-info-year-country a")
|
|
111
|
+
actors = secici.select_texts("div.post-info-cast a > strong")
|
|
112
|
+
duration = int(secici.regex_first(r"(\d+)", secici.select_text("div.post-info-duration")) or 0)
|
|
82
113
|
|
|
83
|
-
|
|
84
|
-
|
|
114
|
+
# Dizi mi film mi kontrol et
|
|
115
|
+
ep_links = secici.select("div.seasons-tab-content a")
|
|
85
116
|
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
tags = secici.select_all_text("div.post-info-genres a")
|
|
89
|
-
|
|
90
|
-
rating = secici.select_text("div.post-info-imdb-rating span") or ""
|
|
91
|
-
|
|
92
|
-
year = secici.select_text("div.post-info-year-country a") or ""
|
|
93
|
-
|
|
94
|
-
actors = secici.select_all_text("div.post-info-cast a > strong")
|
|
95
|
-
|
|
96
|
-
duration_str = secici.select_text("div.post-info-duration") or "0"
|
|
97
|
-
duration_str = duration_str.replace("dakika", "").strip()
|
|
98
|
-
|
|
99
|
-
try:
|
|
100
|
-
duration_val = HTMLHelper(duration_str).regex_first(r'\d+')
|
|
101
|
-
duration_minutes = int(duration_val) if duration_val else 0
|
|
102
|
-
except Exception:
|
|
103
|
-
duration_minutes = 0
|
|
104
|
-
|
|
105
|
-
# Dizi mi film mi kontrol et (Kotlin referansı: div.seasons kontrolü)
|
|
106
|
-
is_series = len(secici.select("div.seasons")) > 0
|
|
107
|
-
|
|
108
|
-
if is_series:
|
|
117
|
+
if ep_links:
|
|
109
118
|
episodes = []
|
|
110
|
-
for ep in
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
# Regex ile sezon ve bölüm numarası çıkar
|
|
116
|
-
ep_val = HTMLHelper(ep_name).regex_first(r'(\d+)\.\s*Bölüm')
|
|
117
|
-
sz_val = HTMLHelper(ep_name).regex_first(r'(\d+)\.\s*Sezon')
|
|
118
|
-
ep_num = int(ep_val) if ep_val and ep_val.isdigit() else 1
|
|
119
|
-
sz_num = int(sz_val) if sz_val and sz_val.isdigit() else 1
|
|
120
|
-
|
|
119
|
+
for ep in ep_links:
|
|
120
|
+
name = secici.select_text("h4", ep)
|
|
121
|
+
href = ep.attrs.get("href")
|
|
122
|
+
if name and href:
|
|
123
|
+
s, e = secici.extract_season_episode(name)
|
|
121
124
|
episodes.append(Episode(
|
|
122
|
-
season =
|
|
123
|
-
episode =
|
|
124
|
-
title =
|
|
125
|
-
url = self.fix_url(
|
|
125
|
+
season = s or 1,
|
|
126
|
+
episode = e or 1,
|
|
127
|
+
title = name,
|
|
128
|
+
url = self.fix_url(href)
|
|
126
129
|
))
|
|
127
130
|
|
|
128
131
|
return SeriesInfo(
|
|
129
132
|
url = url,
|
|
130
|
-
poster = self.fix_url(poster)
|
|
131
|
-
title =
|
|
133
|
+
poster = self.fix_url(poster),
|
|
134
|
+
title = title,
|
|
132
135
|
description = description,
|
|
133
136
|
tags = tags,
|
|
134
137
|
rating = rating,
|
|
@@ -136,118 +139,145 @@ class HDFilmCehennemi(PluginBase):
|
|
|
136
139
|
actors = actors,
|
|
137
140
|
episodes = episodes
|
|
138
141
|
)
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
142
|
+
|
|
143
|
+
return MovieInfo(
|
|
144
|
+
url = url,
|
|
145
|
+
poster = self.fix_url(poster),
|
|
146
|
+
title = title,
|
|
147
|
+
description = description,
|
|
148
|
+
tags = tags,
|
|
149
|
+
rating = rating,
|
|
150
|
+
year = year,
|
|
151
|
+
actors = actors,
|
|
152
|
+
duration = duration
|
|
153
|
+
)
|
|
151
154
|
|
|
152
155
|
def generate_random_cookie(self):
|
|
153
156
|
return "".join(random.choices(string.ascii_letters + string.digits, k=16))
|
|
154
157
|
|
|
155
|
-
async def cehennempass(self, video_id: str) -> list:
|
|
158
|
+
async def cehennempass(self, video_id: str, name_prefix: str = "", subtitles: list[Subtitle] = None) -> list[ExtractResult]:
|
|
156
159
|
results = []
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
161
|
-
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
"Referer" : f"https://cehennempass.pw/download/{video_id}",
|
|
179
|
-
"X-Requested-With" : "fetch",
|
|
180
|
-
"authority" : "cehennempass.pw",
|
|
181
|
-
"Cookie" : f"PHPSESSID={self.generate_random_cookie()}"
|
|
182
|
-
},
|
|
183
|
-
data = {"video_id": video_id, "selected_quality": "high"},
|
|
184
|
-
)
|
|
185
|
-
if video_url := istek.json().get("download_link"):
|
|
186
|
-
results.append(ExtractResult(
|
|
187
|
-
url = self.fix_url(video_url),
|
|
188
|
-
name = "Yüksek Kalite",
|
|
189
|
-
referer = f"https://cehennempass.pw/download/{video_id}"
|
|
190
|
-
))
|
|
160
|
+
subs = subtitles or []
|
|
161
|
+
|
|
162
|
+
for quality, label in [("low", "Düşük Kalite"), ("high", "Yüksek Kalite")]:
|
|
163
|
+
with contextlib.suppress(Exception):
|
|
164
|
+
istek = await self.httpx.post(
|
|
165
|
+
url = "https://cehennempass.pw/process_quality_selection.php",
|
|
166
|
+
headers = {
|
|
167
|
+
"Referer" : f"https://cehennempass.pw/download/{video_id}",
|
|
168
|
+
"X-Requested-With" : "fetch",
|
|
169
|
+
"authority" : "cehennempass.pw",
|
|
170
|
+
"Cookie" : f"PHPSESSID={self.generate_random_cookie()}"
|
|
171
|
+
},
|
|
172
|
+
data = {"video_id": video_id, "selected_quality": quality},
|
|
173
|
+
)
|
|
174
|
+
if video_url := istek.json().get("download_link"):
|
|
175
|
+
results.append(ExtractResult(
|
|
176
|
+
url = self.fix_url(video_url),
|
|
177
|
+
name = f"{name_prefix} | {label}" if name_prefix else label,
|
|
178
|
+
referer = f"https://cehennempass.pw/download/{video_id}",
|
|
179
|
+
subtitles = subs
|
|
180
|
+
))
|
|
191
181
|
|
|
192
182
|
return results
|
|
193
183
|
|
|
194
|
-
def
|
|
195
|
-
"""
|
|
196
|
-
|
|
197
|
-
|
|
184
|
+
def _extract_video_url(self, html: str) -> str | None:
|
|
185
|
+
"""Video URL'sini çeşitli yöntemlerle (JSON-LD, Regex, Packer) çıkarır"""
|
|
186
|
+
secici = HTMLHelper(html)
|
|
187
|
+
|
|
188
|
+
# 1. JSON-LD'den dene
|
|
189
|
+
json_ld = secici.regex_first(r'(?s)<script[^>]+type=["\']application/ld\+json["\'][^>]*>(.*?)</script>')
|
|
198
190
|
if json_ld:
|
|
199
|
-
|
|
200
|
-
import json
|
|
191
|
+
with contextlib.suppress(Exception):
|
|
201
192
|
data = json.loads(json_ld.strip())
|
|
202
193
|
if content_url := data.get("contentUrl"):
|
|
203
194
|
if content_url.startswith("http"):
|
|
204
195
|
return content_url
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
196
|
+
|
|
197
|
+
# 2. Regex ile contentUrl dene
|
|
198
|
+
content_url = secici.regex_first(r'"contentUrl"\s*:\s*"([^"]+)"')
|
|
199
|
+
if content_url and content_url.startswith("http"):
|
|
200
|
+
return content_url
|
|
201
|
+
|
|
202
|
+
# 3. Packed JavaScript (eval(function...)) dene
|
|
203
|
+
if eval_script := secici.regex_first(r'(eval\(function[\s\S]+)'):
|
|
204
|
+
with contextlib.suppress(Exception):
|
|
205
|
+
unpacked = Packer.unpack(eval_script)
|
|
206
|
+
return StreamDecoder.extract_stream_url(unpacked)
|
|
207
|
+
|
|
210
208
|
return None
|
|
211
209
|
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
210
|
+
def _extract_subtitles(self, html: str) -> list[Subtitle]:
|
|
211
|
+
"""HTML içeriğinden çeşitli formatlardaki altyazıları çıkarır"""
|
|
212
|
+
subtitles = []
|
|
213
|
+
secici = HTMLHelper(html)
|
|
214
|
+
|
|
215
|
+
# 1. JWPlayer / Plyr / Generic JS Object (tracks: [ ... ])
|
|
216
|
+
if match := secici.regex_first(r'tracks\s*:\s*(\[[^\]]+\])'):
|
|
217
|
+
# JSON parse denemesi
|
|
218
|
+
with contextlib.suppress(Exception):
|
|
219
|
+
track_data = json.loads(match)
|
|
220
|
+
for t in track_data:
|
|
221
|
+
if file_url := t.get("file"):
|
|
222
|
+
label = t.get("label") or t.get("language") or "TR"
|
|
223
|
+
if t.get("kind", "captions") in ["captions", "subtitles"]:
|
|
224
|
+
subtitles.append(Subtitle(name=label.upper(), url=self.fix_url(file_url)))
|
|
225
|
+
return subtitles # JSON başarılıysa dön
|
|
226
|
+
|
|
227
|
+
# Regex fallback
|
|
228
|
+
for m in HTMLHelper(match).regex_all(r'file\s*:\s*["\']([^"\']+)["\'].*?(?:label|language)\s*:\s*["\']([^"\']+)["\']'):
|
|
229
|
+
file_url, lang = m
|
|
230
|
+
subtitles.append(Subtitle(name=lang.upper(), url=self.fix_url(file_url.replace("\\", ""))))
|
|
231
|
+
|
|
232
|
+
# 2. PlayerJS (subtitle: "url,name;url,name")
|
|
233
|
+
if not subtitles:
|
|
234
|
+
if sub_str := secici.regex_first(r'subtitle\s*:\s*["\']([^"\']+)["\']'):
|
|
235
|
+
for sub_item in sub_str.split(";"):
|
|
236
|
+
if "," in sub_item:
|
|
237
|
+
# [TR]url,[EN]url gibi yapılar için split mantığı
|
|
238
|
+
# Basitçe virgülle ayırıp http kontrolü yapalım
|
|
239
|
+
parts = sub_item.split(",")
|
|
240
|
+
u, n = (parts[0], parts[1]) if "http" in parts[0] else (parts[1], parts[0])
|
|
241
|
+
subtitles.append(Subtitle(name=n.strip(), url=self.fix_url(u.strip())))
|
|
242
|
+
elif "http" in sub_item:
|
|
243
|
+
subtitles.append(Subtitle(name="TR", url=self.fix_url(sub_item.strip())))
|
|
244
|
+
|
|
245
|
+
# 3. HTML5 Track Tags
|
|
246
|
+
if not subtitles:
|
|
247
|
+
for track in secici.select("track[kind='captions'], track[kind='subtitles']"):
|
|
248
|
+
src = track.attrs.get("src")
|
|
249
|
+
label = track.attrs.get("label") or track.attrs.get("srclang") or "TR"
|
|
250
|
+
if src:
|
|
251
|
+
subtitles.append(Subtitle(name=label.upper(), url=self.fix_url(src)))
|
|
252
|
+
|
|
253
|
+
return subtitles
|
|
254
|
+
|
|
255
|
+
async def invoke_local_source(self, iframe: str, source: str, url: str) -> list[ExtractResult]:
|
|
256
|
+
istek = await self.httpx.get(
|
|
257
|
+
url = iframe,
|
|
258
|
+
headers = {
|
|
259
|
+
"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",
|
|
260
|
+
"X-Requested-With" : "XMLHttpRequest",
|
|
261
|
+
"Referer" : self.main_url + "/"
|
|
262
|
+
}
|
|
263
|
+
)
|
|
218
264
|
|
|
219
|
-
|
|
220
|
-
|
|
265
|
+
# ID'yi güvenli al
|
|
266
|
+
video_id = iframe.rstrip("/").split("/")[-1]
|
|
221
267
|
|
|
222
|
-
#
|
|
223
|
-
|
|
268
|
+
# Boş yanıt kontrolü
|
|
269
|
+
if not istek.text or len(istek.text) < 50:
|
|
270
|
+
return await self.cehennempass(video_id, source, [])
|
|
224
271
|
|
|
225
|
-
#
|
|
226
|
-
|
|
227
|
-
# eval(function...) içeren packed script bul
|
|
228
|
-
eval_script = HTMLHelper(istek.text).regex_first(r'(eval\(function[\s\S]+)')
|
|
229
|
-
if not eval_script:
|
|
230
|
-
return await self.cehennempass(iframe.split("/")[-1])
|
|
272
|
+
# 1. Altyazıları Çıkar
|
|
273
|
+
subtitles = self._extract_subtitles(istek.text)
|
|
231
274
|
|
|
232
|
-
|
|
233
|
-
|
|
234
|
-
video_url = StreamDecoder.extract_stream_url(unpacked)
|
|
235
|
-
except Exception:
|
|
236
|
-
return await self.cehennempass(iframe.split("/")[-1])
|
|
237
|
-
|
|
238
|
-
if not video_url:
|
|
239
|
-
return await self.cehennempass(iframe.split("/")[-1])
|
|
275
|
+
# 2. Video URL'sini Çıkar
|
|
276
|
+
video_url = self._extract_video_url(istek.text)
|
|
240
277
|
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
|
|
244
|
-
for file_url, lang in HTMLHelper(sub_data).regex_all(r'(?s)file":"([^\\"]+)".*?"language":"([^\\"]+)"'):
|
|
245
|
-
subtitles.append(Subtitle(
|
|
246
|
-
name = lang.upper(),
|
|
247
|
-
url = self.fix_url(file_url.replace("\\", "")),
|
|
248
|
-
))
|
|
249
|
-
except Exception:
|
|
250
|
-
pass
|
|
278
|
+
# 3. Eğer Video URL yoksa CehennemPass'a git
|
|
279
|
+
if not video_url:
|
|
280
|
+
return await self.cehennempass(video_id, source, subtitles)
|
|
251
281
|
|
|
252
282
|
return [ExtractResult(
|
|
253
283
|
url = video_url,
|
|
@@ -256,49 +286,72 @@ class HDFilmCehennemi(PluginBase):
|
|
|
256
286
|
subtitles = subtitles
|
|
257
287
|
)]
|
|
258
288
|
|
|
289
|
+
async def _get_video_source(self, video_id: str, source_name: str, referer: str) -> list[ExtractResult]:
|
|
290
|
+
try:
|
|
291
|
+
api_get = await self.httpx.get(
|
|
292
|
+
url = f"{self.main_url}/video/{video_id}/",
|
|
293
|
+
headers = {
|
|
294
|
+
"Content-Type" : "application/json",
|
|
295
|
+
"X-Requested-With" : "fetch",
|
|
296
|
+
"Referer" : referer,
|
|
297
|
+
}
|
|
298
|
+
)
|
|
299
|
+
|
|
300
|
+
# JSON Parse (Daha güvenli)
|
|
301
|
+
# Response: {"success": true, "data": {"html": "<iframe class=\"rapidrame\" data-src=\"...\" ...></iframe>"}}
|
|
302
|
+
try:
|
|
303
|
+
json_data = api_get.json()
|
|
304
|
+
html_content = json_data.get("data", {}).get("html", "")
|
|
305
|
+
iframe = HTMLHelper(html_content).select_attr("iframe", "data-src")
|
|
306
|
+
except:
|
|
307
|
+
# RegEx fallback
|
|
308
|
+
iframe = HTMLHelper(api_get.text).regex_first(r'data-src=\\\"([^\"]+)')
|
|
309
|
+
iframe = iframe.replace("\\", "") if iframe else None
|
|
310
|
+
|
|
311
|
+
if not iframe:
|
|
312
|
+
return []
|
|
313
|
+
|
|
314
|
+
# mobi URL'si varsa direkt kullan
|
|
315
|
+
if "mobi" in iframe: # m.hdfilmcehennemi.nl veya /mobi/
|
|
316
|
+
iframe = iframe.split("?")[0]
|
|
317
|
+
# rapidrame ve query varsa
|
|
318
|
+
elif "rapidrame" in iframe and "?rapidrame_id=" in iframe:
|
|
319
|
+
# /rplayer/ID/ formatına çevir
|
|
320
|
+
rap_id = iframe.split('?rapidrame_id=')[1]
|
|
321
|
+
iframe = f"{self.main_url}/rplayer/{rap_id}"
|
|
322
|
+
|
|
323
|
+
return await self.invoke_local_source(iframe, source_name, referer)
|
|
324
|
+
except Exception:
|
|
325
|
+
return []
|
|
326
|
+
|
|
259
327
|
async def load_links(self, url: str) -> list[ExtractResult]:
|
|
260
328
|
istek = await self.httpx.get(url)
|
|
261
329
|
secici = HTMLHelper(istek.text)
|
|
262
330
|
|
|
263
|
-
|
|
331
|
+
sources = []
|
|
264
332
|
for alternatif in secici.select("div.alternative-links"):
|
|
265
333
|
lang_code = alternatif.attrs.get("data-lang", "").upper()
|
|
266
334
|
|
|
335
|
+
# Dil metnini bul
|
|
336
|
+
if lang_code:
|
|
337
|
+
if lang_btn := secici.select_first(f"button.language-link[data-lang='{lang_code.lower()}']"):
|
|
338
|
+
lang_text = lang_btn.text(strip=True)
|
|
339
|
+
# "DUAL (Türkçe Dublaj & Altyazılı)" -> "DUAL" yap, diğerleri aynen kalsın
|
|
340
|
+
if "DUAL" in lang_text:
|
|
341
|
+
lang_code = "DUAL"
|
|
342
|
+
else:
|
|
343
|
+
lang_code = lang_text
|
|
344
|
+
|
|
267
345
|
for link in secici.select("button.alternative-link", alternatif):
|
|
268
346
|
source_text = link.text(strip=True).replace('(HDrip Xbet)', '').strip()
|
|
269
|
-
|
|
270
|
-
video_id
|
|
271
|
-
|
|
272
|
-
if not video_id:
|
|
273
|
-
continue
|
|
274
|
-
|
|
275
|
-
api_get = await self.httpx.get(
|
|
276
|
-
url = f"{self.main_url}/video/{video_id}/",
|
|
277
|
-
headers = {
|
|
278
|
-
"Content-Type" : "application/json",
|
|
279
|
-
"X-Requested-With" : "fetch",
|
|
280
|
-
"Referer" : url,
|
|
281
|
-
},
|
|
282
|
-
)
|
|
283
|
-
|
|
284
|
-
iframe = HTMLHelper(api_get.text).regex_first(r'data-src=\\\"([^\"]+)')
|
|
285
|
-
iframe = iframe.replace("\\", "") if iframe else None
|
|
286
|
-
|
|
287
|
-
if not iframe:
|
|
288
|
-
continue
|
|
289
|
-
|
|
290
|
-
# mobi URL'si varsa direkt kullan (query string'i kaldır)
|
|
291
|
-
if "mobi" in iframe:
|
|
292
|
-
iframe = iframe.split("?")[0] # rapidrame_id query param'ı kaldır
|
|
293
|
-
# mobi değilse ve rapidrame varsa rplayer kullan
|
|
294
|
-
elif "rapidrame" in iframe and "?rapidrame_id=" in iframe:
|
|
295
|
-
iframe = f"{self.main_url}/rplayer/{iframe.split('?rapidrame_id=')[1]}"
|
|
347
|
+
source_name = f"{lang_code} | {source_text}".strip()
|
|
348
|
+
video_id = link.attrs.get("data-video")
|
|
296
349
|
|
|
297
|
-
|
|
298
|
-
|
|
299
|
-
continue
|
|
350
|
+
if video_id:
|
|
351
|
+
sources.append((video_id, source_name, url))
|
|
300
352
|
|
|
301
|
-
|
|
302
|
-
|
|
353
|
+
tasks = []
|
|
354
|
+
for vid, name, ref in sources:
|
|
355
|
+
tasks.append(self._get_video_source(vid, name, ref))
|
|
303
356
|
|
|
304
|
-
return
|
|
357
|
+
return [item for sublist in await asyncio.gather(*tasks) for item in sublist]
|