KekikStream 1.7.1__py3-none-any.whl → 2.2.0__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 +20 -9
- KekikStream/Core/Extractor/ExtractorLoader.py +25 -17
- KekikStream/Core/Extractor/ExtractorManager.py +53 -9
- KekikStream/Core/Extractor/ExtractorModels.py +5 -7
- KekikStream/Core/Extractor/YTDLPCache.py +35 -0
- KekikStream/Core/Media/MediaHandler.py +44 -26
- KekikStream/Core/Media/MediaManager.py +0 -3
- KekikStream/Core/Plugin/PluginBase.py +82 -22
- KekikStream/Core/Plugin/PluginLoader.py +11 -7
- KekikStream/Core/Plugin/PluginModels.py +25 -26
- KekikStream/Core/__init__.py +1 -0
- KekikStream/Extractors/CloseLoad.py +21 -7
- KekikStream/Extractors/ContentX.py +21 -6
- KekikStream/Extractors/DonilasPlay.py +86 -0
- KekikStream/Extractors/DzenRu.py +38 -0
- KekikStream/Extractors/ExPlay.py +53 -0
- KekikStream/Extractors/Filemoon.py +78 -0
- KekikStream/Extractors/HDPlayerSystem.py +41 -0
- KekikStream/Extractors/JetTv.py +45 -0
- KekikStream/Extractors/MailRu.py +3 -4
- KekikStream/Extractors/MixPlayHD.py +2 -3
- KekikStream/Extractors/MixTiger.py +57 -0
- KekikStream/Extractors/MolyStream.py +5 -5
- KekikStream/Extractors/Odnoklassniki.py +13 -7
- KekikStream/Extractors/PeaceMakerst.py +10 -5
- KekikStream/Extractors/PixelDrain.py +1 -2
- KekikStream/Extractors/PlayerFilmIzle.py +65 -0
- KekikStream/Extractors/RapidVid.py +23 -8
- KekikStream/Extractors/SetPlay.py +66 -0
- KekikStream/Extractors/SetPrime.py +45 -0
- KekikStream/Extractors/SibNet.py +2 -3
- KekikStream/Extractors/Sobreatsesuyp.py +4 -5
- KekikStream/Extractors/TRsTX.py +4 -5
- KekikStream/Extractors/TauVideo.py +2 -3
- KekikStream/Extractors/TurboImgz.py +2 -3
- KekikStream/Extractors/TurkeyPlayer.py +34 -0
- KekikStream/Extractors/VCTPlay.py +41 -0
- KekikStream/Extractors/VidHide.py +81 -0
- KekikStream/Extractors/VidMoly.py +55 -34
- KekikStream/Extractors/VidMoxy.py +2 -3
- KekikStream/Extractors/VidPapi.py +89 -0
- KekikStream/Extractors/VideoSeyred.py +3 -4
- KekikStream/Extractors/YTDLP.py +211 -0
- KekikStream/Extractors/YildizKisaFilm.py +41 -0
- KekikStream/Plugins/BelgeselX.py +196 -0
- KekikStream/Plugins/DiziBox.py +25 -34
- KekikStream/Plugins/DiziPal.py +24 -35
- KekikStream/Plugins/DiziYou.py +54 -37
- KekikStream/Plugins/Dizilla.py +66 -46
- KekikStream/Plugins/FilmBip.py +142 -0
- KekikStream/Plugins/FilmMakinesi.py +36 -28
- KekikStream/Plugins/FilmModu.py +20 -24
- KekikStream/Plugins/FullHDFilm.py +220 -0
- KekikStream/Plugins/FullHDFilmizlesene.py +9 -15
- KekikStream/Plugins/HDFilmCehennemi.py +141 -69
- KekikStream/Plugins/JetFilmizle.py +85 -52
- KekikStream/Plugins/KultFilmler.py +217 -0
- KekikStream/Plugins/RecTV.py +22 -34
- KekikStream/Plugins/RoketDizi.py +222 -0
- KekikStream/Plugins/SelcukFlix.py +328 -0
- KekikStream/Plugins/SetFilmIzle.py +252 -0
- KekikStream/Plugins/SezonlukDizi.py +54 -21
- KekikStream/Plugins/SineWix.py +17 -29
- KekikStream/Plugins/Sinefy.py +241 -0
- KekikStream/Plugins/SinemaCX.py +154 -0
- KekikStream/Plugins/Sinezy.py +143 -0
- KekikStream/Plugins/SuperFilmGeldi.py +130 -0
- KekikStream/Plugins/UgurFilm.py +13 -19
- KekikStream/__init__.py +47 -56
- KekikStream/requirements.txt +3 -4
- kekikstream-2.2.0.dist-info/METADATA +312 -0
- kekikstream-2.2.0.dist-info/RECORD +81 -0
- KekikStream/Extractors/FourCX.py +0 -7
- KekikStream/Extractors/FourPichive.py +0 -7
- KekikStream/Extractors/FourPlayRu.py +0 -7
- KekikStream/Extractors/HDStreamAble.py +0 -7
- KekikStream/Extractors/Hotlinger.py +0 -7
- KekikStream/Extractors/OkRuHTTP.py +0 -7
- KekikStream/Extractors/OkRuSSL.py +0 -7
- KekikStream/Extractors/Pichive.py +0 -7
- KekikStream/Extractors/PlayRu.py +0 -7
- KekikStream/Extractors/VidMolyMe.py +0 -7
- kekikstream-1.7.1.dist-info/METADATA +0 -109
- kekikstream-1.7.1.dist-info/RECORD +0 -63
- {kekikstream-1.7.1.dist-info → kekikstream-2.2.0.dist-info}/WHEEL +0 -0
- {kekikstream-1.7.1.dist-info → kekikstream-2.2.0.dist-info}/entry_points.txt +0 -0
- {kekikstream-1.7.1.dist-info → kekikstream-2.2.0.dist-info}/licenses/LICENSE +0 -0
- {kekikstream-1.7.1.dist-info → kekikstream-2.2.0.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,252 @@
|
|
|
1
|
+
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
|
+
|
|
3
|
+
from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo, SeriesInfo, Episode, ExtractResult
|
|
4
|
+
from parsel import Selector
|
|
5
|
+
import re, json
|
|
6
|
+
|
|
7
|
+
class SetFilmIzle(PluginBase):
|
|
8
|
+
name = "SetFilmIzle"
|
|
9
|
+
language = "tr"
|
|
10
|
+
main_url = "https://www.setfilmizle.uk"
|
|
11
|
+
favicon = f"https://www.google.com/s2/favicons?domain={main_url}&sz=64"
|
|
12
|
+
description = "Setfilmizle sitemizde, donma yaşamadan Türkçe dublaj ve altyazılı filmleri ile dizileri muhteşem 1080p full HD kalitesinde izleyebilirsiniz."
|
|
13
|
+
|
|
14
|
+
main_page = {
|
|
15
|
+
f"{main_url}/tur/aile/" : "Aile",
|
|
16
|
+
f"{main_url}/tur/aksiyon/" : "Aksiyon",
|
|
17
|
+
f"{main_url}/tur/animasyon/" : "Animasyon",
|
|
18
|
+
f"{main_url}/tur/belgesel/" : "Belgesel",
|
|
19
|
+
f"{main_url}/tur/bilim-kurgu/" : "Bilim-Kurgu",
|
|
20
|
+
f"{main_url}/tur/biyografi/" : "Biyografi",
|
|
21
|
+
f"{main_url}/tur/dini/" : "Dini",
|
|
22
|
+
f"{main_url}/tur/dram/" : "Dram",
|
|
23
|
+
f"{main_url}/tur/fantastik/" : "Fantastik",
|
|
24
|
+
f"{main_url}/tur/genclik/" : "Gençlik",
|
|
25
|
+
f"{main_url}/tur/gerilim/" : "Gerilim",
|
|
26
|
+
f"{main_url}/tur/gizem/" : "Gizem",
|
|
27
|
+
f"{main_url}/tur/komedi/" : "Komedi",
|
|
28
|
+
f"{main_url}/tur/korku/" : "Korku",
|
|
29
|
+
f"{main_url}/tur/macera/" : "Macera",
|
|
30
|
+
f"{main_url}/tur/romantik/" : "Romantik",
|
|
31
|
+
f"{main_url}/tur/savas/" : "Savaş",
|
|
32
|
+
f"{main_url}/tur/suc/" : "Suç",
|
|
33
|
+
f"{main_url}/tur/tarih/" : "Tarih",
|
|
34
|
+
f"{main_url}/tur/western/" : "Western"
|
|
35
|
+
}
|
|
36
|
+
|
|
37
|
+
def _get_nonce(self, nonce_type: str = "video_nonce", referer: str = None) -> str:
|
|
38
|
+
"""Site cache'lenmiş nonce'ları expire olabiliyor, fresh nonce al"""
|
|
39
|
+
try:
|
|
40
|
+
resp = self.cloudscraper.post(
|
|
41
|
+
f"{self.main_url}/wp-admin/admin-ajax.php",
|
|
42
|
+
headers = {
|
|
43
|
+
"Referer" : referer or self.main_url,
|
|
44
|
+
"Origin" : self.main_url,
|
|
45
|
+
"Content-Type" : "application/x-www-form-urlencoded",
|
|
46
|
+
},
|
|
47
|
+
data = "action=st_cache_refresh_nonces"
|
|
48
|
+
)
|
|
49
|
+
nonces = resp.json().get("data", {}).get("nonces", {})
|
|
50
|
+
return nonces.get(nonce_type, "")
|
|
51
|
+
except:
|
|
52
|
+
return ""
|
|
53
|
+
|
|
54
|
+
async def get_main_page(self, page: int, url: str, category: str) -> list[MainPageResult]:
|
|
55
|
+
istek = self.cloudscraper.get(url)
|
|
56
|
+
secici = Selector(istek.text)
|
|
57
|
+
|
|
58
|
+
results = []
|
|
59
|
+
for item in secici.css("div.items article"):
|
|
60
|
+
title = item.css("h2::text").get()
|
|
61
|
+
href = item.css("a::attr(href)").get()
|
|
62
|
+
poster = item.css("img::attr(data-src)").get()
|
|
63
|
+
|
|
64
|
+
if title and href:
|
|
65
|
+
results.append(MainPageResult(
|
|
66
|
+
category = category,
|
|
67
|
+
title = title.strip(),
|
|
68
|
+
url = self.fix_url(href),
|
|
69
|
+
poster = self.fix_url(poster) if poster else None
|
|
70
|
+
))
|
|
71
|
+
|
|
72
|
+
return results
|
|
73
|
+
|
|
74
|
+
async def search(self, query: str) -> list[SearchResult]:
|
|
75
|
+
nonce = self._get_nonce("search")
|
|
76
|
+
|
|
77
|
+
search_resp = self.cloudscraper.post(
|
|
78
|
+
f"{self.main_url}/wp-admin/admin-ajax.php",
|
|
79
|
+
headers = {
|
|
80
|
+
"X-Requested-With" : "XMLHttpRequest",
|
|
81
|
+
"Content-Type" : "application/x-www-form-urlencoded",
|
|
82
|
+
"Referer" : f"{self.main_url}/"
|
|
83
|
+
},
|
|
84
|
+
data = {
|
|
85
|
+
"action" : "ajax_search",
|
|
86
|
+
"search" : query,
|
|
87
|
+
"original_search" : query,
|
|
88
|
+
"nonce" : nonce
|
|
89
|
+
}
|
|
90
|
+
)
|
|
91
|
+
|
|
92
|
+
try:
|
|
93
|
+
data = search_resp.json()
|
|
94
|
+
html = data.get("html", "")
|
|
95
|
+
except:
|
|
96
|
+
return []
|
|
97
|
+
|
|
98
|
+
secici = Selector(text=html)
|
|
99
|
+
results = []
|
|
100
|
+
|
|
101
|
+
for item in secici.css("div.items article"):
|
|
102
|
+
title = item.css("h2::text").get()
|
|
103
|
+
href = item.css("a::attr(href)").get()
|
|
104
|
+
poster = item.css("img::attr(data-src)").get()
|
|
105
|
+
|
|
106
|
+
if title and href:
|
|
107
|
+
results.append(SearchResult(
|
|
108
|
+
title = title.strip(),
|
|
109
|
+
url = self.fix_url(href),
|
|
110
|
+
poster = self.fix_url(poster) if poster else None
|
|
111
|
+
))
|
|
112
|
+
|
|
113
|
+
return results
|
|
114
|
+
|
|
115
|
+
async def load_item(self, url: str) -> MovieInfo | SeriesInfo:
|
|
116
|
+
istek = await self.httpx.get(url)
|
|
117
|
+
secici = Selector(istek.text)
|
|
118
|
+
|
|
119
|
+
raw_title = secici.css("h1::text").get() or ""
|
|
120
|
+
title = re.sub(r"\s*izle.*$", "", raw_title, flags=re.IGNORECASE).strip()
|
|
121
|
+
poster = secici.css("div.poster img::attr(src)").get()
|
|
122
|
+
description = secici.css("div.wp-content p::text").get()
|
|
123
|
+
year = secici.css("div.extra span.C a::text").get()
|
|
124
|
+
if year:
|
|
125
|
+
year_match = re.search(r"\d{4}", year)
|
|
126
|
+
year = year_match.group() if year_match else None
|
|
127
|
+
tags = [a.css("::text").get().strip() for a in secici.css("div.sgeneros a") if a.css("::text").get()]
|
|
128
|
+
duration = secici.css("span.runtime::text").get()
|
|
129
|
+
if duration:
|
|
130
|
+
dur_match = re.search(r"\d+", duration)
|
|
131
|
+
duration = int(dur_match.group()) if dur_match else None
|
|
132
|
+
|
|
133
|
+
actors = [span.css("::text").get().strip() for span in secici.css("span.valor a > span") if span.css("::text").get()]
|
|
134
|
+
|
|
135
|
+
trailer_match = re.search(r'embed/([^?]*)\?rel', istek.text)
|
|
136
|
+
trailer = f"https://www.youtube.com/embed/{trailer_match.group(1)}" if trailer_match else None
|
|
137
|
+
|
|
138
|
+
# Dizi mi film mi kontrol et
|
|
139
|
+
is_series = "/dizi/" in url
|
|
140
|
+
|
|
141
|
+
if is_series:
|
|
142
|
+
year_elem = secici.css("a[href*='/yil/']::text").get()
|
|
143
|
+
if year_elem:
|
|
144
|
+
year_match = re.search(r"\d{4}", year_elem)
|
|
145
|
+
year = year_match.group() if year_match else year
|
|
146
|
+
|
|
147
|
+
dur_elem = secici.css("div#info span:contains('Dakika')::text").get()
|
|
148
|
+
if dur_elem:
|
|
149
|
+
dur_match = re.search(r"\d+", dur_elem)
|
|
150
|
+
duration = int(dur_match.group()) if dur_match else duration
|
|
151
|
+
|
|
152
|
+
episodes = []
|
|
153
|
+
for ep_item in secici.css("div#episodes ul.episodios li"):
|
|
154
|
+
ep_href = ep_item.css("h4.episodiotitle a::attr(href)").get()
|
|
155
|
+
ep_name = ep_item.css("h4.episodiotitle a::text").get()
|
|
156
|
+
|
|
157
|
+
if not ep_href or not ep_name:
|
|
158
|
+
continue
|
|
159
|
+
|
|
160
|
+
ep_detail = ep_name.strip()
|
|
161
|
+
season_match = re.search(r"(\d+)\.\s*Sezon", ep_detail)
|
|
162
|
+
episode_match = re.search(r"Sezon\s+(\d+)\.\s*Bölüm", ep_detail)
|
|
163
|
+
|
|
164
|
+
ep_season = int(season_match.group(1)) if season_match else 1
|
|
165
|
+
ep_episode = int(episode_match.group(1)) if episode_match else None
|
|
166
|
+
|
|
167
|
+
episodes.append(Episode(
|
|
168
|
+
season = ep_season,
|
|
169
|
+
episode = ep_episode,
|
|
170
|
+
title = ep_name.strip(),
|
|
171
|
+
url = self.fix_url(ep_href)
|
|
172
|
+
))
|
|
173
|
+
|
|
174
|
+
return SeriesInfo(
|
|
175
|
+
url = url,
|
|
176
|
+
poster = self.fix_url(poster) if poster else None,
|
|
177
|
+
title = title,
|
|
178
|
+
description = description.strip() if description else None,
|
|
179
|
+
tags = tags,
|
|
180
|
+
year = year,
|
|
181
|
+
duration = duration,
|
|
182
|
+
actors = actors,
|
|
183
|
+
episodes = episodes
|
|
184
|
+
)
|
|
185
|
+
|
|
186
|
+
return MovieInfo(
|
|
187
|
+
url = url,
|
|
188
|
+
poster = self.fix_url(poster) if poster else None,
|
|
189
|
+
title = title,
|
|
190
|
+
description = description.strip() if description else None,
|
|
191
|
+
tags = tags,
|
|
192
|
+
year = year,
|
|
193
|
+
duration = duration,
|
|
194
|
+
actors = actors
|
|
195
|
+
)
|
|
196
|
+
|
|
197
|
+
async def load_links(self, url: str) -> list[ExtractResult]:
|
|
198
|
+
istek = await self.httpx.get(url)
|
|
199
|
+
secici = Selector(istek.text)
|
|
200
|
+
|
|
201
|
+
nonce = self._get_nonce("video_nonce", referer=url)
|
|
202
|
+
|
|
203
|
+
# partKey to dil label mapping
|
|
204
|
+
part_key_labels = {
|
|
205
|
+
"turkcedublaj" : "Türkçe Dublaj",
|
|
206
|
+
"turkcealtyazi" : "Türkçe Altyazı",
|
|
207
|
+
"orijinal" : "Orijinal"
|
|
208
|
+
}
|
|
209
|
+
|
|
210
|
+
links = []
|
|
211
|
+
for player in secici.css("nav.player a"):
|
|
212
|
+
source_id = player.css("::attr(data-post-id)").get()
|
|
213
|
+
player_name = player.css("::attr(data-player-name)").get()
|
|
214
|
+
part_key = player.css("::attr(data-part-key)").get()
|
|
215
|
+
|
|
216
|
+
if not source_id or "event" in source_id or source_id == "":
|
|
217
|
+
continue
|
|
218
|
+
|
|
219
|
+
try:
|
|
220
|
+
resp = self.cloudscraper.post(
|
|
221
|
+
f"{self.main_url}/wp-admin/admin-ajax.php",
|
|
222
|
+
headers = {"Referer": url},
|
|
223
|
+
data = {
|
|
224
|
+
"action" : "get_video_url",
|
|
225
|
+
"nonce" : nonce,
|
|
226
|
+
"post_id" : source_id,
|
|
227
|
+
"player_name" : player_name or "",
|
|
228
|
+
"part_key" : part_key or ""
|
|
229
|
+
}
|
|
230
|
+
)
|
|
231
|
+
data = resp.json()
|
|
232
|
+
except:
|
|
233
|
+
continue
|
|
234
|
+
|
|
235
|
+
iframe_url = data.get("data", {}).get("url")
|
|
236
|
+
if not iframe_url:
|
|
237
|
+
continue
|
|
238
|
+
|
|
239
|
+
# SetPlay URL'si için part_key ekleme
|
|
240
|
+
if "setplay" not in iframe_url and part_key:
|
|
241
|
+
iframe_url = f"{iframe_url}?partKey={part_key}"
|
|
242
|
+
|
|
243
|
+
# Dil etiketi oluştur
|
|
244
|
+
label = part_key_labels.get(part_key, "")
|
|
245
|
+
if not label and part_key:
|
|
246
|
+
label = part_key.replace("_", " ").title()
|
|
247
|
+
|
|
248
|
+
data = await self.extract(iframe_url, prefix=label if label else None)
|
|
249
|
+
if data:
|
|
250
|
+
links.append(data)
|
|
251
|
+
|
|
252
|
+
return links
|
|
@@ -1,7 +1,8 @@
|
|
|
1
1
|
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
2
|
|
|
3
|
-
from KekikStream.Core import
|
|
3
|
+
from KekikStream.Core import PluginBase, MainPageResult, SearchResult, SeriesInfo, Episode, ExtractResult
|
|
4
4
|
from parsel import Selector
|
|
5
|
+
import re
|
|
5
6
|
|
|
6
7
|
class SezonlukDizi(PluginBase):
|
|
7
8
|
name = "SezonlukDizi"
|
|
@@ -19,11 +20,27 @@ class SezonlukDizi(PluginBase):
|
|
|
19
20
|
f"{main_url}/diziler.asp?siralama_tipi=id&kat=4&s=" : "Animasyonlar",
|
|
20
21
|
f"{main_url}/diziler.asp?siralama_tipi=id&kat=5&s=" : "Animeler",
|
|
21
22
|
f"{main_url}/diziler.asp?siralama_tipi=id&kat=6&s=" : "Belgeseller",
|
|
23
|
+
f"{main_url}/diziler.asp?siralama_tipi=id&tur=aile&s=" : "Aile",
|
|
24
|
+
f"{main_url}/diziler.asp?siralama_tipi=id&tur=aksiyon&s=" : "Aksiyon",
|
|
25
|
+
f"{main_url}/diziler.asp?siralama_tipi=id&tur=bilimkurgu&s=" : "Bilim Kurgu",
|
|
26
|
+
f"{main_url}/diziler.asp?siralama_tipi=id&tur=biyografik&s=" : "Biyografi",
|
|
27
|
+
f"{main_url}/diziler.asp?siralama_tipi=id&tur=dram&s=" : "Dram",
|
|
28
|
+
f"{main_url}/diziler.asp?siralama_tipi=id&tur=fantastik&s=" : "Fantastik",
|
|
29
|
+
f"{main_url}/diziler.asp?siralama_tipi=id&tur=gerilim&s=" : "Gerilim",
|
|
30
|
+
f"{main_url}/diziler.asp?siralama_tipi=id&tur=gizem&s=" : "Gizem",
|
|
31
|
+
f"{main_url}/diziler.asp?siralama_tipi=id&tur=korku&s=" : "Korku",
|
|
32
|
+
f"{main_url}/diziler.asp?siralama_tipi=id&tur=komedi&s=" : "Komedi",
|
|
33
|
+
f"{main_url}/diziler.asp?siralama_tipi=id&tur=macera&s=" : "Macera",
|
|
34
|
+
f"{main_url}/diziler.asp?siralama_tipi=id&tur=muzikal&s=" : "Müzikal",
|
|
35
|
+
f"{main_url}/diziler.asp?siralama_tipi=id&tur=suc&s=" : "Suç",
|
|
36
|
+
f"{main_url}/diziler.asp?siralama_tipi=id&tur=romantik&s=" : "Romantik",
|
|
37
|
+
f"{main_url}/diziler.asp?siralama_tipi=id&tur=savas&s=" : "Savaş",
|
|
38
|
+
f"{main_url}/diziler.asp?siralama_tipi=id&tur=tarihi&s=" : "Tarihi",
|
|
39
|
+
f"{main_url}/diziler.asp?siralama_tipi=id&tur=western&s=" : "Western"
|
|
22
40
|
}
|
|
23
41
|
|
|
24
|
-
#@kekik_cache(ttl=60*60)
|
|
25
42
|
async def get_main_page(self, page: int, url: str, category: str) -> list[MainPageResult]:
|
|
26
|
-
istek = await self.
|
|
43
|
+
istek = await self.httpx.get(f"{url}{page}")
|
|
27
44
|
secici = Selector(istek.text)
|
|
28
45
|
|
|
29
46
|
return [
|
|
@@ -36,9 +53,8 @@ class SezonlukDizi(PluginBase):
|
|
|
36
53
|
for veri in secici.css("div.afis a") if veri.css("div.description::text").get()
|
|
37
54
|
]
|
|
38
55
|
|
|
39
|
-
#@kekik_cache(ttl=60*60)
|
|
40
56
|
async def search(self, query: str) -> list[SearchResult]:
|
|
41
|
-
istek = await self.
|
|
57
|
+
istek = await self.httpx.get(f"{self.main_url}/diziler.asp?adi={query}")
|
|
42
58
|
secici = Selector(istek.text)
|
|
43
59
|
|
|
44
60
|
return [
|
|
@@ -50,9 +66,8 @@ class SezonlukDizi(PluginBase):
|
|
|
50
66
|
for afis in secici.css("div.afis a.column")
|
|
51
67
|
]
|
|
52
68
|
|
|
53
|
-
#@kekik_cache(ttl=60*60)
|
|
54
69
|
async def load_item(self, url: str) -> SeriesInfo:
|
|
55
|
-
istek = await self.
|
|
70
|
+
istek = await self.httpx.get(url)
|
|
56
71
|
secici = Selector(istek.text)
|
|
57
72
|
|
|
58
73
|
title = secici.css("div.header::text").get().strip()
|
|
@@ -63,14 +78,14 @@ class SezonlukDizi(PluginBase):
|
|
|
63
78
|
rating = secici.css("div.dizipuani a div::text").re_first(r"[\d.,]+")
|
|
64
79
|
actors = []
|
|
65
80
|
|
|
66
|
-
actors_istek = await self.
|
|
81
|
+
actors_istek = await self.httpx.get(f"{self.main_url}/oyuncular/{url.split('/')[-1]}")
|
|
67
82
|
actors_secici = Selector(actors_istek.text)
|
|
68
83
|
actors = [
|
|
69
84
|
actor.css("div.header::text").get().strip()
|
|
70
85
|
for actor in actors_secici.css("div.doubling div.ui")
|
|
71
86
|
]
|
|
72
87
|
|
|
73
|
-
episodes_istek = await self.
|
|
88
|
+
episodes_istek = await self.httpx.get(f"{self.main_url}/bolumler/{url.split('/')[-1]}")
|
|
74
89
|
episodes_secici = Selector(episodes_istek.text)
|
|
75
90
|
episodes = []
|
|
76
91
|
|
|
@@ -102,19 +117,35 @@ class SezonlukDizi(PluginBase):
|
|
|
102
117
|
actors = actors
|
|
103
118
|
)
|
|
104
119
|
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
120
|
+
async def get_asp_data(self) -> tuple[str, str]:
|
|
121
|
+
"""Fetch dynamic ASP version numbers from site.min.js"""
|
|
122
|
+
try:
|
|
123
|
+
js_content = await self.httpx.get(f"{self.main_url}/js/site.min.js")
|
|
124
|
+
alternatif_match = re.search(r'dataAlternatif(.*?)\.asp', js_content.text)
|
|
125
|
+
embed_match = re.search(r'dataEmbed(.*?)\.asp', js_content.text)
|
|
126
|
+
|
|
127
|
+
alternatif_ver = alternatif_match.group(1) if alternatif_match else "22"
|
|
128
|
+
embed_ver = embed_match.group(1) if embed_match else "22"
|
|
129
|
+
|
|
130
|
+
return (alternatif_ver, embed_ver)
|
|
131
|
+
except Exception:
|
|
132
|
+
return ("22", "22") # Fallback to default versions
|
|
133
|
+
|
|
134
|
+
async def load_links(self, url: str) -> list[ExtractResult]:
|
|
135
|
+
istek = await self.httpx.get(url)
|
|
108
136
|
secici = Selector(istek.text)
|
|
109
137
|
|
|
110
138
|
bid = secici.css("div#dilsec::attr(data-id)").get()
|
|
111
139
|
if not bid:
|
|
112
140
|
return []
|
|
113
141
|
|
|
142
|
+
# Get dynamic ASP versions
|
|
143
|
+
alternatif_ver, embed_ver = await self.get_asp_data()
|
|
144
|
+
|
|
114
145
|
results = []
|
|
115
146
|
for dil, label in [("1", "Altyazı"), ("0", "Dublaj")]:
|
|
116
|
-
dil_istek = await self.
|
|
117
|
-
url = f"{self.main_url}/ajax/
|
|
147
|
+
dil_istek = await self.httpx.post(
|
|
148
|
+
url = f"{self.main_url}/ajax/dataAlternatif{alternatif_ver}.asp",
|
|
118
149
|
headers = {"X-Requested-With": "XMLHttpRequest"},
|
|
119
150
|
data = {"bid": bid, "dil": dil},
|
|
120
151
|
)
|
|
@@ -126,18 +157,20 @@ class SezonlukDizi(PluginBase):
|
|
|
126
157
|
|
|
127
158
|
if dil_json.get("status") == "success":
|
|
128
159
|
for idx, veri in enumerate(dil_json.get("data", [])):
|
|
129
|
-
veri_response = await self.
|
|
130
|
-
url = f"{self.main_url}/ajax/
|
|
160
|
+
veri_response = await self.httpx.post(
|
|
161
|
+
url = f"{self.main_url}/ajax/dataEmbed{embed_ver}.asp",
|
|
131
162
|
headers = {"X-Requested-With": "XMLHttpRequest"},
|
|
132
163
|
data = {"id": veri.get("id")},
|
|
133
164
|
)
|
|
134
165
|
secici = Selector(veri_response.text)
|
|
135
166
|
|
|
136
167
|
if iframe := secici.css("iframe::attr(src)").get():
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
168
|
+
if "link.asp" in iframe:
|
|
169
|
+
continue
|
|
170
|
+
|
|
171
|
+
iframe_url = self.fix_url(iframe)
|
|
172
|
+
data = await self.extract(iframe_url, prefix=label)
|
|
173
|
+
if data:
|
|
174
|
+
results.append(data)
|
|
142
175
|
|
|
143
176
|
return results
|
KekikStream/Plugins/SineWix.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 import
|
|
3
|
+
from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo, Episode, SeriesInfo, ExtractResult
|
|
4
4
|
import json
|
|
5
5
|
|
|
6
6
|
class SineWix(PluginBase):
|
|
@@ -35,9 +35,8 @@ class SineWix(PluginBase):
|
|
|
35
35
|
f"{main_url}/sinewix/movies/36" : "Tarih",
|
|
36
36
|
}
|
|
37
37
|
|
|
38
|
-
#@kekik_cache(ttl=60*60)
|
|
39
38
|
async def get_main_page(self, page: int, url: str, category: str) -> list[MainPageResult]:
|
|
40
|
-
istek = await self.
|
|
39
|
+
istek = await self.httpx.get(f"{url}/{page}")
|
|
41
40
|
veriler = istek.json()
|
|
42
41
|
|
|
43
42
|
return [
|
|
@@ -50,9 +49,8 @@ class SineWix(PluginBase):
|
|
|
50
49
|
for veri in veriler.get("data")
|
|
51
50
|
]
|
|
52
51
|
|
|
53
|
-
#@kekik_cache(ttl=60*60)
|
|
54
52
|
async def search(self, query: str) -> list[SearchResult]:
|
|
55
|
-
istek = await self.
|
|
53
|
+
istek = await self.httpx.get(f"{self.main_url}/sinewix/search/{query}")
|
|
56
54
|
|
|
57
55
|
return [
|
|
58
56
|
SearchResult(
|
|
@@ -63,12 +61,11 @@ class SineWix(PluginBase):
|
|
|
63
61
|
for veri in istek.json().get("search")
|
|
64
62
|
]
|
|
65
63
|
|
|
66
|
-
#@kekik_cache(ttl=60*60)
|
|
67
64
|
async def load_item(self, url: str) -> MovieInfo | SeriesInfo:
|
|
68
65
|
item_type = url.split("?type=")[-1].split("&id=")[0]
|
|
69
66
|
item_id = url.split("&id=")[-1]
|
|
70
67
|
|
|
71
|
-
istek = await self.
|
|
68
|
+
istek = await self.httpx.get(f"{self.main_url}/sinewix/{item_type}/{item_id}")
|
|
72
69
|
veri = istek.json()
|
|
73
70
|
|
|
74
71
|
match item_type:
|
|
@@ -126,24 +123,23 @@ class SineWix(PluginBase):
|
|
|
126
123
|
episodes = episodes,
|
|
127
124
|
)
|
|
128
125
|
|
|
129
|
-
|
|
130
|
-
async def load_links(self, url: str) -> list[dict]:
|
|
126
|
+
async def load_links(self, url: str) -> list[ExtractResult]:
|
|
131
127
|
try:
|
|
132
128
|
veri = json.loads(url)
|
|
133
129
|
if veri.get("is_episode"):
|
|
134
|
-
return [
|
|
135
|
-
|
|
136
|
-
|
|
137
|
-
|
|
138
|
-
|
|
130
|
+
return [ExtractResult(
|
|
131
|
+
url = veri.get("url"),
|
|
132
|
+
name = veri.get("title"),
|
|
133
|
+
referer = self.main_url
|
|
134
|
+
)]
|
|
139
135
|
except Exception:
|
|
140
136
|
pass
|
|
141
137
|
|
|
142
138
|
# Eğer JSON değilse ve direkt URL ise (eski yapı veya harici link)
|
|
143
139
|
if not url.startswith(self.main_url) and not url.startswith("{"):
|
|
144
|
-
return [
|
|
140
|
+
return [ExtractResult(url=url, name="Video")]
|
|
145
141
|
|
|
146
|
-
istek = await self.
|
|
142
|
+
istek = await self.httpx.get(url)
|
|
147
143
|
veri = istek.json()
|
|
148
144
|
|
|
149
145
|
org_title = veri.get("title")
|
|
@@ -153,18 +149,10 @@ class SineWix(PluginBase):
|
|
|
153
149
|
results = []
|
|
154
150
|
for video in veri.get("videos"):
|
|
155
151
|
video_link = video.get("link").split("_blank\">")[-1]
|
|
156
|
-
results.append(
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
|
|
160
|
-
|
|
152
|
+
results.append(ExtractResult(
|
|
153
|
+
url = video_link,
|
|
154
|
+
name = f"{self.name}",
|
|
155
|
+
referer = self.main_url
|
|
156
|
+
))
|
|
161
157
|
|
|
162
158
|
return results
|
|
163
|
-
|
|
164
|
-
async def play(self, name: str, url: str, referer: str, subtitles: list[Subtitle]):
|
|
165
|
-
extract_result = ExtractResult(name=name, url=url, referer=referer, subtitles=subtitles)
|
|
166
|
-
self.media_handler.title = name
|
|
167
|
-
if self.name not in self.media_handler.title:
|
|
168
|
-
self.media_handler.title = f"{self.name} | {self.media_handler.title}"
|
|
169
|
-
|
|
170
|
-
self.media_handler.play_media(extract_result)
|