KekikStream 2.4.7__py3-none-any.whl → 2.4.8__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/Plugins/BelgeselX.py +3 -4
- KekikStream/Plugins/DiziBox.py +3 -3
- KekikStream/Plugins/DiziMom.py +48 -42
- KekikStream/Plugins/DiziPal.py +1 -1
- KekikStream/Plugins/Dizilla.py +2 -2
- KekikStream/Plugins/FilmBip.py +4 -11
- KekikStream/Plugins/FilmEkseni.py +59 -55
- KekikStream/Plugins/FilmMakinesi.py +42 -5
- KekikStream/Plugins/FilmModu.py +0 -1
- KekikStream/Plugins/Filmatek.py +4 -11
- KekikStream/Plugins/{Full4kizle.py → FilmciBaba.py} +55 -74
- KekikStream/Plugins/FullHDFilmizlesene.py +6 -7
- KekikStream/Plugins/HDFilm.py +243 -0
- KekikStream/Plugins/HDFilmCehennemi.py +193 -124
- {kekikstream-2.4.7.dist-info → kekikstream-2.4.8.dist-info}/METADATA +1 -1
- {kekikstream-2.4.7.dist-info → kekikstream-2.4.8.dist-info}/RECORD +20 -20
- KekikStream/Plugins/FullHDFilm.py +0 -179
- {kekikstream-2.4.7.dist-info → kekikstream-2.4.8.dist-info}/WHEEL +0 -0
- {kekikstream-2.4.7.dist-info → kekikstream-2.4.8.dist-info}/entry_points.txt +0 -0
- {kekikstream-2.4.7.dist-info → kekikstream-2.4.8.dist-info}/licenses/LICENSE +0 -0
- {kekikstream-2.4.7.dist-info → kekikstream-2.4.8.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"
|
|
@@ -34,8 +34,8 @@ class HDFilmCehennemi(PluginBase):
|
|
|
34
34
|
|
|
35
35
|
results = []
|
|
36
36
|
for veri in secici.select("div.section-content a.poster"):
|
|
37
|
-
title
|
|
38
|
-
href
|
|
37
|
+
title = secici.select_text("strong.poster-title", veri)
|
|
38
|
+
href = veri.attrs.get("href")
|
|
39
39
|
poster = secici.select_attr("img", "data-src", veri)
|
|
40
40
|
|
|
41
41
|
if title and href:
|
|
@@ -98,117 +98,163 @@ class HDFilmCehennemi(PluginBase):
|
|
|
98
98
|
href = ep.attrs.get("href")
|
|
99
99
|
if name and href:
|
|
100
100
|
s, e = secici.extract_season_episode(name)
|
|
101
|
-
episodes.append(Episode(
|
|
101
|
+
episodes.append(Episode(
|
|
102
|
+
season = s or 1,
|
|
103
|
+
episode = e or 1,
|
|
104
|
+
title = name,
|
|
105
|
+
url = self.fix_url(href)
|
|
106
|
+
))
|
|
102
107
|
|
|
103
108
|
return SeriesInfo(
|
|
104
|
-
url=url,
|
|
105
|
-
|
|
109
|
+
url = url,
|
|
110
|
+
poster = self.fix_url(poster),
|
|
111
|
+
title = title,
|
|
112
|
+
description = description,
|
|
113
|
+
tags = tags,
|
|
114
|
+
rating = rating,
|
|
115
|
+
year = year,
|
|
116
|
+
actors = actors,
|
|
117
|
+
episodes = episodes
|
|
106
118
|
)
|
|
107
119
|
|
|
108
120
|
return MovieInfo(
|
|
109
|
-
url=url,
|
|
110
|
-
|
|
121
|
+
url = url,
|
|
122
|
+
poster = self.fix_url(poster),
|
|
123
|
+
title = title,
|
|
124
|
+
description = description,
|
|
125
|
+
tags = tags,
|
|
126
|
+
rating = rating,
|
|
127
|
+
year = year,
|
|
128
|
+
actors = actors,
|
|
129
|
+
duration = duration
|
|
111
130
|
)
|
|
112
131
|
|
|
113
132
|
def generate_random_cookie(self):
|
|
114
133
|
return "".join(random.choices(string.ascii_letters + string.digits, k=16))
|
|
115
134
|
|
|
116
|
-
async def cehennempass(self, video_id: str) -> list:
|
|
135
|
+
async def cehennempass(self, video_id: str, name_prefix: str = "", subtitles: list[Subtitle] = None) -> list[ExtractResult]:
|
|
117
136
|
results = []
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
"Referer" : f"https://cehennempass.pw/download/{video_id}",
|
|
140
|
-
"X-Requested-With" : "fetch",
|
|
141
|
-
"authority" : "cehennempass.pw",
|
|
142
|
-
"Cookie" : f"PHPSESSID={self.generate_random_cookie()}"
|
|
143
|
-
},
|
|
144
|
-
data = {"video_id": video_id, "selected_quality": "high"},
|
|
145
|
-
)
|
|
146
|
-
if video_url := istek.json().get("download_link"):
|
|
147
|
-
results.append(ExtractResult(
|
|
148
|
-
url = self.fix_url(video_url),
|
|
149
|
-
name = "Yüksek Kalite",
|
|
150
|
-
referer = f"https://cehennempass.pw/download/{video_id}"
|
|
151
|
-
))
|
|
137
|
+
subs = subtitles or []
|
|
138
|
+
|
|
139
|
+
for quality, label in [("low", "Düşük Kalite"), ("high", "Yüksek Kalite")]:
|
|
140
|
+
with contextlib.suppress(Exception):
|
|
141
|
+
istek = await self.httpx.post(
|
|
142
|
+
url = "https://cehennempass.pw/process_quality_selection.php",
|
|
143
|
+
headers = {
|
|
144
|
+
"Referer" : f"https://cehennempass.pw/download/{video_id}",
|
|
145
|
+
"X-Requested-With" : "fetch",
|
|
146
|
+
"authority" : "cehennempass.pw",
|
|
147
|
+
"Cookie" : f"PHPSESSID={self.generate_random_cookie()}"
|
|
148
|
+
},
|
|
149
|
+
data = {"video_id": video_id, "selected_quality": quality},
|
|
150
|
+
)
|
|
151
|
+
if video_url := istek.json().get("download_link"):
|
|
152
|
+
results.append(ExtractResult(
|
|
153
|
+
url = self.fix_url(video_url),
|
|
154
|
+
name = f"{name_prefix} | {label}" if name_prefix else label,
|
|
155
|
+
referer = f"https://cehennempass.pw/download/{video_id}",
|
|
156
|
+
subtitles = subs
|
|
157
|
+
))
|
|
152
158
|
|
|
153
159
|
return results
|
|
154
160
|
|
|
155
|
-
def
|
|
156
|
-
"""
|
|
157
|
-
|
|
158
|
-
|
|
161
|
+
def _extract_video_url(self, html: str) -> str | None:
|
|
162
|
+
"""Video URL'sini çeşitli yöntemlerle (JSON-LD, Regex, Packer) çıkarır"""
|
|
163
|
+
secici = HTMLHelper(html)
|
|
164
|
+
|
|
165
|
+
# 1. JSON-LD'den dene
|
|
166
|
+
json_ld = secici.regex_first(r'(?s)<script[^>]+type=["\']application/ld\+json["\'][^>]*>(.*?)</script>')
|
|
159
167
|
if json_ld:
|
|
160
|
-
|
|
161
|
-
import json
|
|
168
|
+
with contextlib.suppress(Exception):
|
|
162
169
|
data = json.loads(json_ld.strip())
|
|
163
170
|
if content_url := data.get("contentUrl"):
|
|
164
171
|
if content_url.startswith("http"):
|
|
165
172
|
return content_url
|
|
166
|
-
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
|
|
170
|
-
|
|
173
|
+
|
|
174
|
+
# 2. Regex ile contentUrl dene
|
|
175
|
+
content_url = secici.regex_first(r'"contentUrl"\s*:\s*"([^"]+)"')
|
|
176
|
+
if content_url and content_url.startswith("http"):
|
|
177
|
+
return content_url
|
|
178
|
+
|
|
179
|
+
# 3. Packed JavaScript (eval(function...)) dene
|
|
180
|
+
if eval_script := secici.regex_first(r'(eval\(function[\s\S]+)'):
|
|
181
|
+
with contextlib.suppress(Exception):
|
|
182
|
+
unpacked = Packer.unpack(eval_script)
|
|
183
|
+
return StreamDecoder.extract_stream_url(unpacked)
|
|
184
|
+
|
|
171
185
|
return None
|
|
172
186
|
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
187
|
+
def _extract_subtitles(self, html: str) -> list[Subtitle]:
|
|
188
|
+
"""HTML içeriğinden çeşitli formatlardaki altyazıları çıkarır"""
|
|
189
|
+
subtitles = []
|
|
190
|
+
secici = HTMLHelper(html)
|
|
191
|
+
|
|
192
|
+
# 1. JWPlayer / Plyr / Generic JS Object (tracks: [ ... ])
|
|
193
|
+
if match := secici.regex_first(r'tracks\s*:\s*(\[[^\]]+\])'):
|
|
194
|
+
# JSON parse denemesi
|
|
195
|
+
with contextlib.suppress(Exception):
|
|
196
|
+
track_data = json.loads(match)
|
|
197
|
+
for t in track_data:
|
|
198
|
+
if file_url := t.get("file"):
|
|
199
|
+
label = t.get("label") or t.get("language") or "TR"
|
|
200
|
+
if t.get("kind", "captions") in ["captions", "subtitles"]:
|
|
201
|
+
subtitles.append(Subtitle(name=label.upper(), url=self.fix_url(file_url)))
|
|
202
|
+
return subtitles # JSON başarılıysa dön
|
|
203
|
+
|
|
204
|
+
# Regex fallback
|
|
205
|
+
for m in HTMLHelper(match).regex_all(r'file\s*:\s*["\']([^"\']+)["\'].*?(?:label|language)\s*:\s*["\']([^"\']+)["\']'):
|
|
206
|
+
file_url, lang = m
|
|
207
|
+
subtitles.append(Subtitle(name=lang.upper(), url=self.fix_url(file_url.replace("\\", ""))))
|
|
208
|
+
|
|
209
|
+
# 2. PlayerJS (subtitle: "url,name;url,name")
|
|
210
|
+
if not subtitles:
|
|
211
|
+
if sub_str := secici.regex_first(r'subtitle\s*:\s*["\']([^"\']+)["\']'):
|
|
212
|
+
for sub_item in sub_str.split(";"):
|
|
213
|
+
if "," in sub_item:
|
|
214
|
+
# [TR]url,[EN]url gibi yapılar için split mantığı
|
|
215
|
+
# Basitçe virgülle ayırıp http kontrolü yapalım
|
|
216
|
+
parts = sub_item.split(",")
|
|
217
|
+
u, n = (parts[0], parts[1]) if "http" in parts[0] else (parts[1], parts[0])
|
|
218
|
+
subtitles.append(Subtitle(name=n.strip(), url=self.fix_url(u.strip())))
|
|
219
|
+
elif "http" in sub_item:
|
|
220
|
+
subtitles.append(Subtitle(name="TR", url=self.fix_url(sub_item.strip())))
|
|
221
|
+
|
|
222
|
+
# 3. HTML5 Track Tags
|
|
223
|
+
if not subtitles:
|
|
224
|
+
for track in secici.select("track[kind='captions'], track[kind='subtitles']"):
|
|
225
|
+
src = track.attrs.get("src")
|
|
226
|
+
label = track.attrs.get("label") or track.attrs.get("srclang") or "TR"
|
|
227
|
+
if src:
|
|
228
|
+
subtitles.append(Subtitle(name=label.upper(), url=self.fix_url(src)))
|
|
229
|
+
|
|
230
|
+
return subtitles
|
|
231
|
+
|
|
232
|
+
async def invoke_local_source(self, iframe: str, source: str, url: str) -> list[ExtractResult]:
|
|
233
|
+
istek = await self.httpx.get(
|
|
234
|
+
url = iframe,
|
|
235
|
+
headers = {
|
|
236
|
+
"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",
|
|
237
|
+
"X-Requested-With" : "XMLHttpRequest",
|
|
238
|
+
"Referer" : self.main_url + "/"
|
|
239
|
+
}
|
|
240
|
+
)
|
|
179
241
|
|
|
180
|
-
|
|
181
|
-
|
|
242
|
+
# ID'yi güvenli al
|
|
243
|
+
video_id = iframe.rstrip("/").split("/")[-1]
|
|
182
244
|
|
|
183
|
-
#
|
|
184
|
-
|
|
245
|
+
# Boş yanıt kontrolü
|
|
246
|
+
if not istek.text or len(istek.text) < 50:
|
|
247
|
+
return await self.cehennempass(video_id, source, [])
|
|
185
248
|
|
|
186
|
-
#
|
|
187
|
-
|
|
188
|
-
# eval(function...) içeren packed script bul
|
|
189
|
-
eval_script = HTMLHelper(istek.text).regex_first(r'(eval\(function[\s\S]+)')
|
|
190
|
-
if not eval_script:
|
|
191
|
-
return await self.cehennempass(iframe.split("/")[-1])
|
|
249
|
+
# 1. Altyazıları Çıkar
|
|
250
|
+
subtitles = self._extract_subtitles(istek.text)
|
|
192
251
|
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
video_url = StreamDecoder.extract_stream_url(unpacked)
|
|
196
|
-
except Exception:
|
|
197
|
-
return await self.cehennempass(iframe.split("/")[-1])
|
|
198
|
-
|
|
199
|
-
if not video_url:
|
|
200
|
-
return await self.cehennempass(iframe.split("/")[-1])
|
|
252
|
+
# 2. Video URL'sini Çıkar
|
|
253
|
+
video_url = self._extract_video_url(istek.text)
|
|
201
254
|
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
for file_url, lang in HTMLHelper(sub_data).regex_all(r'(?s)file":"([^\\"]+)".*?"language":"([^\\"]+)"'):
|
|
206
|
-
subtitles.append(Subtitle(
|
|
207
|
-
name = lang.upper(),
|
|
208
|
-
url = self.fix_url(file_url.replace("\\", "")),
|
|
209
|
-
))
|
|
210
|
-
except Exception:
|
|
211
|
-
pass
|
|
255
|
+
# 3. Eğer Video URL yoksa CehennemPass'a git
|
|
256
|
+
if not video_url:
|
|
257
|
+
return await self.cehennempass(video_id, source, subtitles)
|
|
212
258
|
|
|
213
259
|
return [ExtractResult(
|
|
214
260
|
url = video_url,
|
|
@@ -217,49 +263,72 @@ class HDFilmCehennemi(PluginBase):
|
|
|
217
263
|
subtitles = subtitles
|
|
218
264
|
)]
|
|
219
265
|
|
|
266
|
+
async def _get_video_source(self, video_id: str, source_name: str, referer: str) -> list[ExtractResult]:
|
|
267
|
+
try:
|
|
268
|
+
api_get = await self.httpx.get(
|
|
269
|
+
url = f"{self.main_url}/video/{video_id}/",
|
|
270
|
+
headers = {
|
|
271
|
+
"Content-Type" : "application/json",
|
|
272
|
+
"X-Requested-With" : "fetch",
|
|
273
|
+
"Referer" : referer,
|
|
274
|
+
}
|
|
275
|
+
)
|
|
276
|
+
|
|
277
|
+
# JSON Parse (Daha güvenli)
|
|
278
|
+
# Response: {"success": true, "data": {"html": "<iframe class=\"rapidrame\" data-src=\"...\" ...></iframe>"}}
|
|
279
|
+
try:
|
|
280
|
+
json_data = api_get.json()
|
|
281
|
+
html_content = json_data.get("data", {}).get("html", "")
|
|
282
|
+
iframe = HTMLHelper(html_content).select_attr("iframe", "data-src")
|
|
283
|
+
except:
|
|
284
|
+
# RegEx fallback
|
|
285
|
+
iframe = HTMLHelper(api_get.text).regex_first(r'data-src=\\\"([^\"]+)')
|
|
286
|
+
iframe = iframe.replace("\\", "") if iframe else None
|
|
287
|
+
|
|
288
|
+
if not iframe:
|
|
289
|
+
return []
|
|
290
|
+
|
|
291
|
+
# mobi URL'si varsa direkt kullan
|
|
292
|
+
if "mobi" in iframe: # m.hdfilmcehennemi.nl veya /mobi/
|
|
293
|
+
iframe = iframe.split("?")[0]
|
|
294
|
+
# rapidrame ve query varsa
|
|
295
|
+
elif "rapidrame" in iframe and "?rapidrame_id=" in iframe:
|
|
296
|
+
# /rplayer/ID/ formatına çevir
|
|
297
|
+
rap_id = iframe.split('?rapidrame_id=')[1]
|
|
298
|
+
iframe = f"{self.main_url}/rplayer/{rap_id}"
|
|
299
|
+
|
|
300
|
+
return await self.invoke_local_source(iframe, source_name, referer)
|
|
301
|
+
except Exception:
|
|
302
|
+
return []
|
|
303
|
+
|
|
220
304
|
async def load_links(self, url: str) -> list[ExtractResult]:
|
|
221
305
|
istek = await self.httpx.get(url)
|
|
222
306
|
secici = HTMLHelper(istek.text)
|
|
223
307
|
|
|
224
|
-
|
|
308
|
+
sources = []
|
|
225
309
|
for alternatif in secici.select("div.alternative-links"):
|
|
226
310
|
lang_code = alternatif.attrs.get("data-lang", "").upper()
|
|
227
311
|
|
|
312
|
+
# Dil metnini bul
|
|
313
|
+
if lang_code:
|
|
314
|
+
if lang_btn := secici.select_first(f"button.language-link[data-lang='{lang_code.lower()}']"):
|
|
315
|
+
lang_text = lang_btn.text(strip=True)
|
|
316
|
+
# "DUAL (Türkçe Dublaj & Altyazılı)" -> "DUAL" yap, diğerleri aynen kalsın
|
|
317
|
+
if "DUAL" in lang_text:
|
|
318
|
+
lang_code = "DUAL"
|
|
319
|
+
else:
|
|
320
|
+
lang_code = lang_text
|
|
321
|
+
|
|
228
322
|
for link in secici.select("button.alternative-link", alternatif):
|
|
229
323
|
source_text = link.text(strip=True).replace('(HDrip Xbet)', '').strip()
|
|
230
|
-
|
|
231
|
-
video_id
|
|
232
|
-
|
|
233
|
-
if not video_id:
|
|
234
|
-
continue
|
|
235
|
-
|
|
236
|
-
api_get = await self.httpx.get(
|
|
237
|
-
url = f"{self.main_url}/video/{video_id}/",
|
|
238
|
-
headers = {
|
|
239
|
-
"Content-Type" : "application/json",
|
|
240
|
-
"X-Requested-With" : "fetch",
|
|
241
|
-
"Referer" : url,
|
|
242
|
-
},
|
|
243
|
-
)
|
|
244
|
-
|
|
245
|
-
iframe = HTMLHelper(api_get.text).regex_first(r'data-src=\\\"([^\"]+)')
|
|
246
|
-
iframe = iframe.replace("\\", "") if iframe else None
|
|
247
|
-
|
|
248
|
-
if not iframe:
|
|
249
|
-
continue
|
|
250
|
-
|
|
251
|
-
# mobi URL'si varsa direkt kullan (query string'i kaldır)
|
|
252
|
-
if "mobi" in iframe:
|
|
253
|
-
iframe = iframe.split("?")[0] # rapidrame_id query param'ı kaldır
|
|
254
|
-
# mobi değilse ve rapidrame varsa rplayer kullan
|
|
255
|
-
elif "rapidrame" in iframe and "?rapidrame_id=" in iframe:
|
|
256
|
-
iframe = f"{self.main_url}/rplayer/{iframe.split('?rapidrame_id=')[1]}"
|
|
324
|
+
source_name = f"{lang_code} | {source_text}".strip()
|
|
325
|
+
video_id = link.attrs.get("data-video")
|
|
257
326
|
|
|
258
|
-
|
|
259
|
-
|
|
260
|
-
continue
|
|
327
|
+
if video_id:
|
|
328
|
+
sources.append((video_id, source_name, url))
|
|
261
329
|
|
|
262
|
-
|
|
263
|
-
|
|
330
|
+
tasks = []
|
|
331
|
+
for vid, name, ref in sources:
|
|
332
|
+
tasks.append(self._get_video_source(vid, name, ref))
|
|
264
333
|
|
|
265
|
-
return
|
|
334
|
+
return [item for sublist in await asyncio.gather(*tasks) for item in sublist]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: KekikStream
|
|
3
|
-
Version: 2.4.
|
|
3
|
+
Version: 2.4.8
|
|
4
4
|
Summary: terminal üzerinden medya içeriği aramanızı ve VLC/MPV gibi popüler medya oynatıcılar aracılığıyla doğrudan izlemenizi sağlayan modüler ve genişletilebilir bir bıdı bıdı
|
|
5
5
|
Home-page: https://github.com/keyiflerolsun/KekikStream
|
|
6
6
|
Author: keyiflerolsun
|
|
@@ -55,21 +55,21 @@ KekikStream/Extractors/Videostr.py,sha256=CGL9GDzN0QzDir6ss8oUvDYYbGt2k8323P2_z5
|
|
|
55
55
|
KekikStream/Extractors/Vidoza.py,sha256=VSqCI-SYnLh6COnLHpg0feRX37t2WhPxbo08us5wCcc,655
|
|
56
56
|
KekikStream/Extractors/YTDLP.py,sha256=vE08jS9kLrLxiZA8TpofPQg2-ec_6d5DkM9esoh_GI8,7419
|
|
57
57
|
KekikStream/Extractors/YildizKisaFilm.py,sha256=jeCCSIwZvQUr-CSylleUIP--JtN18_wUGl0vQXMCsV4,936
|
|
58
|
-
KekikStream/Plugins/BelgeselX.py,sha256=
|
|
59
|
-
KekikStream/Plugins/DiziBox.py,sha256=
|
|
60
|
-
KekikStream/Plugins/DiziMom.py,sha256=
|
|
61
|
-
KekikStream/Plugins/DiziPal.py,sha256=
|
|
58
|
+
KekikStream/Plugins/BelgeselX.py,sha256=tJw1GZQoqxE7HISCVYUEL2ZP-8Mftdl4WytYA0ftSUc,9648
|
|
59
|
+
KekikStream/Plugins/DiziBox.py,sha256=SuRQxNZetwJJTlobuxB0h7NMeHUMrYMv_94JuCXydds,10204
|
|
60
|
+
KekikStream/Plugins/DiziMom.py,sha256=mRu9YUHs7XeLzXOqKIWcsI82yeltTW-6Q423wt71D5U,8044
|
|
61
|
+
KekikStream/Plugins/DiziPal.py,sha256=Ezrjbfq7EUcEjpA6yuOUtlhC009CE4aXW0_eM8Uf3yE,7927
|
|
62
62
|
KekikStream/Plugins/DiziYou.py,sha256=Z6MznGOcUnnxdsQsK-rnPmGHa1PAq7NcFw0slXlEVGo,6759
|
|
63
|
-
KekikStream/Plugins/Dizilla.py,sha256=
|
|
64
|
-
KekikStream/Plugins/FilmBip.py,sha256=
|
|
65
|
-
KekikStream/Plugins/FilmEkseni.py,sha256=
|
|
66
|
-
KekikStream/Plugins/FilmMakinesi.py,sha256=
|
|
67
|
-
KekikStream/Plugins/FilmModu.py,sha256=
|
|
68
|
-
KekikStream/Plugins/Filmatek.py,sha256=
|
|
69
|
-
KekikStream/Plugins/
|
|
70
|
-
KekikStream/Plugins/
|
|
71
|
-
KekikStream/Plugins/
|
|
72
|
-
KekikStream/Plugins/HDFilmCehennemi.py,sha256=
|
|
63
|
+
KekikStream/Plugins/Dizilla.py,sha256=U6z4cfy48HhtJNGi9-A3kUzoph-JpQuMtiOZ7fE_DUI,12705
|
|
64
|
+
KekikStream/Plugins/FilmBip.py,sha256=enTqWdx8YbseSsyQEYIVs6Dr7A7llkn7AtFaTYuatCE,9137
|
|
65
|
+
KekikStream/Plugins/FilmEkseni.py,sha256=Y2AAo6XBvwLZZ1hztD7hOi9nZlD4HhBqMv0qZJdZdIk,7101
|
|
66
|
+
KekikStream/Plugins/FilmMakinesi.py,sha256=h5-0jWggq6inWtdyHHUPP1HTnjfrf6X4syTgTm22DMs,7972
|
|
67
|
+
KekikStream/Plugins/FilmModu.py,sha256=7qm7kC4R0oH1OWyLleSqj6SMUgWbbERfYbE1d726ZOM,6943
|
|
68
|
+
KekikStream/Plugins/Filmatek.py,sha256=AdOeBVP1rfq5R1YJlQj2saT77rnzVHX54tEOAH-t9fI,7700
|
|
69
|
+
KekikStream/Plugins/FilmciBaba.py,sha256=miwQ7ODHGcAOBacUZf0lqolBElpvOk8oeckWVJYJau0,6936
|
|
70
|
+
KekikStream/Plugins/FullHDFilmizlesene.py,sha256=dJ1xo1D3ujPCQE6PewpqdvSMKlBbifA67uU7BAMmvVM,6274
|
|
71
|
+
KekikStream/Plugins/HDFilm.py,sha256=m6tjV1O1l5U_jqkGKizi62GOdSMd5osyOS2_9jehS-w,10754
|
|
72
|
+
KekikStream/Plugins/HDFilmCehennemi.py,sha256=8uaQPRprs64kdyGeC1pCkocCWPNHmddjcp_tfmHMCBE,15176
|
|
73
73
|
KekikStream/Plugins/JetFilmizle.py,sha256=D3feoxmTNhOMH6d0LwGdYnGVfvUkMmjrNdj3Yo5teOQ,8181
|
|
74
74
|
KekikStream/Plugins/KultFilmler.py,sha256=iHk3X8CwNxHRgGFZRK6BDqvZLs0p9GK5oi8IAm6w3Lw,8441
|
|
75
75
|
KekikStream/Plugins/RecTV.py,sha256=MRoP8KQF2V9kVlRNTQkRz9YFkBmMy3_skiNE47-RAlk,7151
|
|
@@ -85,9 +85,9 @@ KekikStream/Plugins/SuperFilmGeldi.py,sha256=jJKBrLPI4rXI8n55lIdZOTyzNccPAEEIkmT
|
|
|
85
85
|
KekikStream/Plugins/UgurFilm.py,sha256=NO6c1hHlylCfoP8fM-aVsxpBIyTAyu4uBHVM8CjybuI,5037
|
|
86
86
|
KekikStream/Plugins/Watch32.py,sha256=NeESk1unb5SYs6kwkb3dDymv2yYOkRU2QJCPI9izXKk,7915
|
|
87
87
|
KekikStream/Plugins/YabanciDizi.py,sha256=m4I8OM7Br_RRUSY0RAMpqcZ-_BwyjKXWHQuF_jS4EnE,9876
|
|
88
|
-
kekikstream-2.4.
|
|
89
|
-
kekikstream-2.4.
|
|
90
|
-
kekikstream-2.4.
|
|
91
|
-
kekikstream-2.4.
|
|
92
|
-
kekikstream-2.4.
|
|
93
|
-
kekikstream-2.4.
|
|
88
|
+
kekikstream-2.4.8.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
|
89
|
+
kekikstream-2.4.8.dist-info/METADATA,sha256=O9lxMnAoFFOSn8TH6Hp4AEwiJ35fMOQVjqVvQp8pTvc,10745
|
|
90
|
+
kekikstream-2.4.8.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
91
|
+
kekikstream-2.4.8.dist-info/entry_points.txt,sha256=dFwdiTx8djyehI0Gsz-rZwjAfZzUzoBSrmzRu9ubjJc,50
|
|
92
|
+
kekikstream-2.4.8.dist-info/top_level.txt,sha256=DNmGJDXl27Drdfobrak8KYLmocW_uznVYFJOzcjUgmY,12
|
|
93
|
+
kekikstream-2.4.8.dist-info/RECORD,,
|
|
@@ -1,179 +0,0 @@
|
|
|
1
|
-
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
|
-
|
|
3
|
-
from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo, SeriesInfo, Episode, ExtractResult, Subtitle, HTMLHelper
|
|
4
|
-
import base64
|
|
5
|
-
|
|
6
|
-
class FullHDFilm(PluginBase):
|
|
7
|
-
name = "FullHDFilm"
|
|
8
|
-
language = "tr"
|
|
9
|
-
main_url = "https://hdfilm.us"
|
|
10
|
-
favicon = f"https://www.google.com/s2/favicons?domain={main_url}&sz=64"
|
|
11
|
-
description = "Full HD Film izle, Türkçe Dublaj ve Altyazılı filmler."
|
|
12
|
-
|
|
13
|
-
main_page = {
|
|
14
|
-
f"{main_url}/tur/turkce-altyazili-film-izle" : "Altyazılı Filmler",
|
|
15
|
-
f"{main_url}/tur/netflix-filmleri-izle" : "Netflix",
|
|
16
|
-
f"{main_url}/tur/yerli-film-izle" : "Yerli Film",
|
|
17
|
-
f"{main_url}/category/aile-filmleri-izle" : "Aile",
|
|
18
|
-
f"{main_url}/category/aksiyon-filmleri-izle" : "Aksiyon",
|
|
19
|
-
f"{main_url}/category/animasyon-filmleri-izle" : "Animasyon",
|
|
20
|
-
f"{main_url}/category/belgesel-filmleri-izle" : "Belgesel",
|
|
21
|
-
f"{main_url}/category/bilim-kurgu-filmleri-izle" : "Bilim Kurgu",
|
|
22
|
-
f"{main_url}/category/biyografi-filmleri-izle" : "Biyografi",
|
|
23
|
-
f"{main_url}/category/dram-filmleri-izle" : "Dram",
|
|
24
|
-
f"{main_url}/category/fantastik-filmler-izle" : "Fantastik",
|
|
25
|
-
f"{main_url}/category/gerilim-filmleri-izle" : "Gerilim",
|
|
26
|
-
f"{main_url}/category/gizem-filmleri-izle" : "Gizem",
|
|
27
|
-
f"{main_url}/category/kisa" : "Kısa",
|
|
28
|
-
f"{main_url}/category/komedi-filmleri-izle" : "Komedi",
|
|
29
|
-
f"{main_url}/category/korku-filmleri-izle" : "Korku",
|
|
30
|
-
f"{main_url}/category/macera-filmleri-izle" : "Macera",
|
|
31
|
-
f"{main_url}/category/muzik" : "Müzik",
|
|
32
|
-
f"{main_url}/category/muzikal-filmleri-izle" : "Müzikal",
|
|
33
|
-
f"{main_url}/category/romantik-filmler-izle" : "Romantik",
|
|
34
|
-
f"{main_url}/category/savas-filmleri-izle" : "Savaş",
|
|
35
|
-
f"{main_url}/category/spor-filmleri-izle" : "Spor",
|
|
36
|
-
f"{main_url}/category/suc-filmleri-izle" : "Suç",
|
|
37
|
-
f"{main_url}/category/tarih-filmleri-izle" : "Tarih",
|
|
38
|
-
f"{main_url}/category/western-filmleri-izle" : "Western",
|
|
39
|
-
}
|
|
40
|
-
|
|
41
|
-
async def get_main_page(self, page: int, url: str, category: str) -> list[MainPageResult]:
|
|
42
|
-
page_url = url if page == 1 else f"{url}/page/{page}"
|
|
43
|
-
|
|
44
|
-
self.httpx.headers.update({
|
|
45
|
-
"User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
|
|
46
|
-
"Referer" : f"{self.main_url}/"
|
|
47
|
-
})
|
|
48
|
-
|
|
49
|
-
istek = await self.httpx.get(page_url)
|
|
50
|
-
secici = HTMLHelper(istek.text)
|
|
51
|
-
|
|
52
|
-
results = []
|
|
53
|
-
for veri in secici.select("div.movie-poster"):
|
|
54
|
-
alt = secici.select_attr("img", "alt", veri)
|
|
55
|
-
poster = secici.select_attr("img", "src", veri)
|
|
56
|
-
href = secici.select_attr("a", "href", veri)
|
|
57
|
-
|
|
58
|
-
if alt and href:
|
|
59
|
-
results.append(MainPageResult(
|
|
60
|
-
category = category,
|
|
61
|
-
title = alt,
|
|
62
|
-
url = self.fix_url(href),
|
|
63
|
-
poster = self.fix_url(poster),
|
|
64
|
-
))
|
|
65
|
-
|
|
66
|
-
return results
|
|
67
|
-
|
|
68
|
-
async def search(self, query: str) -> list[SearchResult]:
|
|
69
|
-
istek = await self.httpx.get(f"{self.main_url}/?s={query}")
|
|
70
|
-
secici = HTMLHelper(istek.text)
|
|
71
|
-
|
|
72
|
-
results = []
|
|
73
|
-
for veri in secici.select("div.movie-poster"):
|
|
74
|
-
alt = secici.select_attr("img", "alt", veri)
|
|
75
|
-
poster = secici.select_attr("img", "src", veri)
|
|
76
|
-
href = secici.select_attr("a", "href", veri)
|
|
77
|
-
|
|
78
|
-
if alt and href:
|
|
79
|
-
results.append(SearchResult(
|
|
80
|
-
title = alt,
|
|
81
|
-
url = self.fix_url(href),
|
|
82
|
-
poster = self.fix_url(poster),
|
|
83
|
-
))
|
|
84
|
-
|
|
85
|
-
return results
|
|
86
|
-
|
|
87
|
-
async def load_item(self, url: str) -> MovieInfo | SeriesInfo:
|
|
88
|
-
istek = await self.httpx.get(url)
|
|
89
|
-
secici = HTMLHelper(istek.text)
|
|
90
|
-
|
|
91
|
-
title = self.clean_title(secici.select_text("h1"))
|
|
92
|
-
poster = secici.select_poster("div.poster img")
|
|
93
|
-
description = secici.select_text("div.film") or secici.select_attr("meta[property='og:description']", "content")
|
|
94
|
-
year = secici.extract_year("div.yayin-tarihi.info") or secici.regex_first(r"\((\d{4})\)")
|
|
95
|
-
tags = secici.select_texts("div.tur.info a")
|
|
96
|
-
rating = secici.regex_first(r"IMDb\s*([\d\.]+)", secici.select_text("div.imdb"))
|
|
97
|
-
actors = secici.select_direct_text("div.oyuncular")
|
|
98
|
-
|
|
99
|
-
# Kotlin referansı: URL'de -dizi veya tags içinde dizi kontrolü
|
|
100
|
-
is_series = "-dizi" in url.lower() or any("dizi" in tag.lower() for tag in tags)
|
|
101
|
-
|
|
102
|
-
if is_series:
|
|
103
|
-
episodes = []
|
|
104
|
-
for idx, el in enumerate(secici.select("li.psec")):
|
|
105
|
-
part_id = el.attrs.get("id")
|
|
106
|
-
part_name = secici.select_text("a", el) or ""
|
|
107
|
-
if not part_name or "fragman" in part_name.lower(): continue
|
|
108
|
-
|
|
109
|
-
s, e = secici.extract_season_episode(f"{part_id} {part_name}")
|
|
110
|
-
episodes.append(Episode(season=s or 1, episode=e or (idx+1), title=f"{s or 1}. Sezon {e or idx+1}. Bölüm", url=url))
|
|
111
|
-
|
|
112
|
-
return SeriesInfo(
|
|
113
|
-
url=url, poster=self.fix_url(poster), title=title, description=description,
|
|
114
|
-
tags=tags, year=year, actors=actors, rating=rating, episodes=episodes
|
|
115
|
-
)
|
|
116
|
-
|
|
117
|
-
return MovieInfo(
|
|
118
|
-
url=url, poster=self.fix_url(poster), title=title, description=description,
|
|
119
|
-
tags=tags, year=year, actors=actors, rating=rating
|
|
120
|
-
)
|
|
121
|
-
|
|
122
|
-
def _get_iframe(self, source_code: str) -> str:
|
|
123
|
-
"""Base64 kodlu iframe'i çözümle"""
|
|
124
|
-
script_val = HTMLHelper(source_code).regex_first(r'<script[^>]*>(PCEtLWJhc2xpazp[^<]*)</script>')
|
|
125
|
-
if not script_val:
|
|
126
|
-
return ""
|
|
127
|
-
|
|
128
|
-
try:
|
|
129
|
-
decoded_html = base64.b64decode(script_val).decode("utf-8")
|
|
130
|
-
iframe_src = HTMLHelper(decoded_html).regex_first(r'<iframe[^>]+src=["\']([^"\']+)["\']')
|
|
131
|
-
return self.fix_url(iframe_src) if iframe_src else ""
|
|
132
|
-
except Exception:
|
|
133
|
-
return ""
|
|
134
|
-
|
|
135
|
-
def _extract_subtitle_url(self, source_code: str) -> str | None:
|
|
136
|
-
"""playerjsSubtitle değişkeninden .srt URL çıkar"""
|
|
137
|
-
patterns = [
|
|
138
|
-
r'var playerjsSubtitle = "\[Türkçe\](https?://[^\s"]+?\.srt)";',
|
|
139
|
-
r'var playerjsSubtitle = "(https?://[^\s"]+?\.srt)";',
|
|
140
|
-
r'subtitle:\s*"(https?://[^\s"]+?\.srt)"',
|
|
141
|
-
]
|
|
142
|
-
|
|
143
|
-
for pattern in patterns:
|
|
144
|
-
val = HTMLHelper(source_code).regex_first(pattern)
|
|
145
|
-
if val:
|
|
146
|
-
return val
|
|
147
|
-
|
|
148
|
-
return None
|
|
149
|
-
|
|
150
|
-
async def load_links(self, url: str) -> list[ExtractResult]:
|
|
151
|
-
self.httpx.headers.update({
|
|
152
|
-
"User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
|
|
153
|
-
"Referer" : self.main_url
|
|
154
|
-
})
|
|
155
|
-
|
|
156
|
-
istek = await self.httpx.get(url)
|
|
157
|
-
source_code = istek.text
|
|
158
|
-
|
|
159
|
-
# Ana sayfadan altyazı URL'sini çek
|
|
160
|
-
subtitle_url = self._extract_subtitle_url(source_code)
|
|
161
|
-
|
|
162
|
-
# Iframe'den altyazı URL'sini çek
|
|
163
|
-
iframe_src = self._get_iframe(source_code)
|
|
164
|
-
|
|
165
|
-
if not subtitle_url and iframe_src:
|
|
166
|
-
iframe_istek = await self.httpx.get(iframe_src)
|
|
167
|
-
subtitle_url = self._extract_subtitle_url(iframe_istek.text)
|
|
168
|
-
|
|
169
|
-
results = []
|
|
170
|
-
|
|
171
|
-
if iframe_src:
|
|
172
|
-
data = await self.extract(iframe_src)
|
|
173
|
-
if data:
|
|
174
|
-
# ExtractResult objesi immutable, yeni bir kopya oluştur
|
|
175
|
-
subtitles = [Subtitle(name="Türkçe", url=subtitle_url)] if subtitle_url else []
|
|
176
|
-
updated_data = data.model_copy(update={"subtitles": subtitles}) if subtitles else data
|
|
177
|
-
results.append(updated_data)
|
|
178
|
-
|
|
179
|
-
return results
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|