KekikStream 0.8.0__py3-none-any.whl → 0.8.2__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.
@@ -5,12 +5,15 @@ from httpx import AsyncClient, Timeout
5
5
  from cloudscraper import CloudScraper
6
6
  from typing import Optional
7
7
  from .ExtractorModels import ExtractResult
8
+ from urllib.parse import urljoin
8
9
 
9
10
  class ExtractorBase(ABC):
11
+ # Çıkarıcının temel özellikleri
10
12
  name = "Extractor"
11
13
  main_url = ""
12
14
 
13
15
  def __init__(self):
16
+ # HTTP istekleri için oturum oluştur
14
17
  self.oturum = AsyncClient(
15
18
  headers = {
16
19
  "User-Agent" : "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5)",
@@ -18,21 +21,24 @@ class ExtractorBase(ABC):
18
21
  },
19
22
  timeout = Timeout(10.0)
20
23
  )
24
+ # CloudFlare korumalı siteler için scraper ayarla
21
25
  self.cloudscraper = CloudScraper()
22
26
 
23
27
  def can_handle_url(self, url: str) -> bool:
24
- """URL'nin bu extractor tarafından işlenip işlenemeyeceğini kontrol eder."""
28
+ # URL'nin bu çıkarıcı tarafından işlenip işlenemeyeceğini kontrol et
25
29
  return self.main_url in url
26
30
 
27
31
  @abstractmethod
28
32
  async def extract(self, url: str, referer: Optional[str] = None) -> ExtractResult:
29
- """Bir URL'den medya bilgilerini çıkarır."""
33
+ # Alt sınıflar tarafından uygulanacak medya çıkarma fonksiyonu
30
34
  pass
31
35
 
32
36
  async def close(self):
37
+ # HTTP oturumunu güvenli bir şekilde kapat
33
38
  await self.oturum.aclose()
34
39
 
35
40
  def fix_url(self, url: str) -> str:
41
+ # Eksik URL'leri düzelt ve tam URL formatına çevir
36
42
  if not url:
37
43
  return ""
38
44
 
@@ -1,14 +1,17 @@
1
1
  # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
2
 
3
- from ..CLI import konsol, cikis_yap
3
+ from ...CLI import konsol, cikis_yap
4
4
  from .ExtractorBase import ExtractorBase
5
5
  from pathlib import Path
6
6
  import os, importlib.util
7
7
 
8
8
  class ExtractorLoader:
9
9
  def __init__(self, extractors_dir: str):
10
+ # Yerel ve global çıkarıcı dizinlerini ayarla
10
11
  self.local_extractors_dir = Path(extractors_dir)
11
- self.global_extractors_dir = Path(__file__).parent.parent / extractors_dir
12
+ self.global_extractors_dir = Path(__file__).parent.parent.parent / extractors_dir
13
+
14
+ # Dizin kontrolü
12
15
  if not self.local_extractors_dir.exists() and not self.global_extractors_dir.exists():
13
16
  konsol.log(f"[red][!] Extractor dizini bulunamadı: {self.global_extractors_dir}[/red]")
14
17
  cikis_yap(False)
@@ -16,14 +19,14 @@ class ExtractorLoader:
16
19
  def load_all(self) -> list[ExtractorBase]:
17
20
  extractors = []
18
21
 
19
- # Global Extractor'ları yükle
22
+ # Global çıkarıcıları yükle
20
23
  if self.global_extractors_dir.exists():
21
24
  konsol.log(f"[green][*] Global Extractor dizininden yükleniyor: {self.global_extractors_dir}[/green]")
22
25
  global_extractors = self._load_from_directory(self.global_extractors_dir)
23
26
  konsol.log(f"[green]Global Extractor'lar: {[e.__name__ for e in global_extractors]}[/green]")
24
27
  extractors.extend(global_extractors)
25
28
 
26
- # Yerel Extractor'ları yükle
29
+ # Yerel çıkarıcıları yükle
27
30
  if self.local_extractors_dir.exists():
28
31
  konsol.log(f"[green][*] Yerel Extractor dizininden yükleniyor: {self.local_extractors_dir}[/green]")
29
32
  local_extractors = self._load_from_directory(self.local_extractors_dir)
@@ -32,12 +35,12 @@ class ExtractorLoader:
32
35
 
33
36
  # Benzersizliği sağlama (modül adı + sınıf adı bazında)
34
37
  unique_extractors = []
35
- seen = set()
38
+ seen_names = set()
36
39
  for ext in extractors:
37
40
  identifier = f"{ext.__module__}.{ext.__name__}"
38
- if identifier not in seen:
41
+ if identifier not in seen_names:
39
42
  unique_extractors.append(ext)
40
- seen.add(identifier)
43
+ seen_names.add(identifier)
41
44
 
42
45
  konsol.log(f"[blue]Sonuç Extractor'lar: {[e.__name__ for e in unique_extractors]}[/blue]")
43
46
 
@@ -48,12 +51,14 @@ class ExtractorLoader:
48
51
 
49
52
  def _load_from_directory(self, directory: Path) -> list[ExtractorBase]:
50
53
  extractors = []
54
+
55
+ # Dizindeki tüm .py dosyalarını tara
51
56
  for file in os.listdir(directory):
52
57
  if file.endswith(".py") and not file.startswith("__"):
53
- module_name = file[:-3]
54
- konsol.log(f"[cyan]Modül yükleniyor: {module_name}[/cyan]")
58
+ module_name = file[:-3] # .py uzantısını kaldır
59
+ konsol.log(f"[cyan]Okunan Dosya\t\t: {module_name}[/cyan]")
55
60
  if extractor := self._load_extractor(directory, module_name):
56
- konsol.log(f"[magenta]Extractor bulundu: {extractor.__name__}[/magenta]")
61
+ konsol.log(f"[magenta]Extractor Yüklendi\t: {extractor.__name__}[/magenta]")
57
62
  extractors.append(extractor)
58
63
 
59
64
  konsol.log(f"[yellow]{directory} dizininden yüklenen Extractor'lar: {[e.__name__ for e in extractors]}[/yellow]")
@@ -61,11 +66,13 @@ class ExtractorLoader:
61
66
 
62
67
  def _load_extractor(self, directory: Path, module_name: str):
63
68
  try:
69
+ # Modül dosyasını bul ve yükle
64
70
  path = directory / f"{module_name}.py"
65
71
  spec = importlib.util.spec_from_file_location(module_name, path)
66
72
  if not spec or not spec.loader:
67
73
  return None
68
74
 
75
+ # Modülü içe aktar
69
76
  module = importlib.util.module_from_spec(spec)
70
77
  spec.loader.exec_module(module)
71
78
 
@@ -73,7 +80,7 @@ class ExtractorLoader:
73
80
  for attr in dir(module):
74
81
  obj = getattr(module, attr)
75
82
  if obj.__module__ == module_name and isinstance(obj, type) and issubclass(obj, ExtractorBase) and obj is not ExtractorBase:
76
- konsol.log(f"[green]Yüklenen sınıf: {module_name}.{obj.__name__} ({obj.__module__}.{obj.__name__})[/green]")
83
+ konsol.log(f"[green]Yüklenen sınıf\t\t: {module_name}.{obj.__name__} ({obj.__module__}.{obj.__name__})[/green]")
77
84
  return obj
78
85
 
79
86
  except Exception as hata:
@@ -1,13 +1,16 @@
1
1
  # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
2
 
3
- from ..Core import ExtractorLoader, ExtractorBase
3
+ from .ExtractorLoader import ExtractorLoader
4
+ from .ExtractorBase import ExtractorBase
4
5
 
5
6
  class ExtractorManager:
6
7
  def __init__(self, extractor_dir="Extractors"):
8
+ # Çıkarıcı yükleyiciyi başlat ve tüm çıkarıcıları yükle
7
9
  self.extractor_loader = ExtractorLoader(extractor_dir)
8
10
  self.extractors = self.extractor_loader.load_all()
9
11
 
10
- def find_extractor(self, link):
12
+ def find_extractor(self, link) -> ExtractorBase:
13
+ # Verilen bağlantıyı işleyebilecek çıkarıcıyı bul
11
14
  for extractor_cls in self.extractors:
12
15
  extractor:ExtractorBase = extractor_cls()
13
16
  if extractor.can_handle_url(link):
@@ -15,7 +18,8 @@ class ExtractorManager:
15
18
 
16
19
  return None
17
20
 
18
- def map_links_to_extractors(self, links):
21
+ def map_links_to_extractors(self, links) -> dict:
22
+ # Bağlantıları uygun çıkarıcılarla eşleştir
19
23
  mapping = {}
20
24
  for link in links:
21
25
  for extractor_cls in self.extractors:
@@ -1,11 +1,12 @@
1
1
  # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
2
 
3
- from ..CLI import konsol
4
- from .ExtractorModels import ExtractResult
3
+ from ...CLI import konsol
4
+ from ..Extractor.ExtractorModels import ExtractResult
5
5
  import subprocess, os
6
6
 
7
7
  class MediaHandler:
8
8
  def __init__(self, title: str = "KekikStream", headers: dict = None):
9
+ # Varsayılan HTTP başlıklarını ayarla
9
10
  if headers is None:
10
11
  headers = {"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5)"}
11
12
 
@@ -13,12 +14,15 @@ class MediaHandler:
13
14
  self.title = title
14
15
 
15
16
  def play_media(self, extract_data: ExtractResult):
17
+ # Google Drive gibi özel durumlar için yt-dlp kullan
16
18
  if self.headers.get("User-Agent") == "googleusercontent":
17
19
  return self.play_with_ytdlp(extract_data)
18
20
 
21
+ # İşletim sistemine göre oynatıcı seç
19
22
  if subprocess.check_output(['uname', '-o']).strip() == b'Android':
20
23
  return self.play_with_android_mxplayer(extract_data)
21
24
 
25
+ # Cookie veya alt yazılar varsa mpv kullan
22
26
  if "Cookie" in self.headers or extract_data.subtitles:
23
27
  return self.play_with_mpv(extract_data)
24
28
 
@@ -1,6 +1,6 @@
1
1
  # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
2
 
3
- from ..Core import MediaHandler
3
+ from .MediaHandler import MediaHandler
4
4
 
5
5
  class MediaManager:
6
6
  def __init__(self):
@@ -1,11 +1,11 @@
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 SearchResult, MovieInfo
7
- from .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 SearchResult, MovieInfo
7
+ from ..Media.MediaHandler import MediaHandler
8
+ from urllib.parse import urljoin
9
9
  import re
10
10
 
11
11
  class PluginBase(ABC):
@@ -1,61 +1,75 @@
1
1
  # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
2
 
3
- from ..CLI import konsol, cikis_yap
3
+ from ...CLI import konsol, cikis_yap
4
4
  from .PluginBase import PluginBase
5
5
  from pathlib import Path
6
6
  import os, importlib.util, traceback
7
7
 
8
8
  class PluginLoader:
9
9
  def __init__(self, plugins_dir: str):
10
+ # Yerel ve global eklenti dizinlerini ayarla
10
11
  self.local_plugins_dir = Path(plugins_dir).resolve()
11
- self.global_plugins_dir = Path(__file__).parent.parent / plugins_dir
12
+ self.global_plugins_dir = Path(__file__).parent.parent.parent / plugins_dir
13
+
14
+ # Dizin kontrolü
12
15
  if not self.local_plugins_dir.exists() and not self.global_plugins_dir.exists():
13
- konsol.log(f"[red][!] Extractor dizini bulunamadı: {self.plugins_dir}[/red]")
16
+ konsol.log(f"[red][!] Eklenti dizini bulunamadı: {plugins_dir}[/red]")
14
17
  cikis_yap(False)
15
18
 
16
19
  def load_all(self) -> dict[str, PluginBase]:
17
20
  plugins = {}
18
21
 
22
+ # Global eklentileri yükle
19
23
  if self.global_plugins_dir.exists():
20
- konsol.log(f"[green][*] Global Plugin dizininden yükleniyor: {self.global_plugins_dir}[/green]")
24
+ konsol.log(f"[green][*] Global Eklenti dizininden yükleniyor: {self.global_plugins_dir}[/green]")
21
25
  plugins |= self._load_from_directory(self.global_plugins_dir)
22
26
 
27
+ # Yerel eklentileri yükle
23
28
  if self.local_plugins_dir.exists():
24
- konsol.log(f"[green][*] Yerel Plugin dizininden yükleniyor: {self.local_plugins_dir}[/green]")
29
+ konsol.log(f"[green][*] Yerel Eklenti dizininden yükleniyor: {self.local_plugins_dir}[/green]")
25
30
  plugins |= self._load_from_directory(self.local_plugins_dir)
26
31
 
27
32
  if not plugins:
28
- konsol.print("[yellow][!] Yüklenecek bir Plugin bulunamadı![/yellow]")
33
+ konsol.print("[yellow][!] Yüklenecek bir Eklenti bulunamadı![/yellow]")
29
34
 
30
35
  return dict(sorted(plugins.items()))
31
36
 
32
37
  def _load_from_directory(self, directory: Path) -> dict[str, PluginBase]:
33
38
  plugins = {}
39
+
40
+ # Dizindeki tüm .py dosyalarını tara
34
41
  for file in os.listdir(directory):
35
42
  if file.endswith(".py") and not file.startswith("__"):
36
- module_name = file[:-3]
43
+ module_name = file[:-3] # .py uzantısını kaldır
44
+ konsol.log(f"[cyan]Okunan Dosya\t\t: {module_name}[/cyan]")
37
45
  if plugin := self._load_plugin(directory, module_name):
46
+ konsol.log(f"[magenta]Eklenti Yüklendi\t: {plugin.name}[/magenta]")
38
47
  plugins[module_name] = plugin
39
48
 
49
+ konsol.log(f"[yellow]{directory} dizininden yüklenen Eklentiler: {list(plugins.keys())}[/yellow]")
40
50
  return plugins
41
51
 
42
52
  def _load_plugin(self, directory: Path, module_name: str):
43
53
  try:
54
+ # Modül dosyasını bul ve yükle
44
55
  path = directory / f"{module_name}.py"
45
56
  spec = importlib.util.spec_from_file_location(module_name, path)
46
57
  if not spec or not spec.loader:
47
58
  raise ImportError(f"Spec oluşturulamadı: {module_name}")
48
59
 
60
+ # Modülü içe aktar
49
61
  module = importlib.util.module_from_spec(spec)
50
62
  spec.loader.exec_module(module)
51
63
 
64
+ # Yalnızca doğru modülden gelen PluginBase sınıflarını yükle
52
65
  for attr in dir(module):
53
66
  obj = getattr(module, attr)
54
67
  if isinstance(obj, type) and issubclass(obj, PluginBase) and obj is not PluginBase:
68
+ konsol.log(f"[yellow]Yüklenen sınıf\t\t: {module_name}.{obj.__name__} ({obj.__module__}.{obj.__name__})[/yellow]")
55
69
  return obj()
56
70
 
57
71
  except Exception as hata:
58
- konsol.print(f"[red][!] Plugin yüklenirken hata oluştu: {module_name}\nHata: {hata}")
72
+ konsol.print(f"[red][!] Eklenti yüklenirken hata oluştu: {module_name}\nHata: {hata}")
59
73
  konsol.print(f"[dim]{traceback.format_exc()}[/dim]")
60
74
 
61
75
  return None
@@ -1,19 +1,24 @@
1
1
  # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
2
 
3
- from ..Core import PluginLoader, PluginBase
3
+ from .PluginLoader import PluginLoader
4
+ from .PluginBase import PluginBase
4
5
 
5
6
  class PluginManager:
6
7
  def __init__(self, plugin_dir="Plugins"):
8
+ # Eklenti yükleyiciyi başlat ve tüm eklentileri yükle
7
9
  self.plugin_loader = PluginLoader(plugin_dir)
8
10
  self.plugins = self.plugin_loader.load_all()
9
11
 
10
12
  def get_plugin_names(self):
13
+ # Dizindeki tüm eklenti adlarını listeler ve sıralar
11
14
  return sorted(list(self.plugins.keys()))
12
15
 
13
16
  def select_plugin(self, plugin_name):
17
+ # Verilen eklenti adını kullanarak eklentiyi seç
14
18
  return self.plugins.get(plugin_name)
15
19
 
16
20
  async def close_plugins(self):
21
+ # Tüm eklentileri kapat
17
22
  for plugin in self.plugins.values():
18
23
  if isinstance(plugin, PluginBase):
19
24
  await plugin.close()
@@ -1,6 +1,6 @@
1
1
  # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
2
 
3
- from ..CLI import konsol
3
+ from ...CLI import konsol
4
4
  from rich.panel import Panel
5
5
  from rich.table import Table
6
6
  from InquirerPy import inquirer
@@ -1,9 +1,16 @@
1
1
  # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
2
 
3
- from .PluginBase import PluginBase
4
- from .PluginLoader import PluginLoader
5
- from .PluginModels import SearchResult, MovieInfo, Episode, SeriesInfo
6
- from .ExtractorBase import ExtractorBase
7
- from .ExtractorLoader import ExtractorLoader
8
- from .ExtractorModels import ExtractResult, Subtitle
9
- from .MediaHandler import MediaHandler
3
+ from .UI.UIManager import UIManager
4
+
5
+ from .Plugin.PluginManager import PluginManager
6
+ from .Plugin.PluginBase import PluginBase
7
+ from .Plugin.PluginLoader import PluginLoader
8
+ from .Plugin.PluginModels import SearchResult, MovieInfo, Episode, SeriesInfo
9
+
10
+ from .Extractor.ExtractorManager import ExtractorManager
11
+ from .Extractor.ExtractorBase import ExtractorBase
12
+ from .Extractor.ExtractorLoader import ExtractorLoader
13
+ from .Extractor.ExtractorModels import ExtractResult, Subtitle
14
+
15
+ from .Media.MediaManager import MediaManager
16
+ from .Media.MediaHandler import MediaHandler
@@ -1,10 +1,9 @@
1
1
  # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
2
 
3
- from KekikStream.CLI import konsol
4
- from KekikStream.Core import PluginBase, SearchResult, MovieInfo, Episode, SeriesInfo
5
- from KekikStream.Core.ExtractorModels import ExtractResult, Subtitle
6
- from httpx import AsyncClient
7
- from json import dumps, loads
3
+ from KekikStream.CLI import konsol
4
+ from KekikStream.Core import PluginBase, SearchResult, MovieInfo, Episode, SeriesInfo, ExtractResult, Subtitle
5
+ from httpx import AsyncClient
6
+ from json import dumps, loads
8
7
  import re
9
8
 
10
9
 
@@ -1,7 +1,6 @@
1
1
  # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
2
 
3
- from KekikStream.Core import PluginBase, SearchResult, MovieInfo, Episode, SeriesInfo
4
- from KekikStream.Core.ExtractorModels import ExtractResult, Subtitle
3
+ from KekikStream.Core import PluginBase, SearchResult, MovieInfo, Episode, SeriesInfo, ExtractResult, Subtitle
5
4
 
6
5
  class SineWix(PluginBase):
7
6
  name = "SineWix"
KekikStream/__init__.py CHANGED
@@ -1,13 +1,13 @@
1
1
  # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
2
 
3
3
  from .CLI import konsol, cikis_yap, hata_yakala, pypi_kontrol_guncelle
4
- from .Managers import PluginManager, ExtractorManager, UIManager, MediaManager
5
- from .Core import PluginBase, ExtractorBase, SeriesInfo
4
+ from .Core import PluginManager, ExtractorManager, UIManager, MediaManager, PluginBase, ExtractorBase, SeriesInfo
6
5
  from asyncio import run
7
6
  from contextlib import suppress
8
7
 
9
8
  class KekikStream:
10
9
  def __init__(self):
10
+ # Yönetici sınıflarını başlat
11
11
  self.eklentiler_yonetici = PluginManager()
12
12
  self.cikaricilar_yonetici = ExtractorManager()
13
13
  self.arayuz_yonetici = UIManager()
@@ -15,17 +15,22 @@ class KekikStream:
15
15
  self.suanki_eklenti: PluginBase = None
16
16
 
17
17
  async def baslat(self):
18
+ # Konsolu temizle ve başlık göster
18
19
  self.arayuz_yonetici.clear_console()
19
20
  konsol.rule("[bold cyan]KekikStream Başlatılıyor[/bold cyan]")
21
+
22
+ # Eklenti kontrolü
20
23
  if not self.eklentiler_yonetici.get_plugin_names():
21
24
  return konsol.print("[bold red]Hiçbir eklenti bulunamadı![/bold red]")
22
25
 
23
26
  try:
24
27
  await self.eklenti_secimi()
25
28
  finally:
29
+ # Program kapanırken tüm eklentileri kapat
26
30
  await self.eklentiler_yonetici.close_plugins()
27
31
 
28
32
  async def sonuc_bulunamadi(self):
33
+ # Sonuç bulunamadığında kullanıcıya seçenekler sun
29
34
  secim = await self.arayuz_yonetici.select_from_list(
30
35
  message = "Ne yapmak istersiniz?",
31
36
  choices = ["Tüm Eklentilerde Ara", "Ana Menü", "Çıkış"]
@@ -40,6 +45,7 @@ class KekikStream:
40
45
  cikis_yap(False)
41
46
 
42
47
  async def eklenti_secimi(self):
48
+ # Fuzzy ile eklenti seçimi yap
43
49
  eklenti_adi = await self.arayuz_yonetici.select_from_fuzzy(
44
50
  message = "Arama yapılacak eklentiyi seçin:",
45
51
  choices = ["Tüm Eklentilerde Ara", *self.eklentiler_yonetici.get_plugin_names()]
@@ -52,9 +58,11 @@ class KekikStream:
52
58
  await self.eklenti_ile_arama()
53
59
 
54
60
  async def eklenti_ile_arama(self):
61
+ # Seçilen eklentide arama yap
55
62
  self.arayuz_yonetici.clear_console()
56
63
  konsol.rule(f"[bold cyan]{self.suanki_eklenti.name} Eklentisinde Arama Yapın[/bold cyan]")
57
64
 
65
+ # Kullanıcıdan sorgu al ve ara
58
66
  sorgu = await self.arayuz_yonetici.prompt_text("Arama sorgusu girin:")
59
67
  sonuclar = await self.suanki_eklenti.search(sorgu)
60
68
 
@@ -66,12 +74,14 @@ class KekikStream:
66
74
  await self.sonuc_detaylari_goster({"plugin": self.suanki_eklenti.name, "url": secilen_sonuc})
67
75
 
68
76
  async def eklenti_sonuc_secimi(self, sonuclar):
77
+ # Arama sonuçlarından birini seç
69
78
  return await self.arayuz_yonetici.select_from_fuzzy(
70
79
  message = "İçerik sonuçlarından birini seçin:",
71
80
  choices = [{"name": sonuc.title, "value": sonuc.url} for sonuc in sonuclar]
72
81
  )
73
82
 
74
83
  async def tum_eklentilerde_arama(self):
84
+ # Tüm eklentilerde arama yap
75
85
  self.arayuz_yonetici.clear_console()
76
86
  konsol.rule("[bold cyan]Tüm Eklentilerde Arama Yapın[/bold cyan]")
77
87
 
@@ -89,7 +99,9 @@ class KekikStream:
89
99
  async def tum_eklentilerde_arama_sorgula(self, sorgu: str) -> list:
90
100
  tum_sonuclar = []
91
101
 
102
+ # Her eklentide arama yap
92
103
  for eklenti_adi, eklenti in self.eklentiler_yonetici.plugins.items():
104
+ # Eklenti türü kontrolü
93
105
  if not isinstance(eklenti, PluginBase):
94
106
  konsol.print(f"[yellow][!] {eklenti_adi} geçerli bir PluginBase değil, atlanıyor...[/yellow]")
95
107
  continue
@@ -98,6 +110,7 @@ class KekikStream:
98
110
  try:
99
111
  sonuclar = await eklenti.search(sorgu)
100
112
  if sonuclar:
113
+ # Sonuçları listeye ekle
101
114
  tum_sonuclar.extend(
102
115
  [{"plugin": eklenti_adi, "title": sonuc.title, "url": sonuc.url, "poster": sonuc.poster} for sonuc in sonuclar]
103
116
  )
@@ -112,6 +125,7 @@ class KekikStream:
112
125
  return tum_sonuclar
113
126
 
114
127
  async def tum_sonuc_secimi(self, sonuclar):
128
+ # Tüm sonuçlardan birini seç
115
129
  secenekler = [
116
130
  {"name": f"[{sonuc['plugin']}]".ljust(21) + f" » {sonuc['title']}", "value": sonuc}
117
131
  for sonuc in sonuclar
@@ -124,6 +138,7 @@ class KekikStream:
124
138
 
125
139
  async def sonuc_detaylari_goster(self, secilen_sonuc):
126
140
  try:
141
+ # Seçilen sonucun detaylarını al
127
142
  if isinstance(secilen_sonuc, dict) and "plugin" in secilen_sonuc:
128
143
  eklenti_adi = secilen_sonuc["plugin"]
129
144
  url = secilen_sonuc["url"]
@@ -132,6 +147,7 @@ class KekikStream:
132
147
  else:
133
148
  url = secilen_sonuc
134
149
 
150
+ # Medya bilgilerini yükle (3 deneme hakkı)
135
151
  medya_bilgi = None
136
152
  for _ in range(3):
137
153
  with suppress(Exception):
@@ -145,9 +161,11 @@ class KekikStream:
145
161
  konsol.log(secilen_sonuc)
146
162
  return hata_yakala(hata)
147
163
 
164
+ # Medya başlığını ayarla ve bilgileri göster
148
165
  self.medya_yonetici.set_title(f"{self.suanki_eklenti.name} | {medya_bilgi.title}")
149
166
  self.arayuz_yonetici.display_media_info(f"{self.suanki_eklenti.name} | {medya_bilgi.title}", medya_bilgi)
150
167
 
168
+ # Dizi ise bölüm seçimi yap
151
169
  if isinstance(medya_bilgi, SeriesInfo):
152
170
  secilen_bolum = await self.arayuz_yonetici.select_from_fuzzy(
153
171
  message = "İzlemek istediğiniz bölümü seçin:",
@@ -168,15 +186,19 @@ class KekikStream:
168
186
  konsol.print("[bold red]Hiçbir bağlantı bulunamadı![/bold red]")
169
187
  return await self.sonuc_bulunamadi()
170
188
 
189
+ # Bağlantıları çıkarıcılarla eşleştir
171
190
  haritalama = self.cikaricilar_yonetici.map_links_to_extractors(baglantilar)
172
191
  play_fonksiyonu_var = hasattr(self.suanki_eklenti, "play") and callable(getattr(self.suanki_eklenti, "play", None))
173
192
  # ! DEBUG
174
193
  # konsol.print(baglantilar)
194
+
195
+ # Uygun çıkarıcı kontrolü
175
196
  if not haritalama and not play_fonksiyonu_var:
176
197
  konsol.print("[bold red]Hiçbir Extractor bulunamadı![/bold red]")
177
198
  konsol.print(baglantilar)
178
199
  return await self.sonuc_bulunamadi()
179
200
 
201
+ # Doğrudan oynatma seçeneği
180
202
  if not haritalama:
181
203
  secilen_link = await self.arayuz_yonetici.select_from_list(
182
204
  message = "Doğrudan oynatmak için bir bağlantı seçin:",
@@ -186,6 +208,7 @@ class KekikStream:
186
208
  await self.medya_oynat(secilen_link)
187
209
  return
188
210
 
211
+ # Kullanıcı seçenekleri
189
212
  secim = await self.arayuz_yonetici.select_from_list(
190
213
  message = "Ne yapmak istersiniz?",
191
214
  choices = ["İzle", "Tüm Eklentilerde Ara", "Ana Menü"]
@@ -207,6 +230,7 @@ class KekikStream:
207
230
  await self.baslat()
208
231
 
209
232
  async def medya_oynat(self, secilen_link):
233
+ # Eklentinin kendi oynatıcısı varsa onu kullan
210
234
  if hasattr(self.suanki_eklenti, "play") and callable(self.suanki_eklenti.play):
211
235
  konsol.log(f"[yellow][»] Oynatılıyor : {secilen_link}")
212
236
  return await self.suanki_eklenti.play(
@@ -216,16 +240,19 @@ class KekikStream:
216
240
  subtitles = self.suanki_eklenti._data[secilen_link]["subtitles"]
217
241
  )
218
242
 
243
+ # Uygun çıkarıcıyı bul
219
244
  cikarici: ExtractorBase = self.cikaricilar_yonetici.find_extractor(secilen_link)
220
245
  if not cikarici:
221
246
  return konsol.print("[bold red]Uygun Extractor bulunamadı.[/bold red]")
222
247
 
223
248
  try:
249
+ # Medya bilgilerini çıkar
224
250
  extract_data = await cikarici.extract(secilen_link, referer=self.suanki_eklenti.main_url)
225
251
  except Exception as hata:
226
252
  konsol.print(f"[bold red]{cikarici.name} » hata oluştu: {hata}[/bold red]")
227
253
  return await self.sonuc_bulunamadi()
228
254
 
255
+ # Birden fazla bağlantı varsa seçim yap
229
256
  if isinstance(extract_data, list):
230
257
  secilen_data = await self.arayuz_yonetici.select_from_list(
231
258
  message = "Birden fazla bağlantı bulundu, lütfen birini seçin:",
@@ -234,9 +261,11 @@ class KekikStream:
234
261
  else:
235
262
  secilen_data = extract_data
236
263
 
264
+ # Cookie varsa ayarla
237
265
  if secilen_data.headers.get("Cookie"):
238
266
  self.medya_yonetici.set_headers({"Cookie": secilen_data.headers.get("Cookie")})
239
267
 
268
+ # Başlık ve referrer ayarla
240
269
  self.medya_yonetici.set_title(f"{self.medya_yonetici.get_title()} | {secilen_data.name}")
241
270
  self.medya_yonetici.set_headers({"Referer": secilen_data.referer})
242
271
  konsol.log(f"[yellow][»] Oynatılıyor : {secilen_data.url}")
@@ -244,8 +273,10 @@ class KekikStream:
244
273
 
245
274
  def basla():
246
275
  try:
276
+ # PyPI güncellemelerini kontrol et
247
277
  pypi_kontrol_guncelle("KekikStream")
248
278
 
279
+ # Uygulamayı başlat
249
280
  app = KekikStream()
250
281
  run(app.baslat())
251
282
  cikis_yap(False)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: KekikStream
3
- Version: 0.8.0
3
+ Version: 0.8.2
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
@@ -1,16 +1,20 @@
1
- KekikStream/__init__.py,sha256=RuvKGAfgZ8HkMQ8loKSwC4V2yxL1GoW3zHGEeczP-RM,10893
1
+ KekikStream/__init__.py,sha256=2ocXWKQcb05mHfRPHKxHt7nHufvPOzKESmTrIVfy70k,12174
2
2
  KekikStream/__main__.py,sha256=B81dQoeGEb-T5Sycs3eNAmW7unvx0Mef0syCjs4nPds,137
3
3
  KekikStream/requirements.txt,sha256=QWCXrrmKodIm7mGtIz9cWr9sks-lmL_TilKMrruWJn0,77
4
4
  KekikStream/CLI/__init__.py,sha256=U6oLq_O7u5y2eHhBnmfhZNns_EqHHJXJmzl8jvZFUNY,230
5
5
  KekikStream/CLI/pypi_kontrol.py,sha256=MchatOwCWCpFBtgt09yag9Rjal9XFyh2W_oVs2p7SNg,1518
6
- KekikStream/Core/ExtractorBase.py,sha256=wmGl-Xiem4s5M7baVOxYLba7UdygCDAXggo6Up8pFJE,1409
7
- KekikStream/Core/ExtractorLoader.py,sha256=rrll3F2CyVmx3foa57PG0FocQMrFuMpdlG0Uf0-2Fz4,3915
8
- KekikStream/Core/ExtractorModels.py,sha256=huIcPQ5VIRfMx0LcL5SS1u4dldZbHjzHKEdSEtOPlc0,456
9
- KekikStream/Core/MediaHandler.py,sha256=DFw2Npd9fantyERjnUzr3jU7F283tVC7qA3j-zznzAA,5939
10
- KekikStream/Core/PluginBase.py,sha256=ZQx6adxOKuX50TPN5pxE8oG9FD-ZjPXSHpSiW086QPQ,2479
11
- KekikStream/Core/PluginLoader.py,sha256=5HQF8Em1TjvqMBPLKB7M_i2y6zPH6JZao-uekeacoSs,2574
12
- KekikStream/Core/PluginModels.py,sha256=q8tjkt_-uiJ7uNxOThYR0FgTQLZglVAOAaM0Kske-28,2063
13
- KekikStream/Core/__init__.py,sha256=HZpXs3MKy4joO0sDpIGcZ2DrUKwK49IKG-GQgKbO2jk,416
6
+ KekikStream/Core/__init__.py,sha256=2N0VFP4QsyDWn4pV77JX_5_XachD5qKzhuDor3klj58,657
7
+ KekikStream/Core/Extractor/ExtractorBase.py,sha256=ZyasO5m7iAsnh-mwhtlp-VXkZ4pIuWuHvCIskBX7FUg,1726
8
+ KekikStream/Core/Extractor/ExtractorLoader.py,sha256=ecrfz9mYizlENCjbyfjdfnOrQorxQTF4ZFGhPpU6JHk,4193
9
+ KekikStream/Core/Extractor/ExtractorManager.py,sha256=4L1H3jiTnf0kTq4W6uS7n95bBYHlKJ8_hh0og8z4erQ,1244
10
+ KekikStream/Core/Extractor/ExtractorModels.py,sha256=huIcPQ5VIRfMx0LcL5SS1u4dldZbHjzHKEdSEtOPlc0,456
11
+ KekikStream/Core/Media/MediaHandler.py,sha256=-yVOnI5pNKWgvrRgJ8DVKjvTWuHTwUC7JSKlKa06lSw,6179
12
+ KekikStream/Core/Media/MediaManager.py,sha256=9ItiUguOkk3wg3YY5uf3mrjfwLPCvggnP8QviX0uiuE,526
13
+ KekikStream/Core/Plugin/PluginBase.py,sha256=KuR89bkrChPAct4-PMjxbK4i6busXMMFeZjv-x4F1CQ,2521
14
+ KekikStream/Core/Plugin/PluginLoader.py,sha256=2UM3gNcEgd7k-FxG-JB5nTIS0K_clzvFtzGjMA_Sx7Q,3379
15
+ KekikStream/Core/Plugin/PluginManager.py,sha256=CZVg1eegi8vfMfccx0DRV0Box8kXz-aoULTQLgbPbvM,893
16
+ KekikStream/Core/Plugin/PluginModels.py,sha256=q8tjkt_-uiJ7uNxOThYR0FgTQLZglVAOAaM0Kske-28,2063
17
+ KekikStream/Core/UI/UIManager.py,sha256=T4V_kdTTWa-UDamgLSKa__dWJuzcvRK9NuwBlzU9Bzc,1693
14
18
  KekikStream/Extractors/CloseLoad.py,sha256=YmDB3YvuDaCUbQ0T_tmhnkEsC5mSdEN6GNoAR662fl8,990
15
19
  KekikStream/Extractors/ContentX.py,sha256=XPoAuA95LOTgCUGyioXxOFWR0nNKWWOHLkYMlzguIIE,2980
16
20
  KekikStream/Extractors/FourCX.py,sha256=4FrMj1IZBBpN_g1P6S3A-8eUu7QFwlt4fJXzJ7vfe0Q,221
@@ -36,24 +40,19 @@ KekikStream/Extractors/TurboImgz.py,sha256=VXx9vZZRTdQiVNER0LcXm2nsv2OaXnxuPpslG
36
40
  KekikStream/Extractors/VidMoly.py,sha256=BKJgk60GomFYiLFsRQSR2sOYP105Aix5y5XLazBNWmw,3368
37
41
  KekikStream/Extractors/VidMoxy.py,sha256=_K6BA7Uo59DA3ty_tsayCUZjXmRoDBTghekVNXiuZ7g,1800
38
42
  KekikStream/Extractors/VideoSeyred.py,sha256=otyGi1zdY_JPrXJjoZjesCQDiOkxFdaWiXQ9mOmrygA,1780
39
- KekikStream/Managers/ExtractorManager.py,sha256=9rGlUsnedJ7fwIeObN5Vsm8H5VLal0ODO7F93dDRx8w,976
40
- KekikStream/Managers/MediaManager.py,sha256=SPO85LchT7bJKSecmXd1FzCjg0rUT8s3B1wulPa4SMw,519
41
- KekikStream/Managers/PluginManager.py,sha256=YDBLHB_Fh79A3Pei0ny2KLVY4VSihdNiKBh_w5tBl-0,637
42
- KekikStream/Managers/UIManager.py,sha256=e89u_QgmxL85zGAYyYsQp6b3E5y7fHGteLt2OYHHbD8,1693
43
- KekikStream/Managers/__init__.py,sha256=3085I_9Sa2L_Vq6Z-QvYUYn1BapkN4sQqBo8ITZoD_4,251
44
43
  KekikStream/Plugins/DiziBox.py,sha256=i_73VNXk2eM7xTg-6a0Xk2Yts2c9grWbRVVHhxFgoic,5935
45
44
  KekikStream/Plugins/DiziYou.py,sha256=kpRY3U6lqaZKgn9ED2TprwU7qfLxuC2ZZmrRemegryo,5382
46
45
  KekikStream/Plugins/Dizilla.py,sha256=evWYvETw1c4RY0GB5P20cB_I_U7ZxzzvnG7RLNGJRPs,4258
47
46
  KekikStream/Plugins/FilmMakinesi.py,sha256=rz8TQeL41PJbeEmksgPHIhp6J-4vbSCBTeEH0ukExz4,2822
48
47
  KekikStream/Plugins/FullHDFilmizlesene.py,sha256=Fa0gRP_NoMfPC8HIKRxERjQVOv8Fyb-ayMJ2EooZ7BE,3080
49
48
  KekikStream/Plugins/JetFilmizle.py,sha256=FXkMSQtjYoxwIonjRENFa91rC42L_8SYRhjhuSgsu60,3919
50
- KekikStream/Plugins/RecTV.py,sha256=9Cpelwtbriea0pmwEtU0HX_-_uwrQKu8jIWNfRu-cY0,4994
49
+ KekikStream/Plugins/RecTV.py,sha256=Pt2IQ2jLsQp7Mo85uM_ml3nxOR0uirX7vXOnE10CPm0,4886
51
50
  KekikStream/Plugins/SezonlukDizi.py,sha256=5BZVzQ2eQtymHxO0bzjA2ho4FFNahPFQly4hoHuH8lo,4441
52
- KekikStream/Plugins/SineWix.py,sha256=P_ujixGubpsJzAdbRUzVy5ziRGYfSEDc90RMXie6VyE,4866
51
+ KekikStream/Plugins/SineWix.py,sha256=VvFeAS2-Y-KJ1Od16yZjUJLiESwsBBGb2GNG3BLLupU,4806
53
52
  KekikStream/Plugins/UgurFilm.py,sha256=yYXee5uxwNnPqFJZ6s6cRkmUyqS3Vv8x-iesPalc4j4,2930
54
- KekikStream-0.8.0.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
55
- KekikStream-0.8.0.dist-info/METADATA,sha256=Oa4RWJ8K0C5VYtI4LcEVPxCePmSuLJQm8QrFiDEcOAE,4226
56
- KekikStream-0.8.0.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
57
- KekikStream-0.8.0.dist-info/entry_points.txt,sha256=dFwdiTx8djyehI0Gsz-rZwjAfZzUzoBSrmzRu9ubjJc,50
58
- KekikStream-0.8.0.dist-info/top_level.txt,sha256=DNmGJDXl27Drdfobrak8KYLmocW_uznVYFJOzcjUgmY,12
59
- KekikStream-0.8.0.dist-info/RECORD,,
53
+ KekikStream-0.8.2.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
54
+ KekikStream-0.8.2.dist-info/METADATA,sha256=qGDsp7unyH1NgrlDfx5g7dpx59o_e03zkKbSBAQTGs0,4226
55
+ KekikStream-0.8.2.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
56
+ KekikStream-0.8.2.dist-info/entry_points.txt,sha256=dFwdiTx8djyehI0Gsz-rZwjAfZzUzoBSrmzRu9ubjJc,50
57
+ KekikStream-0.8.2.dist-info/top_level.txt,sha256=DNmGJDXl27Drdfobrak8KYLmocW_uznVYFJOzcjUgmY,12
58
+ KekikStream-0.8.2.dist-info/RECORD,,
@@ -1,6 +0,0 @@
1
- # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
-
3
- from .PluginManager import PluginManager
4
- from .ExtractorManager import ExtractorManager
5
- from .UIManager import UIManager
6
- from .MediaManager import MediaManager