KekikStream 2.3.9__py3-none-any.whl → 2.5.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/Extractor/ExtractorLoader.py +8 -14
- KekikStream/Core/HTMLHelper.py +120 -49
- KekikStream/Core/Plugin/PluginBase.py +30 -12
- KekikStream/Core/Plugin/PluginLoader.py +12 -14
- KekikStream/Core/Plugin/PluginManager.py +2 -2
- KekikStream/Core/Plugin/PluginModels.py +0 -3
- KekikStream/Extractors/Abstream.py +27 -0
- 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 +21 -46
- KekikStream/Extractors/HDMomPlayer.py +30 -0
- KekikStream/Extractors/HDPlayerSystem.py +13 -31
- KekikStream/Extractors/HotStream.py +27 -0
- KekikStream/Extractors/JFVid.py +3 -24
- KekikStream/Extractors/JetTv.py +21 -34
- KekikStream/Extractors/JetV.py +55 -0
- 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 +40 -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/Veev.py +145 -0
- KekikStream/Extractors/VidBiz.py +62 -0
- KekikStream/Extractors/VidHide.py +58 -30
- 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 +58 -0
- KekikStream/Extractors/Vidoza.py +18 -0
- KekikStream/Extractors/Vtbe.py +38 -0
- KekikStream/Extractors/YTDLP.py +2 -2
- KekikStream/Extractors/YildizKisaFilm.py +13 -31
- KekikStream/Extractors/Zeus.py +61 -0
- KekikStream/Plugins/BelgeselX.py +97 -77
- KekikStream/Plugins/DiziBox.py +28 -45
- KekikStream/Plugins/DiziMom.py +179 -0
- KekikStream/Plugins/DiziPal.py +95 -161
- KekikStream/Plugins/DiziYou.py +51 -147
- KekikStream/Plugins/Dizilla.py +40 -61
- KekikStream/Plugins/FilmBip.py +90 -39
- KekikStream/Plugins/FilmEkseni.py +199 -0
- KekikStream/Plugins/FilmMakinesi.py +72 -73
- KekikStream/Plugins/FilmModu.py +25 -35
- KekikStream/Plugins/Filmatek.py +184 -0
- KekikStream/Plugins/FilmciBaba.py +155 -0
- KekikStream/Plugins/FullHDFilmizlesene.py +16 -37
- KekikStream/Plugins/HDFilm.py +243 -0
- KekikStream/Plugins/HDFilmCehennemi.py +242 -189
- KekikStream/Plugins/JetFilmizle.py +101 -69
- KekikStream/Plugins/KultFilmler.py +138 -104
- KekikStream/Plugins/RecTV.py +52 -73
- KekikStream/Plugins/RoketDizi.py +18 -27
- KekikStream/Plugins/SelcukFlix.py +30 -48
- KekikStream/Plugins/SetFilmIzle.py +76 -104
- KekikStream/Plugins/SezonlukDizi.py +90 -94
- KekikStream/Plugins/Sinefy.py +195 -167
- KekikStream/Plugins/SinemaCX.py +148 -78
- KekikStream/Plugins/Sinezy.py +29 -31
- KekikStream/Plugins/SuperFilmGeldi.py +12 -17
- KekikStream/Plugins/UgurFilm.py +85 -38
- KekikStream/Plugins/Watch32.py +160 -0
- KekikStream/Plugins/YabanciDizi.py +176 -211
- {kekikstream-2.3.9.dist-info → kekikstream-2.5.3.dist-info}/METADATA +1 -1
- kekikstream-2.5.3.dist-info/RECORD +99 -0
- {kekikstream-2.3.9.dist-info → kekikstream-2.5.3.dist-info}/WHEEL +1 -1
- KekikStream/Plugins/FullHDFilm.py +0 -249
- kekikstream-2.3.9.dist-info/RECORD +0 -84
- {kekikstream-2.3.9.dist-info → kekikstream-2.5.3.dist-info}/entry_points.txt +0 -0
- {kekikstream-2.3.9.dist-info → kekikstream-2.5.3.dist-info}/licenses/LICENSE +0 -0
- {kekikstream-2.3.9.dist-info → kekikstream-2.5.3.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
|
+
|
|
3
|
+
from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo, ExtractResult, HTMLHelper
|
|
4
|
+
import asyncio
|
|
5
|
+
|
|
6
|
+
class FilmEkseni(PluginBase):
|
|
7
|
+
name = "FilmEkseni"
|
|
8
|
+
language = "tr"
|
|
9
|
+
main_url = "https://filmekseni.cc"
|
|
10
|
+
favicon = f"https://www.google.com/s2/favicons?domain={main_url}&sz=64"
|
|
11
|
+
description = "Film Ekseni ⚡️ Vizyonda ki, en güncel ve en yeni filmleri full hd kalitesinde türkçe dublaj ve altyazı seçenekleriyle 1080p olarak izleyebileceğiniz adresiniz."
|
|
12
|
+
|
|
13
|
+
main_page = {
|
|
14
|
+
f"{main_url}/tur/aile-filmleri/page" : "Aile Filmleri",
|
|
15
|
+
f"{main_url}/tur/aksiyon-filmleri/page" : "Aksiyon Filmleri",
|
|
16
|
+
f"{main_url}/tur/animasyon-film-izle/page" : "Animasyon Filmleri",
|
|
17
|
+
f"{main_url}/tur/bilim-kurgu-filmleri/page" : "Bilim Kurgu Filmleri",
|
|
18
|
+
f"{main_url}/tur/biyografi-filmleri/page" : "Biyografi Filmleri",
|
|
19
|
+
f"{main_url}/tur/dram-filmleri-izle/page" : "Dram Filmleri",
|
|
20
|
+
f"{main_url}/tur/fantastik-filmler/page" : "Fantastik Filmleri",
|
|
21
|
+
f"{main_url}/tur/gerilim-filmleri/page" : "Gerilim Filmleri",
|
|
22
|
+
f"{main_url}/tur/gizem-filmleri/page" : "Gizem Filmleri",
|
|
23
|
+
f"{main_url}/tur/komedi-filmleri/page" : "Komedi Filmleri",
|
|
24
|
+
f"{main_url}/tur/korku-filmleri/page" : "Korku Filmleri",
|
|
25
|
+
f"{main_url}/tur/macera-filmleri/page" : "Macera Filmleri",
|
|
26
|
+
f"{main_url}/tur/romantik-filmler/page" : "Romantik Filmleri",
|
|
27
|
+
f"{main_url}/tur/savas-filmleri/page" : "Savaş Filmleri",
|
|
28
|
+
f"{main_url}/tur/suc-filmleri/page" : "Suç Filmleri",
|
|
29
|
+
f"{main_url}/tur/tarih-filmleri/page" : "Tarih Filmleri",
|
|
30
|
+
}
|
|
31
|
+
|
|
32
|
+
async def get_main_page(self, page: int, url: str, category: str) -> list[MainPageResult]:
|
|
33
|
+
istek = await self.httpx.get(f"{url}/{page}/")
|
|
34
|
+
secici = HTMLHelper(istek.text)
|
|
35
|
+
posters = secici.select("div.poster")
|
|
36
|
+
|
|
37
|
+
return [
|
|
38
|
+
MainPageResult(
|
|
39
|
+
category = category,
|
|
40
|
+
title = self.clean_title(secici.select_text("h2", veri)),
|
|
41
|
+
url = secici.select_attr("a", "href", veri),
|
|
42
|
+
poster = secici.select_attr("img", "data-src", veri)
|
|
43
|
+
)
|
|
44
|
+
for veri in posters
|
|
45
|
+
]
|
|
46
|
+
|
|
47
|
+
async def search(self, query: str) -> list[SearchResult]:
|
|
48
|
+
istek = await self.httpx.post(
|
|
49
|
+
url = f"{self.main_url}/search/",
|
|
50
|
+
headers = {
|
|
51
|
+
"X-Requested-With" : "XMLHttpRequest",
|
|
52
|
+
"Content-Type" : "application/x-www-form-urlencoded; charset=UTF-8",
|
|
53
|
+
"Referer" : self.main_url,
|
|
54
|
+
},
|
|
55
|
+
data = {"query": query}
|
|
56
|
+
)
|
|
57
|
+
|
|
58
|
+
veriler = istek.json().get("result", [])
|
|
59
|
+
|
|
60
|
+
return [
|
|
61
|
+
SearchResult(
|
|
62
|
+
title = veri.get("title"),
|
|
63
|
+
url = f"{self.main_url}/{veri.get('slug')}",
|
|
64
|
+
poster = f"{self.main_url}/uploads/poster/{veri.get('cover')}" if veri.get('cover') else None,
|
|
65
|
+
)
|
|
66
|
+
for veri in veriler
|
|
67
|
+
]
|
|
68
|
+
|
|
69
|
+
async def load_item(self, url: str) -> MovieInfo:
|
|
70
|
+
istek = await self.httpx.get(url)
|
|
71
|
+
secici = HTMLHelper(istek.text)
|
|
72
|
+
|
|
73
|
+
title = self.clean_title(secici.select_text("div.page-title h1"))
|
|
74
|
+
poster = secici.select_poster("picture.poster-auto img")
|
|
75
|
+
description = secici.select_direct_text("article.text-white p")
|
|
76
|
+
year = secici.extract_year("div.page-title", "strong a")
|
|
77
|
+
tags = secici.select_texts("div.pb-2 a[href*='/tur/']")
|
|
78
|
+
rating = secici.select_text("div.rate")
|
|
79
|
+
duration = secici.regex_first(r"(\d+)", secici.select_text("div.d-flex.flex-column.text-nowrap"))
|
|
80
|
+
actors = secici.select_texts("div.card-body.p-0.pt-2 .story-item .story-item-title")
|
|
81
|
+
|
|
82
|
+
return MovieInfo(
|
|
83
|
+
url = url,
|
|
84
|
+
poster = self.fix_url(poster),
|
|
85
|
+
title = title,
|
|
86
|
+
description = description,
|
|
87
|
+
tags = tags,
|
|
88
|
+
rating = rating,
|
|
89
|
+
year = year,
|
|
90
|
+
actors = actors,
|
|
91
|
+
duration = duration
|
|
92
|
+
)
|
|
93
|
+
|
|
94
|
+
async def _get_source_links(self, name: str, url: str, is_active: bool, initial_helper: HTMLHelper | None = None) -> list[ExtractResult]:
|
|
95
|
+
try:
|
|
96
|
+
if is_active and initial_helper:
|
|
97
|
+
secici = initial_helper
|
|
98
|
+
else:
|
|
99
|
+
resp = await self.httpx.get(url)
|
|
100
|
+
secici = HTMLHelper(resp.text)
|
|
101
|
+
|
|
102
|
+
iframe = secici.select_first("div.card-video iframe")
|
|
103
|
+
if not iframe:
|
|
104
|
+
return []
|
|
105
|
+
|
|
106
|
+
iframe_url = iframe.attrs.get("data-src") or iframe.attrs.get("src")
|
|
107
|
+
if not iframe_url:
|
|
108
|
+
return []
|
|
109
|
+
|
|
110
|
+
iframe_url = self.fix_url(iframe_url)
|
|
111
|
+
results = []
|
|
112
|
+
|
|
113
|
+
# VIP / EksenLoad mantığı
|
|
114
|
+
if "eksenload" in iframe_url or name == "VIP":
|
|
115
|
+
video_id = iframe_url.split("/")[-1]
|
|
116
|
+
master_url = f"https://eksenload.site/uploads/encode/{video_id}/master.m3u8"
|
|
117
|
+
results.append(ExtractResult(
|
|
118
|
+
url = master_url,
|
|
119
|
+
name = name,
|
|
120
|
+
referer = self.main_url
|
|
121
|
+
))
|
|
122
|
+
else:
|
|
123
|
+
# Diğerleri (Moly, vs.) için extract
|
|
124
|
+
# Name override: "Kaynak Adı | Player Adı" olacak şekilde
|
|
125
|
+
extracted = await self.extract(iframe_url, name_override=name)
|
|
126
|
+
if extracted:
|
|
127
|
+
if isinstance(extracted, list):
|
|
128
|
+
results.extend(extracted)
|
|
129
|
+
else:
|
|
130
|
+
results.append(extracted)
|
|
131
|
+
|
|
132
|
+
return results
|
|
133
|
+
except Exception:
|
|
134
|
+
return []
|
|
135
|
+
|
|
136
|
+
async def load_links(self, url: str) -> list[ExtractResult]:
|
|
137
|
+
istek = await self.httpx.get(url)
|
|
138
|
+
secici = HTMLHelper(istek.text)
|
|
139
|
+
|
|
140
|
+
# Dil sekmelerini bul (Dublaj, Altyazı vb.)
|
|
141
|
+
# Fragman vb. linkleri dahil etmemek için sadece 'a.nav-link' bakıyoruz
|
|
142
|
+
lang_tabs = [
|
|
143
|
+
tab for tab in secici.select("ul.nav-tabs.nav-slider a.nav-link")
|
|
144
|
+
if "fragman" not in tab.text().lower()
|
|
145
|
+
]
|
|
146
|
+
|
|
147
|
+
# Player panellerini bul
|
|
148
|
+
tab_panes = secici.select("div.tab-pane")
|
|
149
|
+
|
|
150
|
+
sources = [] # (name, url, is_active)
|
|
151
|
+
|
|
152
|
+
# Eğer dil sekmeleri ve paneller eşleşiyorsa (ideal durum)
|
|
153
|
+
if lang_tabs and tab_panes:
|
|
154
|
+
for i, pane in enumerate(tab_panes):
|
|
155
|
+
if i >= len(lang_tabs):
|
|
156
|
+
break
|
|
157
|
+
|
|
158
|
+
lang_name = lang_tabs[i].text(strip=True)
|
|
159
|
+
player_links = secici.select("a.nav-link", element=pane)
|
|
160
|
+
|
|
161
|
+
for link in player_links:
|
|
162
|
+
p_name = link.text(strip=True)
|
|
163
|
+
if not p_name or any(x in p_name.lower() for x in ["paylaş", "indir", "hata"]):
|
|
164
|
+
continue
|
|
165
|
+
|
|
166
|
+
href = link.attrs.get("href")
|
|
167
|
+
if not href or href == "#":
|
|
168
|
+
continue
|
|
169
|
+
|
|
170
|
+
# Yeni isim "Moly | Türkçe Dublaj"
|
|
171
|
+
full_name = f"{p_name} | {lang_name}"
|
|
172
|
+
is_active = "active" in link.attrs.get("class", "")
|
|
173
|
+
|
|
174
|
+
sources.append((full_name, self.fix_url(href), is_active))
|
|
175
|
+
|
|
176
|
+
# Eğer panel yapısı beklediğimizden farklıysa eski mantığa dön
|
|
177
|
+
if not sources:
|
|
178
|
+
if nav_links := secici.select("nav.card-nav a.nav-link"):
|
|
179
|
+
seen_urls = set()
|
|
180
|
+
for link in nav_links:
|
|
181
|
+
if link.attrs.get("href") == "#":
|
|
182
|
+
continue # Sinema Modu vb.
|
|
183
|
+
|
|
184
|
+
name = link.text(strip=True)
|
|
185
|
+
href = link.attrs.get("href")
|
|
186
|
+
is_active = "active" in link.attrs.get("class", "")
|
|
187
|
+
|
|
188
|
+
if href and href not in seen_urls:
|
|
189
|
+
seen_urls.add(href)
|
|
190
|
+
sources.append((name, self.fix_url(href), is_active))
|
|
191
|
+
else:
|
|
192
|
+
# Nav yoksa mevcut sayfayı (Varsayılan/VIP) al
|
|
193
|
+
sources.append(("VIP", url, True))
|
|
194
|
+
|
|
195
|
+
tasks = []
|
|
196
|
+
for name, link_url, is_active in sources:
|
|
197
|
+
tasks.append(self._get_source_links(name, link_url, is_active, secici if is_active else None))
|
|
198
|
+
|
|
199
|
+
return [item for sublist in await asyncio.gather(*tasks) for item in sublist]
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
2
|
|
|
3
|
-
from KekikStream.Core
|
|
3
|
+
from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo, SeriesInfo, Episode, ExtractResult, HTMLHelper
|
|
4
4
|
|
|
5
5
|
class FilmMakinesi(PluginBase):
|
|
6
6
|
name = "FilmMakinesi"
|
|
@@ -39,8 +39,8 @@ class FilmMakinesi(PluginBase):
|
|
|
39
39
|
|
|
40
40
|
results = []
|
|
41
41
|
for veri in secici.select("div.item-relative"):
|
|
42
|
-
title
|
|
43
|
-
href
|
|
42
|
+
title = secici.select_text("div.title", veri)
|
|
43
|
+
href = secici.select_attr("a", "href", veri)
|
|
44
44
|
poster = secici.select_poster("img", veri)
|
|
45
45
|
|
|
46
46
|
if title and href:
|
|
@@ -48,7 +48,7 @@ class FilmMakinesi(PluginBase):
|
|
|
48
48
|
category = category,
|
|
49
49
|
title = title,
|
|
50
50
|
url = self.fix_url(href),
|
|
51
|
-
poster = self.fix_url(poster)
|
|
51
|
+
poster = self.fix_url(poster),
|
|
52
52
|
))
|
|
53
53
|
|
|
54
54
|
return results
|
|
@@ -59,15 +59,15 @@ class FilmMakinesi(PluginBase):
|
|
|
59
59
|
|
|
60
60
|
results = []
|
|
61
61
|
for article in secici.select("div.item-relative"):
|
|
62
|
-
title
|
|
63
|
-
href
|
|
62
|
+
title = secici.select_text("div.title", article)
|
|
63
|
+
href = secici.select_attr("a", "href", article)
|
|
64
64
|
poster = secici.select_poster("img", article)
|
|
65
65
|
|
|
66
66
|
if title and href:
|
|
67
67
|
results.append(SearchResult(
|
|
68
|
-
title = title
|
|
69
|
-
url = self.fix_url(href
|
|
70
|
-
poster = self.fix_url(poster
|
|
68
|
+
title = title,
|
|
69
|
+
url = self.fix_url(href),
|
|
70
|
+
poster = self.fix_url(poster),
|
|
71
71
|
))
|
|
72
72
|
|
|
73
73
|
return results
|
|
@@ -76,88 +76,55 @@ class FilmMakinesi(PluginBase):
|
|
|
76
76
|
istek = await self.httpx.get(url)
|
|
77
77
|
secici = HTMLHelper(istek.text)
|
|
78
78
|
|
|
79
|
-
title
|
|
79
|
+
title = self.clean_title(secici.select_text("h1.title"))
|
|
80
|
+
poster = secici.select_poster("img.cover-img")
|
|
81
|
+
description = secici.select_text("div.info-description")
|
|
82
|
+
rating = secici.select_text("div.info div.imdb b")
|
|
83
|
+
year = secici.select_text("span.date a")
|
|
84
|
+
actors = secici.select_texts("div.cast-name")
|
|
85
|
+
tags = secici.select_texts("div.type a[href*='/tur/']")
|
|
86
|
+
duration = secici.regex_first(r"(\d+)", secici.select_text("div.time"))
|
|
80
87
|
|
|
81
|
-
poster = secici.select_attr("img.cover-img", "src") or ""
|
|
82
|
-
poster = poster.strip()
|
|
83
|
-
|
|
84
|
-
description = secici.select_text("div.info-description p") or ""
|
|
85
|
-
|
|
86
|
-
rating_text = secici.select_text("div.score") or ""
|
|
87
|
-
rating = None
|
|
88
|
-
if rating_text:
|
|
89
|
-
rating = rating_text.split()[0]
|
|
90
|
-
|
|
91
|
-
year = secici.select_text("span.date a") or ""
|
|
92
|
-
|
|
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 "")]
|
|
95
|
-
|
|
96
|
-
duration = None
|
|
97
|
-
duration_text = secici.select_text("div.time") or None
|
|
98
|
-
if duration_text:
|
|
99
|
-
parts = duration_text.split()
|
|
100
|
-
if len(parts) > 1:
|
|
101
|
-
duration = parts[1].strip()
|
|
102
|
-
|
|
103
|
-
# Dizi mi kontrol et - sezon/bölüm linkleri var mı?
|
|
104
88
|
episodes = []
|
|
105
|
-
|
|
106
|
-
for link in all_links:
|
|
89
|
+
for link in secici.select("a[href]"):
|
|
107
90
|
href = link.attrs.get("href", "")
|
|
108
|
-
|
|
109
|
-
if
|
|
110
|
-
|
|
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
|
-
|
|
91
|
+
s, e = secici.extract_season_episode(href)
|
|
92
|
+
if s and e:
|
|
93
|
+
name = link.text(strip=True).split("Bölüm")[-1].strip() if "Bölüm" in link.text() else ""
|
|
123
94
|
episodes.append(Episode(
|
|
124
|
-
season =
|
|
125
|
-
episode =
|
|
126
|
-
title =
|
|
95
|
+
season = s,
|
|
96
|
+
episode = e,
|
|
97
|
+
title = name,
|
|
127
98
|
url = self.fix_url(href)
|
|
128
99
|
))
|
|
129
|
-
|
|
130
|
-
#
|
|
100
|
+
|
|
101
|
+
# Tekrar edenleri temizle ve sırala
|
|
131
102
|
if episodes:
|
|
132
|
-
# Tekrar eden bölümleri kaldır
|
|
133
103
|
seen = set()
|
|
134
|
-
|
|
104
|
+
unique = []
|
|
135
105
|
for ep in episodes:
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
# Sırala
|
|
142
|
-
unique_episodes.sort(key=lambda x: (x.season or 0, x.episode or 0))
|
|
143
|
-
|
|
106
|
+
if (ep.season, ep.episode) not in seen:
|
|
107
|
+
seen.add((ep.season, ep.episode))
|
|
108
|
+
unique.append(ep)
|
|
109
|
+
unique.sort(key=lambda x: (x.season or 0, x.episode or 0))
|
|
110
|
+
|
|
144
111
|
return SeriesInfo(
|
|
145
112
|
url = url,
|
|
146
|
-
poster = self.fix_url(poster)
|
|
147
|
-
title =
|
|
113
|
+
poster = self.fix_url(poster),
|
|
114
|
+
title = title,
|
|
148
115
|
description = description,
|
|
149
116
|
tags = tags,
|
|
150
117
|
rating = rating,
|
|
151
118
|
year = year,
|
|
152
119
|
actors = actors,
|
|
153
120
|
duration = duration,
|
|
154
|
-
episodes =
|
|
121
|
+
episodes = unique
|
|
155
122
|
)
|
|
156
123
|
|
|
157
124
|
return MovieInfo(
|
|
158
125
|
url = url,
|
|
159
|
-
poster = self.fix_url(poster)
|
|
160
|
-
title =
|
|
126
|
+
poster = self.fix_url(poster),
|
|
127
|
+
title = title,
|
|
161
128
|
description = description,
|
|
162
129
|
tags = tags,
|
|
163
130
|
rating = rating,
|
|
@@ -170,7 +137,8 @@ class FilmMakinesi(PluginBase):
|
|
|
170
137
|
istek = await self.httpx.get(url)
|
|
171
138
|
secici = HTMLHelper(istek.text)
|
|
172
139
|
|
|
173
|
-
response
|
|
140
|
+
response = []
|
|
141
|
+
shared_subs = []
|
|
174
142
|
|
|
175
143
|
# Video parts linklerini ve etiketlerini al
|
|
176
144
|
for link in secici.select("div.video-parts a[data-video_url]"):
|
|
@@ -180,7 +148,15 @@ class FilmMakinesi(PluginBase):
|
|
|
180
148
|
if video_url:
|
|
181
149
|
data = await self.extract(video_url, prefix=label.split()[0] if label else None)
|
|
182
150
|
if data:
|
|
183
|
-
|
|
151
|
+
if isinstance(data, list):
|
|
152
|
+
for d in data:
|
|
153
|
+
response.append(d)
|
|
154
|
+
if d.subtitles:
|
|
155
|
+
shared_subs.extend(d.subtitles)
|
|
156
|
+
else:
|
|
157
|
+
response.append(data)
|
|
158
|
+
if data.subtitles:
|
|
159
|
+
shared_subs.extend(data.subtitles)
|
|
184
160
|
|
|
185
161
|
# Eğer video-parts yoksa iframe kullan
|
|
186
162
|
if not response:
|
|
@@ -188,6 +164,29 @@ class FilmMakinesi(PluginBase):
|
|
|
188
164
|
if iframe_src:
|
|
189
165
|
data = await self.extract(iframe_src)
|
|
190
166
|
if data:
|
|
191
|
-
|
|
167
|
+
if isinstance(data, list):
|
|
168
|
+
for d in data:
|
|
169
|
+
response.append(d)
|
|
170
|
+
if d.subtitles:
|
|
171
|
+
shared_subs.extend(d.subtitles)
|
|
172
|
+
else:
|
|
173
|
+
response.append(data)
|
|
174
|
+
if data.subtitles:
|
|
175
|
+
shared_subs.extend(data.subtitles)
|
|
176
|
+
|
|
177
|
+
# Altyazıları Dağıt
|
|
178
|
+
if shared_subs:
|
|
179
|
+
unique_subs = []
|
|
180
|
+
seen_urls = set()
|
|
181
|
+
for sub in shared_subs:
|
|
182
|
+
if sub.url not in seen_urls:
|
|
183
|
+
seen_urls.add(sub.url)
|
|
184
|
+
unique_subs.append(sub)
|
|
185
|
+
|
|
186
|
+
for res in response:
|
|
187
|
+
current_urls = {s.url for s in res.subtitles}
|
|
188
|
+
for sub in unique_subs:
|
|
189
|
+
if sub.url not in current_urls:
|
|
190
|
+
res.subtitles.append(sub)
|
|
192
191
|
|
|
193
192
|
return response
|
KekikStream/Plugins/FilmModu.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
2
|
|
|
3
|
-
from KekikStream.Core
|
|
3
|
+
from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo, Subtitle, ExtractResult, HTMLHelper
|
|
4
4
|
|
|
5
5
|
class FilmModu(PluginBase):
|
|
6
6
|
name = "FilmModu"
|
|
@@ -44,8 +44,8 @@ class FilmModu(PluginBase):
|
|
|
44
44
|
|
|
45
45
|
results = []
|
|
46
46
|
for veri in secici.select("div.movie"):
|
|
47
|
-
title
|
|
48
|
-
href
|
|
47
|
+
title = secici.select_text("a", veri)
|
|
48
|
+
href = secici.select_attr("a", "href", veri)
|
|
49
49
|
poster = secici.select_attr("picture img", "data-src", veri)
|
|
50
50
|
|
|
51
51
|
if title and href:
|
|
@@ -53,7 +53,7 @@ class FilmModu(PluginBase):
|
|
|
53
53
|
category = category,
|
|
54
54
|
title = title,
|
|
55
55
|
url = self.fix_url(href),
|
|
56
|
-
poster = self.fix_url(poster)
|
|
56
|
+
poster = self.fix_url(poster),
|
|
57
57
|
))
|
|
58
58
|
|
|
59
59
|
return results
|
|
@@ -64,15 +64,15 @@ class FilmModu(PluginBase):
|
|
|
64
64
|
|
|
65
65
|
results = []
|
|
66
66
|
for veri in secici.select("div.movie"):
|
|
67
|
-
title
|
|
68
|
-
href
|
|
67
|
+
title = secici.select_text("a", veri)
|
|
68
|
+
href = secici.select_attr("a", "href", veri)
|
|
69
69
|
poster = secici.select_attr("picture img", "data-src", veri)
|
|
70
70
|
|
|
71
71
|
if title and href:
|
|
72
72
|
results.append(SearchResult(
|
|
73
73
|
title = title,
|
|
74
74
|
url = self.fix_url(href),
|
|
75
|
-
poster = self.fix_url(poster)
|
|
75
|
+
poster = self.fix_url(poster),
|
|
76
76
|
))
|
|
77
77
|
|
|
78
78
|
return results
|
|
@@ -81,32 +81,25 @@ class FilmModu(PluginBase):
|
|
|
81
81
|
istek = await self.httpx.get(url)
|
|
82
82
|
secici = HTMLHelper(istek.text)
|
|
83
83
|
|
|
84
|
-
org_title
|
|
85
|
-
alt_title
|
|
86
|
-
title
|
|
87
|
-
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
|
|
91
|
-
|
|
92
|
-
|
|
93
|
-
|
|
94
|
-
year = secici.select_text("span[itemprop='dateCreated']") or None
|
|
95
|
-
|
|
96
|
-
actors = []
|
|
97
|
-
for a in secici.select("a[itemprop='actor']"):
|
|
98
|
-
name = secici.select_text("span", a)
|
|
99
|
-
if name:
|
|
100
|
-
actors.append(name)
|
|
84
|
+
org_title = secici.select_text("div.titles h1")
|
|
85
|
+
alt_title = secici.select_text("div.titles h2")
|
|
86
|
+
title = f"{org_title} - {alt_title}" if alt_title else (org_title)
|
|
87
|
+
poster = secici.select_poster("img.img-responsive")
|
|
88
|
+
description = secici.select_text("p[itemprop='description']")
|
|
89
|
+
tags = secici.select_texts("a[href*='film-tur/']")
|
|
90
|
+
rating = secici.meta_value("IMDB")
|
|
91
|
+
year = secici.extract_year("span[itemprop='dateCreated']")
|
|
92
|
+
actors = secici.select_texts("a[itemprop='actor'] span")
|
|
101
93
|
|
|
102
94
|
return MovieInfo(
|
|
103
95
|
url = url,
|
|
104
|
-
poster = self.fix_url(poster)
|
|
96
|
+
poster = self.fix_url(poster),
|
|
105
97
|
title = title,
|
|
106
98
|
description = description,
|
|
107
99
|
tags = tags,
|
|
100
|
+
rating = rating,
|
|
108
101
|
year = year,
|
|
109
|
-
actors = actors
|
|
102
|
+
actors = actors
|
|
110
103
|
)
|
|
111
104
|
|
|
112
105
|
async def load_links(self, url: str) -> list[ExtractResult]:
|
|
@@ -118,7 +111,6 @@ class FilmModu(PluginBase):
|
|
|
118
111
|
return []
|
|
119
112
|
|
|
120
113
|
results = []
|
|
121
|
-
|
|
122
114
|
for alternatif in alternates:
|
|
123
115
|
alt_link = alternatif.attrs.get("href")
|
|
124
116
|
alt_name = alternatif.text(strip=True)
|
|
@@ -126,20 +118,18 @@ class FilmModu(PluginBase):
|
|
|
126
118
|
if alt_name == "Fragman" or not alt_link:
|
|
127
119
|
continue
|
|
128
120
|
|
|
129
|
-
alt_link
|
|
121
|
+
alt_link = self.fix_url(alt_link)
|
|
130
122
|
alt_istek = await self.httpx.get(alt_link)
|
|
131
|
-
|
|
123
|
+
secici = HTMLHelper(alt_istek.text)
|
|
132
124
|
|
|
133
|
-
vid_id =
|
|
134
|
-
vid_type =
|
|
125
|
+
vid_id = secici.regex_first(r"var videoId = '([^']*)'")
|
|
126
|
+
vid_type = secici.regex_first(r"var videoType = '([^']*)'")
|
|
135
127
|
|
|
136
128
|
if not vid_id or not vid_type:
|
|
137
129
|
continue
|
|
138
130
|
|
|
139
|
-
source_istek = await self.httpx.get(
|
|
140
|
-
|
|
141
|
-
)
|
|
142
|
-
source_data = source_istek.json()
|
|
131
|
+
source_istek = await self.httpx.get(f"{self.main_url}/get-source?movie_id={vid_id}&type={vid_type}")
|
|
132
|
+
source_data = source_istek.json()
|
|
143
133
|
|
|
144
134
|
if source_data.get("subtitle"):
|
|
145
135
|
subtitle_url = self.fix_url(source_data["subtitle"])
|