KekikStream 2.2.2__py3-none-any.whl → 2.2.5__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/Extractors/CloseLoad.py +7 -8
- KekikStream/Extractors/Filemoon.py +7 -6
- KekikStream/Extractors/MolyStream.py +6 -5
- KekikStream/Extractors/PlayerFilmIzle.py +6 -2
- KekikStream/Extractors/VidHide.py +0 -1
- KekikStream/Extractors/VidMoly.py +17 -9
- KekikStream/Plugins/BelgeselX.py +39 -20
- KekikStream/Plugins/DiziBox.py +115 -59
- KekikStream/Plugins/DiziPal.py +87 -40
- KekikStream/Plugins/DiziYou.py +105 -64
- KekikStream/Plugins/Dizilla.py +57 -28
- KekikStream/Plugins/FilmBip.py +60 -31
- KekikStream/Plugins/FilmMakinesi.py +75 -51
- KekikStream/Plugins/FilmModu.py +73 -36
- KekikStream/Plugins/FullHDFilm.py +82 -48
- KekikStream/Plugins/FullHDFilmizlesene.py +94 -39
- KekikStream/Plugins/HDFilmCehennemi.py +78 -53
- KekikStream/Plugins/JetFilmizle.py +78 -50
- KekikStream/Plugins/KultFilmler.py +64 -34
- KekikStream/Plugins/RoketDizi.py +43 -26
- KekikStream/Plugins/SelcukFlix.py +27 -14
- KekikStream/Plugins/SetFilmIzle.py +69 -43
- KekikStream/Plugins/SezonlukDizi.py +102 -46
- KekikStream/Plugins/Sinefy.py +130 -101
- KekikStream/Plugins/SinemaCX.py +82 -37
- KekikStream/Plugins/Sinezy.py +61 -47
- KekikStream/Plugins/SuperFilmGeldi.py +72 -36
- KekikStream/Plugins/UgurFilm.py +72 -34
- KekikStream/requirements.txt +1 -1
- {kekikstream-2.2.2.dist-info → kekikstream-2.2.5.dist-info}/METADATA +2 -2
- {kekikstream-2.2.2.dist-info → kekikstream-2.2.5.dist-info}/RECORD +35 -35
- {kekikstream-2.2.2.dist-info → kekikstream-2.2.5.dist-info}/WHEEL +0 -0
- {kekikstream-2.2.2.dist-info → kekikstream-2.2.5.dist-info}/entry_points.txt +0 -0
- {kekikstream-2.2.2.dist-info → kekikstream-2.2.5.dist-info}/licenses/LICENSE +0 -0
- {kekikstream-2.2.2.dist-info → kekikstream-2.2.5.dist-info}/top_level.txt +0 -0
KekikStream/Plugins/FilmBip.py
CHANGED
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
2
|
|
|
3
|
-
from KekikStream.Core
|
|
4
|
-
from
|
|
3
|
+
from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo, ExtractResult
|
|
4
|
+
from selectolax.parser import HTMLParser
|
|
5
|
+
import re
|
|
5
6
|
|
|
6
7
|
class FilmBip(PluginBase):
|
|
7
8
|
name = "FilmBip"
|
|
@@ -36,21 +37,23 @@ class FilmBip(PluginBase):
|
|
|
36
37
|
page_url = page_url.rstrip("/")
|
|
37
38
|
|
|
38
39
|
istek = await self.httpx.get(page_url)
|
|
39
|
-
secici =
|
|
40
|
+
secici = HTMLParser(istek.text)
|
|
40
41
|
|
|
41
42
|
results = []
|
|
42
43
|
for veri in secici.css("div.poster-long"):
|
|
43
|
-
img = veri.
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
44
|
+
img = veri.css_first("a.block img.lazy")
|
|
45
|
+
link_el = veri.css_first("a.block")
|
|
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
|
|
47
50
|
|
|
48
51
|
if title and href:
|
|
49
52
|
results.append(MainPageResult(
|
|
50
53
|
category = category,
|
|
51
54
|
title = title,
|
|
52
|
-
url = href,
|
|
53
|
-
poster = poster,
|
|
55
|
+
url = self.fix_url(href),
|
|
56
|
+
poster = self.fix_url(poster) if poster else None,
|
|
54
57
|
))
|
|
55
58
|
|
|
56
59
|
return results
|
|
@@ -77,47 +80,71 @@ class FilmBip(PluginBase):
|
|
|
77
80
|
except Exception:
|
|
78
81
|
return []
|
|
79
82
|
|
|
80
|
-
secici =
|
|
83
|
+
secici = HTMLParser(html_content)
|
|
81
84
|
|
|
82
85
|
results = []
|
|
83
86
|
for veri in secici.css("li"):
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
87
|
+
link_el = veri.css_first("a.block.truncate")
|
|
88
|
+
href_el = veri.css_first("a")
|
|
89
|
+
img_el = veri.css_first("img.lazy")
|
|
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
|
|
87
94
|
|
|
88
95
|
if title and href:
|
|
89
96
|
results.append(SearchResult(
|
|
90
97
|
title = title.strip(),
|
|
91
|
-
url = href,
|
|
92
|
-
poster = poster,
|
|
98
|
+
url = self.fix_url(href),
|
|
99
|
+
poster = self.fix_url(poster) if poster else None,
|
|
93
100
|
))
|
|
94
101
|
|
|
95
102
|
return results
|
|
96
103
|
|
|
97
104
|
async def load_item(self, url: str) -> MovieInfo:
|
|
98
105
|
istek = await self.httpx.get(url)
|
|
99
|
-
secici =
|
|
106
|
+
secici = HTMLParser(istek.text)
|
|
107
|
+
html_text = istek.text
|
|
108
|
+
|
|
109
|
+
title_el = secici.css_first("div.page-title h1")
|
|
110
|
+
title = title_el.text(strip=True) if title_el else ""
|
|
111
|
+
|
|
112
|
+
og_image = secici.css_first("meta[property='og:image']")
|
|
113
|
+
poster = og_image.attrs.get("content") if og_image else None
|
|
100
114
|
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
115
|
+
trailer_el = secici.css_first("div.series-profile-trailer")
|
|
116
|
+
trailer = trailer_el.attrs.get("data-yt") if trailer_el else None
|
|
117
|
+
|
|
118
|
+
desc_el = secici.css_first("div.series-profile-infos-in.article p")
|
|
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
122
|
|
|
107
|
-
tags = secici.css("div.series-profile-type.tv-show-profile-type a
|
|
123
|
+
tags = [a.text(strip=True) for a in secici.css("div.series-profile-type.tv-show-profile-type a") if a.text(strip=True)]
|
|
124
|
+
|
|
125
|
+
# XPath yerine regex kullanarak yıl, süre vs. çıkarma
|
|
126
|
+
year = None
|
|
127
|
+
year_match = re.search(r'Yapım yılı.*?<p[^>]*>(\d{4})</p>', html_text, re.IGNORECASE | re.DOTALL)
|
|
128
|
+
if year_match:
|
|
129
|
+
year = year_match.group(1)
|
|
130
|
+
|
|
131
|
+
duration = None
|
|
132
|
+
duration_match = re.search(r'Süre.*?<p[^>]*>(\d+)', html_text, re.IGNORECASE | re.DOTALL)
|
|
133
|
+
if duration_match:
|
|
134
|
+
duration = duration_match.group(1)
|
|
108
135
|
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
136
|
+
rating = None
|
|
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)
|
|
113
140
|
|
|
114
|
-
actors = secici.css("div.series-profile-cast ul li a img
|
|
141
|
+
actors = [img.attrs.get("alt") for img in secici.css("div.series-profile-cast ul li a img") if img.attrs.get("alt")]
|
|
115
142
|
|
|
116
143
|
return MovieInfo(
|
|
117
144
|
url = url,
|
|
118
|
-
poster = poster,
|
|
145
|
+
poster = self.fix_url(poster) if poster else None,
|
|
119
146
|
title = self.clean_title(title) if title else "",
|
|
120
|
-
description = description
|
|
147
|
+
description = description,
|
|
121
148
|
tags = tags,
|
|
122
149
|
year = year,
|
|
123
150
|
rating = rating,
|
|
@@ -127,14 +154,16 @@ class FilmBip(PluginBase):
|
|
|
127
154
|
|
|
128
155
|
async def load_links(self, url: str) -> list[ExtractResult]:
|
|
129
156
|
istek = await self.httpx.get(url)
|
|
130
|
-
secici =
|
|
157
|
+
secici = HTMLParser(istek.text)
|
|
131
158
|
|
|
132
159
|
results = []
|
|
133
160
|
|
|
134
161
|
for player in secici.css("div#tv-spoox2"):
|
|
135
|
-
|
|
162
|
+
iframe_el = player.css_first("iframe")
|
|
163
|
+
iframe = iframe_el.attrs.get("src") if iframe_el else None
|
|
136
164
|
|
|
137
165
|
if iframe:
|
|
166
|
+
iframe = self.fix_url(iframe)
|
|
138
167
|
data = await self.extract(iframe)
|
|
139
168
|
if data:
|
|
140
169
|
results.append(data)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
2
|
|
|
3
|
-
from KekikStream.Core
|
|
4
|
-
from
|
|
3
|
+
from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo, ExtractResult
|
|
4
|
+
from selectolax.parser import HTMLParser
|
|
5
5
|
|
|
6
6
|
class FilmMakinesi(PluginBase):
|
|
7
7
|
name = "FilmMakinesi"
|
|
@@ -36,65 +36,88 @@ class FilmMakinesi(PluginBase):
|
|
|
36
36
|
|
|
37
37
|
async def get_main_page(self, page: int, url: str, category: str) -> list[MainPageResult]:
|
|
38
38
|
istek = self.cloudscraper.get(f"{url}{'' if page == 1 else f'page/{page}/'}")
|
|
39
|
-
secici =
|
|
39
|
+
secici = HTMLParser(istek.text)
|
|
40
40
|
|
|
41
|
-
|
|
41
|
+
results = []
|
|
42
|
+
for veri in secici.css("div.item-relative"):
|
|
43
|
+
title_el = veri.css_first("div.title")
|
|
44
|
+
link_el = veri.css_first("a")
|
|
45
|
+
img_el = veri.css_first("img")
|
|
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
|
|
50
|
+
|
|
51
|
+
if title and href:
|
|
52
|
+
results.append(MainPageResult(
|
|
53
|
+
category = category,
|
|
54
|
+
title = title,
|
|
55
|
+
url = self.fix_url(href),
|
|
56
|
+
poster = self.fix_url(poster) if poster else None,
|
|
57
|
+
))
|
|
42
58
|
|
|
43
|
-
return
|
|
44
|
-
MainPageResult(
|
|
45
|
-
category = category,
|
|
46
|
-
title = veri.css("div.title::text").get(),
|
|
47
|
-
url = self.fix_url(veri.css("a::attr(href)").get()),
|
|
48
|
-
poster = self.fix_url(veri.css("img::attr(data-src)").get() or veri.css("img::attr(src)").get()),
|
|
49
|
-
)
|
|
50
|
-
for veri in veriler
|
|
51
|
-
]
|
|
59
|
+
return results
|
|
52
60
|
|
|
53
61
|
async def search(self, query: str) -> list[SearchResult]:
|
|
54
62
|
istek = await self.httpx.get(f"{self.main_url}/arama/?s={query}")
|
|
55
|
-
secici =
|
|
63
|
+
secici = HTMLParser(istek.text)
|
|
56
64
|
|
|
57
65
|
results = []
|
|
58
66
|
for article in secici.css("div.item-relative"):
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
67
|
+
title_el = article.css_first("div.title")
|
|
68
|
+
link_el = article.css_first("a")
|
|
69
|
+
img_el = article.css_first("img")
|
|
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
|
|
62
74
|
|
|
63
75
|
if title and href:
|
|
64
|
-
results.append(
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
|
|
68
|
-
|
|
69
|
-
)
|
|
70
|
-
)
|
|
76
|
+
results.append(SearchResult(
|
|
77
|
+
title = title.strip(),
|
|
78
|
+
url = self.fix_url(href.strip()),
|
|
79
|
+
poster = self.fix_url(poster.strip()) if poster else None,
|
|
80
|
+
))
|
|
71
81
|
|
|
72
82
|
return results
|
|
73
83
|
|
|
74
84
|
async def load_item(self, url: str) -> MovieInfo:
|
|
75
85
|
istek = await self.httpx.get(url)
|
|
76
|
-
secici =
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
title
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
if
|
|
86
|
-
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
86
|
+
secici = HTMLParser(istek.text)
|
|
87
|
+
|
|
88
|
+
title_el = secici.css_first("h1.title")
|
|
89
|
+
title = title_el.text(strip=True) if title_el else ""
|
|
90
|
+
|
|
91
|
+
poster_el = secici.css_first("img.cover-img")
|
|
92
|
+
poster = poster_el.attrs.get("src", "").strip() if poster_el else ""
|
|
93
|
+
|
|
94
|
+
desc_el = secici.css_first("div.info-description p")
|
|
95
|
+
description = desc_el.text(strip=True) if desc_el else ""
|
|
96
|
+
|
|
97
|
+
rating_el = secici.css_first("div.score")
|
|
98
|
+
rating = None
|
|
99
|
+
if rating_el:
|
|
100
|
+
rating_text = rating_el.text(strip=True)
|
|
101
|
+
if rating_text:
|
|
102
|
+
rating = rating_text.split()[0]
|
|
103
|
+
|
|
104
|
+
year_el = secici.css_first("span.date a")
|
|
105
|
+
year = year_el.text(strip=True) if year_el else ""
|
|
106
|
+
|
|
107
|
+
actors = [el.text(strip=True) for el in secici.css("div.cast-name") if el.text(strip=True)]
|
|
108
|
+
tags = [el.text(strip=True) for el in secici.css("div.genre a") if el.text(strip=True)]
|
|
109
|
+
|
|
110
|
+
duration_el = secici.css_first("div.time")
|
|
111
|
+
duration = None
|
|
112
|
+
if duration_el:
|
|
113
|
+
duration_text = duration_el.text(strip=True)
|
|
114
|
+
parts = duration_text.split()
|
|
115
|
+
if len(parts) > 1:
|
|
116
|
+
duration = parts[1].strip()
|
|
94
117
|
|
|
95
118
|
return MovieInfo(
|
|
96
119
|
url = url,
|
|
97
|
-
poster = self.fix_url(poster),
|
|
120
|
+
poster = self.fix_url(poster) if poster else None,
|
|
98
121
|
title = self.clean_title(title),
|
|
99
122
|
description = description,
|
|
100
123
|
tags = tags,
|
|
@@ -106,23 +129,24 @@ class FilmMakinesi(PluginBase):
|
|
|
106
129
|
|
|
107
130
|
async def load_links(self, url: str) -> list[ExtractResult]:
|
|
108
131
|
istek = await self.httpx.get(url)
|
|
109
|
-
secici =
|
|
132
|
+
secici = HTMLParser(istek.text)
|
|
110
133
|
|
|
111
134
|
response = []
|
|
112
135
|
|
|
113
136
|
# Video parts linklerini ve etiketlerini al
|
|
114
137
|
for link in secici.css("div.video-parts a[data-video_url]"):
|
|
115
|
-
video_url = link.
|
|
116
|
-
label = link.
|
|
117
|
-
label = label.strip()
|
|
138
|
+
video_url = link.attrs.get("data-video_url")
|
|
139
|
+
label = link.text(strip=True) if link.text(strip=True) else ""
|
|
118
140
|
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
141
|
+
if video_url:
|
|
142
|
+
data = await self.extract(video_url, prefix=label.split()[0] if label else None)
|
|
143
|
+
if data:
|
|
144
|
+
response.append(data)
|
|
122
145
|
|
|
123
146
|
# Eğer video-parts yoksa iframe kullan
|
|
124
147
|
if not response:
|
|
125
|
-
|
|
148
|
+
iframe_el = secici.css_first("iframe")
|
|
149
|
+
iframe_src = iframe_el.attrs.get("data-src") if iframe_el else None
|
|
126
150
|
if iframe_src:
|
|
127
151
|
data = await self.extract(iframe_src)
|
|
128
152
|
if data:
|
KekikStream/Plugins/FilmModu.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
2
|
|
|
3
|
-
from KekikStream.Core
|
|
4
|
-
from
|
|
3
|
+
from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo, Subtitle, ExtractResult
|
|
4
|
+
from selectolax.parser import HTMLParser
|
|
5
5
|
import re
|
|
6
6
|
|
|
7
7
|
class FilmModu(PluginBase):
|
|
@@ -42,68 +42,105 @@ class FilmModu(PluginBase):
|
|
|
42
42
|
|
|
43
43
|
async def get_main_page(self, page: int, url: str, category: str) -> list[MainPageResult]:
|
|
44
44
|
istek = await self.httpx.get(url.replace("SAYFA", str(page)))
|
|
45
|
-
secici =
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
)
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
45
|
+
secici = HTMLParser(istek.text)
|
|
46
|
+
|
|
47
|
+
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
|
|
55
|
+
|
|
56
|
+
if title and href:
|
|
57
|
+
results.append(MainPageResult(
|
|
58
|
+
category = category,
|
|
59
|
+
title = title,
|
|
60
|
+
url = self.fix_url(href),
|
|
61
|
+
poster = self.fix_url(poster) if poster else None,
|
|
62
|
+
))
|
|
63
|
+
|
|
64
|
+
return results
|
|
57
65
|
|
|
58
66
|
async def search(self, query: str) -> list[SearchResult]:
|
|
59
67
|
istek = await self.httpx.get(f"{self.main_url}/film-ara?term={query}")
|
|
60
|
-
secici =
|
|
68
|
+
secici = HTMLParser(istek.text)
|
|
61
69
|
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
66
|
-
|
|
67
|
-
)
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
70
|
+
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
|
|
78
|
+
|
|
79
|
+
if title and href:
|
|
80
|
+
results.append(SearchResult(
|
|
81
|
+
title = title,
|
|
82
|
+
url = self.fix_url(href),
|
|
83
|
+
poster = self.fix_url(poster) if poster else None,
|
|
84
|
+
))
|
|
85
|
+
|
|
86
|
+
return results
|
|
71
87
|
|
|
72
88
|
async def load_item(self, url: str) -> MovieInfo:
|
|
73
89
|
istek = await self.httpx.get(url)
|
|
74
|
-
secici =
|
|
90
|
+
secici = HTMLParser(istek.text)
|
|
75
91
|
|
|
76
|
-
|
|
77
|
-
|
|
92
|
+
org_title_el = secici.css_first("div.titles h1")
|
|
93
|
+
alt_title_el = secici.css_first("div.titles h2")
|
|
94
|
+
|
|
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 ""
|
|
78
97
|
title = f"{org_title} - {alt_title}" if alt_title else org_title
|
|
79
98
|
|
|
99
|
+
poster_el = secici.css_first("img.img-responsive")
|
|
100
|
+
poster = poster_el.attrs.get("src") if poster_el else None
|
|
101
|
+
|
|
102
|
+
desc_el = secici.css_first("p[itemprop='description']")
|
|
103
|
+
description = desc_el.text(strip=True) if desc_el else None
|
|
104
|
+
|
|
105
|
+
tags = [a.text(strip=True) for a in secici.css("a[href*='film-tur/']") if a.text(strip=True)]
|
|
106
|
+
|
|
107
|
+
year_el = secici.css_first("span[itemprop='dateCreated']")
|
|
108
|
+
year = year_el.text(strip=True) if year_el else None
|
|
109
|
+
|
|
110
|
+
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))
|
|
115
|
+
|
|
80
116
|
return MovieInfo(
|
|
81
117
|
url = url,
|
|
82
|
-
poster = self.fix_url(
|
|
118
|
+
poster = self.fix_url(poster) if poster else None,
|
|
83
119
|
title = title,
|
|
84
|
-
description =
|
|
85
|
-
tags =
|
|
86
|
-
year =
|
|
87
|
-
actors =
|
|
120
|
+
description = description,
|
|
121
|
+
tags = tags,
|
|
122
|
+
year = year,
|
|
123
|
+
actors = actors,
|
|
88
124
|
)
|
|
89
125
|
|
|
90
126
|
async def load_links(self, url: str) -> list[ExtractResult]:
|
|
91
127
|
istek = await self.httpx.get(url)
|
|
92
|
-
secici =
|
|
128
|
+
secici = HTMLParser(istek.text)
|
|
93
129
|
|
|
94
130
|
alternates = secici.css("div.alternates a")
|
|
95
131
|
if not alternates:
|
|
96
|
-
return []
|
|
132
|
+
return []
|
|
97
133
|
|
|
98
134
|
results = []
|
|
99
135
|
|
|
100
136
|
for alternatif in alternates:
|
|
101
|
-
alt_link =
|
|
102
|
-
alt_name = alternatif.
|
|
137
|
+
alt_link = alternatif.attrs.get("href")
|
|
138
|
+
alt_name = alternatif.text(strip=True)
|
|
103
139
|
|
|
104
140
|
if alt_name == "Fragman" or not alt_link:
|
|
105
141
|
continue
|
|
106
142
|
|
|
143
|
+
alt_link = self.fix_url(alt_link)
|
|
107
144
|
alt_istek = await self.httpx.get(alt_link)
|
|
108
145
|
alt_text = alt_istek.text
|
|
109
146
|
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
2
|
|
|
3
|
-
from KekikStream.Core
|
|
4
|
-
from
|
|
3
|
+
from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo, SeriesInfo, Episode, ExtractResult, Subtitle
|
|
4
|
+
from selectolax.parser import HTMLParser
|
|
5
5
|
import re, base64
|
|
6
6
|
|
|
7
7
|
class FullHDFilm(PluginBase):
|
|
@@ -48,55 +48,88 @@ class FullHDFilm(PluginBase):
|
|
|
48
48
|
})
|
|
49
49
|
|
|
50
50
|
istek = await self.httpx.get(page_url)
|
|
51
|
-
secici =
|
|
52
|
-
|
|
53
|
-
|
|
54
|
-
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
)
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
51
|
+
secici = HTMLParser(istek.text)
|
|
52
|
+
|
|
53
|
+
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
|
|
61
|
+
|
|
62
|
+
if alt and href:
|
|
63
|
+
results.append(MainPageResult(
|
|
64
|
+
category = category,
|
|
65
|
+
title = alt,
|
|
66
|
+
url = self.fix_url(href),
|
|
67
|
+
poster = self.fix_url(poster) if poster else None,
|
|
68
|
+
))
|
|
69
|
+
|
|
70
|
+
return results
|
|
63
71
|
|
|
64
72
|
async def search(self, query: str) -> list[SearchResult]:
|
|
65
73
|
istek = await self.httpx.get(f"{self.main_url}/?s={query}")
|
|
66
|
-
secici =
|
|
74
|
+
secici = HTMLParser(istek.text)
|
|
67
75
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
|
|
73
|
-
)
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
76
|
+
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
|
|
84
|
+
|
|
85
|
+
if alt and href:
|
|
86
|
+
results.append(SearchResult(
|
|
87
|
+
title = alt,
|
|
88
|
+
url = self.fix_url(href),
|
|
89
|
+
poster = self.fix_url(poster) if poster else None,
|
|
90
|
+
))
|
|
91
|
+
|
|
92
|
+
return results
|
|
77
93
|
|
|
78
94
|
async def load_item(self, url: str) -> MovieInfo | SeriesInfo:
|
|
79
95
|
istek = await self.httpx.get(url)
|
|
80
|
-
secici =
|
|
96
|
+
secici = HTMLParser(istek.text)
|
|
97
|
+
html_text = istek.text
|
|
81
98
|
|
|
82
|
-
|
|
83
|
-
title
|
|
84
|
-
poster = self.fix_url(secici.css("div.poster img::attr(src)").get() or "")
|
|
85
|
-
|
|
86
|
-
actors_text = secici.css("div.oyuncular.info::text").get()
|
|
87
|
-
if actors_text:
|
|
88
|
-
actors_text = actors_text.replace("Oyuncular:", "").strip()
|
|
89
|
-
actors = [a.strip() for a in actors_text.split(",")]
|
|
90
|
-
else:
|
|
91
|
-
actors = []
|
|
99
|
+
title_el = secici.css_first("h1")
|
|
100
|
+
title = title_el.text(strip=True) if title_el else ""
|
|
92
101
|
|
|
93
|
-
|
|
94
|
-
|
|
95
|
-
rating = secici.css("div.imdb::text").re_first(r"IMDb\s*([\d\.]+)")
|
|
102
|
+
poster_el = secici.css_first("div.poster img")
|
|
103
|
+
poster = self.fix_url(poster_el.attrs.get("src")) if poster_el else ""
|
|
96
104
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
105
|
+
actors_el = secici.css_first("div.oyuncular.info")
|
|
106
|
+
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(",")]
|
|
112
|
+
|
|
113
|
+
# Year: re_first ile regex
|
|
114
|
+
year_el = secici.css_first("div.yayin-tarihi.info")
|
|
115
|
+
year_text = year_el.text(strip=True) if year_el else ""
|
|
116
|
+
year_match = re.search(r"(\d{4})", year_text)
|
|
117
|
+
year = year_match.group(1) if year_match else None
|
|
118
|
+
|
|
119
|
+
tags = [a.text(strip=True) for a in secici.css("div.tur.info a") if a.text(strip=True)]
|
|
120
|
+
|
|
121
|
+
# Rating: regex
|
|
122
|
+
rating_el = secici.css_first("div.imdb")
|
|
123
|
+
rating_text = rating_el.text(strip=True) if rating_el else ""
|
|
124
|
+
rating_match = re.search(r"IMDb\s*([\d\.]+)", rating_text)
|
|
125
|
+
rating = rating_match.group(1) if rating_match else None
|
|
126
|
+
|
|
127
|
+
# Description: others div'den önceki div içindeki text
|
|
128
|
+
# XPath yerine basit yaklaşım: özet sınıfı ile veya ilk paragraf
|
|
129
|
+
description = None
|
|
130
|
+
desc_el = secici.css_first("div.film")
|
|
131
|
+
if desc_el:
|
|
132
|
+
description = desc_el.text(strip=True)
|
|
100
133
|
|
|
101
134
|
# Kotlin referansı: URL'de -dizi kontrolü veya tags içinde "dizi" kontrolü
|
|
102
135
|
is_series = "-dizi" in url.lower() or any("dizi" in tag.lower() for tag in tags)
|
|
@@ -104,16 +137,17 @@ class FullHDFilm(PluginBase):
|
|
|
104
137
|
if is_series:
|
|
105
138
|
episodes = []
|
|
106
139
|
part_elements = secici.css("li.psec")
|
|
107
|
-
part_names = secici.css("li.psec a::text").getall()
|
|
108
140
|
|
|
109
141
|
# pdata değerlerini çıkar
|
|
110
|
-
pdata_matches = re.findall(r"pdata\['([^']+)'\]\s*=\s*'([^']+)'",
|
|
142
|
+
pdata_matches = re.findall(r"pdata\['([^']+)'\]\s*=\s*'([^']+)'", html_text)
|
|
111
143
|
|
|
112
|
-
for idx,
|
|
144
|
+
for idx, el in enumerate(part_elements):
|
|
145
|
+
part_id = el.attrs.get("id")
|
|
146
|
+
link_el = el.css_first("a")
|
|
147
|
+
part_name = link_el.text(strip=True) if link_el else None
|
|
148
|
+
|
|
113
149
|
if not part_name:
|
|
114
150
|
continue
|
|
115
|
-
|
|
116
|
-
part_name = part_name.strip()
|
|
117
151
|
|
|
118
152
|
# Fragman'ları atla
|
|
119
153
|
if "fragman" in part_name.lower() or (part_id and "fragman" in part_id.lower()):
|
|
@@ -146,7 +180,7 @@ class FullHDFilm(PluginBase):
|
|
|
146
180
|
tags = tags,
|
|
147
181
|
year = year,
|
|
148
182
|
actors = actors,
|
|
149
|
-
rating = rating
|
|
183
|
+
rating = rating,
|
|
150
184
|
episodes = episodes
|
|
151
185
|
)
|
|
152
186
|
else:
|
|
@@ -158,7 +192,7 @@ class FullHDFilm(PluginBase):
|
|
|
158
192
|
tags = tags,
|
|
159
193
|
year = year,
|
|
160
194
|
actors = actors,
|
|
161
|
-
rating = rating
|
|
195
|
+
rating = rating,
|
|
162
196
|
)
|
|
163
197
|
|
|
164
198
|
def _get_iframe(self, source_code: str) -> str:
|