KekikStream 2.3.9__py3-none-any.whl → 2.5.4__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 (85) hide show
  1. KekikStream/Core/Extractor/ExtractorBase.py +3 -2
  2. KekikStream/Core/Extractor/ExtractorLoader.py +8 -14
  3. KekikStream/Core/HTMLHelper.py +120 -49
  4. KekikStream/Core/Plugin/PluginBase.py +35 -12
  5. KekikStream/Core/Plugin/PluginLoader.py +12 -14
  6. KekikStream/Core/Plugin/PluginManager.py +2 -2
  7. KekikStream/Core/Plugin/PluginModels.py +0 -3
  8. KekikStream/Extractors/Abstream.py +27 -0
  9. KekikStream/Extractors/CloseLoad.py +30 -54
  10. KekikStream/Extractors/ContentX.py +27 -72
  11. KekikStream/Extractors/DonilasPlay.py +33 -77
  12. KekikStream/Extractors/DzenRu.py +10 -24
  13. KekikStream/Extractors/ExPlay.py +20 -38
  14. KekikStream/Extractors/Filemoon.py +21 -46
  15. KekikStream/Extractors/HDMomPlayer.py +30 -0
  16. KekikStream/Extractors/HDPlayerSystem.py +13 -31
  17. KekikStream/Extractors/HotStream.py +27 -0
  18. KekikStream/Extractors/JFVid.py +3 -24
  19. KekikStream/Extractors/JetTv.py +21 -34
  20. KekikStream/Extractors/JetV.py +55 -0
  21. KekikStream/Extractors/MailRu.py +11 -29
  22. KekikStream/Extractors/MixPlayHD.py +15 -28
  23. KekikStream/Extractors/MixTiger.py +17 -40
  24. KekikStream/Extractors/MolyStream.py +17 -21
  25. KekikStream/Extractors/Odnoklassniki.py +40 -104
  26. KekikStream/Extractors/PeaceMakerst.py +18 -45
  27. KekikStream/Extractors/PixelDrain.py +8 -16
  28. KekikStream/Extractors/PlayerFilmIzle.py +22 -41
  29. KekikStream/Extractors/RapidVid.py +21 -35
  30. KekikStream/Extractors/SetPlay.py +18 -43
  31. KekikStream/Extractors/SibNet.py +7 -17
  32. KekikStream/Extractors/Sobreatsesuyp.py +23 -45
  33. KekikStream/Extractors/TRsTX.py +23 -53
  34. KekikStream/Extractors/TurboImgz.py +7 -14
  35. KekikStream/Extractors/VCTPlay.py +10 -28
  36. KekikStream/Extractors/Veev.py +145 -0
  37. KekikStream/Extractors/VidBiz.py +62 -0
  38. KekikStream/Extractors/VidHide.py +58 -30
  39. KekikStream/Extractors/VidMoly.py +65 -99
  40. KekikStream/Extractors/VidMoxy.py +16 -27
  41. KekikStream/Extractors/VidPapi.py +24 -54
  42. KekikStream/Extractors/VideoSeyred.py +19 -40
  43. KekikStream/Extractors/Videostr.py +58 -0
  44. KekikStream/Extractors/Vidoza.py +18 -0
  45. KekikStream/Extractors/Vtbe.py +38 -0
  46. KekikStream/Extractors/YTDLP.py +2 -2
  47. KekikStream/Extractors/YildizKisaFilm.py +13 -31
  48. KekikStream/Extractors/Zeus.py +61 -0
  49. KekikStream/Plugins/BelgeselX.py +97 -77
  50. KekikStream/Plugins/DiziBox.py +28 -45
  51. KekikStream/Plugins/DiziMom.py +179 -0
  52. KekikStream/Plugins/DiziPal.py +95 -161
  53. KekikStream/Plugins/DiziYou.py +51 -147
  54. KekikStream/Plugins/Dizilla.py +40 -61
  55. KekikStream/Plugins/FilmBip.py +90 -39
  56. KekikStream/Plugins/FilmEkseni.py +199 -0
  57. KekikStream/Plugins/FilmMakinesi.py +72 -73
  58. KekikStream/Plugins/FilmModu.py +25 -35
  59. KekikStream/Plugins/Filmatek.py +184 -0
  60. KekikStream/Plugins/FilmciBaba.py +155 -0
  61. KekikStream/Plugins/FullHDFilmizlesene.py +16 -37
  62. KekikStream/Plugins/HDFilm.py +243 -0
  63. KekikStream/Plugins/HDFilmCehennemi.py +242 -189
  64. KekikStream/Plugins/JetFilmizle.py +101 -69
  65. KekikStream/Plugins/KultFilmler.py +138 -104
  66. KekikStream/Plugins/RecTV.py +52 -73
  67. KekikStream/Plugins/RoketDizi.py +18 -27
  68. KekikStream/Plugins/SelcukFlix.py +30 -48
  69. KekikStream/Plugins/SetFilmIzle.py +76 -104
  70. KekikStream/Plugins/SezonlukDizi.py +90 -94
  71. KekikStream/Plugins/Sinefy.py +195 -167
  72. KekikStream/Plugins/SinemaCX.py +148 -78
  73. KekikStream/Plugins/Sinezy.py +29 -31
  74. KekikStream/Plugins/SuperFilmGeldi.py +12 -17
  75. KekikStream/Plugins/UgurFilm.py +85 -38
  76. KekikStream/Plugins/Watch32.py +160 -0
  77. KekikStream/Plugins/YabanciDizi.py +176 -211
  78. {kekikstream-2.3.9.dist-info → kekikstream-2.5.4.dist-info}/METADATA +1 -1
  79. kekikstream-2.5.4.dist-info/RECORD +99 -0
  80. {kekikstream-2.3.9.dist-info → kekikstream-2.5.4.dist-info}/WHEEL +1 -1
  81. KekikStream/Plugins/FullHDFilm.py +0 -249
  82. kekikstream-2.3.9.dist-info/RECORD +0 -84
  83. {kekikstream-2.3.9.dist-info → kekikstream-2.5.4.dist-info}/entry_points.txt +0 -0
  84. {kekikstream-2.3.9.dist-info → kekikstream-2.5.4.dist-info}/licenses/LICENSE +0 -0
  85. {kekikstream-2.3.9.dist-info → kekikstream-2.5.4.dist-info}/top_level.txt +0 -0
@@ -1,7 +1,7 @@
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, Subtitle, ExtractResult
4
- from KekikStream.Core.HTMLHelper import HTMLHelper
3
+ from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo, Subtitle, ExtractResult, HTMLHelper
4
+ import asyncio, contextlib
5
5
 
6
6
  class SinemaCX(PluginBase):
7
7
  name = "SinemaCX"
@@ -46,14 +46,14 @@ class SinemaCX(PluginBase):
46
46
  if not title:
47
47
  continue
48
48
 
49
- href = secici.select_attr("div.yanac a", "href", veri)
49
+ href = secici.select_attr("div.yanac a", "href", veri)
50
50
  poster = secici.select_attr("a.resim img", "data-src", veri) or secici.select_attr("a.resim img", "src", veri)
51
51
 
52
52
  results.append(MainPageResult(
53
53
  category = category,
54
54
  title = title,
55
- url = self.fix_url(href) if href else "",
56
- poster = self.fix_url(poster) if poster else None,
55
+ url = self.fix_url(href),
56
+ poster = self.fix_url(poster),
57
57
  ))
58
58
 
59
59
  return results
@@ -68,13 +68,13 @@ class SinemaCX(PluginBase):
68
68
  if not title:
69
69
  continue
70
70
 
71
- href = secici.select_attr("div.yanac a", "href", veri)
71
+ href = secici.select_attr("div.yanac a", "href", veri)
72
72
  poster = secici.select_attr("a.resim img", "data-src", veri) or secici.select_attr("a.resim img", "src", veri)
73
73
 
74
74
  results.append(SearchResult(
75
75
  title = title,
76
- url = self.fix_url(href) if href else "",
77
- poster = self.fix_url(poster) if poster else None,
76
+ url = self.fix_url(href),
77
+ poster = self.fix_url(poster),
78
78
  ))
79
79
 
80
80
  return results
@@ -83,93 +83,163 @@ class SinemaCX(PluginBase):
83
83
  istek = await self.httpx.get(url)
84
84
  secici = HTMLHelper(istek.text)
85
85
 
86
- duration_match = secici.regex_first(r"Süre:.*?(\d+)\s*Dakika")
87
-
86
+ title = secici.select_text("div.f-bilgi h1")
87
+ poster = secici.select_poster("div.resim img")
88
88
  description = secici.select_text("div.ackl div.scroll-liste")
89
-
90
- poster = secici.select_attr("link[rel='image_src']", "href")
91
-
92
- title = secici.select_text("div.f-bilgi h1")
93
-
94
- tags = secici.select_all_text("div.f-bilgi div.tur a")
95
-
96
- year = secici.select_text("div.f-bilgi ul.detay a[href*='yapim']")
97
-
98
- actors = secici.select_all_text("li.oync li.oyuncu-k span.isim")
89
+ rating = secici.select_text("b.puandegistir")
90
+ tags = secici.select_texts("div.f-bilgi div.tur a")
91
+ year = secici.extract_year("ul.detay a[href*='yapim']")
92
+ actors = secici.select_texts("li.oync li.oyuncu-k span.isim")
93
+ _duration = secici.regex_first(r"<span>Süre:\s*</span>\s*(\d+)")
94
+ duration = int(_duration) if _duration else None
99
95
 
100
96
  return MovieInfo(
101
97
  url = url,
102
- poster = self.fix_url(poster) if poster else None,
98
+ poster = self.fix_url(poster),
103
99
  title = title,
104
100
  description = description,
101
+ rating = rating,
105
102
  tags = tags,
106
103
  year = year,
107
104
  actors = actors,
108
- duration = int(duration_match) if duration_match else None,
105
+ duration = duration,
109
106
  )
110
107
 
111
- async def load_links(self, url: str) -> list[ExtractResult]:
112
- istek = await self.httpx.get(url)
113
- secici = HTMLHelper(istek.text)
108
+ async def _get_iframe_from_source(self, text: str) -> str | None:
109
+ """Verilen sayfa kaynağındaki iframe'i (data-vsrc veya src) bulur."""
110
+ secici = HTMLHelper(text)
114
111
 
115
- iframe_list = secici.select_all_attr("iframe", "data-vsrc")
112
+ # Öncelik data-vsrc
113
+ if src := secici.select_attr("iframe", "data-vsrc"):
114
+ return self.fix_url(src.split("?img=")[0])
116
115
 
117
- # Sadece fragman varsa /2/ sayfasından dene
118
- has_only_trailer = all(
119
- "youtube" in (i or "").lower() or "fragman" in (i or "").lower() or "trailer" in (i or "").lower()
120
- for i in iframe_list
121
- )
122
-
123
- if has_only_trailer:
124
- alt_url = url.rstrip("/") + "/2/"
125
- alt_istek = await self.httpx.get(alt_url)
126
- alt_istek = await self.httpx.get(alt_url)
127
- alt_sec = HTMLHelper(alt_istek.text)
128
- iframe_list = alt_sec.select_all_attr("iframe", "data-vsrc")
116
+ # Sonra src
117
+ if src := secici.select_attr("iframe", "src"):
118
+ return self.fix_url(src)
129
119
 
130
- if not iframe_list:
131
- return []
132
-
133
- iframe = self.fix_url(iframe_list[0].split("?img=")[0])
134
- if not iframe:
135
- return []
120
+ return None
136
121
 
122
+ async def _process_player(self, iframe_url: str, name: str) -> list[ExtractResult]:
123
+ """Iframe URL'ini işler ve sonuç döndürür."""
137
124
  results = []
138
125
 
139
- # Altyazı kontrolü
140
- self.httpx.headers.update({"Referer": f"{self.main_url}/"})
141
- iframe_istek = await self.httpx.get(iframe)
142
- iframe_text = iframe_istek.text
143
-
144
- subtitles = []
145
- sub_section = HTMLHelper(iframe_text).regex_first(r'playerjsSubtitle\s*=\s*"(.+?)"')
146
- if sub_section:
147
- for lang, link in HTMLHelper(sub_section).regex_all(r'\[(.*?)](https?://[^\s\",]+)'):
148
- subtitles.append(Subtitle(name=lang, url=self.fix_url(link)))
149
-
150
- # player.filmizle.in kontrolü
151
- if "player.filmizle.in" in iframe.lower():
152
- base_url = HTMLHelper(iframe).regex_first(r"https?://([^/]+)")
153
- if base_url:
154
- vid_id = iframe.split("/")[-1]
155
-
156
- self.httpx.headers.update({"X-Requested-With": "XMLHttpRequest"})
157
- vid_istek = await self.httpx.post(
158
- f"https://{base_url}/player/index.php?data={vid_id}&do=getVideo",
159
- )
160
- vid_data = vid_istek.json()
161
-
162
- if vid_data.get("securedLink"):
163
- results.append(ExtractResult(
164
- name = f"{self.name}",
165
- url = vid_data["securedLink"],
166
- referer = iframe,
167
- subtitles = subtitles
168
- ))
126
+ if "player.filmizle.in" in iframe_url.lower():
127
+ with contextlib.suppress(Exception):
128
+ # Referer önemli
129
+ self.httpx.headers.update({"Referer": f"{self.main_url}/"})
130
+
131
+ # Iframe içeriğini çek (Altyazı ve JS için)
132
+ iframe_resp = await self.httpx.get(iframe_url)
133
+ iframe_text = iframe_resp.text
134
+
135
+ subtitles = []
136
+ if sub_section := HTMLHelper(iframe_text).regex_first(r'playerjsSubtitle\s*=\s*"(.+?)"'):
137
+ for lang, link in HTMLHelper(sub_section).regex_all(r'\[(.*?)](https?://[^\s\",]+)'):
138
+ subtitles.append(Subtitle(name=lang, url=self.fix_url(link)))
139
+
140
+ base_url = HTMLHelper(iframe_url).regex_first(r"https?://([^/]+)")
141
+ if base_url:
142
+ vid_id = iframe_url.split("/")[-1]
143
+ self.httpx.headers.update({"X-Requested-With": "XMLHttpRequest"})
144
+
145
+ vid_istek = await self.httpx.post(f"https://{base_url}/player/index.php?data={vid_id}&do=getVideo")
146
+ vid_data = vid_istek.json()
147
+
148
+ if link := vid_data.get("securedLink"):
149
+ results.append(ExtractResult(
150
+ name = name,
151
+ url = link,
152
+ referer = iframe_url,
153
+ subtitles = subtitles
154
+ ))
169
155
  else:
170
- # Extractor'a yönlendir
171
- data = await self.extract(iframe)
172
- if data:
173
- results.append(data)
156
+ # Standart Extractor
157
+ with contextlib.suppress(Exception):
158
+ extracted = await self.extract(iframe_url)
159
+ if extracted:
160
+ items = extracted if isinstance(extracted, list) else [extracted]
161
+ for item in items:
162
+ item.name = name
163
+ results.append(item)
174
164
 
175
165
  return results
166
+
167
+ async def load_links(self, url: str) -> list[ExtractResult]:
168
+ istek = await self.httpx.get(url)
169
+ main_text = istek.text
170
+ secici = HTMLHelper(main_text)
171
+
172
+ sources = [] #List of tuple (url, name, needs_fetch)
173
+
174
+ if part_list := secici.select("ul#part li, ul#f_part li"):
175
+ for li in part_list:
176
+ # Aktif Tab (li.tab-aktif veya span.secili)
177
+ if "tab-aktif" in li.attrs.get("class", ""):
178
+ if a_tag := secici.select_first("a", li):
179
+ # Direkt text al (deep=False)
180
+ val = a_tag.text(strip=True, deep=False)
181
+ name = val if val else "SinemaCX"
182
+ sources.append((None, name, False))
183
+
184
+ elif span := secici.select_first("span.secili", li):
185
+ name = span.text(strip=True)
186
+ sources.append((None, name, False))
187
+
188
+ # Pasif Tab
189
+ elif a_tag := secici.select_first("a", li):
190
+ href = a_tag.attrs.get("href")
191
+ # title varsa title, yoksa text (deep=False ile almayı dene önce)
192
+ name = a_tag.attrs.get("title")
193
+ if not name:
194
+ name = a_tag.text(strip=True, deep=False)
195
+ if not name:
196
+ name = a_tag.text(strip=True) # Fallback
197
+
198
+ if href:
199
+ sources.append((self.fix_url(href), name, True))
200
+ else:
201
+ # Tab yoksa, tek parça filmdir.
202
+ sources.append((None, "SinemaCX", False))
203
+
204
+ # 2. Kaynakları İşle
205
+ extract_tasks = []
206
+
207
+ async def process_task(source):
208
+ src_url, src_name, needs_fetch = source
209
+
210
+ iframe_url = None
211
+ if not needs_fetch:
212
+ # Mevcut sayfa (main_text)
213
+ iframe_url = await self._get_iframe_from_source(main_text)
214
+ else:
215
+ # Yeni sayfa fetch et
216
+ with contextlib.suppress(Exception):
217
+ resp = await self.httpx.get(src_url)
218
+ iframe_url = await self._get_iframe_from_source(resp.text)
219
+
220
+ if iframe_url:
221
+ if "youtube.com" in iframe_url or "youtu.be" in iframe_url:
222
+ return []
223
+ return await self._process_player(iframe_url, src_name)
224
+ return []
225
+
226
+ for src in sources:
227
+ extract_tasks.append(process_task(src))
228
+
229
+ results_groups = await asyncio.gather(*extract_tasks)
230
+
231
+ final_results = []
232
+ for group in results_groups:
233
+ if group:
234
+ final_results.extend(group)
235
+
236
+ # Duplicate Eliminasyonu
237
+ unique_results = []
238
+ seen = set()
239
+ for res in final_results:
240
+ key = (res.url, res.name)
241
+ if res.url and key not in seen:
242
+ unique_results.append(res)
243
+ seen.add(key)
244
+
245
+ return unique_results
@@ -1,12 +1,12 @@
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, ExtractResult, HTMLHelper
3
+ from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo, ExtractResult, HTMLHelper
4
4
  import base64
5
5
 
6
6
  class Sinezy(PluginBase):
7
7
  name = "Sinezy"
8
8
  language = "tr"
9
- main_url = "https://sinezy.fit"
9
+ main_url = "https://sinezy.ink"
10
10
  favicon = f"https://www.google.com/s2/favicons?domain={main_url}&sz=64"
11
11
  description = "Yerli ve yabancı film izle! Türkçe Dublaj ve Alt Yazılı Seçenekleriyle full hd film izlemek için En çok tercih edilen adres!"
12
12
 
@@ -42,30 +42,28 @@ class Sinezy(PluginBase):
42
42
  }
43
43
 
44
44
  async def get_main_page(self, page: int, url: str, category: str) -> list[MainPageResult]:
45
- full_url = f"{url}page/{page}/"
46
- resp = await self.httpx.get(full_url)
47
- secici = HTMLHelper(resp.text)
48
-
45
+ istek = await self.httpx.get(f"{url}page/{page}/")
46
+ secici = HTMLHelper(istek.text)
47
+
49
48
  results = []
50
49
  for item in secici.select("div.container div.content div.movie_box.move_k"):
51
50
  title = secici.select_attr("a", "title", item)
52
51
  href = secici.select_attr("a", "href", item)
53
52
  poster = secici.select_attr("img", "data-src", item)
54
-
53
+
55
54
  if title and href:
56
55
  results.append(MainPageResult(
57
56
  category = category,
58
57
  title = title,
59
58
  url = self.fix_url(href),
60
- poster = self.fix_url(poster) if poster else None
59
+ poster = self.fix_url(poster)
61
60
  ))
62
61
 
63
62
  return results
64
63
 
65
64
  async def search(self, query: str) -> list[SearchResult]:
66
- url = f"{self.main_url}/arama/?s={query}"
67
- resp = await self.httpx.get(url)
68
- secici = HTMLHelper(resp.text)
65
+ istek = await self.httpx.get(f"{self.main_url}/arama/?s={query}")
66
+ secici = HTMLHelper(istek.text)
69
67
 
70
68
  results = []
71
69
  for item in secici.select("div.movie_box.move_k"):
@@ -77,51 +75,51 @@ class Sinezy(PluginBase):
77
75
  results.append(SearchResult(
78
76
  title = title,
79
77
  url = self.fix_url(href),
80
- poster = self.fix_url(poster) if poster else None
78
+ poster = self.fix_url(poster)
81
79
  ))
82
80
 
83
81
  return results
84
82
 
85
83
  async def load_item(self, url: str) -> MovieInfo:
86
- resp = await self.httpx.get(url)
87
- secici = HTMLHelper(resp.text)
84
+ istek = await self.httpx.get(url)
85
+ secici = HTMLHelper(istek.text)
88
86
 
89
- title = secici.select_attr("div.detail", "title")
90
- poster = secici.select_attr("div.move_k img", "data-src")
87
+ title = secici.select_attr("div.detail", "title")
88
+ poster = secici.select_poster("div.move_k img")
91
89
  description = secici.select_text("div.desc.yeniscroll p")
92
- rating = secici.select_text("span.info span.imdb")
93
-
94
- tags = secici.select_all_text("div.detail span a")
95
- actors = secici.select_all_text("span.oyn p")
90
+ rating = secici.select_text("span.info span.imdb")
91
+ tags = secici.select_texts("div.detail span a")
92
+ actors = secici.select_texts("span.oyn p")
93
+ year = secici.extract_year()
94
+ duration = secici.regex_first(r"(\d+) Dakika", secici.select_text("div.detail p"))
96
95
 
97
- year = secici.regex_first(r"\b(19\d{2}|20\d{2})\b")
98
- if not year:
99
- year = secici.regex_first(r"\b(19\d{2}|20\d{2})\b", secici.html)
100
96
  return MovieInfo(
101
- title = title,
102
97
  url = url,
103
- poster = self.fix_url(poster) if poster else None,
98
+ poster = self.fix_url(poster),
99
+ title = title,
104
100
  description = description,
105
101
  tags = tags,
106
102
  rating = rating,
103
+ year = year,
107
104
  actors = actors,
108
- year = year
105
+ duration = duration
109
106
  )
110
107
 
111
108
  async def load_links(self, url: str) -> list[ExtractResult]:
112
- resp = await self.httpx.get(url)
113
- secici = HTMLHelper(resp.text)
109
+ istek = await self.httpx.get(url)
110
+ secici = HTMLHelper(istek.text)
114
111
 
115
112
  encoded = secici.regex_first(r"ilkpartkod\s*=\s*'([^']+)'", secici.html)
113
+ name = secici.select_direct_text("li.pgrup a")
116
114
  if encoded:
117
115
  try:
118
- decoded = base64.b64decode(encoded).decode('utf-8')
116
+ decoded = base64.b64decode(encoded).decode('utf-8')
119
117
  decoded_sec = HTMLHelper(decoded)
120
- iframe = decoded_sec.select_attr('iframe', 'src')
118
+ iframe = decoded_sec.select_attr('iframe', 'src')
121
119
 
122
120
  if iframe:
123
121
  iframe = self.fix_url(iframe)
124
- data = await self.extract(iframe)
122
+ data = await self.extract(iframe, name_override=name)
125
123
  if data:
126
124
  return [data]
127
125
  except Exception:
@@ -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, ExtractResult, HTMLHelper
3
+ from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo, ExtractResult, HTMLHelper
4
4
 
5
5
  class SuperFilmGeldi(PluginBase):
6
6
  name = "SuperFilmGeldi"
@@ -42,14 +42,14 @@ class SuperFilmGeldi(PluginBase):
42
42
  if not title_text:
43
43
  continue
44
44
 
45
- href = secici.select_attr("span.movie-title a", "href", veri)
45
+ href = secici.select_attr("span.movie-title a", "href", veri)
46
46
  poster = secici.select_attr("img", "src", veri)
47
47
 
48
48
  results.append(MainPageResult(
49
49
  category = category,
50
50
  title = self.clean_title(title_text.split(" izle")[0]),
51
51
  url = self.fix_url(href) if href else "",
52
- poster = self.fix_url(poster) if poster else None,
52
+ poster = self.fix_url(poster),
53
53
  ))
54
54
 
55
55
  return results
@@ -64,13 +64,13 @@ class SuperFilmGeldi(PluginBase):
64
64
  if not title_text:
65
65
  continue
66
66
 
67
- href = secici.select_attr("span.movie-title a", "href", veri)
67
+ href = secici.select_attr("span.movie-title a", "href", veri)
68
68
  poster = secici.select_attr("img", "src", veri)
69
69
 
70
70
  results.append(SearchResult(
71
71
  title = self.clean_title(title_text.split(" izle")[0]),
72
72
  url = self.fix_url(href) if href else "",
73
- poster = self.fix_url(poster) if poster else None,
73
+ poster = self.fix_url(poster),
74
74
  ))
75
75
 
76
76
  return results
@@ -79,26 +79,21 @@ class SuperFilmGeldi(PluginBase):
79
79
  istek = await self.httpx.get(url)
80
80
  secici = HTMLHelper(istek.text)
81
81
 
82
- title = secici.select_text("div.title h1") or ""
83
- title = self.clean_title(title.split(" izle")[0]) if title else ""
84
-
85
- poster = secici.select_attr("div.poster img", "src")
86
-
87
- year = secici.extract_year("div.release a")
88
-
82
+ title = self.clean_title(secici.select_text("div.title h1").split(" izle")[0]) if secici.select_text("div.title h1") else ""
83
+ poster = secici.select_poster("div.poster img")
84
+ year = secici.extract_year("div.release a")
89
85
  description = secici.select_text("div.excerpt p")
90
-
91
- tags = secici.select_all_text("div.categories a")
92
- actors = secici.select_all_text("div.actor a")
86
+ tags = secici.select_texts("div.categories a")
87
+ actors = secici.select_texts("div.actor a")
93
88
 
94
89
  return MovieInfo(
95
90
  url = url,
96
- poster = self.fix_url(poster) if poster else None,
91
+ poster = self.fix_url(poster),
97
92
  title = title,
98
93
  description = description,
99
94
  tags = tags,
100
95
  year = year,
101
- actors = actors,
96
+ actors = actors
102
97
  )
103
98
 
104
99
  async def load_links(self, url: str) -> list[ExtractResult]:
@@ -1,6 +1,7 @@
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, ExtractResult, HTMLHelper
3
+ from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo, ExtractResult, HTMLHelper
4
+ import asyncio, contextlib
4
5
 
5
6
  class UgurFilm(PluginBase):
6
7
  name = "UgurFilm"
@@ -33,14 +34,14 @@ class UgurFilm(PluginBase):
33
34
  if not title:
34
35
  continue
35
36
 
36
- href = secici.select_attr("a", "href", veri)
37
+ href = secici.select_attr("a", "href", veri)
37
38
  poster = secici.select_attr("img", "src", veri)
38
39
 
39
40
  results.append(MainPageResult(
40
41
  category = category,
41
42
  title = title,
42
43
  url = self.fix_url(href) if href else "",
43
- poster = self.fix_url(poster) if poster else None,
44
+ poster = self.fix_url(poster),
44
45
  ))
45
46
 
46
47
  return results
@@ -51,8 +52,8 @@ class UgurFilm(PluginBase):
51
52
 
52
53
  results = []
53
54
  for film in secici.select("div.icerik div"):
54
- title = secici.select_text("a.baslik span", film)
55
- href = secici.select_attr("a", "href", film)
55
+ title = secici.select_text("a.baslik span", film)
56
+ href = secici.select_attr("a", "href", film)
56
57
  poster = secici.select_attr("img", "src", film)
57
58
 
58
59
  if title and href:
@@ -68,25 +69,25 @@ class UgurFilm(PluginBase):
68
69
  istek = await self.httpx.get(url)
69
70
  secici = HTMLHelper(istek.text)
70
71
 
71
- title = secici.select_text("div.bilgi h2") or ""
72
- poster = secici.select_attr("div.resim img", "src") or ""
73
- description = secici.select_text("div.slayt-aciklama") or ""
74
-
75
- tags = secici.select_all_text("p.tur a[href*='/category/']")
76
-
77
- year_val = secici.extract_year("a[href*='/yil/']")
78
- year = str(year_val) if year_val else None
79
-
80
- actors = secici.select_all_text("li.oyuncu-k span")
72
+ title = secici.select_text("div.bilgi h2")
73
+ poster = secici.select_poster("div.resim img")
74
+ description = secici.select_text("div.slayt-aciklama")
75
+ rating = secici.select_text("b#puandegistir")
76
+ tags = secici.select_texts("p.tur a[href*='/category/']")
77
+ year = secici.extract_year("a[href*='/yil/']")
78
+ actors = secici.select_texts("li.oyuncu-k span")
79
+ duration = secici.regex_first(r"(\d+) Dakika", secici.select_text("div.bilgi b"))
81
80
 
82
81
  return MovieInfo(
83
- url = self.fix_url(url),
84
- poster = self.fix_url(poster) if poster else None,
82
+ url = url,
83
+ poster = self.fix_url(poster),
85
84
  title = title,
86
85
  description = description,
86
+ rating = rating,
87
87
  tags = tags,
88
88
  year = year,
89
89
  actors = actors,
90
+ duration = duration
90
91
  )
91
92
 
92
93
  async def load_links(self, url: str) -> list[ExtractResult]:
@@ -94,27 +95,73 @@ class UgurFilm(PluginBase):
94
95
  secici = HTMLHelper(istek.text)
95
96
  results = []
96
97
 
97
- part_links = secici.select_all_attr("li.parttab a", "href")
98
+ part_links = secici.select_attrs("li.parttab a", "href")
99
+ if not part_links:
100
+ part_links = [url]
98
101
 
99
- for part_link in part_links:
100
- sub_response = await self.httpx.get(part_link)
101
- sub_selector = HTMLHelper(sub_response.text)
102
-
103
- iframe = sub_selector.select_attr("div#vast iframe", "src")
104
-
105
- if iframe and self.main_url in iframe:
106
- post_data = {
107
- "vid" : iframe.split("vid=")[-1],
108
- "alternative" : "vidmoly",
109
- "ord" : "0",
110
- }
111
- player_response = await self.httpx.post(
102
+ async def process_alt(vid: str, alt_name: str, ord_val: str) -> list[ExtractResult]:
103
+ """Alternatif player kaynağından video linkini çıkarır."""
104
+ with contextlib.suppress(Exception):
105
+ resp = await self.httpx.post(
112
106
  url = f"{self.main_url}/player/ajax_sources.php",
113
- data = post_data
107
+ data = {"vid": vid, "alternative": alt_name, "ord": ord_val}
114
108
  )
115
- iframe = self.fix_url(player_response.json().get("iframe"))
116
- data = await self.extract(iframe)
117
- if data:
118
- results.append(data)
119
-
120
- return results
109
+ if iframe_url := resp.json().get("iframe"):
110
+ data = await self.extract(self.fix_url(iframe_url))
111
+ if not data:
112
+ return []
113
+
114
+ return data if isinstance(data, list) else [data]
115
+
116
+ return []
117
+
118
+ async def process_part(part_url: str) -> list[ExtractResult]:
119
+ """Her bir part sayfasını ve alternatiflerini işler."""
120
+ try:
121
+ # Elimizde zaten olan ana sayfayı tekrar çekmemek için
122
+ if part_url == url:
123
+ sub_sec = secici
124
+ else:
125
+ sub_resp = await self.httpx.get(part_url)
126
+ sub_sec = HTMLHelper(sub_resp.text)
127
+
128
+ iframe = sub_sec.select_attr("div#vast iframe", "src")
129
+ if not iframe:
130
+ return []
131
+
132
+ if self.main_url not in iframe:
133
+ data = await self.extract(self.fix_url(iframe))
134
+ if not data:
135
+ return []
136
+
137
+ return data if isinstance(data, list) else [data]
138
+
139
+ # İç kaynaklı ise 3 alternatif için paralel istek at
140
+ vid = iframe.split("vid=")[-1]
141
+ tasks = [
142
+ process_alt(vid, "vidmoly", "0"),
143
+ process_alt(vid, "ok.ru", "1"),
144
+ process_alt(vid, "mailru", "2")
145
+ ]
146
+
147
+ alt_results = await asyncio.gather(*tasks)
148
+
149
+ return [item for sublist in alt_results for item in sublist]
150
+ except Exception:
151
+ return []
152
+
153
+ # Tüm partları paralel işle
154
+ groups = await asyncio.gather(*(process_part(p) for p in part_links))
155
+
156
+ for group in groups:
157
+ results.extend(group)
158
+
159
+ # Duplicate Temizliği
160
+ unique_results = []
161
+ seen = set()
162
+ for res in results:
163
+ if res.url and res.url not in seen:
164
+ unique_results.append(res)
165
+ seen.add(res.url)
166
+
167
+ return unique_results