KekikStream 2.1.6__tar.gz → 2.1.8__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-2.1.6 → kekikstream-2.1.8}/KekikStream/Core/Plugin/PluginBase.py +20 -21
- kekikstream-2.1.8/KekikStream/Extractors/Filemoon.py +78 -0
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream/Extractors/RapidVid.py +15 -5
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream/Extractors/VidHide.py +11 -2
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream/Plugins/BelgeselX.py +7 -7
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream/Plugins/DiziBox.py +2 -2
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream/Plugins/DiziPal.py +8 -8
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream/Plugins/DiziYou.py +8 -8
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream/Plugins/Dizilla.py +2 -2
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream/Plugins/FilmBip.py +2 -2
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream/Plugins/FilmMakinesi.py +2 -2
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream/Plugins/FilmModu.py +8 -8
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream/Plugins/FullHDFilm.py +13 -5
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream/Plugins/FullHDFilmizlesene.py +2 -2
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream/Plugins/HDFilmCehennemi.py +19 -19
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream/Plugins/JetFilmizle.py +2 -2
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream/Plugins/KultFilmler.py +10 -9
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream/Plugins/RecTV.py +15 -15
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream/Plugins/RoketDizi.py +2 -2
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream/Plugins/SelcukFlix.py +2 -2
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream/Plugins/SetFilmIzle.py +2 -2
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream/Plugins/SezonlukDizi.py +2 -2
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream/Plugins/SineWix.py +13 -13
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream/Plugins/Sinefy.py +6 -6
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream/Plugins/SinemaCX.py +31 -22
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream/Plugins/Sinezy.py +2 -2
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream/Plugins/SuperFilmGeldi.py +30 -19
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream/Plugins/UgurFilm.py +2 -2
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream/__init__.py +15 -15
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream.egg-info/PKG-INFO +3 -3
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream.egg-info/SOURCES.txt +1 -0
- {kekikstream-2.1.6 → kekikstream-2.1.8}/PKG-INFO +3 -3
- {kekikstream-2.1.6 → kekikstream-2.1.8}/README.md +2 -2
- {kekikstream-2.1.6 → kekikstream-2.1.8}/setup.py +1 -1
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream/CLI/__init__.py +0 -0
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream/CLI/pypi_kontrol.py +0 -0
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream/Core/Extractor/ExtractorBase.py +0 -0
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream/Core/Extractor/ExtractorLoader.py +0 -0
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream/Core/Extractor/ExtractorManager.py +0 -0
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream/Core/Extractor/ExtractorModels.py +0 -0
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream/Core/Extractor/YTDLPCache.py +0 -0
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream/Core/Media/MediaHandler.py +0 -0
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream/Core/Media/MediaManager.py +0 -0
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream/Core/Plugin/PluginLoader.py +0 -0
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream/Core/Plugin/PluginManager.py +0 -0
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream/Core/Plugin/PluginModels.py +0 -0
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream/Core/UI/UIManager.py +0 -0
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream/Core/__init__.py +0 -0
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream/Extractors/CloseLoad.py +0 -0
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream/Extractors/ContentX.py +0 -0
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream/Extractors/DonilasPlay.py +0 -0
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream/Extractors/DzenRu.py +0 -0
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream/Extractors/ExPlay.py +0 -0
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream/Extractors/HDPlayerSystem.py +0 -0
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream/Extractors/JetTv.py +0 -0
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream/Extractors/MailRu.py +0 -0
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream/Extractors/MixPlayHD.py +0 -0
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream/Extractors/MixTiger.py +0 -0
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream/Extractors/MolyStream.py +0 -0
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream/Extractors/Odnoklassniki.py +0 -0
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream/Extractors/PeaceMakerst.py +0 -0
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream/Extractors/PixelDrain.py +0 -0
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream/Extractors/PlayerFilmIzle.py +0 -0
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream/Extractors/SetPlay.py +0 -0
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream/Extractors/SetPrime.py +0 -0
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream/Extractors/SibNet.py +0 -0
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream/Extractors/Sobreatsesuyp.py +0 -0
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream/Extractors/TRsTX.py +0 -0
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream/Extractors/TauVideo.py +0 -0
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream/Extractors/TurboImgz.py +0 -0
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream/Extractors/TurkeyPlayer.py +0 -0
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream/Extractors/VCTPlay.py +0 -0
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream/Extractors/VidMoly.py +0 -0
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream/Extractors/VidMoxy.py +0 -0
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream/Extractors/VidPapi.py +0 -0
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream/Extractors/VideoSeyred.py +0 -0
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream/Extractors/YTDLP.py +0 -0
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream/Extractors/YildizKisaFilm.py +0 -0
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream/__main__.py +0 -0
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream/requirements.txt +0 -0
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream.egg-info/dependency_links.txt +0 -0
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream.egg-info/entry_points.txt +0 -0
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream.egg-info/requires.txt +0 -0
- {kekikstream-2.1.6 → kekikstream-2.1.8}/KekikStream.egg-info/top_level.txt +0 -0
- {kekikstream-2.1.6 → kekikstream-2.1.8}/LICENSE +0 -0
- {kekikstream-2.1.6 → kekikstream-2.1.8}/MANIFEST.in +0 -0
- {kekikstream-2.1.6 → kekikstream-2.1.8}/setup.cfg +0 -0
|
@@ -4,7 +4,7 @@ from ...CLI import konsol
|
|
|
4
4
|
from abc import ABC, abstractmethod
|
|
5
5
|
from cloudscraper import CloudScraper
|
|
6
6
|
from httpx import AsyncClient
|
|
7
|
-
from .PluginModels import MainPageResult, SearchResult, MovieInfo
|
|
7
|
+
from .PluginModels import MainPageResult, SearchResult, MovieInfo, SeriesInfo
|
|
8
8
|
from ..Media.MediaHandler import MediaHandler
|
|
9
9
|
from ..Extractor.ExtractorManager import ExtractorManager
|
|
10
10
|
from ..Extractor.ExtractorModels import ExtractResult
|
|
@@ -55,31 +55,31 @@ class PluginBase(ABC):
|
|
|
55
55
|
pass
|
|
56
56
|
|
|
57
57
|
@abstractmethod
|
|
58
|
-
async def load_item(self, url: str) -> MovieInfo:
|
|
58
|
+
async def load_item(self, url: str) -> MovieInfo | SeriesInfo:
|
|
59
59
|
"""Bir medya öğesi hakkında detaylı bilgi döndürür."""
|
|
60
60
|
pass
|
|
61
61
|
|
|
62
62
|
@abstractmethod
|
|
63
|
-
async def load_links(self, url: str) -> list[
|
|
63
|
+
async def load_links(self, url: str) -> list[ExtractResult]:
|
|
64
64
|
"""
|
|
65
65
|
Bir medya öğesi için oynatma bağlantılarını döndürür.
|
|
66
|
-
|
|
66
|
+
|
|
67
67
|
Args:
|
|
68
68
|
url: Medya URL'si
|
|
69
|
-
|
|
69
|
+
|
|
70
70
|
Returns:
|
|
71
|
-
|
|
71
|
+
ExtractResult listesi, her biri şu alanları içerir:
|
|
72
72
|
- url (str, zorunlu): Video URL'si
|
|
73
73
|
- name (str, zorunlu): Gösterim adı (tüm bilgileri içerir)
|
|
74
74
|
- referer (str, opsiyonel): Referer header
|
|
75
|
-
- subtitles (list, opsiyonel): Altyazı listesi
|
|
76
|
-
|
|
75
|
+
- subtitles (list[Subtitle], opsiyonel): Altyazı listesi
|
|
76
|
+
|
|
77
77
|
Example:
|
|
78
78
|
[
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
82
|
-
|
|
79
|
+
ExtractResult(
|
|
80
|
+
url="https://example.com/video.m3u8",
|
|
81
|
+
name="HDFilmCehennemi | 1080p TR Dublaj"
|
|
82
|
+
)
|
|
83
83
|
]
|
|
84
84
|
"""
|
|
85
85
|
pass
|
|
@@ -97,7 +97,7 @@ class PluginBase(ABC):
|
|
|
97
97
|
|
|
98
98
|
return f"https:{url}" if url.startswith("//") else urljoin(self.main_url, url)
|
|
99
99
|
|
|
100
|
-
async def extract(self, url: str, referer: str = None, prefix: str | None = None) ->
|
|
100
|
+
async def extract(self, url: str, referer: str = None, prefix: str | None = None) -> ExtractResult | None:
|
|
101
101
|
"""
|
|
102
102
|
Extractor ile video URL'sini çıkarır.
|
|
103
103
|
|
|
@@ -107,8 +107,8 @@ class PluginBase(ABC):
|
|
|
107
107
|
prefix: İsmin başına eklenecek opsiyonel etiket (örn: "Türkçe Dublaj")
|
|
108
108
|
|
|
109
109
|
Returns:
|
|
110
|
-
|
|
111
|
-
|
|
110
|
+
ExtractResult: Extractor sonucu (name prefix ile birleştirilmiş) veya None
|
|
111
|
+
|
|
112
112
|
Extractor bulunamadığında veya hata oluştuğunda uyarı verir.
|
|
113
113
|
"""
|
|
114
114
|
if referer is None:
|
|
@@ -121,13 +121,12 @@ class PluginBase(ABC):
|
|
|
121
121
|
|
|
122
122
|
try:
|
|
123
123
|
data = await extractor.extract(url, referer=referer)
|
|
124
|
-
|
|
125
|
-
|
|
124
|
+
|
|
126
125
|
# prefix varsa name'e ekle
|
|
127
|
-
if prefix and
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
return
|
|
126
|
+
if prefix and data.name:
|
|
127
|
+
data.name = f"{prefix} | {data.name}"
|
|
128
|
+
|
|
129
|
+
return data
|
|
131
130
|
except Exception as hata:
|
|
132
131
|
konsol.log(f"[red][!] {self.name} » Extractor hatası ({extractor.name}): {hata}")
|
|
133
132
|
return None
|
|
@@ -0,0 +1,78 @@
|
|
|
1
|
+
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
|
+
|
|
3
|
+
from KekikStream.Core import ExtractorBase, ExtractResult
|
|
4
|
+
from Kekik.Sifreleme import Packer
|
|
5
|
+
from parsel import Selector
|
|
6
|
+
import re
|
|
7
|
+
|
|
8
|
+
class Filemoon(ExtractorBase):
|
|
9
|
+
name = "Filemoon"
|
|
10
|
+
main_url = "https://filemoon.to"
|
|
11
|
+
|
|
12
|
+
# Filemoon'un farklı domainlerini destekle
|
|
13
|
+
supported_domains = [
|
|
14
|
+
"filemoon.to",
|
|
15
|
+
"filemoon.in",
|
|
16
|
+
"filemoon.sx",
|
|
17
|
+
"filemoon.nl",
|
|
18
|
+
"filemoon.com"
|
|
19
|
+
]
|
|
20
|
+
|
|
21
|
+
def can_handle_url(self, url: str) -> bool:
|
|
22
|
+
return any(domain in url for domain in self.supported_domains)
|
|
23
|
+
|
|
24
|
+
async def extract(self, url: str, referer: str = None) -> ExtractResult:
|
|
25
|
+
headers = {
|
|
26
|
+
"Referer" : url,
|
|
27
|
+
"Sec-Fetch-Dest" : "iframe",
|
|
28
|
+
"Sec-Fetch-Mode" : "navigate",
|
|
29
|
+
"Sec-Fetch-Site" : "cross-site",
|
|
30
|
+
}
|
|
31
|
+
self.httpx.headers.update(headers)
|
|
32
|
+
|
|
33
|
+
# İlk sayfayı al
|
|
34
|
+
istek = await self.httpx.get(url)
|
|
35
|
+
response = istek.text
|
|
36
|
+
secici = Selector(response)
|
|
37
|
+
|
|
38
|
+
# Eğer iframe varsa, iframe'e git
|
|
39
|
+
iframe_src = secici.css("iframe::attr(src)").get()
|
|
40
|
+
if iframe_src:
|
|
41
|
+
iframe_url = self.fix_url(iframe_src)
|
|
42
|
+
self.httpx.headers.update({
|
|
43
|
+
"Accept-Language" : "en-US,en;q=0.5",
|
|
44
|
+
"Sec-Fetch-Dest" : "iframe"
|
|
45
|
+
})
|
|
46
|
+
istek = await self.httpx.get(iframe_url)
|
|
47
|
+
response = istek.text
|
|
48
|
+
|
|
49
|
+
# Packed script'i bul ve unpack et
|
|
50
|
+
m3u8_url = None
|
|
51
|
+
|
|
52
|
+
if Packer.detect_packed(response):
|
|
53
|
+
try:
|
|
54
|
+
unpacked = Packer.unpack(response)
|
|
55
|
+
# sources:[{file:"..." pattern'ını ara
|
|
56
|
+
if match := re.search(r'sources:\s*\[\s*\{\s*file:\s*"([^"]+)"', unpacked):
|
|
57
|
+
m3u8_url = match.group(1)
|
|
58
|
+
elif match := re.search(r'file:\s*"([^"]*?\.m3u8[^"]*)"', unpacked):
|
|
59
|
+
m3u8_url = match.group(1)
|
|
60
|
+
except Exception:
|
|
61
|
+
pass
|
|
62
|
+
|
|
63
|
+
# Fallback: Doğrudan response'ta ara
|
|
64
|
+
if not m3u8_url:
|
|
65
|
+
if match := re.search(r'sources:\s*\[\s*\{\s*file:\s*"([^"]+)"', response):
|
|
66
|
+
m3u8_url = match.group(1)
|
|
67
|
+
elif match := re.search(r'file:\s*"([^"]*?\.m3u8[^"]*)"', response):
|
|
68
|
+
m3u8_url = match.group(1)
|
|
69
|
+
|
|
70
|
+
if not m3u8_url:
|
|
71
|
+
raise ValueError(f"Filemoon: Video URL bulunamadı. {url}")
|
|
72
|
+
|
|
73
|
+
return ExtractResult(
|
|
74
|
+
name = self.name,
|
|
75
|
+
url = self.fix_url(m3u8_url),
|
|
76
|
+
referer = f"{self.main_url}/",
|
|
77
|
+
subtitles = []
|
|
78
|
+
)
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
2
|
|
|
3
3
|
from KekikStream.Core import ExtractorBase, ExtractResult, Subtitle
|
|
4
|
-
from Kekik.Sifreleme import Packer, HexCodec
|
|
4
|
+
from Kekik.Sifreleme import Packer, HexCodec, StreamDecoder
|
|
5
5
|
import re, base64
|
|
6
6
|
|
|
7
7
|
class RapidVid(ExtractorBase):
|
|
@@ -39,15 +39,25 @@ class RapidVid(ExtractorBase):
|
|
|
39
39
|
subtitles.append(Subtitle(name=decoded_lang, url=sub_url.replace("\\", "")))
|
|
40
40
|
|
|
41
41
|
try:
|
|
42
|
+
decoded_url = None
|
|
43
|
+
|
|
44
|
+
# Method 1: file": "..." pattern (HexCodec)
|
|
42
45
|
if extracted_value := re.search(r'file": "(.*)",', istek.text):
|
|
43
46
|
escaped_hex = extracted_value[1]
|
|
44
47
|
decoded_url = HexCodec.decode(escaped_hex)
|
|
45
|
-
else:
|
|
46
|
-
av_encoded = re.search(r"av\('([^']+)'\)", istek.text)
|
|
47
|
-
if not av_encoded:
|
|
48
|
-
raise ValueError("AV encoding not found.")
|
|
49
48
|
|
|
49
|
+
# Method 2: av('...') pattern
|
|
50
|
+
elif av_encoded := re.search(r"av\('([^']+)'\)", istek.text):
|
|
50
51
|
decoded_url = self.decode_secret(av_encoded[1])
|
|
52
|
+
|
|
53
|
+
# Method 3: Packed script with dc_* function (StreamDecoder)
|
|
54
|
+
elif Packer.detect_packed(istek.text):
|
|
55
|
+
unpacked = Packer.unpack(istek.text)
|
|
56
|
+
decoded_url = StreamDecoder.extract_stream_url(unpacked)
|
|
57
|
+
|
|
58
|
+
if not decoded_url:
|
|
59
|
+
raise ValueError("No valid video URL pattern found.")
|
|
60
|
+
|
|
51
61
|
except Exception as hata:
|
|
52
62
|
raise RuntimeError(f"Extraction failed: {hata}") from hata
|
|
53
63
|
|
|
@@ -9,6 +9,12 @@ class VidHide(ExtractorBase):
|
|
|
9
9
|
name = "VidHide"
|
|
10
10
|
main_url = "https://vidhidepro.com"
|
|
11
11
|
|
|
12
|
+
# Birden fazla domain destekle
|
|
13
|
+
supported_domains = ["vidhidepro.com", "vidhide.com", "rubyvidhub.com"]
|
|
14
|
+
|
|
15
|
+
def can_handle_url(self, url: str) -> bool:
|
|
16
|
+
return any(domain in url for domain in self.supported_domains)
|
|
17
|
+
|
|
12
18
|
def get_embed_url(self, url: str) -> str:
|
|
13
19
|
if "/d/" in url:
|
|
14
20
|
return url.replace("/d/", "/v/")
|
|
@@ -20,6 +26,9 @@ class VidHide(ExtractorBase):
|
|
|
20
26
|
return url.replace("/f/", "/v/")
|
|
21
27
|
|
|
22
28
|
async def extract(self, url: str, referer: str = None) -> ExtractResult:
|
|
29
|
+
# Dinamik base URL kullan
|
|
30
|
+
base_url = self.get_base_url(url)
|
|
31
|
+
|
|
23
32
|
if referer:
|
|
24
33
|
self.httpx.headers.update({"Referer": referer})
|
|
25
34
|
|
|
@@ -27,7 +36,7 @@ class VidHide(ExtractorBase):
|
|
|
27
36
|
"Sec-Fetch-Dest" : "empty",
|
|
28
37
|
"Sec-Fetch-Mode" : "cors",
|
|
29
38
|
"Sec-Fetch-Site" : "cross-site",
|
|
30
|
-
"Origin" :
|
|
39
|
+
"Origin" : base_url,
|
|
31
40
|
})
|
|
32
41
|
|
|
33
42
|
embed_url = self.get_embed_url(url)
|
|
@@ -66,7 +75,7 @@ class VidHide(ExtractorBase):
|
|
|
66
75
|
return ExtractResult(
|
|
67
76
|
name = self.name,
|
|
68
77
|
url = self.fix_url(m3u8_url),
|
|
69
|
-
referer = f"{
|
|
78
|
+
referer = f"{base_url}/",
|
|
70
79
|
user_agent = self.httpx.headers.get("User-Agent", ""),
|
|
71
80
|
subtitles = []
|
|
72
81
|
)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
2
|
|
|
3
|
-
from KekikStream.Core import PluginBase, MainPageResult, SearchResult, SeriesInfo, Episode
|
|
3
|
+
from KekikStream.Core import PluginBase, MainPageResult, SearchResult, SeriesInfo, Episode, ExtractResult
|
|
4
4
|
from parsel import Selector
|
|
5
5
|
import re
|
|
6
6
|
|
|
@@ -164,7 +164,7 @@ class BelgeselX(PluginBase):
|
|
|
164
164
|
episodes = episodes
|
|
165
165
|
)
|
|
166
166
|
|
|
167
|
-
async def load_links(self, url: str) -> list[
|
|
167
|
+
async def load_links(self, url: str) -> list[ExtractResult]:
|
|
168
168
|
istek = await self.httpx.get(url)
|
|
169
169
|
text = istek.text
|
|
170
170
|
|
|
@@ -187,10 +187,10 @@ class BelgeselX(PluginBase):
|
|
|
187
187
|
source_name = "Google" if quality == "FULL" else self.name
|
|
188
188
|
quality_str = "1080p" if quality == "FULL" else quality
|
|
189
189
|
|
|
190
|
-
links.append(
|
|
191
|
-
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
190
|
+
links.append(ExtractResult(
|
|
191
|
+
url = video_url,
|
|
192
|
+
name = f"{source_name} | {quality_str}",
|
|
193
|
+
referer = url
|
|
194
|
+
))
|
|
195
195
|
|
|
196
196
|
return links
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
2
|
|
|
3
|
-
from KekikStream.Core import PluginBase, MainPageResult, SearchResult, SeriesInfo, Episode
|
|
3
|
+
from KekikStream.Core import PluginBase, MainPageResult, SearchResult, SeriesInfo, Episode, ExtractResult
|
|
4
4
|
from Kekik.Sifreleme import CryptoJS
|
|
5
5
|
from parsel import Selector
|
|
6
6
|
import re, urllib.parse, base64, contextlib, asyncio, time
|
|
@@ -174,7 +174,7 @@ class DiziBox(PluginBase):
|
|
|
174
174
|
|
|
175
175
|
return results
|
|
176
176
|
|
|
177
|
-
async def load_links(self, url: str) -> list[
|
|
177
|
+
async def load_links(self, url: str) -> list[ExtractResult]:
|
|
178
178
|
istek = await self.httpx.get(url)
|
|
179
179
|
secici = Selector(istek.text)
|
|
180
180
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
2
|
|
|
3
|
-
from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo, SeriesInfo, Episode, Subtitle
|
|
3
|
+
from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo, SeriesInfo, Episode, Subtitle, ExtractResult
|
|
4
4
|
from parsel import Selector
|
|
5
5
|
import re
|
|
6
6
|
|
|
@@ -177,7 +177,7 @@ class DiziPal(PluginBase):
|
|
|
177
177
|
duration = duration,
|
|
178
178
|
)
|
|
179
179
|
|
|
180
|
-
async def load_links(self, url: str) -> list[
|
|
180
|
+
async def load_links(self, url: str) -> list[ExtractResult]:
|
|
181
181
|
# Reset headers to get HTML response
|
|
182
182
|
self.httpx.headers.update({
|
|
183
183
|
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
|
|
@@ -220,12 +220,12 @@ class DiziPal(PluginBase):
|
|
|
220
220
|
sub_url = sub_text.replace(f"[{lang}]", "")
|
|
221
221
|
subtitles.append(Subtitle(name=lang, url=self.fix_url(sub_url)))
|
|
222
222
|
|
|
223
|
-
results.append(
|
|
224
|
-
|
|
225
|
-
|
|
226
|
-
|
|
227
|
-
|
|
228
|
-
|
|
223
|
+
results.append(ExtractResult(
|
|
224
|
+
name = self.name,
|
|
225
|
+
url = m3u_link,
|
|
226
|
+
referer = f"{self.main_url}/",
|
|
227
|
+
subtitles = subtitles
|
|
228
|
+
))
|
|
229
229
|
else:
|
|
230
230
|
# Extractor'a yönlendir
|
|
231
231
|
data = await self.extract(iframe)
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
2
|
|
|
3
|
-
from KekikStream.Core import PluginBase, MainPageResult, SearchResult, SeriesInfo, Episode, Subtitle
|
|
3
|
+
from KekikStream.Core import PluginBase, MainPageResult, SearchResult, SeriesInfo, Episode, Subtitle, ExtractResult
|
|
4
4
|
from parsel import Selector
|
|
5
5
|
import re
|
|
6
6
|
|
|
@@ -123,7 +123,7 @@ class DiziYou(PluginBase):
|
|
|
123
123
|
actors = actors
|
|
124
124
|
)
|
|
125
125
|
|
|
126
|
-
async def load_links(self, url: str) -> list[
|
|
126
|
+
async def load_links(self, url: str) -> list[ExtractResult]:
|
|
127
127
|
istek = await self.httpx.get(url)
|
|
128
128
|
secici = Selector(istek.text)
|
|
129
129
|
|
|
@@ -179,11 +179,11 @@ class DiziYou(PluginBase):
|
|
|
179
179
|
|
|
180
180
|
results = []
|
|
181
181
|
for stream in stream_urls:
|
|
182
|
-
results.append(
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
186
|
-
|
|
187
|
-
|
|
182
|
+
results.append(ExtractResult(
|
|
183
|
+
url = stream.get("url"),
|
|
184
|
+
name = f"{stream.get('dil')}",
|
|
185
|
+
referer = url,
|
|
186
|
+
subtitles = subtitles
|
|
187
|
+
))
|
|
188
188
|
|
|
189
189
|
return results
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
2
|
|
|
3
|
-
from KekikStream.Core import PluginBase, MainPageResult, SearchResult, SeriesInfo, Episode
|
|
3
|
+
from KekikStream.Core import PluginBase, MainPageResult, SearchResult, SeriesInfo, Episode, ExtractResult
|
|
4
4
|
from parsel import Selector
|
|
5
5
|
from json import loads
|
|
6
6
|
from urllib.parse import urlparse, urlunparse
|
|
@@ -170,7 +170,7 @@ class Dizilla(PluginBase):
|
|
|
170
170
|
actors = actors
|
|
171
171
|
)
|
|
172
172
|
|
|
173
|
-
async def load_links(self, url: str) -> list[
|
|
173
|
+
async def load_links(self, url: str) -> list[ExtractResult]:
|
|
174
174
|
istek = await self.httpx.get(url)
|
|
175
175
|
secici = Selector(istek.text)
|
|
176
176
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
2
|
|
|
3
|
-
from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo
|
|
3
|
+
from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo, ExtractResult
|
|
4
4
|
from parsel import Selector
|
|
5
5
|
|
|
6
6
|
class FilmBip(PluginBase):
|
|
@@ -125,7 +125,7 @@ class FilmBip(PluginBase):
|
|
|
125
125
|
actors = actors,
|
|
126
126
|
)
|
|
127
127
|
|
|
128
|
-
async def load_links(self, url: str) -> list[
|
|
128
|
+
async def load_links(self, url: str) -> list[ExtractResult]:
|
|
129
129
|
istek = await self.httpx.get(url)
|
|
130
130
|
secici = Selector(istek.text)
|
|
131
131
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
2
|
|
|
3
|
-
from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo
|
|
3
|
+
from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo, ExtractResult
|
|
4
4
|
from parsel import Selector
|
|
5
5
|
|
|
6
6
|
class FilmMakinesi(PluginBase):
|
|
@@ -104,7 +104,7 @@ class FilmMakinesi(PluginBase):
|
|
|
104
104
|
duration = duration
|
|
105
105
|
)
|
|
106
106
|
|
|
107
|
-
async def load_links(self, url: str) -> list[
|
|
107
|
+
async def load_links(self, url: str) -> list[ExtractResult]:
|
|
108
108
|
istek = await self.httpx.get(url)
|
|
109
109
|
secici = Selector(istek.text)
|
|
110
110
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
2
|
|
|
3
|
-
from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo, Subtitle
|
|
3
|
+
from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo, Subtitle, ExtractResult
|
|
4
4
|
from parsel import Selector
|
|
5
5
|
import re
|
|
6
6
|
|
|
@@ -87,7 +87,7 @@ class FilmModu(PluginBase):
|
|
|
87
87
|
actors = [a.css("span::text").get() for a in secici.css("a[itemprop='actor']")],
|
|
88
88
|
)
|
|
89
89
|
|
|
90
|
-
async def load_links(self, url: str) -> list[
|
|
90
|
+
async def load_links(self, url: str) -> list[ExtractResult]:
|
|
91
91
|
istek = await self.httpx.get(url)
|
|
92
92
|
secici = Selector(istek.text)
|
|
93
93
|
|
|
@@ -124,11 +124,11 @@ class FilmModu(PluginBase):
|
|
|
124
124
|
subtitle_url = None
|
|
125
125
|
|
|
126
126
|
for source in source_data.get("sources", []):
|
|
127
|
-
results.append(
|
|
128
|
-
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
|
|
127
|
+
results.append(ExtractResult(
|
|
128
|
+
name = f"{self.name} | {alt_name} | {source.get('label', 'Bilinmiyor')}",
|
|
129
|
+
url = self.fix_url(source["src"]),
|
|
130
|
+
referer = f"{self.main_url}/",
|
|
131
|
+
subtitles = [Subtitle(name="Türkçe", url=subtitle_url)] if subtitle_url else []
|
|
132
|
+
))
|
|
133
133
|
|
|
134
134
|
return results
|
|
@@ -14,23 +14,29 @@ class FullHDFilm(PluginBase):
|
|
|
14
14
|
main_page = {
|
|
15
15
|
f"{main_url}/tur/turkce-altyazili-film-izle" : "Altyazılı Filmler",
|
|
16
16
|
f"{main_url}/tur/netflix-filmleri-izle" : "Netflix",
|
|
17
|
+
f"{main_url}/tur/yerli-film-izle" : "Yerli Film",
|
|
17
18
|
f"{main_url}/category/aile-filmleri-izle" : "Aile",
|
|
18
19
|
f"{main_url}/category/aksiyon-filmleri-izle" : "Aksiyon",
|
|
19
20
|
f"{main_url}/category/animasyon-filmleri-izle" : "Animasyon",
|
|
20
21
|
f"{main_url}/category/belgesel-filmleri-izle" : "Belgesel",
|
|
21
|
-
f"{main_url}/category/bilim-kurgu-filmleri-izle" : "Bilim
|
|
22
|
+
f"{main_url}/category/bilim-kurgu-filmleri-izle" : "Bilim Kurgu",
|
|
22
23
|
f"{main_url}/category/biyografi-filmleri-izle" : "Biyografi",
|
|
23
24
|
f"{main_url}/category/dram-filmleri-izle" : "Dram",
|
|
24
25
|
f"{main_url}/category/fantastik-filmler-izle" : "Fantastik",
|
|
25
26
|
f"{main_url}/category/gerilim-filmleri-izle" : "Gerilim",
|
|
26
27
|
f"{main_url}/category/gizem-filmleri-izle" : "Gizem",
|
|
28
|
+
f"{main_url}/category/kisa" : "Kısa",
|
|
27
29
|
f"{main_url}/category/komedi-filmleri-izle" : "Komedi",
|
|
28
30
|
f"{main_url}/category/korku-filmleri-izle" : "Korku",
|
|
29
31
|
f"{main_url}/category/macera-filmleri-izle" : "Macera",
|
|
32
|
+
f"{main_url}/category/muzik" : "Müzik",
|
|
33
|
+
f"{main_url}/category/muzikal-filmleri-izle" : "Müzikal",
|
|
30
34
|
f"{main_url}/category/romantik-filmler-izle" : "Romantik",
|
|
31
35
|
f"{main_url}/category/savas-filmleri-izle" : "Savaş",
|
|
36
|
+
f"{main_url}/category/spor-filmleri-izle" : "Spor",
|
|
32
37
|
f"{main_url}/category/suc-filmleri-izle" : "Suç",
|
|
33
|
-
f"{main_url}/
|
|
38
|
+
f"{main_url}/category/tarih-filmleri-izle" : "Tarih",
|
|
39
|
+
f"{main_url}/category/western-filmleri-izle" : "Western",
|
|
34
40
|
}
|
|
35
41
|
|
|
36
42
|
async def get_main_page(self, page: int, url: str, category: str) -> list[MainPageResult]:
|
|
@@ -182,7 +188,7 @@ class FullHDFilm(PluginBase):
|
|
|
182
188
|
|
|
183
189
|
return None
|
|
184
190
|
|
|
185
|
-
async def load_links(self, url: str) -> list[
|
|
191
|
+
async def load_links(self, url: str) -> list[ExtractResult]:
|
|
186
192
|
self.httpx.headers.update({
|
|
187
193
|
"User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
|
|
188
194
|
"Referer" : self.main_url
|
|
@@ -206,7 +212,9 @@ class FullHDFilm(PluginBase):
|
|
|
206
212
|
if iframe_src:
|
|
207
213
|
data = await self.extract(iframe_src)
|
|
208
214
|
if data:
|
|
209
|
-
|
|
210
|
-
|
|
215
|
+
# ExtractResult objesi immutable, yeni bir kopya oluştur
|
|
216
|
+
subtitles = [Subtitle(name="Türkçe", url=subtitle_url)] if subtitle_url else []
|
|
217
|
+
updated_data = data.model_copy(update={"subtitles": subtitles}) if subtitles else data
|
|
218
|
+
results.append(updated_data)
|
|
211
219
|
|
|
212
220
|
return results
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
2
|
|
|
3
|
-
from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo
|
|
3
|
+
from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo, ExtractResult
|
|
4
4
|
from parsel import Selector
|
|
5
5
|
from Kekik.Sifreleme import StringCodec
|
|
6
6
|
import json, re
|
|
@@ -100,7 +100,7 @@ class FullHDFilmizlesene(PluginBase):
|
|
|
100
100
|
duration = duration
|
|
101
101
|
)
|
|
102
102
|
|
|
103
|
-
async def load_links(self, url: str) -> list[
|
|
103
|
+
async def load_links(self, url: str) -> list[ExtractResult]:
|
|
104
104
|
istek = await self.httpx.get(url)
|
|
105
105
|
secici = Selector(istek.text)
|
|
106
106
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
2
|
|
|
3
|
-
from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo, SeriesInfo, Episode, Subtitle
|
|
3
|
+
from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo, SeriesInfo, Episode, Subtitle, ExtractResult
|
|
4
4
|
from parsel import Selector
|
|
5
5
|
from Kekik.Sifreleme import Packer, StreamDecoder
|
|
6
6
|
import random, string, re
|
|
@@ -145,7 +145,7 @@ class HDFilmCehennemi(PluginBase):
|
|
|
145
145
|
def generate_random_cookie(self):
|
|
146
146
|
return "".join(random.choices(string.ascii_letters + string.digits, k=16))
|
|
147
147
|
|
|
148
|
-
async def cehennempass(self, video_id: str) -> list
|
|
148
|
+
async def cehennempass(self, video_id: str) -> list:
|
|
149
149
|
results = []
|
|
150
150
|
|
|
151
151
|
istek = await self.httpx.post(
|
|
@@ -159,11 +159,11 @@ class HDFilmCehennemi(PluginBase):
|
|
|
159
159
|
data = {"video_id": video_id, "selected_quality": "low"},
|
|
160
160
|
)
|
|
161
161
|
if video_url := istek.json().get("download_link"):
|
|
162
|
-
results.append(
|
|
163
|
-
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
|
|
162
|
+
results.append(ExtractResult(
|
|
163
|
+
url = self.fix_url(video_url),
|
|
164
|
+
name = "Düşük Kalite",
|
|
165
|
+
referer = f"https://cehennempass.pw/download/{video_id}"
|
|
166
|
+
))
|
|
167
167
|
|
|
168
168
|
istek = await self.httpx.post(
|
|
169
169
|
url = "https://cehennempass.pw/process_quality_selection.php",
|
|
@@ -176,11 +176,11 @@ class HDFilmCehennemi(PluginBase):
|
|
|
176
176
|
data = {"video_id": video_id, "selected_quality": "high"},
|
|
177
177
|
)
|
|
178
178
|
if video_url := istek.json().get("download_link"):
|
|
179
|
-
results.append(
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
179
|
+
results.append(ExtractResult(
|
|
180
|
+
url = self.fix_url(video_url),
|
|
181
|
+
name = "Yüksek Kalite",
|
|
182
|
+
referer = f"https://cehennempass.pw/download/{video_id}"
|
|
183
|
+
))
|
|
184
184
|
|
|
185
185
|
return results
|
|
186
186
|
|
|
@@ -246,14 +246,14 @@ class HDFilmCehennemi(PluginBase):
|
|
|
246
246
|
except Exception:
|
|
247
247
|
pass
|
|
248
248
|
|
|
249
|
-
return [
|
|
250
|
-
|
|
251
|
-
|
|
252
|
-
|
|
253
|
-
|
|
254
|
-
|
|
249
|
+
return [ExtractResult(
|
|
250
|
+
url = video_url,
|
|
251
|
+
name = source,
|
|
252
|
+
referer = url,
|
|
253
|
+
subtitles = subtitles
|
|
254
|
+
)]
|
|
255
255
|
|
|
256
|
-
async def load_links(self, url: str) -> list[
|
|
256
|
+
async def load_links(self, url: str) -> list[ExtractResult]:
|
|
257
257
|
istek = await self.httpx.get(url)
|
|
258
258
|
secici = Selector(istek.text)
|
|
259
259
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
2
|
|
|
3
|
-
from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo
|
|
3
|
+
from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo, ExtractResult
|
|
4
4
|
from parsel import Selector
|
|
5
5
|
|
|
6
6
|
class JetFilmizle(PluginBase):
|
|
@@ -96,7 +96,7 @@ class JetFilmizle(PluginBase):
|
|
|
96
96
|
actors = actors
|
|
97
97
|
)
|
|
98
98
|
|
|
99
|
-
async def load_links(self, url: str) -> list[
|
|
99
|
+
async def load_links(self, url: str) -> list[ExtractResult]:
|
|
100
100
|
istek = await self.httpx.get(url)
|
|
101
101
|
secici = Selector(istek.text)
|
|
102
102
|
|