KekikStream 2.3.8__tar.gz → 2.3.9__tar.gz
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-2.3.9/KekikStream/Extractors/MolyStream.py +42 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Plugins/DiziBox.py +15 -25
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream.egg-info/PKG-INFO +1 -1
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream.egg-info/SOURCES.txt +0 -1
- {kekikstream-2.3.8 → kekikstream-2.3.9}/PKG-INFO +1 -1
- {kekikstream-2.3.8 → kekikstream-2.3.9}/setup.py +1 -1
- kekikstream-2.3.8/KekikStream/Extractors/MolyStream.py +0 -83
- kekikstream-2.3.8/KekikStream/Plugins/DiziWatch.py +0 -212
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/CLI/__init__.py +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/CLI/pypi_kontrol.py +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Core/Extractor/ExtractorBase.py +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Core/Extractor/ExtractorLoader.py +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Core/Extractor/ExtractorManager.py +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Core/Extractor/ExtractorModels.py +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Core/Extractor/YTDLPCache.py +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Core/HTMLHelper.py +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Core/Media/MediaHandler.py +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Core/Media/MediaManager.py +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Core/Plugin/PluginBase.py +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Core/Plugin/PluginLoader.py +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Core/Plugin/PluginManager.py +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Core/Plugin/PluginModels.py +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Core/UI/UIManager.py +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Core/__init__.py +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Extractors/CloseLoad.py +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Extractors/ContentX.py +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Extractors/DonilasPlay.py +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Extractors/DzenRu.py +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Extractors/ExPlay.py +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Extractors/Filemoon.py +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Extractors/HDPlayerSystem.py +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Extractors/JFVid.py +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Extractors/JetTv.py +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Extractors/MailRu.py +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Extractors/MixPlayHD.py +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Extractors/MixTiger.py +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Extractors/Odnoklassniki.py +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Extractors/PeaceMakerst.py +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Extractors/PixelDrain.py +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Extractors/PlayerFilmIzle.py +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Extractors/RapidVid.py +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Extractors/SetPlay.py +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Extractors/SetPrime.py +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Extractors/SibNet.py +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Extractors/Sobreatsesuyp.py +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Extractors/TRsTX.py +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Extractors/TauVideo.py +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Extractors/TurboImgz.py +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Extractors/TurkeyPlayer.py +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Extractors/VCTPlay.py +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Extractors/VidHide.py +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Extractors/VidMoly.py +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Extractors/VidMoxy.py +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Extractors/VidPapi.py +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Extractors/VideoSeyred.py +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Extractors/YTDLP.py +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Extractors/YildizKisaFilm.py +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Plugins/BelgeselX.py +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Plugins/DiziPal.py +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Plugins/DiziYou.py +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Plugins/Dizilla.py +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Plugins/FilmBip.py +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Plugins/FilmMakinesi.py +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Plugins/FilmModu.py +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Plugins/FullHDFilm.py +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Plugins/FullHDFilmizlesene.py +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Plugins/HDFilmCehennemi.py +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Plugins/JetFilmizle.py +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Plugins/KultFilmler.py +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Plugins/RecTV.py +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Plugins/RoketDizi.py +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Plugins/SelcukFlix.py +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Plugins/SetFilmIzle.py +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Plugins/SezonlukDizi.py +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Plugins/SineWix.py +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Plugins/Sinefy.py +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Plugins/SinemaCX.py +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Plugins/Sinezy.py +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Plugins/SuperFilmGeldi.py +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Plugins/UgurFilm.py +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Plugins/YabanciDizi.py +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/__init__.py +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/__main__.py +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/requirements.txt +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream.egg-info/dependency_links.txt +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream.egg-info/entry_points.txt +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream.egg-info/requires.txt +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream.egg-info/top_level.txt +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/LICENSE +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/MANIFEST.in +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/README.md +0 -0
- {kekikstream-2.3.8 → kekikstream-2.3.9}/setup.cfg +0 -0
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
|
+
|
|
3
|
+
from KekikStream.Core import ExtractorBase, ExtractResult, Subtitle, HTMLHelper
|
|
4
|
+
import re
|
|
5
|
+
|
|
6
|
+
class MolyStream(ExtractorBase):
|
|
7
|
+
name = "MolyStream"
|
|
8
|
+
main_url = "https://dbx.molystream.org"
|
|
9
|
+
|
|
10
|
+
# Birden fazla domain destekle
|
|
11
|
+
supported_domains = [
|
|
12
|
+
"dbx.molystream.org",
|
|
13
|
+
"ydx.molystream.org",
|
|
14
|
+
"yd.sheila.stream",
|
|
15
|
+
"ydf.popcornvakti.net",
|
|
16
|
+
]
|
|
17
|
+
|
|
18
|
+
def can_handle_url(self, url: str) -> bool:
|
|
19
|
+
return any(domain in url for domain in self.supported_domains)
|
|
20
|
+
|
|
21
|
+
async def extract(self, url, referer=None) -> ExtractResult:
|
|
22
|
+
if "doctype html" in url:
|
|
23
|
+
secici = HTMLHelper(url)
|
|
24
|
+
video = secici.select_attr("video#sheplayer source", "src")
|
|
25
|
+
else:
|
|
26
|
+
video = url
|
|
27
|
+
|
|
28
|
+
resp_sec = HTMLHelper(url)
|
|
29
|
+
matches = resp_sec.regex_all(r"addSrtFile\(['\"]([^'\"]+\.srt)['\"]\s*,\s*['\"][a-z]{2}['\"]\s*,\s*['\"]([^'\"]+)['\"]")
|
|
30
|
+
|
|
31
|
+
subtitles = [
|
|
32
|
+
Subtitle(name = name, url = self.fix_url(url))
|
|
33
|
+
for url, name in matches
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
return ExtractResult(
|
|
37
|
+
name = self.name,
|
|
38
|
+
url = video,
|
|
39
|
+
referer = video.replace("/sheila", "") if video else None,
|
|
40
|
+
user_agent = "Mozilla/5.0 (X11; Linux x86_64; rv:101.0) Gecko/20100101 Firefox/101.0",
|
|
41
|
+
subtitles = subtitles
|
|
42
|
+
)
|
|
@@ -167,44 +167,34 @@ class DiziBox(PluginBase):
|
|
|
167
167
|
|
|
168
168
|
crypt_data = iframe_secici.regex_first(r"CryptoJS\.AES\.decrypt\(\"(.*)\",\"", iframe_istek.text)
|
|
169
169
|
crypt_pass = iframe_secici.regex_first(r"\",\"(.*)\"\);", iframe_istek.text)
|
|
170
|
-
|
|
171
|
-
|
|
172
|
-
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
170
|
+
decode = CryptoJS.decrypt(crypt_pass, crypt_data)
|
|
171
|
+
|
|
172
|
+
if video_match := iframe_secici.regex_first(r"file: '(.*)',", decode):
|
|
173
|
+
results.append(video_match)
|
|
174
|
+
else:
|
|
175
|
+
results.append(decode)
|
|
176
176
|
|
|
177
177
|
elif "/player/moly/moly.php" in iframe_link:
|
|
178
178
|
iframe_link = iframe_link.replace("moly.php?h=", "moly.php?wmode=opaque&h=")
|
|
179
|
-
|
|
179
|
+
while True:
|
|
180
180
|
await asyncio.sleep(.3)
|
|
181
181
|
with contextlib.suppress(Exception):
|
|
182
182
|
moly_istek = await self.httpx.get(iframe_link)
|
|
183
183
|
moly_secici = HTMLHelper(moly_istek.text)
|
|
184
184
|
|
|
185
|
-
if atob_data := moly_secici.regex_first(r"unescape\(\"(.*)\"\)"):
|
|
185
|
+
if atob_data := moly_secici.regex_first(r"unescape\(\"(.*)\"\)", moly_istek.text):
|
|
186
186
|
decoded_atob = urllib.parse.unquote(atob_data)
|
|
187
187
|
str_atob = base64.b64decode(decoded_atob).decode("utf-8")
|
|
188
188
|
|
|
189
|
-
|
|
190
|
-
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
results.append(iframe_src)
|
|
196
|
-
break
|
|
197
|
-
elif embed_matches := moly_secici.regex_all(r'iframe.*?src="(.*?)"'):
|
|
198
|
-
for src in embed_matches:
|
|
199
|
-
if "/embed/" in src:
|
|
200
|
-
src = src.replace("/embed/", "/embed/sheila/").replace("vidmoly.me", "vidmoly.net")
|
|
201
|
-
results.append(src)
|
|
202
|
-
break
|
|
189
|
+
iframe_src = HTMLHelper(str_atob).select_attr("div#Player iframe", "src")
|
|
190
|
+
if iframe_src:
|
|
191
|
+
results.append(iframe_src)
|
|
192
|
+
|
|
193
|
+
break
|
|
203
194
|
|
|
204
195
|
elif "/player/haydi.php" in iframe_link:
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
results.append(okru_url)
|
|
196
|
+
okru_url = base64.b64decode(iframe_link.split("?v=")[-1]).decode("utf-8")
|
|
197
|
+
results.append(okru_url)
|
|
208
198
|
|
|
209
199
|
return results
|
|
210
200
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: KekikStream
|
|
3
|
-
Version: 2.3.
|
|
3
|
+
Version: 2.3.9
|
|
4
4
|
Summary: terminal üzerinden medya içeriği aramanızı ve VLC/MPV gibi popüler medya oynatıcılar aracılığıyla doğrudan izlemenizi sağlayan modüler ve genişletilebilir bir bıdı bıdı
|
|
5
5
|
Home-page: https://github.com/keyiflerolsun/KekikStream
|
|
6
6
|
Author: keyiflerolsun
|
|
@@ -64,7 +64,6 @@ KekikStream/Extractors/YildizKisaFilm.py
|
|
|
64
64
|
KekikStream/Plugins/BelgeselX.py
|
|
65
65
|
KekikStream/Plugins/DiziBox.py
|
|
66
66
|
KekikStream/Plugins/DiziPal.py
|
|
67
|
-
KekikStream/Plugins/DiziWatch.py
|
|
68
67
|
KekikStream/Plugins/DiziYou.py
|
|
69
68
|
KekikStream/Plugins/Dizilla.py
|
|
70
69
|
KekikStream/Plugins/FilmBip.py
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: KekikStream
|
|
3
|
-
Version: 2.3.
|
|
3
|
+
Version: 2.3.9
|
|
4
4
|
Summary: terminal üzerinden medya içeriği aramanızı ve VLC/MPV gibi popüler medya oynatıcılar aracılığıyla doğrudan izlemenizi sağlayan modüler ve genişletilebilir bir bıdı bıdı
|
|
5
5
|
Home-page: https://github.com/keyiflerolsun/KekikStream
|
|
6
6
|
Author: keyiflerolsun
|
|
@@ -6,7 +6,7 @@ from io import open
|
|
|
6
6
|
setup(
|
|
7
7
|
# ? Genel Bilgiler
|
|
8
8
|
name = "KekikStream",
|
|
9
|
-
version = "2.3.
|
|
9
|
+
version = "2.3.9",
|
|
10
10
|
url = "https://github.com/keyiflerolsun/KekikStream",
|
|
11
11
|
description = "terminal üzerinden medya içeriği aramanızı ve VLC/MPV gibi popüler medya oynatıcılar aracılığıyla doğrudan izlemenizi sağlayan modüler ve genişletilebilir bir bıdı bıdı",
|
|
12
12
|
keywords = ["KekikStream", "KekikAkademi", "keyiflerolsun"],
|
|
@@ -1,83 +0,0 @@
|
|
|
1
|
-
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
|
-
|
|
3
|
-
from KekikStream.Core import ExtractorBase, ExtractResult, Subtitle, HTMLHelper
|
|
4
|
-
import re
|
|
5
|
-
|
|
6
|
-
class MolyStream(ExtractorBase):
|
|
7
|
-
name = "MolyStream"
|
|
8
|
-
main_url = "https://dbx.molystream.org"
|
|
9
|
-
|
|
10
|
-
# Birden fazla domain destekle
|
|
11
|
-
supported_domains = [
|
|
12
|
-
"dbx.molystream.org",
|
|
13
|
-
"ydx.molystream.org",
|
|
14
|
-
"yd.sheila.stream",
|
|
15
|
-
"ydf.popcornvakti.net",
|
|
16
|
-
]
|
|
17
|
-
|
|
18
|
-
def can_handle_url(self, url: str) -> bool:
|
|
19
|
-
return any(domain in url for domain in self.supported_domains)
|
|
20
|
-
|
|
21
|
-
async def extract(self, url, referer=None) -> ExtractResult:
|
|
22
|
-
if "doctype html" in url.lower():
|
|
23
|
-
text = url
|
|
24
|
-
else:
|
|
25
|
-
# Sheila-style referer fix
|
|
26
|
-
if "/embed/sheila/" in url:
|
|
27
|
-
referer = url.replace("/embed/sheila/", "/embed/")
|
|
28
|
-
|
|
29
|
-
self.httpx.headers.update({
|
|
30
|
-
"User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
|
|
31
|
-
"Referer" : referer or self.main_url
|
|
32
|
-
})
|
|
33
|
-
istek = await self.httpx.get(url, follow_redirects=True)
|
|
34
|
-
text = istek.text
|
|
35
|
-
|
|
36
|
-
# 1. Sheila-style links often have the m3u8 directly as the first http line or in script
|
|
37
|
-
m3u8 = None
|
|
38
|
-
if "#EXTM3U" in text:
|
|
39
|
-
for line in text.splitlines():
|
|
40
|
-
line = line.strip().replace('"', '').replace("'", "")
|
|
41
|
-
if line.startswith("http"):
|
|
42
|
-
m3u8 = line
|
|
43
|
-
break
|
|
44
|
-
|
|
45
|
-
if not m3u8:
|
|
46
|
-
for line in text.splitlines():
|
|
47
|
-
line = line.strip().replace('"', '').replace("'", "")
|
|
48
|
-
if line.startswith("http") and ".m3u8" in line:
|
|
49
|
-
m3u8 = line
|
|
50
|
-
break
|
|
51
|
-
|
|
52
|
-
if not m3u8:
|
|
53
|
-
secici = HTMLHelper(text)
|
|
54
|
-
# 2. Try video tag
|
|
55
|
-
m3u8 = secici.select_attr("video#sheplayer source", "src") or secici.select_attr("video source", "src")
|
|
56
|
-
|
|
57
|
-
if not m3u8:
|
|
58
|
-
# 3. Try regex
|
|
59
|
-
m3u8 = HTMLHelper(text).regex_first(r'["\'](https?://[^"\']+\.m3u8[^"\']*)["\']')
|
|
60
|
-
|
|
61
|
-
if not m3u8:
|
|
62
|
-
# Fallback to any http link in a script if it looks like a video link
|
|
63
|
-
m3u8 = HTMLHelper(text).regex_first(r'["\'](https?://[^"\']+/q/\d+)["\']')
|
|
64
|
-
|
|
65
|
-
if not m3u8:
|
|
66
|
-
m3u8 = url # Final fallback
|
|
67
|
-
|
|
68
|
-
# Subtitles (Sheila style addSrtFile)
|
|
69
|
-
resp_sec = HTMLHelper(text)
|
|
70
|
-
matches = resp_sec.regex_all(r"addSrtFile\(['\"]([^'\"]+\.srt)['\"]\s*,\s*['\"][a-z]{2}['\"]\s*,\s*['\"]([^'\"]+)['\"]")
|
|
71
|
-
|
|
72
|
-
subtitles = [
|
|
73
|
-
Subtitle(name = name, url = self.fix_url(url))
|
|
74
|
-
for url, name in matches
|
|
75
|
-
]
|
|
76
|
-
|
|
77
|
-
return ExtractResult(
|
|
78
|
-
name = self.name,
|
|
79
|
-
url = m3u8,
|
|
80
|
-
referer = url,
|
|
81
|
-
user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
|
|
82
|
-
subtitles = subtitles
|
|
83
|
-
)
|
|
@@ -1,212 +0,0 @@
|
|
|
1
|
-
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
|
-
|
|
3
|
-
from KekikStream.Core import PluginBase, MainPageResult, SearchResult, SeriesInfo, Episode, ExtractResult, HTMLHelper
|
|
4
|
-
import urllib.parse
|
|
5
|
-
|
|
6
|
-
class DiziWatch(PluginBase):
|
|
7
|
-
name = "DiziWatch"
|
|
8
|
-
language = "tr"
|
|
9
|
-
main_url = "https://diziwatch.to"
|
|
10
|
-
favicon = f"https://www.google.com/s2/favicons?domain={main_url}&sz=64"
|
|
11
|
-
description = "Diziwatch; en güncel yabancı dizileri ve animeleri, Türkçe altyazılı ve dublaj seçenekleriyle izleyebileceğiniz platform."
|
|
12
|
-
|
|
13
|
-
main_page = {
|
|
14
|
-
f"{main_url}/episodes" : "Yeni Bölümler",
|
|
15
|
-
"9" : "Aksiyon",
|
|
16
|
-
"17" : "Animasyon",
|
|
17
|
-
"5" : "Bilim Kurgu",
|
|
18
|
-
"2" : "Dram",
|
|
19
|
-
"12" : "Fantastik",
|
|
20
|
-
"3" : "Gizem",
|
|
21
|
-
"4" : "Komedi",
|
|
22
|
-
"8" : "Korku",
|
|
23
|
-
"24" : "Macera",
|
|
24
|
-
"14" : "Müzik",
|
|
25
|
-
"7" : "Romantik",
|
|
26
|
-
"23" : "Spor",
|
|
27
|
-
"1" : "Suç",
|
|
28
|
-
}
|
|
29
|
-
|
|
30
|
-
c_key = ""
|
|
31
|
-
c_value = ""
|
|
32
|
-
|
|
33
|
-
async def _init_session(self):
|
|
34
|
-
# Fetch anime-arsivi to get CSRF tokens
|
|
35
|
-
resp = await self.httpx.get(f"{self.main_url}/anime-arsivi")
|
|
36
|
-
sel = HTMLHelper(resp.text)
|
|
37
|
-
|
|
38
|
-
# form.bg-[rgba(255,255,255,.15)] > input
|
|
39
|
-
# We can just look for the first two inputs in that specific form
|
|
40
|
-
inputs = sel.select("form.bg-\\[rgba\\(255\\,255\\,255\\,\\.15\\)\\] input")
|
|
41
|
-
if len(inputs) >= 2:
|
|
42
|
-
self.c_key = inputs[0].attrs.get("value")
|
|
43
|
-
self.c_value = inputs[1].attrs.get("value")
|
|
44
|
-
|
|
45
|
-
async def get_main_page(self, page: int, url: str, category: str) -> list[MainPageResult]:
|
|
46
|
-
await self._init_session()
|
|
47
|
-
|
|
48
|
-
if url.startswith("https://"):
|
|
49
|
-
full_url = f"{url}?page={page}"
|
|
50
|
-
resp = await self.httpx.get(full_url, headers={"Referer": f"{self.main_url}/"})
|
|
51
|
-
sel = HTMLHelper(resp.text)
|
|
52
|
-
items = sel.select("div.swiper-slide a")
|
|
53
|
-
else:
|
|
54
|
-
# Category ID based
|
|
55
|
-
full_url = f"{self.main_url}/anime-arsivi?category={url}&minImdb=&name=&release_year=&sort=date_desc&page={page}"
|
|
56
|
-
resp = await self.httpx.get(full_url, headers={"Referer": f"{self.main_url}/"})
|
|
57
|
-
sel = HTMLHelper(resp.text)
|
|
58
|
-
items = sel.select("div.content-inner a")
|
|
59
|
-
|
|
60
|
-
results = []
|
|
61
|
-
for item in items:
|
|
62
|
-
title = sel.select_text("h2", item)
|
|
63
|
-
href = item.attrs.get("href") if item.tag == "a" else sel.select_attr("a", "href", item)
|
|
64
|
-
poster = sel.select_attr("img", "src", item) or sel.select_attr("img", "data-src", item)
|
|
65
|
-
|
|
66
|
-
if title and href:
|
|
67
|
-
# If it's an episode link, clean it to get show link
|
|
68
|
-
# Regex in Kotlin: /sezon-\d+/bolum-\d+/?$
|
|
69
|
-
clean_href = HTMLHelper(href).regex_replace(r"/sezon-\d+/bolum-\d+/?$", "")
|
|
70
|
-
|
|
71
|
-
# If cleaning changed something, it was an episode link, maybe add it to title
|
|
72
|
-
if clean_href != href:
|
|
73
|
-
se_info = sel.select_text("div.flex.gap-1.items-center", item)
|
|
74
|
-
if se_info:
|
|
75
|
-
title = f"{title} - {se_info}"
|
|
76
|
-
|
|
77
|
-
results.append(MainPageResult(
|
|
78
|
-
category = category,
|
|
79
|
-
title = title,
|
|
80
|
-
url = self.fix_url(clean_href),
|
|
81
|
-
poster = self.fix_url(poster) if poster else None
|
|
82
|
-
))
|
|
83
|
-
|
|
84
|
-
return results
|
|
85
|
-
|
|
86
|
-
async def search(self, query: str) -> list[SearchResult]:
|
|
87
|
-
await self._init_session()
|
|
88
|
-
|
|
89
|
-
post_url = f"{self.main_url}/bg/searchcontent"
|
|
90
|
-
data = {
|
|
91
|
-
"cKey" : self.c_key,
|
|
92
|
-
"cValue" : self.c_value,
|
|
93
|
-
"searchterm" : query
|
|
94
|
-
}
|
|
95
|
-
|
|
96
|
-
headers = {
|
|
97
|
-
"X-Requested-With" : "XMLHttpRequest",
|
|
98
|
-
"Accept" : "application/json, text/javascript, */*; q=0.01",
|
|
99
|
-
"Referer" : f"{self.main_url}/"
|
|
100
|
-
}
|
|
101
|
-
|
|
102
|
-
resp = await self.httpx.post(post_url, data=data, headers=headers)
|
|
103
|
-
|
|
104
|
-
try:
|
|
105
|
-
raw = resp.json()
|
|
106
|
-
# Kotlin maps this to ApiResponse -> DataWrapper -> Icerikler
|
|
107
|
-
res_array = raw.get("data", {}).get("result", [])
|
|
108
|
-
|
|
109
|
-
results = []
|
|
110
|
-
for item in res_array:
|
|
111
|
-
title = item.get("object_name", "").replace("\\", "")
|
|
112
|
-
slug = item.get("used_slug", "").replace("\\", "")
|
|
113
|
-
poster = item.get("object_poster_url", "")
|
|
114
|
-
|
|
115
|
-
# Cleanup poster URL as in Kotlin
|
|
116
|
-
if poster:
|
|
117
|
-
poster = poster.replace("images-macellan-online.cdn.ampproject.org/i/s/", "") \
|
|
118
|
-
.replace("file.dizilla.club", "file.macellan.online") \
|
|
119
|
-
.replace("images.dizilla.club", "images.macellan.online") \
|
|
120
|
-
.replace("images.dizimia4.com", "images.macellan.online") \
|
|
121
|
-
.replace("file.dizimia4.com", "file.macellan.online")
|
|
122
|
-
poster = HTMLHelper(poster).regex_replace(r"(file\.)[\w\.]+\/?", r"\1macellan.online/")
|
|
123
|
-
poster = HTMLHelper(poster).regex_replace(r"(images\.)[\w\.]+\/?", r"\1macellan.online/")
|
|
124
|
-
poster = poster.replace("/f/f/", "/630/910/")
|
|
125
|
-
|
|
126
|
-
if title and slug:
|
|
127
|
-
results.append(SearchResult(
|
|
128
|
-
title = title,
|
|
129
|
-
url = self.fix_url(slug),
|
|
130
|
-
poster = self.fix_url(poster) if poster else None
|
|
131
|
-
))
|
|
132
|
-
return results
|
|
133
|
-
except Exception:
|
|
134
|
-
return []
|
|
135
|
-
|
|
136
|
-
async def load_item(self, url: str) -> SeriesInfo:
|
|
137
|
-
resp = await self.httpx.get(url)
|
|
138
|
-
sel = HTMLHelper(resp.text)
|
|
139
|
-
|
|
140
|
-
title = sel.select_text("h2") or sel.select_text("h1")
|
|
141
|
-
poster = sel.select_attr("img.rounded-md", "src") or sel.select_attr("meta[property='og:image']", "content")
|
|
142
|
-
description = sel.select_text("div.text-sm") or sel.select_text("div.summary")
|
|
143
|
-
|
|
144
|
-
year = sel.regex_first(r"Yap\u0131m Y\u0131l\u0131\s*:\s*(\d+)", resp.text)
|
|
145
|
-
|
|
146
|
-
tags = []
|
|
147
|
-
tags_raw = sel.regex_first(r"T\u00fcr\s*:\s*([^<]+)", resp.text)
|
|
148
|
-
if tags_raw:
|
|
149
|
-
tags = [t.strip() for t in tags_raw.split(",")]
|
|
150
|
-
|
|
151
|
-
rating = sel.select_text(".font-semibold.text-white")
|
|
152
|
-
if rating:
|
|
153
|
-
rating = rating.replace(",", ".").strip()
|
|
154
|
-
|
|
155
|
-
actors = [a.text(strip=True) for a in sel.select("span.valor a")]
|
|
156
|
-
|
|
157
|
-
trailer_match = sel.regex_first(r"embed\/(.*)\?rel", resp.text)
|
|
158
|
-
trailer = f"https://www.youtube.com/embed/{trailer_match}" if trailer_match else None
|
|
159
|
-
|
|
160
|
-
duration_text = sel.select_text("span.runtime")
|
|
161
|
-
duration = duration_text.split(" ")[0] if duration_text else None
|
|
162
|
-
|
|
163
|
-
episodes = []
|
|
164
|
-
# ul a handles episodes
|
|
165
|
-
for ep_link in sel.select("ul a"):
|
|
166
|
-
href = ep_link.attrs.get("href")
|
|
167
|
-
if not href or "/sezon-" not in href:
|
|
168
|
-
continue
|
|
169
|
-
|
|
170
|
-
ep_name = sel.select_text("span.hidden.sm\\:block", ep_link)
|
|
171
|
-
|
|
172
|
-
season_match = sel.regex_first(r"sezon-(\d+)", href)
|
|
173
|
-
episode_match = sel.regex_first(r"bolum-(\d+)", href)
|
|
174
|
-
|
|
175
|
-
season = season_match if season_match else None
|
|
176
|
-
episode_num = episode_match if episode_match else None
|
|
177
|
-
|
|
178
|
-
episodes.append(Episode(
|
|
179
|
-
season = int(season) if season and season.isdigit() else None,
|
|
180
|
-
episode = int(episode_num) if episode_num and episode_num.isdigit() else None,
|
|
181
|
-
title = ep_name if ep_name else f"{season}x{episode_num}",
|
|
182
|
-
url = self.fix_url(href)
|
|
183
|
-
))
|
|
184
|
-
|
|
185
|
-
return SeriesInfo(
|
|
186
|
-
title = title,
|
|
187
|
-
url = url,
|
|
188
|
-
poster = self.fix_url(poster) if poster else None,
|
|
189
|
-
description = description,
|
|
190
|
-
rating = rating,
|
|
191
|
-
tags = tags,
|
|
192
|
-
actors = actors,
|
|
193
|
-
year = year,
|
|
194
|
-
episodes = episodes,
|
|
195
|
-
duration = int(duration) if duration and str(duration).isdigit() else None
|
|
196
|
-
)
|
|
197
|
-
|
|
198
|
-
async def load_links(self, url: str) -> list[ExtractResult]:
|
|
199
|
-
resp = await self.httpx.get(url)
|
|
200
|
-
sel = HTMLHelper(resp.text)
|
|
201
|
-
|
|
202
|
-
iframe = sel.select_attr("iframe", "src")
|
|
203
|
-
if not iframe:
|
|
204
|
-
return []
|
|
205
|
-
|
|
206
|
-
iframe_url = self.fix_url(iframe)
|
|
207
|
-
data = await self.extract(iframe_url, referer=f"{self.main_url}/")
|
|
208
|
-
|
|
209
|
-
if not data:
|
|
210
|
-
return []
|
|
211
|
-
|
|
212
|
-
return data if isinstance(data, list) else [data]
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|