KekikStream 0.7.1__py3-none-any.whl
Sign up to get free protection for your applications and to get access to all the features.
Potentially problematic release.
This version of KekikStream might be problematic. Click here for more details.
- KekikStream/CLI/__init__.py +4 -0
- KekikStream/CLI/pypi_kontrol.py +30 -0
- KekikStream/Core/ExtractorBase.py +42 -0
- KekikStream/Core/ExtractorLoader.py +82 -0
- KekikStream/Core/ExtractorModels.py +19 -0
- KekikStream/Core/MediaHandler.py +142 -0
- KekikStream/Core/PluginBase.py +80 -0
- KekikStream/Core/PluginLoader.py +61 -0
- KekikStream/Core/PluginModels.py +63 -0
- KekikStream/Core/__init__.py +9 -0
- KekikStream/Extractors/CloseLoad.py +31 -0
- KekikStream/Extractors/ContentX.py +80 -0
- KekikStream/Extractors/FourCX.py +7 -0
- KekikStream/Extractors/FourPichive.py +7 -0
- KekikStream/Extractors/FourPlayRu.py +7 -0
- KekikStream/Extractors/HDStreamAble.py +7 -0
- KekikStream/Extractors/Hotlinger.py +7 -0
- KekikStream/Extractors/MailRu.py +40 -0
- KekikStream/Extractors/MixPlayHD.py +42 -0
- KekikStream/Extractors/Odnoklassniki.py +106 -0
- KekikStream/Extractors/OkRuHTTP.py +7 -0
- KekikStream/Extractors/OkRuSSL.py +7 -0
- KekikStream/Extractors/PeaceMakerst.py +57 -0
- KekikStream/Extractors/Pichive.py +7 -0
- KekikStream/Extractors/PixelDrain.py +28 -0
- KekikStream/Extractors/PlayRu.py +7 -0
- KekikStream/Extractors/RapidVid.py +60 -0
- KekikStream/Extractors/SibNet.py +29 -0
- KekikStream/Extractors/Sobreatsesuyp.py +59 -0
- KekikStream/Extractors/TRsTX.py +67 -0
- KekikStream/Extractors/TauVideo.py +34 -0
- KekikStream/Extractors/TurboImgz.py +25 -0
- KekikStream/Extractors/VidMoly.py +85 -0
- KekikStream/Extractors/VidMoxy.py +50 -0
- KekikStream/Extractors/VideoSeyred.py +47 -0
- KekikStream/Managers/ExtractorManager.py +27 -0
- KekikStream/Managers/MediaManager.py +19 -0
- KekikStream/Managers/PluginManager.py +19 -0
- KekikStream/Managers/UIManager.py +49 -0
- KekikStream/Managers/__init__.py +6 -0
- KekikStream/Plugins/DiziBox.py +143 -0
- KekikStream/Plugins/DiziYou.py +127 -0
- KekikStream/Plugins/Dizilla.py +106 -0
- KekikStream/Plugins/FilmMakinesi.py +65 -0
- KekikStream/Plugins/FullHDFilmizlesene.py +78 -0
- KekikStream/Plugins/JetFilmizle.py +92 -0
- KekikStream/Plugins/RecTV.py +113 -0
- KekikStream/Plugins/SezonlukDizi.py +108 -0
- KekikStream/Plugins/SineWix.py +108 -0
- KekikStream/Plugins/UgurFilm.py +75 -0
- KekikStream/__init__.py +255 -0
- KekikStream/__main__.py +6 -0
- KekikStream/requirements.txt +10 -0
- KekikStream-0.7.1.dist-info/LICENSE +674 -0
- KekikStream-0.7.1.dist-info/METADATA +94 -0
- KekikStream-0.7.1.dist-info/RECORD +59 -0
- KekikStream-0.7.1.dist-info/WHEEL +5 -0
- KekikStream-0.7.1.dist-info/entry_points.txt +2 -0
- KekikStream-0.7.1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,85 @@
|
|
1
|
+
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
2
|
+
# ! https://github.com/recloudstream/cloudstream/blob/master/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/Vidmoly.kt
|
3
|
+
|
4
|
+
from KekikStream.Core import ExtractorBase, ExtractResult, Subtitle
|
5
|
+
import re, asyncio, contextlib, json
|
6
|
+
|
7
|
+
class VidMoly(ExtractorBase):
|
8
|
+
name = "VidMoly"
|
9
|
+
main_url = "https://vidmoly.to"
|
10
|
+
|
11
|
+
async def extract(self, url: str, referer: str = None) -> ExtractResult:
|
12
|
+
if referer:
|
13
|
+
self.oturum.headers.update({"Referer": referer})
|
14
|
+
|
15
|
+
self.oturum.headers.update({
|
16
|
+
"User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
|
17
|
+
"Sec-Fetch-Dest" : "iframe",
|
18
|
+
})
|
19
|
+
|
20
|
+
# Embed URL oluştur
|
21
|
+
embed_url = url.replace("/w/", "/embed-") + "-920x360.html" if "/w/" in url else url
|
22
|
+
script_content = None
|
23
|
+
attempts = 0
|
24
|
+
|
25
|
+
# Script verisini almak için deneme yap
|
26
|
+
while attempts < 10 and not script_content:
|
27
|
+
attempts += 1
|
28
|
+
response = await self.oturum.get(embed_url)
|
29
|
+
response.raise_for_status()
|
30
|
+
|
31
|
+
script_match = re.search(r"sources:\s*\[(.*?)\],", response.text, re.DOTALL)
|
32
|
+
script_content = script_match[1] if script_match else None
|
33
|
+
if not script_content:
|
34
|
+
await asyncio.sleep(0.5)
|
35
|
+
|
36
|
+
if not script_content:
|
37
|
+
raise ValueError("Gerekli script bulunamadı.")
|
38
|
+
|
39
|
+
# Video kaynaklarını ayrıştır
|
40
|
+
video_data = self._add_marks(script_content, "file")
|
41
|
+
try:
|
42
|
+
video_sources = json.loads(f"[{video_data}]")
|
43
|
+
except json.JSONDecodeError as hata:
|
44
|
+
raise ValueError("Video kaynakları ayrıştırılamadı.") from hata
|
45
|
+
|
46
|
+
# Altyazı kaynaklarını ayrıştır
|
47
|
+
subtitles = []
|
48
|
+
if subtitle_match := re.search(r"tracks:\s*\[(.*?)\]", response.text, re.DOTALL):
|
49
|
+
subtitle_data = self._add_marks(subtitle_match[1], "file")
|
50
|
+
subtitle_data = self._add_marks(subtitle_data, "label")
|
51
|
+
subtitle_data = self._add_marks(subtitle_data, "kind")
|
52
|
+
|
53
|
+
with contextlib.suppress(json.JSONDecodeError):
|
54
|
+
subtitle_sources = json.loads(f"[{subtitle_data}]")
|
55
|
+
subtitles = [
|
56
|
+
Subtitle(
|
57
|
+
name = sub.get("label"),
|
58
|
+
url = self.fix_url(sub.get("file")),
|
59
|
+
)
|
60
|
+
for sub in subtitle_sources
|
61
|
+
if sub.get("kind") == "captions"
|
62
|
+
]
|
63
|
+
# İlk video kaynağını al
|
64
|
+
video_url = None
|
65
|
+
for source in video_sources:
|
66
|
+
if file_url := source.get("file"):
|
67
|
+
video_url = file_url
|
68
|
+
break
|
69
|
+
|
70
|
+
if not video_url:
|
71
|
+
raise ValueError("Video URL bulunamadı.")
|
72
|
+
|
73
|
+
await self.close()
|
74
|
+
return ExtractResult(
|
75
|
+
name = self.name,
|
76
|
+
url = video_url,
|
77
|
+
referer = self.main_url,
|
78
|
+
subtitles = subtitles
|
79
|
+
)
|
80
|
+
|
81
|
+
def _add_marks(self, text: str, field: str) -> str:
|
82
|
+
"""
|
83
|
+
Verilen alanı çift tırnak içine alır.
|
84
|
+
"""
|
85
|
+
return re.sub(rf"\"?{field}\"?", f"\"{field}\"", text)
|
@@ -0,0 +1,50 @@
|
|
1
|
+
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
2
|
+
|
3
|
+
from KekikStream.Core import ExtractorBase, ExtractResult, Subtitle
|
4
|
+
from Kekik.Sifreleme import Packer, HexCodec
|
5
|
+
import re
|
6
|
+
|
7
|
+
class VidMoxy(ExtractorBase):
|
8
|
+
name = "VidMoxy"
|
9
|
+
main_url = "https://vidmoxy.com"
|
10
|
+
|
11
|
+
async def extract(self, url, referer=None) -> ExtractResult:
|
12
|
+
if referer:
|
13
|
+
self.oturum.headers.update({"Referer": referer})
|
14
|
+
|
15
|
+
istek = await self.oturum.get(url)
|
16
|
+
istek.raise_for_status()
|
17
|
+
|
18
|
+
subtitles = []
|
19
|
+
subtitle_matches = re.findall(r'captions","file":"([^"]+)","label":"([^"]+)"', istek.text)
|
20
|
+
seen_subtitles = set()
|
21
|
+
|
22
|
+
for sub_url, sub_lang in subtitle_matches:
|
23
|
+
if sub_url in seen_subtitles:
|
24
|
+
continue
|
25
|
+
|
26
|
+
seen_subtitles.add(sub_url)
|
27
|
+
decoded_lang = (
|
28
|
+
sub_lang.replace("\\u0131", "ı")
|
29
|
+
.replace("\\u0130", "İ")
|
30
|
+
.replace("\\u00fc", "ü")
|
31
|
+
.replace("\\u00e7", "ç")
|
32
|
+
)
|
33
|
+
subtitles.append(Subtitle(name=decoded_lang, url=sub_url.replace("\\", "")))
|
34
|
+
|
35
|
+
try:
|
36
|
+
escaped_hex = re.findall(r'file": "(.*)",', istek.text)[0]
|
37
|
+
except Exception:
|
38
|
+
eval_jwsetup = re.compile(r'\};\s*(eval\(function[\s\S]*?)var played = \d+;').findall(istek.text)[0]
|
39
|
+
jwsetup = Packer.unpack(Packer.unpack(eval_jwsetup))
|
40
|
+
escaped_hex = re.findall(r'file":"(.*)","label', jwsetup)[0]
|
41
|
+
|
42
|
+
m3u_link = HexCodec.decode(escaped_hex)
|
43
|
+
|
44
|
+
await self.close()
|
45
|
+
return ExtractResult(
|
46
|
+
name = self.name,
|
47
|
+
url = m3u_link,
|
48
|
+
referer = self.main_url,
|
49
|
+
subtitles = subtitles
|
50
|
+
)
|
@@ -0,0 +1,47 @@
|
|
1
|
+
# ! Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
2
|
+
|
3
|
+
from KekikStream.Core import ExtractorBase, ExtractResult, Subtitle
|
4
|
+
import json
|
5
|
+
|
6
|
+
class VideoSeyred(ExtractorBase):
|
7
|
+
name = "VideoSeyred"
|
8
|
+
main_url = "https://videoseyred.in"
|
9
|
+
|
10
|
+
async def extract(self, url, referer=None) -> ExtractResult:
|
11
|
+
if referer:
|
12
|
+
self.oturum.headers.update({"Referer": referer})
|
13
|
+
|
14
|
+
video_id = url.split("embed/")[1].split("?")[0]
|
15
|
+
video_url = f"{self.main_url}/playlist/{video_id}.json"
|
16
|
+
|
17
|
+
response = await self.oturum.get(video_url)
|
18
|
+
response.raise_for_status()
|
19
|
+
|
20
|
+
try:
|
21
|
+
if response_list := json.loads(response.text):
|
22
|
+
response_data = response_list[0]
|
23
|
+
else:
|
24
|
+
raise ValueError("Empty response from VideoSeyred.")
|
25
|
+
|
26
|
+
except (json.JSONDecodeError, IndexError) as hata:
|
27
|
+
raise RuntimeError(f"Failed to parse response: {hata}") from hata
|
28
|
+
|
29
|
+
subtitles = [
|
30
|
+
Subtitle(name=track["label"], url=self.fix_url(track["file"]))
|
31
|
+
for track in response_data.get("tracks", [])
|
32
|
+
if track.get("kind") == "captions" and track.get("label")
|
33
|
+
]
|
34
|
+
|
35
|
+
if video_links := [
|
36
|
+
ExtractResult(
|
37
|
+
name = self.name,
|
38
|
+
url = self.fix_url(source["file"]),
|
39
|
+
referer = self.main_url,
|
40
|
+
subtitles = subtitles,
|
41
|
+
)
|
42
|
+
for source in response_data.get("sources", [])
|
43
|
+
]:
|
44
|
+
# En yüksek kaliteli videoyu döndür (varsayılan olarak ilk video)
|
45
|
+
return video_links[0] if len(video_links) == 1 else video_links
|
46
|
+
else:
|
47
|
+
raise ValueError("No video links found in the response.")
|
@@ -0,0 +1,27 @@
|
|
1
|
+
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
2
|
+
|
3
|
+
from ..Core import ExtractorLoader, ExtractorBase
|
4
|
+
|
5
|
+
class ExtractorManager:
|
6
|
+
def __init__(self, extractor_dir="Extractors"):
|
7
|
+
self.extractor_loader = ExtractorLoader(extractor_dir)
|
8
|
+
self.extractors = self.extractor_loader.load_all()
|
9
|
+
|
10
|
+
def find_extractor(self, link):
|
11
|
+
for extractor_cls in self.extractors:
|
12
|
+
extractor:ExtractorBase = extractor_cls()
|
13
|
+
if extractor.can_handle_url(link):
|
14
|
+
return extractor
|
15
|
+
|
16
|
+
return None
|
17
|
+
|
18
|
+
def map_links_to_extractors(self, links):
|
19
|
+
mapping = {}
|
20
|
+
for link in links:
|
21
|
+
for extractor_cls in self.extractors:
|
22
|
+
extractor:ExtractorBase = extractor_cls()
|
23
|
+
if extractor.can_handle_url(link):
|
24
|
+
mapping[link] = f"{extractor.name:<30} » {link.replace(extractor.main_url, '')}"
|
25
|
+
break
|
26
|
+
|
27
|
+
return mapping
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
2
|
+
|
3
|
+
from ..Core import MediaHandler
|
4
|
+
|
5
|
+
class MediaManager:
|
6
|
+
def __init__(self):
|
7
|
+
self.media_handler = MediaHandler()
|
8
|
+
|
9
|
+
def set_title(self, title):
|
10
|
+
self.media_handler.title = title
|
11
|
+
|
12
|
+
def get_title(self):
|
13
|
+
return self.media_handler.title
|
14
|
+
|
15
|
+
def set_headers(self, headers):
|
16
|
+
self.media_handler.headers.update(headers)
|
17
|
+
|
18
|
+
def play_media(self, extract_data):
|
19
|
+
self.media_handler.play_media(extract_data)
|
@@ -0,0 +1,19 @@
|
|
1
|
+
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
2
|
+
|
3
|
+
from ..Core import PluginLoader, PluginBase
|
4
|
+
|
5
|
+
class PluginManager:
|
6
|
+
def __init__(self, plugin_dir="Plugins"):
|
7
|
+
self.plugin_loader = PluginLoader(plugin_dir)
|
8
|
+
self.plugins = self.plugin_loader.load_all()
|
9
|
+
|
10
|
+
def get_plugin_names(self):
|
11
|
+
return sorted(list(self.plugins.keys()))
|
12
|
+
|
13
|
+
def select_plugin(self, plugin_name):
|
14
|
+
return self.plugins.get(plugin_name)
|
15
|
+
|
16
|
+
async def close_plugins(self):
|
17
|
+
for plugin in self.plugins.values():
|
18
|
+
if isinstance(plugin, PluginBase):
|
19
|
+
await plugin.close()
|
@@ -0,0 +1,49 @@
|
|
1
|
+
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
2
|
+
|
3
|
+
from ..CLI import konsol
|
4
|
+
from rich.panel import Panel
|
5
|
+
from rich.table import Table
|
6
|
+
from InquirerPy import inquirer
|
7
|
+
import os
|
8
|
+
|
9
|
+
class UIManager:
|
10
|
+
@staticmethod
|
11
|
+
def clear_console():
|
12
|
+
# return True
|
13
|
+
os.system("cls" if os.name == "nt" else "clear")
|
14
|
+
|
15
|
+
@staticmethod
|
16
|
+
async def select_from_list(message, choices):
|
17
|
+
return await inquirer.select(message=message, choices=choices, max_height="75%").execute_async()
|
18
|
+
|
19
|
+
@staticmethod
|
20
|
+
async def select_from_fuzzy(message, choices):
|
21
|
+
return await inquirer.fuzzy(
|
22
|
+
message = message,
|
23
|
+
choices = choices,
|
24
|
+
validate = lambda result: result in [choice if isinstance(choice, str) else choice["value"] for choice in choices],
|
25
|
+
filter = lambda result: result,
|
26
|
+
max_height = "75%"
|
27
|
+
).execute_async()
|
28
|
+
|
29
|
+
@staticmethod
|
30
|
+
async def prompt_text(message):
|
31
|
+
return await inquirer.text(message=message).execute_async()
|
32
|
+
|
33
|
+
@staticmethod
|
34
|
+
def display_media_info(plugin_name, media_info):
|
35
|
+
table = Table(show_header=False, box=None)
|
36
|
+
table.add_column(justify="right", style="cyan", no_wrap=True)
|
37
|
+
table.add_column(style="magenta")
|
38
|
+
|
39
|
+
for key, value in media_info.dict().items():
|
40
|
+
if key == "episodes":
|
41
|
+
continue
|
42
|
+
|
43
|
+
if isinstance(value, str):
|
44
|
+
if '",' in value:
|
45
|
+
continue
|
46
|
+
|
47
|
+
table.add_row(f"[bold cyan]{key.capitalize()}[/bold cyan]", str(value))
|
48
|
+
|
49
|
+
konsol.print(Panel(table, title=f"[bold green]{plugin_name}[/bold green]", expand=False))
|
@@ -0,0 +1,143 @@
|
|
1
|
+
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
2
|
+
|
3
|
+
from KekikStream.Core import PluginBase, SearchResult, SeriesInfo, Episode
|
4
|
+
from Kekik.Sifreleme import CryptoJS
|
5
|
+
from parsel import Selector
|
6
|
+
import re, urllib.parse, base64, contextlib, asyncio
|
7
|
+
|
8
|
+
class DiziBox(PluginBase):
|
9
|
+
name = "DiziBox"
|
10
|
+
main_url = "https://www.dizibox.plus"
|
11
|
+
|
12
|
+
async def search(self, query: str) -> list[SearchResult]:
|
13
|
+
self.oturum.cookies.update({
|
14
|
+
"LockUser" : "true",
|
15
|
+
"isTrustedUser" : "true",
|
16
|
+
"dbxu" : "1722403730363"
|
17
|
+
})
|
18
|
+
istek = await self.oturum.get(f"{self.main_url}/?s={query}")
|
19
|
+
secici = Selector(istek.text)
|
20
|
+
|
21
|
+
return [
|
22
|
+
SearchResult(
|
23
|
+
title = item.css("h3 a::text").get(),
|
24
|
+
url = self.fix_url(item.css("h3 a::attr(href)").get()),
|
25
|
+
poster = self.fix_url(item.css("img::attr(src)").get()),
|
26
|
+
)
|
27
|
+
for item in secici.css("article.detailed-article")
|
28
|
+
]
|
29
|
+
|
30
|
+
async def load_item(self, url: str) -> SeriesInfo:
|
31
|
+
istek = await self.oturum.get(url)
|
32
|
+
secici = Selector(istek.text)
|
33
|
+
|
34
|
+
title = secici.css("div.tv-overview h1 a::text").get()
|
35
|
+
poster = self.fix_url(secici.css("div.tv-overview figure img::attr(src)").get())
|
36
|
+
description = secici.css("div.tv-story p::text").get()
|
37
|
+
year = secici.css("a[href*='/yil/']::text").re_first(r"(\d{4})")
|
38
|
+
tags = secici.css("a[href*='/tur/']::text").getall()
|
39
|
+
rating = secici.css("span.label-imdb b::text").re_first(r"[\d.,]+")
|
40
|
+
actors = [actor.css("::text").get() for actor in secici.css("a[href*='/oyuncu/']")]
|
41
|
+
|
42
|
+
episodes = []
|
43
|
+
for sezon_link in secici.css("div#seasons-list a::attr(href)").getall():
|
44
|
+
sezon_url = self.fix_url(sezon_link)
|
45
|
+
sezon_istek = await self.oturum.get(sezon_url)
|
46
|
+
sezon_secici = Selector(sezon_istek.text)
|
47
|
+
|
48
|
+
for bolum in sezon_secici.css("article.grid-box"):
|
49
|
+
ep_secici = bolum.css("div.post-title a::text")
|
50
|
+
|
51
|
+
ep_title = ep_secici.get()
|
52
|
+
ep_href = self.fix_url(bolum.css("div.post-title a::attr(href)").get())
|
53
|
+
ep_season = ep_secici.re_first(r"(\d+)\. ?Sezon")
|
54
|
+
ep_episode = ep_secici.re_first(r"(\d+)\. ?Bölüm")
|
55
|
+
|
56
|
+
if ep_title and ep_href:
|
57
|
+
episodes.append(Episode(
|
58
|
+
season = ep_season,
|
59
|
+
episode = ep_episode,
|
60
|
+
title = ep_title.strip(),
|
61
|
+
url = ep_href,
|
62
|
+
))
|
63
|
+
|
64
|
+
return SeriesInfo(
|
65
|
+
url = url,
|
66
|
+
poster = poster,
|
67
|
+
title = title,
|
68
|
+
description = description,
|
69
|
+
tags = tags,
|
70
|
+
rating = rating,
|
71
|
+
year = year,
|
72
|
+
episodes = episodes,
|
73
|
+
actors = actors,
|
74
|
+
)
|
75
|
+
|
76
|
+
async def _iframe_decode(self, name:str, iframe_link:str, referer:str) -> list[str]:
|
77
|
+
results = []
|
78
|
+
|
79
|
+
if "/player/king/king.php" in iframe_link:
|
80
|
+
iframe_link = iframe_link.replace("king.php?v=", "king.php?wmode=opaque&v=")
|
81
|
+
self.oturum.headers.update({"Referer": referer})
|
82
|
+
|
83
|
+
istek = await self.oturum.get(iframe_link)
|
84
|
+
secici = Selector(istek.text)
|
85
|
+
iframe = secici.css("div#Player iframe::attr(src)").get()
|
86
|
+
|
87
|
+
self.oturum.headers.update({"Referer": self.main_url})
|
88
|
+
istek = await self.oturum.get(iframe)
|
89
|
+
|
90
|
+
crypt_data = re.search(r"CryptoJS\.AES\.decrypt\(\"(.*)\",\"", istek.text)[1]
|
91
|
+
crypt_pass = re.search(r"\",\"(.*)\"\);", istek.text)[1]
|
92
|
+
|
93
|
+
results.append(CryptoJS.decrypt(crypt_pass, crypt_data))
|
94
|
+
|
95
|
+
elif "/player/moly/moly.php" in iframe_link:
|
96
|
+
iframe_link = iframe_link.replace("moly.php?h=", "moly.php?wmode=opaque&h=")
|
97
|
+
self.oturum.headers.update({"Referer": referer})
|
98
|
+
while True:
|
99
|
+
await asyncio.sleep(.3)
|
100
|
+
with contextlib.suppress(Exception):
|
101
|
+
istek = await self.oturum.get(iframe_link)
|
102
|
+
|
103
|
+
if atob_data := re.search(r"unescape\(\"(.*)\"\)", istek.text):
|
104
|
+
decoded_atob = urllib.parse.unquote(atob_data[1])
|
105
|
+
str_atob = base64.b64decode(decoded_atob).decode("utf-8")
|
106
|
+
|
107
|
+
if iframe := Selector(str_atob).css("div#Player iframe::attr(src)").get():
|
108
|
+
results.append(iframe)
|
109
|
+
|
110
|
+
break
|
111
|
+
|
112
|
+
elif "/player/haydi.php" in iframe_link:
|
113
|
+
okru_url = base64.b64decode(iframe_link.split("?v=")[-1]).decode("utf-8")
|
114
|
+
results.append(okru_url)
|
115
|
+
|
116
|
+
return results
|
117
|
+
|
118
|
+
async def load_links(self, url: str) -> list[str]:
|
119
|
+
istek = await self.oturum.get(url)
|
120
|
+
secici = Selector(istek.text)
|
121
|
+
|
122
|
+
iframes = []
|
123
|
+
if main_iframe := secici.css("div#video-area iframe::attr(src)").get():
|
124
|
+
if decoded := await self._iframe_decode(self.name, main_iframe, url):
|
125
|
+
iframes.extend(decoded)
|
126
|
+
|
127
|
+
for alternatif in secici.css("div.video-toolbar option[value]"):
|
128
|
+
alt_name = alternatif.css("::text").get()
|
129
|
+
alt_link = alternatif.css("::attr(value)").get()
|
130
|
+
|
131
|
+
if not alt_link:
|
132
|
+
continue
|
133
|
+
|
134
|
+
self.oturum.headers.update({"Referer": url})
|
135
|
+
alt_istek = await self.oturum.get(alt_link)
|
136
|
+
alt_istek.raise_for_status()
|
137
|
+
|
138
|
+
alt_secici = Selector(alt_istek.text)
|
139
|
+
if alt_iframe := alt_secici.css("div#video-area iframe::attr(src)").get():
|
140
|
+
if decoded := await self._iframe_decode(alt_name, alt_iframe, url):
|
141
|
+
iframes.extend(decoded)
|
142
|
+
|
143
|
+
return iframes
|
@@ -0,0 +1,127 @@
|
|
1
|
+
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
2
|
+
|
3
|
+
from KekikStream.Core import PluginBase, SearchResult, SeriesInfo, Episode, Subtitle, ExtractResult
|
4
|
+
from parsel import Selector
|
5
|
+
import re
|
6
|
+
|
7
|
+
class DiziYou(PluginBase):
|
8
|
+
name = "DiziYou"
|
9
|
+
main_url = "https://www.diziyou.co"
|
10
|
+
|
11
|
+
async def search(self, query: str) -> list[SearchResult]:
|
12
|
+
istek = await self.oturum.get(f"{self.main_url}/?s={query}")
|
13
|
+
secici = Selector(istek.text)
|
14
|
+
|
15
|
+
return [
|
16
|
+
SearchResult(
|
17
|
+
title = afis.css("div#categorytitle a::text").get().strip(),
|
18
|
+
url = self.fix_url(afis.css("div#categorytitle a::attr(href)").get()),
|
19
|
+
poster = self.fix_url(afis.css("img::attr(src)").get()),
|
20
|
+
)
|
21
|
+
for afis in secici.css("div.incontent div#list-series")
|
22
|
+
]
|
23
|
+
|
24
|
+
async def load_item(self, url: str) -> SeriesInfo:
|
25
|
+
istek = await self.oturum.get(url)
|
26
|
+
secici = Selector(istek.text)
|
27
|
+
|
28
|
+
title = secici.css("h1::text").get().strip()
|
29
|
+
poster = self.fix_url(secici.css("div.category_image img::attr(src)").get().strip())
|
30
|
+
year = secici.xpath("//span[contains(., 'Yapım Yılı')]/following-sibling::text()[1]").get()
|
31
|
+
description = secici.css("div.diziyou_desc::text").get().strip()
|
32
|
+
tags = secici.css("div.genres a::text").getall()
|
33
|
+
rating = secici.xpath("//span[contains(., 'IMDB')]/following-sibling::text()[1]").get()
|
34
|
+
_actors = secici.xpath("//span[contains(., 'Oyuncular')]/following-sibling::text()[1]").get()
|
35
|
+
actors = [actor.strip() for actor in _actors.split(",")] if _actors else []
|
36
|
+
|
37
|
+
episodes = []
|
38
|
+
for it in secici.css("div.bolumust"):
|
39
|
+
ep_name = it.css("div.baslik::text").get().strip()
|
40
|
+
ep_href = it.xpath("ancestor::a/@href").get()
|
41
|
+
if not ep_name or not ep_href:
|
42
|
+
continue
|
43
|
+
|
44
|
+
ep_name_clean = it.css("div.bolumismi::text").get().strip().replace("(", "").replace(")", "").strip() if it.css("div.bolumismi::text").get() else ep_name
|
45
|
+
|
46
|
+
ep_episode = re.search(r"(\d+)\. Bölüm", ep_name)[1]
|
47
|
+
ep_season = re.search(r"(\d+)\. Sezon", ep_name)[1]
|
48
|
+
|
49
|
+
episode = Episode(
|
50
|
+
season = ep_season,
|
51
|
+
episode = ep_episode,
|
52
|
+
title = ep_name_clean,
|
53
|
+
url = ep_href,
|
54
|
+
)
|
55
|
+
|
56
|
+
episodes.append(episode)
|
57
|
+
|
58
|
+
return SeriesInfo(
|
59
|
+
url = url,
|
60
|
+
poster = poster,
|
61
|
+
title = title,
|
62
|
+
description = description,
|
63
|
+
tags = tags,
|
64
|
+
rating = rating,
|
65
|
+
year = year,
|
66
|
+
episodes = episodes,
|
67
|
+
actors = actors
|
68
|
+
)
|
69
|
+
|
70
|
+
async def load_links(self, url: str) -> list[str]:
|
71
|
+
istek = await self.oturum.get(url)
|
72
|
+
secici = Selector(istek.text)
|
73
|
+
|
74
|
+
item_title = secici.css("div.title h1::text").get().strip()
|
75
|
+
item_id = secici.css("iframe#diziyouPlayer::attr(src)").get().split("/")[-1].replace(".html", "")
|
76
|
+
|
77
|
+
subtitles = []
|
78
|
+
stream_urls = []
|
79
|
+
|
80
|
+
for secenek in secici.css("span.diziyouOption"):
|
81
|
+
opt_id = secenek.css("::attr(id)").get()
|
82
|
+
op_name = secenek.css("::text").get()
|
83
|
+
|
84
|
+
match opt_id:
|
85
|
+
case "turkceAltyazili":
|
86
|
+
subtitles.append(Subtitle(
|
87
|
+
name = op_name,
|
88
|
+
url = self.fix_url(f"https://storage.diziyou.co/subtitles/{item_id}/tr.vtt"),
|
89
|
+
))
|
90
|
+
veri = {
|
91
|
+
"dil": "Orjinal Dil",
|
92
|
+
"url": f"https://storage.diziyou.co/episodes/{item_id}/play.m3u8"
|
93
|
+
}
|
94
|
+
if veri not in stream_urls:
|
95
|
+
stream_urls.append(veri)
|
96
|
+
case "ingilizceAltyazili":
|
97
|
+
subtitles.append(Subtitle(
|
98
|
+
name = op_name,
|
99
|
+
url = self.fix_url(f"https://storage.diziyou.co/subtitles/{item_id}/en.vtt"),
|
100
|
+
))
|
101
|
+
veri = {
|
102
|
+
"dil": "Orjinal Dil",
|
103
|
+
"url": f"https://storage.diziyou.co/episodes/{item_id}/play.m3u8"
|
104
|
+
}
|
105
|
+
if veri not in stream_urls:
|
106
|
+
stream_urls.append(veri)
|
107
|
+
case "turkceDublaj":
|
108
|
+
stream_urls.append({
|
109
|
+
"dil": "Dublaj",
|
110
|
+
"url": f"https://storage.diziyou.co/episodes/{item_id}_tr/play.m3u8"
|
111
|
+
})
|
112
|
+
|
113
|
+
|
114
|
+
for stream in stream_urls:
|
115
|
+
self._data[stream.get("url")] = {
|
116
|
+
"name" : f"{self.name} | {stream.get('dil')} | {item_title}",
|
117
|
+
"ext_name" : f"{self.name} | {stream.get('dil')}",
|
118
|
+
"referer" : url,
|
119
|
+
"subtitles" : subtitles
|
120
|
+
}
|
121
|
+
|
122
|
+
return [stream.get("url") for stream in stream_urls]
|
123
|
+
|
124
|
+
async def play(self, name: str, url: str, referer: str, subtitles: list[Subtitle]):
|
125
|
+
extract_result = ExtractResult(name=name, url=url, referer=referer, subtitles=subtitles)
|
126
|
+
self.media_handler.title = name
|
127
|
+
self.media_handler.play_media(extract_result)
|