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.
@@ -1,16 +1,16 @@
1
1
  # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
2
 
3
- from . import konsol
4
- from rich.panel import Panel
5
- from pkg_resources import get_distribution
6
- from requests import get
7
- from subprocess import check_call
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 = get_distribution(paket_adi).version
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 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 urllib.parse import urljoin
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[str]:
57
- """Bir medya öğesi için oynatma bağlantılarını döndürür."""
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, base64
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.de"
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 = get_m3u_link(extract_data(Packer.unpack(eval_func)))
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 = url,
13
- referer = url.replace("/sheila", ""),
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
- eval_jwsetup = re.search(r'\};\s*(eval\(function[\s\S]*?)var played = \d+;', istek.text)
41
- if not eval_jwsetup:
42
- raise ValueError("JWPlayer setup not found.")
40
+ av_encoded = re.search(r"av\('([^']+)'\)", istek.text)
41
+ if not av_encoded:
42
+ raise ValueError("AV encoding not found.")
43
43
 
44
- unpacked_jwsetup = Packer.unpack(Packer.unpack(eval_jwsetup[1]))
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 re, asyncio, contextlib, json
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", ".to")
22
- url = url.replace(".me", ".to")
22
+ self.main_url = self.main_url.replace(".me", ".net")
23
+ url = url.replace(".me", ".net")
23
24
 
24
- # Embed URL oluştur
25
- embed_url = url.replace("/w/", "/embed-") + "-920x360.html" if "/w/" in url else url
26
- script_content = None
27
- attempts = 0
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
- # Script verisini almak için deneme yap
30
- while attempts < 10 and not script_content:
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ı.")
@@ -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
- @kekik_cache(ttl=60*60)
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
- @kekik_cache(ttl=60*60)
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" : "1722403730363"
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
- @kekik_cache(ttl=60*60)
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
- @kekik_cache(ttl=60*60)
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
- @kekik_cache(ttl=15*60)
175
- async def load_links(self, url: str) -> list[str]:
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
- iframes = []
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
- iframes.extend(decoded)
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
- iframes.extend(decoded)
199
-
200
- return iframes
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
@@ -7,7 +7,7 @@ import re
7
7
  class DiziYou(PluginBase):
8
8
  name = "DiziYou"
9
9
  language = "tr"
10
- main_url = "https://www.diziyou2.com"
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
- _data = {}
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
- @kekik_cache(ttl=60*60)
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
- @kekik_cache(ttl=60*60)
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().strip()
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
- @kekik_cache(ttl=15*60)
111
- async def load_links(self, url: str) -> list[str]:
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
- self._data[stream.get("url")] = {
158
- "ext_name" : f"{self.name} | {stream.get('dil')}",
159
- "name" : f"{self.name} | {stream.get('dil')} | {item_title} - {ep_name}",
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 [stream.get("url") for stream in stream_urls]
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)