KekikStream 1.7.7__tar.gz → 1.8.5__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.7.7 → kekikstream-1.8.5}/KekikStream/Core/Extractor/ExtractorBase.py +2 -14
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream/Core/Extractor/ExtractorModels.py +5 -7
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream/Core/Media/MediaHandler.py +16 -20
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream/Core/Media/MediaManager.py +0 -3
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream/Core/Plugin/PluginBase.py +2 -15
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream/Core/Plugin/PluginModels.py +25 -26
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream/Extractors/CloseLoad.py +1 -2
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream/Extractors/ContentX.py +0 -2
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream/Extractors/DzenRu.py +0 -1
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream/Extractors/ExPlay.py +0 -1
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream/Extractors/FirePlayer.py +4 -5
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream/Extractors/HDPlayerSystem.py +0 -1
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream/Extractors/JetTv.py +0 -1
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream/Extractors/MailRu.py +1 -2
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream/Extractors/MixPlayHD.py +0 -1
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream/Extractors/MixTiger.py +1 -5
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream/Extractors/MolyStream.py +5 -5
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream/Extractors/Odnoklassniki.py +5 -5
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream/Extractors/PeaceMakerst.py +0 -1
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream/Extractors/PixelDrain.py +0 -1
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream/Extractors/PlayerFilmIzle.py +5 -5
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream/Extractors/RapidVid.py +0 -1
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream/Extractors/SetPlay.py +0 -1
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream/Extractors/SetPrime.py +0 -1
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream/Extractors/SibNet.py +0 -1
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream/Extractors/Sobreatsesuyp.py +0 -1
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream/Extractors/TRsTX.py +0 -1
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream/Extractors/TauVideo.py +0 -1
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream/Extractors/TurboImgz.py +0 -1
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream/Extractors/TurkeyPlayer.py +5 -5
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream/Extractors/VidHide.py +5 -5
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream/Extractors/VidMoly.py +0 -1
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream/Extractors/VidMoxy.py +0 -1
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream/Extractors/VidPapi.py +0 -1
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream/Extractors/VideoSeyred.py +0 -1
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream/Extractors/YildizKisaFilm.py +0 -1
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream/Plugins/DiziBox.py +2 -7
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream/Plugins/DiziPal.py +5 -5
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream/Plugins/DiziYou.py +44 -19
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream/Plugins/Dizilla.py +38 -27
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream/Plugins/FilmBip.py +1 -1
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream/Plugins/FilmMakinesi.py +1 -5
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream/Plugins/FilmModu.py +3 -3
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream/Plugins/FullHDFilmizlesene.py +1 -5
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream/Plugins/HDFilmCehennemi.py +14 -21
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream/Plugins/JetFilmizle.py +1 -5
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream/Plugins/RecTV.py +12 -16
- kekikstream-1.8.5/KekikStream/Plugins/RoketDizi.py +219 -0
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream/Plugins/SelcukFlix.py +160 -67
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream/Plugins/SezonlukDizi.py +1 -5
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream/Plugins/SineWix.py +4 -8
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream/Plugins/Sinefy.py +72 -51
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream/Plugins/SinemaCX.py +4 -4
- kekikstream-1.8.5/KekikStream/Plugins/Sinezy.py +131 -0
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream/Plugins/UgurFilm.py +1 -5
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream/__init__.py +5 -8
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream/requirements.txt +2 -3
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream.egg-info/PKG-INFO +1 -2
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream.egg-info/requires.txt +0 -1
- {kekikstream-1.7.7 → kekikstream-1.8.5}/PKG-INFO +1 -2
- {kekikstream-1.7.7 → kekikstream-1.8.5}/setup.py +1 -2
- kekikstream-1.7.7/KekikStream/Plugins/RoketDizi.py +0 -207
- kekikstream-1.7.7/KekikStream/Plugins/Sinezy.py +0 -99
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream/CLI/__init__.py +0 -0
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream/CLI/pypi_kontrol.py +0 -0
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream/Core/Extractor/ExtractorLoader.py +0 -0
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream/Core/Extractor/ExtractorManager.py +0 -0
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream/Core/Plugin/PluginLoader.py +0 -0
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream/Core/Plugin/PluginManager.py +0 -0
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream/Core/UI/UIManager.py +0 -0
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream/Core/__init__.py +0 -0
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream/Extractors/FourCX.py +0 -0
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream/Extractors/FourPichive.py +0 -0
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream/Extractors/FourPlayRu.py +0 -0
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream/Extractors/HDStreamAble.py +0 -0
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream/Extractors/Hotlinger.py +0 -0
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream/Extractors/OkRuHTTP.py +0 -0
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream/Extractors/OkRuSSL.py +0 -0
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream/Extractors/Pichive.py +0 -0
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream/Extractors/PlayRu.py +0 -0
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream/Extractors/VidMolyMe.py +0 -0
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream/Plugins/FullHDFilm.py +0 -0
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream/Plugins/KultFilmler.py +0 -0
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream/Plugins/SuperFilmGeldi.py +0 -0
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream/__main__.py +0 -0
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream.egg-info/SOURCES.txt +0 -0
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream.egg-info/dependency_links.txt +0 -0
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream.egg-info/entry_points.txt +0 -0
- {kekikstream-1.7.7 → kekikstream-1.8.5}/KekikStream.egg-info/top_level.txt +0 -0
- {kekikstream-1.7.7 → kekikstream-1.8.5}/LICENSE +0 -0
- {kekikstream-1.7.7 → kekikstream-1.8.5}/MANIFEST.in +0 -0
- {kekikstream-1.7.7 → kekikstream-1.8.5}/README.md +0 -0
- {kekikstream-1.7.7 → kekikstream-1.8.5}/setup.cfg +0 -0
|
@@ -1,7 +1,6 @@
|
|
|
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 curl_cffi import AsyncSession
|
|
5
4
|
from cloudscraper import CloudScraper
|
|
6
5
|
from httpx import AsyncClient
|
|
7
6
|
from typing import Optional
|
|
@@ -12,7 +11,6 @@ class ExtractorBase(ABC):
|
|
|
12
11
|
# Çıkarıcının temel özellikleri
|
|
13
12
|
name = "Extractor"
|
|
14
13
|
main_url = ""
|
|
15
|
-
requires_cffi = False
|
|
16
14
|
|
|
17
15
|
def __init__(self):
|
|
18
16
|
# cloudscraper - for bypassing Cloudflare
|
|
@@ -21,19 +19,11 @@ class ExtractorBase(ABC):
|
|
|
21
19
|
# httpx - lightweight and safe for most HTTP requests
|
|
22
20
|
self.httpx = AsyncClient(
|
|
23
21
|
timeout = 3,
|
|
24
|
-
follow_redirects = True
|
|
22
|
+
follow_redirects = True
|
|
25
23
|
)
|
|
26
24
|
self.httpx.headers.update(self.cloudscraper.headers)
|
|
27
25
|
self.httpx.cookies.update(self.cloudscraper.cookies)
|
|
28
26
|
|
|
29
|
-
# curl_cffi - only initialize if needed for anti-bot bypass
|
|
30
|
-
self.cffi = None
|
|
31
|
-
|
|
32
|
-
if self.requires_cffi:
|
|
33
|
-
self.cffi = AsyncSession(impersonate="firefox135")
|
|
34
|
-
self.cffi.cookies.update(self.cloudscraper.cookies)
|
|
35
|
-
self.cffi.headers.update({"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 15.7; rv:135.0) Gecko/20100101 Firefox/135.0"})
|
|
36
|
-
|
|
37
27
|
def can_handle_url(self, url: str) -> bool:
|
|
38
28
|
# URL'nin bu çıkarıcı tarafından işlenip işlenemeyeceğini kontrol et
|
|
39
29
|
return self.main_url in url
|
|
@@ -44,10 +34,8 @@ class ExtractorBase(ABC):
|
|
|
44
34
|
pass
|
|
45
35
|
|
|
46
36
|
async def close(self):
|
|
47
|
-
"""Close
|
|
37
|
+
"""Close HTTP client."""
|
|
48
38
|
await self.httpx.aclose()
|
|
49
|
-
if self.cffi:
|
|
50
|
-
await self.cffi.close()
|
|
51
39
|
|
|
52
40
|
def fix_url(self, url: str) -> str:
|
|
53
41
|
# Eksik URL'leri düzelt ve tam URL formatına çevir
|
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
2
|
|
|
3
3
|
from pydantic import BaseModel
|
|
4
|
-
from typing import List, Optional
|
|
5
|
-
|
|
6
4
|
|
|
7
5
|
class Subtitle(BaseModel):
|
|
8
6
|
"""Altyazı modeli."""
|
|
@@ -12,8 +10,8 @@ class Subtitle(BaseModel):
|
|
|
12
10
|
|
|
13
11
|
class ExtractResult(BaseModel):
|
|
14
12
|
"""Extractor'ın döndürmesi gereken sonuç modeli."""
|
|
15
|
-
name
|
|
16
|
-
url
|
|
17
|
-
referer
|
|
18
|
-
|
|
19
|
-
subtitles
|
|
13
|
+
name : str
|
|
14
|
+
url : str
|
|
15
|
+
referer : str | None = None
|
|
16
|
+
user_agent : str | None = None
|
|
17
|
+
subtitles : list[Subtitle] = []
|
|
@@ -5,33 +5,29 @@ from ..Extractor.ExtractorModels import ExtractResult
|
|
|
5
5
|
import subprocess, os
|
|
6
6
|
|
|
7
7
|
class MediaHandler:
|
|
8
|
-
def __init__(self, title: str = "KekikStream"
|
|
9
|
-
# Varsayılan HTTP başlıklarını ayarla
|
|
10
|
-
if headers is None:
|
|
11
|
-
headers = {"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5)"}
|
|
12
|
-
|
|
13
|
-
self.headers = headers
|
|
8
|
+
def __init__(self, title: str = "KekikStream"):
|
|
14
9
|
self.title = title
|
|
10
|
+
self.headers = {}
|
|
15
11
|
|
|
16
12
|
def play_media(self, extract_data: ExtractResult):
|
|
17
|
-
#
|
|
18
|
-
|
|
19
|
-
|
|
13
|
+
# user-agent ekle (varsayılan veya extract_data'dan)
|
|
14
|
+
user_agent = extract_data.user_agent or "Mozilla/5.0 (Macintosh; Intel Mac OS X 10_14_5)"
|
|
15
|
+
self.headers["user-agent"] = user_agent
|
|
20
16
|
|
|
21
|
-
#
|
|
22
|
-
if extract_data.
|
|
23
|
-
self.headers
|
|
17
|
+
# referer ekle
|
|
18
|
+
if extract_data.referer:
|
|
19
|
+
self.headers["referer"] = extract_data.referer
|
|
24
20
|
|
|
25
21
|
# Google Drive gibi özel durumlar için yt-dlp kullan
|
|
26
|
-
if
|
|
22
|
+
if user_agent in ["googleusercontent", "Mozilla/5.0 (X11; Linux x86_64; rv:101.0) Gecko/20100101 Firefox/101.0"]:
|
|
27
23
|
return self.play_with_ytdlp(extract_data)
|
|
28
24
|
|
|
29
25
|
# İşletim sistemine göre oynatıcı seç
|
|
30
26
|
if subprocess.check_output(['uname', '-o']).strip() == b'Android':
|
|
31
27
|
return self.play_with_android_mxplayer(extract_data)
|
|
32
28
|
|
|
33
|
-
#
|
|
34
|
-
if
|
|
29
|
+
# Alt yazılar varsa mpv kullan
|
|
30
|
+
if extract_data.subtitles:
|
|
35
31
|
return self.play_with_mpv(extract_data)
|
|
36
32
|
|
|
37
33
|
return self.play_with_vlc(extract_data) or self.play_with_mpv(extract_data)
|
|
@@ -48,11 +44,11 @@ class MediaHandler:
|
|
|
48
44
|
f"--input-title-format={self.title}"
|
|
49
45
|
])
|
|
50
46
|
|
|
51
|
-
if "
|
|
52
|
-
vlc_command.append(f"--http-user-agent={self.headers.get('
|
|
47
|
+
if "user-agent" in self.headers:
|
|
48
|
+
vlc_command.append(f"--http-user-agent={self.headers.get('user-agent')}")
|
|
53
49
|
|
|
54
|
-
if "
|
|
55
|
-
vlc_command.append(f"--http-referrer={self.headers.get('
|
|
50
|
+
if "referer" in self.headers:
|
|
51
|
+
vlc_command.append(f"--http-referrer={self.headers.get('referer')}")
|
|
56
52
|
|
|
57
53
|
vlc_command.extend(
|
|
58
54
|
f"--sub-file={subtitle.url}" for subtitle in extract_data.subtitles
|
|
@@ -162,4 +158,4 @@ class MediaHandler:
|
|
|
162
158
|
konsol.print({"title": self.title, "url": extract_data.url, "headers": self.headers})
|
|
163
159
|
except FileNotFoundError:
|
|
164
160
|
konsol.print(f"Paket: {paket}, Hata: MX Player kurulu değil")
|
|
165
|
-
konsol.print({"title": self.title, "url": extract_data.url, "headers": self.headers})
|
|
161
|
+
konsol.print({"title": self.title, "url": extract_data.url, "headers": self.headers})
|
|
@@ -1,7 +1,6 @@
|
|
|
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 curl_cffi import AsyncSession
|
|
5
4
|
from cloudscraper import CloudScraper
|
|
6
5
|
from httpx import AsyncClient
|
|
7
6
|
from .PluginModels import MainPageResult, SearchResult, MovieInfo
|
|
@@ -17,8 +16,6 @@ class PluginBase(ABC):
|
|
|
17
16
|
favicon = f"https://www.google.com/s2/favicons?domain={main_url}&sz=64"
|
|
18
17
|
description = "No description provided."
|
|
19
18
|
|
|
20
|
-
requires_cffi = False
|
|
21
|
-
|
|
22
19
|
main_page = {}
|
|
23
20
|
|
|
24
21
|
async def url_update(self, new_url: str):
|
|
@@ -33,19 +30,11 @@ class PluginBase(ABC):
|
|
|
33
30
|
# httpx - lightweight and safe for most HTTP requests
|
|
34
31
|
self.httpx = AsyncClient(
|
|
35
32
|
timeout = 3,
|
|
36
|
-
follow_redirects = True
|
|
33
|
+
follow_redirects = True
|
|
37
34
|
)
|
|
38
35
|
self.httpx.headers.update(self.cloudscraper.headers)
|
|
39
36
|
self.httpx.cookies.update(self.cloudscraper.cookies)
|
|
40
37
|
|
|
41
|
-
# curl_cffi - only initialize if needed for anti-bot bypass
|
|
42
|
-
self.cffi = None
|
|
43
|
-
|
|
44
|
-
if self.requires_cffi:
|
|
45
|
-
self.cffi = AsyncSession(impersonate="firefox135")
|
|
46
|
-
self.cffi.cookies.update(self.cloudscraper.cookies)
|
|
47
|
-
self.cffi.headers.update({"User-Agent": "Mozilla/5.0 (Macintosh; Intel Mac OS X 15.7; rv:135.0) Gecko/20100101 Firefox/135.0"})
|
|
48
|
-
|
|
49
38
|
self.media_handler = MediaHandler()
|
|
50
39
|
self.ex_manager = ExtractorManager()
|
|
51
40
|
|
|
@@ -90,10 +79,8 @@ class PluginBase(ABC):
|
|
|
90
79
|
pass
|
|
91
80
|
|
|
92
81
|
async def close(self):
|
|
93
|
-
"""Close
|
|
82
|
+
"""Close HTTP client."""
|
|
94
83
|
await self.httpx.aclose()
|
|
95
|
-
if self.cffi:
|
|
96
|
-
await self.cffi.close()
|
|
97
84
|
|
|
98
85
|
def fix_url(self, url: str) -> str:
|
|
99
86
|
if not url:
|
|
@@ -1,34 +1,33 @@
|
|
|
1
1
|
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
2
|
|
|
3
3
|
from pydantic import BaseModel, field_validator, model_validator
|
|
4
|
-
from typing import List, Optional
|
|
5
4
|
|
|
6
5
|
class MainPageResult(BaseModel):
|
|
7
6
|
"""Ana sayfa sonucunda dönecek veri modeli."""
|
|
8
7
|
category : str
|
|
9
8
|
title : str
|
|
10
9
|
url : str
|
|
11
|
-
poster :
|
|
10
|
+
poster : str | None = None
|
|
12
11
|
|
|
13
12
|
|
|
14
13
|
class SearchResult(BaseModel):
|
|
15
14
|
"""Arama sonucunda dönecek veri modeli."""
|
|
16
15
|
title : str
|
|
17
16
|
url : str
|
|
18
|
-
poster :
|
|
17
|
+
poster : str | None = None
|
|
19
18
|
|
|
20
19
|
|
|
21
20
|
class MovieInfo(BaseModel):
|
|
22
21
|
"""Bir medya öğesinin bilgilerini tutan model."""
|
|
23
22
|
url : str
|
|
24
|
-
poster :
|
|
25
|
-
title :
|
|
26
|
-
description :
|
|
27
|
-
tags :
|
|
28
|
-
rating :
|
|
29
|
-
year :
|
|
30
|
-
actors :
|
|
31
|
-
duration :
|
|
23
|
+
poster : str | None = None
|
|
24
|
+
title : str | None = None
|
|
25
|
+
description : str | None = None
|
|
26
|
+
tags : str | None = None
|
|
27
|
+
rating : str | None = None
|
|
28
|
+
year : str | None = None
|
|
29
|
+
actors : str | None = None
|
|
30
|
+
duration : int | None = None
|
|
32
31
|
|
|
33
32
|
@field_validator("tags", "actors", mode="before")
|
|
34
33
|
@classmethod
|
|
@@ -42,10 +41,10 @@ class MovieInfo(BaseModel):
|
|
|
42
41
|
|
|
43
42
|
|
|
44
43
|
class Episode(BaseModel):
|
|
45
|
-
season :
|
|
46
|
-
episode :
|
|
47
|
-
title :
|
|
48
|
-
url :
|
|
44
|
+
season : int | None = None
|
|
45
|
+
episode : int | None = None
|
|
46
|
+
title : str | None = None
|
|
47
|
+
url : str | None = None
|
|
49
48
|
|
|
50
49
|
@model_validator(mode="after")
|
|
51
50
|
def check_title(self) -> "Episode":
|
|
@@ -58,16 +57,16 @@ class Episode(BaseModel):
|
|
|
58
57
|
return self
|
|
59
58
|
|
|
60
59
|
class SeriesInfo(BaseModel):
|
|
61
|
-
url :
|
|
62
|
-
poster :
|
|
63
|
-
title :
|
|
64
|
-
description :
|
|
65
|
-
tags :
|
|
66
|
-
rating :
|
|
67
|
-
year :
|
|
68
|
-
actors :
|
|
69
|
-
duration :
|
|
70
|
-
episodes :
|
|
60
|
+
url : str | None = None
|
|
61
|
+
poster : str | None = None
|
|
62
|
+
title : str | None = None
|
|
63
|
+
description : str | None = None
|
|
64
|
+
tags : str | None = None
|
|
65
|
+
rating : str | None = None
|
|
66
|
+
year : str | None = None
|
|
67
|
+
actors : str | None = None
|
|
68
|
+
duration : int | None = None
|
|
69
|
+
episodes : list[Episode] | None = None
|
|
71
70
|
|
|
72
71
|
@field_validator("tags", "actors", mode="before")
|
|
73
72
|
@classmethod
|
|
@@ -77,4 +76,4 @@ class SeriesInfo(BaseModel):
|
|
|
77
76
|
@field_validator("rating", "year", mode="before")
|
|
78
77
|
@classmethod
|
|
79
78
|
def ensure_string(cls, value):
|
|
80
|
-
return str(value) if value is not None else value
|
|
79
|
+
return str(value) if value is not None else value
|
|
@@ -53,7 +53,6 @@ class ContentX(ExtractorBase):
|
|
|
53
53
|
name = self.name,
|
|
54
54
|
url = m3u_link,
|
|
55
55
|
referer = url,
|
|
56
|
-
headers = {},
|
|
57
56
|
subtitles = subtitles
|
|
58
57
|
)
|
|
59
58
|
]
|
|
@@ -74,7 +73,6 @@ class ContentX(ExtractorBase):
|
|
|
74
73
|
name = f"{self.name} Türkçe Dublaj",
|
|
75
74
|
url = dublaj_link,
|
|
76
75
|
referer = url,
|
|
77
|
-
headers = {},
|
|
78
76
|
subtitles = []
|
|
79
77
|
)
|
|
80
78
|
)
|
|
@@ -53,9 +53,8 @@ class FirePlayer(ExtractorBase):
|
|
|
53
53
|
raise ValueError("Could not find video URL in unpacked content")
|
|
54
54
|
|
|
55
55
|
return ExtractResult(
|
|
56
|
-
name
|
|
57
|
-
url
|
|
58
|
-
referer
|
|
59
|
-
|
|
56
|
+
name = self.name,
|
|
57
|
+
url = video_url,
|
|
58
|
+
referer = url,
|
|
59
|
+
user_agent = headers.get("User-Agent", "")
|
|
60
60
|
)
|
|
61
|
-
|
|
@@ -37,9 +37,6 @@ class MixTiger(ExtractorBase):
|
|
|
37
37
|
if not m3u_link:
|
|
38
38
|
raise ValueError("Video URL not found in response")
|
|
39
39
|
|
|
40
|
-
# disk.yandex için referer boş olmalı
|
|
41
|
-
final_referer = "" if "disk.yandex" in m3u_link else ext_ref
|
|
42
|
-
|
|
43
40
|
# Recursive extraction check
|
|
44
41
|
try:
|
|
45
42
|
from KekikStream.Core.Extractor.ExtractorManager import ExtractorManager
|
|
@@ -55,7 +52,6 @@ class MixTiger(ExtractorBase):
|
|
|
55
52
|
return ExtractResult(
|
|
56
53
|
name = self.name,
|
|
57
54
|
url = m3u_link,
|
|
58
|
-
referer =
|
|
59
|
-
headers = {},
|
|
55
|
+
referer = None if "disk.yandex" in m3u_link else ext_ref,
|
|
60
56
|
subtitles = []
|
|
61
57
|
)
|
|
@@ -26,9 +26,9 @@ class MolyStream(ExtractorBase):
|
|
|
26
26
|
]
|
|
27
27
|
|
|
28
28
|
return ExtractResult(
|
|
29
|
-
name
|
|
30
|
-
url
|
|
31
|
-
referer
|
|
32
|
-
|
|
33
|
-
subtitles
|
|
29
|
+
name = self.name,
|
|
30
|
+
url = video,
|
|
31
|
+
referer = video.replace("/sheila", ""),
|
|
32
|
+
user_agent = "Mozilla/5.0 (X11; Linux x86_64; rv:101.0) Gecko/20100101 Firefox/101.0",
|
|
33
|
+
subtitles = subtitles
|
|
34
34
|
)
|
|
@@ -82,11 +82,11 @@ class Odnoklassniki(ExtractorBase):
|
|
|
82
82
|
best_video = f"https:{best_video}"
|
|
83
83
|
|
|
84
84
|
return ExtractResult(
|
|
85
|
-
name
|
|
86
|
-
url
|
|
87
|
-
referer
|
|
88
|
-
|
|
89
|
-
subtitles
|
|
85
|
+
name = self.name,
|
|
86
|
+
url = best_video,
|
|
87
|
+
referer = referer,
|
|
88
|
+
user_agent = headers.get("User-Agent", None),
|
|
89
|
+
subtitles = []
|
|
90
90
|
)
|
|
91
91
|
|
|
92
92
|
async def fetch_with_redirects(self, url, max_redirects=5):
|
|
@@ -54,9 +54,9 @@ class PlayerFilmIzle(ExtractorBase):
|
|
|
54
54
|
raise ValueError("PlayerFilmIzle: M3U8 linki bulunamadı")
|
|
55
55
|
|
|
56
56
|
return ExtractResult(
|
|
57
|
-
name
|
|
58
|
-
url
|
|
59
|
-
referer
|
|
60
|
-
|
|
61
|
-
subtitles
|
|
57
|
+
name = self.name,
|
|
58
|
+
url = m3u8_url,
|
|
59
|
+
referer = ext_ref,
|
|
60
|
+
user_agent = self.httpx.headers.get("User-Agent", None),
|
|
61
|
+
subtitles = subtitles
|
|
62
62
|
)
|
|
@@ -26,9 +26,9 @@ class TurkeyPlayer(ExtractorBase):
|
|
|
26
26
|
master_url = f"https://watch.turkeyplayer.com/m3u8/8/{video_md5}/master.txt?s=1&id={video_id}&cache=1"
|
|
27
27
|
|
|
28
28
|
return ExtractResult(
|
|
29
|
-
name
|
|
30
|
-
url
|
|
31
|
-
referer
|
|
32
|
-
|
|
33
|
-
subtitles
|
|
29
|
+
name = self.name,
|
|
30
|
+
url = master_url,
|
|
31
|
+
referer = referer or url,
|
|
32
|
+
user_agent = self.httpx.headers.get("User-Agent", ""),
|
|
33
|
+
subtitles = []
|
|
34
34
|
)
|
|
@@ -64,9 +64,9 @@ class VidHide(ExtractorBase):
|
|
|
64
64
|
raise ValueError(f"VidHide: Video URL bulunamadı. {url}")
|
|
65
65
|
|
|
66
66
|
return ExtractResult(
|
|
67
|
-
name
|
|
68
|
-
url
|
|
69
|
-
referer
|
|
70
|
-
|
|
71
|
-
subtitles
|
|
67
|
+
name = self.name,
|
|
68
|
+
url = self.fix_url(m3u8_url),
|
|
69
|
+
referer = f"{self.main_url}/",
|
|
70
|
+
user_agent = self.httpx.headers.get("User-Agent", ""),
|
|
71
|
+
subtitles = []
|
|
72
72
|
)
|