KekikStream 2.4.2__py3-none-any.whl → 2.4.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 (72) hide show
  1. KekikStream/Core/Extractor/ExtractorBase.py +3 -2
  2. KekikStream/Core/HTMLHelper.py +134 -40
  3. KekikStream/Core/Plugin/PluginBase.py +3 -2
  4. KekikStream/Extractors/CloseLoad.py +30 -54
  5. KekikStream/Extractors/ContentX.py +27 -72
  6. KekikStream/Extractors/DonilasPlay.py +33 -77
  7. KekikStream/Extractors/DzenRu.py +10 -24
  8. KekikStream/Extractors/ExPlay.py +20 -38
  9. KekikStream/Extractors/Filemoon.py +19 -45
  10. KekikStream/Extractors/HDMomPlayer.py +24 -56
  11. KekikStream/Extractors/HDPlayerSystem.py +13 -31
  12. KekikStream/Extractors/HotStream.py +14 -32
  13. KekikStream/Extractors/JFVid.py +3 -24
  14. KekikStream/Extractors/JetTv.py +21 -34
  15. KekikStream/Extractors/MailRu.py +11 -29
  16. KekikStream/Extractors/MixPlayHD.py +15 -28
  17. KekikStream/Extractors/MixTiger.py +17 -40
  18. KekikStream/Extractors/MolyStream.py +17 -21
  19. KekikStream/Extractors/Odnoklassniki.py +28 -104
  20. KekikStream/Extractors/PeaceMakerst.py +18 -45
  21. KekikStream/Extractors/PixelDrain.py +8 -16
  22. KekikStream/Extractors/PlayerFilmIzle.py +22 -41
  23. KekikStream/Extractors/RapidVid.py +21 -35
  24. KekikStream/Extractors/SetPlay.py +18 -43
  25. KekikStream/Extractors/SibNet.py +7 -17
  26. KekikStream/Extractors/Sobreatsesuyp.py +23 -45
  27. KekikStream/Extractors/TRsTX.py +23 -53
  28. KekikStream/Extractors/TurboImgz.py +7 -14
  29. KekikStream/Extractors/VCTPlay.py +10 -28
  30. KekikStream/Extractors/VidHide.py +10 -31
  31. KekikStream/Extractors/VidMoly.py +65 -99
  32. KekikStream/Extractors/VidMoxy.py +16 -27
  33. KekikStream/Extractors/VidPapi.py +24 -54
  34. KekikStream/Extractors/VideoSeyred.py +19 -40
  35. KekikStream/Extractors/Videostr.py +42 -99
  36. KekikStream/Extractors/Vidoza.py +8 -15
  37. KekikStream/Extractors/YildizKisaFilm.py +13 -31
  38. KekikStream/Plugins/BelgeselX.py +63 -69
  39. KekikStream/Plugins/DiziBox.py +16 -36
  40. KekikStream/Plugins/DiziMom.py +37 -129
  41. KekikStream/Plugins/DiziPal.py +71 -164
  42. KekikStream/Plugins/DiziYou.py +44 -152
  43. KekikStream/Plugins/Dizilla.py +18 -44
  44. KekikStream/Plugins/FilmBip.py +10 -24
  45. KekikStream/Plugins/FilmEkseni.py +12 -32
  46. KekikStream/Plugins/FilmMakinesi.py +24 -77
  47. KekikStream/Plugins/FilmModu.py +11 -18
  48. KekikStream/Plugins/Filmatek.py +13 -39
  49. KekikStream/Plugins/Full4kizle.py +33 -133
  50. KekikStream/Plugins/FullHDFilm.py +23 -93
  51. KekikStream/Plugins/FullHDFilmizlesene.py +10 -29
  52. KekikStream/Plugins/HDFilmCehennemi.py +27 -66
  53. KekikStream/Plugins/JetFilmizle.py +19 -20
  54. KekikStream/Plugins/KultFilmler.py +16 -50
  55. KekikStream/Plugins/RecTV.py +47 -85
  56. KekikStream/Plugins/SelcukFlix.py +29 -47
  57. KekikStream/Plugins/SetFilmIzle.py +28 -84
  58. KekikStream/Plugins/SezonlukDizi.py +27 -59
  59. KekikStream/Plugins/Sinefy.py +37 -100
  60. KekikStream/Plugins/SinemaCX.py +12 -18
  61. KekikStream/Plugins/Sinezy.py +11 -12
  62. KekikStream/Plugins/SuperFilmGeldi.py +8 -13
  63. KekikStream/Plugins/UgurFilm.py +14 -14
  64. KekikStream/Plugins/Watch32.py +42 -74
  65. KekikStream/Plugins/YabanciDizi.py +33 -87
  66. {kekikstream-2.4.2.dist-info → kekikstream-2.4.4.dist-info}/METADATA +1 -1
  67. kekikstream-2.4.4.dist-info/RECORD +93 -0
  68. kekikstream-2.4.2.dist-info/RECORD +0 -93
  69. {kekikstream-2.4.2.dist-info → kekikstream-2.4.4.dist-info}/WHEEL +0 -0
  70. {kekikstream-2.4.2.dist-info → kekikstream-2.4.4.dist-info}/entry_points.txt +0 -0
  71. {kekikstream-2.4.2.dist-info → kekikstream-2.4.4.dist-info}/licenses/LICENSE +0 -0
  72. {kekikstream-2.4.2.dist-info → kekikstream-2.4.4.dist-info}/top_level.txt +0 -0
@@ -93,44 +93,24 @@ class DiziBox(PluginBase):
93
93
  istek = await self.httpx.get(url)
94
94
  secici = HTMLHelper(istek.text)
95
95
 
96
- title = secici.select_text("div.tv-overview h1 a")
97
-
98
- poster = secici.select_attr("div.tv-overview figure img", "src")
99
-
96
+ title = secici.select_text("div.tv-overview h1 a")
97
+ poster = secici.select_poster("div.tv-overview figure img")
100
98
  description = secici.select_text("div.tv-story p")
101
-
102
- # year
103
- year_text = secici.select_text("a[href*='/yil/']")
104
- year = secici.regex_first(r"(\d{4})", year_text)
105
-
106
- tags = secici.select_all_text("a[href*='/tur/']")
107
-
108
- # rating
109
- rating_text = secici.select_text("span.label-imdb b")
110
- rating = secici.regex_first(r"[\d.,]+", rating_text)
111
-
112
- actors = secici.select_all_text("a[href*='/oyuncu/']")
99
+ year = secici.extract_year("a[href*='/yil/']")
100
+ tags = secici.select_texts("a[href*='/tur/']")
101
+ rating = secici.regex_first(r"[\d.,]+", secici.select_text("span.label-imdb b"))
102
+ actors = secici.select_texts("a[href*='/oyuncu/']")
113
103
 
114
104
  episodes = []
115
- for sezon_link in secici.select_all_attr("div#seasons-list a", "href"):
116
- sezon_url = self.fix_url(sezon_link)
117
- sezon_istek = await self.httpx.get(sezon_url)
118
- sezon_secici = HTMLHelper(sezon_istek.text)
119
-
120
- for bolum in sezon_secici.select("article.grid-box"):
121
- ep_title = sezon_secici.select_text("div.post-title a", bolum)
122
- ep_href = sezon_secici.select_attr("div.post-title a", "href", bolum)
123
-
124
- ep_season = sezon_secici.regex_first(r"(\d+)\. ?Sezon", ep_title)
125
- ep_episode = sezon_secici.regex_first(r"(\d+)\. ?Bölüm", ep_title)
126
-
127
- if ep_title and ep_href:
128
- episodes.append(Episode(
129
- season = ep_season,
130
- episode = ep_episode,
131
- title = ep_title,
132
- url = self.fix_url(ep_href),
133
- ))
105
+ for link in secici.select_attrs("div#seasons-list a", "href"):
106
+ r = await self.httpx.get(self.fix_url(link))
107
+ s_secici = HTMLHelper(r.text)
108
+ for bolum in s_secici.select("article.grid-box"):
109
+ name = s_secici.select_text("div.post-title a", bolum)
110
+ href = s_secici.select_attr("div.post-title a", "href", bolum)
111
+ if name and href:
112
+ s, e = s_secici.extract_season_episode(name)
113
+ episodes.append(Episode(season=s, episode=e, title=name, url=self.fix_url(href)))
134
114
 
135
115
  return SeriesInfo(
136
116
  url = url,
@@ -139,7 +119,7 @@ class DiziBox(PluginBase):
139
119
  description = description,
140
120
  tags = tags,
141
121
  rating = rating,
142
- year = year,
122
+ year = str(year) if year else None,
143
123
  episodes = episodes,
144
124
  actors = actors,
145
125
  )
@@ -19,34 +19,28 @@ class DiziMom(PluginBase):
19
19
  }
20
20
 
21
21
  async def get_main_page(self, page: int, url: str, category: str) -> list[MainPageResult]:
22
- istek = await self.httpx.get(f"{url}/{page}/")
23
- helper = HTMLHelper(istek.text)
22
+ full_url = f"{url}/{page}/"
23
+ istek = await self.httpx.get(full_url)
24
+ helper = HTMLHelper(istek.text)
24
25
 
26
+ results = []
27
+ # Eğer "tum-bolumler" ise Episode kutularını, değilse Dizi kutularını tara
25
28
  if "/tum-bolumler/" in url:
26
- items = helper.select("div.episode-box")
27
- results = []
28
- for item in items:
29
- name_el = helper.select_first("div.episode-name a", item)
30
- if not name_el: continue
31
- name = name_el.text(strip=True).split(" izle")[0]
32
- title = name.replace(".Sezon ", "x").replace(".Bölüm", "")
33
-
34
- ep_href = self.fix_url(name_el.attrs.get("href"))
35
- pass
36
-
37
- # Revert to standard categories if "tum-bolumler" is complex
38
- return []
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)
33
+ 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)))
39
35
  else:
40
- items = helper.select("div.single-item")
41
- return [
42
- MainPageResult(
43
- category = category,
44
- title = helper.select_text("div.categorytitle a", item).split(" izle")[0],
45
- url = self.fix_url(helper.select_attr("div.categorytitle a", "href", item)),
46
- poster = self.fix_url(helper.select_attr("div.cat-img img", "src", item))
47
- )
48
- for item in items
49
- ]
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)
40
+ 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)))
42
+
43
+ return results
50
44
 
51
45
  async def search(self, query: str) -> list[SearchResult]:
52
46
  url = f"{self.main_url}/?s={query}"
@@ -67,117 +61,31 @@ class DiziMom(PluginBase):
67
61
  istek = await self.httpx.get(url)
68
62
  helper = HTMLHelper(istek.text)
69
63
 
70
- title_raw = helper.select_text("div.title h1")
71
- title = title_raw.split(" izle")[0] if title_raw else "Bilinmiyor"
72
-
73
- poster = self.fix_url(helper.select_attr("div.category_image img", "src"))
74
-
75
- # Custom extraction for fields that were using xpath_text
76
- year = None
77
- rating = None
78
- actors = None
79
-
80
- # Regex approach based on debug output (multiline support)
81
- # Context: <span class="dizimeta"><i class="fas fa-globe"></i> Yapım Yılı : </span>\n 2022
82
- year_val_all = helper.regex_all(r"Yapım Yılı\s*:\s*(?:</span>)?\s*(\d{4})", flags=re.DOTALL)
83
- if year_val_all:
84
- year = int(year_val_all[0])
85
-
86
- # Context: <span class="dizimeta"><i class="fas fa-star"></i> IMDB : </span>\n 4.5
87
- rating_val_all = helper.regex_all(r"IMDB\s*:\s*(?:</span>)?\s*([\d\.]+)", flags=re.DOTALL)
88
- if rating_val_all:
89
- rating = rating_val_all[0]
90
-
91
- actors_val = helper.regex_first(r"Oyuncular\s*:\s*(.+?)(?:</div>|<br|$)")
92
- if not actors_val:
93
- # Try selecting the div text directly if regex fails due to HTML tags
94
- # Find div containing "Oyuncular :"
95
- all_divs = helper.select("div")
96
- for div in all_divs:
97
- txt = div.text()
98
- if "Oyuncular :" in txt:
99
- actors_val = txt.split("Oyuncular :")[1].strip()
100
- break
101
-
102
- if actors_val:
103
- # Remove footer / junk from actors
104
- if "IMDB :" in actors_val:
105
- actors_val = actors_val.split("IMDB :")[0].strip()
106
-
107
- if "IMDB :" in actors_val:
108
- actors_val = actors_val.split("IMDB :")[0].strip()
109
-
110
- # Remove '×' and other junk if present at end
111
- if "×" in actors_val:
112
- actors_val = actors_val.split("×")[0].strip()
113
-
114
- # Remove simple tags if any remaining
115
- clean_actors = [a.strip() for a in actors_val.split(",")]
116
- # Filter empty
117
- clean_actors = [a for a in clean_actors if a]
118
-
119
- actors = ", ".join(clean_actors)
120
-
121
- description_raw = helper.select_text("div.category_desc")
122
- description = None
123
- if description_raw:
124
- # Clean header "The Librarians izle..." etc. if present, usually it is fine.
125
- # Clean "IMDB :" if attached
126
- if "IMDB :" in description_raw:
127
- description_raw = description_raw.split("IMDB :")[0].strip()
128
-
129
- # Clean footer text start
130
- # The footer block usually starts with "Dizimom, dizi ve film..."
131
- if "Dizimom," in description_raw:
132
- description = description_raw.split("Dizimom,")[0].strip()
133
- elif "dizi izle film izle" in description_raw:
134
- description = description_raw.split("dizi izle film izle")[0].strip()
135
- else:
136
- description = description_raw
137
-
138
- # Fallback cleanup for JSON
139
- if description and "{" in description:
140
- description = description.split("{")[0].strip()
141
-
142
- tags = helper.select_all_text("div.genres a")
143
-
144
- # Improved year regex
145
- if not year:
146
- # Look for "Yapım Yılı : 2014" pattern in ANY text
147
- # Get all text from category_text which usually contains it
148
- meta_text = helper.select_text("div.category_text")
149
- if meta_text:
150
- match = re.search(r"Yapım Yılı\s*:\s*(\d{4})", meta_text)
151
- if match:
152
- year = int(match.group(1))
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"IMDB\s*:\s*(?:</span>)?\s*([\d\.]+)", helper.html, flags=re.DOTALL)
69
+ year = helper.extract_year("div.category_text")
70
+ actors = helper.meta_list("Oyuncular", container_selector="div#icerikcat2")
153
71
 
154
72
  episodes = []
155
- ep_items = helper.select("div.bolumust")
156
- for item in ep_items:
157
- ep_name_raw = helper.select_text("div.baslik", item)
158
- ep_href = self.fix_url(helper.select_attr("a", "href", item))
159
-
160
- if ep_name_raw:
161
- # 1.Sezon 1.Bölüm
162
- s_m = re.search(r"(\d+)\.Sezon", ep_name_raw)
163
- e_m = re.search(r"(\d+)\.Bölüm", ep_name_raw)
164
-
165
- season = int(s_m.group(1)) if s_m else 1
166
- episode = int(e_m.group(1)) if e_m else 1
167
-
168
- name = ep_name_raw.split(" izle")[0].replace(title, "").strip()
169
-
73
+ for item in helper.select("div.bolumust"):
74
+ name = helper.select_text("div.baslik", item)
75
+ href = helper.select_attr("a", "href", item)
76
+ if name and href:
77
+ s, e = helper.extract_season_episode(name)
170
78
  episodes.append(Episode(
171
- season = season,
172
- episode = episode,
173
- title = name,
174
- url = ep_href
79
+ season = s or 1,
80
+ episode = e or 1,
81
+ title = self.clean_title(name.replace(title or "", "").strip()),
82
+ url = self.fix_url(href)
175
83
  ))
176
84
 
177
85
  return SeriesInfo(
178
86
  url = url,
179
- poster = poster,
180
- title = title,
87
+ poster = self.fix_url(poster) if poster else None,
88
+ title = title or "Bilinmiyor",
181
89
  description = description,
182
90
  tags = tags,
183
91
  rating = rating,
@@ -5,205 +5,114 @@ from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInf
5
5
  class DiziPal(PluginBase):
6
6
  name = "DiziPal"
7
7
  language = "tr"
8
- main_url = "https://dizipal1226.com"
8
+ main_url = "https://dizipal.cc"
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
 
12
12
  main_page = {
13
- f"{main_url}/diziler/son-bolumler" : "Son Bölümler",
14
- f"{main_url}/diziler" : "Yeni Diziler",
15
- f"{main_url}/filmler" : "Yeni Filmler",
16
- f"{main_url}/koleksiyon/netflix" : "Netflix",
17
- f"{main_url}/koleksiyon/exxen" : "Exxen",
18
- f"{main_url}/koleksiyon/blutv" : "BluTV",
19
- f"{main_url}/koleksiyon/disney" : "Disney+",
20
- f"{main_url}/koleksiyon/amazon-prime" : "Amazon Prime",
21
- f"{main_url}/koleksiyon/tod-bein" : "TOD (beIN)",
22
- f"{main_url}/koleksiyon/gain" : "Gain",
23
- f"{main_url}/tur/mubi" : "Mubi",
13
+ f"{main_url}/kategori/aile/page/" : "Aile",
14
+ f"{main_url}/kategori/aksiyon/page/" : "Aksiyon",
15
+ f"{main_url}/kategori/animasyon/page/" : "Animasyon",
16
+ f"{main_url}/kategori/belgesel/page/" : "Belgesel",
17
+ f"{main_url}/kategori/bilim-kurgu/page/" : "Bilim Kurgu",
18
+ f"{main_url}/kategori/dram/page/" : "Dram",
19
+ f"{main_url}/kategori/fantastik/page/" : "Fantastik",
20
+ f"{main_url}/kategori/gerilim/page/" : "Gerilim",
21
+ f"{main_url}/kategori/gizem/page/" : "Gizem",
22
+ f"{main_url}/kategori/komedi/page/" : "Komedi",
23
+ f"{main_url}/kategori/korku/page/" : "Korku",
24
+ f"{main_url}/kategori/macera/page/" : "Macera",
25
+ f"{main_url}/kategori/muzik/page/" : "Müzik",
26
+ f"{main_url}/kategori/romantik/page/" : "Romantik",
27
+ f"{main_url}/kategori/savas/page/" : "Savaş",
28
+ f"{main_url}/kategori/suc/page/" : "Suç",
29
+ f"{main_url}/kategori/tarih/page/" : "Tarih",
30
+ f"{main_url}/kategori/vahsi-bati/page/" : "Vahşi Batı",
31
+ f"{main_url}/kategori/yerli/page/" : "Yerli",
24
32
  }
25
33
 
26
34
  async def get_main_page(self, page: int, url: str, category: str) -> list[MainPageResult]:
27
- istek = await self.httpx.get(url)
35
+ istek = await self.httpx.get(f"{url}{page}/")
28
36
  secici = HTMLHelper(istek.text)
29
37
 
30
38
  results = []
31
-
32
- if "/son-bolumler" in url:
33
- for veri in secici.select("div.episode-item"):
34
- name = secici.select_text("div.name", veri)
35
- episode = secici.select_text("div.episode", veri)
36
- href = secici.select_attr("a", "href", veri)
37
- poster = secici.select_attr("img", "src", veri)
38
-
39
- if name and href:
40
- ep_text = episode.replace(". Sezon ", "x").replace(". Bölüm", "") if episode else ""
41
- title = f"{name} {ep_text}"
42
- # Son bölümler linkini dizi sayfasına çevir
43
- dizi_url = href.split("/sezon")[0] if "/sezon" in href else href
44
-
45
- results.append(MainPageResult(
46
- category = category,
47
- title = title,
48
- url = self.fix_url(dizi_url),
49
- poster = self.fix_url(poster) if poster else None,
50
- ))
51
- else:
52
- for veri in secici.select("article.type2 ul li"):
53
- title = secici.select_text("span.title", veri)
54
- href = secici.select_attr("a", "href", veri)
55
- poster = secici.select_attr("img", "src", veri)
56
-
57
- if title and href:
58
- results.append(MainPageResult(
59
- category = category,
60
- title = title,
61
- url = self.fix_url(href),
62
- poster = self.fix_url(poster) if poster else None,
63
- ))
39
+ for veri in secici.select("div.grid div.post-item"):
40
+ title = secici.select_attr("a", "title", veri)
41
+ href = secici.select_attr("a", "href", veri)
42
+ poster = secici.select_poster("div.poster img", veri)
43
+
44
+ if title and href:
45
+ results.append(MainPageResult(
46
+ category = category,
47
+ title = title,
48
+ url = self.fix_url(href),
49
+ poster = self.fix_url(poster) if poster else None,
50
+ ))
64
51
 
65
52
  return results
66
53
 
67
54
  async def search(self, query: str) -> list[SearchResult]:
68
- self.httpx.headers.update({
69
- "Accept" : "application/json, text/javascript, */*; q=0.01",
70
- "X-Requested-With" : "XMLHttpRequest"
71
- })
72
-
73
- istek = await self.httpx.post(
74
- url = f"{self.main_url}/api/search-autocomplete",
75
- data = {"query": query}
76
- )
77
-
78
- try:
79
- data = istek.json()
80
- except Exception:
81
- return []
55
+ istek = await self.httpx.get(f"{self.main_url}/?s={query}")
56
+ secici = HTMLHelper(istek.text)
82
57
 
83
58
  results = []
59
+ for veri in secici.select("div.grid div.post-item"):
60
+ title = secici.select_attr("a", "title", veri)
61
+ href = secici.select_attr("a", "href", veri)
62
+ poster = secici.select_poster("div.poster img", veri)
84
63
 
85
- # API bazen dict, bazen list döner
86
- items = data.values() if isinstance(data, dict) else data
87
-
88
- for item in items:
89
- if not isinstance(item, dict):
90
- continue
91
-
92
- title = item.get("title")
93
- url = item.get("url")
94
- poster = item.get("poster")
95
-
96
- if title and url:
64
+ if title and href:
97
65
  results.append(SearchResult(
98
66
  title = title,
99
- url = f"{self.main_url}{url}",
67
+ url = self.fix_url(href),
100
68
  poster = self.fix_url(poster) if poster else None,
101
69
  ))
102
70
 
103
71
  return results
104
72
 
105
- def _find_sibling_text(self, secici: HTMLHelper, label_text: str) -> str | None:
106
- """Bir label'ın kardeş div'inden text çıkarır (xpath yerine)"""
107
- for div in secici.select("div"):
108
- if secici.select_text(element=div) == label_text:
109
- # Sonraki kardeş elementi bul
110
- next_sibling = div.next
111
- while next_sibling:
112
- if hasattr(next_sibling, 'text') and next_sibling.text(strip=True):
113
- return next_sibling.text(strip=True)
114
- next_sibling = next_sibling.next if hasattr(next_sibling, 'next') else None
115
- return None
116
-
117
73
  async def load_item(self, url: str) -> MovieInfo | SeriesInfo:
118
- # Reset headers to get HTML response
119
- self.httpx.headers.update({
120
- "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
121
- })
122
- self.httpx.headers.pop("X-Requested-With", None)
123
-
124
74
  istek = await self.httpx.get(url)
125
75
  secici = HTMLHelper(istek.text)
126
- html_text = istek.text
127
76
 
128
- poster = self.fix_url(secici.select_attr("meta[property='og:image']", "content")) if secici.select_attr("meta[property='og:image']", "content") else None
129
-
130
- # Sidebar bilgilerini topla
131
- info = {}
132
- for li in secici.select("li"):
133
- key = secici.select_text("div.key", li)
134
- val = secici.select_text("div.value", li)
135
- if key and val:
136
- info[key.strip(":")] = val.strip()
137
-
138
- year = info.get("Yapım Yılı")
139
- rating = info.get("IMDB Puanı")
77
+ poster = self.fix_url(secici.select_attr("meta[property='og:image']", "content"))
78
+ description = secici.select_attr("meta[property='og:description']", "content")
79
+ title = secici.select_text("h1")
140
80
 
141
- tags_raw = info.get("Türler", "")
142
- tags = [t.strip() for t in tags_raw.split() if t.strip()] if tags_raw else None
143
-
144
- actors_raw = info.get("Oyuncular")
145
- actors = [a.strip() for a in actors_raw.split(",") if a.strip()] if actors_raw else None
146
-
147
- description = secici.select_text("div.summary p")
148
-
149
- duration_raw = info.get("Ortalama Süre")
150
- duration = int(secici.regex_first(r"(\d+)", duration_raw)) if duration_raw else None
81
+ year = secici.meta_value("Yapım Yılı")
82
+ rating = secici.meta_value("IMDB Puanı")
83
+ duration = secici.meta_value("Süre")
84
+ duration = int(secici.regex_first(r"(\d+)", duration)) if duration else None
85
+ tags = secici.meta_list("Tür")
86
+
87
+ actors = secici.meta_list("Oyuncular")
88
+ if not actors:
89
+ actors = secici.select_attrs("div.swiper-slide a", "title")
151
90
 
152
91
  if "/dizi/" in url:
153
- title = secici.select_text("div.cover h5")
154
-
155
92
  episodes = []
156
93
  for ep in secici.select("div.episode-item"):
157
- ep_name = secici.select_text("div.name", ep)
158
- ep_href = secici.select_attr("a", "href", ep)
159
- ep_text = secici.select_text("div.episode", ep)
160
- ep_parts = ep_text.split(" ")
94
+ name = secici.select_text("h4 a", ep)
95
+ href = secici.select_attr("a", "href", ep)
96
+ link_title = secici.select_attr("a", "title", ep)
97
+
98
+ h4_texts = secici.select_texts("h4", ep)
99
+ text = h4_texts[1] if len(h4_texts) > 1 else (h4_texts[0] if h4_texts else "")
161
100
 
162
- ep_season = None
163
- ep_episode = None
164
- if len(ep_parts) >= 4:
165
- try:
166
- ep_season = int(ep_parts[0].replace(".", ""))
167
- ep_episode = int(ep_parts[2].replace(".", ""))
168
- except ValueError:
169
- pass
101
+ full_text = f"{text} {link_title}" if link_title else text
170
102
 
171
- if ep_name and ep_href:
172
- episodes.append(Episode(
173
- season = ep_season,
174
- episode = ep_episode,
175
- title = ep_name,
176
- url = self.fix_url(ep_href),
177
- ))
103
+ if name and href:
104
+ s, e = secici.extract_season_episode(full_text or "")
105
+ episodes.append(Episode(season=s, episode=e, title=name, url=self.fix_url(href)))
178
106
 
179
107
  return SeriesInfo(
180
- url = url,
181
- poster = poster,
182
- title = title,
183
- description = description,
184
- tags = tags,
185
- rating = rating,
186
- year = year,
187
- duration = duration,
188
- episodes = episodes if episodes else None,
189
- actors = actors,
190
- )
191
- else:
192
- # Film için title - g-title div'lerinin 2. olanı
193
- g_titles = secici.select("div.g-title div")
194
- title = secici.select_text(element=g_titles[1]) if len(g_titles) >= 2 else None
195
-
196
- return MovieInfo(
197
- url = url,
198
- poster = poster,
199
- title = title,
200
- description = description,
201
- tags = tags,
202
- rating = rating,
203
- year = year,
204
- duration = duration,
205
- actors = actors,
108
+ url=url, poster=poster, title=title, description=description, tags=tags,
109
+ rating=rating, year=year, duration=duration, episodes=episodes or None, actors=actors
206
110
  )
111
+
112
+ return MovieInfo(
113
+ url=url, poster=poster, title=title, description=description, tags=tags,
114
+ rating=rating, year=year, duration=duration, actors=actors
115
+ )
207
116
 
208
117
  async def load_links(self, url: str) -> list[ExtractResult]:
209
118
  # Reset headers to get HTML response
@@ -215,9 +124,7 @@ class DiziPal(PluginBase):
215
124
  istek = await self.httpx.get(url)
216
125
  secici = HTMLHelper(istek.text)
217
126
 
218
- # iframe presence checked via select_attr below
219
-
220
- iframe = secici.select_attr(".series-player-container iframe", "src") or secici.select_attr("div#vast_new iframe", "src")
127
+ iframe = secici.select_attr("div.video-player-area iframe", "src") or secici.select_attr("div.responsive-player iframe", "src")
221
128
  if not iframe:
222
129
  return []
223
130