KekikStream 2.0.2__py3-none-any.whl → 2.2.0__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 +7 -2
- KekikStream/Core/Plugin/PluginBase.py +61 -13
- KekikStream/Extractors/CloseLoad.py +17 -2
- KekikStream/Extractors/ContentX.py +19 -2
- KekikStream/Extractors/DonilasPlay.py +86 -0
- KekikStream/Extractors/Filemoon.py +78 -0
- KekikStream/Extractors/MixTiger.py +5 -5
- KekikStream/Extractors/Odnoklassniki.py +6 -0
- KekikStream/Extractors/PeaceMakerst.py +6 -0
- KekikStream/Extractors/PlayerFilmIzle.py +8 -5
- KekikStream/Extractors/RapidVid.py +21 -5
- KekikStream/Extractors/SetPlay.py +13 -4
- KekikStream/Extractors/VCTPlay.py +41 -0
- KekikStream/Extractors/VidHide.py +11 -2
- KekikStream/Extractors/VidMoly.py +52 -30
- KekikStream/Extractors/YTDLP.py +88 -54
- KekikStream/Plugins/BelgeselX.py +196 -0
- KekikStream/Plugins/DiziBox.py +8 -12
- KekikStream/Plugins/DiziPal.py +11 -22
- KekikStream/Plugins/DiziYou.py +9 -17
- KekikStream/Plugins/Dizilla.py +19 -14
- KekikStream/Plugins/FilmBip.py +5 -8
- KekikStream/Plugins/FilmMakinesi.py +31 -21
- KekikStream/Plugins/FilmModu.py +14 -18
- KekikStream/Plugins/FullHDFilm.py +83 -27
- KekikStream/Plugins/FullHDFilmizlesene.py +6 -8
- KekikStream/Plugins/HDFilmCehennemi.py +133 -57
- KekikStream/Plugins/JetFilmizle.py +29 -14
- KekikStream/Plugins/KultFilmler.py +13 -15
- KekikStream/Plugins/RecTV.py +16 -24
- KekikStream/Plugins/RoketDizi.py +22 -32
- KekikStream/Plugins/SelcukFlix.py +99 -80
- KekikStream/Plugins/SetFilmIzle.py +252 -0
- KekikStream/Plugins/SezonlukDizi.py +43 -9
- KekikStream/Plugins/SineWix.py +13 -21
- KekikStream/Plugins/Sinefy.py +13 -10
- KekikStream/Plugins/SinemaCX.py +35 -38
- KekikStream/Plugins/Sinezy.py +5 -8
- KekikStream/Plugins/SuperFilmGeldi.py +36 -27
- KekikStream/Plugins/UgurFilm.py +7 -9
- KekikStream/__init__.py +17 -36
- {kekikstream-2.0.2.dist-info → kekikstream-2.2.0.dist-info}/METADATA +6 -3
- kekikstream-2.2.0.dist-info/RECORD +81 -0
- KekikStream/Extractors/ContentX_.py +0 -40
- KekikStream/Extractors/FirePlayer.py +0 -60
- KekikStream/Extractors/Odnoklassniki_.py +0 -11
- KekikStream/Extractors/PeaceMakerst_.py +0 -7
- KekikStream/Extractors/RapidVid_.py +0 -7
- KekikStream/Extractors/VidMoly_.py +0 -7
- kekikstream-2.0.2.dist-info/RECORD +0 -82
- {kekikstream-2.0.2.dist-info → kekikstream-2.2.0.dist-info}/WHEEL +0 -0
- {kekikstream-2.0.2.dist-info → kekikstream-2.2.0.dist-info}/entry_points.txt +0 -0
- {kekikstream-2.0.2.dist-info → kekikstream-2.2.0.dist-info}/licenses/LICENSE +0 -0
- {kekikstream-2.0.2.dist-info → kekikstream-2.2.0.dist-info}/top_level.txt +0 -0
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
2
|
|
|
3
|
-
from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo,
|
|
3
|
+
from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo, SeriesInfo, Episode, Subtitle, ExtractResult
|
|
4
4
|
from parsel import Selector
|
|
5
5
|
from Kekik.Sifreleme import Packer, StreamDecoder
|
|
6
6
|
import random, string, re
|
|
@@ -10,9 +10,7 @@ class HDFilmCehennemi(PluginBase):
|
|
|
10
10
|
language = "tr"
|
|
11
11
|
main_url = "https://www.hdfilmcehennemi.ws"
|
|
12
12
|
favicon = f"https://www.google.com/s2/favicons?domain={main_url}&sz=64"
|
|
13
|
-
description = "Türkiye'nin en hızlı hd film izleme sitesi"
|
|
14
|
-
|
|
15
|
-
|
|
13
|
+
description = "Türkiye'nin en hızlı hd film izleme sitesi. Tek ve gerçek hdfilmcehennemi sitesi."
|
|
16
14
|
|
|
17
15
|
main_page = {
|
|
18
16
|
f"{main_url}" : "Yeni Eklenen Filmler",
|
|
@@ -73,41 +71,81 @@ class HDFilmCehennemi(PluginBase):
|
|
|
73
71
|
|
|
74
72
|
return results
|
|
75
73
|
|
|
76
|
-
async def load_item(self, url: str) -> MovieInfo:
|
|
74
|
+
async def load_item(self, url: str) -> MovieInfo | SeriesInfo:
|
|
77
75
|
istek = await self.httpx.get(url, headers = {"Referer": f"{self.main_url}/"})
|
|
78
76
|
secici = Selector(istek.text)
|
|
79
77
|
|
|
80
|
-
title = secici.css("h1.section-title::text").get()
|
|
81
|
-
|
|
82
|
-
|
|
78
|
+
title = secici.css("h1.section-title::text").get()
|
|
79
|
+
title = title.strip() if title else ""
|
|
80
|
+
poster = secici.css("aside.post-info-poster img.lazyload::attr(data-src)").get() or ""
|
|
81
|
+
poster = poster.strip() if poster else ""
|
|
82
|
+
description = secici.css("article.post-info-content > p::text").get() or ""
|
|
83
|
+
description = description.strip() if description else ""
|
|
83
84
|
tags = secici.css("div.post-info-genres a::text").getall()
|
|
84
|
-
rating = secici.css("div.post-info-imdb-rating span::text").get()
|
|
85
|
-
|
|
85
|
+
rating = secici.css("div.post-info-imdb-rating span::text").get() or ""
|
|
86
|
+
rating = rating.strip() if rating else ""
|
|
87
|
+
year = secici.css("div.post-info-year-country a::text").get() or ""
|
|
88
|
+
year = year.strip() if year else ""
|
|
86
89
|
actors = secici.css("div.post-info-cast a > strong::text").getall()
|
|
87
|
-
duration = secici.css("div.post-info-duration::text").get()
|
|
90
|
+
duration = secici.css("div.post-info-duration::text").get() or "0"
|
|
91
|
+
duration = duration.replace("dakika", "").strip()
|
|
88
92
|
|
|
89
|
-
|
|
90
93
|
try:
|
|
91
|
-
duration_minutes = int(duration
|
|
94
|
+
duration_minutes = int(re.search(r'\d+', duration).group()) if re.search(r'\d+', duration) else 0
|
|
92
95
|
except Exception:
|
|
93
96
|
duration_minutes = 0
|
|
94
97
|
|
|
95
|
-
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
98
|
+
# Dizi mi film mi kontrol et (Kotlin referansı: div.seasons kontrolü)
|
|
99
|
+
is_series = len(secici.css("div.seasons").getall()) > 0
|
|
100
|
+
|
|
101
|
+
if is_series:
|
|
102
|
+
episodes = []
|
|
103
|
+
for ep in secici.css("div.seasons-tab-content a"):
|
|
104
|
+
ep_name = ep.css("h4::text").get()
|
|
105
|
+
ep_href = ep.css("::attr(href)").get()
|
|
106
|
+
if ep_name and ep_href:
|
|
107
|
+
ep_name = ep_name.strip()
|
|
108
|
+
# Regex ile sezon ve bölüm numarası çıkar
|
|
109
|
+
ep_match = re.search(r'(\d+)\.\s*Bölüm', ep_name)
|
|
110
|
+
sz_match = re.search(r'(\d+)\.\s*Sezon', ep_name)
|
|
111
|
+
ep_num = int(ep_match.group(1)) if ep_match else 1
|
|
112
|
+
sz_num = int(sz_match.group(1)) if sz_match else 1
|
|
113
|
+
|
|
114
|
+
episodes.append(Episode(
|
|
115
|
+
season = sz_num,
|
|
116
|
+
episode = ep_num,
|
|
117
|
+
title = ep_name,
|
|
118
|
+
url = self.fix_url(ep_href)
|
|
119
|
+
))
|
|
120
|
+
|
|
121
|
+
return SeriesInfo(
|
|
122
|
+
url = url,
|
|
123
|
+
poster = self.fix_url(poster),
|
|
124
|
+
title = self.clean_title(title),
|
|
125
|
+
description = description,
|
|
126
|
+
tags = tags,
|
|
127
|
+
rating = rating,
|
|
128
|
+
year = year,
|
|
129
|
+
actors = actors,
|
|
130
|
+
episodes = episodes
|
|
131
|
+
)
|
|
132
|
+
else:
|
|
133
|
+
return MovieInfo(
|
|
134
|
+
url = url,
|
|
135
|
+
poster = self.fix_url(poster),
|
|
136
|
+
title = self.clean_title(title),
|
|
137
|
+
description = description,
|
|
138
|
+
tags = tags,
|
|
139
|
+
rating = rating,
|
|
140
|
+
year = year,
|
|
141
|
+
actors = actors,
|
|
142
|
+
duration = duration_minutes
|
|
143
|
+
)
|
|
106
144
|
|
|
107
145
|
def generate_random_cookie(self):
|
|
108
146
|
return "".join(random.choices(string.ascii_letters + string.digits, k=16))
|
|
109
147
|
|
|
110
|
-
async def cehennempass(self, video_id: str) -> list
|
|
148
|
+
async def cehennempass(self, video_id: str) -> list:
|
|
111
149
|
results = []
|
|
112
150
|
|
|
113
151
|
istek = await self.httpx.post(
|
|
@@ -121,11 +159,11 @@ class HDFilmCehennemi(PluginBase):
|
|
|
121
159
|
data = {"video_id": video_id, "selected_quality": "low"},
|
|
122
160
|
)
|
|
123
161
|
if video_url := istek.json().get("download_link"):
|
|
124
|
-
results.append(
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
162
|
+
results.append(ExtractResult(
|
|
163
|
+
url = self.fix_url(video_url),
|
|
164
|
+
name = "Düşük Kalite",
|
|
165
|
+
referer = f"https://cehennempass.pw/download/{video_id}"
|
|
166
|
+
))
|
|
129
167
|
|
|
130
168
|
istek = await self.httpx.post(
|
|
131
169
|
url = "https://cehennempass.pw/process_quality_selection.php",
|
|
@@ -138,25 +176,64 @@ class HDFilmCehennemi(PluginBase):
|
|
|
138
176
|
data = {"video_id": video_id, "selected_quality": "high"},
|
|
139
177
|
)
|
|
140
178
|
if video_url := istek.json().get("download_link"):
|
|
141
|
-
results.append(
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
179
|
+
results.append(ExtractResult(
|
|
180
|
+
url = self.fix_url(video_url),
|
|
181
|
+
name = "Yüksek Kalite",
|
|
182
|
+
referer = f"https://cehennempass.pw/download/{video_id}"
|
|
183
|
+
))
|
|
146
184
|
|
|
147
185
|
return results
|
|
148
186
|
|
|
187
|
+
def extract_hdch_url(self, unpacked: str) -> str:
|
|
188
|
+
"""HDFilmCehennemi unpacked script'ten video URL'sini çıkar"""
|
|
189
|
+
# 1) Decode fonksiyonunun adını bul: function <NAME>(value_parts)
|
|
190
|
+
match_fn = re.search(r'function\s+(\w+)\s*\(\s*value_parts\s*\)', unpacked)
|
|
191
|
+
if not match_fn:
|
|
192
|
+
return ""
|
|
193
|
+
|
|
194
|
+
fn_name = match_fn.group(1)
|
|
195
|
+
|
|
196
|
+
# 2) Bu fonksiyonun array ile çağrıldığı yeri bul: <NAME>([ ... ])
|
|
197
|
+
array_call_regex = re.compile(rf'{re.escape(fn_name)}\(\s*\[(.*?)\]\s*\)', re.DOTALL)
|
|
198
|
+
match_call = array_call_regex.search(unpacked)
|
|
199
|
+
if not match_call:
|
|
200
|
+
return ""
|
|
201
|
+
|
|
202
|
+
array_body = match_call.group(1)
|
|
203
|
+
|
|
204
|
+
# 3) Array içindeki string parçalarını topla
|
|
205
|
+
parts = re.findall(r'["\']([^"\']+)["\']', array_body)
|
|
206
|
+
if not parts:
|
|
207
|
+
return ""
|
|
208
|
+
|
|
209
|
+
# 4) Özel decoder ile çöz
|
|
210
|
+
return StreamDecoder._brute_force(parts)
|
|
211
|
+
|
|
149
212
|
async def invoke_local_source(self, iframe: str, source: str, url: str):
|
|
150
|
-
self.httpx.headers.update({
|
|
213
|
+
self.httpx.headers.update({
|
|
214
|
+
"Referer": f"{self.main_url}/",
|
|
215
|
+
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:137.0) Gecko/20100101 Firefox/137.0"
|
|
216
|
+
})
|
|
151
217
|
istek = await self.httpx.get(iframe)
|
|
152
218
|
|
|
219
|
+
if not istek.text:
|
|
220
|
+
return await self.cehennempass(iframe.split("/")[-1])
|
|
221
|
+
|
|
222
|
+
# eval(function...) içeren packed script bul
|
|
223
|
+
eval_match = re.search(r'(eval\(function[\s\S]+)', istek.text)
|
|
224
|
+
if not eval_match:
|
|
225
|
+
return await self.cehennempass(iframe.split("/")[-1])
|
|
226
|
+
|
|
153
227
|
try:
|
|
154
|
-
|
|
228
|
+
unpacked = Packer.unpack(eval_match.group(1))
|
|
155
229
|
except Exception:
|
|
156
230
|
return await self.cehennempass(iframe.split("/")[-1])
|
|
157
231
|
|
|
158
|
-
|
|
159
|
-
video_url =
|
|
232
|
+
# HDFilmCehennemi özel decoder ile video URL'sini çıkar
|
|
233
|
+
video_url = self.extract_hdch_url(unpacked)
|
|
234
|
+
|
|
235
|
+
if not video_url:
|
|
236
|
+
return await self.cehennempass(iframe.split("/")[-1])
|
|
160
237
|
|
|
161
238
|
subtitles = []
|
|
162
239
|
try:
|
|
@@ -169,14 +246,14 @@ class HDFilmCehennemi(PluginBase):
|
|
|
169
246
|
except Exception:
|
|
170
247
|
pass
|
|
171
248
|
|
|
172
|
-
return [
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
249
|
+
return [ExtractResult(
|
|
250
|
+
url = video_url,
|
|
251
|
+
name = source,
|
|
252
|
+
referer = url,
|
|
253
|
+
subtitles = subtitles
|
|
254
|
+
)]
|
|
178
255
|
|
|
179
|
-
async def load_links(self, url: str) -> list[
|
|
256
|
+
async def load_links(self, url: str) -> list[ExtractResult]:
|
|
180
257
|
istek = await self.httpx.get(url)
|
|
181
258
|
secici = Selector(istek.text)
|
|
182
259
|
|
|
@@ -200,8 +277,15 @@ class HDFilmCehennemi(PluginBase):
|
|
|
200
277
|
match = re.search(r'data-src=\\\"([^"]+)', api_get.text)
|
|
201
278
|
iframe = match[1].replace("\\", "") if match else None
|
|
202
279
|
|
|
203
|
-
if
|
|
204
|
-
|
|
280
|
+
if not iframe:
|
|
281
|
+
continue
|
|
282
|
+
|
|
283
|
+
# mobi URL'si varsa direkt kullan (query string'i kaldır)
|
|
284
|
+
if "mobi" in iframe:
|
|
285
|
+
iframe = iframe.split("?")[0] # rapidrame_id query param'ı kaldır
|
|
286
|
+
# mobi değilse ve rapidrame varsa rplayer kullan
|
|
287
|
+
elif "rapidrame" in iframe and "?rapidrame_id=" in iframe:
|
|
288
|
+
iframe = f"{self.main_url}/rplayer/{iframe.split('?rapidrame_id=')[1]}"
|
|
205
289
|
|
|
206
290
|
video_data_list = await self.invoke_local_source(iframe, source, url)
|
|
207
291
|
if not video_data_list:
|
|
@@ -210,12 +294,4 @@ class HDFilmCehennemi(PluginBase):
|
|
|
210
294
|
for video_data in video_data_list:
|
|
211
295
|
results.append(video_data)
|
|
212
296
|
|
|
213
|
-
return results
|
|
214
|
-
|
|
215
|
-
async def play(self, **kwargs):
|
|
216
|
-
extract_result = ExtractResult(**kwargs)
|
|
217
|
-
self.media_handler.title = kwargs.get("name")
|
|
218
|
-
if self.name not in self.media_handler.title:
|
|
219
|
-
self.media_handler.title = f"{self.name} | {self.media_handler.title}"
|
|
220
|
-
|
|
221
|
-
self.media_handler.play_media(extract_result)
|
|
297
|
+
return results
|
|
@@ -1,14 +1,15 @@
|
|
|
1
1
|
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
2
|
|
|
3
|
-
from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo
|
|
3
|
+
from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo, ExtractResult
|
|
4
4
|
from parsel import Selector
|
|
5
|
+
import re
|
|
5
6
|
|
|
6
7
|
class JetFilmizle(PluginBase):
|
|
7
8
|
name = "JetFilmizle"
|
|
8
9
|
language = "tr"
|
|
9
10
|
main_url = "https://jetfilmizle.website"
|
|
10
11
|
favicon = f"https://www.google.com/s2/favicons?domain={main_url}&sz=64"
|
|
11
|
-
description = "
|
|
12
|
+
description = "Film izle, Yerli, Yabancı film izle, Türkçe dublaj, alt yazılı seçenekleriyle ödül almış filmleri Full HD kalitesiyle ve jetfilmizle hızıyla donmadan ücretsizce izleyebilirsiniz."
|
|
12
13
|
|
|
13
14
|
main_page = {
|
|
14
15
|
f"{main_url}/page/" : "Son Filmler",
|
|
@@ -16,7 +17,25 @@ class JetFilmizle(PluginBase):
|
|
|
16
17
|
f"{main_url}/editorun-secimi/page/" : "Editörün Seçimi",
|
|
17
18
|
f"{main_url}/turk-film-izle/page/" : "Türk Filmleri",
|
|
18
19
|
f"{main_url}/cizgi-filmler-izle/page/" : "Çizgi Filmler",
|
|
19
|
-
f"{main_url}/kategoriler/yesilcam-filmleri-izlee/page/" : "Yeşilçam Filmleri"
|
|
20
|
+
f"{main_url}/kategoriler/yesilcam-filmleri-izlee/page/" : "Yeşilçam Filmleri",
|
|
21
|
+
f"{main_url}/film-turu/aile-filmleri-izle/page/" : "Aile Filmleri",
|
|
22
|
+
f"{main_url}/film-turu/aksiyon-filmleri/page/" : "Aksiyon Filmleri",
|
|
23
|
+
f"{main_url}/film-turu/animasyon-filmler-izle/page/" : "Animasyon Filmleri",
|
|
24
|
+
f"{main_url}/film-turu/bilim-kurgu-filmler/page/" : "Bilim Kurgu Filmleri",
|
|
25
|
+
f"{main_url}/film-turu/dram-filmleri-izle/page/" : "Dram Filmleri",
|
|
26
|
+
f"{main_url}/film-turu/fantastik-filmleri-izle/page/" : "Fantastik Filmler",
|
|
27
|
+
f"{main_url}/film-turu/gerilim-filmleri/page/" : "Gerilim Filmleri",
|
|
28
|
+
f"{main_url}/film-turu/gizem-filmleri/page/" : "Gizem Filmleri",
|
|
29
|
+
f"{main_url}/film-turu/komedi-film-full-izle/page/" : "Komedi Filmleri",
|
|
30
|
+
f"{main_url}/film-turu/korku-filmleri-izle/page/" : "Korku Filmleri",
|
|
31
|
+
f"{main_url}/film-turu/macera-filmleri/page/" : "Macera Filmleri",
|
|
32
|
+
f"{main_url}/film-turu/muzikal/page/" : "Müzikal Filmler",
|
|
33
|
+
f"{main_url}/film-turu/polisiye/page/" : "Polisiye Filmler",
|
|
34
|
+
f"{main_url}/film-turu/romantik-film-izle/page/" : "Romantik Filmler",
|
|
35
|
+
f"{main_url}/film-turu/savas-filmi-izle/page/" : "Savaş Filmleri",
|
|
36
|
+
f"{main_url}/film-turu/spor/page/" : "Spor Filmleri",
|
|
37
|
+
f"{main_url}/film-turu/suc-filmleri/page/" : "Suç Filmleri",
|
|
38
|
+
f"{main_url}/film-turu/tarihi-filmler/page/" : "Tarihi Filmleri",
|
|
20
39
|
}
|
|
21
40
|
|
|
22
41
|
async def get_main_page(self, page: int, url: str, category: str) -> list[MainPageResult]:
|
|
@@ -96,7 +115,7 @@ class JetFilmizle(PluginBase):
|
|
|
96
115
|
actors = actors
|
|
97
116
|
)
|
|
98
117
|
|
|
99
|
-
async def load_links(self, url: str) -> list[
|
|
118
|
+
async def load_links(self, url: str) -> list[ExtractResult]:
|
|
100
119
|
istek = await self.httpx.get(url)
|
|
101
120
|
secici = Selector(istek.text)
|
|
102
121
|
|
|
@@ -110,11 +129,9 @@ class JetFilmizle(PluginBase):
|
|
|
110
129
|
|
|
111
130
|
if src and src != "about:blank":
|
|
112
131
|
iframe_url = self.fix_url(src)
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
"name": extractor.name if extractor else "Ana Player"
|
|
117
|
-
})
|
|
132
|
+
data = await self.extract(iframe_url)
|
|
133
|
+
if data:
|
|
134
|
+
results.append(data)
|
|
118
135
|
|
|
119
136
|
# 2) Sayfa numaralarından linkleri topla (Fragman hariç)
|
|
120
137
|
page_links = []
|
|
@@ -138,11 +155,9 @@ class JetFilmizle(PluginBase):
|
|
|
138
155
|
|
|
139
156
|
if src and src != "about:blank":
|
|
140
157
|
iframe_url = self.fix_url(src)
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
"name": f"{extractor.name if extractor else 'Player'} | {isim}"
|
|
145
|
-
})
|
|
158
|
+
data = await self.extract(iframe_url, prefix=isim)
|
|
159
|
+
if data:
|
|
160
|
+
results.append(data)
|
|
146
161
|
except Exception:
|
|
147
162
|
continue
|
|
148
163
|
|
|
@@ -9,7 +9,7 @@ class KultFilmler(PluginBase):
|
|
|
9
9
|
language = "tr"
|
|
10
10
|
main_url = "https://kultfilmler.net"
|
|
11
11
|
favicon = f"https://www.google.com/s2/favicons?domain={main_url}&sz=64"
|
|
12
|
-
description = "Kült
|
|
12
|
+
description = "Kült Filmler özenle en iyi filmleri derler ve iyi bir altyazılı film izleme deneyimi sunmayı amaçlar. Reklamsız 1080P Altyazılı Film izle..."
|
|
13
13
|
|
|
14
14
|
main_page = {
|
|
15
15
|
f"{main_url}/category/aile-filmleri-izle" : "Aile",
|
|
@@ -160,7 +160,7 @@ class KultFilmler(PluginBase):
|
|
|
160
160
|
match = re.search(r"(https?://[^\s\"]+\.srt)", source_code)
|
|
161
161
|
return match[1] if match else None
|
|
162
162
|
|
|
163
|
-
async def load_links(self, url: str) -> list[
|
|
163
|
+
async def load_links(self, url: str) -> list[ExtractResult]:
|
|
164
164
|
istek = await self.httpx.get(url)
|
|
165
165
|
secici = Selector(istek.text)
|
|
166
166
|
|
|
@@ -195,12 +195,12 @@ class KultFilmler(PluginBase):
|
|
|
195
195
|
m3u_match = re.search(r'file:"([^"]+)"', iframe_istek.text)
|
|
196
196
|
|
|
197
197
|
if m3u_match:
|
|
198
|
-
results.append(
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
198
|
+
results.append(ExtractResult(
|
|
199
|
+
name = "VidMoly",
|
|
200
|
+
url = m3u_match[1],
|
|
201
|
+
referer = self.main_url,
|
|
202
|
+
subtitles = []
|
|
203
|
+
))
|
|
204
204
|
continue
|
|
205
205
|
|
|
206
206
|
# Altyazı çıkar
|
|
@@ -208,12 +208,10 @@ class KultFilmler(PluginBase):
|
|
|
208
208
|
if subtitle_url:
|
|
209
209
|
subtitles.append(Subtitle(name="Türkçe", url=subtitle_url))
|
|
210
210
|
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
|
|
214
|
-
"
|
|
215
|
-
|
|
216
|
-
"subtitles" : subtitles
|
|
217
|
-
})
|
|
211
|
+
data = await self.extract(iframe)
|
|
212
|
+
if data:
|
|
213
|
+
# ExtractResult objesi immutable, yeni bir kopya oluştur
|
|
214
|
+
updated_data = data.model_copy(update={"subtitles": subtitles}) if subtitles else data
|
|
215
|
+
results.append(updated_data)
|
|
218
216
|
|
|
219
217
|
return results
|
KekikStream/Plugins/RecTV.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
2
|
|
|
3
|
-
from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo, Episode, SeriesInfo, ExtractResult
|
|
3
|
+
from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo, Episode, SeriesInfo, ExtractResult
|
|
4
4
|
from json import dumps, loads
|
|
5
5
|
import re
|
|
6
6
|
|
|
@@ -116,21 +116,21 @@ class RecTV(PluginBase):
|
|
|
116
116
|
actors = []
|
|
117
117
|
)
|
|
118
118
|
|
|
119
|
-
async def load_links(self, url: str) -> list[
|
|
119
|
+
async def load_links(self, url: str) -> list[ExtractResult]:
|
|
120
120
|
try:
|
|
121
121
|
veri = loads(url)
|
|
122
122
|
except Exception:
|
|
123
123
|
# JSON değilse düz URL'dir (eski yapı veya hata)
|
|
124
|
-
return [
|
|
124
|
+
return [ExtractResult(url=url, name="Video")]
|
|
125
125
|
|
|
126
126
|
# Eğer dizi bölümü ise (bizim oluşturduğumuz yapı)
|
|
127
127
|
if veri.get("is_episode"):
|
|
128
|
-
return [
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
128
|
+
return [ExtractResult(
|
|
129
|
+
url = veri.get("url"),
|
|
130
|
+
name = veri.get("title", "Bölüm"),
|
|
131
|
+
user_agent = "googleusercontent",
|
|
132
|
+
referer = "https://twitter.com/"
|
|
133
|
+
)]
|
|
134
134
|
|
|
135
135
|
# Film ise (RecTV API yapısı)
|
|
136
136
|
results = []
|
|
@@ -140,19 +140,11 @@ class RecTV(PluginBase):
|
|
|
140
140
|
if "otolinkaff" in video_link:
|
|
141
141
|
continue
|
|
142
142
|
|
|
143
|
-
results.append(
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
143
|
+
results.append(ExtractResult(
|
|
144
|
+
url = video_link,
|
|
145
|
+
name = f"{veri.get('title')} - {kaynak.get('title')}",
|
|
146
|
+
user_agent = "googleusercontent",
|
|
147
|
+
referer = "https://twitter.com/"
|
|
148
|
+
))
|
|
149
149
|
|
|
150
|
-
return results
|
|
151
|
-
|
|
152
|
-
async def play(self, **kwargs):
|
|
153
|
-
extract_result = ExtractResult(**kwargs)
|
|
154
|
-
self.media_handler.title = kwargs.get("name")
|
|
155
|
-
if self.name not in self.media_handler.title:
|
|
156
|
-
self.media_handler.title = f"{self.name} | {self.media_handler.title}"
|
|
157
|
-
|
|
158
|
-
self.media_handler.play_media(extract_result)
|
|
150
|
+
return results
|
KekikStream/Plugins/RoketDizi.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
2
|
|
|
3
|
-
from KekikStream.Core import PluginBase, MainPageResult, SearchResult, SeriesInfo, Episode, MovieInfo
|
|
3
|
+
from KekikStream.Core import PluginBase, MainPageResult, SearchResult, SeriesInfo, Episode, ExtractResult, MovieInfo
|
|
4
4
|
from parsel import Selector
|
|
5
5
|
import re, base64, json
|
|
6
6
|
|
|
@@ -169,7 +169,7 @@ class RoketDizi(PluginBase):
|
|
|
169
169
|
year = year
|
|
170
170
|
)
|
|
171
171
|
|
|
172
|
-
async def load_links(self, url: str) -> list[
|
|
172
|
+
async def load_links(self, url: str) -> list[ExtractResult]:
|
|
173
173
|
resp = await self.httpx.get(url)
|
|
174
174
|
sel = Selector(resp.text)
|
|
175
175
|
|
|
@@ -185,6 +185,7 @@ class RoketDizi(PluginBase):
|
|
|
185
185
|
# secureData içindeki RelatedResults -> getEpisodeSources -> result dizisini al
|
|
186
186
|
sources = decoded_json.get("RelatedResults", {}).get("getEpisodeSources", {}).get("result", [])
|
|
187
187
|
|
|
188
|
+
seen_urls = set()
|
|
188
189
|
results = []
|
|
189
190
|
for source in sources:
|
|
190
191
|
source_content = source.get("source_content", "")
|
|
@@ -195,36 +196,25 @@ class RoketDizi(PluginBase):
|
|
|
195
196
|
continue
|
|
196
197
|
|
|
197
198
|
iframe_url = iframe_match.group(1)
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
#
|
|
209
|
-
|
|
210
|
-
|
|
211
|
-
|
|
212
|
-
|
|
213
|
-
#
|
|
214
|
-
|
|
215
|
-
if
|
|
216
|
-
|
|
217
|
-
if ext_name:
|
|
218
|
-
name_parts.append(ext_name)
|
|
219
|
-
if language_name:
|
|
220
|
-
name_parts.append(language_name)
|
|
221
|
-
if quality_name:
|
|
222
|
-
name_parts.append(quality_name)
|
|
223
|
-
|
|
224
|
-
results.append({
|
|
225
|
-
"url" : iframe_url,
|
|
226
|
-
"name" : " | ".join(name_parts)
|
|
227
|
-
})
|
|
199
|
+
|
|
200
|
+
# Fix URL protocol
|
|
201
|
+
if not iframe_url.startswith("http"):
|
|
202
|
+
if iframe_url.startswith("//"):
|
|
203
|
+
iframe_url = "https:" + iframe_url
|
|
204
|
+
else:
|
|
205
|
+
iframe_url = "https://" + iframe_url
|
|
206
|
+
|
|
207
|
+
iframe_url = self.fix_url(iframe_url)
|
|
208
|
+
|
|
209
|
+
# Deduplicate
|
|
210
|
+
if iframe_url in seen_urls:
|
|
211
|
+
continue
|
|
212
|
+
seen_urls.add(iframe_url)
|
|
213
|
+
|
|
214
|
+
# Extract with helper
|
|
215
|
+
data = await self.extract(iframe_url)
|
|
216
|
+
if data:
|
|
217
|
+
results.append(data)
|
|
228
218
|
|
|
229
219
|
return results
|
|
230
220
|
|