KekikStream 2.4.6__py3-none-any.whl → 2.4.7__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.
Potentially problematic release.
This version of KekikStream might be problematic. Click here for more details.
- KekikStream/Core/HTMLHelper.py +2 -2
- KekikStream/Core/Plugin/PluginBase.py +15 -4
- KekikStream/Extractors/Odnoklassniki.py +14 -2
- KekikStream/Extractors/YTDLP.py +2 -2
- KekikStream/Plugins/BelgeselX.py +27 -19
- KekikStream/Plugins/DiziBox.py +11 -8
- KekikStream/Plugins/DiziMom.py +71 -53
- KekikStream/Plugins/DiziPal.py +37 -23
- KekikStream/Plugins/DiziYou.py +23 -11
- KekikStream/Plugins/Dizilla.py +35 -30
- KekikStream/Plugins/FilmBip.py +90 -18
- KekikStream/Plugins/FilmEkseni.py +78 -40
- KekikStream/Plugins/FilmMakinesi.py +29 -14
- KekikStream/Plugins/FilmModu.py +17 -19
- KekikStream/Plugins/Filmatek.py +103 -91
- KekikStream/Plugins/Full4kizle.py +6 -6
- KekikStream/Plugins/FullHDFilm.py +6 -6
- KekikStream/Plugins/FullHDFilmizlesene.py +6 -7
- KekikStream/Plugins/HDFilmCehennemi.py +3 -3
- KekikStream/Plugins/JetFilmizle.py +5 -5
- KekikStream/Plugins/KultFilmler.py +6 -6
- KekikStream/Plugins/RoketDizi.py +5 -5
- KekikStream/Plugins/SelcukFlix.py +2 -2
- KekikStream/Plugins/SetFilmIzle.py +5 -5
- KekikStream/Plugins/SezonlukDizi.py +4 -4
- KekikStream/Plugins/Sinefy.py +5 -5
- KekikStream/Plugins/SinemaCX.py +5 -5
- KekikStream/Plugins/Sinezy.py +5 -5
- KekikStream/Plugins/SuperFilmGeldi.py +5 -5
- KekikStream/Plugins/UgurFilm.py +4 -4
- KekikStream/Plugins/YabanciDizi.py +5 -5
- {kekikstream-2.4.6.dist-info → kekikstream-2.4.7.dist-info}/METADATA +1 -1
- {kekikstream-2.4.6.dist-info → kekikstream-2.4.7.dist-info}/RECORD +37 -37
- {kekikstream-2.4.6.dist-info → kekikstream-2.4.7.dist-info}/WHEEL +0 -0
- {kekikstream-2.4.6.dist-info → kekikstream-2.4.7.dist-info}/entry_points.txt +0 -0
- {kekikstream-2.4.6.dist-info → kekikstream-2.4.7.dist-info}/licenses/LICENSE +0 -0
- {kekikstream-2.4.6.dist-info → kekikstream-2.4.7.dist-info}/top_level.txt +0 -0
KekikStream/Plugins/DiziYou.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
|
|
3
|
+
from KekikStream.Core import PluginBase, MainPageResult, SearchResult, SeriesInfo, Episode, Subtitle, ExtractResult, HTMLHelper
|
|
4
4
|
|
|
5
5
|
class DiziYou(PluginBase):
|
|
6
6
|
name = "DiziYou"
|
|
@@ -42,7 +42,7 @@ class DiziYou(PluginBase):
|
|
|
42
42
|
category = category,
|
|
43
43
|
title = title,
|
|
44
44
|
url = self.fix_url(href),
|
|
45
|
-
poster = self.fix_url(poster)
|
|
45
|
+
poster = self.fix_url(poster),
|
|
46
46
|
))
|
|
47
47
|
|
|
48
48
|
return results
|
|
@@ -61,7 +61,7 @@ class DiziYou(PluginBase):
|
|
|
61
61
|
results.append(SearchResult(
|
|
62
62
|
title = title,
|
|
63
63
|
url = self.fix_url(href),
|
|
64
|
-
poster = self.fix_url(poster)
|
|
64
|
+
poster = self.fix_url(poster),
|
|
65
65
|
))
|
|
66
66
|
|
|
67
67
|
return results
|
|
@@ -76,8 +76,8 @@ class DiziYou(PluginBase):
|
|
|
76
76
|
tags = secici.select_texts("div.genres a")
|
|
77
77
|
rating = secici.regex_first(r"(?is)IMDB\s*:\s*</span>([0-9.]+)", secici.html)
|
|
78
78
|
year = secici.extract_year("div#icerikcat2")
|
|
79
|
-
|
|
80
|
-
actors = [
|
|
79
|
+
raw_actors = secici.meta_value("Oyuncular", container_selector="div#icerikcat2")
|
|
80
|
+
actors = [x.strip() for x in raw_actors.split(",")] if raw_actors else None
|
|
81
81
|
|
|
82
82
|
episodes = []
|
|
83
83
|
for link in secici.select("div#scrollbar-container a"):
|
|
@@ -86,23 +86,35 @@ class DiziYou(PluginBase):
|
|
|
86
86
|
name = secici.select_text("div.bolumismi", link).strip("()")
|
|
87
87
|
s, e = secici.extract_season_episode(f"{name} {href}")
|
|
88
88
|
if e:
|
|
89
|
-
episodes.append(Episode(
|
|
89
|
+
episodes.append(Episode(
|
|
90
|
+
season = s or 1,
|
|
91
|
+
episode = e,
|
|
92
|
+
title = name,
|
|
93
|
+
url = self.fix_url(href)
|
|
94
|
+
))
|
|
90
95
|
|
|
91
96
|
return SeriesInfo(
|
|
92
|
-
url=url,
|
|
93
|
-
|
|
97
|
+
url = url,
|
|
98
|
+
poster = poster,
|
|
99
|
+
title = title,
|
|
100
|
+
description = description,
|
|
101
|
+
tags = tags,
|
|
102
|
+
rating = rating,
|
|
103
|
+
year = year,
|
|
104
|
+
episodes = episodes,
|
|
105
|
+
actors = actors
|
|
94
106
|
)
|
|
95
107
|
|
|
96
108
|
async def load_links(self, url: str) -> list[ExtractResult]:
|
|
97
109
|
istek = await self.httpx.get(url)
|
|
98
110
|
secici = HTMLHelper(istek.text)
|
|
99
|
-
|
|
111
|
+
|
|
100
112
|
# Player iframe'inden ID'yi yakala
|
|
101
113
|
iframe_src = secici.select_attr("iframe#diziyouPlayer", "src") or secici.select_attr("iframe[src*='/player/']", "src")
|
|
102
114
|
if not iframe_src:
|
|
103
115
|
return []
|
|
104
116
|
|
|
105
|
-
item_id
|
|
117
|
+
item_id = iframe_src.split("/")[-1].replace(".html", "")
|
|
106
118
|
base_storage = self.main_url.replace("www", "storage")
|
|
107
119
|
|
|
108
120
|
subtitles = []
|
|
@@ -132,4 +144,4 @@ class DiziYou(PluginBase):
|
|
|
132
144
|
subtitles = subtitles
|
|
133
145
|
))
|
|
134
146
|
|
|
135
|
-
return results
|
|
147
|
+
return results
|
KekikStream/Plugins/Dizilla.py
CHANGED
|
@@ -1,10 +1,10 @@
|
|
|
1
1
|
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
2
|
|
|
3
|
-
from KekikStream.Core
|
|
4
|
-
from json
|
|
5
|
-
from urllib.parse
|
|
6
|
-
from Crypto.Cipher
|
|
7
|
-
from base64
|
|
3
|
+
from KekikStream.Core import PluginBase, MainPageResult, SearchResult, SeriesInfo, Episode, ExtractResult, HTMLHelper
|
|
4
|
+
from json import loads
|
|
5
|
+
from urllib.parse import urlparse, urlunparse
|
|
6
|
+
from Crypto.Cipher import AES
|
|
7
|
+
from base64 import b64decode
|
|
8
8
|
|
|
9
9
|
class Dizilla(PluginBase):
|
|
10
10
|
name = "Dizilla"
|
|
@@ -44,7 +44,7 @@ class Dizilla(PluginBase):
|
|
|
44
44
|
category = category,
|
|
45
45
|
title = veri.get("original_title"),
|
|
46
46
|
url = self.fix_url(f"{self.main_url}/{veri.get('used_slug')}"),
|
|
47
|
-
poster = self.fix_poster_url(self.fix_url(veri.get("
|
|
47
|
+
poster = self.fix_poster_url(self.fix_url(veri.get("poster_url"))),
|
|
48
48
|
)
|
|
49
49
|
for veri in veriler
|
|
50
50
|
])
|
|
@@ -60,15 +60,15 @@ class Dizilla(PluginBase):
|
|
|
60
60
|
continue
|
|
61
61
|
|
|
62
62
|
# Detay sayfasından poster vb. bilgileri al
|
|
63
|
-
ep_req
|
|
63
|
+
ep_req = await self.httpx.get(self.fix_url(href))
|
|
64
64
|
ep_secici = HTMLHelper(ep_req.text)
|
|
65
|
-
poster
|
|
65
|
+
poster = ep_secici.select_poster('img.imgt') or ep_secici.select_poster('img')
|
|
66
66
|
|
|
67
67
|
ana_sayfa.append(MainPageResult(
|
|
68
68
|
category = category,
|
|
69
69
|
title = title,
|
|
70
70
|
url = self.fix_url(href),
|
|
71
|
-
poster = self.fix_url(poster)
|
|
71
|
+
poster = self.fix_url(poster)
|
|
72
72
|
))
|
|
73
73
|
|
|
74
74
|
return ana_sayfa
|
|
@@ -118,7 +118,7 @@ class Dizilla(PluginBase):
|
|
|
118
118
|
SearchResult(
|
|
119
119
|
title = veri.get("object_name"),
|
|
120
120
|
url = self.fix_url(f"{self.main_url}/{veri.get('used_slug')}"),
|
|
121
|
-
poster = self.fix_poster_url(self.fix_url(veri.get("
|
|
121
|
+
poster = self.fix_poster_url(self.fix_url(veri.get("poster_url"))),
|
|
122
122
|
)
|
|
123
123
|
for veri in arama_veri
|
|
124
124
|
]
|
|
@@ -138,15 +138,18 @@ class Dizilla(PluginBase):
|
|
|
138
138
|
secici = HTMLHelper(istek.text)
|
|
139
139
|
|
|
140
140
|
next_data_text = secici.select_text("script#__NEXT_DATA__")
|
|
141
|
-
if not next_data_text:
|
|
141
|
+
if not next_data_text:
|
|
142
|
+
return None
|
|
142
143
|
|
|
143
144
|
next_data = loads(next_data_text)
|
|
144
145
|
secure_data = next_data.get("props", {}).get("pageProps", {}).get("secureData")
|
|
145
|
-
if not secure_data:
|
|
146
|
+
if not secure_data:
|
|
147
|
+
return None
|
|
146
148
|
|
|
147
149
|
decrypted = await self.decrypt_response(secure_data)
|
|
148
150
|
content = decrypted.get("contentItem", {})
|
|
149
|
-
if not content:
|
|
151
|
+
if not content:
|
|
152
|
+
return None
|
|
150
153
|
|
|
151
154
|
title = content.get("original_title") or content.get("used_title")
|
|
152
155
|
description = content.get("description") or content.get("used_description")
|
|
@@ -165,29 +168,34 @@ class Dizilla(PluginBase):
|
|
|
165
168
|
slug = ep.get("used_slug")
|
|
166
169
|
name = ep.get("episode_text") or ""
|
|
167
170
|
if not any(e.season == s_no and e.episode == e_no for e in episodes):
|
|
168
|
-
episodes.append(Episode(
|
|
171
|
+
episodes.append(Episode(
|
|
172
|
+
season = s_no,
|
|
173
|
+
episode = e_no,
|
|
174
|
+
title = name,
|
|
175
|
+
url = self.fix_url(f"{self.main_url}/{slug}")
|
|
176
|
+
))
|
|
169
177
|
|
|
170
178
|
return SeriesInfo(
|
|
171
179
|
url = url,
|
|
172
180
|
poster = poster,
|
|
173
|
-
title = title
|
|
181
|
+
title = title,
|
|
174
182
|
description = description,
|
|
175
183
|
tags = tags,
|
|
176
|
-
rating =
|
|
177
|
-
year =
|
|
184
|
+
rating = rating,
|
|
185
|
+
year = year,
|
|
178
186
|
episodes = episodes,
|
|
179
187
|
actors = actors
|
|
180
188
|
)
|
|
181
189
|
|
|
182
190
|
async def load_links(self, url: str) -> list[ExtractResult]:
|
|
183
|
-
istek
|
|
184
|
-
secici
|
|
191
|
+
istek = await self.httpx.get(url)
|
|
192
|
+
secici = HTMLHelper(istek.text)
|
|
185
193
|
|
|
186
194
|
next_data_text = secici.select_text("script#__NEXT_DATA__")
|
|
187
195
|
if not next_data_text:
|
|
188
196
|
return []
|
|
189
197
|
|
|
190
|
-
next_data
|
|
198
|
+
next_data = loads(next_data_text)
|
|
191
199
|
secure_data = next_data.get("props", {}).get("pageProps", {}).get("secureData", {})
|
|
192
200
|
decrypted = await self.decrypt_response(secure_data)
|
|
193
201
|
results = decrypted.get("RelatedResults", {}).get("getEpisodeSources", {}).get("result", [])
|
|
@@ -195,24 +203,21 @@ class Dizilla(PluginBase):
|
|
|
195
203
|
if not results:
|
|
196
204
|
return []
|
|
197
205
|
|
|
198
|
-
|
|
199
|
-
first_result = results[0]
|
|
206
|
+
first_result = results[0]
|
|
200
207
|
source_content = str(first_result.get("source_content", ""))
|
|
201
|
-
|
|
202
|
-
# Clean the source_content string (matching Kotlin: .replace("\"", "").replace("\\", ""))
|
|
208
|
+
|
|
203
209
|
cleaned_source = source_content.replace('"', '').replace('\\', '')
|
|
204
|
-
|
|
205
|
-
# Parse cleaned HTML
|
|
210
|
+
|
|
206
211
|
iframe_secici = HTMLHelper(cleaned_source)
|
|
207
|
-
iframe_src
|
|
208
|
-
|
|
209
|
-
# Referer check (matching Kotlin: loadExtractor(iframe, "${mainUrl}/", ...))
|
|
212
|
+
iframe_src = iframe_secici.select_attr("iframe", "src")
|
|
213
|
+
|
|
210
214
|
iframe_url = self.fix_url(iframe_src) if iframe_src else None
|
|
211
|
-
|
|
215
|
+
|
|
212
216
|
if not iframe_url:
|
|
213
217
|
return []
|
|
214
218
|
|
|
215
219
|
data = await self.extract(iframe_url, referer=f"{self.main_url}/", prefix=first_result.get('language_name', 'Unknown'))
|
|
216
220
|
if not data:
|
|
217
221
|
return []
|
|
222
|
+
|
|
218
223
|
return data if isinstance(data, list) else [data]
|
KekikStream/Plugins/FilmBip.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
|
|
3
|
+
from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo, ExtractResult, HTMLHelper
|
|
4
4
|
|
|
5
5
|
class FilmBip(PluginBase):
|
|
6
6
|
name = "FilmBip"
|
|
@@ -39,8 +39,8 @@ class FilmBip(PluginBase):
|
|
|
39
39
|
|
|
40
40
|
results = []
|
|
41
41
|
for veri in secici.select("div.poster-long"):
|
|
42
|
-
title
|
|
43
|
-
href
|
|
42
|
+
title = secici.select_attr("a.block img.lazy", "alt", veri)
|
|
43
|
+
href = secici.select_attr("a.block", "href", veri)
|
|
44
44
|
poster = secici.select_poster("a.block img.lazy", veri)
|
|
45
45
|
|
|
46
46
|
if title and href:
|
|
@@ -48,7 +48,7 @@ class FilmBip(PluginBase):
|
|
|
48
48
|
category = category,
|
|
49
49
|
title = title,
|
|
50
50
|
url = self.fix_url(href),
|
|
51
|
-
poster = self.fix_url(poster)
|
|
51
|
+
poster = self.fix_url(poster),
|
|
52
52
|
))
|
|
53
53
|
|
|
54
54
|
return results
|
|
@@ -87,7 +87,7 @@ class FilmBip(PluginBase):
|
|
|
87
87
|
results.append(SearchResult(
|
|
88
88
|
title = title.strip(),
|
|
89
89
|
url = self.fix_url(href),
|
|
90
|
-
poster = self.fix_url(poster)
|
|
90
|
+
poster = self.fix_url(poster),
|
|
91
91
|
))
|
|
92
92
|
|
|
93
93
|
return results
|
|
@@ -108,13 +108,13 @@ class FilmBip(PluginBase):
|
|
|
108
108
|
|
|
109
109
|
return MovieInfo(
|
|
110
110
|
url = url,
|
|
111
|
-
poster = self.fix_url(poster)
|
|
112
|
-
title = title
|
|
111
|
+
poster = self.fix_url(poster),
|
|
112
|
+
title = title,
|
|
113
113
|
description = description,
|
|
114
114
|
tags = tags,
|
|
115
|
-
year =
|
|
115
|
+
year = year,
|
|
116
116
|
rating = rating,
|
|
117
|
-
duration =
|
|
117
|
+
duration = duration,
|
|
118
118
|
actors = actors,
|
|
119
119
|
)
|
|
120
120
|
|
|
@@ -123,14 +123,86 @@ class FilmBip(PluginBase):
|
|
|
123
123
|
secici = HTMLHelper(istek.text)
|
|
124
124
|
|
|
125
125
|
results = []
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
|
|
134
|
-
|
|
126
|
+
# Tabs (Diller)
|
|
127
|
+
tabs = secici.select("ul.tab.alternative-group li[data-number]")
|
|
128
|
+
|
|
129
|
+
for tab in tabs:
|
|
130
|
+
tab_id = tab.attrs.get("data-number")
|
|
131
|
+
# Tab ismini al
|
|
132
|
+
tab_name = secici.select_text(None, tab)
|
|
133
|
+
tab_hash = tab.attrs.get("data-group-hash")
|
|
134
|
+
|
|
135
|
+
if not tab_id:
|
|
136
|
+
continue
|
|
137
|
+
|
|
138
|
+
button_data = [] # (player_name, iframe_url)
|
|
139
|
+
|
|
140
|
+
# İlgili content divini bul
|
|
141
|
+
content_div = secici.select_first(f"div#{tab_id}")
|
|
142
|
+
|
|
143
|
+
# Eğer div var ve içi doluysa oradan al
|
|
144
|
+
if content_div and secici.select("ul li button", content_div):
|
|
145
|
+
buttons = secici.select("ul li button", content_div)
|
|
146
|
+
for btn in buttons:
|
|
147
|
+
button_data.append((btn.text(strip=True), btn.attrs.get("data-hhs")))
|
|
148
|
+
|
|
149
|
+
elif tab_hash:
|
|
150
|
+
# Div yok veya boş, AJAX ile çek
|
|
151
|
+
try:
|
|
152
|
+
hash_resp = await self.httpx.post(
|
|
153
|
+
url = f"{self.main_url}/get/video/group",
|
|
154
|
+
headers = {
|
|
155
|
+
"X-Requested-With" : "XMLHttpRequest",
|
|
156
|
+
"Content-Type" : "application/x-www-form-urlencoded; charset=UTF-8",
|
|
157
|
+
"Referer" : url
|
|
158
|
+
},
|
|
159
|
+
data = {"hash": tab_hash}
|
|
160
|
+
)
|
|
161
|
+
|
|
162
|
+
if hash_resp.status_code == 200:
|
|
163
|
+
json_data = hash_resp.json()
|
|
164
|
+
if json_data.get("success"):
|
|
165
|
+
# 1. Videos listesi (API yanıtı)
|
|
166
|
+
if videos := json_data.get("videos"):
|
|
167
|
+
for vid in videos:
|
|
168
|
+
button_data.append((vid.get("name"), vid.get("link")))
|
|
169
|
+
|
|
170
|
+
# 2. HTML content (Fallback)
|
|
171
|
+
else:
|
|
172
|
+
html_content = json_data.get("content") or json_data.get("html") or json_data.get("theme")
|
|
173
|
+
if html_content:
|
|
174
|
+
sub_helper = HTMLHelper(html_content)
|
|
175
|
+
sub_btns = sub_helper.select("ul li button")
|
|
176
|
+
for btn in sub_btns:
|
|
177
|
+
button_data.append((btn.text(strip=True), btn.attrs.get("data-hhs")))
|
|
178
|
+
except Exception:
|
|
179
|
+
pass
|
|
180
|
+
|
|
181
|
+
for player_name, iframe_url in button_data:
|
|
182
|
+
try:
|
|
183
|
+
if iframe_url:
|
|
184
|
+
data = await self.extract(
|
|
185
|
+
url = self.fix_url(iframe_url),
|
|
186
|
+
name_override = f"{tab_name} | {player_name}"
|
|
187
|
+
)
|
|
188
|
+
if data:
|
|
189
|
+
if isinstance(data, list):
|
|
190
|
+
results.extend(data)
|
|
191
|
+
else:
|
|
192
|
+
results.append(data)
|
|
193
|
+
except Exception:
|
|
194
|
+
pass
|
|
195
|
+
|
|
196
|
+
# Eğer hiç sonuç bulunamazsa fallback
|
|
197
|
+
if not results:
|
|
198
|
+
for player in secici.select("div#tv-spoox2"):
|
|
199
|
+
if iframe := secici.select_attr("iframe", "src", player):
|
|
200
|
+
iframe = self.fix_url(iframe)
|
|
201
|
+
data = await self.extract(iframe)
|
|
202
|
+
if data:
|
|
203
|
+
if isinstance(data, list):
|
|
204
|
+
results.extend(data)
|
|
205
|
+
else:
|
|
206
|
+
results.append(data)
|
|
135
207
|
|
|
136
208
|
return results
|
|
@@ -1,8 +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,
|
|
4
|
-
from json import dumps, loads
|
|
5
|
-
import re
|
|
3
|
+
from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo, ExtractResult, HTMLHelper
|
|
6
4
|
|
|
7
5
|
class FilmEkseni(PluginBase):
|
|
8
6
|
name = "FilmEkseni"
|
|
@@ -46,15 +44,16 @@ class FilmEkseni(PluginBase):
|
|
|
46
44
|
]
|
|
47
45
|
|
|
48
46
|
async def search(self, query: str) -> list[SearchResult]:
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
47
|
+
istek = await self.httpx.post(
|
|
48
|
+
url = f"{self.main_url}/search/",
|
|
49
|
+
headers = {
|
|
50
|
+
"X-Requested-With" : "XMLHttpRequest",
|
|
51
|
+
"Content-Type" : "application/x-www-form-urlencoded; charset=UTF-8",
|
|
52
|
+
"Referer" : self.main_url,
|
|
53
|
+
},
|
|
54
|
+
data = {"query": query}
|
|
55
|
+
)
|
|
56
|
+
|
|
58
57
|
veriler = istek.json().get("result", [])
|
|
59
58
|
|
|
60
59
|
return [
|
|
@@ -81,40 +80,79 @@ class FilmEkseni(PluginBase):
|
|
|
81
80
|
|
|
82
81
|
return MovieInfo(
|
|
83
82
|
url = url,
|
|
84
|
-
poster = self.fix_url(poster)
|
|
85
|
-
title = title
|
|
83
|
+
poster = self.fix_url(poster),
|
|
84
|
+
title = title,
|
|
86
85
|
description = description,
|
|
87
86
|
tags = tags,
|
|
88
87
|
rating = rating,
|
|
89
|
-
year =
|
|
90
|
-
actors = actors
|
|
91
|
-
duration =
|
|
88
|
+
year = year,
|
|
89
|
+
actors = actors,
|
|
90
|
+
duration = duration
|
|
92
91
|
)
|
|
93
92
|
|
|
94
93
|
async def load_links(self, url: str) -> list[ExtractResult]:
|
|
95
94
|
istek = await self.httpx.get(url)
|
|
96
95
|
helper = HTMLHelper(istek.text)
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
)
|
|
118
|
-
|
|
119
|
-
|
|
96
|
+
|
|
97
|
+
results = []
|
|
98
|
+
sources = [] # (name, url, is_active)
|
|
99
|
+
|
|
100
|
+
nav_links = helper.select("nav.card-nav a.nav-link")
|
|
101
|
+
if nav_links:
|
|
102
|
+
seen_urls = set()
|
|
103
|
+
for link in nav_links:
|
|
104
|
+
if link.attrs.get("href") == "#":
|
|
105
|
+
continue # Sinema Modu vb.
|
|
106
|
+
|
|
107
|
+
name = link.text(strip=True)
|
|
108
|
+
href = link.attrs.get("href")
|
|
109
|
+
is_active = "active" in link.attrs.get("class", "")
|
|
110
|
+
|
|
111
|
+
if href and href not in seen_urls:
|
|
112
|
+
seen_urls.add(href)
|
|
113
|
+
sources.append((name, href, is_active))
|
|
114
|
+
else:
|
|
115
|
+
# Nav yoksa mevcut sayfayı (Varsayılan/VIP) al
|
|
116
|
+
sources.append(("VIP", url, True))
|
|
117
|
+
|
|
118
|
+
for name, link_url, is_active in sources:
|
|
119
|
+
current_helper = helper
|
|
120
|
+
|
|
121
|
+
# Eğer aktif değilse sayfaya git
|
|
122
|
+
if not is_active:
|
|
123
|
+
try:
|
|
124
|
+
resp = await self.httpx.get(link_url)
|
|
125
|
+
current_helper = HTMLHelper(resp.text)
|
|
126
|
+
except:
|
|
127
|
+
continue
|
|
128
|
+
|
|
129
|
+
iframe = current_helper.select_first("div.card-video iframe")
|
|
130
|
+
if not iframe:
|
|
131
|
+
continue
|
|
132
|
+
|
|
133
|
+
iframe_url = iframe.attrs.get("data-src") or iframe.attrs.get("src")
|
|
134
|
+
if not iframe_url:
|
|
135
|
+
continue
|
|
136
|
+
|
|
137
|
+
iframe_url = self.fix_url(iframe_url)
|
|
138
|
+
|
|
139
|
+
# VIP / EksenLoad mantığı
|
|
140
|
+
if "eksenload" in iframe_url or name == "VIP":
|
|
141
|
+
video_id = iframe_url.split("/")[-1]
|
|
142
|
+
master_url = f"https://eksenload.site/uploads/encode/{video_id}/master.m3u8"
|
|
143
|
+
results.append(ExtractResult(
|
|
144
|
+
url = master_url,
|
|
145
|
+
name = name,
|
|
146
|
+
referer = self.main_url
|
|
147
|
+
))
|
|
148
|
+
else:
|
|
149
|
+
# Diğerleri (Moly, vs.) için extract
|
|
150
|
+
# Name override: "Kaynak Adı | Player Adı" olacak şekilde
|
|
151
|
+
extracted = await self.extract(iframe_url, name_override=name)
|
|
152
|
+
if extracted:
|
|
153
|
+
if isinstance(extracted, list):
|
|
154
|
+
results.extend(extracted)
|
|
155
|
+
else:
|
|
156
|
+
results.append(extracted)
|
|
157
|
+
|
|
120
158
|
return results
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
2
|
|
|
3
|
-
from KekikStream.Core
|
|
3
|
+
from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo, SeriesInfo, Episode, ExtractResult, HTMLHelper
|
|
4
4
|
|
|
5
5
|
class FilmMakinesi(PluginBase):
|
|
6
6
|
name = "FilmMakinesi"
|
|
@@ -39,8 +39,8 @@ class FilmMakinesi(PluginBase):
|
|
|
39
39
|
|
|
40
40
|
results = []
|
|
41
41
|
for veri in secici.select("div.item-relative"):
|
|
42
|
-
title
|
|
43
|
-
href
|
|
42
|
+
title = secici.select_text("div.title", veri)
|
|
43
|
+
href = secici.select_attr("a", "href", veri)
|
|
44
44
|
poster = secici.select_poster("img", veri)
|
|
45
45
|
|
|
46
46
|
if title and href:
|
|
@@ -48,7 +48,7 @@ class FilmMakinesi(PluginBase):
|
|
|
48
48
|
category = category,
|
|
49
49
|
title = title,
|
|
50
50
|
url = self.fix_url(href),
|
|
51
|
-
poster = self.fix_url(poster)
|
|
51
|
+
poster = self.fix_url(poster),
|
|
52
52
|
))
|
|
53
53
|
|
|
54
54
|
return results
|
|
@@ -59,15 +59,15 @@ class FilmMakinesi(PluginBase):
|
|
|
59
59
|
|
|
60
60
|
results = []
|
|
61
61
|
for article in secici.select("div.item-relative"):
|
|
62
|
-
title
|
|
63
|
-
href
|
|
62
|
+
title = secici.select_text("div.title", article)
|
|
63
|
+
href = secici.select_attr("a", "href", article)
|
|
64
64
|
poster = secici.select_poster("img", article)
|
|
65
65
|
|
|
66
66
|
if title and href:
|
|
67
67
|
results.append(SearchResult(
|
|
68
|
-
title = title
|
|
69
|
-
url = self.fix_url(href
|
|
70
|
-
poster = self.fix_url(poster
|
|
68
|
+
title = title,
|
|
69
|
+
url = self.fix_url(href),
|
|
70
|
+
poster = self.fix_url(poster),
|
|
71
71
|
))
|
|
72
72
|
|
|
73
73
|
return results
|
|
@@ -92,7 +92,7 @@ class FilmMakinesi(PluginBase):
|
|
|
92
92
|
if s and e:
|
|
93
93
|
name = link.text(strip=True).split("Bölüm")[-1].strip() if "Bölüm" in link.text() else ""
|
|
94
94
|
episodes.append(Episode(season=s, episode=e, title=name, url=self.fix_url(href)))
|
|
95
|
-
|
|
95
|
+
|
|
96
96
|
# Tekrar edenleri temizle ve sırala
|
|
97
97
|
if episodes:
|
|
98
98
|
seen = set()
|
|
@@ -104,13 +104,28 @@ class FilmMakinesi(PluginBase):
|
|
|
104
104
|
unique.sort(key=lambda x: (x.season or 0, x.episode or 0))
|
|
105
105
|
|
|
106
106
|
return SeriesInfo(
|
|
107
|
-
url=url,
|
|
108
|
-
|
|
107
|
+
url = url,
|
|
108
|
+
poster = self.fix_url(poster),
|
|
109
|
+
title = title,
|
|
110
|
+
description = description,
|
|
111
|
+
tags = tags,
|
|
112
|
+
rating = rating,
|
|
113
|
+
year = year,
|
|
114
|
+
actors = actors,
|
|
115
|
+
duration = duration,
|
|
116
|
+
episodes = unique
|
|
109
117
|
)
|
|
110
118
|
|
|
111
119
|
return MovieInfo(
|
|
112
|
-
url=url,
|
|
113
|
-
|
|
120
|
+
url = url,
|
|
121
|
+
poster = self.fix_url(poster),
|
|
122
|
+
title = title,
|
|
123
|
+
description = description,
|
|
124
|
+
tags = tags,
|
|
125
|
+
rating = rating,
|
|
126
|
+
year = year,
|
|
127
|
+
actors = actors,
|
|
128
|
+
duration = duration
|
|
114
129
|
)
|
|
115
130
|
|
|
116
131
|
async def load_links(self, url: str) -> list[ExtractResult]:
|