KekikStream 1.5.2__py3-none-any.whl → 1.6.4__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/CLI/pypi_kontrol.py +6 -6
- KekikStream/Core/Media/MediaHandler.py +9 -6
- KekikStream/Core/Plugin/PluginBase.py +30 -10
- KekikStream/Extractors/CloseLoad.py +4 -23
- KekikStream/Extractors/MolyStream.py +23 -5
- KekikStream/Extractors/RapidVid.py +30 -12
- KekikStream/Extractors/VidMoly.py +20 -17
- KekikStream/Plugins/DiziBox.py +33 -16
- KekikStream/Plugins/DiziYou.py +18 -19
- KekikStream/Plugins/Dizilla.py +60 -46
- KekikStream/Plugins/FilmMakinesi.py +63 -52
- KekikStream/Plugins/FullHDFilmizlesene.py +41 -36
- KekikStream/Plugins/HDFilmCehennemi.py +41 -51
- KekikStream/Plugins/JetFilmizle.py +15 -7
- KekikStream/Plugins/RecTV.py +33 -29
- KekikStream/Plugins/SezonlukDizi.py +15 -12
- KekikStream/Plugins/UgurFilm.py +13 -9
- KekikStream/__init__.py +285 -318
- {kekikstream-1.5.2.dist-info → kekikstream-1.6.4.dist-info}/METADATA +4 -3
- {kekikstream-1.5.2.dist-info → kekikstream-1.6.4.dist-info}/RECORD +24 -26
- {kekikstream-1.5.2.dist-info → kekikstream-1.6.4.dist-info}/WHEEL +1 -1
- KekikStream/Plugins/Shorten.py +0 -226
- KekikStream/Plugins/SineWix.py +0 -161
- {kekikstream-1.5.2.dist-info → kekikstream-1.6.4.dist-info}/entry_points.txt +0 -0
- {kekikstream-1.5.2.dist-info → kekikstream-1.6.4.dist-info/licenses}/LICENSE +0 -0
- {kekikstream-1.5.2.dist-info → kekikstream-1.6.4.dist-info}/top_level.txt +0 -0
KekikStream/CLI/pypi_kontrol.py
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
2
|
|
|
3
|
-
from .
|
|
4
|
-
from rich.panel
|
|
5
|
-
from
|
|
6
|
-
from requests
|
|
7
|
-
from subprocess
|
|
3
|
+
from . import konsol
|
|
4
|
+
from rich.panel import Panel
|
|
5
|
+
from importlib import metadata
|
|
6
|
+
from requests import get
|
|
7
|
+
from subprocess import check_call
|
|
8
8
|
import sys
|
|
9
9
|
|
|
10
10
|
def pypi_kontrol_guncelle(paket_adi: str):
|
|
11
11
|
try:
|
|
12
12
|
konsol.print(f"[bold cyan] {paket_adi} Güncellemesi kontrol ediliyor...[/bold cyan]")
|
|
13
|
-
mevcut_surum =
|
|
13
|
+
mevcut_surum = metadata.version(paket_adi)
|
|
14
14
|
konsol.print(Panel(f"[cyan]Yüklü sürüm:[/cyan] [bold yellow]{mevcut_surum}[/bold yellow]"))
|
|
15
15
|
|
|
16
16
|
istek = get(f"https://pypi.org/pypi/{paket_adi}/json")
|
|
@@ -34,11 +34,11 @@ class MediaHandler:
|
|
|
34
34
|
if "Cookie" in self.headers or extract_data.subtitles:
|
|
35
35
|
return self.play_with_mpv(extract_data)
|
|
36
36
|
|
|
37
|
-
return self.play_with_vlc(extract_data)
|
|
37
|
+
return self.play_with_vlc(extract_data) or self.play_with_mpv(extract_data)
|
|
38
38
|
|
|
39
39
|
def play_with_vlc(self, extract_data: ExtractResult):
|
|
40
40
|
konsol.log(f"[yellow][»] VLC ile Oynatılıyor : {extract_data.url}")
|
|
41
|
-
konsol.print(self.headers)
|
|
41
|
+
# konsol.print(self.headers)
|
|
42
42
|
try:
|
|
43
43
|
vlc_command = ["vlc", "--quiet"]
|
|
44
44
|
|
|
@@ -62,16 +62,19 @@ class MediaHandler:
|
|
|
62
62
|
with open(os.devnull, "w") as devnull:
|
|
63
63
|
subprocess.run(vlc_command, stdout=devnull, stderr=devnull, check=True)
|
|
64
64
|
|
|
65
|
+
return True
|
|
65
66
|
except subprocess.CalledProcessError as hata:
|
|
66
67
|
konsol.print(f"[red]VLC oynatma hatası: {hata}[/red]")
|
|
67
68
|
konsol.print({"title": self.title, "url": extract_data.url, "headers": self.headers})
|
|
69
|
+
return False
|
|
68
70
|
except FileNotFoundError:
|
|
69
71
|
konsol.print("[red]VLC bulunamadı! VLC kurulu olduğundan emin olun.[/red]")
|
|
70
|
-
konsol.print({"title": self.title, "url": extract_data.url, "headers": self.headers})
|
|
72
|
+
# konsol.print({"title": self.title, "url": extract_data.url, "headers": self.headers})
|
|
73
|
+
return False
|
|
71
74
|
|
|
72
75
|
def play_with_mpv(self, extract_data: ExtractResult):
|
|
73
76
|
konsol.log(f"[yellow][»] MPV ile Oynatılıyor : {extract_data.url}")
|
|
74
|
-
konsol.print(self.headers)
|
|
77
|
+
# konsol.print(self.headers)
|
|
75
78
|
try:
|
|
76
79
|
mpv_command = ["mpv"]
|
|
77
80
|
|
|
@@ -98,7 +101,7 @@ class MediaHandler:
|
|
|
98
101
|
|
|
99
102
|
def play_with_ytdlp(self, extract_data: ExtractResult):
|
|
100
103
|
konsol.log(f"[yellow][»] yt-dlp ile Oynatılıyor : {extract_data.url}")
|
|
101
|
-
konsol.print(self.headers)
|
|
104
|
+
# konsol.print(self.headers)
|
|
102
105
|
try:
|
|
103
106
|
ytdlp_command = ["yt-dlp", "--quiet", "--no-warnings"]
|
|
104
107
|
|
|
@@ -131,7 +134,7 @@ class MediaHandler:
|
|
|
131
134
|
|
|
132
135
|
def play_with_android_mxplayer(self, extract_data: ExtractResult):
|
|
133
136
|
konsol.log(f"[yellow][»] MxPlayer ile Oynatılıyor : {extract_data.url}")
|
|
134
|
-
konsol.print(self.headers)
|
|
137
|
+
# konsol.print(self.headers)
|
|
135
138
|
paketler = [
|
|
136
139
|
"com.mxtech.videoplayer.ad/.ActivityScreen", # Free sürüm
|
|
137
140
|
"com.mxtech.videoplayer.pro/.ActivityScreen" # Pro sürüm
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
2
|
|
|
3
|
-
from abc
|
|
4
|
-
from httpx
|
|
5
|
-
from cloudscraper
|
|
6
|
-
from .PluginModels
|
|
7
|
-
from ..Media.MediaHandler
|
|
8
|
-
from
|
|
3
|
+
from abc import ABC, abstractmethod
|
|
4
|
+
from httpx import AsyncClient, Timeout
|
|
5
|
+
from cloudscraper import CloudScraper
|
|
6
|
+
from .PluginModels import MainPageResult, SearchResult, MovieInfo
|
|
7
|
+
from ..Media.MediaHandler import MediaHandler
|
|
8
|
+
from ..Extractor.ExtractorManager import ExtractorManager
|
|
9
|
+
from urllib.parse import urljoin
|
|
9
10
|
import re
|
|
10
11
|
|
|
11
12
|
class PluginBase(ABC):
|
|
@@ -17,8 +18,6 @@ class PluginBase(ABC):
|
|
|
17
18
|
|
|
18
19
|
main_page = {}
|
|
19
20
|
|
|
20
|
-
_data = {}
|
|
21
|
-
|
|
22
21
|
async def url_update(self, new_url: str):
|
|
23
22
|
self.favicon = self.favicon.replace(self.main_url, new_url)
|
|
24
23
|
self.main_page = {url.replace(self.main_url, new_url): category for url, category in self.main_page.items()}
|
|
@@ -34,6 +33,7 @@ class PluginBase(ABC):
|
|
|
34
33
|
)
|
|
35
34
|
self.media_handler = MediaHandler()
|
|
36
35
|
self.cloudscraper = CloudScraper()
|
|
36
|
+
self.ex_manager = ExtractorManager()
|
|
37
37
|
self.httpx.headers.update(self.cloudscraper.headers)
|
|
38
38
|
self.httpx.cookies.update(self.cloudscraper.cookies)
|
|
39
39
|
|
|
@@ -53,8 +53,28 @@ class PluginBase(ABC):
|
|
|
53
53
|
pass
|
|
54
54
|
|
|
55
55
|
@abstractmethod
|
|
56
|
-
async def load_links(self, url: str) -> list[
|
|
57
|
-
"""
|
|
56
|
+
async def load_links(self, url: str) -> list[dict]:
|
|
57
|
+
"""
|
|
58
|
+
Bir medya öğesi için oynatma bağlantılarını döndürür.
|
|
59
|
+
|
|
60
|
+
Args:
|
|
61
|
+
url: Medya URL'si
|
|
62
|
+
|
|
63
|
+
Returns:
|
|
64
|
+
Dictionary listesi, her biri şu alanları içerir:
|
|
65
|
+
- url (str, zorunlu): Video URL'si
|
|
66
|
+
- name (str, zorunlu): Gösterim adı (tüm bilgileri içerir)
|
|
67
|
+
- referer (str, opsiyonel): Referer header
|
|
68
|
+
- subtitles (list, opsiyonel): Altyazı listesi
|
|
69
|
+
|
|
70
|
+
Example:
|
|
71
|
+
[
|
|
72
|
+
{
|
|
73
|
+
"url": "https://example.com/video.m3u8",
|
|
74
|
+
"name": "HDFilmCehennemi | 1080p TR Dublaj"
|
|
75
|
+
}
|
|
76
|
+
]
|
|
77
|
+
"""
|
|
58
78
|
pass
|
|
59
79
|
|
|
60
80
|
async def close(self):
|
|
@@ -1,31 +1,12 @@
|
|
|
1
1
|
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
2
|
|
|
3
3
|
from KekikStream.Core import ExtractorBase, ExtractResult
|
|
4
|
-
from Kekik.Sifreleme import Packer
|
|
5
|
-
import re
|
|
6
|
-
|
|
7
|
-
def get_m3u_link(data: str) -> str:
|
|
8
|
-
first = base64.b64decode(data)
|
|
9
|
-
first_reversed = first[::-1]
|
|
10
|
-
|
|
11
|
-
second = base64.b64decode(first_reversed)
|
|
12
|
-
|
|
13
|
-
parts = second.decode('utf-8').split("|")
|
|
14
|
-
if len(parts) < 2:
|
|
15
|
-
raise ValueError("Decoded data has an unexpected format.")
|
|
16
|
-
|
|
17
|
-
return parts[1]
|
|
18
|
-
|
|
19
|
-
def extract_data(raw_script: str) -> str:
|
|
20
|
-
pattern = re.compile(r'return result\}var .*?=.*?\("(.*?)"\)')
|
|
21
|
-
if match := pattern.search(raw_script):
|
|
22
|
-
return match[1]
|
|
23
|
-
else:
|
|
24
|
-
raise Exception("data not found")
|
|
4
|
+
from Kekik.Sifreleme import Packer, StreamDecoder
|
|
5
|
+
import re
|
|
25
6
|
|
|
26
7
|
class CloseLoadExtractor(ExtractorBase):
|
|
27
8
|
name = "CloseLoad"
|
|
28
|
-
main_url = "https://closeload.filmmakinesi.
|
|
9
|
+
main_url = "https://closeload.filmmakinesi.sh"
|
|
29
10
|
|
|
30
11
|
async def extract(self, url, referer=None) -> ExtractResult:
|
|
31
12
|
if referer:
|
|
@@ -35,7 +16,7 @@ class CloseLoadExtractor(ExtractorBase):
|
|
|
35
16
|
istek.raise_for_status()
|
|
36
17
|
|
|
37
18
|
eval_func = re.compile(r'\s*(eval\(function[\s\S].*)\s*').findall(istek.text)[0]
|
|
38
|
-
m3u_link =
|
|
19
|
+
m3u_link = StreamDecoder.extract_stream_url(Packer.unpack(eval_func))
|
|
39
20
|
|
|
40
21
|
await self.close()
|
|
41
22
|
return ExtractResult(
|
|
@@ -1,16 +1,34 @@
|
|
|
1
1
|
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
2
|
|
|
3
|
-
from KekikStream.Core import ExtractorBase, ExtractResult
|
|
3
|
+
from KekikStream.Core import ExtractorBase, ExtractResult, Subtitle
|
|
4
|
+
from parsel import Selector
|
|
5
|
+
import re
|
|
4
6
|
|
|
5
7
|
class MolyStream(ExtractorBase):
|
|
6
8
|
name = "MolyStream"
|
|
7
9
|
main_url = "https://dbx.molystream.org"
|
|
8
10
|
|
|
9
11
|
async def extract(self, url, referer=None) -> ExtractResult:
|
|
12
|
+
if "doctype html" in url:
|
|
13
|
+
secici = Selector(url)
|
|
14
|
+
video = secici.css("video#sheplayer source::attr(src)").get()
|
|
15
|
+
else:
|
|
16
|
+
video = url
|
|
17
|
+
|
|
18
|
+
matches = re.findall(
|
|
19
|
+
pattern = r"addSrtFile\(['\"]([^'\"]+\.srt)['\"]\s*,\s*['\"][a-z]{2}['\"]\s*,\s*['\"]([^'\"]+)['\"]",
|
|
20
|
+
string = url
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
subtitles = [
|
|
24
|
+
Subtitle(name = name, url = self.fix_url(url))
|
|
25
|
+
for url, name in matches
|
|
26
|
+
]
|
|
27
|
+
|
|
10
28
|
return ExtractResult(
|
|
11
29
|
name = self.name,
|
|
12
|
-
url =
|
|
13
|
-
referer =
|
|
30
|
+
url = video,
|
|
31
|
+
referer = video.replace("/sheila", ""),
|
|
14
32
|
headers = {"User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:101.0) Gecko/20100101 Firefox/101.0"},
|
|
15
|
-
subtitles =
|
|
16
|
-
)
|
|
33
|
+
subtitles = subtitles
|
|
34
|
+
)
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
from KekikStream.Core import ExtractorBase, ExtractResult, Subtitle
|
|
4
4
|
from Kekik.Sifreleme import Packer, HexCodec
|
|
5
|
-
import re
|
|
5
|
+
import re, base64
|
|
6
6
|
|
|
7
7
|
class RapidVid(ExtractorBase):
|
|
8
8
|
name = "RapidVid"
|
|
@@ -37,17 +37,11 @@ class RapidVid(ExtractorBase):
|
|
|
37
37
|
escaped_hex = extracted_value[1]
|
|
38
38
|
decoded_url = HexCodec.decode(escaped_hex)
|
|
39
39
|
else:
|
|
40
|
-
|
|
41
|
-
if not
|
|
42
|
-
raise ValueError("
|
|
40
|
+
av_encoded = re.search(r"av\('([^']+)'\)", istek.text)
|
|
41
|
+
if not av_encoded:
|
|
42
|
+
raise ValueError("AV encoding not found.")
|
|
43
43
|
|
|
44
|
-
|
|
45
|
-
extracted_value = re.search(r'file":"(.*)","label', unpacked_jwsetup)
|
|
46
|
-
if not extracted_value:
|
|
47
|
-
raise ValueError("File URL not found in unpacked JWPlayer setup.")
|
|
48
|
-
|
|
49
|
-
escaped_hex = extracted_value[1].replace("\\\\x", "")
|
|
50
|
-
decoded_url = bytes.fromhex(escaped_hex).decode("utf-8")
|
|
44
|
+
decoded_url = self.decode_secret(av_encoded[1])
|
|
51
45
|
except Exception as hata:
|
|
52
46
|
raise RuntimeError(f"Extraction failed: {hata}") from hata
|
|
53
47
|
|
|
@@ -58,4 +52,28 @@ class RapidVid(ExtractorBase):
|
|
|
58
52
|
referer = self.main_url,
|
|
59
53
|
headers = {},
|
|
60
54
|
subtitles = subtitles
|
|
61
|
-
)
|
|
55
|
+
)
|
|
56
|
+
|
|
57
|
+
def decode_secret(self, encoded_string: str) -> str:
|
|
58
|
+
# 1. Base64 ile şifrelenmiş string ters çevrilmiş, önce geri çeviriyoruz
|
|
59
|
+
reversed_input = encoded_string[::-1]
|
|
60
|
+
|
|
61
|
+
# 2. İlk base64 çözme işlemi
|
|
62
|
+
decoded_once = base64.b64decode(reversed_input).decode("utf-8")
|
|
63
|
+
|
|
64
|
+
decrypted_chars = []
|
|
65
|
+
key = "K9L"
|
|
66
|
+
|
|
67
|
+
# 3. Key'e göre karakter kaydırma geri alınıyor
|
|
68
|
+
for index, encoded_char in enumerate(decoded_once):
|
|
69
|
+
key_char = key[index % len(key)]
|
|
70
|
+
offset = (ord(key_char) % 5) + 1 # Her karakter için dinamik offset
|
|
71
|
+
|
|
72
|
+
original_char_code = ord(encoded_char) - offset
|
|
73
|
+
decrypted_chars.append(chr(original_char_code))
|
|
74
|
+
|
|
75
|
+
# 4. Karakterleri birleştirip ikinci base64 çözme işlemini yapıyoruz
|
|
76
|
+
intermediate_string = "".join(decrypted_chars)
|
|
77
|
+
final_decoded_bytes = base64.b64decode(intermediate_string)
|
|
78
|
+
|
|
79
|
+
return final_decoded_bytes.decode("utf-8")
|
|
@@ -2,7 +2,8 @@
|
|
|
2
2
|
# ! https://github.com/recloudstream/cloudstream/blob/master/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/Vidmoly.kt
|
|
3
3
|
|
|
4
4
|
from KekikStream.Core import ExtractorBase, ExtractResult, Subtitle
|
|
5
|
-
import
|
|
5
|
+
from parsel import Selector
|
|
6
|
+
import re, contextlib, json
|
|
6
7
|
|
|
7
8
|
class VidMoly(ExtractorBase):
|
|
8
9
|
name = "VidMoly"
|
|
@@ -18,24 +19,26 @@ class VidMoly(ExtractorBase):
|
|
|
18
19
|
})
|
|
19
20
|
|
|
20
21
|
if self.main_url.endswith(".me"):
|
|
21
|
-
self.main_url = self.main_url.replace(".me", ".
|
|
22
|
-
url
|
|
22
|
+
self.main_url = self.main_url.replace(".me", ".net")
|
|
23
|
+
url = url.replace(".me", ".net")
|
|
23
24
|
|
|
24
|
-
|
|
25
|
-
|
|
26
|
-
|
|
27
|
-
|
|
25
|
+
response = await self.httpx.get(url)
|
|
26
|
+
if "Select number" in response.text:
|
|
27
|
+
secici = Selector(response.text)
|
|
28
|
+
response = await self.httpx.post(
|
|
29
|
+
url = url,
|
|
30
|
+
data = {
|
|
31
|
+
"op" : secici.css("input[name='op']::attr(value)").get(),
|
|
32
|
+
"file_code" : secici.css("input[name='file_code']::attr(value)").get(),
|
|
33
|
+
"answer" : secici.css("div.vhint b::text").get(),
|
|
34
|
+
"ts" : secici.css("input[name='ts']::attr(value)").get(),
|
|
35
|
+
"nonce" : secici.css("input[name='nonce']::attr(value)").get(),
|
|
36
|
+
"ctok" : secici.css("input[name='ctok']::attr(value)").get()
|
|
37
|
+
}
|
|
38
|
+
)
|
|
28
39
|
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
attempts += 1
|
|
32
|
-
response = await self.httpx.get(embed_url)
|
|
33
|
-
response.raise_for_status()
|
|
34
|
-
|
|
35
|
-
script_match = re.search(r"sources:\s*\[(.*?)\],", response.text, re.DOTALL)
|
|
36
|
-
script_content = script_match[1] if script_match else None
|
|
37
|
-
if not script_content:
|
|
38
|
-
await asyncio.sleep(0.5)
|
|
40
|
+
script_match = re.search(r"sources:\s*\[(.*?)\],", response.text, re.DOTALL)
|
|
41
|
+
script_content = script_match[1] if script_match else None
|
|
39
42
|
|
|
40
43
|
if not script_content:
|
|
41
44
|
raise ValueError("Gerekli script bulunamadı.")
|
KekikStream/Plugins/DiziBox.py
CHANGED
|
@@ -3,7 +3,7 @@
|
|
|
3
3
|
from KekikStream.Core import kekik_cache, PluginBase, MainPageResult, SearchResult, SeriesInfo, Episode
|
|
4
4
|
from Kekik.Sifreleme import CryptoJS
|
|
5
5
|
from parsel import Selector
|
|
6
|
-
import re, urllib.parse, base64, contextlib, asyncio
|
|
6
|
+
import re, urllib.parse, base64, contextlib, asyncio, time
|
|
7
7
|
|
|
8
8
|
class DiziBox(PluginBase):
|
|
9
9
|
name = "DiziBox"
|
|
@@ -40,8 +40,12 @@ class DiziBox(PluginBase):
|
|
|
40
40
|
f"{main_url}/dizi-arsivi/page/SAYFA/?tur[0]=yarisma&yil&imdb" : "Yarışma"
|
|
41
41
|
}
|
|
42
42
|
|
|
43
|
-
|
|
43
|
+
#@kekik_cache(ttl=60*60)
|
|
44
44
|
async def get_main_page(self, page: int, url: str, category: str) -> list[MainPageResult]:
|
|
45
|
+
self.httpx.cookies.update({
|
|
46
|
+
"isTrustedUser" : "true",
|
|
47
|
+
"dbxu" : str(time.time() * 1000).split(".")[0]
|
|
48
|
+
})
|
|
45
49
|
istek = await self.httpx.get(
|
|
46
50
|
url = f"{url.replace('SAYFA', str(page))}",
|
|
47
51
|
follow_redirects = True
|
|
@@ -58,12 +62,11 @@ class DiziBox(PluginBase):
|
|
|
58
62
|
for veri in secici.css("article.detailed-article")
|
|
59
63
|
]
|
|
60
64
|
|
|
61
|
-
|
|
65
|
+
#@kekik_cache(ttl=60*60)
|
|
62
66
|
async def search(self, query: str) -> list[SearchResult]:
|
|
63
67
|
self.httpx.cookies.update({
|
|
64
|
-
"LockUser" : "true",
|
|
65
68
|
"isTrustedUser" : "true",
|
|
66
|
-
"dbxu" : "
|
|
69
|
+
"dbxu" : str(time.time() * 1000).split(".")[0]
|
|
67
70
|
})
|
|
68
71
|
istek = await self.httpx.get(f"{self.main_url}/?s={query}")
|
|
69
72
|
secici = Selector(istek.text)
|
|
@@ -77,7 +80,7 @@ class DiziBox(PluginBase):
|
|
|
77
80
|
for item in secici.css("article.detailed-article")
|
|
78
81
|
]
|
|
79
82
|
|
|
80
|
-
|
|
83
|
+
#@kekik_cache(ttl=60*60)
|
|
81
84
|
async def load_item(self, url: str) -> SeriesInfo:
|
|
82
85
|
istek = await self.httpx.get(url)
|
|
83
86
|
secici = Selector(istek.text)
|
|
@@ -124,13 +127,18 @@ class DiziBox(PluginBase):
|
|
|
124
127
|
actors = actors,
|
|
125
128
|
)
|
|
126
129
|
|
|
127
|
-
|
|
130
|
+
#@kekik_cache(ttl=60*60)
|
|
128
131
|
async def _iframe_decode(self, name:str, iframe_link:str, referer:str) -> list[str]:
|
|
129
132
|
results = []
|
|
130
133
|
|
|
134
|
+
self.httpx.headers.update({"Referer": referer})
|
|
135
|
+
self.httpx.cookies.update({
|
|
136
|
+
"isTrustedUser" : "true",
|
|
137
|
+
"dbxu" : str(time.time() * 1000).split(".")[0]
|
|
138
|
+
})
|
|
139
|
+
|
|
131
140
|
if "/player/king/king.php" in iframe_link:
|
|
132
141
|
iframe_link = iframe_link.replace("king.php?v=", "king.php?wmode=opaque&v=")
|
|
133
|
-
self.httpx.headers.update({"Referer": referer})
|
|
134
142
|
|
|
135
143
|
istek = await self.httpx.get(iframe_link)
|
|
136
144
|
secici = Selector(istek.text)
|
|
@@ -150,7 +158,6 @@ class DiziBox(PluginBase):
|
|
|
150
158
|
|
|
151
159
|
elif "/player/moly/moly.php" in iframe_link:
|
|
152
160
|
iframe_link = iframe_link.replace("moly.php?h=", "moly.php?wmode=opaque&h=")
|
|
153
|
-
self.httpx.headers.update({"Referer": referer})
|
|
154
161
|
while True:
|
|
155
162
|
await asyncio.sleep(.3)
|
|
156
163
|
with contextlib.suppress(Exception):
|
|
@@ -171,15 +178,20 @@ class DiziBox(PluginBase):
|
|
|
171
178
|
|
|
172
179
|
return results
|
|
173
180
|
|
|
174
|
-
|
|
175
|
-
async def load_links(self, url: str) -> list[
|
|
181
|
+
#@kekik_cache(ttl=15*60)
|
|
182
|
+
async def load_links(self, url: str) -> list[dict]:
|
|
176
183
|
istek = await self.httpx.get(url)
|
|
177
184
|
secici = Selector(istek.text)
|
|
178
185
|
|
|
179
|
-
|
|
186
|
+
results = []
|
|
180
187
|
if main_iframe := secici.css("div#video-area iframe::attr(src)").get():
|
|
181
188
|
if decoded := await self._iframe_decode(self.name, main_iframe, url):
|
|
182
|
-
|
|
189
|
+
for iframe in decoded:
|
|
190
|
+
extractor = self.ex_manager.find_extractor(iframe)
|
|
191
|
+
results.append({
|
|
192
|
+
"url" : iframe,
|
|
193
|
+
"name" : f"{extractor.name if extractor else 'Main Player'}"
|
|
194
|
+
})
|
|
183
195
|
|
|
184
196
|
for alternatif in secici.css("div.video-toolbar option[value]"):
|
|
185
197
|
alt_name = alternatif.css("::text").get()
|
|
@@ -195,6 +207,11 @@ class DiziBox(PluginBase):
|
|
|
195
207
|
alt_secici = Selector(alt_istek.text)
|
|
196
208
|
if alt_iframe := alt_secici.css("div#video-area iframe::attr(src)").get():
|
|
197
209
|
if decoded := await self._iframe_decode(alt_name, alt_iframe, url):
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
210
|
+
for iframe in decoded:
|
|
211
|
+
extractor = self.ex_manager.find_extractor(iframe)
|
|
212
|
+
results.append({
|
|
213
|
+
"url" : iframe,
|
|
214
|
+
"name" : f"{extractor.name if extractor else alt_name}"
|
|
215
|
+
})
|
|
216
|
+
|
|
217
|
+
return results
|
KekikStream/Plugins/DiziYou.py
CHANGED
|
@@ -7,7 +7,7 @@ import re
|
|
|
7
7
|
class DiziYou(PluginBase):
|
|
8
8
|
name = "DiziYou"
|
|
9
9
|
language = "tr"
|
|
10
|
-
main_url = "https://www.
|
|
10
|
+
main_url = "https://www.diziyou.mx"
|
|
11
11
|
favicon = f"https://www.google.com/s2/favicons?domain={main_url}&sz=64"
|
|
12
12
|
description = "Diziyou en kaliteli Türkçe dublaj ve altyazılı yabancı dizi izleme sitesidir. Güncel ve efsanevi dizileri 1080p Full HD kalitede izlemek için hemen tıkla!"
|
|
13
13
|
|
|
@@ -29,9 +29,7 @@ class DiziYou(PluginBase):
|
|
|
29
29
|
f"{main_url}/dizi-arsivi/page/SAYFA/?tur=Vah%C5%9Fi+Bat%C4%B1" : "Vahşi Batı"
|
|
30
30
|
}
|
|
31
31
|
|
|
32
|
-
|
|
33
|
-
|
|
34
|
-
@kekik_cache(ttl=60*60)
|
|
32
|
+
#@kekik_cache(ttl=60*60)
|
|
35
33
|
async def get_main_page(self, page: int, url: str, category: str) -> list[MainPageResult]:
|
|
36
34
|
istek = await self.httpx.get(f"{url.replace('SAYFA', str(page))}")
|
|
37
35
|
secici = Selector(istek.text)
|
|
@@ -46,7 +44,7 @@ class DiziYou(PluginBase):
|
|
|
46
44
|
for veri in secici.css("div.single-item")
|
|
47
45
|
]
|
|
48
46
|
|
|
49
|
-
|
|
47
|
+
#@kekik_cache(ttl=60*60)
|
|
50
48
|
async def search(self, query: str) -> list[SearchResult]:
|
|
51
49
|
istek = await self.httpx.get(f"{self.main_url}/?s={query}")
|
|
52
50
|
secici = Selector(istek.text)
|
|
@@ -60,7 +58,7 @@ class DiziYou(PluginBase):
|
|
|
60
58
|
for afis in secici.css("div.incontent div#list-series")
|
|
61
59
|
]
|
|
62
60
|
|
|
63
|
-
|
|
61
|
+
#@kekik_cache(ttl=60*60)
|
|
64
62
|
async def load_item(self, url: str) -> SeriesInfo:
|
|
65
63
|
istek = await self.httpx.get(url)
|
|
66
64
|
secici = Selector(istek.text)
|
|
@@ -68,7 +66,9 @@ class DiziYou(PluginBase):
|
|
|
68
66
|
title = secici.css("h1::text").get().strip()
|
|
69
67
|
poster = self.fix_url(secici.css("div.category_image img::attr(src)").get().strip())
|
|
70
68
|
year = secici.xpath("//span[contains(., 'Yapım Yılı')]/following-sibling::text()[1]").get()
|
|
71
|
-
description = secici.css("div.diziyou_desc::text").get()
|
|
69
|
+
description = secici.css("div.diziyou_desc::text").get()
|
|
70
|
+
if description:
|
|
71
|
+
description = description.strip()
|
|
72
72
|
tags = secici.css("div.genres a::text").getall()
|
|
73
73
|
rating = secici.xpath("//span[contains(., 'IMDB')]/following-sibling::text()[1]").get()
|
|
74
74
|
_actors = secici.xpath("//span[contains(., 'Oyuncular')]/following-sibling::text()[1]").get()
|
|
@@ -107,8 +107,8 @@ class DiziYou(PluginBase):
|
|
|
107
107
|
actors = actors
|
|
108
108
|
)
|
|
109
109
|
|
|
110
|
-
|
|
111
|
-
async def load_links(self, url: str) -> list[
|
|
110
|
+
#@kekik_cache(ttl=15*60)
|
|
111
|
+
async def load_links(self, url: str) -> list[dict]:
|
|
112
112
|
istek = await self.httpx.get(url)
|
|
113
113
|
secici = Selector(istek.text)
|
|
114
114
|
|
|
@@ -130,7 +130,7 @@ class DiziYou(PluginBase):
|
|
|
130
130
|
url = self.fix_url(f"{self.main_url.replace('www', 'storage')}/subtitles/{item_id}/tr.vtt"),
|
|
131
131
|
))
|
|
132
132
|
veri = {
|
|
133
|
-
"dil": "Orjinal Dil",
|
|
133
|
+
"dil": "Orjinal Dil (TR Altyazı)",
|
|
134
134
|
"url": f"{self.main_url.replace('www', 'storage')}/episodes/{item_id}/play.m3u8"
|
|
135
135
|
}
|
|
136
136
|
if veri not in stream_urls:
|
|
@@ -141,28 +141,27 @@ class DiziYou(PluginBase):
|
|
|
141
141
|
url = self.fix_url(f"{self.main_url.replace('www', 'storage')}/subtitles/{item_id}/en.vtt"),
|
|
142
142
|
))
|
|
143
143
|
veri = {
|
|
144
|
-
"dil": "Orjinal Dil",
|
|
144
|
+
"dil": "Orjinal Dil (EN Altyazı)",
|
|
145
145
|
"url": f"{self.main_url.replace('www', 'storage')}/episodes/{item_id}/play.m3u8"
|
|
146
146
|
}
|
|
147
147
|
if veri not in stream_urls:
|
|
148
148
|
stream_urls.append(veri)
|
|
149
149
|
case "turkceDublaj":
|
|
150
150
|
stream_urls.append({
|
|
151
|
-
"dil": "Dublaj",
|
|
151
|
+
"dil": "Türkçe Dublaj",
|
|
152
152
|
"url": f"{self.main_url.replace('www', 'storage')}/episodes/{item_id}_tr/play.m3u8"
|
|
153
153
|
})
|
|
154
154
|
|
|
155
|
-
|
|
155
|
+
results = []
|
|
156
156
|
for stream in stream_urls:
|
|
157
|
-
|
|
158
|
-
"
|
|
159
|
-
"name" : f"{
|
|
157
|
+
results.append({
|
|
158
|
+
"url" : stream.get("url"),
|
|
159
|
+
"name" : f"{stream.get('dil')}",
|
|
160
160
|
"referer" : url,
|
|
161
|
-
"headers" : self.media_handler.headers,
|
|
162
161
|
"subtitles" : subtitles
|
|
163
|
-
}
|
|
162
|
+
})
|
|
164
163
|
|
|
165
|
-
return
|
|
164
|
+
return results
|
|
166
165
|
|
|
167
166
|
async def play(self, name: str, url: str, referer: str, subtitles: list[Subtitle]):
|
|
168
167
|
extract_result = ExtractResult(name=name, url=url, referer=referer, subtitles=subtitles)
|