KekikStream 2.4.7__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.
@@ -1,10 +1,9 @@
1
1
  # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
2
 
3
3
  from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo, SeriesInfo, Episode, ExtractResult, HTMLHelper
4
- import re
5
4
 
6
- class Full4kizle(PluginBase):
7
- name = "Full4kizle"
5
+ class FilmciBaba(PluginBase):
6
+ name = "FilmciBaba"
8
7
  language = "tr"
9
8
  main_url = "https://izlehdfilm.cc"
10
9
  favicon = f"https://www.google.com/s2/favicons?domain={main_url}&sz=64"
@@ -35,81 +34,65 @@ class Full4kizle(PluginBase):
35
34
  f"{main_url}/Kategori/tur/18-erotik-filmler/page" : "+18 Erotik Filmler",
36
35
  }
37
36
 
38
-
39
37
  async def get_main_page(self, page: int, url: str, category: str) -> list[MainPageResult]:
40
- target_url = f"{url}/{page}/"
41
- istek = await self.httpx.get(target_url)
42
- helper = HTMLHelper(istek.text)
43
-
44
- items = helper.select("div.movie-preview")
45
- results = []
46
-
47
- for item in items:
48
- title_el = helper.select_first(".movie-title a", item)
49
- if not title_el: continue
50
-
51
- title = title_el.text(strip=True)
52
- # Remove " izle" case insensitive
53
- title = re.sub(r"(?i) izle", "", title).strip()
54
-
55
- href = self.fix_url(title_el.attrs.get("href"))
56
-
57
- poster_el = helper.select_first(".movie-poster img", item)
58
- poster = self.fix_url(poster_el.attrs.get("src")) if poster_el else None
59
-
38
+ istek = await self.httpx.get(f"{url}/{page}/")
39
+ secici = HTMLHelper(istek.text)
40
+
41
+ results = []
42
+ for item in secici.select("div.movie-preview"):
43
+ title_el = secici.select_first(".movie-title a", item)
44
+ if not title_el:
45
+ continue
46
+
47
+ title = self.clean_title(title_el.text(strip=True))
48
+ href = self.fix_url(title_el.attrs.get("href"))
49
+ poster = self.fix_url(secici.select_poster(".movie-poster img", item))
50
+
60
51
  results.append(MainPageResult(
61
52
  category = category,
62
53
  title = title,
63
54
  url = href,
64
55
  poster = poster
65
56
  ))
66
-
57
+
67
58
  return results
68
59
 
69
60
  async def search(self, query: str) -> list[SearchResult]:
70
- url = f"{self.main_url}/?s={query}"
71
- istek = await self.httpx.get(url)
72
- helper = HTMLHelper(istek.text)
73
-
74
- items = helper.select("div.movie-preview")
61
+ istek = await self.httpx.get(f"{self.main_url}/?s={query}")
62
+ secici = HTMLHelper(istek.text)
63
+
75
64
  results = []
76
-
77
- for item in items:
78
- title_el = helper.select_first(".movie-title a", item)
79
- if not title_el: continue
80
-
81
- title = title_el.text(strip=True)
82
- # Remove " izle" case insensitive
83
- title = re.sub(r"(?i) izle", "", title).strip()
84
-
85
- href = self.fix_url(title_el.attrs.get("href"))
86
-
87
- poster_el = helper.select_first(".movie-poster img", item)
88
- poster = self.fix_url(poster_el.attrs.get("src")) if poster_el else None
89
-
65
+ for item in secici.select("div.movie-preview"):
66
+ title_el = secici.select_first(".movie-title a", item)
67
+ if not title_el:
68
+ continue
69
+
70
+ title = self.clean_title(title_el.text(strip=True))
71
+ href = self.fix_url(title_el.attrs.get("href"))
72
+ poster = self.fix_url(secici.select_poster(".movie-poster img", item))
73
+
90
74
  results.append(SearchResult(
91
75
  title = title,
92
76
  url = href,
93
77
  poster = poster
94
78
  ))
95
-
79
+
96
80
  return results
97
81
 
98
82
  async def load_item(self, url: str) -> MovieInfo | SeriesInfo:
99
- istek = await self.httpx.get(url)
100
- helper = HTMLHelper(istek.text)
101
-
102
- title = self.clean_title(helper.select_text("h1"))
103
- poster = helper.select_poster(".poster img")
104
- description = helper.select_text(".excerpt p")
105
- year = helper.extract_year(".release", ".movie-info")
106
- rating = helper.regex_first(r"([\d\.]+)", helper.select_text(".imdb-rating"))
107
- duration = int(helper.regex_first(r"(\d+)", helper.select_text(".movie-info")) or 0)
108
- tags = helper.select_texts("a[href*='/tur/'], a[href*='/Kategori/tur/']")
109
- actors = helper.select_texts("a[href*='/oyuncular/']") or helper.select_texts(".cast-list .actor-name, .cast-list a")
83
+ istek = await self.httpx.get(url)
84
+ secici = HTMLHelper(istek.text)
85
+
86
+ title = self.clean_title(secici.select_text("h1"))
87
+ poster = secici.select_poster(".poster img")
88
+ description = secici.select_text(".excerpt p")
89
+ year = secici.extract_year(".release", ".movie-info")
90
+ rating = secici.regex_first(r"([\d\.]+)", secici.select_text(".imdb-rating"))
91
+ tags = secici.select_texts("div.categories a[href*='/Kategori/tur/']")
92
+ actors = secici.select_texts("a[href*='/oyuncular/']") or secici.select_texts(".cast-list .actor-name, .cast-list a")
110
93
 
111
94
  # Bölüm linklerini kontrol et
112
- ep_elements = helper.select(".parts-middle a, .parts-middle .part.active")
95
+ ep_elements = secici.select(".parts-middle a, .parts-middle .part.active")
113
96
 
114
97
  if not ep_elements:
115
98
  return MovieInfo(
@@ -118,17 +101,16 @@ class Full4kizle(PluginBase):
118
101
  description = description,
119
102
  poster = self.fix_url(poster),
120
103
  year = year,
121
- rating = rating,
122
- duration = duration,
104
+ rating = rating if rating != "." else None,
123
105
  tags = tags,
124
106
  actors = actors
125
107
  )
126
-
108
+
127
109
  episodes = []
128
110
  for i, el in enumerate(ep_elements):
129
- name = helper.select_text(".part-name", el) or f"Bölüm {i+1}"
111
+ name = secici.select_text(".part-name", el) or f"Bölüm {i+1}"
130
112
  href = el.attrs.get("href") or url
131
- s, e = helper.extract_season_episode(name)
113
+ s, e = secici.extract_season_episode(name)
132
114
  episodes.append(Episode(season=s or 1, episode=e or (i + 1), title=name, url=self.fix_url(href)))
133
115
 
134
116
  return SeriesInfo(
@@ -138,25 +120,24 @@ class Full4kizle(PluginBase):
138
120
  poster = self.fix_url(poster),
139
121
  year = year,
140
122
  rating = rating,
141
- duration = duration,
142
123
  tags = tags,
143
124
  actors = actors,
144
125
  episodes = episodes
145
126
  )
146
127
 
147
128
  async def load_links(self, url: str) -> list[ExtractResult]:
148
- istek = await self.httpx.get(url)
149
- helper = HTMLHelper(istek.text)
150
-
151
- iframe = helper.select_attr(".center-container iframe", "src")
129
+ istek = await self.httpx.get(url)
130
+ secici = HTMLHelper(istek.text)
131
+
132
+ iframe = secici.select_attr(".center-container iframe", "src")
152
133
  if not iframe:
153
- iframe = helper.select_attr("iframe[src*='hotstream.club']", "src")
154
-
134
+ iframe = secici.select_attr("iframe[src*='hotstream.club']", "src")
135
+
155
136
  results = []
156
-
137
+
157
138
  if iframe:
158
139
  iframe = self.fix_url(iframe)
159
-
140
+
160
141
  # Use general extract method
161
142
  extracted = await self.extract(iframe)
162
143
  if extracted:
@@ -166,9 +147,9 @@ class Full4kizle(PluginBase):
166
147
  results.append(extracted)
167
148
  else:
168
149
  results.append(ExtractResult(
169
- name = "Full4kizle | External",
170
- url = iframe,
150
+ name = "FilmciBaba | External",
151
+ url = iframe,
171
152
  referer = url
172
153
  ))
173
-
154
+
174
155
  return results
@@ -65,8 +65,8 @@ class FullHDFilmizlesene(PluginBase):
65
65
 
66
66
  results = []
67
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)
68
+ title = secici.select_text("span.film-title", film)
69
+ href = secici.select_attr("a", "href", film)
70
70
  poster = secici.select_attr("img", "data-src", film)
71
71
 
72
72
  if title and href:
@@ -84,12 +84,12 @@ class FullHDFilmizlesene(PluginBase):
84
84
 
85
85
  title = self.clean_title(secici.select_text("div.izle-titles"))
86
86
  poster = secici.select_poster("div img[data-src]")
87
- description = secici.select_text("div.ozet-ic p")
87
+ description = secici.select_text("div.ozet-ic")
88
88
  tags = secici.select_texts("a[rel='category tag']")
89
89
  rating = secici.regex_first(r"(\d+\.\d+|\d+)", secici.select_text("div.puanx-puan"))
90
90
  year = secici.extract_year("div.dd a.category")
91
91
  actors = secici.select_texts("a > span", secici.select_first("div.film-info ul li:nth-child(2)"))
92
- duration = int(secici.regex_first(r"(\d+)", secici.select_text("div.film-info ul li:nth-child(4)")) or 0)
92
+ duration = secici.regex_first(r"Süre: (\d+)\s*dk", secici.select_text("div.ozet-ic"))
93
93
 
94
94
  return MovieInfo(
95
95
  url = url,
@@ -106,10 +106,9 @@ class FullHDFilmizlesene(PluginBase):
106
106
  async def load_links(self, url: str) -> list[ExtractResult]:
107
107
  istek = await self.httpx.get(url)
108
108
  secici = HTMLHelper(istek.text)
109
- html_text = istek.text
110
109
 
111
110
  # İlk script'i al (xpath (//script)[1] yerine)
112
- scripts = secici.select("script")
111
+ scripts = secici.select("script")
113
112
  script_content = scripts[0].text() if scripts else ""
114
113
 
115
114
  scx_json = HTMLHelper(script_content).regex_first(r"scx = (.*?);")
@@ -133,4 +132,4 @@ class FullHDFilmizlesene(PluginBase):
133
132
  if data:
134
133
  response.append(data)
135
134
 
136
- return response
135
+ return response
@@ -0,0 +1,243 @@
1
+ # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
+
3
+ from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo, SeriesInfo, Episode, ExtractResult, Subtitle, HTMLHelper
4
+ import base64, asyncio, contextlib
5
+
6
+ class HDFilm(PluginBase):
7
+ name = "HDFilm"
8
+ language = "tr"
9
+ main_url = "https://hdfilm.us"
10
+ favicon = f"https://www.google.com/s2/favicons?domain={main_url}&sz=64"
11
+ description = "Full HD Film izle, Türkçe Dublaj ve Altyazılı filmler."
12
+
13
+ main_page = {
14
+ f"{main_url}/tur/turkce-altyazili-film-izle" : "Altyazılı Filmler",
15
+ f"{main_url}/tur/netflix-filmleri-izle" : "Netflix",
16
+ f"{main_url}/tur/yerli-film-izle" : "Yerli Film",
17
+ f"{main_url}/category/aile-filmleri-izle" : "Aile",
18
+ f"{main_url}/category/aksiyon-filmleri-izle" : "Aksiyon",
19
+ f"{main_url}/category/animasyon-filmleri-izle" : "Animasyon",
20
+ f"{main_url}/category/belgesel-filmleri-izle" : "Belgesel",
21
+ f"{main_url}/category/bilim-kurgu-filmleri-izle" : "Bilim Kurgu",
22
+ f"{main_url}/category/biyografi-filmleri-izle" : "Biyografi",
23
+ f"{main_url}/category/dram-filmleri-izle" : "Dram",
24
+ f"{main_url}/category/fantastik-filmler-izle" : "Fantastik",
25
+ f"{main_url}/category/gerilim-filmleri-izle" : "Gerilim",
26
+ f"{main_url}/category/gizem-filmleri-izle" : "Gizem",
27
+ f"{main_url}/category/kisa" : "Kısa",
28
+ f"{main_url}/category/komedi-filmleri-izle" : "Komedi",
29
+ f"{main_url}/category/korku-filmleri-izle" : "Korku",
30
+ f"{main_url}/category/macera-filmleri-izle" : "Macera",
31
+ f"{main_url}/category/muzik" : "Müzik",
32
+ f"{main_url}/category/muzikal-filmleri-izle" : "Müzikal",
33
+ f"{main_url}/category/romantik-filmler-izle" : "Romantik",
34
+ f"{main_url}/category/savas-filmleri-izle" : "Savaş",
35
+ f"{main_url}/category/spor-filmleri-izle" : "Spor",
36
+ f"{main_url}/category/suc-filmleri-izle" : "Suç",
37
+ f"{main_url}/category/tarih-filmleri-izle" : "Tarih",
38
+ f"{main_url}/category/western-filmleri-izle" : "Western",
39
+ }
40
+
41
+ async def get_main_page(self, page: int, url: str, category: str) -> list[MainPageResult]:
42
+ istek = await self.httpx.get(url if page == 1 else f"{url}/page/{page}")
43
+ secici = HTMLHelper(istek.text)
44
+
45
+ results = []
46
+ for veri in secici.select("div.movie-poster"):
47
+ title = secici.select_attr("img", "alt", veri)
48
+ poster = secici.select_attr("img", "src", veri)
49
+ href = secici.select_attr("a", "href", veri)
50
+
51
+ if title and href:
52
+ results.append(MainPageResult(
53
+ category = category,
54
+ title = self.clean_title(title),
55
+ url = self.fix_url(href),
56
+ poster = self.fix_url(poster)
57
+ ))
58
+
59
+ return results
60
+
61
+ async def search(self, query: str) -> list[SearchResult]:
62
+ istek = await self.httpx.get(f"{self.main_url}/?s={query}")
63
+ secici = HTMLHelper(istek.text)
64
+
65
+ results = []
66
+ for veri in secici.select("div.movie-poster"):
67
+ title = secici.select_attr("img", "alt", veri)
68
+ poster = secici.select_attr("img", "src", veri)
69
+ href = secici.select_attr("a", "href", veri)
70
+
71
+ if title and href:
72
+ results.append(SearchResult(
73
+ title = self.clean_title(title),
74
+ url = self.fix_url(href),
75
+ poster = self.fix_url(poster)
76
+ ))
77
+
78
+ return results
79
+
80
+ async def load_item(self, url: str) -> MovieInfo | SeriesInfo:
81
+ istek = await self.httpx.get(url)
82
+ secici = HTMLHelper(istek.text)
83
+
84
+ title = self.clean_title(secici.select_text("h1"))
85
+ poster = secici.select_poster("div.poster img")
86
+ description = secici.select_text("div.film") or secici.select_attr("meta[property='og:description']", "content")
87
+ year = secici.extract_year("div.yayin-tarihi.info") or secici.regex_first(r"\((\d{4})\)")
88
+ tags = secici.select_texts("div.tur.info a")
89
+ rating = secici.regex_first(r"IMDb\s*([\d\.]+)", secici.select_text("div.imdb"))
90
+ actors = secici.select_direct_text("div.oyuncular")
91
+
92
+ is_series = "-dizi" in url.lower() or any("dizi" in tag.lower() for tag in tags)
93
+ if is_series:
94
+ episodes = []
95
+ for idx, el in enumerate(secici.select("li.psec")):
96
+ part_id = el.attrs.get("id")
97
+ part_name = secici.select_text("a", el) or ""
98
+ if not part_name or "fragman" in part_name.lower():
99
+ continue
100
+
101
+ s, e = secici.extract_season_episode(f"{part_id} {part_name}")
102
+ episodes.append(Episode(
103
+ season = s or 1,
104
+ episode = e or (idx+1),
105
+ title = f"{s or 1}. Sezon {e or idx+1}. Bölüm",
106
+ url = url
107
+ ))
108
+
109
+ return SeriesInfo(
110
+ url = url,
111
+ poster = self.fix_url(poster),
112
+ title = title,
113
+ description = description,
114
+ tags = tags,
115
+ year = year,
116
+ actors = actors,
117
+ rating = rating,
118
+ episodes = episodes
119
+ )
120
+
121
+ return MovieInfo(
122
+ url = url,
123
+ poster = self.fix_url(poster),
124
+ title = title,
125
+ description = description,
126
+ tags = tags,
127
+ year = year,
128
+ actors = actors,
129
+ rating = rating
130
+ )
131
+
132
+ def _get_iframe(self, source_code: str) -> str:
133
+ """Base64 kodlu iframe'i çözümle"""
134
+ script_val = HTMLHelper(source_code).regex_first(r'<script[^>]*>(PCEtLWJhc2xpazp[^<]*)</script>')
135
+ if not script_val:
136
+ return ""
137
+
138
+ try:
139
+ decoded_html = base64.b64decode(script_val).decode("utf-8")
140
+ iframe_src = HTMLHelper(decoded_html).regex_first(r'<iframe[^>]+src=["\']([^"\']+)["\']')
141
+ return self.fix_url(iframe_src) if iframe_src else ""
142
+ except Exception:
143
+ return ""
144
+
145
+ def _extract_subtitle_url(self, source_code: str) -> str | None:
146
+ """playerjsSubtitle değişkeninden .srt URL çıkar"""
147
+ patterns = [
148
+ r'var playerjsSubtitle = "\[Türkçe\](https?://[^\s"]+?\.srt)";',
149
+ r'var playerjsSubtitle = "(https?://[^\s"]+?\.srt)";',
150
+ r'subtitle:\s*"(https?://[^\s"]+?\.srt)"',
151
+ ]
152
+
153
+ for pattern in patterns:
154
+ val = HTMLHelper(source_code).regex_first(pattern)
155
+ if val:
156
+ return val
157
+
158
+ return None
159
+
160
+ async def _get_source_links(self, url: str, initial_text: str | None = None) -> list[ExtractResult]:
161
+ results = []
162
+ try:
163
+ if initial_text:
164
+ source_code = initial_text
165
+ secici = HTMLHelper(source_code)
166
+ else:
167
+ resp = await self.httpx.get(url)
168
+ source_code = resp.text
169
+ secici = HTMLHelper(source_code)
170
+
171
+ iframe_src = self._get_iframe(source_code)
172
+ subtitle_url = self._extract_subtitle_url(source_code)
173
+
174
+ # İsim Oluştur (Dil | Player)
175
+ parts = []
176
+
177
+ if action_parts := secici.select_first("div#action-parts"):
178
+ # Aktif olan wrapper'ları bul
179
+ for wrapper in secici.select("div.button-custom-wrapper", action_parts):
180
+ # Aktif buton/link
181
+ active_el = secici.select_first("button", wrapper) or secici.select_first("a.button", wrapper)
182
+ if active_el:
183
+ parts.append(active_el.text(strip=True))
184
+
185
+ final_name = " | ".join(parts) if parts else "HDFilm"
186
+
187
+ if not subtitle_url and iframe_src:
188
+ with contextlib.suppress(Exception):
189
+ iframe_istek = await self.httpx.get(iframe_src)
190
+ subtitle_url = self._extract_subtitle_url(iframe_istek.text)
191
+
192
+ if iframe_src:
193
+ data = await self.extract(iframe_src, name_override=final_name)
194
+ if data:
195
+ sub = Subtitle(name="Türkçe", url=subtitle_url) if subtitle_url else None
196
+ if isinstance(data, list):
197
+ for d in data:
198
+ if sub:
199
+ d.subtitles.append(sub)
200
+ results.append(d)
201
+ else:
202
+ if sub:
203
+ data.subtitles.append(sub)
204
+ results.append(data)
205
+
206
+ return results
207
+ except Exception:
208
+ return []
209
+
210
+ async def load_links(self, url: str) -> list[ExtractResult]:
211
+ initial_istek = await self.httpx.get(url)
212
+ initial_text = initial_istek.text
213
+ secici = HTMLHelper(initial_text)
214
+
215
+ base_url = url.split("?")[0].rstrip("/")
216
+ unique_urls = {base_url} # ?page=1 varsa da base_url olarak sakla
217
+
218
+ if action_parts := secici.select_first("div#action-parts"):
219
+ for link in secici.select("a[href]", action_parts):
220
+ href = link.attrs.get("href", "")
221
+ if "?page=" in href:
222
+ if href.endswith("?page=1") or href == "?page=1":
223
+ unique_urls.add(base_url)
224
+ elif href.startswith("?"):
225
+ unique_urls.add(f"{base_url}{href}")
226
+ else:
227
+ unique_urls.add(self.fix_url(href))
228
+
229
+ tasks = []
230
+ for p_url in unique_urls:
231
+ # Eğer p_url şu anki url ile eşleşiyorsa (veya ?page=1 farkı varsa) metni kullan
232
+ # Basit eşleşme: Eğer p_url == base_url ve (url == base_url veya url == base_url + "?page=1")
233
+
234
+ use_initial = False
235
+ if p_url == base_url:
236
+ if url.rstrip("/") == base_url or url.rstrip("/") == f"{base_url}?page=1":
237
+ use_initial = True
238
+ elif p_url == url.rstrip("/"):
239
+ use_initial = True
240
+
241
+ tasks.append(self._get_source_links(p_url, initial_text if use_initial else None))
242
+
243
+ return [item for sublist in await asyncio.gather(*tasks) for item in sublist]