KekikStream 2.4.6__py3-none-any.whl → 2.4.7__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


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

Files changed (37) 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 +27 -19
  6. KekikStream/Plugins/DiziBox.py +11 -8
  7. KekikStream/Plugins/DiziMom.py +71 -53
  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 +90 -18
  12. KekikStream/Plugins/FilmEkseni.py +78 -40
  13. KekikStream/Plugins/FilmMakinesi.py +29 -14
  14. KekikStream/Plugins/FilmModu.py +17 -19
  15. KekikStream/Plugins/Filmatek.py +103 -91
  16. KekikStream/Plugins/Full4kizle.py +6 -6
  17. KekikStream/Plugins/FullHDFilm.py +6 -6
  18. KekikStream/Plugins/FullHDFilmizlesene.py +6 -7
  19. KekikStream/Plugins/HDFilmCehennemi.py +3 -3
  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.7.dist-info}/METADATA +1 -1
  33. {kekikstream-2.4.6.dist-info → kekikstream-2.4.7.dist-info}/RECORD +37 -37
  34. {kekikstream-2.4.6.dist-info → kekikstream-2.4.7.dist-info}/WHEEL +0 -0
  35. {kekikstream-2.4.6.dist-info → kekikstream-2.4.7.dist-info}/entry_points.txt +0 -0
  36. {kekikstream-2.4.6.dist-info → kekikstream-2.4.7.dist-info}/licenses/LICENSE +0 -0
  37. {kekikstream-2.4.6.dist-info → kekikstream-2.4.7.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
@@ -36,15 +36,15 @@ class BelgeselX(PluginBase):
36
36
  """Türkçe için title case dönüşümü."""
37
37
  if not text:
38
38
  return ""
39
-
40
- words = text.split()
39
+
40
+ words = text.split()
41
41
  new_words = []
42
-
42
+
43
43
  for word in words:
44
44
  # Önce Türkçe karakterleri koruyarak küçült
45
45
  # İ -> i, I -> ı
46
46
  word = word.replace("İ", "i").replace("I", "ı").lower()
47
-
47
+
48
48
  # Sonra ilk harfi Türkçe kurallarına göre büyüt
49
49
  if word:
50
50
  if word[0] == "i":
@@ -53,9 +53,9 @@ class BelgeselX(PluginBase):
53
53
  word = "I" + word[1:]
54
54
  else:
55
55
  word = word[0].upper() + word[1:]
56
-
56
+
57
57
  new_words.append(word)
58
-
58
+
59
59
  return " ".join(new_words)
60
60
 
61
61
  async def get_main_page(self, page: int, url: str, category: str) -> list[MainPageResult]:
@@ -63,21 +63,17 @@ class BelgeselX(PluginBase):
63
63
  secici = HTMLHelper(istek.text)
64
64
 
65
65
  results = []
66
- # xpath kullanamıyoruz, en üst seviye gen-movie-contain'leri alıp içlerinden bilgileri çekelim
67
66
  for container in secici.select("div.gen-movie-contain"):
68
- # Poster için img'i container'ın içinden alalım
69
67
  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)
68
+ title = secici.select_text("div.gen-movie-info h3 a", container)
69
+ href = secici.select_attr("div.gen-movie-info h3 a", "href", container)
74
70
 
75
71
  if title and href:
76
72
  results.append(MainPageResult(
77
73
  category = category,
78
74
  title = self._to_title_case(title),
79
75
  url = self.fix_url(href),
80
- poster = self.fix_url(poster) if poster else None
76
+ poster = self.fix_url(poster)
81
77
  ))
82
78
 
83
79
  return results
@@ -117,7 +113,6 @@ class BelgeselX(PluginBase):
117
113
  poster = images[i] if i < len(images) else None
118
114
 
119
115
  if not url_val or "diziresimleri" not in url_val:
120
- # URL'den belgesel linkini oluştur
121
116
  if poster and "diziresimleri" in poster:
122
117
  file_name = poster.rsplit("/", 1)[-1]
123
118
  file_name = HTMLHelper(file_name).regex_replace(r"\.(jpe?g|png|webp)$", "")
@@ -154,6 +149,7 @@ class BelgeselX(PluginBase):
154
149
  if not rating:
155
150
  if r_match := secici.regex_first(r"%\s*(\d+)\s*Puan", item):
156
151
  rating = float(r_match) / 10
152
+ rating = rating or None
157
153
 
158
154
  episodes = []
159
155
  for i, ep in enumerate(secici.select("div.gen-movie-contain")):
@@ -166,12 +162,23 @@ class BelgeselX(PluginBase):
166
162
  final_url = self.fix_url(href)
167
163
  if item_id:
168
164
  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))
165
+
166
+ episodes.append(Episode(
167
+ season = s or 1,
168
+ episode = e or (i + 1),
169
+ title = name,
170
+ url = final_url
171
+ ))
171
172
 
172
173
  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
174
+ url = url,
175
+ poster = self.fix_url(poster),
176
+ title = title,
177
+ description = description,
178
+ tags = tags,
179
+ year = year,
180
+ rating = rating,
181
+ episodes = episodes
175
182
  )
176
183
 
177
184
  async def load_links(self, url: str) -> list[ExtractResult]:
@@ -198,6 +205,7 @@ class BelgeselX(PluginBase):
198
205
 
199
206
  for i, video_url in enumerate(files):
200
207
  quality = labels[i] if i < len(labels) else "HD"
208
+ 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
209
 
202
210
  # belgeselx.php redirect'ini çöz
203
211
  if "belgeselx.php" in video_url or "belgeselx2.php" in video_url:
@@ -210,7 +218,7 @@ class BelgeselX(PluginBase):
210
218
 
211
219
  links.append(ExtractResult(
212
220
  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}",
221
+ name = name,
214
222
  referer = main_url
215
223
  ))
216
224
 
@@ -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):
@@ -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
+ # 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
+
185
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"
@@ -31,23 +29,33 @@ class DiziMom(PluginBase):
31
29
  href = helper.select_attr("div.episode-name a", "href", item)
32
30
  img = helper.select_poster("div.cat-img img", item)
33
31
  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)))
32
+ results.append(MainPageResult(
33
+ category = category,
34
+ title = title.split(" izle")[0],
35
+ url = self.fix_url(href),
36
+ poster = self.fix_url(img)
37
+ ))
35
38
  else:
36
39
  for item in helper.select("div.single-item"):
37
40
  title = helper.select_text("div.categorytitle a", item)
38
41
  href = helper.select_attr("div.categorytitle a", "href", item)
39
42
  img = helper.select_poster("div.cat-img img", item)
40
43
  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)))
44
+ results.append(MainPageResult(
45
+ category = category,
46
+ title = title.split(" izle")[0],
47
+ url = self.fix_url(href),
48
+ poster = self.fix_url(img)
49
+ ))
42
50
 
43
51
  return results
44
52
 
45
53
  async def search(self, query: str) -> list[SearchResult]:
46
- url = f"{self.main_url}/?s={query}"
47
- istek = await self.httpx.get(url)
54
+ url = f"{self.main_url}/?s={query}"
55
+ istek = await self.httpx.get(url)
48
56
  helper = HTMLHelper(istek.text)
49
- items = helper.select("div.single-item")
50
-
57
+ items = helper.select("div.single-item")
58
+
51
59
  return [
52
60
  SearchResult(
53
61
  title = helper.select_text("div.categorytitle a", item).split(" izle")[0],
@@ -78,68 +86,78 @@ class DiziMom(PluginBase):
78
86
  episodes.append(Episode(
79
87
  season = s or 1,
80
88
  episode = e or 1,
81
- title = self.clean_title(name.replace(title or "", "").strip()),
89
+ title = self.clean_title(name.replace(title, "").strip()),
82
90
  url = self.fix_url(href)
83
91
  ))
84
92
 
85
93
  return SeriesInfo(
86
94
  url = url,
87
- poster = self.fix_url(poster) if poster else None,
88
- title = title or "Bilinmiyor",
95
+ poster = self.fix_url(poster),
96
+ title = title,
89
97
  description = description,
90
98
  tags = tags,
91
99
  rating = rating,
92
- year = str(year) if year else None,
100
+ year = year,
93
101
  actors = actors,
94
102
  episodes = episodes
95
103
  )
96
104
 
97
105
  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)
106
+ await self.httpx.post(
107
+ url = f"{self.main_url}/wp-login.php",
108
+ headers = {
109
+ "User-Agent" : "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36",
110
+ "sec-ch-ua" : 'Not/A)Brand";v="8", "Chromium";v="137", "Google Chrome";v="137"',
111
+ "sec-ch-ua-mobile" : "?1",
112
+ "sec-ch-ua-platform" : "Android"
113
+ },
114
+ data = {
115
+ "log" : "keyiflerolsun",
116
+ "pwd" : "12345",
117
+ "rememberme" : "forever",
118
+ "redirect_to" : self.main_url
119
+ }
120
+ )
121
+
122
+ istek = await self.httpx.get(url)
118
123
  helper = HTMLHelper(istek.text)
119
-
120
- iframes = []
121
-
124
+
125
+ iframe_data = []
126
+
127
+ # Aktif kaynağın (main iframe) adını bul
128
+ current_name = helper.select_text("div.sources span.current_dil") or ""
122
129
  main_iframe = helper.select_attr("iframe[src]", "src")
130
+
131
+ # Bazen iframe doğrudan video p içinde olabilir
132
+ if not main_iframe:
133
+ main_iframe = helper.select_attr("div.video p iframe", "src")
134
+
123
135
  if main_iframe:
124
- iframes.append(main_iframe)
125
-
126
- sources = helper.select("div.sources a")
136
+ iframe_data.append((main_iframe, current_name))
137
+
138
+ # Diğer kaynakları (Partlar) gez
139
+ sources = helper.select("div.sources a.post-page-numbers")
127
140
  for source in sources:
128
- href = source.attrs.get("href")
141
+ href = helper.select_attr(None, "href", source)
142
+ name = helper.select_text("span.dil", source)
143
+
129
144
  if href:
130
- sub_istek = await self.httpx.get(href, headers=headers)
145
+ # Part sayfasına git
146
+ sub_istek = await self.httpx.get(href)
131
147
  sub_helper = HTMLHelper(sub_istek.text)
132
- sub_iframe = sub_helper.select_attr("div.video p iframe", "src")
148
+ sub_iframe = sub_helper.select_attr("div.video p iframe", "src") or sub_helper.select_attr("iframe[src]", "src")
149
+
133
150
  if sub_iframe:
134
- iframes.append(sub_iframe)
135
-
151
+ iframe_data.append((sub_iframe, name or f"{len(iframe_data)+1}.Kısım"))
152
+
136
153
  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)
154
+ for iframe_url, source_name in iframe_data:
155
+ # URL düzeltme
156
+ iframe_url = self.fix_url(iframe_url)
157
+
158
+ # Prefix olarak kaynak adını kullan (1.Kısım | HDMomPlayer)
159
+ extract_result = await self.extract(iframe_url, prefix=source_name)
160
+
143
161
  if extract_result:
144
162
  if isinstance(extract_result, list):
145
163
  results.extend(extract_result)
@@ -147,9 +165,9 @@ class DiziMom(PluginBase):
147
165
  results.append(extract_result)
148
166
  else:
149
167
  results.append(ExtractResult(
150
- url = iframe_url,
151
- name = f"{self.name} | External",
168
+ url = iframe_url,
169
+ name = f"{source_name} | External",
152
170
  referer = self.main_url
153
171
  ))
154
-
172
+
155
173
  return results
@@ -1,11 +1,11 @@
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, Subtitle, ExtractResult, HTMLHelper
3
+ from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo, SeriesInfo, Episode, Subtitle, ExtractResult, HTMLHelper
4
4
 
5
5
  class DiziPal(PluginBase):
6
6
  name = "DiziPal"
7
7
  language = "tr"
8
- main_url = "https://dizipal.cc"
8
+ main_url = "https://dizipal.uk"
9
9
  favicon = f"https://www.google.com/s2/favicons?domain={main_url}&sz=64"
10
10
  description = "dizipal güncel, dizipal yeni ve gerçek adresi. dizipal en yeni dizi ve filmleri güvenli ve hızlı şekilde sunar."
11
11
 
@@ -46,7 +46,7 @@ class DiziPal(PluginBase):
46
46
  category = category,
47
47
  title = title,
48
48
  url = self.fix_url(href),
49
- poster = self.fix_url(poster) if poster else None,
49
+ poster = self.fix_url(poster),
50
50
  ))
51
51
 
52
52
  return results
@@ -65,7 +65,7 @@ class DiziPal(PluginBase):
65
65
  results.append(SearchResult(
66
66
  title = title,
67
67
  url = self.fix_url(href),
68
- poster = self.fix_url(poster) if poster else None,
68
+ poster = self.fix_url(poster),
69
69
  ))
70
70
 
71
71
  return results
@@ -82,8 +82,8 @@ class DiziPal(PluginBase):
82
82
  rating = secici.meta_value("IMDB Puanı")
83
83
  duration_raw = secici.meta_value("Süre")
84
84
  if duration_raw:
85
- parts = duration_raw.split()
86
- saat = 0
85
+ parts = duration_raw.split()
86
+ saat = 0
87
87
  dakika = 0
88
88
 
89
89
  for p in parts:
@@ -95,7 +95,7 @@ class DiziPal(PluginBase):
95
95
  duration = saat * 60 + dakika
96
96
  else:
97
97
  duration = None
98
-
98
+
99
99
  tags = secici.meta_list("Tür")
100
100
  actors = secici.meta_list("Oyuncular")
101
101
  if not actors:
@@ -104,36 +104,50 @@ class DiziPal(PluginBase):
104
104
  if "/dizi/" in url:
105
105
  episodes = []
106
106
  for ep in secici.select("div.episode-item"):
107
- name = secici.select_text("h4 a", ep)
108
- href = secici.select_attr("a", "href", ep)
107
+ name = secici.select_text("h4 a", ep)
108
+ href = secici.select_attr("a", "href", ep)
109
109
  link_title = secici.select_attr("a", "title", ep)
110
-
110
+
111
111
  h4_texts = secici.select_texts("h4", ep)
112
- text = h4_texts[1] if len(h4_texts) > 1 else (h4_texts[0] if h4_texts else "")
112
+ text = h4_texts[1] if len(h4_texts) > 1 else (h4_texts[0] if h4_texts else "")
113
113
 
114
114
  full_text = f"{text} {link_title}" if link_title else text
115
115
 
116
116
  if name and href:
117
117
  s, e = secici.extract_season_episode(full_text or "")
118
- episodes.append(Episode(season=s, episode=e, title=name, url=self.fix_url(href)))
118
+ episodes.append(Episode(
119
+ season = s,
120
+ episode = e,
121
+ title = name,
122
+ url = self.fix_url(href)
123
+ ))
119
124
 
120
125
  return SeriesInfo(
121
- url=url, poster=poster.replace("https://test4test.online", self.main_url), title=title, description=description, tags=tags,
122
- rating=rating, year=year, duration=duration, episodes=episodes or None, actors=actors
126
+ url = url,
127
+ poster = poster.replace("https://test4test.online", self.main_url),
128
+ title = title,
129
+ description = description,
130
+ tags = tags,
131
+ rating = rating,
132
+ year = year,
133
+ duration = duration,
134
+ episodes = episodes or None,
135
+ actors = actors
123
136
  )
124
-
137
+
125
138
  return MovieInfo(
126
- url=url, poster=poster.replace("https://test4test.online", self.main_url), title=title, description=description, tags=tags,
127
- rating=rating, year=year, duration=duration, actors=actors
139
+ url = url,
140
+ poster = poster.replace("https://test4test.online", self.main_url),
141
+ title = title,
142
+ description = description,
143
+ tags = tags,
144
+ rating = rating,
145
+ year = year,
146
+ duration = duration,
147
+ actors = actors
128
148
  )
129
149
 
130
150
  async def load_links(self, url: str) -> list[ExtractResult]:
131
- # Reset headers to get HTML response
132
- self.httpx.headers.update({
133
- "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
134
- })
135
- self.httpx.headers.pop("X-Requested-With", None)
136
-
137
151
  istek = await self.httpx.get(url)
138
152
  secici = HTMLHelper(istek.text)
139
153