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.
Files changed (54) hide show
  1. KekikStream/Core/Extractor/ExtractorBase.py +7 -2
  2. KekikStream/Core/Plugin/PluginBase.py +61 -13
  3. KekikStream/Extractors/CloseLoad.py +17 -2
  4. KekikStream/Extractors/ContentX.py +19 -2
  5. KekikStream/Extractors/DonilasPlay.py +86 -0
  6. KekikStream/Extractors/Filemoon.py +78 -0
  7. KekikStream/Extractors/MixTiger.py +5 -5
  8. KekikStream/Extractors/Odnoklassniki.py +6 -0
  9. KekikStream/Extractors/PeaceMakerst.py +6 -0
  10. KekikStream/Extractors/PlayerFilmIzle.py +8 -5
  11. KekikStream/Extractors/RapidVid.py +21 -5
  12. KekikStream/Extractors/SetPlay.py +13 -4
  13. KekikStream/Extractors/VCTPlay.py +41 -0
  14. KekikStream/Extractors/VidHide.py +11 -2
  15. KekikStream/Extractors/VidMoly.py +52 -30
  16. KekikStream/Extractors/YTDLP.py +88 -54
  17. KekikStream/Plugins/BelgeselX.py +196 -0
  18. KekikStream/Plugins/DiziBox.py +8 -12
  19. KekikStream/Plugins/DiziPal.py +11 -22
  20. KekikStream/Plugins/DiziYou.py +9 -17
  21. KekikStream/Plugins/Dizilla.py +19 -14
  22. KekikStream/Plugins/FilmBip.py +5 -8
  23. KekikStream/Plugins/FilmMakinesi.py +31 -21
  24. KekikStream/Plugins/FilmModu.py +14 -18
  25. KekikStream/Plugins/FullHDFilm.py +83 -27
  26. KekikStream/Plugins/FullHDFilmizlesene.py +6 -8
  27. KekikStream/Plugins/HDFilmCehennemi.py +133 -57
  28. KekikStream/Plugins/JetFilmizle.py +29 -14
  29. KekikStream/Plugins/KultFilmler.py +13 -15
  30. KekikStream/Plugins/RecTV.py +16 -24
  31. KekikStream/Plugins/RoketDizi.py +22 -32
  32. KekikStream/Plugins/SelcukFlix.py +99 -80
  33. KekikStream/Plugins/SetFilmIzle.py +252 -0
  34. KekikStream/Plugins/SezonlukDizi.py +43 -9
  35. KekikStream/Plugins/SineWix.py +13 -21
  36. KekikStream/Plugins/Sinefy.py +13 -10
  37. KekikStream/Plugins/SinemaCX.py +35 -38
  38. KekikStream/Plugins/Sinezy.py +5 -8
  39. KekikStream/Plugins/SuperFilmGeldi.py +36 -27
  40. KekikStream/Plugins/UgurFilm.py +7 -9
  41. KekikStream/__init__.py +17 -36
  42. {kekikstream-2.0.2.dist-info → kekikstream-2.2.0.dist-info}/METADATA +6 -3
  43. kekikstream-2.2.0.dist-info/RECORD +81 -0
  44. KekikStream/Extractors/ContentX_.py +0 -40
  45. KekikStream/Extractors/FirePlayer.py +0 -60
  46. KekikStream/Extractors/Odnoklassniki_.py +0 -11
  47. KekikStream/Extractors/PeaceMakerst_.py +0 -7
  48. KekikStream/Extractors/RapidVid_.py +0 -7
  49. KekikStream/Extractors/VidMoly_.py +0 -7
  50. kekikstream-2.0.2.dist-info/RECORD +0 -82
  51. {kekikstream-2.0.2.dist-info → kekikstream-2.2.0.dist-info}/WHEEL +0 -0
  52. {kekikstream-2.0.2.dist-info → kekikstream-2.2.0.dist-info}/entry_points.txt +0 -0
  53. {kekikstream-2.0.2.dist-info → kekikstream-2.2.0.dist-info}/licenses/LICENSE +0 -0
  54. {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, SeriesInfo, Episode
3
+ from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo, SeriesInfo, Episode, ExtractResult
4
4
  from parsel import Selector
5
5
  import re, base64, json, urllib.parse
6
6
 
@@ -9,7 +9,7 @@ class SelcukFlix(PluginBase):
9
9
  lang = "tr"
10
10
  main_url = "https://selcukflix.net"
11
11
  favicon = f"https://www.google.com/s2/favicons?domain={main_url}&sz=64"
12
- description = "Selcukflix'te her türden en yeni ve en popüler dizi ve filmleri izlemenin keyfini çıkarın. Aksiyondan romantiğe, bilim kurgudan dramaya, geniş kütüphanemizde herkes için bir şey var."
12
+ description = "Selcukflix'te her türden en yeni ve en popüler dizi ve filmleri izlemenin keyfini çıkarın. Aksiyondan romantiğe, bilim kurgudan dramaya, geniş kütüphanemizde herkes için bir şey var."
13
13
 
14
14
  main_page = {
15
15
  f"{main_url}/tum-bolumler" : "Yeni Eklenen Bölümler",
@@ -137,8 +137,13 @@ class SelcukFlix(PluginBase):
137
137
  search_url = f"{self.main_url}/api/bg/searchcontent?searchterm={query}"
138
138
 
139
139
  headers = {
140
+ "User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:137.0) Gecko/20100101 Firefox/137.0",
140
141
  "Accept" : "application/json, text/plain, */*",
142
+ "Accept-Language" : "en-US,en;q=0.5",
141
143
  "X-Requested-With" : "XMLHttpRequest",
144
+ "Sec-Fetch-Site" : "same-origin",
145
+ "Sec-Fetch-Mode" : "cors",
146
+ "Sec-Fetch-Dest" : "empty",
142
147
  "Referer" : f"{self.main_url}/"
143
148
  }
144
149
 
@@ -151,15 +156,16 @@ class SelcukFlix(PluginBase):
151
156
  try:
152
157
  decoded_str = raw_data.decode('utf-8')
153
158
  except UnicodeDecodeError:
154
- decoded_str = raw_data.decode('iso-8859-1').encode('utf-8').decode('utf-8')
159
+ decoded_str = raw_data.decode('iso-8859-1')
155
160
 
156
161
  search_data = json.loads(decoded_str)
157
162
 
158
163
  results = []
159
164
  for item in search_data.get("result", []):
160
- title = item.get("title")
161
- slug = item.get("slug")
162
- poster = item.get("poster")
165
+ # API field isimleri: object_name, used_slug, object_poster_url
166
+ title = item.get("object_name") or item.get("title")
167
+ slug = item.get("used_slug") or item.get("slug")
168
+ poster = item.get("object_poster_url") or item.get("poster")
163
169
 
164
170
  if poster:
165
171
  poster = self.clean_image_url(poster)
@@ -176,7 +182,7 @@ class SelcukFlix(PluginBase):
176
182
  except Exception:
177
183
  return []
178
184
 
179
- async def load_item(self, url: str) -> SeriesInfo:
185
+ async def load_item(self, url: str) -> MovieInfo | SeriesInfo:
180
186
  resp = await self.httpx.get(url)
181
187
  sel = Selector(resp.text)
182
188
 
@@ -190,15 +196,17 @@ class SelcukFlix(PluginBase):
190
196
  try:
191
197
  decoded_str = raw_data.decode('utf-8')
192
198
  except UnicodeDecodeError:
193
- decoded_str = raw_data.decode('iso-8859-1') # .encode('utf-8').decode('utf-8') implied
199
+ decoded_str = raw_data.decode('iso-8859-1')
194
200
 
195
201
  content_details = json.loads(decoded_str)
196
202
  item = content_details.get("contentItem", {})
197
203
 
198
- title = item.get("original_title") or item.get("originalTitle")
204
+ title = item.get("original_title") or item.get("originalTitle") or ""
199
205
  poster = self.clean_image_url(item.get("poster_url") or item.get("posterUrl"))
200
206
  description = item.get("description") or item.get("used_description")
201
207
  rating = str(item.get("imdb_point") or item.get("imdbPoint", ""))
208
+ year = item.get("release_year") or item.get("releaseYear")
209
+ duration = item.get("total_minutes") or item.get("totalMinutes")
202
210
 
203
211
  series_data = content_details.get("relatedData", {}).get("seriesData")
204
212
  if not series_data and "RelatedResults" in content_details:
@@ -206,17 +214,18 @@ class SelcukFlix(PluginBase):
206
214
  if series_data and isinstance(series_data, list):
207
215
  pass
208
216
 
209
- episodes = []
217
+ # Dizi mi film mi kontrol et (Kotlin referansı)
210
218
  if series_data:
211
- seasons_list = []
212
- if isinstance(series_data, dict):
213
- seasons_list = series_data.get("seasons", [])
214
- elif isinstance(series_data, list):
215
- seasons_list = series_data
216
-
217
- for season in seasons_list:
219
+ episodes = []
220
+ seasons_list = []
221
+ if isinstance(series_data, dict):
222
+ seasons_list = series_data.get("seasons", [])
223
+ elif isinstance(series_data, list):
224
+ seasons_list = series_data
225
+
226
+ for season in seasons_list:
218
227
  if not isinstance(season, dict): continue
219
- s_no = season.get("season_no") or season.get("seasonNo") # Try snake_case too
228
+ s_no = season.get("season_no") or season.get("seasonNo")
220
229
  ep_list = season.get("episodes", [])
221
230
  for ep in ep_list:
222
231
  episodes.append(Episode(
@@ -225,75 +234,85 @@ class SelcukFlix(PluginBase):
225
234
  title = ep.get("ep_text") or ep.get("epText"),
226
235
  url = self.fix_url(ep.get("used_slug") or ep.get("usedSlug"))
227
236
  ))
228
-
229
- return SeriesInfo(
230
- title = title,
231
- url = url,
232
- poster = poster,
233
- description = description,
234
- rating = rating,
235
- episodes = episodes
236
- )
237
-
238
- async def load_links(self, url: str) -> list[dict]:
237
+
238
+ return SeriesInfo(
239
+ title = title,
240
+ url = url,
241
+ poster = poster,
242
+ description = description,
243
+ rating = rating,
244
+ year = year,
245
+ episodes = episodes
246
+ )
247
+ else:
248
+ # Film ise MovieInfo döndür
249
+ return MovieInfo(
250
+ title = title,
251
+ url = url,
252
+ poster = poster,
253
+ description = description,
254
+ rating = rating,
255
+ year = year,
256
+ duration = duration
257
+ )
258
+
259
+ async def load_links(self, url: str) -> list[ExtractResult]:
239
260
  resp = await self.httpx.get(url)
240
261
  sel = Selector(resp.text)
241
262
 
242
263
  next_data = sel.css("script#__NEXT_DATA__::text").get()
243
- if not next_data: return []
264
+ if not next_data:
265
+ return []
244
266
 
245
267
  try:
246
- data = json.loads(next_data)
247
- secure_data = data["props"]["pageProps"]["secureData"]
248
- raw_data = base64.b64decode(secure_data.replace('"', ''))
249
- try:
250
- decoded_str = raw_data.decode('utf-8')
251
- except UnicodeDecodeError:
252
- decoded_str = raw_data.decode('iso-8859-1')
268
+ data = json.loads(next_data)
269
+ secure_data = data["props"]["pageProps"]["secureData"]
270
+ raw_data = base64.b64decode(secure_data.replace('"', ''))
253
271
 
254
- content_details = json.loads(decoded_str)
255
- related_data = content_details.get("relatedData", {})
256
-
257
- source_content = None
258
-
259
- # Check if Series (episode) or Movie
260
- if "/dizi/" in url:
261
- if related_data.get("episodeSources", {}).get("state"):
262
- res = related_data["episodeSources"].get("result", [])
263
- if res:
264
- source_content = res[0].get("sourceContent")
265
- else:
266
- # Movie
267
- if related_data.get("movieParts", {}).get("state"):
268
- # Looking for first part source
269
- movie_parts = related_data["movieParts"].get("result", [])
270
- if movie_parts:
271
- first_part_id = movie_parts[0].get("id")
272
- # RelatedResults -> getMoviePartSourcesById_ID
273
- rr = content_details.get("RelatedResults", {})
274
- key = f"getMoviePartSourcesById_{first_part_id}"
275
- if key in rr:
276
- res = rr[key].get("result", [])
277
- if res:
278
- source_content = res[0].get("source_content")
279
-
280
- results = []
281
- if source_content:
282
- iframe_sel = Selector(source_content)
283
- iframe_src = iframe_sel.css("iframe::attr(src)").get()
284
- if iframe_src:
285
- iframe_src = self.fix_url(iframe_src)
286
- # Domain replace
287
- if "sn.dplayer74.site" in iframe_src:
288
- iframe_src = iframe_src.replace("sn.dplayer74.site", "sn.hotlinger.com")
289
-
290
- extractor = self.ex_manager.find_extractor(iframe_src)
291
- results.append({
292
- "url": iframe_src,
293
- "name": extractor.name if extractor else "Iframe"
294
- })
295
-
296
- return results
272
+ try:
273
+ decoded_str = raw_data.decode('utf-8')
274
+ except UnicodeDecodeError:
275
+ decoded_str = raw_data.decode('iso-8859-1')
276
+
277
+ content_details = json.loads(decoded_str)
278
+ related_results = content_details.get("RelatedResults", {})
279
+
280
+ source_content = None
281
+
282
+ # Dizi (bölüm) için
283
+ if "/dizi/" in url:
284
+ episode_sources = related_results.get("getEpisodeSources", {})
285
+ if episode_sources.get("state"):
286
+ res = episode_sources.get("result", [])
287
+ if res:
288
+ source_content = res[0].get("source_content") or res[0].get("sourceContent")
289
+ else:
290
+ # Film için
291
+ movie_parts = related_results.get("getMoviePartsById", {})
292
+ if movie_parts.get("state"):
293
+ parts = movie_parts.get("result", [])
294
+ if parts:
295
+ first_part_id = parts[0].get("id")
296
+ key = f"getMoviePartSourcesById_{first_part_id}"
297
+ if key in related_results:
298
+ res = related_results[key].get("result", [])
299
+ if res:
300
+ source_content = res[0].get("source_content") or res[0].get("sourceContent")
301
+
302
+ if source_content:
303
+ iframe_sel = Selector(source_content)
304
+ iframe_src = iframe_sel.css("iframe::attr(src)").get()
305
+ if iframe_src:
306
+ iframe_src = self.fix_url(iframe_src)
307
+ # Hotlinger domain değişimi (Kotlin referansı)
308
+ if "sn.dplayer74.site" in iframe_src:
309
+ iframe_src = iframe_src.replace("sn.dplayer74.site", "sn.hotlinger.com")
310
+
311
+ data = await self.extract(iframe_src)
312
+ if data:
313
+ return [data]
314
+
315
+ return []
297
316
 
298
317
  except Exception:
299
318
  return []
@@ -0,0 +1,252 @@
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
4
+ from parsel import Selector
5
+ import re, json
6
+
7
+ class SetFilmIzle(PluginBase):
8
+ name = "SetFilmIzle"
9
+ language = "tr"
10
+ main_url = "https://www.setfilmizle.uk"
11
+ favicon = f"https://www.google.com/s2/favicons?domain={main_url}&sz=64"
12
+ description = "Setfilmizle sitemizde, donma yaşamadan Türkçe dublaj ve altyazılı filmleri ile dizileri muhteşem 1080p full HD kalitesinde izleyebilirsiniz."
13
+
14
+ main_page = {
15
+ f"{main_url}/tur/aile/" : "Aile",
16
+ f"{main_url}/tur/aksiyon/" : "Aksiyon",
17
+ f"{main_url}/tur/animasyon/" : "Animasyon",
18
+ f"{main_url}/tur/belgesel/" : "Belgesel",
19
+ f"{main_url}/tur/bilim-kurgu/" : "Bilim-Kurgu",
20
+ f"{main_url}/tur/biyografi/" : "Biyografi",
21
+ f"{main_url}/tur/dini/" : "Dini",
22
+ f"{main_url}/tur/dram/" : "Dram",
23
+ f"{main_url}/tur/fantastik/" : "Fantastik",
24
+ f"{main_url}/tur/genclik/" : "Gençlik",
25
+ f"{main_url}/tur/gerilim/" : "Gerilim",
26
+ f"{main_url}/tur/gizem/" : "Gizem",
27
+ f"{main_url}/tur/komedi/" : "Komedi",
28
+ f"{main_url}/tur/korku/" : "Korku",
29
+ f"{main_url}/tur/macera/" : "Macera",
30
+ f"{main_url}/tur/romantik/" : "Romantik",
31
+ f"{main_url}/tur/savas/" : "Savaş",
32
+ f"{main_url}/tur/suc/" : "Suç",
33
+ f"{main_url}/tur/tarih/" : "Tarih",
34
+ f"{main_url}/tur/western/" : "Western"
35
+ }
36
+
37
+ def _get_nonce(self, nonce_type: str = "video_nonce", referer: str = None) -> str:
38
+ """Site cache'lenmiş nonce'ları expire olabiliyor, fresh nonce al"""
39
+ try:
40
+ resp = self.cloudscraper.post(
41
+ f"{self.main_url}/wp-admin/admin-ajax.php",
42
+ headers = {
43
+ "Referer" : referer or self.main_url,
44
+ "Origin" : self.main_url,
45
+ "Content-Type" : "application/x-www-form-urlencoded",
46
+ },
47
+ data = "action=st_cache_refresh_nonces"
48
+ )
49
+ nonces = resp.json().get("data", {}).get("nonces", {})
50
+ return nonces.get(nonce_type, "")
51
+ except:
52
+ return ""
53
+
54
+ async def get_main_page(self, page: int, url: str, category: str) -> list[MainPageResult]:
55
+ istek = self.cloudscraper.get(url)
56
+ secici = Selector(istek.text)
57
+
58
+ results = []
59
+ for item in secici.css("div.items article"):
60
+ title = item.css("h2::text").get()
61
+ href = item.css("a::attr(href)").get()
62
+ poster = item.css("img::attr(data-src)").get()
63
+
64
+ if title and href:
65
+ results.append(MainPageResult(
66
+ category = category,
67
+ title = title.strip(),
68
+ url = self.fix_url(href),
69
+ poster = self.fix_url(poster) if poster else None
70
+ ))
71
+
72
+ return results
73
+
74
+ async def search(self, query: str) -> list[SearchResult]:
75
+ nonce = self._get_nonce("search")
76
+
77
+ search_resp = self.cloudscraper.post(
78
+ f"{self.main_url}/wp-admin/admin-ajax.php",
79
+ headers = {
80
+ "X-Requested-With" : "XMLHttpRequest",
81
+ "Content-Type" : "application/x-www-form-urlencoded",
82
+ "Referer" : f"{self.main_url}/"
83
+ },
84
+ data = {
85
+ "action" : "ajax_search",
86
+ "search" : query,
87
+ "original_search" : query,
88
+ "nonce" : nonce
89
+ }
90
+ )
91
+
92
+ try:
93
+ data = search_resp.json()
94
+ html = data.get("html", "")
95
+ except:
96
+ return []
97
+
98
+ secici = Selector(text=html)
99
+ results = []
100
+
101
+ for item in secici.css("div.items article"):
102
+ title = item.css("h2::text").get()
103
+ href = item.css("a::attr(href)").get()
104
+ poster = item.css("img::attr(data-src)").get()
105
+
106
+ if title and href:
107
+ results.append(SearchResult(
108
+ title = title.strip(),
109
+ url = self.fix_url(href),
110
+ poster = self.fix_url(poster) if poster else None
111
+ ))
112
+
113
+ return results
114
+
115
+ async def load_item(self, url: str) -> MovieInfo | SeriesInfo:
116
+ istek = await self.httpx.get(url)
117
+ secici = Selector(istek.text)
118
+
119
+ raw_title = secici.css("h1::text").get() or ""
120
+ title = re.sub(r"\s*izle.*$", "", raw_title, flags=re.IGNORECASE).strip()
121
+ poster = secici.css("div.poster img::attr(src)").get()
122
+ description = secici.css("div.wp-content p::text").get()
123
+ year = secici.css("div.extra span.C a::text").get()
124
+ if year:
125
+ year_match = re.search(r"\d{4}", year)
126
+ year = year_match.group() if year_match else None
127
+ tags = [a.css("::text").get().strip() for a in secici.css("div.sgeneros a") if a.css("::text").get()]
128
+ duration = secici.css("span.runtime::text").get()
129
+ if duration:
130
+ dur_match = re.search(r"\d+", duration)
131
+ duration = int(dur_match.group()) if dur_match else None
132
+
133
+ actors = [span.css("::text").get().strip() for span in secici.css("span.valor a > span") if span.css("::text").get()]
134
+
135
+ trailer_match = re.search(r'embed/([^?]*)\?rel', istek.text)
136
+ trailer = f"https://www.youtube.com/embed/{trailer_match.group(1)}" if trailer_match else None
137
+
138
+ # Dizi mi film mi kontrol et
139
+ is_series = "/dizi/" in url
140
+
141
+ if is_series:
142
+ year_elem = secici.css("a[href*='/yil/']::text").get()
143
+ if year_elem:
144
+ year_match = re.search(r"\d{4}", year_elem)
145
+ year = year_match.group() if year_match else year
146
+
147
+ dur_elem = secici.css("div#info span:contains('Dakika')::text").get()
148
+ if dur_elem:
149
+ dur_match = re.search(r"\d+", dur_elem)
150
+ duration = int(dur_match.group()) if dur_match else duration
151
+
152
+ episodes = []
153
+ for ep_item in secici.css("div#episodes ul.episodios li"):
154
+ ep_href = ep_item.css("h4.episodiotitle a::attr(href)").get()
155
+ ep_name = ep_item.css("h4.episodiotitle a::text").get()
156
+
157
+ if not ep_href or not ep_name:
158
+ continue
159
+
160
+ ep_detail = ep_name.strip()
161
+ season_match = re.search(r"(\d+)\.\s*Sezon", ep_detail)
162
+ episode_match = re.search(r"Sezon\s+(\d+)\.\s*Bölüm", ep_detail)
163
+
164
+ ep_season = int(season_match.group(1)) if season_match else 1
165
+ ep_episode = int(episode_match.group(1)) if episode_match else None
166
+
167
+ episodes.append(Episode(
168
+ season = ep_season,
169
+ episode = ep_episode,
170
+ title = ep_name.strip(),
171
+ url = self.fix_url(ep_href)
172
+ ))
173
+
174
+ return SeriesInfo(
175
+ url = url,
176
+ poster = self.fix_url(poster) if poster else None,
177
+ title = title,
178
+ description = description.strip() if description else None,
179
+ tags = tags,
180
+ year = year,
181
+ duration = duration,
182
+ actors = actors,
183
+ episodes = episodes
184
+ )
185
+
186
+ return MovieInfo(
187
+ url = url,
188
+ poster = self.fix_url(poster) if poster else None,
189
+ title = title,
190
+ description = description.strip() if description else None,
191
+ tags = tags,
192
+ year = year,
193
+ duration = duration,
194
+ actors = actors
195
+ )
196
+
197
+ async def load_links(self, url: str) -> list[ExtractResult]:
198
+ istek = await self.httpx.get(url)
199
+ secici = Selector(istek.text)
200
+
201
+ nonce = self._get_nonce("video_nonce", referer=url)
202
+
203
+ # partKey to dil label mapping
204
+ part_key_labels = {
205
+ "turkcedublaj" : "Türkçe Dublaj",
206
+ "turkcealtyazi" : "Türkçe Altyazı",
207
+ "orijinal" : "Orijinal"
208
+ }
209
+
210
+ links = []
211
+ for player in secici.css("nav.player a"):
212
+ source_id = player.css("::attr(data-post-id)").get()
213
+ player_name = player.css("::attr(data-player-name)").get()
214
+ part_key = player.css("::attr(data-part-key)").get()
215
+
216
+ if not source_id or "event" in source_id or source_id == "":
217
+ continue
218
+
219
+ try:
220
+ resp = self.cloudscraper.post(
221
+ f"{self.main_url}/wp-admin/admin-ajax.php",
222
+ headers = {"Referer": url},
223
+ data = {
224
+ "action" : "get_video_url",
225
+ "nonce" : nonce,
226
+ "post_id" : source_id,
227
+ "player_name" : player_name or "",
228
+ "part_key" : part_key or ""
229
+ }
230
+ )
231
+ data = resp.json()
232
+ except:
233
+ continue
234
+
235
+ iframe_url = data.get("data", {}).get("url")
236
+ if not iframe_url:
237
+ continue
238
+
239
+ # SetPlay URL'si için part_key ekleme
240
+ if "setplay" not in iframe_url and part_key:
241
+ iframe_url = f"{iframe_url}?partKey={part_key}"
242
+
243
+ # Dil etiketi oluştur
244
+ label = part_key_labels.get(part_key, "")
245
+ if not label and part_key:
246
+ label = part_key.replace("_", " ").title()
247
+
248
+ data = await self.extract(iframe_url, prefix=label if label else None)
249
+ if data:
250
+ links.append(data)
251
+
252
+ return links
@@ -1,7 +1,8 @@
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
3
+ from KekikStream.Core import PluginBase, MainPageResult, SearchResult, SeriesInfo, Episode, ExtractResult
4
4
  from parsel import Selector
5
+ import re
5
6
 
6
7
  class SezonlukDizi(PluginBase):
7
8
  name = "SezonlukDizi"
@@ -19,6 +20,23 @@ class SezonlukDizi(PluginBase):
19
20
  f"{main_url}/diziler.asp?siralama_tipi=id&kat=4&s=" : "Animasyonlar",
20
21
  f"{main_url}/diziler.asp?siralama_tipi=id&kat=5&s=" : "Animeler",
21
22
  f"{main_url}/diziler.asp?siralama_tipi=id&kat=6&s=" : "Belgeseller",
23
+ f"{main_url}/diziler.asp?siralama_tipi=id&tur=aile&s=" : "Aile",
24
+ f"{main_url}/diziler.asp?siralama_tipi=id&tur=aksiyon&s=" : "Aksiyon",
25
+ f"{main_url}/diziler.asp?siralama_tipi=id&tur=bilimkurgu&s=" : "Bilim Kurgu",
26
+ f"{main_url}/diziler.asp?siralama_tipi=id&tur=biyografik&s=" : "Biyografi",
27
+ f"{main_url}/diziler.asp?siralama_tipi=id&tur=dram&s=" : "Dram",
28
+ f"{main_url}/diziler.asp?siralama_tipi=id&tur=fantastik&s=" : "Fantastik",
29
+ f"{main_url}/diziler.asp?siralama_tipi=id&tur=gerilim&s=" : "Gerilim",
30
+ f"{main_url}/diziler.asp?siralama_tipi=id&tur=gizem&s=" : "Gizem",
31
+ f"{main_url}/diziler.asp?siralama_tipi=id&tur=korku&s=" : "Korku",
32
+ f"{main_url}/diziler.asp?siralama_tipi=id&tur=komedi&s=" : "Komedi",
33
+ f"{main_url}/diziler.asp?siralama_tipi=id&tur=macera&s=" : "Macera",
34
+ f"{main_url}/diziler.asp?siralama_tipi=id&tur=muzikal&s=" : "Müzikal",
35
+ f"{main_url}/diziler.asp?siralama_tipi=id&tur=suc&s=" : "Suç",
36
+ f"{main_url}/diziler.asp?siralama_tipi=id&tur=romantik&s=" : "Romantik",
37
+ f"{main_url}/diziler.asp?siralama_tipi=id&tur=savas&s=" : "Savaş",
38
+ f"{main_url}/diziler.asp?siralama_tipi=id&tur=tarihi&s=" : "Tarihi",
39
+ f"{main_url}/diziler.asp?siralama_tipi=id&tur=western&s=" : "Western"
22
40
  }
23
41
 
24
42
  async def get_main_page(self, page: int, url: str, category: str) -> list[MainPageResult]:
@@ -99,7 +117,21 @@ class SezonlukDizi(PluginBase):
99
117
  actors = actors
100
118
  )
101
119
 
102
- async def load_links(self, url: str) -> list[dict]:
120
+ async def get_asp_data(self) -> tuple[str, str]:
121
+ """Fetch dynamic ASP version numbers from site.min.js"""
122
+ try:
123
+ js_content = await self.httpx.get(f"{self.main_url}/js/site.min.js")
124
+ alternatif_match = re.search(r'dataAlternatif(.*?)\.asp', js_content.text)
125
+ embed_match = re.search(r'dataEmbed(.*?)\.asp', js_content.text)
126
+
127
+ alternatif_ver = alternatif_match.group(1) if alternatif_match else "22"
128
+ embed_ver = embed_match.group(1) if embed_match else "22"
129
+
130
+ return (alternatif_ver, embed_ver)
131
+ except Exception:
132
+ return ("22", "22") # Fallback to default versions
133
+
134
+ async def load_links(self, url: str) -> list[ExtractResult]:
103
135
  istek = await self.httpx.get(url)
104
136
  secici = Selector(istek.text)
105
137
 
@@ -107,10 +139,13 @@ class SezonlukDizi(PluginBase):
107
139
  if not bid:
108
140
  return []
109
141
 
142
+ # Get dynamic ASP versions
143
+ alternatif_ver, embed_ver = await self.get_asp_data()
144
+
110
145
  results = []
111
146
  for dil, label in [("1", "Altyazı"), ("0", "Dublaj")]:
112
147
  dil_istek = await self.httpx.post(
113
- url = f"{self.main_url}/ajax/dataAlternatif22.asp",
148
+ url = f"{self.main_url}/ajax/dataAlternatif{alternatif_ver}.asp",
114
149
  headers = {"X-Requested-With": "XMLHttpRequest"},
115
150
  data = {"bid": bid, "dil": dil},
116
151
  )
@@ -123,7 +158,7 @@ class SezonlukDizi(PluginBase):
123
158
  if dil_json.get("status") == "success":
124
159
  for idx, veri in enumerate(dil_json.get("data", [])):
125
160
  veri_response = await self.httpx.post(
126
- url = f"{self.main_url}/ajax/dataEmbed22.asp",
161
+ url = f"{self.main_url}/ajax/dataEmbed{embed_ver}.asp",
127
162
  headers = {"X-Requested-With": "XMLHttpRequest"},
128
163
  data = {"id": veri.get("id")},
129
164
  )
@@ -133,10 +168,9 @@ class SezonlukDizi(PluginBase):
133
168
  if "link.asp" in iframe:
134
169
  continue
135
170
 
136
- extractor = self.ex_manager.find_extractor(self.fix_url(iframe))
137
- results.append({
138
- "url" : self.fix_url(iframe),
139
- "name" : f"{extractor.name if extractor else f'{label} - Player {idx + 1}'}"
140
- })
171
+ iframe_url = self.fix_url(iframe)
172
+ data = await self.extract(iframe_url, prefix=label)
173
+ if data:
174
+ results.append(data)
141
175
 
142
176
  return results