KekikStream 2.3.9__py3-none-any.whl → 2.5.3__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 +30 -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.3.dist-info}/METADATA +1 -1
- kekikstream-2.5.3.dist-info/RECORD +99 -0
- {kekikstream-2.3.9.dist-info → kekikstream-2.5.3.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.3.dist-info}/entry_points.txt +0 -0
- {kekikstream-2.3.9.dist-info → kekikstream-2.5.3.dist-info}/licenses/LICENSE +0 -0
- {kekikstream-2.3.9.dist-info → kekikstream-2.5.3.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,243 @@
|
|
|
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, asyncio, contextlib
|
|
5
|
+
|
|
6
|
+
class HDFilm(PluginBase):
|
|
7
|
+
name = "HDFilm"
|
|
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
|
+
istek = await self.httpx.get(url if page == 1 else f"{url}/page/{page}")
|
|
43
|
+
secici = HTMLHelper(istek.text)
|
|
44
|
+
|
|
45
|
+
results = []
|
|
46
|
+
for veri in secici.select("div.movie-poster"):
|
|
47
|
+
title = secici.select_attr("img", "alt", veri)
|
|
48
|
+
poster = secici.select_attr("img", "src", veri)
|
|
49
|
+
href = secici.select_attr("a", "href", veri)
|
|
50
|
+
|
|
51
|
+
if title and href:
|
|
52
|
+
results.append(MainPageResult(
|
|
53
|
+
category = category,
|
|
54
|
+
title = self.clean_title(title),
|
|
55
|
+
url = self.fix_url(href),
|
|
56
|
+
poster = self.fix_url(poster)
|
|
57
|
+
))
|
|
58
|
+
|
|
59
|
+
return results
|
|
60
|
+
|
|
61
|
+
async def search(self, query: str) -> list[SearchResult]:
|
|
62
|
+
istek = await self.httpx.get(f"{self.main_url}/?s={query}")
|
|
63
|
+
secici = HTMLHelper(istek.text)
|
|
64
|
+
|
|
65
|
+
results = []
|
|
66
|
+
for veri in secici.select("div.movie-poster"):
|
|
67
|
+
title = secici.select_attr("img", "alt", veri)
|
|
68
|
+
poster = secici.select_attr("img", "src", veri)
|
|
69
|
+
href = secici.select_attr("a", "href", veri)
|
|
70
|
+
|
|
71
|
+
if title and href:
|
|
72
|
+
results.append(SearchResult(
|
|
73
|
+
title = self.clean_title(title),
|
|
74
|
+
url = self.fix_url(href),
|
|
75
|
+
poster = self.fix_url(poster)
|
|
76
|
+
))
|
|
77
|
+
|
|
78
|
+
return results
|
|
79
|
+
|
|
80
|
+
async def load_item(self, url: str) -> MovieInfo | SeriesInfo:
|
|
81
|
+
istek = await self.httpx.get(url)
|
|
82
|
+
secici = HTMLHelper(istek.text)
|
|
83
|
+
|
|
84
|
+
title = self.clean_title(secici.select_text("h1"))
|
|
85
|
+
poster = secici.select_poster("div.poster img")
|
|
86
|
+
description = secici.select_text("div.film") or secici.select_attr("meta[property='og:description']", "content")
|
|
87
|
+
year = secici.extract_year("div.yayin-tarihi.info") or secici.regex_first(r"\((\d{4})\)")
|
|
88
|
+
tags = secici.select_texts("div.tur.info a")
|
|
89
|
+
rating = secici.regex_first(r"IMDb\s*([\d\.]+)", secici.select_text("div.imdb"))
|
|
90
|
+
actors = secici.select_direct_text("div.oyuncular")
|
|
91
|
+
|
|
92
|
+
is_series = "-dizi" in url.lower() or any("dizi" in tag.lower() for tag in tags)
|
|
93
|
+
if is_series:
|
|
94
|
+
episodes = []
|
|
95
|
+
for idx, el in enumerate(secici.select("li.psec")):
|
|
96
|
+
part_id = el.attrs.get("id")
|
|
97
|
+
part_name = secici.select_text("a", el) or ""
|
|
98
|
+
if not part_name or "fragman" in part_name.lower():
|
|
99
|
+
continue
|
|
100
|
+
|
|
101
|
+
s, e = secici.extract_season_episode(f"{part_id} {part_name}")
|
|
102
|
+
episodes.append(Episode(
|
|
103
|
+
season = s or 1,
|
|
104
|
+
episode = e or (idx+1),
|
|
105
|
+
title = f"{s or 1}. Sezon {e or idx+1}. Bölüm",
|
|
106
|
+
url = url
|
|
107
|
+
))
|
|
108
|
+
|
|
109
|
+
return SeriesInfo(
|
|
110
|
+
url = url,
|
|
111
|
+
poster = self.fix_url(poster),
|
|
112
|
+
title = title,
|
|
113
|
+
description = description,
|
|
114
|
+
tags = tags,
|
|
115
|
+
year = year,
|
|
116
|
+
actors = actors,
|
|
117
|
+
rating = rating,
|
|
118
|
+
episodes = episodes
|
|
119
|
+
)
|
|
120
|
+
|
|
121
|
+
return MovieInfo(
|
|
122
|
+
url = url,
|
|
123
|
+
poster = self.fix_url(poster),
|
|
124
|
+
title = title,
|
|
125
|
+
description = description,
|
|
126
|
+
tags = tags,
|
|
127
|
+
year = year,
|
|
128
|
+
actors = actors,
|
|
129
|
+
rating = rating
|
|
130
|
+
)
|
|
131
|
+
|
|
132
|
+
def _get_iframe(self, source_code: str) -> str:
|
|
133
|
+
"""Base64 kodlu iframe'i çözümle"""
|
|
134
|
+
script_val = HTMLHelper(source_code).regex_first(r'<script[^>]*>(PCEtLWJhc2xpazp[^<]*)</script>')
|
|
135
|
+
if not script_val:
|
|
136
|
+
return ""
|
|
137
|
+
|
|
138
|
+
try:
|
|
139
|
+
decoded_html = base64.b64decode(script_val).decode("utf-8")
|
|
140
|
+
iframe_src = HTMLHelper(decoded_html).regex_first(r'<iframe[^>]+src=["\']([^"\']+)["\']')
|
|
141
|
+
return self.fix_url(iframe_src) if iframe_src else ""
|
|
142
|
+
except Exception:
|
|
143
|
+
return ""
|
|
144
|
+
|
|
145
|
+
def _extract_subtitle_url(self, source_code: str) -> str | None:
|
|
146
|
+
"""playerjsSubtitle değişkeninden .srt URL çıkar"""
|
|
147
|
+
patterns = [
|
|
148
|
+
r'var playerjsSubtitle = "\[Türkçe\](https?://[^\s"]+?\.srt)";',
|
|
149
|
+
r'var playerjsSubtitle = "(https?://[^\s"]+?\.srt)";',
|
|
150
|
+
r'subtitle:\s*"(https?://[^\s"]+?\.srt)"',
|
|
151
|
+
]
|
|
152
|
+
|
|
153
|
+
for pattern in patterns:
|
|
154
|
+
val = HTMLHelper(source_code).regex_first(pattern)
|
|
155
|
+
if val:
|
|
156
|
+
return val
|
|
157
|
+
|
|
158
|
+
return None
|
|
159
|
+
|
|
160
|
+
async def _get_source_links(self, url: str, initial_text: str | None = None) -> list[ExtractResult]:
|
|
161
|
+
results = []
|
|
162
|
+
try:
|
|
163
|
+
if initial_text:
|
|
164
|
+
source_code = initial_text
|
|
165
|
+
secici = HTMLHelper(source_code)
|
|
166
|
+
else:
|
|
167
|
+
resp = await self.httpx.get(url)
|
|
168
|
+
source_code = resp.text
|
|
169
|
+
secici = HTMLHelper(source_code)
|
|
170
|
+
|
|
171
|
+
iframe_src = self._get_iframe(source_code)
|
|
172
|
+
subtitle_url = self._extract_subtitle_url(source_code)
|
|
173
|
+
|
|
174
|
+
# İsim Oluştur (Dil | Player)
|
|
175
|
+
parts = []
|
|
176
|
+
|
|
177
|
+
if action_parts := secici.select_first("div#action-parts"):
|
|
178
|
+
# Aktif olan wrapper'ları bul
|
|
179
|
+
for wrapper in secici.select("div.button-custom-wrapper", action_parts):
|
|
180
|
+
# Aktif buton/link
|
|
181
|
+
active_el = secici.select_first("button", wrapper) or secici.select_first("a.button", wrapper)
|
|
182
|
+
if active_el:
|
|
183
|
+
parts.append(active_el.text(strip=True))
|
|
184
|
+
|
|
185
|
+
final_name = " | ".join(parts) if parts else "HDFilm"
|
|
186
|
+
|
|
187
|
+
if not subtitle_url and iframe_src:
|
|
188
|
+
with contextlib.suppress(Exception):
|
|
189
|
+
iframe_istek = await self.httpx.get(iframe_src)
|
|
190
|
+
subtitle_url = self._extract_subtitle_url(iframe_istek.text)
|
|
191
|
+
|
|
192
|
+
if iframe_src:
|
|
193
|
+
data = await self.extract(iframe_src, name_override=final_name)
|
|
194
|
+
if data:
|
|
195
|
+
sub = Subtitle(name="Türkçe", url=subtitle_url) if subtitle_url else None
|
|
196
|
+
if isinstance(data, list):
|
|
197
|
+
for d in data:
|
|
198
|
+
if sub:
|
|
199
|
+
d.subtitles.append(sub)
|
|
200
|
+
results.append(d)
|
|
201
|
+
else:
|
|
202
|
+
if sub:
|
|
203
|
+
data.subtitles.append(sub)
|
|
204
|
+
results.append(data)
|
|
205
|
+
|
|
206
|
+
return results
|
|
207
|
+
except Exception:
|
|
208
|
+
return []
|
|
209
|
+
|
|
210
|
+
async def load_links(self, url: str) -> list[ExtractResult]:
|
|
211
|
+
initial_istek = await self.httpx.get(url)
|
|
212
|
+
initial_text = initial_istek.text
|
|
213
|
+
secici = HTMLHelper(initial_text)
|
|
214
|
+
|
|
215
|
+
base_url = url.split("?")[0].rstrip("/")
|
|
216
|
+
unique_urls = {base_url} # ?page=1 varsa da base_url olarak sakla
|
|
217
|
+
|
|
218
|
+
if action_parts := secici.select_first("div#action-parts"):
|
|
219
|
+
for link in secici.select("a[href]", action_parts):
|
|
220
|
+
href = link.attrs.get("href", "")
|
|
221
|
+
if "?page=" in href:
|
|
222
|
+
if href.endswith("?page=1") or href == "?page=1":
|
|
223
|
+
unique_urls.add(base_url)
|
|
224
|
+
elif href.startswith("?"):
|
|
225
|
+
unique_urls.add(f"{base_url}{href}")
|
|
226
|
+
else:
|
|
227
|
+
unique_urls.add(self.fix_url(href))
|
|
228
|
+
|
|
229
|
+
tasks = []
|
|
230
|
+
for p_url in unique_urls:
|
|
231
|
+
# Eğer p_url şu anki url ile eşleşiyorsa (veya ?page=1 farkı varsa) metni kullan
|
|
232
|
+
# Basit eşleşme: Eğer p_url == base_url ve (url == base_url veya url == base_url + "?page=1")
|
|
233
|
+
|
|
234
|
+
use_initial = False
|
|
235
|
+
if p_url == base_url:
|
|
236
|
+
if url.rstrip("/") == base_url or url.rstrip("/") == f"{base_url}?page=1":
|
|
237
|
+
use_initial = True
|
|
238
|
+
elif p_url == url.rstrip("/"):
|
|
239
|
+
use_initial = True
|
|
240
|
+
|
|
241
|
+
tasks.append(self._get_source_links(p_url, initial_text if use_initial else None))
|
|
242
|
+
|
|
243
|
+
return [item for sublist in await asyncio.gather(*tasks) for item in sublist]
|