KekikStream 2.3.3__py3-none-any.whl → 2.3.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 (59) hide show
  1. KekikStream/Core/HTMLHelper.py +134 -0
  2. KekikStream/Core/Plugin/PluginBase.py +4 -1
  3. KekikStream/Core/__init__.py +2 -0
  4. KekikStream/Extractors/CloseLoad.py +12 -13
  5. KekikStream/Extractors/ContentX.py +12 -15
  6. KekikStream/Extractors/DonilasPlay.py +10 -10
  7. KekikStream/Extractors/DzenRu.py +3 -3
  8. KekikStream/Extractors/ExPlay.py +10 -10
  9. KekikStream/Extractors/Filemoon.py +11 -16
  10. KekikStream/Extractors/JetTv.py +4 -4
  11. KekikStream/Extractors/MixPlayHD.py +10 -11
  12. KekikStream/Extractors/MolyStream.py +5 -9
  13. KekikStream/Extractors/Odnoklassniki.py +4 -4
  14. KekikStream/Extractors/PeaceMakerst.py +3 -3
  15. KekikStream/Extractors/PixelDrain.py +6 -5
  16. KekikStream/Extractors/PlayerFilmIzle.py +6 -10
  17. KekikStream/Extractors/RapidVid.py +8 -7
  18. KekikStream/Extractors/SetPlay.py +10 -10
  19. KekikStream/Extractors/SetPrime.py +3 -6
  20. KekikStream/Extractors/SibNet.py +4 -5
  21. KekikStream/Extractors/Sobreatsesuyp.py +5 -5
  22. KekikStream/Extractors/TRsTX.py +5 -5
  23. KekikStream/Extractors/TurboImgz.py +3 -4
  24. KekikStream/Extractors/TurkeyPlayer.py +5 -5
  25. KekikStream/Extractors/VidHide.py +4 -7
  26. KekikStream/Extractors/VidMoly.py +24 -25
  27. KekikStream/Extractors/VidMoxy.py +8 -9
  28. KekikStream/Extractors/VidPapi.py +5 -7
  29. KekikStream/Extractors/VideoSeyred.py +3 -3
  30. KekikStream/Plugins/BelgeselX.py +40 -51
  31. KekikStream/Plugins/DiziBox.py +53 -81
  32. KekikStream/Plugins/DiziPal.py +41 -74
  33. KekikStream/Plugins/DiziYou.py +95 -88
  34. KekikStream/Plugins/Dizilla.py +51 -71
  35. KekikStream/Plugins/FilmBip.py +24 -49
  36. KekikStream/Plugins/FilmMakinesi.py +35 -52
  37. KekikStream/Plugins/FilmModu.py +27 -41
  38. KekikStream/Plugins/FullHDFilm.py +50 -72
  39. KekikStream/Plugins/FullHDFilmizlesene.py +35 -51
  40. KekikStream/Plugins/HDFilmCehennemi.py +48 -62
  41. KekikStream/Plugins/JetFilmizle.py +32 -50
  42. KekikStream/Plugins/KultFilmler.py +42 -67
  43. KekikStream/Plugins/RecTV.py +7 -4
  44. KekikStream/Plugins/RoketDizi.py +30 -50
  45. KekikStream/Plugins/SelcukFlix.py +15 -29
  46. KekikStream/Plugins/SetFilmIzle.py +41 -70
  47. KekikStream/Plugins/SezonlukDizi.py +47 -65
  48. KekikStream/Plugins/Sinefy.py +34 -50
  49. KekikStream/Plugins/SinemaCX.py +31 -55
  50. KekikStream/Plugins/Sinezy.py +27 -54
  51. KekikStream/Plugins/SuperFilmGeldi.py +25 -44
  52. KekikStream/Plugins/UgurFilm.py +23 -48
  53. {kekikstream-2.3.3.dist-info → kekikstream-2.3.4.dist-info}/METADATA +1 -1
  54. kekikstream-2.3.4.dist-info/RECORD +83 -0
  55. kekikstream-2.3.3.dist-info/RECORD +0 -82
  56. {kekikstream-2.3.3.dist-info → kekikstream-2.3.4.dist-info}/WHEEL +0 -0
  57. {kekikstream-2.3.3.dist-info → kekikstream-2.3.4.dist-info}/entry_points.txt +0 -0
  58. {kekikstream-2.3.3.dist-info → kekikstream-2.3.4.dist-info}/licenses/LICENSE +0 -0
  59. {kekikstream-2.3.3.dist-info → kekikstream-2.3.4.dist-info}/top_level.txt +0 -0
@@ -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
4
- from selectolax.parser import HTMLParser
5
- import re
3
+ from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo, SeriesInfo, Episode, ExtractResult, HTMLHelper
6
4
 
7
5
  class FilmMakinesi(PluginBase):
8
6
  name = "FilmMakinesi"
@@ -37,17 +35,13 @@ class FilmMakinesi(PluginBase):
37
35
 
38
36
  async def get_main_page(self, page: int, url: str, category: str) -> list[MainPageResult]:
39
37
  istek = self.cloudscraper.get(f"{url}{'' if page == 1 else f'page/{page}/'}")
40
- secici = HTMLParser(istek.text)
38
+ secici = HTMLHelper(istek.text)
41
39
 
42
40
  results = []
43
- for veri in secici.css("div.item-relative"):
44
- title_el = veri.css_first("div.title")
45
- link_el = veri.css_first("a")
46
- img_el = veri.css_first("img")
47
-
48
- title = title_el.text(strip=True) if title_el else None
49
- href = link_el.attrs.get("href") if link_el else None
50
- poster = (img_el.attrs.get("data-src") or img_el.attrs.get("src")) if img_el else None
41
+ for veri in secici.select("div.item-relative"):
42
+ title = secici.select_text("div.title", veri)
43
+ href = secici.select_attr("a", "href", veri)
44
+ poster = secici.select_poster("img", veri)
51
45
 
52
46
  if title and href:
53
47
  results.append(MainPageResult(
@@ -61,17 +55,13 @@ class FilmMakinesi(PluginBase):
61
55
 
62
56
  async def search(self, query: str) -> list[SearchResult]:
63
57
  istek = await self.httpx.get(f"{self.main_url}/arama/?s={query}")
64
- secici = HTMLParser(istek.text)
58
+ secici = HTMLHelper(istek.text)
65
59
 
66
60
  results = []
67
- for article in secici.css("div.item-relative"):
68
- title_el = article.css_first("div.title")
69
- link_el = article.css_first("a")
70
- img_el = article.css_first("img")
71
-
72
- title = title_el.text(strip=True) if title_el else None
73
- href = link_el.attrs.get("href") if link_el else None
74
- poster = (img_el.attrs.get("data-src") or img_el.attrs.get("src")) if img_el else None
61
+ for article in secici.select("div.item-relative"):
62
+ title = secici.select_text("div.title", article)
63
+ href = secici.select_attr("a", "href", article)
64
+ poster = secici.select_poster("img", article)
75
65
 
76
66
  if title and href:
77
67
  results.append(SearchResult(
@@ -84,48 +74,42 @@ class FilmMakinesi(PluginBase):
84
74
 
85
75
  async def load_item(self, url: str) -> MovieInfo | SeriesInfo:
86
76
  istek = await self.httpx.get(url)
87
- secici = HTMLParser(istek.text)
77
+ secici = HTMLHelper(istek.text)
88
78
 
89
- title_el = secici.css_first("h1.title")
90
- title = title_el.text(strip=True) if title_el else ""
79
+ title = secici.select_text("h1.title") or ""
91
80
 
92
- poster_el = secici.css_first("img.cover-img")
93
- poster = poster_el.attrs.get("src", "").strip() if poster_el else ""
81
+ poster = secici.select_attr("img.cover-img", "src") or ""
82
+ poster = poster.strip()
94
83
 
95
- desc_el = secici.css_first("div.info-description p")
96
- description = desc_el.text(strip=True) if desc_el else ""
84
+ description = secici.select_text("div.info-description p") or ""
97
85
 
98
- rating_el = secici.css_first("div.score")
99
- rating = None
100
- if rating_el:
101
- rating_text = rating_el.text(strip=True)
102
- if rating_text:
103
- rating = rating_text.split()[0]
86
+ rating_text = secici.select_text("div.score") or ""
87
+ rating = None
88
+ if rating_text:
89
+ rating = rating_text.split()[0]
104
90
 
105
- year_el = secici.css_first("span.date a")
106
- year = year_el.text(strip=True) if year_el else ""
91
+ year = secici.select_text("span.date a") or ""
107
92
 
108
- actors = [el.text(strip=True) for el in secici.css("div.cast-name") if el.text(strip=True)]
109
- tags = [el.text(strip=True) for el in secici.css("div.genre a") if el.text(strip=True)]
93
+ actors = secici.select_all_text("div.cast-name")
94
+ tags = secici.select_all_text("div.genre a")
110
95
 
111
- duration_el = secici.css_first("div.time")
112
- duration = None
113
- if duration_el:
114
- duration_text = duration_el.text(strip=True)
96
+ duration = None
97
+ duration_text = secici.select_text("div.time") or None
98
+ if duration_text:
115
99
  parts = duration_text.split()
116
100
  if len(parts) > 1:
117
101
  duration = parts[1].strip()
118
102
 
119
103
  # Dizi mi kontrol et - sezon/bölüm linkleri var mı?
120
104
  episodes = []
121
- all_links = secici.css("a[href]")
105
+ all_links = secici.select("a[href]")
122
106
  for link in all_links:
123
107
  href = link.attrs.get("href", "")
124
- match = re.search(r"/sezon-(\d+)/bolum-(\d+)", href)
125
- if match:
126
- season_no = int(match.group(1))
127
- ep_no = int(match.group(2))
128
-
108
+ pairs = HTMLHelper(href).regex_all(r"/sezon-(\d+)/bolum-(\d+)")
109
+ if pairs:
110
+ season_no = int(pairs[0][0])
111
+ ep_no = int(pairs[0][1])
112
+
129
113
  # Bölüm başlığını çıkar - text'ten gerçek ismi al
130
114
  # Format: "22 Eylül 2014 / 44 dk /1. Sezon / 1. BölümPilot"
131
115
  full_text = link.text(strip=True)
@@ -184,12 +168,12 @@ class FilmMakinesi(PluginBase):
184
168
 
185
169
  async def load_links(self, url: str) -> list[ExtractResult]:
186
170
  istek = await self.httpx.get(url)
187
- secici = HTMLParser(istek.text)
171
+ secici = HTMLHelper(istek.text)
188
172
 
189
173
  response = []
190
174
 
191
175
  # Video parts linklerini ve etiketlerini al
192
- for link in secici.css("div.video-parts a[data-video_url]"):
176
+ for link in secici.select("div.video-parts a[data-video_url]"):
193
177
  video_url = link.attrs.get("data-video_url")
194
178
  label = link.text(strip=True) if link.text(strip=True) else ""
195
179
 
@@ -200,8 +184,7 @@ class FilmMakinesi(PluginBase):
200
184
 
201
185
  # Eğer video-parts yoksa iframe kullan
202
186
  if not response:
203
- iframe_el = secici.css_first("iframe")
204
- iframe_src = iframe_el.attrs.get("data-src") if iframe_el else None
187
+ iframe_src = secici.select_attr("iframe", "data-src")
205
188
  if iframe_src:
206
189
  data = await self.extract(iframe_src)
207
190
  if data:
@@ -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, Subtitle, ExtractResult
4
- from selectolax.parser import HTMLParser
5
- import re
3
+ from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo, Subtitle, ExtractResult, HTMLHelper
6
4
 
7
5
  class FilmModu(PluginBase):
8
6
  name = "FilmModu"
@@ -42,16 +40,13 @@ class FilmModu(PluginBase):
42
40
 
43
41
  async def get_main_page(self, page: int, url: str, category: str) -> list[MainPageResult]:
44
42
  istek = await self.httpx.get(url.replace("SAYFA", str(page)))
45
- secici = HTMLParser(istek.text)
43
+ secici = HTMLHelper(istek.text)
46
44
 
47
45
  results = []
48
- for veri in secici.css("div.movie"):
49
- link_el = veri.css_first("a")
50
- img_el = veri.css_first("picture img")
51
-
52
- title = link_el.text(strip=True) if link_el else None
53
- href = link_el.attrs.get("href") if link_el else None
54
- poster = img_el.attrs.get("data-src") if img_el else None
46
+ for veri in secici.select("div.movie"):
47
+ title = secici.select_text("a", veri)
48
+ href = secici.select_attr("a", "href", veri)
49
+ poster = secici.select_attr("picture img", "data-src", veri)
55
50
 
56
51
  if title and href:
57
52
  results.append(MainPageResult(
@@ -65,16 +60,13 @@ class FilmModu(PluginBase):
65
60
 
66
61
  async def search(self, query: str) -> list[SearchResult]:
67
62
  istek = await self.httpx.get(f"{self.main_url}/film-ara?term={query}")
68
- secici = HTMLParser(istek.text)
63
+ secici = HTMLHelper(istek.text)
69
64
 
70
65
  results = []
71
- for veri in secici.css("div.movie"):
72
- link_el = veri.css_first("a")
73
- img_el = veri.css_first("picture img")
74
-
75
- title = link_el.text(strip=True) if link_el else None
76
- href = link_el.attrs.get("href") if link_el else None
77
- poster = img_el.attrs.get("data-src") if img_el else None
66
+ for veri in secici.select("div.movie"):
67
+ title = secici.select_text("a", veri)
68
+ href = secici.select_attr("a", "href", veri)
69
+ poster = secici.select_attr("picture img", "data-src", veri)
78
70
 
79
71
  if title and href:
80
72
  results.append(SearchResult(
@@ -87,31 +79,25 @@ class FilmModu(PluginBase):
87
79
 
88
80
  async def load_item(self, url: str) -> MovieInfo:
89
81
  istek = await self.httpx.get(url)
90
- secici = HTMLParser(istek.text)
91
-
92
- org_title_el = secici.css_first("div.titles h1")
93
- alt_title_el = secici.css_first("div.titles h2")
82
+ secici = HTMLHelper(istek.text)
94
83
 
95
- org_title = org_title_el.text(strip=True) if org_title_el else ""
96
- alt_title = alt_title_el.text(strip=True) if alt_title_el else ""
84
+ org_title = secici.select_text("div.titles h1") or ""
85
+ alt_title = secici.select_text("div.titles h2") or ""
97
86
  title = f"{org_title} - {alt_title}" if alt_title else org_title
98
87
 
99
- poster_el = secici.css_first("img.img-responsive")
100
- poster = poster_el.attrs.get("src") if poster_el else None
88
+ poster = secici.select_attr("img.img-responsive", "src") if secici.select_attr("img.img-responsive", "src") else None
101
89
 
102
- desc_el = secici.css_first("p[itemprop='description']")
103
- description = desc_el.text(strip=True) if desc_el else None
90
+ description = secici.select_text("p[itemprop='description']") or None
104
91
 
105
- tags = [a.text(strip=True) for a in secici.css("a[href*='film-tur/']") if a.text(strip=True)]
92
+ tags = secici.select_all_text("a[href*='film-tur/']")
106
93
 
107
- year_el = secici.css_first("span[itemprop='dateCreated']")
108
- year = year_el.text(strip=True) if year_el else None
94
+ year = secici.select_text("span[itemprop='dateCreated']") or None
109
95
 
110
96
  actors = []
111
- for a in secici.css("a[itemprop='actor']"):
112
- span_el = a.css_first("span")
113
- if span_el and span_el.text(strip=True):
114
- actors.append(span_el.text(strip=True))
97
+ for a in secici.select("a[itemprop='actor']"):
98
+ name = secici.select_text("span", a)
99
+ if name:
100
+ actors.append(name)
115
101
 
116
102
  return MovieInfo(
117
103
  url = url,
@@ -125,9 +111,9 @@ class FilmModu(PluginBase):
125
111
 
126
112
  async def load_links(self, url: str) -> list[ExtractResult]:
127
113
  istek = await self.httpx.get(url)
128
- secici = HTMLParser(istek.text)
114
+ secici = HTMLHelper(istek.text)
129
115
 
130
- alternates = secici.css("div.alternates a")
116
+ alternates = secici.select("div.alternates a")
131
117
  if not alternates:
132
118
  return []
133
119
 
@@ -144,14 +130,14 @@ class FilmModu(PluginBase):
144
130
  alt_istek = await self.httpx.get(alt_link)
145
131
  alt_text = alt_istek.text
146
132
 
147
- vid_id = re.search(r"var videoId = '(.*)'", alt_text)
148
- vid_type = re.search(r"var videoType = '(.*)'", alt_text)
133
+ vid_id = HTMLHelper(alt_text).regex_first(r"var videoId = '([^']*)'")
134
+ vid_type = HTMLHelper(alt_text).regex_first(r"var videoType = '([^']*)'")
149
135
 
150
136
  if not vid_id or not vid_type:
151
137
  continue
152
138
 
153
139
  source_istek = await self.httpx.get(
154
- f"{self.main_url}/get-source?movie_id={vid_id[1]}&type={vid_type[1]}"
140
+ f"{self.main_url}/get-source?movie_id={vid_id}&type={vid_type}"
155
141
  )
156
142
  source_data = source_istek.json()
157
143
 
@@ -1,8 +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, SeriesInfo, Episode, ExtractResult, Subtitle
4
- from selectolax.parser import HTMLParser
5
- import re, base64
3
+ from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo, SeriesInfo, Episode, ExtractResult, Subtitle, HTMLHelper
4
+ import base64
6
5
 
7
6
  class FullHDFilm(PluginBase):
8
7
  name = "FullHDFilm"
@@ -48,16 +47,13 @@ class FullHDFilm(PluginBase):
48
47
  })
49
48
 
50
49
  istek = await self.httpx.get(page_url)
51
- secici = HTMLParser(istek.text)
50
+ secici = HTMLHelper(istek.text)
52
51
 
53
52
  results = []
54
- for veri in secici.css("div.movie-poster"):
55
- img_el = veri.css_first("img")
56
- link_el = veri.css_first("a")
57
-
58
- alt = img_el.attrs.get("alt") if img_el else None
59
- poster = img_el.attrs.get("src") if img_el else None
60
- href = link_el.attrs.get("href") if link_el else None
53
+ for veri in secici.select("div.movie-poster"):
54
+ alt = secici.select_attr("img", "alt", veri)
55
+ poster = secici.select_attr("img", "src", veri)
56
+ href = secici.select_attr("a", "href", veri)
61
57
 
62
58
  if alt and href:
63
59
  results.append(MainPageResult(
@@ -71,16 +67,13 @@ class FullHDFilm(PluginBase):
71
67
 
72
68
  async def search(self, query: str) -> list[SearchResult]:
73
69
  istek = await self.httpx.get(f"{self.main_url}/?s={query}")
74
- secici = HTMLParser(istek.text)
70
+ secici = HTMLHelper(istek.text)
75
71
 
76
72
  results = []
77
- for veri in secici.css("div.movie-poster"):
78
- img_el = veri.css_first("img")
79
- link_el = veri.css_first("a")
80
-
81
- alt = img_el.attrs.get("alt") if img_el else None
82
- poster = img_el.attrs.get("src") if img_el else None
83
- href = link_el.attrs.get("href") if link_el else None
73
+ for veri in secici.select("div.movie-poster"):
74
+ alt = secici.select_attr("img", "alt", veri)
75
+ poster = secici.select_attr("img", "src", veri)
76
+ href = secici.select_attr("a", "href", veri)
84
77
 
85
78
  if alt and href:
86
79
  results.append(SearchResult(
@@ -93,75 +86,59 @@ class FullHDFilm(PluginBase):
93
86
 
94
87
  async def load_item(self, url: str) -> MovieInfo | SeriesInfo:
95
88
  istek = await self.httpx.get(url)
96
- secici = HTMLParser(istek.text)
89
+ secici = HTMLHelper(istek.text)
97
90
  html_text = istek.text
98
91
 
99
- title_el = secici.css_first("h1")
100
- title = title_el.text(strip=True) if title_el else ""
92
+ title = secici.select_text("h1") or ""
101
93
 
102
- poster_el = secici.css_first("div.poster img")
103
- poster = self.fix_url(poster_el.attrs.get("src")) if poster_el else ""
94
+ poster = secici.select_attr("div.poster img", "src") or ""
95
+ poster = self.fix_url(poster)
104
96
 
105
- actors_el = secici.css_first("div.oyuncular.info")
106
97
  actors = []
107
- if actors_el:
108
- actors_text = actors_el.text(strip=True)
109
- if actors_text:
110
- actors_text = actors_text.replace("Oyuncular:", "").strip()
111
- actors = [a.strip() for a in actors_text.split(",")]
98
+ actors_text = secici.select_text("div.oyuncular.info")
99
+ if actors_text:
100
+ actors_text = actors_text.replace("Oyuncular:", "").strip()
101
+ actors = [a.strip() for a in actors_text.split(",")]
112
102
 
113
103
  # Year: önce div.yayin-tarihi.info dene
114
- year = None
115
- year_el = secici.css_first("div.yayin-tarihi.info")
116
- if year_el:
117
- year_text = year_el.text(strip=True)
118
- year_match = re.search(r"(\d{4})", year_text)
119
- if year_match:
120
- year = year_match.group(1)
121
-
104
+ year = secici.extract_year("div.yayin-tarihi.info")
105
+
122
106
  # Fallback: h1'in parent'ından (2019) formatında ara
123
- if not year and title_el:
124
- parent = title_el.parent
125
- if parent:
126
- parent_text = parent.text(strip=True)
127
- year_match = re.search(r"\((\d{4})\)", parent_text)
128
- if year_match:
129
- year = year_match.group(1)
107
+ if not year:
108
+ # Parent'ın tüm text içeriğinden yıl çıkar
109
+ title_text = secici.select_text("h1")
110
+ if title_text:
111
+ # h1 parent'ındaki (2019) gibi text'i bul
112
+ year = secici.regex_first(r"\((\d{4})\)")
130
113
 
131
- tags = [a.text(strip=True) for a in secici.css("div.tur.info a") if a.text(strip=True)]
114
+ tags = secici.select_all_text("div.tur.info a")
132
115
 
133
116
  # Rating: regex
134
- rating_el = secici.css_first("div.imdb")
135
- rating_text = rating_el.text(strip=True) if rating_el else ""
136
- rating_match = re.search(r"IMDb\s*([\d\.]+)", rating_text)
137
- rating = rating_match.group(1) if rating_match else None
117
+ rating_text = secici.select_text("div.imdb") or ""
118
+ rating = HTMLHelper(rating_text).regex_first(r"IMDb\s*([\d\.]+)")
138
119
 
139
120
  # Description: önce div.film dene, yoksa og:description meta tag'ını kullan
140
- description = None
141
- desc_el = secici.css_first("div.film")
142
- if desc_el:
143
- description = desc_el.text(strip=True)
121
+ description = secici.select_text("div.film")
144
122
 
145
123
  # Fallback: og:description meta tag'ı
146
124
  if not description:
147
- og_desc = secici.css_first("meta[property='og:description']")
125
+ og_desc = secici.select_attr("meta[property='og:description']", "content")
148
126
  if og_desc:
149
- description = og_desc.attrs.get("content", "")
127
+ description = og_desc
150
128
 
151
129
  # Kotlin referansı: URL'de -dizi kontrolü veya tags içinde "dizi" kontrolü
152
130
  is_series = "-dizi" in url.lower() or any("dizi" in tag.lower() for tag in tags)
153
131
 
154
132
  if is_series:
155
133
  episodes = []
156
- part_elements = secici.css("li.psec")
134
+ part_elements = secici.select("li.psec")
157
135
 
158
136
  # pdata değerlerini çıkar
159
- pdata_matches = re.findall(r"pdata\['([^']+)'\]\s*=\s*'([^']+)'", html_text)
137
+ pdata_matches = HTMLHelper(html_text).regex_all(r"pdata\['([^']+)'\]\s*=\s*'([^']+)'")
160
138
 
161
139
  for idx, el in enumerate(part_elements):
162
140
  part_id = el.attrs.get("id")
163
- link_el = el.css_first("a")
164
- part_name = link_el.text(strip=True) if link_el else None
141
+ part_name = secici.select_text("a", el)
165
142
 
166
143
  if not part_name:
167
144
  continue
@@ -171,11 +148,11 @@ class FullHDFilm(PluginBase):
171
148
  continue
172
149
 
173
150
  # Sezon ve bölüm numarası çıkar
174
- sz_match = re.search(r'(\d+)\s*sezon', part_id.lower() if part_id else "")
175
- ep_match = re.search(r'^(\d+)\.', part_name)
176
-
177
- sz_num = int(sz_match.group(1)) if sz_match else 1
178
- ep_num = int(ep_match.group(1)) if ep_match else idx + 1
151
+ sz_val = HTMLHelper(part_id.lower() if part_id else "").regex_first(r'(\d+)\s*sezon')
152
+ ep_val = HTMLHelper(part_name).regex_first(r'^(\d+)\.')
153
+
154
+ sz_num = int(sz_val) if sz_val and sz_val.isdigit() else 1
155
+ ep_num = int(ep_val) if ep_val and ep_val.isdigit() else idx + 1
179
156
 
180
157
  # pdata'dan video URL'si çık (varsa)
181
158
  video_url = url # Varsayılan olarak ana URL kullan
@@ -214,14 +191,14 @@ class FullHDFilm(PluginBase):
214
191
 
215
192
  def _get_iframe(self, source_code: str) -> str:
216
193
  """Base64 kodlu iframe'i çözümle"""
217
- match = re.search(r'<script[^>]*>(PCEtLWJhc2xpazp[^<]*)</script>', source_code)
218
- if not match:
194
+ script_val = HTMLHelper(source_code).regex_first(r'<script[^>]*>(PCEtLWJhc2xpazp[^<]*)</script>')
195
+ if not script_val:
219
196
  return ""
220
197
 
221
198
  try:
222
- decoded_html = base64.b64decode(match[1]).decode("utf-8")
223
- iframe_match = re.search(r'<iframe[^>]+src=["\']([^"\']+)["\']', decoded_html)
224
- return self.fix_url(iframe_match[1]) if iframe_match else ""
199
+ decoded_html = base64.b64decode(script_val).decode("utf-8")
200
+ iframe_src = HTMLHelper(decoded_html).regex_first(r'<iframe[^>]+src=["\']([^"\']+)["\']')
201
+ return self.fix_url(iframe_src) if iframe_src else ""
225
202
  except Exception:
226
203
  return ""
227
204
 
@@ -234,8 +211,9 @@ class FullHDFilm(PluginBase):
234
211
  ]
235
212
 
236
213
  for pattern in patterns:
237
- if match := re.search(pattern, source_code):
238
- return match[1]
214
+ val = HTMLHelper(source_code).regex_first(pattern)
215
+ if val:
216
+ return val
239
217
 
240
218
  return None
241
219
 
@@ -1,9 +1,8 @@
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
4
- from selectolax.parser import HTMLParser
3
+ from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo, ExtractResult, HTMLHelper
5
4
  from Kekik.Sifreleme import StringCodec
6
- import json, re
5
+ import json
7
6
 
8
7
  class FullHDFilmizlesene(PluginBase):
9
8
  name = "FullHDFilmizlesene"
@@ -42,17 +41,13 @@ class FullHDFilmizlesene(PluginBase):
42
41
 
43
42
  async def get_main_page(self, page: int, url: str, category: str) -> list[MainPageResult]:
44
43
  istek = self.cloudscraper.get(f"{url}{page}")
45
- secici = HTMLParser(istek.text)
44
+ secici = HTMLHelper(istek.text)
46
45
 
47
46
  results = []
48
- for veri in secici.css("li.film"):
49
- title_el = veri.css_first("span.film-title")
50
- link_el = veri.css_first("a")
51
- img_el = veri.css_first("img")
52
-
53
- title = title_el.text(strip=True) if title_el else None
54
- href = link_el.attrs.get("href") if link_el else None
55
- poster = img_el.attrs.get("data-src") if img_el else None
47
+ for veri in secici.select("li.film"):
48
+ title = secici.select_text("span.film-title", veri)
49
+ href = secici.select_attr("a", "href", veri)
50
+ poster = secici.select_attr("img", "data-src", veri)
56
51
 
57
52
  if title and href:
58
53
  results.append(MainPageResult(
@@ -66,17 +61,13 @@ class FullHDFilmizlesene(PluginBase):
66
61
 
67
62
  async def search(self, query: str) -> list[SearchResult]:
68
63
  istek = await self.httpx.get(f"{self.main_url}/arama/{query}")
69
- secici = HTMLParser(istek.text)
64
+ secici = HTMLHelper(istek.text)
70
65
 
71
66
  results = []
72
- for film in secici.css("li.film"):
73
- title_el = film.css_first("span.film-title")
74
- link_el = film.css_first("a")
75
- img_el = film.css_first("img")
76
-
77
- title = title_el.text(strip=True) if title_el else None
78
- href = link_el.attrs.get("href") if link_el else None
79
- poster = img_el.attrs.get("data-src") if img_el else None
67
+ for film in secici.select("li.film"):
68
+ title = secici.select_text("span.film-title", film)
69
+ href = secici.select_attr("a", "href", film)
70
+ poster = secici.select_attr("img", "data-src", film)
80
71
 
81
72
  if title and href:
82
73
  results.append(SearchResult(
@@ -89,49 +80,42 @@ class FullHDFilmizlesene(PluginBase):
89
80
 
90
81
  async def load_item(self, url: str) -> MovieInfo:
91
82
  istek = await self.httpx.get(url)
92
- secici = HTMLParser(istek.text)
83
+ secici = HTMLHelper(istek.text)
93
84
  html_text = istek.text
94
85
 
95
86
  # Title: normalize-space yerine doğrudan class ile
96
- title_el = secici.css_first("div.izle-titles")
97
- title = title_el.text(strip=True) if title_el else ""
87
+ title = secici.select_text("div.izle-titles") or ""
98
88
 
99
- img_el = secici.css_first("div img[data-src]")
100
- poster = img_el.attrs.get("data-src", "").strip() if img_el else ""
89
+ poster = secici.select_attr("div img[data-src]", "data-src") or ""
90
+ poster = poster.strip()
101
91
 
102
- desc_el = secici.css_first("div.ozet-ic p")
103
- description = desc_el.text(strip=True) if desc_el else ""
92
+ description = secici.select_text("div.ozet-ic p") or ""
104
93
 
105
- tags = [a.text(strip=True) for a in secici.css("a[rel='category tag']") if a.text(strip=True)]
94
+ tags = secici.select_all_text("a[rel='category tag']")
106
95
 
107
96
  # Rating: normalize-space yerine doğrudan class ile ve son kelimeyi al
108
- rating_el = secici.css_first("div.puanx-puan")
97
+ rating_text = secici.select_text("div.puanx-puan") or None
109
98
  rating = None
110
- if rating_el:
111
- rating_text = rating_el.text(strip=True)
112
- if rating_text:
113
- parts = rating_text.split()
114
- rating = parts[-1] if parts else None
99
+ if rating_text:
100
+ parts = rating_text.split()
101
+ rating = parts[-1] if parts else None
115
102
 
116
103
  # Year: ilk yıl formatında değer
117
- year_el = secici.css_first("div.dd a.category")
104
+ year_text = secici.select_text("div.dd a.category") or None
118
105
  year = None
119
- if year_el:
120
- year_text = year_el.text(strip=True)
121
- if year_text:
122
- parts = year_text.split()
123
- year = parts[0] if parts else None
106
+ if year_text:
107
+ parts = year_text.split()
108
+ year = parts[0] if parts else None
124
109
 
125
110
  # Actors: nth-child yerine tüm li'leri alıp 2. index
126
- lis = secici.css("div.film-info ul li")
111
+ lis = secici.select("div.film-info ul li")
127
112
  actors = []
128
113
  if len(lis) >= 2:
129
- actors = [a.text(strip=True) for a in lis[1].css("a > span") if a.text(strip=True)]
114
+ actors = secici.select_all_text("a > span", lis[1])
130
115
 
131
- duration_el = secici.css_first("span.sure")
132
116
  duration = "0"
133
- if duration_el:
134
- duration_text = duration_el.text(strip=True)
117
+ duration_text = secici.select_text("span.sure") or None
118
+ if duration_text:
135
119
  duration_parts = duration_text.split()
136
120
  duration = duration_parts[0] if duration_parts else "0"
137
121
 
@@ -149,18 +133,18 @@ class FullHDFilmizlesene(PluginBase):
149
133
 
150
134
  async def load_links(self, url: str) -> list[ExtractResult]:
151
135
  istek = await self.httpx.get(url)
152
- secici = HTMLParser(istek.text)
136
+ secici = HTMLHelper(istek.text)
153
137
  html_text = istek.text
154
138
 
155
139
  # İlk script'i al (xpath (//script)[1] yerine)
156
- scripts = secici.css("script")
140
+ scripts = secici.select("script")
157
141
  script_content = scripts[0].text() if scripts else ""
158
142
 
159
- scx_match = re.search(r"scx = (.*?);", script_content)
160
- if not scx_match:
143
+ scx_json = HTMLHelper(script_content).regex_first(r"scx = (.*?);")
144
+ if not scx_json:
161
145
  return []
162
146
 
163
- scx_data = json.loads(scx_match.group(1))
147
+ scx_data = json.loads(scx_json)
164
148
  scx_keys = list(scx_data.keys())
165
149
 
166
150
  link_list = []