KekikStream 2.4.6__py3-none-any.whl → 2.4.8__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 (38) hide show
  1. KekikStream/Core/HTMLHelper.py +2 -2
  2. KekikStream/Core/Plugin/PluginBase.py +15 -4
  3. KekikStream/Extractors/Odnoklassniki.py +14 -2
  4. KekikStream/Extractors/YTDLP.py +2 -2
  5. KekikStream/Plugins/BelgeselX.py +30 -23
  6. KekikStream/Plugins/DiziBox.py +14 -11
  7. KekikStream/Plugins/DiziMom.py +110 -86
  8. KekikStream/Plugins/DiziPal.py +37 -23
  9. KekikStream/Plugins/DiziYou.py +23 -11
  10. KekikStream/Plugins/Dizilla.py +35 -30
  11. KekikStream/Plugins/FilmBip.py +83 -18
  12. KekikStream/Plugins/FilmEkseni.py +100 -58
  13. KekikStream/Plugins/FilmMakinesi.py +71 -19
  14. KekikStream/Plugins/FilmModu.py +17 -20
  15. KekikStream/Plugins/Filmatek.py +103 -98
  16. KekikStream/Plugins/{Full4kizle.py → FilmciBaba.py} +61 -80
  17. KekikStream/Plugins/FullHDFilmizlesene.py +12 -14
  18. KekikStream/Plugins/HDFilm.py +243 -0
  19. KekikStream/Plugins/HDFilmCehennemi.py +194 -125
  20. KekikStream/Plugins/JetFilmizle.py +5 -5
  21. KekikStream/Plugins/KultFilmler.py +6 -6
  22. KekikStream/Plugins/RoketDizi.py +5 -5
  23. KekikStream/Plugins/SelcukFlix.py +2 -2
  24. KekikStream/Plugins/SetFilmIzle.py +5 -5
  25. KekikStream/Plugins/SezonlukDizi.py +4 -4
  26. KekikStream/Plugins/Sinefy.py +5 -5
  27. KekikStream/Plugins/SinemaCX.py +5 -5
  28. KekikStream/Plugins/Sinezy.py +5 -5
  29. KekikStream/Plugins/SuperFilmGeldi.py +5 -5
  30. KekikStream/Plugins/UgurFilm.py +4 -4
  31. KekikStream/Plugins/YabanciDizi.py +5 -5
  32. {kekikstream-2.4.6.dist-info → kekikstream-2.4.8.dist-info}/METADATA +1 -1
  33. {kekikstream-2.4.6.dist-info → kekikstream-2.4.8.dist-info}/RECORD +37 -37
  34. KekikStream/Plugins/FullHDFilm.py +0 -179
  35. {kekikstream-2.4.6.dist-info → kekikstream-2.4.8.dist-info}/WHEEL +0 -0
  36. {kekikstream-2.4.6.dist-info → kekikstream-2.4.8.dist-info}/entry_points.txt +0 -0
  37. {kekikstream-2.4.6.dist-info → kekikstream-2.4.8.dist-info}/licenses/LICENSE +0 -0
  38. {kekikstream-2.4.6.dist-info → kekikstream-2.4.8.dist-info}/top_level.txt +0 -0
@@ -41,14 +41,14 @@ class HTMLHelper:
41
41
  val = el.text(strip=True)
42
42
  return val or None
43
43
 
44
- def select_texts(self, selector: str, element: Node | None = None) -> list[str]:
44
+ def select_texts(self, selector: str, element: Node | None = None) -> list[str] | None:
45
45
  """CSS selector ile tüm eşleşen elementlerin text içeriklerini döndür."""
46
46
  out: list[str] = []
47
47
  for el in self.select(selector, element):
48
48
  txt = el.text(strip=True)
49
49
  if txt:
50
50
  out.append(txt)
51
- return out
51
+ return out or None
52
52
 
53
53
  def select_attr(self, selector: str | None, attr: str, element: Node | None = None) -> str | None:
54
54
  """CSS selector ile element bul ve attribute değerini döndür."""
@@ -106,7 +106,13 @@ class PluginBase(ABC):
106
106
  url = f"https:{url}" if url.startswith("//") else urljoin(self.main_url, url)
107
107
  return url.replace("\\", "")
108
108
 
109
- async def extract(self, url: str, referer: str = None, prefix: str | None = None) -> ExtractResult | None:
109
+ async def extract(
110
+ self,
111
+ url: str,
112
+ referer: str = None,
113
+ prefix: str | None = None,
114
+ name_override: str | None = None
115
+ ) -> ExtractResult | list[ExtractResult] | None:
110
116
  """
111
117
  Extractor ile video URL'sini çıkarır.
112
118
 
@@ -114,6 +120,7 @@ class PluginBase(ABC):
114
120
  url: Iframe veya video URL'si
115
121
  referer: Referer header (varsayılan: plugin main_url)
116
122
  prefix: İsmin başına eklenecek opsiyonel etiket (örn: "Türkçe Dublaj")
123
+ name_override: İsmi tamamen değiştirecek opsiyonel etiket (Extractor adını ezer)
117
124
 
118
125
  Returns:
119
126
  ExtractResult: Extractor sonucu (name prefix ile birleştirilmiş) veya None
@@ -131,15 +138,19 @@ class PluginBase(ABC):
131
138
  try:
132
139
  data = await extractor.extract(url, referer=referer)
133
140
 
134
- # Liste ise her bir öğe için prefix ekle
141
+ # Liste ise her bir öğe için prefix/override ekle
135
142
  if isinstance(data, list):
136
143
  for item in data:
137
- if prefix and item.name:
144
+ if name_override:
145
+ item.name = name_override
146
+ elif prefix and item.name:
138
147
  item.name = f"{prefix} | {item.name}"
139
148
  return data
140
149
 
141
150
  # Tekil öğe ise
142
- if prefix and data.name:
151
+ if name_override:
152
+ data.name = name_override
153
+ elif prefix and data.name:
143
154
  data.name = f"{prefix} | {data.name}"
144
155
 
145
156
  return data
@@ -1,7 +1,7 @@
1
1
  # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
2
 
3
3
  from KekikStream.Core import ExtractorBase, ExtractResult, HTMLHelper
4
- import json
4
+ import json, html
5
5
 
6
6
  class Odnoklassniki(ExtractorBase):
7
7
  name = "Odnoklassniki"
@@ -19,12 +19,18 @@ class Odnoklassniki(ExtractorBase):
19
19
  resp = await self.httpx.get(url, follow_redirects=True)
20
20
  sel = HTMLHelper(resp.text)
21
21
 
22
- v_data = sel.regex_first(r'"videos":(\[.*?\])')
22
+ # Metadata içinden videos array'ini al (esnek regex)
23
+ v_data = sel.regex_first(r'videos[^:]+:(\[.*?\])')
23
24
  if not v_data:
25
+ if "Видео заблокировано" in resp.text or "copyrightsRestricted" in resp.text:
26
+ raise ValueError("Odnoklassniki: Video telif nedeniyle silinmiş/erişilemiyor.")
24
27
  raise ValueError(f"Odnoklassniki: Video verisi bulunamadı. {url}")
25
28
 
26
29
  # Kalite sıralaması (En yüksekten düşüğe)
27
30
  order = ["ULTRA", "QUAD", "FULL", "HD", "SD", "LOW", "MOBILE"]
31
+ # Escaped string'i temizle
32
+ v_data = html.unescape(v_data)
33
+ v_data = v_data.replace('\\"', '"').replace('\\/', '/')
28
34
  videos = json.loads(v_data)
29
35
 
30
36
  best_url = None
@@ -38,4 +44,10 @@ class Odnoklassniki(ExtractorBase):
38
44
  if not best_url:
39
45
  raise ValueError("Odnoklassniki: Geçerli video URL'si bulunamadı.")
40
46
 
47
+ # URL temizliği (u0026 -> & ve olası unicode kaçışları)
48
+ best_url = best_url.replace("u0026", "&").replace("\\u0026", "&")
49
+ # Eğer hala \uXXXX formatında unicode kaçışları varsa çöz
50
+ if "\\u" in best_url:
51
+ best_url = best_url.encode().decode('unicode-escape')
52
+
41
53
  return ExtractResult(name=self.name, url=self.fix_url(best_url), referer=referer)
@@ -151,8 +151,8 @@ class YTDLP(ExtractorBase):
151
151
  ydl_opts = {
152
152
  "quiet" : True,
153
153
  "no_warnings" : True,
154
- "extract_flat" : False, # Tam bilgi al
155
- "format" : "best", # En iyi kalite
154
+ "extract_flat" : False, # Tam bilgi al
155
+ "format" : "best/all", # En iyi kalite, yoksa herhangi biri
156
156
  "no_check_certificates" : True,
157
157
  "socket_timeout" : 3,
158
158
  "retries" : 1
@@ -1,6 +1,7 @@
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, SeriesInfo, Episode, ExtractResult, HTMLHelper
4
+ from contextlib import suppress
4
5
 
5
6
  class BelgeselX(PluginBase):
6
7
  name = "BelgeselX"
@@ -36,15 +37,15 @@ class BelgeselX(PluginBase):
36
37
  """Türkçe için title case dönüşümü."""
37
38
  if not text:
38
39
  return ""
39
-
40
- words = text.split()
40
+
41
+ words = text.split()
41
42
  new_words = []
42
-
43
+
43
44
  for word in words:
44
45
  # Önce Türkçe karakterleri koruyarak küçült
45
46
  # İ -> i, I -> ı
46
47
  word = word.replace("İ", "i").replace("I", "ı").lower()
47
-
48
+
48
49
  # Sonra ilk harfi Türkçe kurallarına göre büyüt
49
50
  if word:
50
51
  if word[0] == "i":
@@ -53,9 +54,9 @@ class BelgeselX(PluginBase):
53
54
  word = "I" + word[1:]
54
55
  else:
55
56
  word = word[0].upper() + word[1:]
56
-
57
+
57
58
  new_words.append(word)
58
-
59
+
59
60
  return " ".join(new_words)
60
61
 
61
62
  async def get_main_page(self, page: int, url: str, category: str) -> list[MainPageResult]:
@@ -63,21 +64,17 @@ class BelgeselX(PluginBase):
63
64
  secici = HTMLHelper(istek.text)
64
65
 
65
66
  results = []
66
- # xpath kullanamıyoruz, en üst seviye gen-movie-contain'leri alıp içlerinden bilgileri çekelim
67
67
  for container in secici.select("div.gen-movie-contain"):
68
- # Poster için img'i container'ın içinden alalım
69
68
  poster = secici.select_attr("div.gen-movie-img img", "src", container)
70
-
71
- # Title ve href için gen-movie-info
72
- title = secici.select_text("div.gen-movie-info h3 a", container)
73
- href = secici.select_attr("div.gen-movie-info h3 a", "href", container)
69
+ title = secici.select_text("div.gen-movie-info h3 a", container)
70
+ href = secici.select_attr("div.gen-movie-info h3 a", "href", container)
74
71
 
75
72
  if title and href:
76
73
  results.append(MainPageResult(
77
74
  category = category,
78
75
  title = self._to_title_case(title),
79
76
  url = self.fix_url(href),
80
- poster = self.fix_url(poster) if poster else None
77
+ poster = self.fix_url(poster)
81
78
  ))
82
79
 
83
80
  return results
@@ -117,7 +114,6 @@ class BelgeselX(PluginBase):
117
114
  poster = images[i] if i < len(images) else None
118
115
 
119
116
  if not url_val or "diziresimleri" not in url_val:
120
- # URL'den belgesel linkini oluştur
121
117
  if poster and "diziresimleri" in poster:
122
118
  file_name = poster.rsplit("/", 1)[-1]
123
119
  file_name = HTMLHelper(file_name).regex_replace(r"\.(jpe?g|png|webp)$", "")
@@ -154,6 +150,7 @@ class BelgeselX(PluginBase):
154
150
  if not rating:
155
151
  if r_match := secici.regex_first(r"%\s*(\d+)\s*Puan", item):
156
152
  rating = float(r_match) / 10
153
+ rating = rating or None
157
154
 
158
155
  episodes = []
159
156
  for i, ep in enumerate(secici.select("div.gen-movie-contain")):
@@ -166,12 +163,23 @@ class BelgeselX(PluginBase):
166
163
  final_url = self.fix_url(href)
167
164
  if item_id:
168
165
  final_url = f"{final_url}?id={item_id}"
169
-
170
- episodes.append(Episode(season=s or 1, episode=e or (i + 1), title=name, url=final_url))
166
+
167
+ episodes.append(Episode(
168
+ season = s or 1,
169
+ episode = e or (i + 1),
170
+ title = name,
171
+ url = final_url
172
+ ))
171
173
 
172
174
  return SeriesInfo(
173
- url=url, poster=self.fix_url(poster) if poster else None, title=title or "Bilinmiyor",
174
- description=description, tags=tags, year=year, rating=rating, episodes=episodes
175
+ url = url,
176
+ poster = self.fix_url(poster),
177
+ title = title,
178
+ description = description,
179
+ tags = tags,
180
+ year = year,
181
+ rating = rating,
182
+ episodes = episodes
175
183
  )
176
184
 
177
185
  async def load_links(self, url: str) -> list[ExtractResult]:
@@ -198,19 +206,18 @@ class BelgeselX(PluginBase):
198
206
 
199
207
  for i, video_url in enumerate(files):
200
208
  quality = labels[i] if i < len(labels) else "HD"
209
+ name = f"{'Google' if 'google' in video_url.lower() or 'blogspot' in video_url.lower() or quality == 'FULL' else self.name} | {'1080p' if quality == 'FULL' else quality}"
201
210
 
202
211
  # belgeselx.php redirect'ini çöz
203
212
  if "belgeselx.php" in video_url or "belgeselx2.php" in video_url:
204
- try:
213
+ with suppress(Exception):
205
214
  # HEAD isteği ile lokasyonu alalım
206
- resp = await self.httpx.head(video_url, headers={"Referer": main_url}, follow_redirects=True)
215
+ resp = await self.httpx.head(video_url, headers={"Referer": main_url}, follow_redirects=True)
207
216
  video_url = str(resp.url)
208
- except:
209
- pass
210
217
 
211
218
  links.append(ExtractResult(
212
219
  url = video_url,
213
- name = f"{'Google' if 'google' in video_url.lower() or 'blogspot' in video_url.lower() or quality == 'FULL' else self.name} | {'1080p' if quality == 'FULL' else quality}",
220
+ name = name,
214
221
  referer = main_url
215
222
  ))
216
223
 
@@ -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, SeriesInfo, Episode, ExtractResult, HTMLHelper
4
- from Kekik.Sifreleme import CryptoJS
3
+ from KekikStream.Core import PluginBase, MainPageResult, SearchResult, SeriesInfo, Episode, ExtractResult, HTMLHelper
4
+ from Kekik.Sifreleme import CryptoJS
5
5
  import urllib.parse, base64, contextlib, asyncio, time
6
6
 
7
7
  class DiziBox(PluginBase):
@@ -52,8 +52,8 @@ class DiziBox(PluginBase):
52
52
 
53
53
  results = []
54
54
  for veri in secici.select("article.detailed-article"):
55
- title = secici.select_text("h3 a", veri)
56
- href = secici.select_attr("h3 a", "href", veri)
55
+ title = secici.select_text("h3 a", veri)
56
+ href = secici.select_attr("h3 a", "href", veri)
57
57
  poster = secici.select_attr("img", "src", veri)
58
58
 
59
59
  if title and href:
@@ -61,7 +61,7 @@ class DiziBox(PluginBase):
61
61
  category = category,
62
62
  title = title,
63
63
  url = self.fix_url(href),
64
- poster = self.fix_url(poster) if poster else None,
64
+ poster = self.fix_url(poster),
65
65
  ))
66
66
 
67
67
  return results
@@ -84,7 +84,7 @@ class DiziBox(PluginBase):
84
84
  results.append(SearchResult(
85
85
  title = title,
86
86
  url = self.fix_url(href),
87
- poster = self.fix_url(poster) if poster else None,
87
+ poster = self.fix_url(poster),
88
88
  ))
89
89
 
90
90
  return results
@@ -114,12 +114,12 @@ class DiziBox(PluginBase):
114
114
 
115
115
  return SeriesInfo(
116
116
  url = url,
117
- poster = self.fix_url(poster) if poster else None,
117
+ poster = self.fix_url(poster),
118
118
  title = title,
119
119
  description = description,
120
120
  tags = tags,
121
121
  rating = rating,
122
- year = str(year) if year else None,
122
+ year = year,
123
123
  episodes = episodes,
124
124
  actors = actors,
125
125
  )
@@ -182,13 +182,16 @@ class DiziBox(PluginBase):
182
182
  istek = await self.httpx.get(url)
183
183
  secici = HTMLHelper(istek.text)
184
184
 
185
- results = []
185
+ # Aktif kaynağın adını bul (DBX Pro vs.)
186
+ current_source_name = secici.select_text("div.video-toolbar option[selected]") or self.name
187
+
188
+ results = []
186
189
  main_iframe = secici.select_attr("div#video-area iframe", "src")
187
190
 
188
191
  if main_iframe:
189
192
  if decoded := await self._iframe_decode(self.name, main_iframe, url):
190
193
  for iframe in decoded:
191
- data = await self.extract(iframe)
194
+ data = await self.extract(iframe, name_override=current_source_name)
192
195
  if data:
193
196
  results.append(data)
194
197
 
@@ -209,7 +212,7 @@ class DiziBox(PluginBase):
209
212
  if alt_iframe:
210
213
  if decoded := await self._iframe_decode(alt_name, alt_iframe, url):
211
214
  for iframe in decoded:
212
- data = await self.extract(iframe, prefix=alt_name)
215
+ data = await self.extract(iframe, name_override=alt_name)
213
216
  if data:
214
217
  results.append(data)
215
218
 
@@ -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, SeriesInfo, Episode, ExtractResult, HTMLHelper
4
- from json import dumps, loads
5
- import re
3
+ from KekikStream.Core import PluginBase, MainPageResult, SearchResult, SeriesInfo, Episode, ExtractResult, HTMLHelper
6
4
 
7
5
  class DiziMom(PluginBase):
8
6
  name = "DiziMom"
@@ -12,134 +10,160 @@ class DiziMom(PluginBase):
12
10
  description = "Binlerce yerli yabancı dizi arşivi, tüm sezonlar, kesintisiz bölümler. Sadece dizi izle, Dizimom heryerde seninle!"
13
11
 
14
12
  main_page = {
15
- f"{main_url}/tum-bolumler/page" : "Son Bölümler",
16
- f"{main_url}/yerli-dizi-izle/page" : "Yerli Diziler",
17
- f"{main_url}/yabanci-dizi-izle/page" : "Yabancı Diziler",
18
- f"{main_url}/tv-programlari-izle/page" : "TV Programları",
13
+ f"{main_url}/tum-bolumler/page" : "Son Bölümler",
14
+ f"{main_url}/yerli-dizi-izle/page" : "Yerli Diziler",
15
+ f"{main_url}/yabanci-dizi-izle/page" : "Yabancı Diziler",
16
+ f"{main_url}/tv-programlari-izle/page" : "TV Programları",
17
+ f"{main_url}/netflix-dizileri-izle/page" : "Netflix Dizileri",
18
+ f"{main_url}/turkce-dublaj-diziler-hd/page" : "Dublajlı Diziler",
19
+ f"{main_url}/yerli-dizi-izle/page" : "Yerli Diziler",
20
+ f"{main_url}/anime-izle/page" : "Animeler",
21
+ f"{main_url}/yabanci-dizi-izle/page" : "Yabancı Diziler",
22
+ f"{main_url}/kore-dizileri-izle-hd/page" : "Kore Dizileri",
23
+ f"{main_url}/full-hd-hint-dizileri-izle/page" : "Hint Dizileri",
24
+ f"{main_url}/pakistan-dizileri-izle/page" : "Pakistan Dizileri",
25
+ f"{main_url}/tv-programlari-izle/page" : "Tv Programları",
19
26
  }
20
27
 
21
28
  async def get_main_page(self, page: int, url: str, category: str) -> list[MainPageResult]:
22
- full_url = f"{url}/{page}/"
23
- istek = await self.httpx.get(full_url)
24
- helper = HTMLHelper(istek.text)
29
+ istek = await self.httpx.get(f"{url}/{page}/")
30
+ secici = HTMLHelper(istek.text)
25
31
 
26
32
  results = []
27
33
  # Eğer "tum-bolumler" ise Episode kutularını, değilse Dizi kutularını tara
28
34
  if "/tum-bolumler/" in url:
29
- for item in helper.select("div.episode-box"):
30
- title = helper.select_text("div.episode-name a", item)
31
- href = helper.select_attr("div.episode-name a", "href", item)
32
- img = helper.select_poster("div.cat-img img", item)
35
+ for item in secici.select("div.episode-box"):
36
+ title = secici.select_text("div.episode-name a", item)
37
+ href = secici.select_attr("div.episode-name a", "href", item)
38
+ img = secici.select_poster("div.cat-img img", item)
33
39
  if title and href:
34
- results.append(MainPageResult(category=category, title=title.split(" izle")[0], url=self.fix_url(href), poster=self.fix_url(img)))
40
+ results.append(MainPageResult(
41
+ category = category,
42
+ title = title.split(" izle")[0],
43
+ url = self.fix_url(href),
44
+ poster = self.fix_url(img)
45
+ ))
35
46
  else:
36
- for item in helper.select("div.single-item"):
37
- title = helper.select_text("div.categorytitle a", item)
38
- href = helper.select_attr("div.categorytitle a", "href", item)
39
- img = helper.select_poster("div.cat-img img", item)
47
+ for item in secici.select("div.single-item"):
48
+ title = secici.select_text("div.categorytitle a", item)
49
+ href = secici.select_attr("div.categorytitle a", "href", item)
50
+ img = secici.select_poster("div.cat-img img", item)
40
51
  if title and href:
41
- results.append(MainPageResult(category=category, title=title.split(" izle")[0], url=self.fix_url(href), poster=self.fix_url(img)))
52
+ results.append(MainPageResult(
53
+ category = category,
54
+ title = title.split(" izle")[0],
55
+ url = self.fix_url(href),
56
+ poster = self.fix_url(img)
57
+ ))
42
58
 
43
59
  return results
44
60
 
45
61
  async def search(self, query: str) -> list[SearchResult]:
46
- url = f"{self.main_url}/?s={query}"
47
- istek = await self.httpx.get(url)
48
- helper = HTMLHelper(istek.text)
49
- items = helper.select("div.single-item")
50
-
62
+ istek = await self.httpx.get(f"{self.main_url}/?s={query}")
63
+ secici = HTMLHelper(istek.text)
64
+ items = secici.select("div.single-item")
65
+
51
66
  return [
52
67
  SearchResult(
53
- title = helper.select_text("div.categorytitle a", item).split(" izle")[0],
54
- url = self.fix_url(helper.select_attr("div.categorytitle a", "href", item)),
55
- poster = self.fix_url(helper.select_attr("div.cat-img img", "src", item))
68
+ title = secici.select_text("div.categorytitle a", item).split(" izle")[0],
69
+ url = self.fix_url(secici.select_attr("div.categorytitle a", "href", item)),
70
+ poster = self.fix_url(secici.select_attr("div.cat-img img", "src", item))
56
71
  )
57
72
  for item in items
58
73
  ]
59
74
 
60
75
  async def load_item(self, url: str) -> SeriesInfo:
61
76
  istek = await self.httpx.get(url)
62
- helper = HTMLHelper(istek.text)
77
+ secici = HTMLHelper(istek.text)
63
78
 
64
- title = self.clean_title(helper.select_text("div.title h1"))
65
- poster = helper.select_poster("div.category_image img")
66
- description = helper.select_direct_text("div.category_desc")
67
- tags = helper.select_texts("div.genres a")
68
- rating = helper.regex_first(r"(?s)IMDB\s*:\s*(?:</span>)?\s*([\d\.]+)", helper.html)
69
- year = helper.extract_year("div.category_text")
70
- actors = helper.meta_list("Oyuncular", container_selector="div#icerikcat2")
79
+ title = self.clean_title(secici.select_text("div.title h1"))
80
+ poster = secici.select_poster("div.category_image img")
81
+ description = secici.select_direct_text("div.category_desc")
82
+ tags = secici.select_texts("div.genres a")
83
+ rating = secici.regex_first(r"(?s)IMDB\s*:\s*(?:</span>)?\s*([\d\.]+)", secici.html)
84
+ year = secici.extract_year("div.category_text")
85
+ actors = secici.meta_list("Oyuncular", container_selector="div#icerikcat2")
71
86
 
72
87
  episodes = []
73
- for item in helper.select("div.bolumust"):
74
- name = helper.select_text("div.baslik", item)
75
- href = helper.select_attr("a", "href", item)
88
+ for item in secici.select("div.bolumust"):
89
+ name = secici.select_text("div.baslik", item)
90
+ href = secici.select_attr("a", "href", item)
76
91
  if name and href:
77
- s, e = helper.extract_season_episode(name)
92
+ s, e = secici.extract_season_episode(name)
78
93
  episodes.append(Episode(
79
94
  season = s or 1,
80
95
  episode = e or 1,
81
- title = self.clean_title(name.replace(title or "", "").strip()),
96
+ title = self.clean_title(name.replace(title, "").strip()),
82
97
  url = self.fix_url(href)
83
98
  ))
84
99
 
85
100
  return SeriesInfo(
86
101
  url = url,
87
- poster = self.fix_url(poster) if poster else None,
88
- title = title or "Bilinmiyor",
102
+ poster = self.fix_url(poster),
103
+ title = title,
89
104
  description = description,
90
105
  tags = tags,
91
106
  rating = rating,
92
- year = str(year) if year else None,
107
+ year = year,
93
108
  actors = actors,
94
109
  episodes = episodes
95
110
  )
96
111
 
97
112
  async def load_links(self, url: str) -> list[ExtractResult]:
98
- # Login simulation headers
99
- headers = {
100
- "User-Agent": "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36",
101
- "sec-ch-ua": 'Not/A)Brand";v="8", "Chromium";v="137", "Google Chrome";v="137"',
102
- "sec-ch-ua-mobile": "?1",
103
- "sec-ch-ua-platform": "Android"
104
- }
105
-
106
- # Simulate login (as seen in Kotlin)
107
- login_url = f"{self.main_url}/wp-login.php"
108
- login_data = {
109
- "log": "keyiflerolsun",
110
- "pwd": "12345",
111
- "rememberme": "forever",
112
- "redirect_to": self.main_url
113
- }
114
-
115
- await self.httpx.post(login_url, headers=headers, data=login_data)
116
-
117
- istek = await self.httpx.get(url, headers=headers)
118
- helper = HTMLHelper(istek.text)
119
-
120
- iframes = []
121
-
122
- main_iframe = helper.select_attr("iframe[src]", "src")
113
+ await self.httpx.post(
114
+ url = f"{self.main_url}/wp-login.php",
115
+ headers = {
116
+ "User-Agent" : "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36",
117
+ "sec-ch-ua" : 'Not/A)Brand";v="8", "Chromium";v="137", "Google Chrome";v="137"',
118
+ "sec-ch-ua-mobile" : "?1",
119
+ "sec-ch-ua-platform" : "Android"
120
+ },
121
+ data = {
122
+ "log" : "keyiflerolsun",
123
+ "pwd" : "12345",
124
+ "rememberme" : "forever",
125
+ "redirect_to" : self.main_url
126
+ }
127
+ )
128
+
129
+ istek = await self.httpx.get(url)
130
+ secici = HTMLHelper(istek.text)
131
+
132
+ iframe_data = []
133
+
134
+ # Aktif kaynağın (main iframe) adını bul
135
+ current_name = secici.select_text("div.sources span.current_dil") or ""
136
+ main_iframe = secici.select_attr("iframe[src]", "src")
137
+
138
+ # Bazen iframe doğrudan video p içinde olabilir
139
+ if not main_iframe:
140
+ main_iframe = secici.select_attr("div.video p iframe", "src")
141
+
123
142
  if main_iframe:
124
- iframes.append(main_iframe)
125
-
126
- sources = helper.select("div.sources a")
143
+ iframe_data.append((main_iframe, current_name))
144
+
145
+ # Diğer kaynakları (Partlar) gez
146
+ sources = secici.select("div.sources a.post-page-numbers")
127
147
  for source in sources:
128
- href = source.attrs.get("href")
148
+ href = secici.select_attr(None, "href", source)
149
+ name = secici.select_text("span.dil", source)
129
150
  if href:
130
- sub_istek = await self.httpx.get(href, headers=headers)
151
+ # Part sayfasına git
152
+ sub_istek = await self.httpx.get(href)
131
153
  sub_helper = HTMLHelper(sub_istek.text)
132
- sub_iframe = sub_helper.select_attr("div.video p iframe", "src")
154
+ sub_iframe = sub_helper.select_attr("div.video p iframe", "src") or sub_helper.select_attr("iframe[src]", "src")
155
+
133
156
  if sub_iframe:
134
- iframes.append(sub_iframe)
135
-
157
+ iframe_data.append((sub_iframe, name or f"{len(iframe_data)+1}.Kısım"))
158
+
136
159
  results = []
137
- for iframe_url in iframes:
138
- # Check for known extractors
139
- if iframe_url.startswith("//"):
140
- iframe_url = f"https:{iframe_url}"
141
-
142
- extract_result = await self.extract(iframe_url)
160
+ for iframe_url, source_name in iframe_data:
161
+ # URL düzeltme
162
+ iframe_url = self.fix_url(iframe_url)
163
+
164
+ # Prefix olarak kaynak adını kullan (1.Kısım | HDMomPlayer)
165
+ extract_result = await self.extract(iframe_url, prefix=source_name)
166
+
143
167
  if extract_result:
144
168
  if isinstance(extract_result, list):
145
169
  results.extend(extract_result)
@@ -147,9 +171,9 @@ class DiziMom(PluginBase):
147
171
  results.append(extract_result)
148
172
  else:
149
173
  results.append(ExtractResult(
150
- url = iframe_url,
151
- name = f"{self.name} | External",
174
+ url = iframe_url,
175
+ name = f"{source_name} | External",
152
176
  referer = self.main_url
153
177
  ))
154
-
178
+
155
179
  return results