KekikStream 1.7.1__py3-none-any.whl → 2.0.2__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/Core/Extractor/ExtractorBase.py +13 -7
- KekikStream/Core/Extractor/ExtractorLoader.py +25 -17
- KekikStream/Core/Extractor/ExtractorManager.py +53 -9
- KekikStream/Core/Extractor/ExtractorModels.py +5 -7
- KekikStream/Core/Extractor/YTDLPCache.py +35 -0
- KekikStream/Core/Media/MediaHandler.py +44 -26
- KekikStream/Core/Media/MediaManager.py +0 -3
- KekikStream/Core/Plugin/PluginBase.py +21 -9
- KekikStream/Core/Plugin/PluginLoader.py +11 -7
- KekikStream/Core/Plugin/PluginModels.py +25 -26
- KekikStream/Core/__init__.py +1 -0
- KekikStream/Extractors/CloseLoad.py +4 -5
- KekikStream/Extractors/ContentX.py +4 -6
- KekikStream/Extractors/ContentX_.py +40 -0
- KekikStream/Extractors/DzenRu.py +38 -0
- KekikStream/Extractors/ExPlay.py +53 -0
- KekikStream/Extractors/FirePlayer.py +60 -0
- KekikStream/Extractors/HDPlayerSystem.py +41 -0
- KekikStream/Extractors/JetTv.py +45 -0
- KekikStream/Extractors/MailRu.py +3 -4
- KekikStream/Extractors/MixPlayHD.py +2 -3
- KekikStream/Extractors/MixTiger.py +57 -0
- KekikStream/Extractors/MolyStream.py +5 -5
- KekikStream/Extractors/Odnoklassniki.py +7 -7
- KekikStream/Extractors/{OkRuHTTP.py → Odnoklassniki_.py} +5 -1
- KekikStream/Extractors/PeaceMakerst.py +4 -5
- KekikStream/Extractors/{HDStreamAble.py → PeaceMakerst_.py} +1 -1
- KekikStream/Extractors/PixelDrain.py +1 -2
- KekikStream/Extractors/PlayerFilmIzle.py +62 -0
- KekikStream/Extractors/RapidVid.py +2 -3
- KekikStream/Extractors/RapidVid_.py +7 -0
- KekikStream/Extractors/SetPlay.py +57 -0
- KekikStream/Extractors/SetPrime.py +45 -0
- KekikStream/Extractors/SibNet.py +2 -3
- KekikStream/Extractors/Sobreatsesuyp.py +4 -5
- KekikStream/Extractors/TRsTX.py +4 -5
- KekikStream/Extractors/TauVideo.py +2 -3
- KekikStream/Extractors/TurboImgz.py +2 -3
- KekikStream/Extractors/TurkeyPlayer.py +34 -0
- KekikStream/Extractors/VidHide.py +72 -0
- KekikStream/Extractors/VidMoly.py +4 -5
- KekikStream/Extractors/{VidMolyMe.py → VidMoly_.py} +1 -1
- KekikStream/Extractors/VidMoxy.py +2 -3
- KekikStream/Extractors/VidPapi.py +89 -0
- KekikStream/Extractors/VideoSeyred.py +3 -4
- KekikStream/Extractors/YTDLP.py +177 -0
- KekikStream/Extractors/YildizKisaFilm.py +41 -0
- KekikStream/Plugins/DiziBox.py +18 -23
- KekikStream/Plugins/DiziPal.py +16 -16
- KekikStream/Plugins/DiziYou.py +48 -23
- KekikStream/Plugins/Dizilla.py +47 -32
- KekikStream/Plugins/FilmBip.py +145 -0
- KekikStream/Plugins/FilmMakinesi.py +6 -8
- KekikStream/Plugins/FilmModu.py +9 -9
- KekikStream/Plugins/FullHDFilm.py +164 -0
- KekikStream/Plugins/FullHDFilmizlesene.py +4 -8
- KekikStream/Plugins/HDFilmCehennemi.py +15 -19
- KekikStream/Plugins/JetFilmizle.py +67 -49
- KekikStream/Plugins/KultFilmler.py +219 -0
- KekikStream/Plugins/RecTV.py +18 -22
- KekikStream/Plugins/RoketDizi.py +232 -0
- KekikStream/Plugins/SelcukFlix.py +309 -0
- KekikStream/Plugins/SezonlukDizi.py +12 -13
- KekikStream/Plugins/SineWix.py +8 -12
- KekikStream/Plugins/Sinefy.py +238 -0
- KekikStream/Plugins/SinemaCX.py +157 -0
- KekikStream/Plugins/Sinezy.py +146 -0
- KekikStream/Plugins/SuperFilmGeldi.py +121 -0
- KekikStream/Plugins/UgurFilm.py +7 -11
- KekikStream/__init__.py +34 -24
- KekikStream/requirements.txt +3 -4
- kekikstream-2.0.2.dist-info/METADATA +309 -0
- kekikstream-2.0.2.dist-info/RECORD +82 -0
- KekikStream/Extractors/FourCX.py +0 -7
- KekikStream/Extractors/FourPichive.py +0 -7
- KekikStream/Extractors/FourPlayRu.py +0 -7
- KekikStream/Extractors/Hotlinger.py +0 -7
- KekikStream/Extractors/OkRuSSL.py +0 -7
- KekikStream/Extractors/Pichive.py +0 -7
- KekikStream/Extractors/PlayRu.py +0 -7
- kekikstream-1.7.1.dist-info/METADATA +0 -109
- kekikstream-1.7.1.dist-info/RECORD +0 -63
- {kekikstream-1.7.1.dist-info → kekikstream-2.0.2.dist-info}/WHEEL +0 -0
- {kekikstream-1.7.1.dist-info → kekikstream-2.0.2.dist-info}/entry_points.txt +0 -0
- {kekikstream-1.7.1.dist-info → kekikstream-2.0.2.dist-info}/licenses/LICENSE +0 -0
- {kekikstream-1.7.1.dist-info → kekikstream-2.0.2.dist-info}/top_level.txt +0 -0
|
@@ -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
|
|
3
|
+
from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo
|
|
4
4
|
from parsel import Selector
|
|
5
5
|
|
|
6
6
|
class JetFilmizle(PluginBase):
|
|
@@ -19,9 +19,8 @@ class JetFilmizle(PluginBase):
|
|
|
19
19
|
f"{main_url}/kategoriler/yesilcam-filmleri-izlee/page/" : "Yeşilçam Filmleri"
|
|
20
20
|
}
|
|
21
21
|
|
|
22
|
-
#@kekik_cache(ttl=60*60)
|
|
23
22
|
async def get_main_page(self, page: int, url: str, category: str) -> list[MainPageResult]:
|
|
24
|
-
istek = await self.
|
|
23
|
+
istek = await self.httpx.get(f"{url}{page}", follow_redirects=True)
|
|
25
24
|
secici = Selector(istek.text)
|
|
26
25
|
|
|
27
26
|
return [
|
|
@@ -34,9 +33,8 @@ class JetFilmizle(PluginBase):
|
|
|
34
33
|
for veri in secici.css("article.movie") if veri.css("h2 a::text, h3 a::text, h4 a::text, h5 a::text, h6 a::text").get()
|
|
35
34
|
]
|
|
36
35
|
|
|
37
|
-
#@kekik_cache(ttl=60*60)
|
|
38
36
|
async def search(self, query: str) -> list[SearchResult]:
|
|
39
|
-
istek = await self.
|
|
37
|
+
istek = await self.httpx.post(
|
|
40
38
|
url = f"{self.main_url}/filmara.php",
|
|
41
39
|
data = {"s": query},
|
|
42
40
|
headers = {"Referer": f"{self.main_url}/"}
|
|
@@ -60,18 +58,31 @@ class JetFilmizle(PluginBase):
|
|
|
60
58
|
|
|
61
59
|
return results
|
|
62
60
|
|
|
63
|
-
#@kekik_cache(ttl=60*60)
|
|
64
61
|
async def load_item(self, url: str) -> MovieInfo:
|
|
65
|
-
istek = await self.
|
|
62
|
+
istek = await self.httpx.get(url)
|
|
66
63
|
secici = Selector(istek.text)
|
|
67
64
|
|
|
68
65
|
title = self.clean_title(secici.css("div.movie-exp-title::text").get())
|
|
69
|
-
|
|
70
|
-
|
|
66
|
+
poster_raw = secici.css("section.movie-exp img::attr(data-src), section.movie-exp img::attr(src)").get()
|
|
67
|
+
poster = poster_raw.strip() if poster_raw else None
|
|
68
|
+
|
|
69
|
+
desc_raw = secici.css("section.movie-exp p.aciklama::text").get()
|
|
70
|
+
description = desc_raw.strip() if desc_raw else None
|
|
71
|
+
|
|
71
72
|
tags = secici.css("section.movie-exp div.catss a::text").getall()
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
73
|
+
|
|
74
|
+
rating_raw = secici.css("section.movie-exp div.imdb_puan span::text").get()
|
|
75
|
+
rating = rating_raw.strip() if rating_raw else None
|
|
76
|
+
|
|
77
|
+
|
|
78
|
+
# Year - div.yap içinde 4 haneli sayı ara
|
|
79
|
+
year_div = secici.xpath("//div[@class='yap' and (contains(., 'Vizyon') or contains(., 'Yapım'))]/text()").get()
|
|
80
|
+
year = None
|
|
81
|
+
if year_div:
|
|
82
|
+
year_match = re.search(r'(\d{4})', year_div.strip())
|
|
83
|
+
if year_match:
|
|
84
|
+
year = year_match.group(1)
|
|
85
|
+
|
|
75
86
|
actors = secici.css("div[itemprop='actor'] a span::text").getall()
|
|
76
87
|
|
|
77
88
|
return MovieInfo(
|
|
@@ -85,47 +96,54 @@ class JetFilmizle(PluginBase):
|
|
|
85
96
|
actors = actors
|
|
86
97
|
)
|
|
87
98
|
|
|
88
|
-
#@kekik_cache(ttl=15*60)
|
|
89
99
|
async def load_links(self, url: str) -> list[dict]:
|
|
90
|
-
istek = await self.
|
|
100
|
+
istek = await self.httpx.get(url)
|
|
91
101
|
secici = Selector(istek.text)
|
|
92
102
|
|
|
93
|
-
|
|
94
|
-
if main_iframe := secici.css("div#movie iframe::attr(data-src), div#movie iframe::attr(data), div#movie iframe::attr(src)").get():
|
|
95
|
-
iframes.append(self.fix_url(main_iframe))
|
|
103
|
+
results = []
|
|
96
104
|
|
|
97
|
-
|
|
98
|
-
|
|
99
|
-
|
|
105
|
+
# 1) Ana iframe'leri kontrol et
|
|
106
|
+
for iframe in secici.css("iframe"):
|
|
107
|
+
src = (iframe.css("::attr(src)").get() or
|
|
108
|
+
iframe.css("::attr(data-src)").get() or
|
|
109
|
+
iframe.css("::attr(data-lazy-src)").get())
|
|
110
|
+
|
|
111
|
+
if src and src != "about:blank":
|
|
112
|
+
iframe_url = self.fix_url(src)
|
|
113
|
+
extractor = self.ex_manager.find_extractor(iframe_url)
|
|
114
|
+
results.append({
|
|
115
|
+
"url": iframe_url,
|
|
116
|
+
"name": extractor.name if extractor else "Ana Player"
|
|
117
|
+
})
|
|
118
|
+
|
|
119
|
+
# 2) Sayfa numaralarından linkleri topla (Fragman hariç)
|
|
120
|
+
page_links = []
|
|
121
|
+
for link in secici.css("a.post-page-numbers"):
|
|
122
|
+
isim = link.css("span::text").get() or ""
|
|
123
|
+
if isim != "Fragman":
|
|
124
|
+
href = link.css("::attr(href)").get()
|
|
125
|
+
if href:
|
|
126
|
+
page_links.append((self.fix_url(href), isim))
|
|
127
|
+
|
|
128
|
+
# 3) Her sayfa linkindeki iframe'leri bul
|
|
129
|
+
for page_url, isim in page_links:
|
|
130
|
+
try:
|
|
131
|
+
page_resp = await self.httpx.get(page_url)
|
|
132
|
+
page_sel = Selector(page_resp.text)
|
|
133
|
+
|
|
134
|
+
for iframe in page_sel.css("div#movie iframe"):
|
|
135
|
+
src = (iframe.css("::attr(src)").get() or
|
|
136
|
+
iframe.css("::attr(data-src)").get() or
|
|
137
|
+
iframe.css("::attr(data-lazy-src)").get())
|
|
138
|
+
|
|
139
|
+
if src and src != "about:blank":
|
|
140
|
+
iframe_url = self.fix_url(src)
|
|
141
|
+
extractor = self.ex_manager.find_extractor(iframe_url)
|
|
142
|
+
results.append({
|
|
143
|
+
"url": iframe_url,
|
|
144
|
+
"name": f"{extractor.name if extractor else 'Player'} | {isim}"
|
|
145
|
+
})
|
|
146
|
+
except Exception:
|
|
100
147
|
continue
|
|
101
148
|
|
|
102
|
-
part_istek = await self.cffi.get(part_href)
|
|
103
|
-
part_secici = Selector(part_istek.text)
|
|
104
|
-
|
|
105
|
-
if iframe := part_secici.css("div#movie iframe::attr(data-src), div#movie iframe::attr(data), div#movie iframe::attr(src)").get():
|
|
106
|
-
iframes.append(self.fix_url(iframe))
|
|
107
|
-
else:
|
|
108
|
-
for link in part_secici.css("div#movie p a"):
|
|
109
|
-
if download_link := link.attrib.get("href"):
|
|
110
|
-
iframes.append(self.fix_url(download_link))
|
|
111
|
-
|
|
112
|
-
processed_iframes = []
|
|
113
|
-
for iframe in iframes:
|
|
114
|
-
if "jetv.xyz" in iframe:
|
|
115
|
-
jetv_istek = await self.cffi.get(iframe)
|
|
116
|
-
jetv_secici = Selector(jetv_istek.text)
|
|
117
|
-
|
|
118
|
-
if jetv_iframe := jetv_secici.css("iframe::attr(src)").get():
|
|
119
|
-
processed_iframes.append(self.fix_url(jetv_iframe))
|
|
120
|
-
else:
|
|
121
|
-
processed_iframes.append(iframe)
|
|
122
|
-
|
|
123
|
-
results = []
|
|
124
|
-
for idx, iframe in enumerate(processed_iframes):
|
|
125
|
-
extractor = self.ex_manager.find_extractor(iframe)
|
|
126
|
-
results.append({
|
|
127
|
-
"url" : iframe,
|
|
128
|
-
"name" : f"{extractor.name if extractor else f'Player {idx + 1}'}"
|
|
129
|
-
})
|
|
130
|
-
|
|
131
149
|
return results
|
|
@@ -0,0 +1,219 @@
|
|
|
1
|
+
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
|
+
|
|
3
|
+
from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo, SeriesInfo, Episode, ExtractResult, Subtitle
|
|
4
|
+
from parsel import Selector
|
|
5
|
+
import re, base64
|
|
6
|
+
|
|
7
|
+
class KultFilmler(PluginBase):
|
|
8
|
+
name = "KultFilmler"
|
|
9
|
+
language = "tr"
|
|
10
|
+
main_url = "https://kultfilmler.net"
|
|
11
|
+
favicon = f"https://www.google.com/s2/favicons?domain={main_url}&sz=64"
|
|
12
|
+
description = "Kült film ve dizi izleme sitesi."
|
|
13
|
+
|
|
14
|
+
main_page = {
|
|
15
|
+
f"{main_url}/category/aile-filmleri-izle" : "Aile",
|
|
16
|
+
f"{main_url}/category/aksiyon-filmleri-izle" : "Aksiyon",
|
|
17
|
+
f"{main_url}/category/animasyon-filmleri-izle" : "Animasyon",
|
|
18
|
+
f"{main_url}/category/belgesel-izle" : "Belgesel",
|
|
19
|
+
f"{main_url}/category/bilim-kurgu-filmleri-izle": "Bilim Kurgu",
|
|
20
|
+
f"{main_url}/category/biyografi-filmleri-izle" : "Biyografi",
|
|
21
|
+
f"{main_url}/category/dram-filmleri-izle" : "Dram",
|
|
22
|
+
f"{main_url}/category/fantastik-filmleri-izle" : "Fantastik",
|
|
23
|
+
f"{main_url}/category/gerilim-filmleri-izle" : "Gerilim",
|
|
24
|
+
f"{main_url}/category/gizem-filmleri-izle" : "Gizem",
|
|
25
|
+
f"{main_url}/category/kara-filmleri-izle" : "Kara Film",
|
|
26
|
+
f"{main_url}/category/kisa-film-izle" : "Kısa Metraj",
|
|
27
|
+
f"{main_url}/category/komedi-filmleri-izle" : "Komedi",
|
|
28
|
+
f"{main_url}/category/korku-filmleri-izle" : "Korku",
|
|
29
|
+
f"{main_url}/category/macera-filmleri-izle" : "Macera",
|
|
30
|
+
f"{main_url}/category/muzik-filmleri-izle" : "Müzik",
|
|
31
|
+
f"{main_url}/category/polisiye-filmleri-izle" : "Polisiye",
|
|
32
|
+
f"{main_url}/category/romantik-filmleri-izle" : "Romantik",
|
|
33
|
+
f"{main_url}/category/savas-filmleri-izle" : "Savaş",
|
|
34
|
+
f"{main_url}/category/suc-filmleri-izle" : "Suç",
|
|
35
|
+
f"{main_url}/category/tarih-filmleri-izle" : "Tarih",
|
|
36
|
+
f"{main_url}/category/yerli-filmleri-izle" : "Yerli",
|
|
37
|
+
}
|
|
38
|
+
|
|
39
|
+
async def get_main_page(self, page: int, url: str, category: str) -> list[MainPageResult]:
|
|
40
|
+
istek = await self.httpx.get(url)
|
|
41
|
+
secici = Selector(istek.text)
|
|
42
|
+
|
|
43
|
+
results = []
|
|
44
|
+
for veri in secici.css("div.col-md-12 div.movie-box"):
|
|
45
|
+
title = veri.css("div.img img::attr(alt)").get()
|
|
46
|
+
href = self.fix_url(veri.css("a::attr(href)").get())
|
|
47
|
+
poster = self.fix_url(veri.css("div.img img::attr(src)").get())
|
|
48
|
+
|
|
49
|
+
if title and href:
|
|
50
|
+
results.append(MainPageResult(
|
|
51
|
+
category = category,
|
|
52
|
+
title = title,
|
|
53
|
+
url = href,
|
|
54
|
+
poster = poster,
|
|
55
|
+
))
|
|
56
|
+
|
|
57
|
+
return results
|
|
58
|
+
|
|
59
|
+
async def search(self, query: str) -> list[SearchResult]:
|
|
60
|
+
istek = await self.httpx.get(f"{self.main_url}?s={query}")
|
|
61
|
+
secici = Selector(istek.text)
|
|
62
|
+
|
|
63
|
+
results = []
|
|
64
|
+
for veri in secici.css("div.movie-box"):
|
|
65
|
+
title = veri.css("div.img img::attr(alt)").get()
|
|
66
|
+
href = self.fix_url(veri.css("a::attr(href)").get())
|
|
67
|
+
poster = self.fix_url(veri.css("div.img img::attr(src)").get())
|
|
68
|
+
|
|
69
|
+
if title and href:
|
|
70
|
+
results.append(SearchResult(
|
|
71
|
+
title = title,
|
|
72
|
+
url = href,
|
|
73
|
+
poster = poster,
|
|
74
|
+
))
|
|
75
|
+
|
|
76
|
+
return results
|
|
77
|
+
|
|
78
|
+
async def load_item(self, url: str) -> MovieInfo | SeriesInfo:
|
|
79
|
+
istek = await self.httpx.get(url)
|
|
80
|
+
secici = Selector(istek.text)
|
|
81
|
+
|
|
82
|
+
title = secici.css("div.film-bilgileri img::attr(alt)").get() or secici.css("[property='og:title']::attr(content)").get()
|
|
83
|
+
poster = self.fix_url(secici.css("[property='og:image']::attr(content)").get())
|
|
84
|
+
description = secici.css("div.description::text").get()
|
|
85
|
+
tags = secici.css("ul.post-categories a::text").getall()
|
|
86
|
+
# HTML analizine göre güncellenen alanlar
|
|
87
|
+
year = secici.css("li.release span a::text").get()
|
|
88
|
+
duration = secici.css("li.time span::text").re_first(r"(\d+)")
|
|
89
|
+
rating = secici.css("div.imdb-count::text").get()
|
|
90
|
+
actors = secici.css("div.actors a::text").getall()
|
|
91
|
+
if rating:
|
|
92
|
+
rating = rating.strip()
|
|
93
|
+
|
|
94
|
+
# Dizi mi kontrol et
|
|
95
|
+
if "/dizi/" in url:
|
|
96
|
+
episodes = []
|
|
97
|
+
for bolum in secici.css("div.episode-box"):
|
|
98
|
+
ep_href = self.fix_url(bolum.css("div.name a::attr(href)").get())
|
|
99
|
+
ssn_detail = bolum.css("span.episodetitle::text").get() or ""
|
|
100
|
+
ep_detail = bolum.css("span.episodetitle b::text").get() or ""
|
|
101
|
+
ep_name = f"{ssn_detail} - {ep_detail}"
|
|
102
|
+
|
|
103
|
+
if ep_href:
|
|
104
|
+
ep_season = re.search(r"(\d+)\.", ssn_detail)
|
|
105
|
+
ep_episode = re.search(r"(\d+)\.", ep_detail)
|
|
106
|
+
|
|
107
|
+
episodes.append(Episode(
|
|
108
|
+
season = int(ep_season[1]) if ep_season else 1,
|
|
109
|
+
episode = int(ep_episode[1]) if ep_episode else 1,
|
|
110
|
+
title = ep_name.strip(" -"),
|
|
111
|
+
url = ep_href,
|
|
112
|
+
))
|
|
113
|
+
|
|
114
|
+
return SeriesInfo(
|
|
115
|
+
url = url,
|
|
116
|
+
poster = poster,
|
|
117
|
+
title = self.clean_title(title) if title else "",
|
|
118
|
+
description = description,
|
|
119
|
+
tags = tags,
|
|
120
|
+
year = year,
|
|
121
|
+
actors = actors,
|
|
122
|
+
rating = rating,
|
|
123
|
+
episodes = episodes,
|
|
124
|
+
)
|
|
125
|
+
|
|
126
|
+
return MovieInfo(
|
|
127
|
+
url = url,
|
|
128
|
+
poster = poster,
|
|
129
|
+
title = self.clean_title(title) if title else "",
|
|
130
|
+
description = description,
|
|
131
|
+
tags = tags,
|
|
132
|
+
year = year,
|
|
133
|
+
rating = rating,
|
|
134
|
+
actors = actors,
|
|
135
|
+
duration = int(duration) if duration else None,
|
|
136
|
+
)
|
|
137
|
+
|
|
138
|
+
def _get_iframe(self, source_code: str) -> str:
|
|
139
|
+
"""Base64 kodlu iframe'i çözümle"""
|
|
140
|
+
atob_match = re.search(r"PHA\+[0-9a-zA-Z+/=]*", source_code)
|
|
141
|
+
if not atob_match:
|
|
142
|
+
return ""
|
|
143
|
+
|
|
144
|
+
atob = atob_match.group()
|
|
145
|
+
|
|
146
|
+
# Padding düzelt
|
|
147
|
+
padding = 4 - len(atob) % 4
|
|
148
|
+
if padding < 4:
|
|
149
|
+
atob = atob + "=" * padding
|
|
150
|
+
|
|
151
|
+
try:
|
|
152
|
+
decoded = base64.b64decode(atob).decode("utf-8")
|
|
153
|
+
secici = Selector(text=decoded)
|
|
154
|
+
return self.fix_url(secici.css("iframe::attr(src)").get()) or ""
|
|
155
|
+
except Exception:
|
|
156
|
+
return ""
|
|
157
|
+
|
|
158
|
+
def _extract_subtitle_url(self, source_code: str) -> str | None:
|
|
159
|
+
"""Altyazı URL'sini çıkar"""
|
|
160
|
+
match = re.search(r"(https?://[^\s\"]+\.srt)", source_code)
|
|
161
|
+
return match[1] if match else None
|
|
162
|
+
|
|
163
|
+
async def load_links(self, url: str) -> list[dict]:
|
|
164
|
+
istek = await self.httpx.get(url)
|
|
165
|
+
secici = Selector(istek.text)
|
|
166
|
+
|
|
167
|
+
iframes = set()
|
|
168
|
+
|
|
169
|
+
# Ana iframe
|
|
170
|
+
main_frame = self._get_iframe(istek.text)
|
|
171
|
+
if main_frame:
|
|
172
|
+
iframes.add(main_frame)
|
|
173
|
+
|
|
174
|
+
# Alternatif player'lar
|
|
175
|
+
for player in secici.css("div.container#player"):
|
|
176
|
+
alt_iframe = self.fix_url(player.css("iframe::attr(src)").get())
|
|
177
|
+
if alt_iframe:
|
|
178
|
+
alt_istek = await self.httpx.get(alt_iframe)
|
|
179
|
+
alt_frame = self._get_iframe(alt_istek.text)
|
|
180
|
+
if alt_frame:
|
|
181
|
+
iframes.add(alt_frame)
|
|
182
|
+
|
|
183
|
+
results = []
|
|
184
|
+
|
|
185
|
+
for iframe in iframes:
|
|
186
|
+
subtitles = []
|
|
187
|
+
|
|
188
|
+
# VidMoly özel işleme
|
|
189
|
+
if "vidmoly" in iframe:
|
|
190
|
+
headers = {
|
|
191
|
+
"User-Agent" : "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36",
|
|
192
|
+
"Sec-Fetch-Dest" : "iframe"
|
|
193
|
+
}
|
|
194
|
+
iframe_istek = await self.httpx.get(iframe, headers=headers)
|
|
195
|
+
m3u_match = re.search(r'file:"([^"]+)"', iframe_istek.text)
|
|
196
|
+
|
|
197
|
+
if m3u_match:
|
|
198
|
+
results.append({
|
|
199
|
+
"name" : "VidMoly",
|
|
200
|
+
"url" : m3u_match[1],
|
|
201
|
+
"referer" : self.main_url,
|
|
202
|
+
"subtitles" : []
|
|
203
|
+
})
|
|
204
|
+
continue
|
|
205
|
+
|
|
206
|
+
# Altyazı çıkar
|
|
207
|
+
subtitle_url = self._extract_subtitle_url(url)
|
|
208
|
+
if subtitle_url:
|
|
209
|
+
subtitles.append(Subtitle(name="Türkçe", url=subtitle_url))
|
|
210
|
+
|
|
211
|
+
extractor = self.ex_manager.find_extractor(iframe)
|
|
212
|
+
results.append({
|
|
213
|
+
"name" : extractor.name if extractor else "Player",
|
|
214
|
+
"url" : iframe,
|
|
215
|
+
"referer" : f"{self.main_url}/",
|
|
216
|
+
"subtitles" : subtitles
|
|
217
|
+
})
|
|
218
|
+
|
|
219
|
+
return results
|
KekikStream/Plugins/RecTV.py
CHANGED
|
@@ -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
|
|
3
|
+
from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo, Episode, SeriesInfo, ExtractResult, Subtitle
|
|
4
4
|
from json import dumps, loads
|
|
5
5
|
import re
|
|
6
6
|
|
|
@@ -30,10 +30,9 @@ class RecTV(PluginBase):
|
|
|
30
30
|
f"{main_url}/api/movie/by/filtres/5/created/SAYFA/{sw_key}/" : "Romantik"
|
|
31
31
|
}
|
|
32
32
|
|
|
33
|
-
#@kekik_cache(ttl=60*60)
|
|
34
33
|
async def get_main_page(self, page: int, url: str, category: str) -> list[MainPageResult]:
|
|
35
|
-
self.
|
|
36
|
-
istek = await self.
|
|
34
|
+
self.httpx.headers.update({"user-agent": "okhttp/4.12.0"})
|
|
35
|
+
istek = await self.httpx.get(f"{url.replace('SAYFA', str(int(page) - 1))}")
|
|
37
36
|
veriler = istek.json()
|
|
38
37
|
|
|
39
38
|
return [
|
|
@@ -46,10 +45,9 @@ class RecTV(PluginBase):
|
|
|
46
45
|
for veri in veriler
|
|
47
46
|
]
|
|
48
47
|
|
|
49
|
-
#@kekik_cache(ttl=60*60)
|
|
50
48
|
async def search(self, query: str) -> list[SearchResult]:
|
|
51
|
-
self.
|
|
52
|
-
istek = await self.
|
|
49
|
+
self.httpx.headers.update({"user-agent": "okhttp/4.12.0"})
|
|
50
|
+
istek = await self.httpx.get(f"{self.main_url}/api/search/{query}/{self.sw_key}/")
|
|
53
51
|
|
|
54
52
|
kanallar = istek.json().get("channels")
|
|
55
53
|
icerikler = istek.json().get("posters")
|
|
@@ -67,14 +65,13 @@ class RecTV(PluginBase):
|
|
|
67
65
|
for veri in tum_veri
|
|
68
66
|
]
|
|
69
67
|
|
|
70
|
-
#@kekik_cache(ttl=60*60)
|
|
71
68
|
async def load_item(self, url: str) -> MovieInfo:
|
|
72
|
-
self.
|
|
69
|
+
self.httpx.headers.update({"user-agent": "okhttp/4.12.0"})
|
|
73
70
|
veri = loads(url)
|
|
74
71
|
|
|
75
72
|
match veri.get("type"):
|
|
76
73
|
case "serie":
|
|
77
|
-
dizi_istek = await self.
|
|
74
|
+
dizi_istek = await self.httpx.get(f"{self.main_url}/api/season/by/serie/{veri.get('id')}/{self.sw_key}/")
|
|
78
75
|
dizi_veri = dizi_istek.json()
|
|
79
76
|
|
|
80
77
|
episodes = []
|
|
@@ -119,10 +116,7 @@ class RecTV(PluginBase):
|
|
|
119
116
|
actors = []
|
|
120
117
|
)
|
|
121
118
|
|
|
122
|
-
#@kekik_cache(ttl=15*60)
|
|
123
119
|
async def load_links(self, url: str) -> list[dict]:
|
|
124
|
-
self.media_handler.headers.update({"User-Agent": "googleusercontent"})
|
|
125
|
-
|
|
126
120
|
try:
|
|
127
121
|
veri = loads(url)
|
|
128
122
|
except Exception:
|
|
@@ -132,9 +126,10 @@ class RecTV(PluginBase):
|
|
|
132
126
|
# Eğer dizi bölümü ise (bizim oluşturduğumuz yapı)
|
|
133
127
|
if veri.get("is_episode"):
|
|
134
128
|
return [{
|
|
135
|
-
"url"
|
|
136
|
-
"name"
|
|
137
|
-
"
|
|
129
|
+
"url" : veri.get("url"),
|
|
130
|
+
"name" : veri.get("title", "Bölüm"),
|
|
131
|
+
"user_agent" : "googleusercontent",
|
|
132
|
+
"referer" : "https://twitter.com/"
|
|
138
133
|
}]
|
|
139
134
|
|
|
140
135
|
# Film ise (RecTV API yapısı)
|
|
@@ -146,16 +141,17 @@ class RecTV(PluginBase):
|
|
|
146
141
|
continue
|
|
147
142
|
|
|
148
143
|
results.append({
|
|
149
|
-
"url"
|
|
150
|
-
"name"
|
|
151
|
-
"
|
|
144
|
+
"url" : video_link,
|
|
145
|
+
"name" : f"{veri.get('title')} - {kaynak.get('title')}",
|
|
146
|
+
"user_agent" : "googleusercontent",
|
|
147
|
+
"referer" : "https://twitter.com/"
|
|
152
148
|
})
|
|
153
149
|
|
|
154
150
|
return results
|
|
155
151
|
|
|
156
|
-
async def play(self,
|
|
157
|
-
extract_result = ExtractResult(
|
|
158
|
-
self.media_handler.title = name
|
|
152
|
+
async def play(self, **kwargs):
|
|
153
|
+
extract_result = ExtractResult(**kwargs)
|
|
154
|
+
self.media_handler.title = kwargs.get("name")
|
|
159
155
|
if self.name not in self.media_handler.title:
|
|
160
156
|
self.media_handler.title = f"{self.name} | {self.media_handler.title}"
|
|
161
157
|
|