KekikStream 2.2.9__py3-none-any.whl → 2.3.9__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Potentially problematic release.
This version of KekikStream might be problematic. Click here for more details.
- KekikStream/Core/HTMLHelper.py +134 -0
- KekikStream/Core/Plugin/PluginBase.py +22 -4
- KekikStream/Core/Plugin/PluginLoader.py +3 -2
- KekikStream/Core/Plugin/PluginManager.py +2 -2
- KekikStream/Core/__init__.py +2 -0
- KekikStream/Extractors/CloseLoad.py +12 -13
- KekikStream/Extractors/ContentX.py +33 -31
- KekikStream/Extractors/DonilasPlay.py +10 -10
- KekikStream/Extractors/DzenRu.py +3 -3
- KekikStream/Extractors/ExPlay.py +10 -10
- KekikStream/Extractors/Filemoon.py +11 -16
- KekikStream/Extractors/JetTv.py +4 -4
- KekikStream/Extractors/MixPlayHD.py +10 -11
- KekikStream/Extractors/MolyStream.py +16 -9
- KekikStream/Extractors/Odnoklassniki.py +4 -4
- KekikStream/Extractors/PeaceMakerst.py +3 -3
- KekikStream/Extractors/PixelDrain.py +6 -5
- KekikStream/Extractors/PlayerFilmIzle.py +6 -10
- KekikStream/Extractors/RapidVid.py +8 -7
- KekikStream/Extractors/SetPlay.py +10 -10
- KekikStream/Extractors/SetPrime.py +3 -6
- KekikStream/Extractors/SibNet.py +4 -5
- KekikStream/Extractors/Sobreatsesuyp.py +5 -5
- KekikStream/Extractors/TRsTX.py +5 -5
- KekikStream/Extractors/TurboImgz.py +3 -4
- KekikStream/Extractors/TurkeyPlayer.py +5 -5
- KekikStream/Extractors/VidHide.py +4 -7
- KekikStream/Extractors/VidMoly.py +37 -25
- KekikStream/Extractors/VidMoxy.py +8 -9
- KekikStream/Extractors/VidPapi.py +5 -7
- KekikStream/Extractors/VideoSeyred.py +3 -3
- KekikStream/Plugins/BelgeselX.py +40 -51
- KekikStream/Plugins/DiziBox.py +53 -81
- KekikStream/Plugins/DiziPal.py +50 -72
- KekikStream/Plugins/DiziYou.py +96 -83
- KekikStream/Plugins/Dizilla.py +95 -107
- KekikStream/Plugins/FilmBip.py +29 -50
- KekikStream/Plugins/FilmMakinesi.py +84 -46
- KekikStream/Plugins/FilmModu.py +27 -41
- KekikStream/Plugins/FullHDFilm.py +57 -62
- KekikStream/Plugins/FullHDFilmizlesene.py +32 -57
- KekikStream/Plugins/HDFilmCehennemi.py +51 -65
- KekikStream/Plugins/JetFilmizle.py +38 -51
- KekikStream/Plugins/KultFilmler.py +43 -67
- KekikStream/Plugins/RecTV.py +34 -9
- KekikStream/Plugins/RoketDizi.py +89 -111
- KekikStream/Plugins/SelcukFlix.py +102 -93
- KekikStream/Plugins/SetFilmIzle.py +65 -75
- KekikStream/Plugins/SezonlukDizi.py +47 -65
- KekikStream/Plugins/Sinefy.py +70 -70
- KekikStream/Plugins/SinemaCX.py +31 -55
- KekikStream/Plugins/Sinezy.py +27 -54
- KekikStream/Plugins/SuperFilmGeldi.py +25 -44
- KekikStream/Plugins/UgurFilm.py +23 -48
- KekikStream/Plugins/YabanciDizi.py +285 -0
- {kekikstream-2.2.9.dist-info → kekikstream-2.3.9.dist-info}/METADATA +1 -1
- kekikstream-2.3.9.dist-info/RECORD +84 -0
- kekikstream-2.2.9.dist-info/RECORD +0 -82
- {kekikstream-2.2.9.dist-info → kekikstream-2.3.9.dist-info}/WHEEL +0 -0
- {kekikstream-2.2.9.dist-info → kekikstream-2.3.9.dist-info}/entry_points.txt +0 -0
- {kekikstream-2.2.9.dist-info → kekikstream-2.3.9.dist-info}/licenses/LICENSE +0 -0
- {kekikstream-2.2.9.dist-info → kekikstream-2.3.9.dist-info}/top_level.txt +0 -0
KekikStream/Plugins/FilmBip.py
CHANGED
|
@@ -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, ExtractResult
|
|
4
|
-
from selectolax.parser import HTMLParser
|
|
5
|
-
import re
|
|
3
|
+
from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo, ExtractResult, HTMLHelper
|
|
6
4
|
|
|
7
5
|
class FilmBip(PluginBase):
|
|
8
6
|
name = "FilmBip"
|
|
@@ -37,16 +35,13 @@ class FilmBip(PluginBase):
|
|
|
37
35
|
page_url = page_url.rstrip("/")
|
|
38
36
|
|
|
39
37
|
istek = await self.httpx.get(page_url)
|
|
40
|
-
secici =
|
|
38
|
+
secici = HTMLHelper(istek.text)
|
|
41
39
|
|
|
42
40
|
results = []
|
|
43
|
-
for veri in secici.
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
title = img.attrs.get("alt") if img else None
|
|
48
|
-
href = link_el.attrs.get("href") if link_el else None
|
|
49
|
-
poster = (img.attrs.get("data-src") or img.attrs.get("src")) if img else None
|
|
41
|
+
for veri in secici.select("div.poster-long"):
|
|
42
|
+
title = secici.select_attr("a.block img.lazy", "alt", veri)
|
|
43
|
+
href = secici.select_attr("a.block", "href", veri)
|
|
44
|
+
poster = secici.select_poster("a.block img.lazy", veri)
|
|
50
45
|
|
|
51
46
|
if title and href:
|
|
52
47
|
results.append(MainPageResult(
|
|
@@ -80,17 +75,13 @@ class FilmBip(PluginBase):
|
|
|
80
75
|
except Exception:
|
|
81
76
|
return []
|
|
82
77
|
|
|
83
|
-
secici =
|
|
78
|
+
secici = HTMLHelper(html_content)
|
|
84
79
|
|
|
85
80
|
results = []
|
|
86
|
-
for veri in secici.
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
title = link_el.text(strip=True) if link_el else None
|
|
92
|
-
href = href_el.attrs.get("href") if href_el else None
|
|
93
|
-
poster = img_el.attrs.get("data-src") if img_el else None
|
|
81
|
+
for veri in secici.select("li"):
|
|
82
|
+
title = secici.select_text("a.block.truncate", veri)
|
|
83
|
+
href = secici.select_attr("a", "href", veri)
|
|
84
|
+
poster = secici.select_attr("img.lazy", "data-src", veri)
|
|
94
85
|
|
|
95
86
|
if title and href:
|
|
96
87
|
results.append(SearchResult(
|
|
@@ -103,47 +94,36 @@ class FilmBip(PluginBase):
|
|
|
103
94
|
|
|
104
95
|
async def load_item(self, url: str) -> MovieInfo:
|
|
105
96
|
istek = await self.httpx.get(url)
|
|
106
|
-
secici =
|
|
97
|
+
secici = HTMLHelper(istek.text)
|
|
107
98
|
html_text = istek.text
|
|
108
99
|
|
|
109
|
-
|
|
110
|
-
title = title_el.text(strip=True) if title_el else ""
|
|
100
|
+
title = secici.select_text("div.page-title h1") or ""
|
|
111
101
|
|
|
112
|
-
|
|
113
|
-
poster = og_image.attrs.get("content") if og_image else None
|
|
102
|
+
poster = secici.select_attr("meta[property='og:image']", "content")
|
|
114
103
|
|
|
115
|
-
|
|
116
|
-
trailer = trailer_el.attrs.get("data-yt") if trailer_el else None
|
|
104
|
+
trailer = secici.select_attr("div.series-profile-trailer", "data-yt")
|
|
117
105
|
|
|
118
|
-
|
|
119
|
-
if not desc_el:
|
|
120
|
-
desc_el = secici.css_first("div.series-profile-summary p")
|
|
121
|
-
description = desc_el.text(strip=True) if desc_el else None
|
|
106
|
+
description = secici.select_text("div.series-profile-infos-in.article p") or secici.select_text("div.series-profile-summary p")
|
|
122
107
|
|
|
123
|
-
tags =
|
|
108
|
+
tags = secici.select_all_text("div.series-profile-type.tv-show-profile-type a")
|
|
124
109
|
|
|
125
110
|
# XPath yerine regex kullanarak yıl, süre vs. çıkarma
|
|
126
|
-
year =
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
year =
|
|
111
|
+
year = secici.regex_first(r"(?is)Yap\u0131m y\u0131l\u0131.*?<p[^>]*>(.*?)<\/p>")
|
|
112
|
+
if not year:
|
|
113
|
+
# Fallback: Başlığın sonundaki parantezli yılı yakala
|
|
114
|
+
year = secici.regex_first(r"\((\d{4})\)", title)
|
|
130
115
|
|
|
131
|
-
|
|
132
|
-
|
|
133
|
-
if duration_match:
|
|
134
|
-
duration = duration_match.group(1)
|
|
116
|
+
duration_raw = secici.regex_first(r"(?is)S\u00fcre.*?<p[^>]*>(.*?)<\/p>")
|
|
117
|
+
duration = secici.regex_first(r"(\d+)", duration_raw) if duration_raw else None
|
|
135
118
|
|
|
136
|
-
rating =
|
|
137
|
-
rating_match = re.search(r'IMDB Puanı.*?<span[^>]*>([0-9.]+)</span>', html_text, re.IGNORECASE | re.DOTALL)
|
|
138
|
-
if rating_match:
|
|
139
|
-
rating = rating_match.group(1)
|
|
119
|
+
rating = secici.regex_first(r"(?is)IMDB Puan\u0131.*?<span[^>]*>(.*?)<\/span>")
|
|
140
120
|
|
|
141
|
-
actors = [img.attrs.get("alt") for img in secici.
|
|
121
|
+
actors = [img.attrs.get("alt") for img in secici.select("div.series-profile-cast ul li a img") if img.attrs.get("alt")]
|
|
142
122
|
|
|
143
123
|
return MovieInfo(
|
|
144
124
|
url = url,
|
|
145
125
|
poster = self.fix_url(poster) if poster else None,
|
|
146
|
-
title =
|
|
126
|
+
title = HTMLHelper(title).regex_replace(r"\(\d{4}\)", "").strip() if title else "",
|
|
147
127
|
description = description,
|
|
148
128
|
tags = tags,
|
|
149
129
|
year = year,
|
|
@@ -154,13 +134,12 @@ class FilmBip(PluginBase):
|
|
|
154
134
|
|
|
155
135
|
async def load_links(self, url: str) -> list[ExtractResult]:
|
|
156
136
|
istek = await self.httpx.get(url)
|
|
157
|
-
secici =
|
|
137
|
+
secici = HTMLHelper(istek.text)
|
|
158
138
|
|
|
159
139
|
results = []
|
|
160
140
|
|
|
161
|
-
for player in secici.
|
|
162
|
-
|
|
163
|
-
iframe = iframe_el.attrs.get("src") if iframe_el else None
|
|
141
|
+
for player in secici.select("div#tv-spoox2"):
|
|
142
|
+
iframe = secici.select_attr("iframe", "src", player)
|
|
164
143
|
|
|
165
144
|
if iframe:
|
|
166
145
|
iframe = self.fix_url(iframe)
|
|
@@ -1,7 +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, ExtractResult
|
|
4
|
-
from selectolax.parser import HTMLParser
|
|
3
|
+
from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo, SeriesInfo, Episode, ExtractResult, HTMLHelper
|
|
5
4
|
|
|
6
5
|
class FilmMakinesi(PluginBase):
|
|
7
6
|
name = "FilmMakinesi"
|
|
@@ -36,17 +35,13 @@ class FilmMakinesi(PluginBase):
|
|
|
36
35
|
|
|
37
36
|
async def get_main_page(self, page: int, url: str, category: str) -> list[MainPageResult]:
|
|
38
37
|
istek = self.cloudscraper.get(f"{url}{'' if page == 1 else f'page/{page}/'}")
|
|
39
|
-
secici =
|
|
38
|
+
secici = HTMLHelper(istek.text)
|
|
40
39
|
|
|
41
40
|
results = []
|
|
42
|
-
for veri in secici.
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
title = title_el.text(strip=True) if title_el else None
|
|
48
|
-
href = link_el.attrs.get("href") if link_el else None
|
|
49
|
-
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)
|
|
50
45
|
|
|
51
46
|
if title and href:
|
|
52
47
|
results.append(MainPageResult(
|
|
@@ -60,17 +55,13 @@ class FilmMakinesi(PluginBase):
|
|
|
60
55
|
|
|
61
56
|
async def search(self, query: str) -> list[SearchResult]:
|
|
62
57
|
istek = await self.httpx.get(f"{self.main_url}/arama/?s={query}")
|
|
63
|
-
secici =
|
|
58
|
+
secici = HTMLHelper(istek.text)
|
|
64
59
|
|
|
65
60
|
results = []
|
|
66
|
-
for article in secici.
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
title = title_el.text(strip=True) if title_el else None
|
|
72
|
-
href = link_el.attrs.get("href") if link_el else None
|
|
73
|
-
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)
|
|
74
65
|
|
|
75
66
|
if title and href:
|
|
76
67
|
results.append(SearchResult(
|
|
@@ -81,40 +72,88 @@ class FilmMakinesi(PluginBase):
|
|
|
81
72
|
|
|
82
73
|
return results
|
|
83
74
|
|
|
84
|
-
async def load_item(self, url: str) -> MovieInfo:
|
|
75
|
+
async def load_item(self, url: str) -> MovieInfo | SeriesInfo:
|
|
85
76
|
istek = await self.httpx.get(url)
|
|
86
|
-
secici =
|
|
77
|
+
secici = HTMLHelper(istek.text)
|
|
87
78
|
|
|
88
|
-
|
|
89
|
-
title = title_el.text(strip=True) if title_el else ""
|
|
79
|
+
title = secici.select_text("h1.title") or ""
|
|
90
80
|
|
|
91
|
-
|
|
92
|
-
poster
|
|
81
|
+
poster = secici.select_attr("img.cover-img", "src") or ""
|
|
82
|
+
poster = poster.strip()
|
|
93
83
|
|
|
94
|
-
|
|
95
|
-
description = desc_el.text(strip=True) if desc_el else ""
|
|
84
|
+
description = secici.select_text("div.info-description p") or ""
|
|
96
85
|
|
|
97
|
-
|
|
98
|
-
rating
|
|
99
|
-
if
|
|
100
|
-
|
|
101
|
-
if rating_text:
|
|
102
|
-
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]
|
|
103
90
|
|
|
104
|
-
|
|
105
|
-
year = year_el.text(strip=True) if year_el else ""
|
|
91
|
+
year = secici.select_text("span.date a") or ""
|
|
106
92
|
|
|
107
|
-
actors =
|
|
108
|
-
tags
|
|
93
|
+
actors = secici.select_all_text("div.cast-name")
|
|
94
|
+
tags = [a.text(strip=True) for a in secici.select("div.type a") if "/tur/" in (a.attrs.get("href") or "")]
|
|
109
95
|
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
if
|
|
113
|
-
duration_text = duration_el.text(strip=True)
|
|
96
|
+
duration = None
|
|
97
|
+
duration_text = secici.select_text("div.time") or None
|
|
98
|
+
if duration_text:
|
|
114
99
|
parts = duration_text.split()
|
|
115
100
|
if len(parts) > 1:
|
|
116
101
|
duration = parts[1].strip()
|
|
117
102
|
|
|
103
|
+
# Dizi mi kontrol et - sezon/bölüm linkleri var mı?
|
|
104
|
+
episodes = []
|
|
105
|
+
all_links = secici.select("a[href]")
|
|
106
|
+
for link in all_links:
|
|
107
|
+
href = link.attrs.get("href", "")
|
|
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
|
+
|
|
113
|
+
# Bölüm başlığını çıkar - text'ten gerçek ismi al
|
|
114
|
+
# Format: "22 Eylül 2014 / 44 dk /1. Sezon / 1. BölümPilot"
|
|
115
|
+
full_text = link.text(strip=True)
|
|
116
|
+
# "Bölüm" kelimesinden sonraki kısmı al
|
|
117
|
+
ep_title = ""
|
|
118
|
+
if "Bölüm" in full_text:
|
|
119
|
+
parts = full_text.split("Bölüm")
|
|
120
|
+
if len(parts) > 1:
|
|
121
|
+
ep_title = parts[-1].strip()
|
|
122
|
+
|
|
123
|
+
episodes.append(Episode(
|
|
124
|
+
season = season_no,
|
|
125
|
+
episode = ep_no,
|
|
126
|
+
title = ep_title,
|
|
127
|
+
url = self.fix_url(href)
|
|
128
|
+
))
|
|
129
|
+
|
|
130
|
+
# Bölümler varsa SeriesInfo döndür
|
|
131
|
+
if episodes:
|
|
132
|
+
# Tekrar eden bölümleri kaldır
|
|
133
|
+
seen = set()
|
|
134
|
+
unique_episodes = []
|
|
135
|
+
for ep in episodes:
|
|
136
|
+
key = (ep.season, ep.episode)
|
|
137
|
+
if key not in seen:
|
|
138
|
+
seen.add(key)
|
|
139
|
+
unique_episodes.append(ep)
|
|
140
|
+
|
|
141
|
+
# Sırala
|
|
142
|
+
unique_episodes.sort(key=lambda x: (x.season or 0, x.episode or 0))
|
|
143
|
+
|
|
144
|
+
return SeriesInfo(
|
|
145
|
+
url = url,
|
|
146
|
+
poster = self.fix_url(poster) if poster else None,
|
|
147
|
+
title = self.clean_title(title),
|
|
148
|
+
description = description,
|
|
149
|
+
tags = tags,
|
|
150
|
+
rating = rating,
|
|
151
|
+
year = year,
|
|
152
|
+
actors = actors,
|
|
153
|
+
duration = duration,
|
|
154
|
+
episodes = unique_episodes
|
|
155
|
+
)
|
|
156
|
+
|
|
118
157
|
return MovieInfo(
|
|
119
158
|
url = url,
|
|
120
159
|
poster = self.fix_url(poster) if poster else None,
|
|
@@ -129,12 +168,12 @@ class FilmMakinesi(PluginBase):
|
|
|
129
168
|
|
|
130
169
|
async def load_links(self, url: str) -> list[ExtractResult]:
|
|
131
170
|
istek = await self.httpx.get(url)
|
|
132
|
-
secici =
|
|
171
|
+
secici = HTMLHelper(istek.text)
|
|
133
172
|
|
|
134
173
|
response = []
|
|
135
174
|
|
|
136
175
|
# Video parts linklerini ve etiketlerini al
|
|
137
|
-
for link in secici.
|
|
176
|
+
for link in secici.select("div.video-parts a[data-video_url]"):
|
|
138
177
|
video_url = link.attrs.get("data-video_url")
|
|
139
178
|
label = link.text(strip=True) if link.text(strip=True) else ""
|
|
140
179
|
|
|
@@ -145,8 +184,7 @@ class FilmMakinesi(PluginBase):
|
|
|
145
184
|
|
|
146
185
|
# Eğer video-parts yoksa iframe kullan
|
|
147
186
|
if not response:
|
|
148
|
-
|
|
149
|
-
iframe_src = iframe_el.attrs.get("data-src") if iframe_el else None
|
|
187
|
+
iframe_src = secici.select_attr("iframe", "data-src")
|
|
150
188
|
if iframe_src:
|
|
151
189
|
data = await self.extract(iframe_src)
|
|
152
190
|
if data:
|
KekikStream/Plugins/FilmModu.py
CHANGED
|
@@ -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 =
|
|
43
|
+
secici = HTMLHelper(istek.text)
|
|
46
44
|
|
|
47
45
|
results = []
|
|
48
|
-
for veri in secici.
|
|
49
|
-
|
|
50
|
-
|
|
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 =
|
|
63
|
+
secici = HTMLHelper(istek.text)
|
|
69
64
|
|
|
70
65
|
results = []
|
|
71
|
-
for veri in secici.
|
|
72
|
-
|
|
73
|
-
|
|
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 =
|
|
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 =
|
|
96
|
-
alt_title =
|
|
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
|
-
|
|
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
|
-
|
|
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 =
|
|
92
|
+
tags = secici.select_all_text("a[href*='film-tur/']")
|
|
106
93
|
|
|
107
|
-
|
|
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.
|
|
112
|
-
|
|
113
|
-
if
|
|
114
|
-
actors.append(
|
|
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 =
|
|
114
|
+
secici = HTMLHelper(istek.text)
|
|
129
115
|
|
|
130
|
-
alternates = secici.
|
|
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 =
|
|
148
|
-
vid_type =
|
|
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
|
|
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
|
-
|
|
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 =
|
|
50
|
+
secici = HTMLHelper(istek.text)
|
|
52
51
|
|
|
53
52
|
results = []
|
|
54
|
-
for veri in secici.
|
|
55
|
-
|
|
56
|
-
|
|
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 =
|
|
70
|
+
secici = HTMLHelper(istek.text)
|
|
75
71
|
|
|
76
72
|
results = []
|
|
77
|
-
for veri in secici.
|
|
78
|
-
|
|
79
|
-
|
|
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,58 +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 =
|
|
89
|
+
secici = HTMLHelper(istek.text)
|
|
97
90
|
html_text = istek.text
|
|
98
91
|
|
|
99
|
-
|
|
100
|
-
title = title_el.text(strip=True) if title_el else ""
|
|
92
|
+
title = secici.select_text("h1") or ""
|
|
101
93
|
|
|
102
|
-
|
|
103
|
-
poster
|
|
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
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
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(",")]
|
|
102
|
+
|
|
103
|
+
# Year: önce div.yayin-tarihi.info dene
|
|
104
|
+
year = secici.extract_year("div.yayin-tarihi.info")
|
|
112
105
|
|
|
113
|
-
#
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
106
|
+
# Fallback: h1'in parent'ından (2019) formatında ara
|
|
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})\)")
|
|
118
113
|
|
|
119
|
-
tags =
|
|
114
|
+
tags = secici.select_all_text("div.tur.info a")
|
|
120
115
|
|
|
121
116
|
# Rating: regex
|
|
122
|
-
|
|
123
|
-
|
|
124
|
-
rating_match = re.search(r"IMDb\s*([\d\.]+)", rating_text)
|
|
125
|
-
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\.]+)")
|
|
126
119
|
|
|
127
|
-
# Description:
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
if
|
|
132
|
-
|
|
120
|
+
# Description: önce div.film dene, yoksa og:description meta tag'ını kullan
|
|
121
|
+
description = secici.select_text("div.film")
|
|
122
|
+
|
|
123
|
+
# Fallback: og:description meta tag'ı
|
|
124
|
+
if not description:
|
|
125
|
+
og_desc = secici.select_attr("meta[property='og:description']", "content")
|
|
126
|
+
if og_desc:
|
|
127
|
+
description = og_desc
|
|
133
128
|
|
|
134
129
|
# Kotlin referansı: URL'de -dizi kontrolü veya tags içinde "dizi" kontrolü
|
|
135
130
|
is_series = "-dizi" in url.lower() or any("dizi" in tag.lower() for tag in tags)
|
|
136
131
|
|
|
137
132
|
if is_series:
|
|
138
133
|
episodes = []
|
|
139
|
-
part_elements = secici.
|
|
134
|
+
part_elements = secici.select("li.psec")
|
|
140
135
|
|
|
141
136
|
# pdata değerlerini çıkar
|
|
142
|
-
pdata_matches =
|
|
137
|
+
pdata_matches = HTMLHelper(html_text).regex_all(r"pdata\['([^']+)'\]\s*=\s*'([^']+)'")
|
|
143
138
|
|
|
144
139
|
for idx, el in enumerate(part_elements):
|
|
145
140
|
part_id = el.attrs.get("id")
|
|
146
|
-
|
|
147
|
-
part_name = link_el.text(strip=True) if link_el else None
|
|
141
|
+
part_name = secici.select_text("a", el)
|
|
148
142
|
|
|
149
143
|
if not part_name:
|
|
150
144
|
continue
|
|
@@ -154,11 +148,11 @@ class FullHDFilm(PluginBase):
|
|
|
154
148
|
continue
|
|
155
149
|
|
|
156
150
|
# Sezon ve bölüm numarası çıkar
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
sz_num = int(
|
|
161
|
-
ep_num = int(
|
|
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
|
|
162
156
|
|
|
163
157
|
# pdata'dan video URL'si çık (varsa)
|
|
164
158
|
video_url = url # Varsayılan olarak ana URL kullan
|
|
@@ -197,14 +191,14 @@ class FullHDFilm(PluginBase):
|
|
|
197
191
|
|
|
198
192
|
def _get_iframe(self, source_code: str) -> str:
|
|
199
193
|
"""Base64 kodlu iframe'i çözümle"""
|
|
200
|
-
|
|
201
|
-
if not
|
|
194
|
+
script_val = HTMLHelper(source_code).regex_first(r'<script[^>]*>(PCEtLWJhc2xpazp[^<]*)</script>')
|
|
195
|
+
if not script_val:
|
|
202
196
|
return ""
|
|
203
197
|
|
|
204
198
|
try:
|
|
205
|
-
decoded_html = base64.b64decode(
|
|
206
|
-
|
|
207
|
-
return self.fix_url(
|
|
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 ""
|
|
208
202
|
except Exception:
|
|
209
203
|
return ""
|
|
210
204
|
|
|
@@ -217,8 +211,9 @@ class FullHDFilm(PluginBase):
|
|
|
217
211
|
]
|
|
218
212
|
|
|
219
213
|
for pattern in patterns:
|
|
220
|
-
|
|
221
|
-
|
|
214
|
+
val = HTMLHelper(source_code).regex_first(pattern)
|
|
215
|
+
if val:
|
|
216
|
+
return val
|
|
222
217
|
|
|
223
218
|
return None
|
|
224
219
|
|