KekikStream 1.8.6__tar.gz → 1.9.3__tar.gz
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- kekikstream-1.9.3/KekikStream/Core/Extractor/ExtractorManager.py +52 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream/Core/Media/MediaHandler.py +30 -8
- kekikstream-1.9.3/KekikStream/Extractors/YTDLP.py +172 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream.egg-info/PKG-INFO +105 -104
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream.egg-info/SOURCES.txt +1 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/PKG-INFO +105 -104
- {kekikstream-1.8.6 → kekikstream-1.9.3}/README.md +104 -103
- {kekikstream-1.8.6 → kekikstream-1.9.3}/setup.py +1 -1
- kekikstream-1.8.6/KekikStream/Core/Extractor/ExtractorManager.py +0 -31
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream/CLI/__init__.py +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream/CLI/pypi_kontrol.py +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream/Core/Extractor/ExtractorBase.py +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream/Core/Extractor/ExtractorLoader.py +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream/Core/Extractor/ExtractorModels.py +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream/Core/Media/MediaManager.py +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream/Core/Plugin/PluginBase.py +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream/Core/Plugin/PluginLoader.py +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream/Core/Plugin/PluginManager.py +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream/Core/Plugin/PluginModels.py +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream/Core/UI/UIManager.py +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream/Core/__init__.py +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream/Extractors/CloseLoad.py +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream/Extractors/ContentX.py +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream/Extractors/DzenRu.py +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream/Extractors/ExPlay.py +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream/Extractors/FirePlayer.py +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream/Extractors/FourCX.py +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream/Extractors/FourPichive.py +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream/Extractors/FourPlayRu.py +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream/Extractors/HDPlayerSystem.py +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream/Extractors/HDStreamAble.py +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream/Extractors/Hotlinger.py +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream/Extractors/JetTv.py +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream/Extractors/MailRu.py +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream/Extractors/MixPlayHD.py +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream/Extractors/MixTiger.py +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream/Extractors/MolyStream.py +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream/Extractors/Odnoklassniki.py +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream/Extractors/OkRuHTTP.py +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream/Extractors/OkRuSSL.py +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream/Extractors/PeaceMakerst.py +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream/Extractors/Pichive.py +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream/Extractors/PixelDrain.py +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream/Extractors/PlayRu.py +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream/Extractors/PlayerFilmIzle.py +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream/Extractors/RapidVid.py +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream/Extractors/SetPlay.py +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream/Extractors/SetPrime.py +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream/Extractors/SibNet.py +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream/Extractors/Sobreatsesuyp.py +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream/Extractors/TRsTX.py +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream/Extractors/TauVideo.py +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream/Extractors/TurboImgz.py +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream/Extractors/TurkeyPlayer.py +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream/Extractors/VidHide.py +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream/Extractors/VidMoly.py +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream/Extractors/VidMolyMe.py +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream/Extractors/VidMoxy.py +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream/Extractors/VidPapi.py +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream/Extractors/VideoSeyred.py +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream/Extractors/YildizKisaFilm.py +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream/Plugins/DiziBox.py +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream/Plugins/DiziPal.py +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream/Plugins/DiziYou.py +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream/Plugins/Dizilla.py +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream/Plugins/FilmBip.py +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream/Plugins/FilmMakinesi.py +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream/Plugins/FilmModu.py +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream/Plugins/FullHDFilm.py +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream/Plugins/FullHDFilmizlesene.py +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream/Plugins/HDFilmCehennemi.py +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream/Plugins/JetFilmizle.py +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream/Plugins/KultFilmler.py +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream/Plugins/RecTV.py +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream/Plugins/RoketDizi.py +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream/Plugins/SelcukFlix.py +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream/Plugins/SezonlukDizi.py +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream/Plugins/SineWix.py +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream/Plugins/Sinefy.py +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream/Plugins/SinemaCX.py +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream/Plugins/Sinezy.py +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream/Plugins/SuperFilmGeldi.py +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream/Plugins/UgurFilm.py +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream/__init__.py +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream/__main__.py +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream/requirements.txt +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream.egg-info/dependency_links.txt +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream.egg-info/entry_points.txt +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream.egg-info/requires.txt +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/KekikStream.egg-info/top_level.txt +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/LICENSE +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/MANIFEST.in +0 -0
- {kekikstream-1.8.6 → kekikstream-1.9.3}/setup.cfg +0 -0
|
@@ -0,0 +1,52 @@
|
|
|
1
|
+
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
|
+
|
|
3
|
+
from .ExtractorLoader import ExtractorLoader
|
|
4
|
+
from .ExtractorBase import ExtractorBase
|
|
5
|
+
|
|
6
|
+
class ExtractorManager:
|
|
7
|
+
def __init__(self, extractor_dir="Extractors"):
|
|
8
|
+
# Çıkarıcı yükleyiciyi başlat ve tüm çıkarıcıları yükle
|
|
9
|
+
self.extractor_loader = ExtractorLoader(extractor_dir)
|
|
10
|
+
self.extractors = self.extractor_loader.load_all()
|
|
11
|
+
|
|
12
|
+
# Extractor instance'larını cache'le
|
|
13
|
+
self._extractor_instances = []
|
|
14
|
+
self._ytdlp_extractor = None
|
|
15
|
+
|
|
16
|
+
for extractor_cls in self.extractors:
|
|
17
|
+
instance = extractor_cls()
|
|
18
|
+
|
|
19
|
+
# YTDLP'yi ayrı tut
|
|
20
|
+
if instance.name == "yt-dlp":
|
|
21
|
+
self._ytdlp_extractor = instance
|
|
22
|
+
else:
|
|
23
|
+
self._extractor_instances.append(instance)
|
|
24
|
+
|
|
25
|
+
# YTDLP'yi EN BAŞA ekle
|
|
26
|
+
if self._ytdlp_extractor:
|
|
27
|
+
self._extractor_instances.insert(0, self._ytdlp_extractor)
|
|
28
|
+
|
|
29
|
+
def find_extractor(self, link) -> ExtractorBase:
|
|
30
|
+
"""
|
|
31
|
+
Verilen bağlantıyı işleyebilecek çıkarıcıyı bul
|
|
32
|
+
"""
|
|
33
|
+
# Cached instance'ları kullan
|
|
34
|
+
for extractor in self._extractor_instances:
|
|
35
|
+
if extractor.can_handle_url(link):
|
|
36
|
+
return extractor
|
|
37
|
+
|
|
38
|
+
return None
|
|
39
|
+
|
|
40
|
+
def map_links_to_extractors(self, links) -> dict:
|
|
41
|
+
"""
|
|
42
|
+
Bağlantıları uygun çıkarıcılarla eşleştir
|
|
43
|
+
"""
|
|
44
|
+
mapping = {}
|
|
45
|
+
for link in links:
|
|
46
|
+
# Cached instance'ları kullan
|
|
47
|
+
for extractor in self._extractor_instances:
|
|
48
|
+
if extractor.can_handle_url(link):
|
|
49
|
+
mapping[link] = f"{extractor.name:<30} » {link.replace(extractor.main_url, '')}"
|
|
50
|
+
break # İlk eşleşmede dur
|
|
51
|
+
|
|
52
|
+
return mapping
|
|
@@ -18,19 +18,34 @@ class MediaHandler:
|
|
|
18
18
|
if extract_data.referer:
|
|
19
19
|
self.headers["referer"] = extract_data.referer
|
|
20
20
|
|
|
21
|
-
#
|
|
21
|
+
# Özel Durumlar (RecTV vs. Googleusercontent)
|
|
22
22
|
if user_agent in ["googleusercontent", "Mozilla/5.0 (X11; Linux x86_64; rv:101.0) Gecko/20100101 Firefox/101.0"]:
|
|
23
23
|
return self.play_with_ytdlp(extract_data)
|
|
24
24
|
|
|
25
|
-
# İşletim sistemine göre oynatıcı seç
|
|
25
|
+
# İşletim sistemine göre oynatıcı seç (Android durumu)
|
|
26
26
|
if subprocess.check_output(['uname', '-o']).strip() == b'Android':
|
|
27
27
|
return self.play_with_android_mxplayer(extract_data)
|
|
28
28
|
|
|
29
|
-
#
|
|
30
|
-
|
|
31
|
-
|
|
29
|
+
# Oynatıcı öncelik sırası (fallback zincirleme)
|
|
30
|
+
players = [
|
|
31
|
+
("MPV", self.play_with_mpv),
|
|
32
|
+
("VLC", self.play_with_vlc),
|
|
33
|
+
("yt-dlp", self.play_with_ytdlp)
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
# Fallback zincirleme
|
|
37
|
+
for player_name, player_func in players:
|
|
38
|
+
try:
|
|
39
|
+
result = player_func(extract_data)
|
|
40
|
+
if result or result is None: # None = MPV (exception yok)
|
|
41
|
+
konsol.log(f"[green][✓] {player_name} ile başarılı[/green]")
|
|
42
|
+
return True
|
|
43
|
+
except Exception as e:
|
|
44
|
+
konsol.log(f"[yellow][⚠] {player_name} hatası: {e}[/yellow]")
|
|
45
|
+
continue
|
|
32
46
|
|
|
33
|
-
|
|
47
|
+
konsol.print("[red][✗] Hiçbir oynatıcı çalışmadı![/red]")
|
|
48
|
+
return False
|
|
34
49
|
|
|
35
50
|
def play_with_vlc(self, extract_data: ExtractResult):
|
|
36
51
|
konsol.log(f"[yellow][»] VLC ile Oynatılıyor : {extract_data.url}")
|
|
@@ -88,12 +103,15 @@ class MediaHandler:
|
|
|
88
103
|
with open(os.devnull, "w") as devnull:
|
|
89
104
|
subprocess.run(mpv_command, stdout=devnull, stderr=devnull, check=True)
|
|
90
105
|
|
|
106
|
+
return True
|
|
91
107
|
except subprocess.CalledProcessError as hata:
|
|
92
108
|
konsol.print(f"[red]mpv oynatma hatası: {hata}[/red]")
|
|
93
109
|
konsol.print({"title": self.title, "url": extract_data.url, "headers": self.headers})
|
|
110
|
+
return False
|
|
94
111
|
except FileNotFoundError:
|
|
95
112
|
konsol.print("[red]mpv bulunamadı! mpv kurulu olduğundan emin olun.[/red]")
|
|
96
113
|
konsol.print({"title": self.title, "url": extract_data.url, "headers": self.headers})
|
|
114
|
+
return False
|
|
97
115
|
|
|
98
116
|
def play_with_ytdlp(self, extract_data: ExtractResult):
|
|
99
117
|
konsol.log(f"[yellow][»] yt-dlp ile Oynatılıyor : {extract_data.url}")
|
|
@@ -121,12 +139,15 @@ class MediaHandler:
|
|
|
121
139
|
with subprocess.Popen(ytdlp_command, stdout=subprocess.PIPE) as ytdlp_proc:
|
|
122
140
|
subprocess.run(mpv_command, stdin=ytdlp_proc.stdout, check=True)
|
|
123
141
|
|
|
142
|
+
return True
|
|
124
143
|
except subprocess.CalledProcessError as hata:
|
|
125
144
|
konsol.print(f"[red]Oynatma hatası: {hata}[/red]")
|
|
126
145
|
konsol.print({"title": self.title, "url": extract_data.url, "headers": self.headers})
|
|
146
|
+
return False
|
|
127
147
|
except FileNotFoundError:
|
|
128
148
|
konsol.print("[red]yt-dlp veya mpv bulunamadı! Kurulumlarından emin olun.[/red]")
|
|
129
149
|
konsol.print({"title": self.title, "url": extract_data.url, "headers": self.headers})
|
|
150
|
+
return False
|
|
130
151
|
|
|
131
152
|
def play_with_android_mxplayer(self, extract_data: ExtractResult):
|
|
132
153
|
konsol.log(f"[yellow][»] MxPlayer ile Oynatılıyor : {extract_data.url}")
|
|
@@ -151,11 +172,12 @@ class MediaHandler:
|
|
|
151
172
|
with open(os.devnull, "w") as devnull:
|
|
152
173
|
subprocess.run(android_command, stdout=devnull, stderr=devnull, check=True)
|
|
153
174
|
|
|
154
|
-
return
|
|
155
|
-
|
|
175
|
+
return True
|
|
156
176
|
except subprocess.CalledProcessError as hata:
|
|
157
177
|
konsol.print(f"[red]{paket} oynatma hatası: {hata}[/red]")
|
|
158
178
|
konsol.print({"title": self.title, "url": extract_data.url, "headers": self.headers})
|
|
179
|
+
return False
|
|
159
180
|
except FileNotFoundError:
|
|
160
181
|
konsol.print(f"Paket: {paket}, Hata: MX Player kurulu değil")
|
|
161
182
|
konsol.print({"title": self.title, "url": extract_data.url, "headers": self.headers})
|
|
183
|
+
return False
|
|
@@ -0,0 +1,172 @@
|
|
|
1
|
+
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
|
+
|
|
3
|
+
from KekikStream.Core import ExtractorBase, ExtractResult, Subtitle
|
|
4
|
+
from urllib.parse import urlparse
|
|
5
|
+
from yt_dlp.extractor import gen_extractors
|
|
6
|
+
import yt_dlp, re, sys, os
|
|
7
|
+
|
|
8
|
+
class YTDLP(ExtractorBase):
|
|
9
|
+
name = "yt-dlp"
|
|
10
|
+
main_url = "" # Universal - tüm siteleri destekler
|
|
11
|
+
|
|
12
|
+
_FAST_DOMAIN_RE = None # compiled mega-regex (host üstünden)
|
|
13
|
+
|
|
14
|
+
@classmethod
|
|
15
|
+
def _init_fast_domain_regex(cls):
|
|
16
|
+
if cls._FAST_DOMAIN_RE is not None:
|
|
17
|
+
return
|
|
18
|
+
|
|
19
|
+
domains = set()
|
|
20
|
+
|
|
21
|
+
# yt-dlp extractor'larının _VALID_URL regex'lerinden domain yakala
|
|
22
|
+
# Regex metinlerinde domainler genelde "\." şeklinde geçer.
|
|
23
|
+
domain_pat = re.compile(r"(?:[a-z0-9-]+\\\.)+[a-z]{2,}", re.IGNORECASE)
|
|
24
|
+
|
|
25
|
+
for ie in gen_extractors():
|
|
26
|
+
# Generic'i fast-path'e dahil etmiyoruz
|
|
27
|
+
if getattr(ie, "IE_NAME", "").lower() == "generic":
|
|
28
|
+
continue
|
|
29
|
+
|
|
30
|
+
valid = getattr(ie, "_VALID_URL", None)
|
|
31
|
+
if not valid or not isinstance(valid, str):
|
|
32
|
+
continue
|
|
33
|
+
|
|
34
|
+
for m in domain_pat.findall(valid):
|
|
35
|
+
d = m.replace(r"\.", ".").lower()
|
|
36
|
+
|
|
37
|
+
# Çok agresif/şüpheli şeyleri elemek istersen burada filtre koyabilirsin
|
|
38
|
+
# (genelde gerek kalmıyor)
|
|
39
|
+
domains.add(d)
|
|
40
|
+
|
|
41
|
+
# Hiç domain çıkmazsa (çok uç durum) fallback: boş regex
|
|
42
|
+
if not domains:
|
|
43
|
+
cls._FAST_DOMAIN_RE = re.compile(r"$^") # hiçbir şeye match etmez
|
|
44
|
+
return
|
|
45
|
+
|
|
46
|
+
# Host eşleştirmesi: subdomain destekli (m.youtube.com, player.vimeo.com vs.)
|
|
47
|
+
# (?:^|.*\.) (domain1|domain2|...) $
|
|
48
|
+
joined = "|".join(sorted(re.escape(d) for d in domains))
|
|
49
|
+
pattern = rf"(?:^|.*\.)(?:{joined})$"
|
|
50
|
+
cls._FAST_DOMAIN_RE = re.compile(pattern, re.IGNORECASE)
|
|
51
|
+
|
|
52
|
+
def __init__(self):
|
|
53
|
+
self.__class__._init_fast_domain_regex()
|
|
54
|
+
|
|
55
|
+
def can_handle_url(self, url: str) -> bool:
|
|
56
|
+
"""
|
|
57
|
+
Fast-path: URL host'unu tek mega-regex ile kontrol et (loop yok)
|
|
58
|
+
Slow-path: gerekirse mevcut extract_info tabanlı kontrolün
|
|
59
|
+
"""
|
|
60
|
+
# URL parse + host al
|
|
61
|
+
try:
|
|
62
|
+
parsed = urlparse(url)
|
|
63
|
+
host = (parsed.hostname or "").lower()
|
|
64
|
+
except Exception:
|
|
65
|
+
host = ""
|
|
66
|
+
|
|
67
|
+
# Şemasız URL desteği: "youtube.com/..." gibi
|
|
68
|
+
if not host and "://" not in url:
|
|
69
|
+
try:
|
|
70
|
+
parsed = urlparse("https://" + url)
|
|
71
|
+
host = (parsed.hostname or "").lower()
|
|
72
|
+
except Exception:
|
|
73
|
+
host = ""
|
|
74
|
+
|
|
75
|
+
# Fast-path
|
|
76
|
+
if host and self.__class__._FAST_DOMAIN_RE.search(host):
|
|
77
|
+
return True
|
|
78
|
+
|
|
79
|
+
# SLOW PATH: Diğer siteler için yt-dlp'nin native kontrolü
|
|
80
|
+
try:
|
|
81
|
+
# stderr'ı geçici olarak kapat (hata mesajlarını gizle)
|
|
82
|
+
old_stderr = sys.stderr
|
|
83
|
+
sys.stderr = open(os.devnull, "w")
|
|
84
|
+
|
|
85
|
+
try:
|
|
86
|
+
ydl_opts = {
|
|
87
|
+
"simulate" : True, # Download yok, sadece tespit
|
|
88
|
+
"quiet" : True, # Log kirliliği yok
|
|
89
|
+
"no_warnings" : True, # Uyarı mesajları yok
|
|
90
|
+
"extract_flat" : True, # Minimal işlem
|
|
91
|
+
"no_check_certificates" : True,
|
|
92
|
+
"ignoreerrors" : True # Hataları yoksay
|
|
93
|
+
}
|
|
94
|
+
|
|
95
|
+
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
|
|
96
|
+
# URL'yi işleyebiliyor mu kontrol et
|
|
97
|
+
info = ydl.extract_info(url, download=False, process=False)
|
|
98
|
+
|
|
99
|
+
# Generic extractor ise atla
|
|
100
|
+
if info and info.get("extractor_key") != "Generic":
|
|
101
|
+
return True
|
|
102
|
+
|
|
103
|
+
return False
|
|
104
|
+
finally:
|
|
105
|
+
# stderr'ı geri yükle
|
|
106
|
+
sys.stderr.close()
|
|
107
|
+
sys.stderr = old_stderr
|
|
108
|
+
|
|
109
|
+
except Exception:
|
|
110
|
+
# yt-dlp işleyemezse False döndür
|
|
111
|
+
return False
|
|
112
|
+
|
|
113
|
+
async def extract(self, url: str, referer: str | None = None) -> ExtractResult:
|
|
114
|
+
ydl_opts = {
|
|
115
|
+
"quiet" : True,
|
|
116
|
+
"no_warnings" : True,
|
|
117
|
+
"extract_flat" : False, # Tam bilgi al
|
|
118
|
+
"format" : "best", # En iyi kalite
|
|
119
|
+
"no_check_certificates" : True
|
|
120
|
+
}
|
|
121
|
+
|
|
122
|
+
# Referer varsa header olarak ekle
|
|
123
|
+
if referer:
|
|
124
|
+
ydl_opts["http_headers"] = {"Referer": referer}
|
|
125
|
+
|
|
126
|
+
with yt_dlp.YoutubeDL(ydl_opts) as ydl:
|
|
127
|
+
info = ydl.extract_info(url, download=False)
|
|
128
|
+
|
|
129
|
+
if not info:
|
|
130
|
+
raise ValueError("yt-dlp video bilgisi döndürmedi")
|
|
131
|
+
|
|
132
|
+
# Video URL'sini al
|
|
133
|
+
video_url = info.get("url")
|
|
134
|
+
if not video_url:
|
|
135
|
+
# Bazen formatlar listesinde olabilir
|
|
136
|
+
formats = info.get("formats", [])
|
|
137
|
+
if formats:
|
|
138
|
+
video_url = formats[-1].get("url") # Son format (genellikle en iyi)
|
|
139
|
+
|
|
140
|
+
if not video_url:
|
|
141
|
+
raise ValueError("Video URL bulunamadı")
|
|
142
|
+
|
|
143
|
+
# Altyazıları çıkar
|
|
144
|
+
subtitles = []
|
|
145
|
+
if subtitle_data := info.get("subtitles"):
|
|
146
|
+
for lang, subs in subtitle_data.items():
|
|
147
|
+
for sub in subs:
|
|
148
|
+
if sub_url := sub.get("url"):
|
|
149
|
+
subtitles.append(
|
|
150
|
+
Subtitle(
|
|
151
|
+
name=f"{lang} ({sub.get('ext', 'unknown')})",
|
|
152
|
+
url=sub_url
|
|
153
|
+
)
|
|
154
|
+
)
|
|
155
|
+
|
|
156
|
+
# User-Agent al
|
|
157
|
+
user_agent = None
|
|
158
|
+
http_headers = info.get("http_headers", {})
|
|
159
|
+
if http_headers:
|
|
160
|
+
user_agent = http_headers.get("User-Agent")
|
|
161
|
+
|
|
162
|
+
return ExtractResult(
|
|
163
|
+
name = self.name,
|
|
164
|
+
url = video_url,
|
|
165
|
+
referer = referer or info.get("webpage_url"),
|
|
166
|
+
user_agent = user_agent,
|
|
167
|
+
subtitles = subtitles
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
async def close(self):
|
|
171
|
+
"""yt-dlp için cleanup gerekmez"""
|
|
172
|
+
pass
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: KekikStream
|
|
3
|
-
Version: 1.
|
|
3
|
+
Version: 1.9.3
|
|
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
|
|
@@ -51,8 +51,8 @@ Dynamic: summary
|
|
|
51
51
|
|
|
52
52
|
[](https://github.com/keyiflerolsun/KekikStream/actions/workflows/pypiYukle.yml)
|
|
53
53
|
|
|
54
|
-
**Modüler ve
|
|
55
|
-
Terminal üzerinden
|
|
54
|
+
**Modüler ve genişletilebilir medya streaming kütüphanesi**
|
|
55
|
+
Terminal üzerinden içerik arayın, VLC/MPV ile doğrudan izleyin veya kendi API’nizi kurun. 🚀
|
|
56
56
|
|
|
57
57
|
[](https://github.com/user-attachments/assets/63d31bb0-0b69-40b4-84aa-66623f2a253f)
|
|
58
58
|
|
|
@@ -61,98 +61,46 @@ Terminal üzerinden medya içeriği arayın, VLC/MPV ile doğrudan izleyin! 🚀
|
|
|
61
61
|
|
|
62
62
|
---
|
|
63
63
|
|
|
64
|
-
##
|
|
64
|
+
## 🚦 Ne Sunar?
|
|
65
65
|
|
|
66
|
-
|
|
66
|
+
KekikStream, Türkçe medya kaynaklarını tek CLI arayüzünde toplayarak hızlı arama ve oynatma sunar. Plugin mimarisi sayesinde yeni kaynaklar eklemek ve [KekikStreamAPI](https://github.com/keyiflerolsun/KekikStreamAPI) ile web/API üzerinden yayın yapmak kolaydır.
|
|
67
67
|
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
-
|
|
71
|
-
-
|
|
72
|
-
-
|
|
73
|
-
- 🖥️ **CLI & Kütüphane** - Terminal veya kod içinde kullanın
|
|
74
|
-
- 🌐 **API ve Web UI Desteği** - [KekikStreamAPI](https://github.com/keyiflerolsun/KekikStreamAPI) ile ağ üzerinden erişim
|
|
68
|
+
- 🎥 Çoklu kaynak desteği: Onlarca Türkçe medya sitesi
|
|
69
|
+
- 🔌 Plugin mimarisi: Yeni kaynak eklemek dakikalar sürer
|
|
70
|
+
- 🎬 Çoklu oynatıcı: VLC, MPV, MX Player
|
|
71
|
+
- 🖥️ CLI & kütüphane: Terminalde veya kod içinde kullanın
|
|
72
|
+
- 🌐 API/Web UI: KekikStreamAPI üzerinden uzak erişim
|
|
75
73
|
|
|
76
74
|
---
|
|
77
75
|
|
|
78
76
|
## 🚀 Hızlı Başlangıç
|
|
79
77
|
|
|
80
|
-
|
|
78
|
+
> Gereksinimler: Python 3.11+, sistemde VLC veya MPV kurulu olmalı (Android için MX Player + ADB).
|
|
81
79
|
|
|
82
80
|
```bash
|
|
83
|
-
#
|
|
81
|
+
# Kurulum
|
|
84
82
|
pip install KekikStream
|
|
85
83
|
|
|
86
|
-
#
|
|
84
|
+
# Güncelleme
|
|
87
85
|
pip install -U KekikStream
|
|
88
86
|
```
|
|
89
87
|
|
|
90
|
-
> **Gereksinimler:** Sisteminizde VLC veya MPV yüklü olmalıdır.
|
|
91
|
-
|
|
92
88
|
### Temel Kullanım
|
|
93
89
|
|
|
94
|
-
**
|
|
90
|
+
**CLI:**
|
|
95
91
|
```bash
|
|
96
92
|
KekikStream
|
|
97
93
|
```
|
|
98
94
|
|
|
99
95
|
---
|
|
100
96
|
|
|
101
|
-
## 🏗️ Mimari
|
|
102
|
-
|
|
103
|
-
```mermaid
|
|
104
|
-
graph TB
|
|
105
|
-
CLI[🖥️ CLI Interface]
|
|
106
|
-
Manager[🔌 Plugin Manager]
|
|
107
|
-
|
|
108
|
-
subgraph Plugins
|
|
109
|
-
P1[📺 Dizilla]
|
|
110
|
-
P2[🎬 HDFilmCehennemi]
|
|
111
|
-
P3[🍿 Dizipal]
|
|
112
|
-
PN[... 20+ Plugin]
|
|
113
|
-
end
|
|
114
|
-
|
|
115
|
-
subgraph Extractors
|
|
116
|
-
E1[🔗 Vidmoly]
|
|
117
|
-
E2[🔗 Filemoon]
|
|
118
|
-
E3[🔗 Sibnet]
|
|
119
|
-
EN[... Extractors]
|
|
120
|
-
end
|
|
121
|
-
|
|
122
|
-
subgraph Players
|
|
123
|
-
VLC[🎥 VLC]
|
|
124
|
-
MPV[🎥 MPV]
|
|
125
|
-
MX[🎥 MX Player]
|
|
126
|
-
end
|
|
127
|
-
|
|
128
|
-
CLI --> Manager
|
|
129
|
-
Manager --> P1
|
|
130
|
-
Manager --> P2
|
|
131
|
-
Manager --> P3
|
|
132
|
-
Manager --> PN
|
|
133
|
-
|
|
134
|
-
P1 --> E1
|
|
135
|
-
P2 --> E2
|
|
136
|
-
P3 --> E3
|
|
137
|
-
PN --> EN
|
|
138
|
-
|
|
139
|
-
E1 --> VLC
|
|
140
|
-
E1 --> MPV
|
|
141
|
-
E1 --> MX
|
|
142
|
-
```
|
|
143
|
-
|
|
144
|
-
---
|
|
145
|
-
|
|
146
97
|
## ✨ Özellikler
|
|
147
98
|
|
|
148
99
|
### 🔌 Plugin Sistemi
|
|
149
100
|
|
|
150
|
-
KekikStream modüler bir plugin mimarisi kullanır
|
|
101
|
+
KekikStream modüler bir plugin mimarisi kullanır; her medya kaynağı bağımsız bir plugin'dir.
|
|
151
102
|
|
|
152
|
-
**Mevcut Pluginler:**
|
|
153
|
-
- Dizilla, HDFilmCehennemi, Dizipal, Dizifon
|
|
154
|
-
- RoketDizi, Sinefy, Moviesseed, FullHDFilmizlesene
|
|
155
|
-
- HDBestMovies, SuperFilmGeldi, Sinezy ve daha fazlası...
|
|
103
|
+
**Mevcut Pluginler (örnek):** Dizilla, HDFilmCehennemi, Dizipal, Dizifon, RoketDizi, Sinefy, Moviesseed, FullHDFilmizlesene, HDBestMovies, SuperFilmGeldi, Sinezy ve daha fazlası.
|
|
156
104
|
|
|
157
105
|
**Plugin Geliştirme:**
|
|
158
106
|
```python
|
|
@@ -170,39 +118,97 @@ class MyPlugin(PluginBase):
|
|
|
170
118
|
}
|
|
171
119
|
|
|
172
120
|
async def get_main_page(self, page: int, url: str, category: str) -> list[MainPageResult]:
|
|
173
|
-
# Ana sayfa implementasyonu
|
|
174
121
|
return results
|
|
175
122
|
|
|
176
123
|
async def search(self, query: str) -> list[SearchResult]:
|
|
177
|
-
# Arama implementasyonu
|
|
178
124
|
return results
|
|
179
125
|
|
|
180
126
|
async def load_item(self, url: str) -> MovieInfo | SeriesInfo:
|
|
181
|
-
# İçerik detayları
|
|
182
127
|
return details
|
|
183
128
|
|
|
184
129
|
async def load_links(self, url: str) -> list[dict]:
|
|
185
|
-
# Video bağlantıları
|
|
186
130
|
return links
|
|
187
131
|
```
|
|
188
132
|
|
|
189
133
|
### 🎬 Oynatıcı Desteği
|
|
190
134
|
|
|
191
|
-
| Oynatıcı
|
|
192
|
-
|
|
193
|
-
| **
|
|
194
|
-
| **
|
|
195
|
-
| **MX Player** | Android
|
|
135
|
+
| Oynatıcı | Platform | Özellikler |
|
|
136
|
+
|---------------|----------|---------------------------|
|
|
137
|
+
| **MPV** | Desktop | Custom headers, subtitles |
|
|
138
|
+
| **VLC** | Desktop | Custom headers, subtitles |
|
|
139
|
+
| **MX Player** | Android | ADB üzerinden |
|
|
196
140
|
|
|
197
|
-
>
|
|
141
|
+
> Özel durumlar için (Google Drive vb.) arka planda otomatik olarak yt-dlp devreye girer.
|
|
198
142
|
|
|
199
143
|
### 🔗 Extractor Sistemi
|
|
200
144
|
|
|
201
|
-
|
|
145
|
+
Vidmoly, Filemoon, Sibnet, Sendvid, Voe, Doodstream, Streamtape, Upstream, Dailymotion, JWPlayer ve birçok kaynaktan direkt streaming linki çıkarır.
|
|
202
146
|
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
147
|
+
---
|
|
148
|
+
|
|
149
|
+
## 🏗️ Mimari
|
|
150
|
+
|
|
151
|
+
```mermaid
|
|
152
|
+
graph TB
|
|
153
|
+
CLI[🖥️ CLI Interface]
|
|
154
|
+
Manager[🔌 Plugin Manager]
|
|
155
|
+
|
|
156
|
+
subgraph Plugins
|
|
157
|
+
P1[📺 Dizilla]
|
|
158
|
+
P2[🎬 HDFilmCehennemi]
|
|
159
|
+
P3[🍿 Dizipal]
|
|
160
|
+
PN[... 20+ Plugin]
|
|
161
|
+
end
|
|
162
|
+
|
|
163
|
+
subgraph Extractors
|
|
164
|
+
E1[🔗 Vidmoly]
|
|
165
|
+
E2[🔗 Filemoon]
|
|
166
|
+
E3[🔗 Sibnet]
|
|
167
|
+
EN[... Extractors]
|
|
168
|
+
end
|
|
169
|
+
|
|
170
|
+
subgraph Players
|
|
171
|
+
MPV[🎥 MPV]
|
|
172
|
+
VLC[🎥 VLC]
|
|
173
|
+
MX[🎥 MX Player]
|
|
174
|
+
end
|
|
175
|
+
|
|
176
|
+
CLI --> Manager
|
|
177
|
+
Manager --> P1
|
|
178
|
+
Manager --> P2
|
|
179
|
+
Manager --> P3
|
|
180
|
+
Manager --> PN
|
|
181
|
+
|
|
182
|
+
%% Her plugin otomatik olarak ihtiyaç duyduğu extractor'ı kullanır
|
|
183
|
+
P1 -.-> E1
|
|
184
|
+
P1 -.-> E2
|
|
185
|
+
P1 -.-> E3
|
|
186
|
+
|
|
187
|
+
P2 -.-> E1
|
|
188
|
+
P2 -.-> E2
|
|
189
|
+
P2 -.-> E3
|
|
190
|
+
|
|
191
|
+
P3 -.-> E1
|
|
192
|
+
P3 -.-> E2
|
|
193
|
+
P3 -.-> E3
|
|
194
|
+
|
|
195
|
+
PN -.-> EN
|
|
196
|
+
|
|
197
|
+
E1 --> VLC
|
|
198
|
+
E2 --> VLC
|
|
199
|
+
E3 --> VLC
|
|
200
|
+
EN --> VLC
|
|
201
|
+
|
|
202
|
+
E1 --> MPV
|
|
203
|
+
E2 --> MPV
|
|
204
|
+
E3 --> MPV
|
|
205
|
+
EN --> MPV
|
|
206
|
+
|
|
207
|
+
E1 --> MX
|
|
208
|
+
E2 --> MX
|
|
209
|
+
E3 --> MX
|
|
210
|
+
EN --> MX
|
|
211
|
+
```
|
|
206
212
|
|
|
207
213
|
---
|
|
208
214
|
|
|
@@ -224,24 +230,22 @@ KekikStream/
|
|
|
224
230
|
|
|
225
231
|
### Yeni Plugin Ekleme
|
|
226
232
|
|
|
227
|
-
1. `KekikStream/Plugins/` altına yeni dosya oluşturun
|
|
228
|
-
2. `PluginBase` sınıfından türetin
|
|
229
|
-
3.
|
|
230
|
-
4. Plugin'i test edin
|
|
231
|
-
|
|
232
|
-
**Örnek:** [Tests/Single.py](https://github.com/keyiflerolsun/KekikStream/blob/master/Tests/Single.py)
|
|
233
|
+
1. `KekikStream/Plugins/` altına yeni dosya oluşturun.
|
|
234
|
+
2. `PluginBase` sınıfından türetin.
|
|
235
|
+
3. `get_main_page`, `search`, `load_item`, `load_links` metodlarını implemente edin.
|
|
236
|
+
4. Plugin'i test edin (örnek: `Tests/Single.py`).
|
|
233
237
|
|
|
234
238
|
---
|
|
235
239
|
|
|
236
240
|
## 📊 Performans
|
|
237
241
|
|
|
238
|
-
| Metrik
|
|
239
|
-
|
|
240
|
-
| Plugin Sayısı
|
|
241
|
-
| Extractor Sayısı
|
|
242
|
+
| Metrik | Değer |
|
|
243
|
+
|----------------------|------------------|
|
|
244
|
+
| Plugin Sayısı | 20+ |
|
|
245
|
+
| Extractor Sayısı | 40+ |
|
|
242
246
|
| Desteklenen Platform | Desktop, Android |
|
|
243
|
-
| Async Arama
|
|
244
|
-
| Cache Desteği
|
|
247
|
+
| Async Arama | ✅ |
|
|
248
|
+
| Cache Desteği | ✅ |
|
|
245
249
|
|
|
246
250
|
---
|
|
247
251
|
|
|
@@ -249,12 +253,10 @@ KekikStream/
|
|
|
249
253
|
|
|
250
254
|
Projeyi geliştirmek için katkılarınızı bekliyoruz!
|
|
251
255
|
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
255
|
-
|
|
256
|
-
3. **Feature Request:** Yeni özellik önerileri
|
|
257
|
-
4. **Dokümantasyon:** README ve kod dokümantasyonu iyileştirmeleri
|
|
256
|
+
1. Yeni plugin ekleyin
|
|
257
|
+
2. Bug raporu açın
|
|
258
|
+
3. Feature request gönderin
|
|
259
|
+
4. Dokümantasyon iyileştirin
|
|
258
260
|
|
|
259
261
|
### 🎁 Teşekkürler
|
|
260
262
|
|
|
@@ -262,14 +264,13 @@ Projeyi geliştirmek için katkılarınızı bekliyoruz!
|
|
|
262
264
|
|
|
263
265
|
### 💻 Genişletme Referansları
|
|
264
266
|
|
|
265
|
-
- [keyiflerolsun/Kekik-cloudstream](https://github.com/keyiflerolsun/Kekik-cloudstream)
|
|
267
|
+
- [keyiflerolsun/Kekik-cloudstream](https://github.com/keyiflerolsun/Kekik-cloudstream)
|
|
266
268
|
- [keyiflerolsun/seyirTurk-Parser](https://github.com/keyiflerolsun/seyirTurk-Parser)
|
|
267
269
|
|
|
268
270
|
## 🌐 Telif Hakkı ve Lisans
|
|
269
271
|
|
|
270
|
-
*
|
|
271
|
-
|
|
272
|
-
|
|
272
|
+
*Copyright (C) 2024 by* [keyiflerolsun](https://github.com/keyiflerolsun) ❤️️
|
|
273
|
+
[GNU GENERAL PUBLIC LICENSE Version 3, 29 June 2007](https://github.com/keyiflerolsun/KekikStream/blob/master/LICENSE) *Koşullarına göre lisanslanmıştır..*
|
|
273
274
|
|
|
274
275
|
---
|
|
275
276
|
|
|
@@ -64,6 +64,7 @@ KekikStream/Extractors/VidMolyMe.py
|
|
|
64
64
|
KekikStream/Extractors/VidMoxy.py
|
|
65
65
|
KekikStream/Extractors/VidPapi.py
|
|
66
66
|
KekikStream/Extractors/VideoSeyred.py
|
|
67
|
+
KekikStream/Extractors/YTDLP.py
|
|
67
68
|
KekikStream/Extractors/YildizKisaFilm.py
|
|
68
69
|
KekikStream/Plugins/DiziBox.py
|
|
69
70
|
KekikStream/Plugins/DiziPal.py
|