KekikStream 2.4.1__py3-none-any.whl → 2.4.3__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.
- KekikStream/Core/Extractor/ExtractorBase.py +3 -2
- KekikStream/Core/HTMLHelper.py +134 -40
- KekikStream/Core/Plugin/PluginBase.py +3 -2
- KekikStream/Extractors/CloseLoad.py +30 -54
- KekikStream/Extractors/ContentX.py +27 -72
- KekikStream/Extractors/DonilasPlay.py +33 -77
- KekikStream/Extractors/DzenRu.py +10 -24
- KekikStream/Extractors/ExPlay.py +20 -38
- KekikStream/Extractors/Filemoon.py +19 -45
- KekikStream/Extractors/HDMomPlayer.py +24 -56
- KekikStream/Extractors/HDPlayerSystem.py +13 -31
- KekikStream/Extractors/HotStream.py +14 -32
- KekikStream/Extractors/JFVid.py +3 -24
- KekikStream/Extractors/JetTv.py +21 -34
- KekikStream/Extractors/MailRu.py +11 -29
- KekikStream/Extractors/MixPlayHD.py +15 -28
- KekikStream/Extractors/MixTiger.py +17 -40
- KekikStream/Extractors/MolyStream.py +17 -21
- KekikStream/Extractors/Odnoklassniki.py +28 -104
- KekikStream/Extractors/PeaceMakerst.py +18 -45
- KekikStream/Extractors/PixelDrain.py +8 -16
- KekikStream/Extractors/PlayerFilmIzle.py +22 -41
- KekikStream/Extractors/RapidVid.py +21 -35
- KekikStream/Extractors/SetPlay.py +18 -43
- KekikStream/Extractors/SibNet.py +7 -17
- KekikStream/Extractors/Sobreatsesuyp.py +23 -45
- KekikStream/Extractors/TRsTX.py +23 -53
- KekikStream/Extractors/TurboImgz.py +7 -14
- KekikStream/Extractors/VCTPlay.py +10 -28
- KekikStream/Extractors/VidHide.py +10 -31
- KekikStream/Extractors/VidMoly.py +65 -99
- KekikStream/Extractors/VidMoxy.py +16 -27
- KekikStream/Extractors/VidPapi.py +24 -54
- KekikStream/Extractors/VideoSeyred.py +19 -40
- KekikStream/Extractors/Videostr.py +42 -99
- KekikStream/Extractors/Vidoza.py +8 -15
- KekikStream/Extractors/YildizKisaFilm.py +13 -31
- KekikStream/Plugins/BelgeselX.py +63 -69
- KekikStream/Plugins/DiziBox.py +16 -36
- KekikStream/Plugins/DiziMom.py +37 -129
- KekikStream/Plugins/DiziPal.py +26 -75
- KekikStream/Plugins/DiziYou.py +44 -152
- KekikStream/Plugins/Dizilla.py +18 -44
- KekikStream/Plugins/FilmBip.py +10 -24
- KekikStream/Plugins/FilmEkseni.py +12 -32
- KekikStream/Plugins/FilmMakinesi.py +24 -77
- KekikStream/Plugins/FilmModu.py +11 -18
- KekikStream/Plugins/Filmatek.py +13 -39
- KekikStream/Plugins/Full4kizle.py +33 -133
- KekikStream/Plugins/FullHDFilm.py +23 -93
- KekikStream/Plugins/FullHDFilmizlesene.py +10 -29
- KekikStream/Plugins/HDFilmCehennemi.py +27 -66
- KekikStream/Plugins/JetFilmizle.py +19 -20
- KekikStream/Plugins/KultFilmler.py +16 -50
- KekikStream/Plugins/RecTV.py +47 -85
- KekikStream/Plugins/SelcukFlix.py +29 -47
- KekikStream/Plugins/SetFilmIzle.py +28 -84
- KekikStream/Plugins/SezonlukDizi.py +27 -59
- KekikStream/Plugins/Sinefy.py +37 -100
- KekikStream/Plugins/SinemaCX.py +12 -18
- KekikStream/Plugins/Sinezy.py +12 -13
- KekikStream/Plugins/SuperFilmGeldi.py +8 -13
- KekikStream/Plugins/UgurFilm.py +14 -14
- KekikStream/Plugins/Watch32.py +42 -74
- KekikStream/Plugins/YabanciDizi.py +33 -87
- {kekikstream-2.4.1.dist-info → kekikstream-2.4.3.dist-info}/METADATA +1 -1
- kekikstream-2.4.3.dist-info/RECORD +93 -0
- {kekikstream-2.4.1.dist-info → kekikstream-2.4.3.dist-info}/WHEEL +1 -1
- kekikstream-2.4.1.dist-info/RECORD +0 -93
- {kekikstream-2.4.1.dist-info → kekikstream-2.4.3.dist-info}/entry_points.txt +0 -0
- {kekikstream-2.4.1.dist-info → kekikstream-2.4.3.dist-info}/licenses/LICENSE +0 -0
- {kekikstream-2.4.1.dist-info → kekikstream-2.4.3.dist-info}/top_level.txt +0 -0
|
@@ -187,54 +187,55 @@ class SelcukFlix(PluginBase):
|
|
|
187
187
|
|
|
188
188
|
next_data_text = sel.select_text("script#__NEXT_DATA__")
|
|
189
189
|
if not next_data_text:
|
|
190
|
-
return SeriesInfo(url=url, title=sel.select_text("h1") or "Bilinmeyen")
|
|
190
|
+
return SeriesInfo(url=url, title=self.clean_title(sel.select_text("h1")) or "Bilinmeyen")
|
|
191
191
|
|
|
192
192
|
try:
|
|
193
193
|
next_data = json.loads(next_data_text)
|
|
194
194
|
secure_data_raw = next_data["props"]["pageProps"].get("secureData")
|
|
195
195
|
if not secure_data_raw:
|
|
196
|
-
|
|
196
|
+
return SeriesInfo(url=url, title=self.clean_title(sel.select_text("h1")) or "Bilinmeyen")
|
|
197
197
|
|
|
198
198
|
# Clean possible quotes from string before decoding
|
|
199
199
|
if isinstance(secure_data_raw, str):
|
|
200
200
|
secure_data_raw = secure_data_raw.strip('"')
|
|
201
201
|
|
|
202
|
-
|
|
203
|
-
content_details = json.loads(
|
|
204
|
-
|
|
205
|
-
# Sometimes content_details might be a string (double encoded)
|
|
206
|
-
if isinstance(content_details, str):
|
|
207
|
-
content_details = json.loads(content_details)
|
|
202
|
+
content_details = json.loads(base64.b64decode(secure_data_raw).decode('utf-8'))
|
|
203
|
+
if isinstance(content_details, str): content_details = json.loads(content_details)
|
|
208
204
|
|
|
209
|
-
print(f"DEBUG: type(content_details)={type(content_details)}")
|
|
210
205
|
item = content_details.get("contentItem", {})
|
|
211
|
-
print(f"DEBUG: type(item)={type(item)}")
|
|
212
206
|
related_results = content_details.get("RelatedResults", {})
|
|
213
207
|
|
|
214
|
-
title
|
|
215
|
-
poster
|
|
216
|
-
description
|
|
217
|
-
rating
|
|
218
|
-
year
|
|
219
|
-
duration
|
|
208
|
+
title = self.clean_title(item.get("original_title") or item.get("culture_title") or item.get("originalTitle") or "")
|
|
209
|
+
poster = self.clean_image_url(item.get("poster_url") or item.get("posterUrl") or item.get("face_url"))
|
|
210
|
+
description = item.get("description") or item.get("used_description")
|
|
211
|
+
rating = str(item.get("imdb_point") or item.get("imdbPoint") or "")
|
|
212
|
+
year = str(item.get("release_year") or item.get("releaseYear") or "")
|
|
213
|
+
duration = item.get("total_minutes") or item.get("totalMinutes")
|
|
220
214
|
|
|
221
215
|
tags = []
|
|
222
216
|
tags_raw = item.get("category_names") or item.get("categoryNames") or item.get("categories")
|
|
223
217
|
if isinstance(tags_raw, str):
|
|
224
|
-
tags = [t.strip() for t in tags_raw.split(",")]
|
|
218
|
+
tags = [t.strip() for t in tags_raw.split(",") if t.strip()]
|
|
225
219
|
elif isinstance(tags_raw, list):
|
|
226
220
|
tags = [c.get("title") if isinstance(c, dict) else str(c) for c in tags_raw]
|
|
227
221
|
|
|
228
222
|
actors = []
|
|
229
|
-
actors_raw = item.get("actor_names") or item.get("actorNames")
|
|
230
|
-
if isinstance(actors_raw, str):
|
|
231
|
-
actors = [a.strip() for a in actors_raw.split(",")]
|
|
232
|
-
|
|
233
|
-
# Casts from RelatedResults
|
|
234
223
|
casts_data = related_results.get("getSerieCastsById") or related_results.get("getMovieCastsById")
|
|
235
224
|
if casts_data and isinstance(casts_data, dict) and casts_data.get("result"):
|
|
236
225
|
actors = [cast.get("name") for cast in casts_data["result"] if cast.get("name")]
|
|
237
226
|
|
|
227
|
+
common_info = {
|
|
228
|
+
"url" : url,
|
|
229
|
+
"poster" : poster,
|
|
230
|
+
"title" : title or "Bilinmiyor",
|
|
231
|
+
"description" : description,
|
|
232
|
+
"tags" : tags,
|
|
233
|
+
"rating" : rating,
|
|
234
|
+
"year" : year,
|
|
235
|
+
"actors" : actors,
|
|
236
|
+
"duration" : duration
|
|
237
|
+
}
|
|
238
|
+
|
|
238
239
|
series_data = related_results.get("getSerieSeasonAndEpisodes")
|
|
239
240
|
if series_data and isinstance(series_data, dict) and series_data.get("result"):
|
|
240
241
|
episodes = []
|
|
@@ -249,31 +250,12 @@ class SelcukFlix(PluginBase):
|
|
|
249
250
|
title = ep.get("ep_text") or ep.get("epText") or "",
|
|
250
251
|
url = self.fix_url(ep_slug)
|
|
251
252
|
))
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
|
|
257
|
-
|
|
258
|
-
tags = tags,
|
|
259
|
-
rating = rating,
|
|
260
|
-
year = year,
|
|
261
|
-
actors = actors,
|
|
262
|
-
duration = duration,
|
|
263
|
-
episodes = episodes
|
|
264
|
-
)
|
|
265
|
-
else:
|
|
266
|
-
return MovieInfo(
|
|
267
|
-
url = url,
|
|
268
|
-
poster = poster,
|
|
269
|
-
title = self.clean_title(title),
|
|
270
|
-
description = description,
|
|
271
|
-
tags = tags,
|
|
272
|
-
rating = rating,
|
|
273
|
-
year = year,
|
|
274
|
-
actors = actors,
|
|
275
|
-
duration = duration
|
|
276
|
-
)
|
|
253
|
+
return SeriesInfo(**common_info, episodes=episodes)
|
|
254
|
+
|
|
255
|
+
return MovieInfo(**common_info)
|
|
256
|
+
|
|
257
|
+
except Exception:
|
|
258
|
+
return SeriesInfo(url=url, title=self.clean_title(sel.select_text("h1")) or "Bilinmeyen")
|
|
277
259
|
|
|
278
260
|
except Exception:
|
|
279
261
|
return SeriesInfo(url=url, title=self.clean_title(sel.select_text("h1")) or "Bilinmeyen")
|
|
@@ -125,95 +125,39 @@ class SetFilmIzle(PluginBase):
|
|
|
125
125
|
async def load_item(self, url: str) -> MovieInfo | SeriesInfo:
|
|
126
126
|
istek = self.cloudscraper.get(url)
|
|
127
127
|
secici = HTMLHelper(istek.text)
|
|
128
|
-
html_text = istek.text
|
|
129
|
-
|
|
130
|
-
raw_title = secici.select_text("h1") or secici.select_text(".titles h1") or secici.select_attr("meta[property='og:title']", "content") or ""
|
|
131
|
-
title = HTMLHelper(raw_title).regex_replace(r"(?i)\s*izle.*$", "", flags=0).strip()
|
|
132
|
-
|
|
133
|
-
poster = secici.select_attr("div.poster img", "src")
|
|
134
128
|
|
|
129
|
+
title = self.clean_title(secici.select_text("h1") or secici.select_text(".titles h1") or secici.select_attr("meta[property='og:title']", "content"))
|
|
130
|
+
poster = secici.select_poster("div.poster img")
|
|
135
131
|
description = secici.select_text("div.wp-content p")
|
|
132
|
+
rating = secici.select_text("b#repimdb strong") or secici.regex_first(r"([\d.]+)", secici.select_text("div.imdb"))
|
|
133
|
+
year = secici.extract_year("div.extra span.valor")
|
|
134
|
+
tags = secici.select_texts("div.sgeneros a")
|
|
135
|
+
duration = int(secici.regex_first(r"(\d+)", secici.select_text("span.runtime")) or 0)
|
|
136
|
+
actors = secici.select_texts("span.valor a[href*='/oyuncu/']")
|
|
137
|
+
|
|
138
|
+
common_info = {
|
|
139
|
+
"url" : url,
|
|
140
|
+
"poster" : self.fix_url(poster) if poster else None,
|
|
141
|
+
"title" : title or "Bilinmiyor",
|
|
142
|
+
"description" : description,
|
|
143
|
+
"tags" : tags,
|
|
144
|
+
"rating" : rating,
|
|
145
|
+
"year" : str(year) if year else None,
|
|
146
|
+
"duration" : duration,
|
|
147
|
+
"actors" : actors
|
|
148
|
+
}
|
|
136
149
|
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
# Yıl için info bölümünden veya regex ile yakala
|
|
140
|
-
year = secici.regex_first(r'(\d{4})', secici.select_text("div.extra span.valor") or secici.select_text("span.valor") or "")
|
|
141
|
-
if not year:
|
|
142
|
-
year = secici.regex_first(r'<span>(\d{4})</span>', html_text) or secici.regex_first(r'(\d{4})', html_text)
|
|
143
|
-
|
|
144
|
-
tags = [a.text(strip=True) for a in secici.select("div.sgeneros a") if a.text(strip=True)]
|
|
145
|
-
|
|
146
|
-
duration_text = secici.select_text("span.runtime")
|
|
147
|
-
duration = int(secici.regex_first(r"\d+", duration_text)) if duration_text and secici.regex_first(r"\d+", duration_text) else None
|
|
148
|
-
|
|
149
|
-
actors = [a.text(strip=True) for a in secici.select("span.valor a") if "/oyuncu/" in (a.attrs.get("href") or "")]
|
|
150
|
-
if not actors:
|
|
151
|
-
actors = secici.regex_all(r'href="[^"]*/oyuncu/[^"]*">([^<]+)</a>')
|
|
152
|
-
|
|
153
|
-
trailer = None
|
|
154
|
-
if trailer_id := secici.regex_first(r'embed/([^?]*)\?rel', html_text):
|
|
155
|
-
trailer = f"https://www.youtube.com/embed/{trailer_id}"
|
|
156
|
-
|
|
157
|
-
# Dizi mi film mi kontrol et
|
|
158
|
-
is_series = "/dizi/" in url
|
|
159
|
-
|
|
160
|
-
if is_series:
|
|
161
|
-
year_elem = secici.select_text("a[href*='/yil/']")
|
|
162
|
-
if year_elem:
|
|
163
|
-
year = secici.regex_first(r"\d{4}", year_elem) or year
|
|
164
|
-
|
|
165
|
-
# Duration from info section
|
|
166
|
-
for span in secici.select("div#info span"):
|
|
167
|
-
span_text = span.text(strip=True) if span.text() else ""
|
|
168
|
-
if "Dakika" in span_text:
|
|
169
|
-
duration = secici.regex_first(r"\d+", span_text) and int(secici.regex_first(r"\d+", span_text))
|
|
170
|
-
break
|
|
171
|
-
|
|
150
|
+
if "/dizi/" in url:
|
|
172
151
|
episodes = []
|
|
173
152
|
for ep_item in secici.select("div#episodes ul.episodios li"):
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
ep_episode = secici.regex_first(r"Sezon\s+(\d+)\.\s*Bölüm", ep_detail)
|
|
183
|
-
|
|
184
|
-
ep_season = int(ep_season) if isinstance(ep_season, str) and ep_season.isdigit() else 1
|
|
185
|
-
ep_episode = int(ep_episode) if isinstance(ep_episode, str) and ep_episode.isdigit() else None
|
|
186
|
-
|
|
187
|
-
episodes.append(Episode(
|
|
188
|
-
season = ep_season,
|
|
189
|
-
episode = ep_episode,
|
|
190
|
-
title = ep_name,
|
|
191
|
-
url = self.fix_url(ep_href)
|
|
192
|
-
))
|
|
193
|
-
return SeriesInfo(
|
|
194
|
-
url = url,
|
|
195
|
-
poster = self.fix_url(poster) if poster else None,
|
|
196
|
-
title = title,
|
|
197
|
-
description = description,
|
|
198
|
-
tags = tags,
|
|
199
|
-
rating = rating,
|
|
200
|
-
year = year,
|
|
201
|
-
duration = duration,
|
|
202
|
-
actors = actors,
|
|
203
|
-
episodes = episodes
|
|
204
|
-
)
|
|
205
|
-
|
|
206
|
-
return MovieInfo(
|
|
207
|
-
url = url,
|
|
208
|
-
poster = self.fix_url(poster) if poster else None,
|
|
209
|
-
title = title,
|
|
210
|
-
description = description,
|
|
211
|
-
tags = tags,
|
|
212
|
-
rating = rating,
|
|
213
|
-
year = year,
|
|
214
|
-
duration = duration,
|
|
215
|
-
actors = actors
|
|
216
|
-
)
|
|
153
|
+
href = secici.select_attr("h4.episodiotitle a", "href", ep_item)
|
|
154
|
+
name = secici.select_direct_text("h4.episodiotitle a", ep_item)
|
|
155
|
+
if href and name:
|
|
156
|
+
s, e = secici.extract_season_episode(name)
|
|
157
|
+
episodes.append(Episode(season=s or 1, episode=e or 1, title=name, url=self.fix_url(href)))
|
|
158
|
+
return SeriesInfo(**common_info, episodes=episodes)
|
|
159
|
+
|
|
160
|
+
return MovieInfo(**common_info)
|
|
217
161
|
|
|
218
162
|
async def load_links(self, url: str) -> list[ExtractResult]:
|
|
219
163
|
istek = await self.httpx.get(url)
|
|
@@ -70,7 +70,7 @@ class SezonlukDizi(PluginBase):
|
|
|
70
70
|
return results
|
|
71
71
|
|
|
72
72
|
async def search(self, query: str) -> list[SearchResult]:
|
|
73
|
-
istek = await self.httpx.get(f"{self.main_url}/diziler.asp?
|
|
73
|
+
istek = await self.httpx.get(f"{self.main_url}/diziler.asp?q={query}")
|
|
74
74
|
secici = HTMLHelper(istek.text)
|
|
75
75
|
|
|
76
76
|
results = []
|
|
@@ -92,63 +92,31 @@ class SezonlukDizi(PluginBase):
|
|
|
92
92
|
istek = await self.httpx.get(url)
|
|
93
93
|
secici = HTMLHelper(istek.text)
|
|
94
94
|
|
|
95
|
-
title
|
|
96
|
-
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
#
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
episodes_istek = await self.httpx.get(f"{self.main_url}/bolumler/{url.split('/')[-1]}")
|
|
122
|
-
episodes_secici = HTMLHelper(episodes_istek.text)
|
|
123
|
-
episodes = []
|
|
124
|
-
|
|
125
|
-
for sezon in episodes_secici.select("table.unstackable"):
|
|
126
|
-
for bolum in episodes_secici.select("tbody tr", sezon):
|
|
127
|
-
# td:nth-of-type selectolax'ta desteklenmiyor, alternatif yol: tüm td'leri alıp indexle
|
|
128
|
-
tds = episodes_secici.select("td", bolum)
|
|
129
|
-
if len(tds) < 4:
|
|
130
|
-
continue
|
|
131
|
-
|
|
132
|
-
# 4. td'den isim ve href
|
|
133
|
-
ep_name = episodes_secici.select_text("a", tds[3])
|
|
134
|
-
ep_href = episodes_secici.select_attr("a", "href", tds[3])
|
|
135
|
-
|
|
136
|
-
# 3. td'den episode (re_first yerine regex)
|
|
137
|
-
ep_episode_text = episodes_secici.select_text("a", tds[2]) or ""
|
|
138
|
-
ep_episode = episodes_secici.regex_first(r"(\d+)", ep_episode_text)
|
|
139
|
-
|
|
140
|
-
# 2. td'den season (re_first yerine regex)
|
|
141
|
-
ep_season_text = tds[1].text(strip=True) if tds[1] else ""
|
|
142
|
-
ep_season = secici.regex_first(r"(\d+)", ep_season_text)
|
|
143
|
-
|
|
144
|
-
if ep_name and ep_href:
|
|
145
|
-
episode = Episode(
|
|
146
|
-
season = ep_season,
|
|
147
|
-
episode = ep_episode,
|
|
148
|
-
title = ep_name,
|
|
149
|
-
url = self.fix_url(ep_href),
|
|
150
|
-
)
|
|
151
|
-
episodes.append(episode)
|
|
95
|
+
title = secici.select_text("div.header") or ""
|
|
96
|
+
poster = secici.select_poster("div.image img")
|
|
97
|
+
year = secici.extract_year("div.extra span")
|
|
98
|
+
description = secici.select_text("span#tartismayorum-konu")
|
|
99
|
+
tags = secici.select_texts("div.labels a[href*='tur']")
|
|
100
|
+
rating = secici.regex_first(r"[\d.,]+", secici.select_text("div.dizipuani a div"))
|
|
101
|
+
|
|
102
|
+
# Actors extraction
|
|
103
|
+
id_slug = url.split('/')[-1]
|
|
104
|
+
a_resp = await self.httpx.get(f"{self.main_url}/oyuncular/{id_slug}")
|
|
105
|
+
a_sel = HTMLHelper(a_resp.text)
|
|
106
|
+
actors = a_sel.select_texts("div.doubling div.ui div.header")
|
|
107
|
+
|
|
108
|
+
# Episodes extraction
|
|
109
|
+
e_resp = await self.httpx.get(f"{self.main_url}/bolumler/{id_slug}")
|
|
110
|
+
e_sel = HTMLHelper(e_resp.text)
|
|
111
|
+
episodes = []
|
|
112
|
+
for row in e_sel.select("table.unstackable tbody tr"):
|
|
113
|
+
tds = e_sel.select("td", row)
|
|
114
|
+
if len(tds) >= 4:
|
|
115
|
+
name = e_sel.select_text("a", tds[3])
|
|
116
|
+
href = e_sel.select_attr("a", "href", tds[3])
|
|
117
|
+
if name and href:
|
|
118
|
+
s, e = e_sel.extract_season_episode(f"{tds[1].text(strip=True)} {tds[2].text(strip=True)}")
|
|
119
|
+
episodes.append(Episode(season=s or 1, episode=e or 1, title=name, url=self.fix_url(href)))
|
|
152
120
|
|
|
153
121
|
return SeriesInfo(
|
|
154
122
|
url = url,
|
|
@@ -157,7 +125,7 @@ class SezonlukDizi(PluginBase):
|
|
|
157
125
|
description = description,
|
|
158
126
|
tags = tags,
|
|
159
127
|
rating = rating,
|
|
160
|
-
year = year,
|
|
128
|
+
year = str(year) if year else None,
|
|
161
129
|
episodes = episodes,
|
|
162
130
|
actors = actors
|
|
163
131
|
)
|
KekikStream/Plugins/Sinefy.py
CHANGED
|
@@ -135,114 +135,51 @@ class Sinefy(PluginBase):
|
|
|
135
135
|
pass
|
|
136
136
|
return []
|
|
137
137
|
|
|
138
|
-
async def load_item(self, url: str) -> SeriesInfo:
|
|
138
|
+
async def load_item(self, url: str) -> SeriesInfo | MovieInfo:
|
|
139
139
|
resp = await self.httpx.get(url)
|
|
140
140
|
sel = HTMLHelper(resp.text)
|
|
141
141
|
|
|
142
|
-
title
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
if "1x" in p:
|
|
150
|
-
poster = p.strip().split(" ")[0]
|
|
151
|
-
break
|
|
152
|
-
|
|
142
|
+
title = sel.select_direct_text("h1")
|
|
143
|
+
poster_attr = sel.select_attr("img.series-profile-thumb", "data-srcset") or sel.select_attr("img.series-profile-thumb", "srcset")
|
|
144
|
+
if poster_attr:
|
|
145
|
+
# "url 1x, url 2x" -> en sondakini (en yüksek kalite) al
|
|
146
|
+
poster = poster_attr.split(",")[-1].strip().split(" ")[0]
|
|
147
|
+
else:
|
|
148
|
+
poster = sel.select_poster("img.series-profile-thumb")
|
|
153
149
|
description = sel.select_text("p#tv-series-desc")
|
|
150
|
+
tags = sel.select_texts("div.item.categories a")
|
|
151
|
+
rating = sel.select_text("span.color-imdb")
|
|
152
|
+
actors = sel.select_texts("div.content h5")
|
|
153
|
+
year = sel.extract_year("div.truncate")
|
|
154
|
+
duration = sel.regex_first(r"(\d+)", sel.select_text(".media-meta td:last-child"))
|
|
155
|
+
if duration == year or int(duration) < 40:
|
|
156
|
+
duration = None
|
|
157
|
+
|
|
158
|
+
common_info = {
|
|
159
|
+
"url" : url,
|
|
160
|
+
"poster" : self.fix_url(poster) if poster else None,
|
|
161
|
+
"title" : title or "Bilinmiyor",
|
|
162
|
+
"description" : description,
|
|
163
|
+
"tags" : tags,
|
|
164
|
+
"rating" : rating,
|
|
165
|
+
"year" : str(year) if year else None,
|
|
166
|
+
"actors" : actors,
|
|
167
|
+
"duration" : duration
|
|
168
|
+
}
|
|
154
169
|
|
|
155
|
-
tags = [a.text(strip=True) for a in sel.select("div.item.categories a") if a.text(strip=True)]
|
|
156
|
-
|
|
157
|
-
rating = sel.select_text("span.color-imdb")
|
|
158
|
-
|
|
159
|
-
actors = [h5.text(strip=True) for h5 in sel.select("div.content h5") if h5.text(strip=True)]
|
|
160
|
-
|
|
161
|
-
year = sel.select_text("span.item.year")
|
|
162
|
-
if not year and title:
|
|
163
|
-
# Try to extract year from title like "Movie Name(2024)"
|
|
164
|
-
year_match = sel.regex_first(r"\((\d{4})\)", title)
|
|
165
|
-
if year_match:
|
|
166
|
-
year = year_match
|
|
167
|
-
|
|
168
170
|
episodes = []
|
|
169
|
-
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
# Sezon tab içeriklerini al
|
|
177
|
-
season_tabs = sel.select("div.ui.tab", episodes_box)
|
|
178
|
-
|
|
179
|
-
# Eğer birden fazla sezon varsa, her sezon tab'ından bölümleri çek
|
|
180
|
-
if season_tabs:
|
|
181
|
-
for idx, season_tab in enumerate(season_tabs):
|
|
182
|
-
# Sezon numarasını belirle
|
|
183
|
-
current_season_no = idx + 1
|
|
184
|
-
|
|
185
|
-
# Menüden sezon numarasını almaya çalış
|
|
186
|
-
if idx < len(season_menu):
|
|
187
|
-
menu_href = season_menu[idx].attrs.get("href", "")
|
|
188
|
-
match = sel.regex_first(r"sezon-(\d+)", menu_href)
|
|
189
|
-
if match:
|
|
190
|
-
current_season_no = int(match)
|
|
191
|
-
|
|
192
|
-
# Bu sezon tab'ından bölüm linklerini çek
|
|
193
|
-
ep_links = sel.select("a[href*='bolum']", season_tab)
|
|
194
|
-
|
|
195
|
-
seen_urls = set()
|
|
196
|
-
for ep_link in ep_links:
|
|
197
|
-
href = ep_link.attrs.get("href")
|
|
198
|
-
if not href or href in seen_urls:
|
|
199
|
-
continue
|
|
200
|
-
seen_urls.add(href)
|
|
201
|
-
|
|
202
|
-
# Bölüm numarasını URL'den çıkar
|
|
203
|
-
ep_no = 0
|
|
204
|
-
match_ep = sel.regex_first(r"bolum-(\d+)", href)
|
|
205
|
-
if match_ep:
|
|
206
|
-
ep_no = int(match_ep)
|
|
207
|
-
|
|
208
|
-
# Bölüm başlığını çıkar (önce title attribute, sonra text)
|
|
209
|
-
name = ep_link.attrs.get("title", "")
|
|
210
|
-
if not name:
|
|
211
|
-
name = sel.select_text("div.content div.header", ep_link)
|
|
212
|
-
if not name:
|
|
213
|
-
name = ep_link.text(strip=True)
|
|
214
|
-
|
|
215
|
-
if href and ep_no > 0:
|
|
216
|
-
episodes.append(Episode(
|
|
217
|
-
season = current_season_no,
|
|
218
|
-
episode = ep_no,
|
|
219
|
-
title = name.strip() if name else f"{ep_no}. Bölüm",
|
|
220
|
-
url = self.fix_url(href)
|
|
221
|
-
))
|
|
171
|
+
for tab in sel.select("div.ui.tab"):
|
|
172
|
+
for link in sel.select("a[href*='bolum']", tab):
|
|
173
|
+
href = link.attrs.get("href")
|
|
174
|
+
if href:
|
|
175
|
+
s, e = sel.extract_season_episode(href)
|
|
176
|
+
name = sel.select_text("div.content div.header", link) or link.text(strip=True)
|
|
177
|
+
episodes.append(Episode(season=s or 1, episode=e or 1, title=name, url=self.fix_url(href)))
|
|
222
178
|
|
|
223
179
|
if episodes:
|
|
224
|
-
return SeriesInfo(
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
poster = self.fix_url(poster) if poster else None,
|
|
228
|
-
description = description,
|
|
229
|
-
rating = rating,
|
|
230
|
-
tags = tags,
|
|
231
|
-
actors = actors,
|
|
232
|
-
year = year,
|
|
233
|
-
episodes = episodes
|
|
234
|
-
)
|
|
235
|
-
else:
|
|
236
|
-
return MovieInfo(
|
|
237
|
-
title = title,
|
|
238
|
-
url = url,
|
|
239
|
-
poster = self.fix_url(poster) if poster else None,
|
|
240
|
-
description = description,
|
|
241
|
-
rating = rating,
|
|
242
|
-
tags = tags,
|
|
243
|
-
actors = actors,
|
|
244
|
-
year = year
|
|
245
|
-
)
|
|
180
|
+
return SeriesInfo(**common_info, episodes=episodes)
|
|
181
|
+
|
|
182
|
+
return MovieInfo(**common_info)
|
|
246
183
|
|
|
247
184
|
async def load_links(self, url: str) -> list[ExtractResult]:
|
|
248
185
|
resp = await self.httpx.get(url)
|
KekikStream/Plugins/SinemaCX.py
CHANGED
|
@@ -83,36 +83,30 @@ class SinemaCX(PluginBase):
|
|
|
83
83
|
istek = await self.httpx.get(url)
|
|
84
84
|
secici = HTMLHelper(istek.text)
|
|
85
85
|
|
|
86
|
-
|
|
87
|
-
|
|
86
|
+
title = secici.select_text("div.f-bilgi h1")
|
|
87
|
+
poster = secici.select_poster("div.resim img")
|
|
88
88
|
description = secici.select_text("div.ackl div.scroll-liste")
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
tags = secici.select_all_text("div.f-bilgi div.tur a")
|
|
95
|
-
|
|
96
|
-
year = secici.select_text("div.f-bilgi ul.detay a[href*='yapim']")
|
|
97
|
-
|
|
98
|
-
actors = secici.select_all_text("li.oync li.oyuncu-k span.isim")
|
|
89
|
+
rating = secici.select_text("b.puandegistir")
|
|
90
|
+
tags = secici.select_texts("div.f-bilgi div.tur a")
|
|
91
|
+
year = secici.extract_year("ul.detay a[href*='yapim']")
|
|
92
|
+
actors = secici.select_texts("li.oync li.oyuncu-k span.isim")
|
|
99
93
|
|
|
100
94
|
return MovieInfo(
|
|
101
95
|
url = url,
|
|
102
96
|
poster = self.fix_url(poster) if poster else None,
|
|
103
|
-
title = title,
|
|
97
|
+
title = title or "Bilinmiyor",
|
|
104
98
|
description = description,
|
|
99
|
+
rating = rating,
|
|
105
100
|
tags = tags,
|
|
106
|
-
year = year,
|
|
107
|
-
actors = actors
|
|
108
|
-
duration = int(duration_match) if duration_match else None,
|
|
101
|
+
year = str(year) if year else None,
|
|
102
|
+
actors = actors
|
|
109
103
|
)
|
|
110
104
|
|
|
111
105
|
async def load_links(self, url: str) -> list[ExtractResult]:
|
|
112
106
|
istek = await self.httpx.get(url)
|
|
113
107
|
secici = HTMLHelper(istek.text)
|
|
114
108
|
|
|
115
|
-
iframe_list = secici.
|
|
109
|
+
iframe_list = secici.select_attrs("iframe", "data-vsrc")
|
|
116
110
|
|
|
117
111
|
# Sadece fragman varsa /2/ sayfasından dene
|
|
118
112
|
has_only_trailer = all(
|
|
@@ -125,7 +119,7 @@ class SinemaCX(PluginBase):
|
|
|
125
119
|
alt_istek = await self.httpx.get(alt_url)
|
|
126
120
|
alt_istek = await self.httpx.get(alt_url)
|
|
127
121
|
alt_sec = HTMLHelper(alt_istek.text)
|
|
128
|
-
iframe_list = alt_sec.
|
|
122
|
+
iframe_list = alt_sec.select_attrs("iframe", "data-vsrc")
|
|
129
123
|
|
|
130
124
|
if not iframe_list:
|
|
131
125
|
return []
|
KekikStream/Plugins/Sinezy.py
CHANGED
|
@@ -6,7 +6,7 @@ import base64
|
|
|
6
6
|
class Sinezy(PluginBase):
|
|
7
7
|
name = "Sinezy"
|
|
8
8
|
language = "tr"
|
|
9
|
-
main_url = "https://sinezy.
|
|
9
|
+
main_url = "https://sinezy.ink"
|
|
10
10
|
favicon = f"https://www.google.com/s2/favicons?domain={main_url}&sz=64"
|
|
11
11
|
description = "Yerli ve yabancı film izle! Türkçe Dublaj ve Alt Yazılı Seçenekleriyle full hd film izlemek için En çok tercih edilen adres!"
|
|
12
12
|
|
|
@@ -83,29 +83,28 @@ class Sinezy(PluginBase):
|
|
|
83
83
|
return results
|
|
84
84
|
|
|
85
85
|
async def load_item(self, url: str) -> MovieInfo:
|
|
86
|
-
resp
|
|
86
|
+
resp = await self.httpx.get(url)
|
|
87
87
|
secici = HTMLHelper(resp.text)
|
|
88
88
|
|
|
89
|
-
title
|
|
90
|
-
poster
|
|
89
|
+
title = secici.select_attr("div.detail", "title")
|
|
90
|
+
poster = secici.select_poster("div.move_k img")
|
|
91
91
|
description = secici.select_text("div.desc.yeniscroll p")
|
|
92
|
-
rating
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
|
|
92
|
+
rating = secici.select_text("span.info span.imdb")
|
|
93
|
+
tags = secici.select_texts("div.detail span a")
|
|
94
|
+
actors = secici.select_texts("span.oyn p")
|
|
95
|
+
year = secici.extract_year()
|
|
96
|
+
duration = secici.regex_first(r"(\d+) Dakika", secici.select_text("div.detail p"))
|
|
96
97
|
|
|
97
|
-
year = secici.regex_first(r"\b(19\d{2}|20\d{2})\b")
|
|
98
|
-
if not year:
|
|
99
|
-
year = secici.regex_first(r"\b(19\d{2}|20\d{2})\b", secici.html)
|
|
100
98
|
return MovieInfo(
|
|
101
|
-
title = title,
|
|
102
99
|
url = url,
|
|
103
100
|
poster = self.fix_url(poster) if poster else None,
|
|
101
|
+
title = title or "Bilinmiyor",
|
|
104
102
|
description = description,
|
|
105
103
|
tags = tags,
|
|
106
104
|
rating = rating,
|
|
105
|
+
year = str(year) if year else None,
|
|
107
106
|
actors = actors,
|
|
108
|
-
|
|
107
|
+
duration = duration
|
|
109
108
|
)
|
|
110
109
|
|
|
111
110
|
async def load_links(self, url: str) -> list[ExtractResult]:
|
|
@@ -79,26 +79,21 @@ class SuperFilmGeldi(PluginBase):
|
|
|
79
79
|
istek = await self.httpx.get(url)
|
|
80
80
|
secici = HTMLHelper(istek.text)
|
|
81
81
|
|
|
82
|
-
title
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
poster = secici.select_attr("div.poster img", "src")
|
|
86
|
-
|
|
87
|
-
year = secici.extract_year("div.release a")
|
|
88
|
-
|
|
82
|
+
title = self.clean_title(secici.select_text("div.title h1").split(" izle")[0]) if secici.select_text("div.title h1") else ""
|
|
83
|
+
poster = secici.select_poster("div.poster img")
|
|
84
|
+
year = secici.extract_year("div.release a")
|
|
89
85
|
description = secici.select_text("div.excerpt p")
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
actors = secici.select_all_text("div.actor a")
|
|
86
|
+
tags = secici.select_texts("div.categories a")
|
|
87
|
+
actors = secici.select_texts("div.actor a")
|
|
93
88
|
|
|
94
89
|
return MovieInfo(
|
|
95
90
|
url = url,
|
|
96
91
|
poster = self.fix_url(poster) if poster else None,
|
|
97
|
-
title = title,
|
|
92
|
+
title = title or "Bilinmiyor",
|
|
98
93
|
description = description,
|
|
99
94
|
tags = tags,
|
|
100
|
-
year = year,
|
|
101
|
-
actors = actors
|
|
95
|
+
year = str(year) if year else None,
|
|
96
|
+
actors = actors
|
|
102
97
|
)
|
|
103
98
|
|
|
104
99
|
async def load_links(self, url: str) -> list[ExtractResult]:
|