KekikStream 1.3.3__py3-none-any.whl → 1.7.1__py3-none-any.whl
This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
- KekikStream/CLI/pypi_kontrol.py +6 -6
- KekikStream/Core/Extractor/ExtractorBase.py +6 -11
- KekikStream/Core/Extractor/ExtractorModels.py +2 -2
- KekikStream/Core/Media/MediaHandler.py +9 -6
- KekikStream/Core/Plugin/PluginBase.py +35 -21
- KekikStream/Core/Plugin/PluginModels.py +1 -0
- KekikStream/Extractors/CloseLoad.py +8 -27
- KekikStream/Extractors/ContentX.py +6 -4
- KekikStream/Extractors/MailRu.py +4 -5
- KekikStream/Extractors/MixPlayHD.py +3 -2
- KekikStream/Extractors/MolyStream.py +23 -5
- KekikStream/Extractors/Odnoklassniki.py +14 -9
- KekikStream/Extractors/PeaceMakerst.py +5 -4
- KekikStream/Extractors/PixelDrain.py +2 -2
- KekikStream/Extractors/RapidVid.py +33 -15
- KekikStream/Extractors/SibNet.py +3 -3
- KekikStream/Extractors/Sobreatsesuyp.py +5 -4
- KekikStream/Extractors/TRsTX.py +5 -4
- KekikStream/Extractors/TauVideo.py +3 -2
- KekikStream/Extractors/TurboImgz.py +3 -2
- KekikStream/Extractors/VidMoly.py +23 -21
- KekikStream/Extractors/VidMoxy.py +3 -3
- KekikStream/Extractors/VideoSeyred.py +4 -3
- KekikStream/Plugins/DiziBox.py +46 -29
- KekikStream/Plugins/DiziPal.py +246 -0
- KekikStream/Plugins/DiziYou.py +22 -20
- KekikStream/Plugins/Dizilla.py +62 -48
- KekikStream/Plugins/FilmMakinesi.py +65 -54
- KekikStream/Plugins/FilmModu.py +138 -0
- KekikStream/Plugins/FullHDFilmizlesene.py +44 -39
- KekikStream/Plugins/HDFilmCehennemi.py +98 -74
- KekikStream/Plugins/JetFilmizle.py +22 -14
- KekikStream/Plugins/RecTV.py +43 -35
- KekikStream/Plugins/SezonlukDizi.py +52 -20
- KekikStream/Plugins/SineWix.py +43 -30
- KekikStream/Plugins/UgurFilm.py +50 -15
- KekikStream/__init__.py +285 -318
- KekikStream/requirements.txt +1 -1
- {kekikstream-1.3.3.dist-info → kekikstream-1.7.1.dist-info}/METADATA +11 -4
- kekikstream-1.7.1.dist-info/RECORD +63 -0
- {kekikstream-1.3.3.dist-info → kekikstream-1.7.1.dist-info}/WHEEL +1 -1
- KekikStream/Helpers/Unpack.py +0 -75
- KekikStream/Plugins/Shorten.py +0 -225
- kekikstream-1.3.3.dist-info/RECORD +0 -63
- {kekikstream-1.3.3.dist-info → kekikstream-1.7.1.dist-info}/entry_points.txt +0 -0
- {kekikstream-1.3.3.dist-info → kekikstream-1.7.1.dist-info/licenses}/LICENSE +0 -0
- {kekikstream-1.3.3.dist-info → kekikstream-1.7.1.dist-info}/top_level.txt +0 -0
KekikStream/CLI/pypi_kontrol.py
CHANGED
|
@@ -1,16 +1,16 @@
|
|
|
1
1
|
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
2
|
|
|
3
|
-
from .
|
|
4
|
-
from rich.panel
|
|
5
|
-
from
|
|
6
|
-
from requests
|
|
7
|
-
from subprocess
|
|
3
|
+
from . import konsol
|
|
4
|
+
from rich.panel import Panel
|
|
5
|
+
from importlib import metadata
|
|
6
|
+
from requests import get
|
|
7
|
+
from subprocess import check_call
|
|
8
8
|
import sys
|
|
9
9
|
|
|
10
10
|
def pypi_kontrol_guncelle(paket_adi: str):
|
|
11
11
|
try:
|
|
12
12
|
konsol.print(f"[bold cyan] {paket_adi} Güncellemesi kontrol ediliyor...[/bold cyan]")
|
|
13
|
-
mevcut_surum =
|
|
13
|
+
mevcut_surum = metadata.version(paket_adi)
|
|
14
14
|
konsol.print(Panel(f"[cyan]Yüklü sürüm:[/cyan] [bold yellow]{mevcut_surum}[/bold yellow]"))
|
|
15
15
|
|
|
16
16
|
istek = get(f"https://pypi.org/pypi/{paket_adi}/json")
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
2
|
|
|
3
3
|
from abc import ABC, abstractmethod
|
|
4
|
-
from
|
|
4
|
+
from curl_cffi import AsyncSession
|
|
5
5
|
from cloudscraper import CloudScraper
|
|
6
6
|
from typing import Optional
|
|
7
7
|
from .ExtractorModels import ExtractResult
|
|
@@ -14,15 +14,10 @@ class ExtractorBase(ABC):
|
|
|
14
14
|
|
|
15
15
|
def __init__(self):
|
|
16
16
|
# HTTP istekleri için oturum oluştur
|
|
17
|
-
self.
|
|
18
|
-
|
|
19
|
-
|
|
20
|
-
|
|
21
|
-
},
|
|
22
|
-
timeout = Timeout(10.0)
|
|
23
|
-
)
|
|
24
|
-
# CloudFlare korumalı siteler için scraper ayarla
|
|
25
|
-
self.cloudscraper = CloudScraper()
|
|
17
|
+
self.cffi = AsyncSession(impersonate="firefox135")
|
|
18
|
+
self.cloudscraper = CloudScraper()
|
|
19
|
+
self.cffi.cookies.update(self.cloudscraper.cookies)
|
|
20
|
+
self.cffi.headers.update({"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 15.7; rv:135.0) Gecko/20100101 Firefox/135.0"})
|
|
26
21
|
|
|
27
22
|
def can_handle_url(self, url: str) -> bool:
|
|
28
23
|
# URL'nin bu çıkarıcı tarafından işlenip işlenemeyeceğini kontrol et
|
|
@@ -35,7 +30,7 @@ class ExtractorBase(ABC):
|
|
|
35
30
|
|
|
36
31
|
async def close(self):
|
|
37
32
|
# HTTP oturumunu güvenli bir şekilde kapat
|
|
38
|
-
await self.
|
|
33
|
+
await self.cffi.close()
|
|
39
34
|
|
|
40
35
|
def fix_url(self, url: str) -> str:
|
|
41
36
|
# Eksik URL'leri düzelt ve tam URL formatına çevir
|
|
@@ -34,11 +34,11 @@ class MediaHandler:
|
|
|
34
34
|
if "Cookie" in self.headers or extract_data.subtitles:
|
|
35
35
|
return self.play_with_mpv(extract_data)
|
|
36
36
|
|
|
37
|
-
return self.play_with_vlc(extract_data)
|
|
37
|
+
return self.play_with_vlc(extract_data) or self.play_with_mpv(extract_data)
|
|
38
38
|
|
|
39
39
|
def play_with_vlc(self, extract_data: ExtractResult):
|
|
40
40
|
konsol.log(f"[yellow][»] VLC ile Oynatılıyor : {extract_data.url}")
|
|
41
|
-
konsol.print(self.headers)
|
|
41
|
+
# konsol.print(self.headers)
|
|
42
42
|
try:
|
|
43
43
|
vlc_command = ["vlc", "--quiet"]
|
|
44
44
|
|
|
@@ -62,16 +62,19 @@ class MediaHandler:
|
|
|
62
62
|
with open(os.devnull, "w") as devnull:
|
|
63
63
|
subprocess.run(vlc_command, stdout=devnull, stderr=devnull, check=True)
|
|
64
64
|
|
|
65
|
+
return True
|
|
65
66
|
except subprocess.CalledProcessError as hata:
|
|
66
67
|
konsol.print(f"[red]VLC oynatma hatası: {hata}[/red]")
|
|
67
68
|
konsol.print({"title": self.title, "url": extract_data.url, "headers": self.headers})
|
|
69
|
+
return False
|
|
68
70
|
except FileNotFoundError:
|
|
69
71
|
konsol.print("[red]VLC bulunamadı! VLC kurulu olduğundan emin olun.[/red]")
|
|
70
|
-
konsol.print({"title": self.title, "url": extract_data.url, "headers": self.headers})
|
|
72
|
+
# konsol.print({"title": self.title, "url": extract_data.url, "headers": self.headers})
|
|
73
|
+
return False
|
|
71
74
|
|
|
72
75
|
def play_with_mpv(self, extract_data: ExtractResult):
|
|
73
76
|
konsol.log(f"[yellow][»] MPV ile Oynatılıyor : {extract_data.url}")
|
|
74
|
-
konsol.print(self.headers)
|
|
77
|
+
# konsol.print(self.headers)
|
|
75
78
|
try:
|
|
76
79
|
mpv_command = ["mpv"]
|
|
77
80
|
|
|
@@ -98,7 +101,7 @@ class MediaHandler:
|
|
|
98
101
|
|
|
99
102
|
def play_with_ytdlp(self, extract_data: ExtractResult):
|
|
100
103
|
konsol.log(f"[yellow][»] yt-dlp ile Oynatılıyor : {extract_data.url}")
|
|
101
|
-
konsol.print(self.headers)
|
|
104
|
+
# konsol.print(self.headers)
|
|
102
105
|
try:
|
|
103
106
|
ytdlp_command = ["yt-dlp", "--quiet", "--no-warnings"]
|
|
104
107
|
|
|
@@ -131,7 +134,7 @@ class MediaHandler:
|
|
|
131
134
|
|
|
132
135
|
def play_with_android_mxplayer(self, extract_data: ExtractResult):
|
|
133
136
|
konsol.log(f"[yellow][»] MxPlayer ile Oynatılıyor : {extract_data.url}")
|
|
134
|
-
konsol.print(self.headers)
|
|
137
|
+
# konsol.print(self.headers)
|
|
135
138
|
paketler = [
|
|
136
139
|
"com.mxtech.videoplayer.ad/.ActivityScreen", # Free sürüm
|
|
137
140
|
"com.mxtech.videoplayer.pro/.ActivityScreen" # Pro sürüm
|
|
@@ -1,11 +1,12 @@
|
|
|
1
1
|
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
2
|
|
|
3
|
-
from abc
|
|
4
|
-
from
|
|
5
|
-
from cloudscraper
|
|
6
|
-
from .PluginModels
|
|
7
|
-
from ..Media.MediaHandler
|
|
8
|
-
from
|
|
3
|
+
from abc import ABC, abstractmethod
|
|
4
|
+
from curl_cffi import AsyncSession
|
|
5
|
+
from cloudscraper import CloudScraper
|
|
6
|
+
from .PluginModels import MainPageResult, SearchResult, MovieInfo
|
|
7
|
+
from ..Media.MediaHandler import MediaHandler
|
|
8
|
+
from ..Extractor.ExtractorManager import ExtractorManager
|
|
9
|
+
from urllib.parse import urljoin
|
|
9
10
|
import re
|
|
10
11
|
|
|
11
12
|
class PluginBase(ABC):
|
|
@@ -17,25 +18,18 @@ class PluginBase(ABC):
|
|
|
17
18
|
|
|
18
19
|
main_page = {}
|
|
19
20
|
|
|
20
|
-
_data = {}
|
|
21
|
-
|
|
22
21
|
async def url_update(self, new_url: str):
|
|
23
22
|
self.favicon = self.favicon.replace(self.main_url, new_url)
|
|
24
23
|
self.main_page = {url.replace(self.main_url, new_url): category for url, category in self.main_page.items()}
|
|
25
24
|
self.main_url = new_url
|
|
26
25
|
|
|
27
26
|
def __init__(self):
|
|
28
|
-
self.
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
|
|
32
|
-
},
|
|
33
|
-
timeout = Timeout(10.0),
|
|
34
|
-
)
|
|
27
|
+
self.cffi = AsyncSession(impersonate="firefox135")
|
|
28
|
+
self.cloudscraper = CloudScraper()
|
|
29
|
+
self.cffi.cookies.update(self.cloudscraper.cookies)
|
|
30
|
+
self.cffi.headers.update({"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 15.7; rv:135.0) Gecko/20100101 Firefox/135.0"})
|
|
35
31
|
self.media_handler = MediaHandler()
|
|
36
|
-
self.
|
|
37
|
-
self.httpx.headers.update(self.cloudscraper.headers)
|
|
38
|
-
self.httpx.cookies.update(self.cloudscraper.cookies)
|
|
32
|
+
self.ex_manager = ExtractorManager()
|
|
39
33
|
|
|
40
34
|
# @abstractmethod
|
|
41
35
|
# async def get_main_page(self, page: int, url: str, category: str) -> list[MainPageResult]:
|
|
@@ -53,12 +47,32 @@ class PluginBase(ABC):
|
|
|
53
47
|
pass
|
|
54
48
|
|
|
55
49
|
@abstractmethod
|
|
56
|
-
async def load_links(self, url: str) -> list[
|
|
57
|
-
"""
|
|
50
|
+
async def load_links(self, url: str) -> list[dict]:
|
|
51
|
+
"""
|
|
52
|
+
Bir medya öğesi için oynatma bağlantılarını döndürür.
|
|
53
|
+
|
|
54
|
+
Args:
|
|
55
|
+
url: Medya URL'si
|
|
56
|
+
|
|
57
|
+
Returns:
|
|
58
|
+
Dictionary listesi, her biri şu alanları içerir:
|
|
59
|
+
- url (str, zorunlu): Video URL'si
|
|
60
|
+
- name (str, zorunlu): Gösterim adı (tüm bilgileri içerir)
|
|
61
|
+
- referer (str, opsiyonel): Referer header
|
|
62
|
+
- subtitles (list, opsiyonel): Altyazı listesi
|
|
63
|
+
|
|
64
|
+
Example:
|
|
65
|
+
[
|
|
66
|
+
{
|
|
67
|
+
"url": "https://example.com/video.m3u8",
|
|
68
|
+
"name": "HDFilmCehennemi | 1080p TR Dublaj"
|
|
69
|
+
}
|
|
70
|
+
]
|
|
71
|
+
"""
|
|
58
72
|
pass
|
|
59
73
|
|
|
60
74
|
async def close(self):
|
|
61
|
-
await self.
|
|
75
|
+
await self.cffi.close()
|
|
62
76
|
|
|
63
77
|
def fix_url(self, url: str) -> str:
|
|
64
78
|
if not url:
|
|
@@ -1,46 +1,27 @@
|
|
|
1
1
|
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
2
|
|
|
3
|
-
from KekikStream.Core
|
|
4
|
-
from
|
|
5
|
-
import re
|
|
6
|
-
|
|
7
|
-
def get_m3u_link(data: str) -> str:
|
|
8
|
-
first = base64.b64decode(data)
|
|
9
|
-
first_reversed = first[::-1]
|
|
10
|
-
|
|
11
|
-
second = base64.b64decode(first_reversed)
|
|
12
|
-
|
|
13
|
-
parts = second.decode('utf-8').split("|")
|
|
14
|
-
if len(parts) < 2:
|
|
15
|
-
raise ValueError("Decoded data has an unexpected format.")
|
|
16
|
-
|
|
17
|
-
return parts[1]
|
|
18
|
-
|
|
19
|
-
def extract_data(raw_script: str) -> str:
|
|
20
|
-
pattern = re.compile(r'return result\}var .*?=.*?\("(.*?)"\)')
|
|
21
|
-
if match := pattern.search(raw_script):
|
|
22
|
-
return match[1]
|
|
23
|
-
else:
|
|
24
|
-
raise Exception("data not found")
|
|
3
|
+
from KekikStream.Core import ExtractorBase, ExtractResult
|
|
4
|
+
from Kekik.Sifreleme import Packer, StreamDecoder
|
|
5
|
+
import re
|
|
25
6
|
|
|
26
7
|
class CloseLoadExtractor(ExtractorBase):
|
|
27
8
|
name = "CloseLoad"
|
|
28
|
-
main_url = "https://closeload.filmmakinesi.
|
|
9
|
+
main_url = "https://closeload.filmmakinesi.sh"
|
|
29
10
|
|
|
30
11
|
async def extract(self, url, referer=None) -> ExtractResult:
|
|
31
12
|
if referer:
|
|
32
|
-
self.
|
|
13
|
+
self.cffi.headers.update({"Referer": referer})
|
|
33
14
|
|
|
34
|
-
istek = await self.
|
|
15
|
+
istek = await self.cffi.get(url)
|
|
35
16
|
istek.raise_for_status()
|
|
36
17
|
|
|
37
18
|
eval_func = re.compile(r'\s*(eval\(function[\s\S].*)\s*').findall(istek.text)[0]
|
|
38
|
-
m3u_link =
|
|
19
|
+
m3u_link = StreamDecoder.extract_stream_url(Packer.unpack(eval_func))
|
|
39
20
|
|
|
40
|
-
await self.close()
|
|
41
21
|
return ExtractResult(
|
|
42
22
|
name = self.name,
|
|
43
23
|
url = m3u_link,
|
|
44
24
|
referer = self.main_url,
|
|
25
|
+
headers = {},
|
|
45
26
|
subtitles = []
|
|
46
27
|
)
|
|
@@ -9,9 +9,9 @@ class ContentX(ExtractorBase):
|
|
|
9
9
|
|
|
10
10
|
async def extract(self, url, referer=None) -> list[ExtractResult]:
|
|
11
11
|
if referer:
|
|
12
|
-
self.
|
|
12
|
+
self.cffi.headers.update({"Referer": referer})
|
|
13
13
|
|
|
14
|
-
istek = await self.
|
|
14
|
+
istek = await self.cffi.get(url)
|
|
15
15
|
istek.raise_for_status()
|
|
16
16
|
i_source = istek.text
|
|
17
17
|
|
|
@@ -39,7 +39,7 @@ class ContentX(ExtractorBase):
|
|
|
39
39
|
)
|
|
40
40
|
)
|
|
41
41
|
|
|
42
|
-
vid_source_request = await self.
|
|
42
|
+
vid_source_request = await self.cffi.get(f"{self.main_url}/source2.php?v={i_extract_value}", headers={"Referer": referer or self.main_url})
|
|
43
43
|
vid_source_request.raise_for_status()
|
|
44
44
|
|
|
45
45
|
vid_source = vid_source_request.text
|
|
@@ -53,13 +53,14 @@ class ContentX(ExtractorBase):
|
|
|
53
53
|
name = self.name,
|
|
54
54
|
url = m3u_link,
|
|
55
55
|
referer = url,
|
|
56
|
+
headers = {},
|
|
56
57
|
subtitles = subtitles
|
|
57
58
|
)
|
|
58
59
|
]
|
|
59
60
|
|
|
60
61
|
if i_dublaj := re.search(r',\"([^"]+)\",\"Türkçe"', i_source):
|
|
61
62
|
dublaj_value = i_dublaj[1]
|
|
62
|
-
dublaj_source_request = await self.
|
|
63
|
+
dublaj_source_request = await self.cffi.get(f"{self.main_url}/source2.php?v={dublaj_value}", headers={"Referer": referer or self.main_url})
|
|
63
64
|
dublaj_source_request.raise_for_status()
|
|
64
65
|
|
|
65
66
|
dublaj_source = dublaj_source_request.text
|
|
@@ -73,6 +74,7 @@ class ContentX(ExtractorBase):
|
|
|
73
74
|
name = f"{self.name} Türkçe Dublaj",
|
|
74
75
|
url = dublaj_link,
|
|
75
76
|
referer = url,
|
|
77
|
+
headers = {},
|
|
76
78
|
subtitles = []
|
|
77
79
|
)
|
|
78
80
|
)
|
KekikStream/Extractors/MailRu.py
CHANGED
|
@@ -11,9 +11,9 @@ class MailRuExtractor(ExtractorBase):
|
|
|
11
11
|
video_meta_url = f"{self.main_url}/+/video/meta/{vid_id}"
|
|
12
12
|
|
|
13
13
|
if referer:
|
|
14
|
-
self.
|
|
14
|
+
self.cffi.headers.update({"Referer": referer})
|
|
15
15
|
|
|
16
|
-
istek = await self.
|
|
16
|
+
istek = await self.cffi.get(video_meta_url)
|
|
17
17
|
istek.raise_for_status()
|
|
18
18
|
|
|
19
19
|
video_key = istek.cookies.get("video_key")
|
|
@@ -30,11 +30,10 @@ class MailRuExtractor(ExtractorBase):
|
|
|
30
30
|
if video_url.startswith("//"):
|
|
31
31
|
video_url = f"https:{video_url}"
|
|
32
32
|
|
|
33
|
-
await self.close()
|
|
34
33
|
return ExtractResult(
|
|
35
34
|
name = self.name,
|
|
36
35
|
url = video_url,
|
|
37
36
|
referer = self.main_url,
|
|
38
|
-
|
|
39
|
-
|
|
37
|
+
headers = {"Cookie": f"video_key={video_key}"},
|
|
38
|
+
subtitles = []
|
|
40
39
|
)
|
|
@@ -10,9 +10,9 @@ class MixPlayHD(ExtractorBase):
|
|
|
10
10
|
|
|
11
11
|
async def extract(self, url, referer=None) -> ExtractResult:
|
|
12
12
|
if referer:
|
|
13
|
-
self.
|
|
13
|
+
self.cffi.headers.update({"Referer": referer})
|
|
14
14
|
|
|
15
|
-
istek = await self.
|
|
15
|
+
istek = await self.cffi.get(url)
|
|
16
16
|
istek.raise_for_status()
|
|
17
17
|
|
|
18
18
|
be_player_match = re.search(r"bePlayer\('([^']+)',\s*'(\{[^\}]+\})'\);", istek.text)
|
|
@@ -36,6 +36,7 @@ class MixPlayHD(ExtractorBase):
|
|
|
36
36
|
name = self.name,
|
|
37
37
|
url = video_url_match[1],
|
|
38
38
|
referer = self.main_url,
|
|
39
|
+
headers = {},
|
|
39
40
|
subtitles = []
|
|
40
41
|
)
|
|
41
42
|
else:
|
|
@@ -1,16 +1,34 @@
|
|
|
1
1
|
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
2
|
|
|
3
|
-
from KekikStream.Core import ExtractorBase, ExtractResult
|
|
3
|
+
from KekikStream.Core import ExtractorBase, ExtractResult, Subtitle
|
|
4
|
+
from parsel import Selector
|
|
5
|
+
import re
|
|
4
6
|
|
|
5
7
|
class MolyStream(ExtractorBase):
|
|
6
8
|
name = "MolyStream"
|
|
7
9
|
main_url = "https://dbx.molystream.org"
|
|
8
10
|
|
|
9
11
|
async def extract(self, url, referer=None) -> ExtractResult:
|
|
12
|
+
if "doctype html" in url:
|
|
13
|
+
secici = Selector(url)
|
|
14
|
+
video = secici.css("video#sheplayer source::attr(src)").get()
|
|
15
|
+
else:
|
|
16
|
+
video = url
|
|
17
|
+
|
|
18
|
+
matches = re.findall(
|
|
19
|
+
pattern = r"addSrtFile\(['\"]([^'\"]+\.srt)['\"]\s*,\s*['\"][a-z]{2}['\"]\s*,\s*['\"]([^'\"]+)['\"]",
|
|
20
|
+
string = url
|
|
21
|
+
)
|
|
22
|
+
|
|
23
|
+
subtitles = [
|
|
24
|
+
Subtitle(name = name, url = self.fix_url(url))
|
|
25
|
+
for url, name in matches
|
|
26
|
+
]
|
|
27
|
+
|
|
10
28
|
return ExtractResult(
|
|
11
29
|
name = self.name,
|
|
12
|
-
url =
|
|
13
|
-
referer =
|
|
30
|
+
url = video,
|
|
31
|
+
referer = video.replace("/sheila", ""),
|
|
14
32
|
headers = {"User-Agent": "Mozilla/5.0 (X11; Linux x86_64; rv:101.0) Gecko/20100101 Firefox/101.0"},
|
|
15
|
-
subtitles =
|
|
16
|
-
)
|
|
33
|
+
subtitles = subtitles
|
|
34
|
+
)
|
|
@@ -8,16 +8,20 @@ class Odnoklassniki(ExtractorBase):
|
|
|
8
8
|
main_url = "https://odnoklassniki.ru"
|
|
9
9
|
|
|
10
10
|
async def extract(self, url, referer=None) -> ExtractResult:
|
|
11
|
-
if referer:
|
|
12
|
-
self.httpx.headers.update({"Referer": referer})
|
|
13
|
-
|
|
14
|
-
self.httpx.headers.update({
|
|
15
|
-
"User-Agent": "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Mobile Safari/537.36"
|
|
16
|
-
})
|
|
17
|
-
|
|
18
11
|
if "/video/" in url:
|
|
19
12
|
url = url.replace("/video/", "/videoembed/")
|
|
20
13
|
|
|
14
|
+
headers = {
|
|
15
|
+
"Accept" : "*/*",
|
|
16
|
+
"Connection" : "keep-alive",
|
|
17
|
+
"Sec-Fetch-Dest" : "empty",
|
|
18
|
+
"Sec-Fetch-Mode" : "cors",
|
|
19
|
+
"Sec-Fetch-Site" : "cross-site",
|
|
20
|
+
"Origin" : self.main_url,
|
|
21
|
+
"User-Agent" : "Mozilla/5.0 (X11; Linux x86_64; rv:101.0) Gecko/20100101 Firefox/101.0",
|
|
22
|
+
}
|
|
23
|
+
self.cffi.headers.update(headers)
|
|
24
|
+
|
|
21
25
|
try:
|
|
22
26
|
istek = await self.fetch_with_redirects(url)
|
|
23
27
|
istek.raise_for_status()
|
|
@@ -80,7 +84,8 @@ class Odnoklassniki(ExtractorBase):
|
|
|
80
84
|
return ExtractResult(
|
|
81
85
|
name = self.name,
|
|
82
86
|
url = best_video,
|
|
83
|
-
referer =
|
|
87
|
+
referer = referer,
|
|
88
|
+
headers = headers,
|
|
84
89
|
subtitles = []
|
|
85
90
|
)
|
|
86
91
|
|
|
@@ -88,7 +93,7 @@ class Odnoklassniki(ExtractorBase):
|
|
|
88
93
|
"""Yönlendirmeleri takip eden bir fonksiyon"""
|
|
89
94
|
redirects = 0
|
|
90
95
|
while redirects < max_redirects:
|
|
91
|
-
istek = await self.
|
|
96
|
+
istek = await self.cffi.get(url, allow_redirects=False)
|
|
92
97
|
|
|
93
98
|
if istek.status_code not in [301, 302]:
|
|
94
99
|
break # Yönlendirme yoksa çık
|
|
@@ -9,14 +9,14 @@ class PeaceMakerst(ExtractorBase):
|
|
|
9
9
|
|
|
10
10
|
async def extract(self, url, referer=None) -> ExtractResult:
|
|
11
11
|
if referer:
|
|
12
|
-
self.
|
|
12
|
+
self.cffi.headers.update({"Referer": referer})
|
|
13
13
|
|
|
14
|
-
self.
|
|
14
|
+
self.cffi.headers.update({
|
|
15
15
|
"Content-Type" : "application/x-www-form-urlencoded; charset=UTF-8",
|
|
16
16
|
"X-Requested-With" : "XMLHttpRequest"
|
|
17
17
|
})
|
|
18
18
|
|
|
19
|
-
response = await self.
|
|
19
|
+
response = await self.cffi.post(
|
|
20
20
|
url = f"{url}?do=getVideo",
|
|
21
21
|
data = {
|
|
22
22
|
"hash" : url.split("video/")[-1],
|
|
@@ -33,7 +33,7 @@ class PeaceMakerst(ExtractorBase):
|
|
|
33
33
|
teve2_id = re.search(r"teve2\.com\.tr\\\/embed\\\/(\d+)", response_text)[1]
|
|
34
34
|
teve2_url = f"https://www.teve2.com.tr/action/media/{teve2_id}"
|
|
35
35
|
|
|
36
|
-
teve2_response = await self.
|
|
36
|
+
teve2_response = await self.cffi.get(teve2_url, headers={"Referer": f"https://www.teve2.com.tr/embed/{teve2_id}"})
|
|
37
37
|
teve2_response.raise_for_status()
|
|
38
38
|
teve2_json = teve2_response.json()
|
|
39
39
|
|
|
@@ -53,5 +53,6 @@ class PeaceMakerst(ExtractorBase):
|
|
|
53
53
|
name = self.name,
|
|
54
54
|
url = m3u_link,
|
|
55
55
|
referer = url,
|
|
56
|
+
headers = {},
|
|
56
57
|
subtitles = []
|
|
57
58
|
)
|
|
@@ -9,7 +9,7 @@ class PixelDrain(ExtractorBase):
|
|
|
9
9
|
|
|
10
10
|
async def extract(self, url, referer=None) -> ExtractResult:
|
|
11
11
|
if referer:
|
|
12
|
-
self.
|
|
12
|
+
self.cffi.headers.update({"Referer": referer})
|
|
13
13
|
|
|
14
14
|
pixel_id_match = re.search(r"/u/([^/?]+)|([^\/]+)(?=\?download)", url)
|
|
15
15
|
if not pixel_id_match:
|
|
@@ -19,10 +19,10 @@ class PixelDrain(ExtractorBase):
|
|
|
19
19
|
download_link = f"{self.main_url}/api/file/{pixel_id}?download"
|
|
20
20
|
referer_link = f"{self.main_url}/u/{pixel_id}?download"
|
|
21
21
|
|
|
22
|
-
await self.close()
|
|
23
22
|
return ExtractResult(
|
|
24
23
|
name = f"{self.name} - {pixel_id}",
|
|
25
24
|
url = download_link,
|
|
26
25
|
referer = referer_link,
|
|
26
|
+
headers = {},
|
|
27
27
|
subtitles = []
|
|
28
28
|
)
|
|
@@ -2,7 +2,7 @@
|
|
|
2
2
|
|
|
3
3
|
from KekikStream.Core import ExtractorBase, ExtractResult, Subtitle
|
|
4
4
|
from Kekik.Sifreleme import Packer, HexCodec
|
|
5
|
-
import re
|
|
5
|
+
import re, base64
|
|
6
6
|
|
|
7
7
|
class RapidVid(ExtractorBase):
|
|
8
8
|
name = "RapidVid"
|
|
@@ -10,9 +10,9 @@ class RapidVid(ExtractorBase):
|
|
|
10
10
|
|
|
11
11
|
async def extract(self, url, referer=None) -> ExtractResult:
|
|
12
12
|
if referer:
|
|
13
|
-
self.
|
|
13
|
+
self.cffi.headers.update({"Referer": referer})
|
|
14
14
|
|
|
15
|
-
istek = await self.
|
|
15
|
+
istek = await self.cffi.get(url)
|
|
16
16
|
istek.raise_for_status()
|
|
17
17
|
|
|
18
18
|
subtitles = []
|
|
@@ -37,24 +37,42 @@ class RapidVid(ExtractorBase):
|
|
|
37
37
|
escaped_hex = extracted_value[1]
|
|
38
38
|
decoded_url = HexCodec.decode(escaped_hex)
|
|
39
39
|
else:
|
|
40
|
-
|
|
41
|
-
if not
|
|
42
|
-
raise ValueError("
|
|
40
|
+
av_encoded = re.search(r"av\('([^']+)'\)", istek.text)
|
|
41
|
+
if not av_encoded:
|
|
42
|
+
raise ValueError("AV encoding not found.")
|
|
43
43
|
|
|
44
|
-
|
|
45
|
-
extracted_value = re.search(r'file":"(.*)","label', unpacked_jwsetup)
|
|
46
|
-
if not extracted_value:
|
|
47
|
-
raise ValueError("File URL not found in unpacked JWPlayer setup.")
|
|
48
|
-
|
|
49
|
-
escaped_hex = extracted_value[1].replace("\\\\x", "")
|
|
50
|
-
decoded_url = bytes.fromhex(escaped_hex).decode("utf-8")
|
|
44
|
+
decoded_url = self.decode_secret(av_encoded[1])
|
|
51
45
|
except Exception as hata:
|
|
52
46
|
raise RuntimeError(f"Extraction failed: {hata}") from hata
|
|
53
47
|
|
|
54
|
-
await self.close()
|
|
55
48
|
return ExtractResult(
|
|
56
49
|
name = self.name,
|
|
57
50
|
url = decoded_url,
|
|
58
51
|
referer = self.main_url,
|
|
52
|
+
headers = {},
|
|
59
53
|
subtitles = subtitles
|
|
60
|
-
)
|
|
54
|
+
)
|
|
55
|
+
|
|
56
|
+
def decode_secret(self, encoded_string: str) -> str:
|
|
57
|
+
# 1. Base64 ile şifrelenmiş string ters çevrilmiş, önce geri çeviriyoruz
|
|
58
|
+
reversed_input = encoded_string[::-1]
|
|
59
|
+
|
|
60
|
+
# 2. İlk base64 çözme işlemi
|
|
61
|
+
decoded_once = base64.b64decode(reversed_input).decode("utf-8")
|
|
62
|
+
|
|
63
|
+
decrypted_chars = []
|
|
64
|
+
key = "K9L"
|
|
65
|
+
|
|
66
|
+
# 3. Key'e göre karakter kaydırma geri alınıyor
|
|
67
|
+
for index, encoded_char in enumerate(decoded_once):
|
|
68
|
+
key_char = key[index % len(key)]
|
|
69
|
+
offset = (ord(key_char) % 5) + 1 # Her karakter için dinamik offset
|
|
70
|
+
|
|
71
|
+
original_char_code = ord(encoded_char) - offset
|
|
72
|
+
decrypted_chars.append(chr(original_char_code))
|
|
73
|
+
|
|
74
|
+
# 4. Karakterleri birleştirip ikinci base64 çözme işlemini yapıyoruz
|
|
75
|
+
intermediate_string = "".join(decrypted_chars)
|
|
76
|
+
final_decoded_bytes = base64.b64decode(intermediate_string)
|
|
77
|
+
|
|
78
|
+
return final_decoded_bytes.decode("utf-8")
|
KekikStream/Extractors/SibNet.py
CHANGED
|
@@ -9,9 +9,9 @@ class SibNet(ExtractorBase):
|
|
|
9
9
|
|
|
10
10
|
async def extract(self, url, referer=None) -> ExtractResult:
|
|
11
11
|
if referer:
|
|
12
|
-
self.
|
|
12
|
+
self.cffi.headers.update({"Referer": referer})
|
|
13
13
|
|
|
14
|
-
response = await self.
|
|
14
|
+
response = await self.cffi.get(url)
|
|
15
15
|
response.raise_for_status()
|
|
16
16
|
|
|
17
17
|
match = re.search(r'player\.src\(\[\{src: \"([^\"]+)\"', response.text)
|
|
@@ -20,10 +20,10 @@ class SibNet(ExtractorBase):
|
|
|
20
20
|
|
|
21
21
|
m3u_link = f"{self.main_url}{match[1]}"
|
|
22
22
|
|
|
23
|
-
await self.close()
|
|
24
23
|
return ExtractResult(
|
|
25
24
|
name = self.name,
|
|
26
25
|
url = m3u_link,
|
|
27
26
|
referer = url,
|
|
27
|
+
headers = {},
|
|
28
28
|
subtitles = []
|
|
29
29
|
)
|
|
@@ -9,9 +9,9 @@ class Sobreatsesuyp(ExtractorBase):
|
|
|
9
9
|
|
|
10
10
|
async def extract(self, url, referer=None) -> ExtractResult:
|
|
11
11
|
if referer:
|
|
12
|
-
self.
|
|
12
|
+
self.cffi.headers.update({"Referer": referer})
|
|
13
13
|
|
|
14
|
-
istek = await self.
|
|
14
|
+
istek = await self.cffi.get(url)
|
|
15
15
|
istek.raise_for_status()
|
|
16
16
|
|
|
17
17
|
file_match = re.search(r'file\":\"([^\"]+)', istek.text)
|
|
@@ -21,7 +21,7 @@ class Sobreatsesuyp(ExtractorBase):
|
|
|
21
21
|
file_path = file_match[1].replace("\\", "")
|
|
22
22
|
post_link = f"{self.main_url}/{file_path}"
|
|
23
23
|
|
|
24
|
-
post_istek = await self.
|
|
24
|
+
post_istek = await self.cffi.post(post_link)
|
|
25
25
|
post_istek.raise_for_status()
|
|
26
26
|
|
|
27
27
|
try:
|
|
@@ -41,7 +41,7 @@ class Sobreatsesuyp(ExtractorBase):
|
|
|
41
41
|
continue
|
|
42
42
|
|
|
43
43
|
playlist_url = f"{self.main_url}/playlist/{file.lstrip('/')}.txt"
|
|
44
|
-
playlist_request = await self.
|
|
44
|
+
playlist_request = await self.cffi.post(playlist_url, headers={"Referer": referer or self.main_url})
|
|
45
45
|
playlist_request.raise_for_status()
|
|
46
46
|
|
|
47
47
|
all_results.append(
|
|
@@ -49,6 +49,7 @@ class Sobreatsesuyp(ExtractorBase):
|
|
|
49
49
|
name = f"{self.name} - {title}",
|
|
50
50
|
url = playlist_request.text,
|
|
51
51
|
referer = self.main_url,
|
|
52
|
+
headers = {},
|
|
52
53
|
subtitles = []
|
|
53
54
|
)
|
|
54
55
|
)
|