Skip to content

Commit 0f2880e

Browse files
committed
🕊
🕊
1 parent cf92e03 commit 0f2880e

File tree

7 files changed

+215
-83
lines changed

7 files changed

+215
-83
lines changed

‎KekikStream/Extractors/CloseLoad.py‎

Lines changed: 17 additions & 2 deletions
Original file line numberDiff line numberDiff line change
@@ -1,7 +1,8 @@
11
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
22

3-
from KekikStream.Core import ExtractorBase, ExtractResult
3+
from KekikStream.Core import ExtractorBase, ExtractResult, Subtitle
44
from Kekik.Sifreleme import Packer, StreamDecoder
5+
from parsel import Selector
56
import re
67

78
class CloseLoadExtractor(ExtractorBase):
@@ -15,12 +16,26 @@ async def extract(self, url, referer=None) -> ExtractResult:
1516
istek = await self.httpx.get(url)
1617
istek.raise_for_status()
1718

19+
# Video URL'sini çıkar
1820
eval_func = re.compile(r'\s*(eval\(function[\s\S].*)\s*').findall(istek.text)[0]
1921
m3u_link = StreamDecoder.extract_stream_url(Packer.unpack(eval_func))
2022

23+
# Subtitle'ları parse et (Kotlin referansı: track elementleri)
24+
subtitles = []
25+
secici = Selector(istek.text)
26+
for track in secici.css("track"):
27+
raw_src = track.css("::attr(src)").get() or ""
28+
raw_src = raw_src.strip()
29+
label = track.css("::attr(label)").get() or track.css("::attr(srclang)").get() or "Altyazı"
30+
31+
if raw_src:
32+
full_url = raw_src if raw_src.startswith("http") else f"{self.main_url}{raw_src}"
33+
subtitles.append(Subtitle(name=label, url=full_url))
34+
2135
return ExtractResult(
2236
name = self.name,
2337
url = m3u_link,
2438
referer = self.main_url,
25-
subtitles = []
39+
subtitles = subtitles
2640
)
41+

‎KekikStream/Plugins/FullHDFilm.py‎

Lines changed: 68 additions & 17 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
22

3-
from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo, ExtractResult, Subtitle
3+
from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo, SeriesInfo, Episode, ExtractResult, Subtitle
44
from parsel import Selector
55
import re, base64
66

@@ -69,14 +69,13 @@ async def search(self, query: str) -> list[SearchResult]:
6969
if veri.css("img::attr(alt)").get()
7070
]
7171

72-
async def load_item(self, url: str) -> MovieInfo:
72+
async def load_item(self, url: str) -> MovieInfo | SeriesInfo:
7373
istek = await self.httpx.get(url)
7474
secici = Selector(istek.text)
7575

76-
title = secici.css("h1::text").get()
77-
poster = self.fix_url(secici.css("div.poster img::attr(src)").get())
78-
description = secici.css("div#details div.text::text").get() or \
79-
secici.css("div#details div::text").get()
76+
title = secici.css("h1::text").get() or ""
77+
title = title.strip() if title else ""
78+
poster = self.fix_url(secici.css("div.poster img::attr(src)").get() or "")
8079

8180
actors_text = secici.css("div.oyuncular.info::text").get()
8281
if actors_text:
@@ -89,20 +88,72 @@ async def load_item(self, url: str) -> MovieInfo:
8988
tags = secici.css("div.tur.info a::text").getall()
9089
rating = secici.css("div.imdb::text").re_first(r"IMDb\s*([\d\.]+)")
9190

92-
# Açıklama usually above .others
91+
# Description
9392
description = secici.xpath("//div[contains(@class, 'others')]/preceding-sibling::div[1]//text()").getall()
9493
description = "".join(description).strip() if description else None
9594

96-
return MovieInfo(
97-
url = url,
98-
poster = poster,
99-
title = self.clean_title(title) if title else "",
100-
description = description,
101-
tags = tags,
102-
year = year,
103-
actors = actors,
104-
rating = rating.strip() if rating else None,
105-
)
95+
# Kotlin referansı: URL'de -dizi kontrolü veya tags içinde "dizi" kontrolü
96+
is_series = "-dizi" in url.lower() or any("dizi" in tag.lower() for tag in tags)
97+
98+
if is_series:
99+
episodes = []
100+
part_elements = secici.css("li.psec")
101+
part_names = secici.css("li.psec a::text").getall()
102+
103+
# pdata değerlerini çıkar
104+
pdata_matches = re.findall(r"pdata\['([^']+)'\]\s*=\s*'([^']+)'", istek.text)
105+
106+
for idx, (part_id, part_name) in enumerate(zip([el.css("::attr(id)").get() for el in part_elements], part_names)):
107+
if not part_name:
108+
continue
109+
110+
part_name = part_name.strip()
111+
112+
# Fragman'ları atla
113+
if "fragman" in part_name.lower() or (part_id and "fragman" in part_id.lower()):
114+
continue
115+
116+
# Sezon ve bölüm numarası çıkar
117+
sz_match = re.search(r'(\d+)\s*sezon', part_id.lower() if part_id else "")
118+
ep_match = re.search(r'^(\d+)\.', part_name)
119+
120+
sz_num = int(sz_match.group(1)) if sz_match else 1
121+
ep_num = int(ep_match.group(1)) if ep_match else idx + 1
122+
123+
# pdata'dan video URL'si çık (varsa)
124+
video_url = url # Varsayılan olarak ana URL kullan
125+
if idx < len(pdata_matches):
126+
video_url = pdata_matches[idx][1] if pdata_matches[idx][1] else url
127+
128+
episodes.append(Episode(
129+
season = sz_num,
130+
episode = ep_num,
131+
title = f"{sz_num}. Sezon {ep_num}. Bölüm",
132+
url = url # Bölüm URL'leri load_links'te işlenecek
133+
))
134+
135+
return SeriesInfo(
136+
url = url,
137+
poster = poster,
138+
title = self.clean_title(title) if title else "",
139+
description = description,
140+
tags = tags,
141+
year = year,
142+
actors = actors,
143+
rating = rating.strip() if rating else None,
144+
episodes = episodes
145+
)
146+
else:
147+
return MovieInfo(
148+
url = url,
149+
poster = poster,
150+
title = self.clean_title(title) if title else "",
151+
description = description,
152+
tags = tags,
153+
year = year,
154+
actors = actors,
155+
rating = rating.strip() if rating else None,
156+
)
106157

107158
def _get_iframe(self, source_code: str) -> str:
108159
"""Base64 kodlu iframe'i çözümle"""

‎KekikStream/Plugins/HDFilmCehennemi.py‎

Lines changed: 61 additions & 21 deletions
Original file line numberDiff line numberDiff line change
@@ -1,6 +1,6 @@
11
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
22

3-
from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo, Subtitle
3+
from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo, SeriesInfo, Episode, Subtitle
44
from parsel import Selector
55
from Kekik.Sifreleme import Packer, StreamDecoder
66
import random, string, re
@@ -71,36 +71,76 @@ async def search(self, query: str) -> list[SearchResult]:
7171

7272
return results
7373

74-
async def load_item(self, url: str) -> MovieInfo:
74+
async def load_item(self, url: str) -> MovieInfo | SeriesInfo:
7575
istek = await self.httpx.get(url, headers = {"Referer": f"{self.main_url}/"})
7676
secici = Selector(istek.text)
7777

78-
title = secici.css("h1.section-title::text").get().strip()
79-
poster = secici.css("aside.post-info-poster img.lazyload::attr(data-src)").get().strip()
80-
description = secici.css("article.post-info-content > p::text").get().strip()
78+
title = secici.css("h1.section-title::text").get()
79+
title = title.strip() if title else ""
80+
poster = secici.css("aside.post-info-poster img.lazyload::attr(data-src)").get() or ""
81+
poster = poster.strip() if poster else ""
82+
description = secici.css("article.post-info-content > p::text").get() or ""
83+
description = description.strip() if description else ""
8184
tags = secici.css("div.post-info-genres a::text").getall()
82-
rating = secici.css("div.post-info-imdb-rating span::text").get().strip()
83-
year = secici.css("div.post-info-year-country a::text").get().strip()
85+
rating = secici.css("div.post-info-imdb-rating span::text").get() or ""
86+
rating = rating.strip() if rating else ""
87+
year = secici.css("div.post-info-year-country a::text").get() or ""
88+
year = year.strip() if year else ""
8489
actors = secici.css("div.post-info-cast a > strong::text").getall()
85-
duration = secici.css("div.post-info-duration::text").get().replace("dakika", "").strip()
90+
duration = secici.css("div.post-info-duration::text").get() or "0"
91+
duration = duration.replace("dakika", "").strip()
8692

87-
8893
try:
89-
duration_minutes = int(duration[2:-1])
94+
duration_minutes = int(re.search(r'\d+', duration).group()) if re.search(r'\d+', duration) else 0
9095
except Exception:
9196
duration_minutes = 0
9297

93-
return MovieInfo(
94-
url = url,
95-
poster = self.fix_url(poster),
96-
title = self.clean_title(title),
97-
description = description,
98-
tags = tags,
99-
rating = rating,
100-
year = year,
101-
actors = actors,
102-
duration = duration_minutes
103-
)
98+
# Dizi mi film mi kontrol et (Kotlin referansı: div.seasons kontrolü)
99+
is_series = len(secici.css("div.seasons").getall()) > 0
100+
101+
if is_series:
102+
episodes = []
103+
for ep in secici.css("div.seasons-tab-content a"):
104+
ep_name = ep.css("h4::text").get()
105+
ep_href = ep.css("::attr(href)").get()
106+
if ep_name and ep_href:
107+
ep_name = ep_name.strip()
108+
# Regex ile sezon ve bölüm numarası çıkar
109+
ep_match = re.search(r'(\d+)\.\s*Bölüm', ep_name)
110+
sz_match = re.search(r'(\d+)\.\s*Sezon', ep_name)
111+
ep_num = int(ep_match.group(1)) if ep_match else 1
112+
sz_num = int(sz_match.group(1)) if sz_match else 1
113+
114+
episodes.append(Episode(
115+
season = sz_num,
116+
episode = ep_num,
117+
title = ep_name,
118+
url = self.fix_url(ep_href)
119+
))
120+
121+
return SeriesInfo(
122+
url = url,
123+
poster = self.fix_url(poster),
124+
title = self.clean_title(title),
125+
description = description,
126+
tags = tags,
127+
rating = rating,
128+
year = year,
129+
actors = actors,
130+
episodes = episodes
131+
)
132+
else:
133+
return MovieInfo(
134+
url = url,
135+
poster = self.fix_url(poster),
136+
title = self.clean_title(title),
137+
description = description,
138+
tags = tags,
139+
rating = rating,
140+
year = year,
141+
actors = actors,
142+
duration = duration_minutes
143+
)
104144

105145
def generate_random_cookie(self):
106146
return "".join(random.choices(string.ascii_letters + string.digits, k=16))

0 commit comments

Comments
 (0)