KekikStream 2.4.8__py3-none-any.whl → 2.5.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.

Potentially problematic release.


This version of KekikStream might be problematic. Click here for more details.

@@ -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,13 +46,13 @@ 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 "",
55
+ url = self.fix_url(href),
56
56
  poster = self.fix_url(poster),
57
57
  ))
58
58
 
@@ -68,12 +68,12 @@ 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 "",
76
+ url = self.fix_url(href),
77
77
  poster = self.fix_url(poster),
78
78
  ))
79
79
 
@@ -90,6 +90,8 @@ class SinemaCX(PluginBase):
90
90
  tags = secici.select_texts("div.f-bilgi div.tur a")
91
91
  year = secici.extract_year("ul.detay a[href*='yapim']")
92
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
93
95
 
94
96
  return MovieInfo(
95
97
  url = url,
@@ -99,71 +101,145 @@ class SinemaCX(PluginBase):
99
101
  rating = rating,
100
102
  tags = tags,
101
103
  year = year,
102
- actors = actors
104
+ actors = actors,
105
+ duration = duration,
103
106
  )
104
107
 
105
- async def load_links(self, url: str) -> list[ExtractResult]:
106
- istek = await self.httpx.get(url)
107
- 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)
108
111
 
109
- iframe_list = secici.select_attrs("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])
110
115
 
111
- # Sadece fragman varsa /2/ sayfasından dene
112
- has_only_trailer = all(
113
- "youtube" in (i or "").lower() or "fragman" in (i or "").lower() or "trailer" in (i or "").lower()
114
- for i in iframe_list
115
- )
116
+ # Sonra src
117
+ if src := secici.select_attr("iframe", "src"):
118
+ return self.fix_url(src)
116
119
 
117
- if has_only_trailer:
118
- alt_url = url.rstrip("/") + "/2/"
119
- alt_istek = await self.httpx.get(alt_url)
120
+ return None
120
121
 
121
- alt_sec = HTMLHelper(alt_istek.text)
122
- iframe_list = alt_sec.select_attrs("iframe", "data-vsrc")
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."""
124
+ results = []
123
125
 
124
- if not iframe_list:
125
- return []
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
+ ))
155
+ else:
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)
164
+
165
+ return results
126
166
 
127
- iframe = self.fix_url(iframe_list[0].split("?img=")[0])
128
- if not iframe:
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)
129
224
  return []
130
225
 
131
- results = []
226
+ for src in sources:
227
+ extract_tasks.append(process_task(src))
132
228
 
133
- # Altyazı kontrolü
134
- self.httpx.headers.update({"Referer": f"{self.main_url}/"})
135
- iframe_istek = await self.httpx.get(iframe)
136
- iframe_text = iframe_istek.text
137
-
138
- subtitles = []
139
- sub_section = HTMLHelper(iframe_text).regex_first(r'playerjsSubtitle\s*=\s*"(.+?)"')
140
- if sub_section:
141
- for lang, link in HTMLHelper(sub_section).regex_all(r'\[(.*?)](https?://[^\s\",]+)'):
142
- subtitles.append(Subtitle(name=lang, url=self.fix_url(link)))
143
-
144
- # player.filmizle.in kontrolü
145
- if "player.filmizle.in" in iframe.lower():
146
- base_url = HTMLHelper(iframe).regex_first(r"https?://([^/]+)")
147
- if base_url:
148
- vid_id = iframe.split("/")[-1]
149
-
150
- self.httpx.headers.update({"X-Requested-With": "XMLHttpRequest"})
151
- vid_istek = await self.httpx.post(
152
- f"https://{base_url}/player/index.php?data={vid_id}&do=getVideo",
153
- )
154
- vid_data = vid_istek.json()
155
-
156
- if vid_data.get("securedLink"):
157
- results.append(ExtractResult(
158
- name = f"{self.name}",
159
- url = vid_data["securedLink"],
160
- referer = iframe,
161
- subtitles = subtitles
162
- ))
163
- else:
164
- # Extractor'a yönlendir
165
- data = await self.extract(iframe)
166
- if data:
167
- results.append(data)
229
+ results_groups = await asyncio.gather(*extract_tasks)
168
230
 
169
- return results
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,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
  import base64
5
5
 
6
6
  class Sinezy(PluginBase):
@@ -42,16 +42,15 @@ 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,
@@ -63,9 +62,8 @@ class Sinezy(PluginBase):
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"):
@@ -83,8 +81,8 @@ class Sinezy(PluginBase):
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
87
  title = secici.select_attr("div.detail", "title")
90
88
  poster = secici.select_poster("div.move_k img")
@@ -108,19 +106,20 @@ class Sinezy(PluginBase):
108
106
  )
109
107
 
110
108
  async def load_links(self, url: str) -> list[ExtractResult]:
111
- resp = await self.httpx.get(url)
112
- secici = HTMLHelper(resp.text)
109
+ istek = await self.httpx.get(url)
110
+ secici = HTMLHelper(istek.text)
113
111
 
114
112
  encoded = secici.regex_first(r"ilkpartkod\s*=\s*'([^']+)'", secici.html)
113
+ name = secici.select_direct_text("li.pgrup a")
115
114
  if encoded:
116
115
  try:
117
- decoded = base64.b64decode(encoded).decode('utf-8')
116
+ decoded = base64.b64decode(encoded).decode('utf-8')
118
117
  decoded_sec = HTMLHelper(decoded)
119
- iframe = decoded_sec.select_attr('iframe', 'src')
118
+ iframe = decoded_sec.select_attr('iframe', 'src')
120
119
 
121
120
  if iframe:
122
121
  iframe = self.fix_url(iframe)
123
- data = await self.extract(iframe)
122
+ data = await self.extract(iframe, name_override=name)
124
123
  if data:
125
124
  return [data]
126
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,7 +42,7 @@ 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(
@@ -64,7 +64,7 @@ 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(
@@ -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,7 +34,7 @@ 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(
@@ -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:
@@ -95,26 +96,72 @@ class UgurFilm(PluginBase):
95
96
  results = []
96
97
 
97
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
@@ -1,8 +1,6 @@
1
1
  # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
2
 
3
3
  from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo, SeriesInfo, Episode, ExtractResult, HTMLHelper
4
- from json import dumps, loads
5
- import re
6
4
 
7
5
  class Watch32(PluginBase):
8
6
  name = "Watch32"
@@ -39,7 +37,6 @@ class Watch32(PluginBase):
39
37
  f"{main_url}/genre/western?page=" : "Western",
40
38
  }
41
39
 
42
-
43
40
  async def get_main_page(self, page: int, url: str, category: str) -> list[MainPageResult]:
44
41
  istek = await self.httpx.get(f"{url}{page}")
45
42
  helper = HTMLHelper(istek.text)
@@ -52,44 +49,40 @@ class Watch32(PluginBase):
52
49
  url = self.fix_url(helper.select_attr("h2.film-name a", "href", veri)),
53
50
  poster = helper.select_attr("img.film-poster-img", "data-src", veri)
54
51
  )
55
- for veri in items
52
+ for veri in items
56
53
  ]
57
54
 
58
55
  async def search(self, query: str) -> list[SearchResult]:
59
- slug = query.replace(" ", "-")
60
- url = f"{self.main_url}/search/{slug}"
61
-
62
- istek = await self.httpx.get(url)
63
- helper = HTMLHelper(istek.text)
64
- items = helper.select("div.flw-item")
56
+ istek = await self.httpx.get(f"{self.main_url}/search/{query.replace(' ', '-')}")
57
+ secici = HTMLHelper(istek.text)
65
58
 
66
59
  return [
67
60
  SearchResult(
68
- title = helper.select_attr("h2.film-name a", "title", veri),
69
- url = self.fix_url(helper.select_attr("h2.film-name a", "href", veri)),
70
- poster = helper.select_attr("img.film-poster-img", "data-src", veri)
61
+ title = secici.select_attr("h2.film-name a", "title", veri),
62
+ url = self.fix_url(secici.select_attr("h2.film-name a", "href", veri)),
63
+ poster = secici.select_attr("img.film-poster-img", "data-src", veri)
71
64
  )
72
- for veri in items
65
+ for veri in secici.select("div.flw-item")
73
66
  ]
74
67
 
75
68
  async def load_item(self, url: str) -> MovieInfo | SeriesInfo:
76
69
  istek = await self.httpx.get(url)
77
- helper = HTMLHelper(istek.text)
78
-
79
- content_id = helper.select_attr("div.detail_page-watch", "data-id")
80
- details = helper.select_first("div.detail_page-infor")
81
- name = helper.select_text("h2.heading-name > a", details)
82
- poster = helper.select_poster("div.film-poster > img", details)
83
- description = helper.select_text("div.description", details)
84
- year = str(helper.extract_year())
85
- tags = helper.meta_list("Genre", container_selector="div.row-line")
86
- rating = helper.select_text("button.btn-imdb").replace("N/A", "").split(":")[-1].strip() if helper.select_text("button.btn-imdb") else None
87
- actors = helper.meta_list("Casts", container_selector="div.row-line")
70
+ secici = HTMLHelper(istek.text)
71
+
72
+ content_id = secici.select_attr("div.detail_page-watch", "data-id")
73
+ details = secici.select_first("div.detail_page-infor")
74
+ name = secici.select_text("h2.heading-name > a", details)
75
+ poster = secici.select_poster("div.film-poster > img", details)
76
+ description = secici.select_text("div.description", details)
77
+ year = str(secici.extract_year())
78
+ tags = secici.meta_list("Genre", container_selector="div.row-line")
79
+ rating = secici.select_text("button.btn-imdb").replace("N/A", "").split(":")[-1].strip() if secici.select_text("button.btn-imdb") else None
80
+ actors = secici.meta_list("Casts", container_selector="div.row-line")
88
81
 
89
82
  common_info = {
90
83
  "url" : url,
91
84
  "poster" : self.fix_url(poster),
92
- "title" : name or "Bilinmiyor",
85
+ "title" : name,
93
86
  "description" : description,
94
87
  "tags" : tags,
95
88
  "rating" : rating,
@@ -103,32 +96,30 @@ class Watch32(PluginBase):
103
96
  episodes = []
104
97
  seasons_resp = await self.httpx.get(f"{self.main_url}/ajax/season/list/{content_id}")
105
98
  sh = HTMLHelper(seasons_resp.text)
106
-
99
+
107
100
  for season in sh.select("a.dropdown-item"):
108
101
  season_id = season.attrs.get("data-id")
109
102
  s_val, _ = sh.extract_season_episode(season.text())
110
-
103
+
111
104
  e_resp = await self.httpx.get(f"{self.main_url}/ajax/season/episodes/{season_id}")
112
105
  eh = HTMLHelper(e_resp.text)
113
-
106
+
114
107
  for ep in eh.select("a.eps-item"):
115
108
  ep_id = ep.attrs.get("data-id")
116
109
  ep_title = ep.attrs.get("title", "")
117
110
  _, e_val = eh.extract_season_episode(ep_title)
118
-
111
+
119
112
  episodes.append(Episode(
120
113
  season = s_val or 1,
121
114
  episode = e_val or 1,
122
115
  title = ep_title,
123
116
  url = f"servers/{ep_id}"
124
117
  ))
125
-
118
+
126
119
  return SeriesInfo(**common_info, episodes=episodes)
127
120
 
128
121
  async def load_links(self, url: str) -> list[ExtractResult]:
129
122
  # url in load_links might be the full page URL for movies or "servers/epId" for episodes
130
- if "servers/" in url:
131
- data = url.split("/")[-1]
132
123
  if "servers/" in url:
133
124
  data = url.split("/")[-1]
134
125
  servers_url = f"servers/{data}"
@@ -137,39 +128,33 @@ class Watch32(PluginBase):
137
128
  servers_url = f"list/{data}"
138
129
  else:
139
130
  # Re-fetch page to get contentId only if we don't have list/ or servers/
140
- istek = await self.httpx.get(url)
141
- helper = HTMLHelper(istek.text)
142
- content_id = helper.select_attr("div.detail_page-watch", "data-id")
131
+ istek = await self.httpx.get(url)
132
+ secici = HTMLHelper(istek.text)
133
+ content_id = secici.select_attr("div.detail_page-watch", "data-id")
143
134
  if not content_id:
144
- # Try to get id from url if direct parse fails, similar to Kotlin logic
145
- # But Kotlin parses search first. Here we assume we are at the page.
146
- # If no content_id found, maybe it's not a valid page or structure changed.
147
135
  return []
148
136
  servers_url = f"list/{content_id}"
149
137
 
150
138
  servers_resp = await self.httpx.get(f"{self.main_url}/ajax/episode/{servers_url}")
151
- sh = HTMLHelper(servers_resp.text)
152
- servers = sh.select("a.link-item")
153
-
139
+ sh = HTMLHelper(servers_resp.text)
140
+ servers = sh.select("a.link-item")
141
+
154
142
  results = []
155
143
  for server in servers:
156
- link_id = server.attrs.get("data-linkid") or server.attrs.get("data-id")
144
+ server_name = server.text(strip=True)
145
+ link_id = server.attrs.get("data-linkid") or server.attrs.get("data-id")
157
146
  source_resp = await self.httpx.get(f"{self.main_url}/ajax/episode/sources/{link_id}")
158
147
  source_data = source_resp.json()
159
- video_url = source_data.get("link")
160
-
148
+ video_url = source_data.get("link")
149
+
161
150
  if video_url:
162
- # Use extractors if possible
163
- extract_result = await self.extract(video_url)
151
+ extract_result = await self.extract(video_url, name_override=server_name)
164
152
  if extract_result:
165
- if isinstance(extract_result, list):
166
- results.extend(extract_result)
167
- else:
168
- results.append(extract_result)
153
+ results.extend(extract_result if isinstance(extract_result, list) else [extract_result])
169
154
  else:
170
155
  results.append(ExtractResult(
171
156
  url = video_url,
172
- name = f"{self.name} | {server.text()}"
157
+ name = f"{self.name} | {server_name}"
173
158
  ))
174
-
159
+
175
160
  return results