KekikStream 1.7.2__py3-none-any.whl → 1.7.3__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/Extractors/DzenRu.py +39 -0
- KekikStream/Extractors/ExPlay.py +54 -0
- KekikStream/Extractors/FirePlayer.py +61 -0
- KekikStream/Extractors/HDPlayerSystem.py +42 -0
- KekikStream/Extractors/JetTv.py +47 -0
- KekikStream/Extractors/MixTiger.py +61 -0
- KekikStream/Extractors/PlayerFilmIzle.py +63 -0
- KekikStream/Extractors/SetPlay.py +58 -0
- KekikStream/Extractors/SetPrime.py +46 -0
- KekikStream/Extractors/TurkeyPlayer.py +35 -0
- KekikStream/Extractors/VidHide.py +73 -0
- KekikStream/Extractors/VidPapi.py +90 -0
- KekikStream/Extractors/VidStack.py +75 -0
- KekikStream/Extractors/YildizKisaFilm.py +42 -0
- KekikStream/Plugins/Dizilla.py +5 -1
- KekikStream/Plugins/FilmBip.py +145 -0
- KekikStream/Plugins/FullHDFilm.py +164 -0
- KekikStream/Plugins/JetFilmizle.py +10 -3
- KekikStream/Plugins/KultFilmler.py +219 -0
- KekikStream/Plugins/RoketDizi.py +204 -0
- KekikStream/Plugins/SelcukFlix.py +216 -0
- KekikStream/Plugins/SezonlukDizi.py +3 -0
- KekikStream/Plugins/Sinefy.py +214 -0
- KekikStream/Plugins/Sinezy.py +99 -0
- KekikStream/Plugins/SuperFilmGeldi.py +121 -0
- {kekikstream-1.7.2.dist-info → kekikstream-1.7.3.dist-info}/METADATA +1 -1
- {kekikstream-1.7.2.dist-info → kekikstream-1.7.3.dist-info}/RECORD +31 -9
- {kekikstream-1.7.2.dist-info → kekikstream-1.7.3.dist-info}/WHEEL +0 -0
- {kekikstream-1.7.2.dist-info → kekikstream-1.7.3.dist-info}/entry_points.txt +0 -0
- {kekikstream-1.7.2.dist-info → kekikstream-1.7.3.dist-info}/licenses/LICENSE +0 -0
- {kekikstream-1.7.2.dist-info → kekikstream-1.7.3.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,75 @@
|
|
|
1
|
+
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
|
+
|
|
3
|
+
from KekikStream.Core import ExtractorBase, ExtractResult, Subtitle
|
|
4
|
+
from Crypto.Cipher import AES
|
|
5
|
+
from urllib.parse import urlparse
|
|
6
|
+
import re, binascii
|
|
7
|
+
|
|
8
|
+
class VidStack(ExtractorBase):
|
|
9
|
+
name = "VidStack"
|
|
10
|
+
main_url = "https://vidstack.io"
|
|
11
|
+
requires_referer = True
|
|
12
|
+
|
|
13
|
+
def get_base_url(self, url: str) -> str:
|
|
14
|
+
try:
|
|
15
|
+
parsed = urlparse(url)
|
|
16
|
+
return f"{parsed.scheme}://{parsed.netloc}"
|
|
17
|
+
except Exception:
|
|
18
|
+
return self.main_url
|
|
19
|
+
|
|
20
|
+
def decrypt_aes(self, encrypted_hex: str, key: str, iv: str) -> str:
|
|
21
|
+
try:
|
|
22
|
+
key_bytes = key.encode('utf-8')
|
|
23
|
+
iv_bytes = iv.encode('utf-8')
|
|
24
|
+
cipher = AES.new(key_bytes, AES.MODE_CBC, iv_bytes)
|
|
25
|
+
|
|
26
|
+
encrypted_bytes = binascii.unhexlify(encrypted_hex)
|
|
27
|
+
decrypted_bytes = cipher.decrypt(encrypted_bytes)
|
|
28
|
+
|
|
29
|
+
# Remove PKCS5 padding
|
|
30
|
+
padding_len = decrypted_bytes[-1]
|
|
31
|
+
return decrypted_bytes[:-padding_len].decode('utf-8')
|
|
32
|
+
except Exception:
|
|
33
|
+
return None
|
|
34
|
+
|
|
35
|
+
async def extract(self, url: str, referer: str = None) -> ExtractResult:
|
|
36
|
+
self.cffi.headers.update({
|
|
37
|
+
"User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:134.0) Gecko/20100101 Firefox/134.0"
|
|
38
|
+
})
|
|
39
|
+
|
|
40
|
+
if referer:
|
|
41
|
+
self.cffi.headers.update({"Referer": referer})
|
|
42
|
+
|
|
43
|
+
video_hash = url.split("#")[-1].split("/")[-1]
|
|
44
|
+
base_url = self.get_base_url(url)
|
|
45
|
+
|
|
46
|
+
api_url = f"{base_url}/api/v1/video?id={video_hash}"
|
|
47
|
+
istek = await self.cffi.get(api_url)
|
|
48
|
+
encoded = istek.text.strip()
|
|
49
|
+
|
|
50
|
+
key = "kiemtienmua911ca"
|
|
51
|
+
iv_list = ["1234567890oiuytr", "0123456789abcdef"]
|
|
52
|
+
|
|
53
|
+
decrypted_text = None
|
|
54
|
+
for iv in iv_list:
|
|
55
|
+
if result := self.decrypt_aes(encoded, key, iv):
|
|
56
|
+
decrypted_text = result
|
|
57
|
+
break
|
|
58
|
+
|
|
59
|
+
if not decrypted_text:
|
|
60
|
+
raise ValueError(f"VidStack: Şifre çözülemedi. {url}")
|
|
61
|
+
|
|
62
|
+
m3u8_url = ""
|
|
63
|
+
if match := re.search(r'"source":"(.*?)"', decrypted_text):
|
|
64
|
+
m3u8_url = match.group(1).replace("\\/", "/")
|
|
65
|
+
|
|
66
|
+
if not m3u8_url:
|
|
67
|
+
raise ValueError(f"VidStack: Source bulunamadı. {url}")
|
|
68
|
+
|
|
69
|
+
return ExtractResult(
|
|
70
|
+
name = self.name,
|
|
71
|
+
url = m3u8_url,
|
|
72
|
+
referer = url,
|
|
73
|
+
headers = {},
|
|
74
|
+
subtitles = []
|
|
75
|
+
)
|
|
@@ -0,0 +1,42 @@
|
|
|
1
|
+
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
|
+
|
|
3
|
+
from KekikStream.Core import ExtractorBase, ExtractResult
|
|
4
|
+
|
|
5
|
+
class YildizKisaFilm(ExtractorBase):
|
|
6
|
+
name = "YildizKisaFilm"
|
|
7
|
+
main_url = "https://yildizkisafilm.org"
|
|
8
|
+
|
|
9
|
+
async def extract(self, url, referer=None) -> ExtractResult:
|
|
10
|
+
ext_ref = referer or ""
|
|
11
|
+
|
|
12
|
+
if "video/" in url:
|
|
13
|
+
vid_id = url.split("video/")[-1]
|
|
14
|
+
else:
|
|
15
|
+
vid_id = url.split("?data=")[-1]
|
|
16
|
+
|
|
17
|
+
post_url = f"{self.main_url}/player/index.php?data={vid_id}&do=getVideo"
|
|
18
|
+
|
|
19
|
+
response = await self.cffi.post(
|
|
20
|
+
url = post_url,
|
|
21
|
+
data = {"hash": vid_id, "r": ext_ref},
|
|
22
|
+
headers = {
|
|
23
|
+
"Referer" : ext_ref,
|
|
24
|
+
"Content-Type" : "application/x-www-form-urlencoded; charset=UTF-8",
|
|
25
|
+
"X-Requested-With" : "XMLHttpRequest"
|
|
26
|
+
}
|
|
27
|
+
)
|
|
28
|
+
response.raise_for_status()
|
|
29
|
+
|
|
30
|
+
video_data = response.json()
|
|
31
|
+
m3u_link = video_data.get("securedLink")
|
|
32
|
+
|
|
33
|
+
if not m3u_link:
|
|
34
|
+
raise ValueError("securedLink not found in response")
|
|
35
|
+
|
|
36
|
+
return ExtractResult(
|
|
37
|
+
name = self.name,
|
|
38
|
+
url = m3u_link,
|
|
39
|
+
referer = ext_ref,
|
|
40
|
+
headers = {},
|
|
41
|
+
subtitles = []
|
|
42
|
+
)
|
KekikStream/Plugins/Dizilla.py
CHANGED
|
@@ -134,7 +134,11 @@ class Dizilla(PluginBase):
|
|
|
134
134
|
bolumler = []
|
|
135
135
|
sezonlar = veri.get("containsSeason") if isinstance(veri.get("containsSeason"), list) else [veri.get("containsSeason")]
|
|
136
136
|
for sezon in sezonlar:
|
|
137
|
-
|
|
137
|
+
episodes = sezon.get("episode")
|
|
138
|
+
if isinstance(episodes, dict):
|
|
139
|
+
episodes = [episodes]
|
|
140
|
+
|
|
141
|
+
for bolum in episodes:
|
|
138
142
|
bolumler.append(Episode(
|
|
139
143
|
season = sezon.get("seasonNumber"),
|
|
140
144
|
episode = bolum.get("episodeNumber"),
|
|
@@ -0,0 +1,145 @@
|
|
|
1
|
+
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
|
+
|
|
3
|
+
from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo
|
|
4
|
+
from parsel import Selector
|
|
5
|
+
|
|
6
|
+
class FilmBip(PluginBase):
|
|
7
|
+
name = "FilmBip"
|
|
8
|
+
language = "tr"
|
|
9
|
+
main_url = "https://filmbip.com"
|
|
10
|
+
favicon = f"https://www.google.com/s2/favicons?domain={main_url}&sz=64"
|
|
11
|
+
description = "Film izleme sitesi."
|
|
12
|
+
|
|
13
|
+
main_page = {
|
|
14
|
+
f"{main_url}/filmler/SAYFA" : "Yeni Filmler",
|
|
15
|
+
f"{main_url}/film/tur/aile/SAYFA" : "Aile",
|
|
16
|
+
f"{main_url}/film/tur/aksiyon/SAYFA" : "Aksiyon",
|
|
17
|
+
f"{main_url}/film/tur/belgesel/SAYFA" : "Belgesel",
|
|
18
|
+
f"{main_url}/film/tur/bilim-kurgu/SAYFA" : "Bilim Kurgu",
|
|
19
|
+
f"{main_url}/film/tur/dram/SAYFA" : "Dram",
|
|
20
|
+
f"{main_url}/film/tur/fantastik/SAYFA" : "Fantastik",
|
|
21
|
+
f"{main_url}/film/tur/gerilim/SAYFA" : "Gerilim",
|
|
22
|
+
f"{main_url}/film/tur/gizem/SAYFA" : "Gizem",
|
|
23
|
+
f"{main_url}/film/tur/komedi/SAYFA" : "Komedi",
|
|
24
|
+
f"{main_url}/film/tur/korku/SAYFA" : "Korku",
|
|
25
|
+
f"{main_url}/film/tur/macera/SAYFA" : "Macera",
|
|
26
|
+
f"{main_url}/film/tur/muzik/SAYFA" : "Müzik",
|
|
27
|
+
f"{main_url}/film/tur/romantik/SAYFA" : "Romantik",
|
|
28
|
+
f"{main_url}/film/tur/savas/SAYFA" : "Savaş",
|
|
29
|
+
f"{main_url}/film/tur/suc/SAYFA" : "Suç",
|
|
30
|
+
f"{main_url}/film/tur/tarih/SAYFA" : "Tarih",
|
|
31
|
+
f"{main_url}/film/tur/vahsi-bati/SAYFA" : "Western",
|
|
32
|
+
}
|
|
33
|
+
|
|
34
|
+
async def get_main_page(self, page: int, url: str, category: str) -> list[MainPageResult]:
|
|
35
|
+
page_url = url.replace("SAYFA", "") if page == 1 else url.replace("SAYFA", str(page))
|
|
36
|
+
page_url = page_url.rstrip("/")
|
|
37
|
+
|
|
38
|
+
istek = await self.cffi.get(page_url)
|
|
39
|
+
secici = Selector(istek.text)
|
|
40
|
+
|
|
41
|
+
results = []
|
|
42
|
+
for veri in secici.css("div.poster-long"):
|
|
43
|
+
img = veri.css("a.block img.lazy")
|
|
44
|
+
title = img.css("::attr(alt)").get()
|
|
45
|
+
href = self.fix_url(veri.css("a.block::attr(href)").get())
|
|
46
|
+
poster = self.fix_url(img.css("::attr(data-src)").get() or img.css("::attr(src)").get())
|
|
47
|
+
|
|
48
|
+
if title and href:
|
|
49
|
+
results.append(MainPageResult(
|
|
50
|
+
category = category,
|
|
51
|
+
title = title,
|
|
52
|
+
url = href,
|
|
53
|
+
poster = poster,
|
|
54
|
+
))
|
|
55
|
+
|
|
56
|
+
return results
|
|
57
|
+
|
|
58
|
+
async def search(self, query: str) -> list[SearchResult]:
|
|
59
|
+
istek = await self.cffi.post(
|
|
60
|
+
url = f"{self.main_url}/search",
|
|
61
|
+
headers = {
|
|
62
|
+
"Accept" : "application/json, text/javascript, */*; q=0.01",
|
|
63
|
+
"X-Requested-With" : "XMLHttpRequest",
|
|
64
|
+
"Content-Type" : "application/x-www-form-urlencoded; charset=UTF-8",
|
|
65
|
+
"Origin" : self.main_url,
|
|
66
|
+
"Referer" : f"{self.main_url}/"
|
|
67
|
+
},
|
|
68
|
+
data = {"query": query}
|
|
69
|
+
)
|
|
70
|
+
|
|
71
|
+
try:
|
|
72
|
+
json_data = istek.json()
|
|
73
|
+
if not json_data.get("success"):
|
|
74
|
+
return []
|
|
75
|
+
|
|
76
|
+
html_content = json_data.get("theme", "")
|
|
77
|
+
except Exception:
|
|
78
|
+
return []
|
|
79
|
+
|
|
80
|
+
secici = Selector(text=html_content)
|
|
81
|
+
|
|
82
|
+
results = []
|
|
83
|
+
for veri in secici.css("li"):
|
|
84
|
+
title = veri.css("a.block.truncate::text").get()
|
|
85
|
+
href = self.fix_url(veri.css("a::attr(href)").get())
|
|
86
|
+
poster = self.fix_url(veri.css("img.lazy::attr(data-src)").get())
|
|
87
|
+
|
|
88
|
+
if title and href:
|
|
89
|
+
results.append(SearchResult(
|
|
90
|
+
title = title.strip(),
|
|
91
|
+
url = href,
|
|
92
|
+
poster = poster,
|
|
93
|
+
))
|
|
94
|
+
|
|
95
|
+
return results
|
|
96
|
+
|
|
97
|
+
async def load_item(self, url: str) -> MovieInfo:
|
|
98
|
+
istek = await self.cffi.get(url)
|
|
99
|
+
secici = Selector(istek.text)
|
|
100
|
+
|
|
101
|
+
title = secici.css("div.page-title h1::text").get()
|
|
102
|
+
poster = self.fix_url(secici.css("meta[property='og:image']::attr(content)").get())
|
|
103
|
+
trailer = secici.css("div.series-profile-trailer::attr(data-yt)").get()
|
|
104
|
+
description = secici.css("div.series-profile-infos-in.article p::text").get() or \
|
|
105
|
+
secici.css("div.series-profile-summary p::text").get()
|
|
106
|
+
|
|
107
|
+
tags = secici.css("div.series-profile-type.tv-show-profile-type a::text").getall()
|
|
108
|
+
|
|
109
|
+
# XPath ile yıl, süre ve puan
|
|
110
|
+
year = secici.xpath("//li[span[contains(text(), 'Yapım yılı')]]/p/text()").re_first(r"(\d{4})")
|
|
111
|
+
duration = secici.xpath("//li[span[contains(text(), 'Süre')]]/p/text()").re_first(r"(\d+)")
|
|
112
|
+
rating = secici.xpath("//li[span[contains(text(), 'IMDB Puanı')]]/p/span/text()").get()
|
|
113
|
+
|
|
114
|
+
actors = secici.css("div.series-profile-cast ul li a img::attr(alt)").getall()
|
|
115
|
+
|
|
116
|
+
return MovieInfo(
|
|
117
|
+
url = url,
|
|
118
|
+
poster = poster,
|
|
119
|
+
title = self.clean_title(title) if title else "",
|
|
120
|
+
description = description.strip() if description else None,
|
|
121
|
+
tags = tags,
|
|
122
|
+
year = year,
|
|
123
|
+
rating = rating,
|
|
124
|
+
duration = int(duration) if duration else None,
|
|
125
|
+
actors = actors,
|
|
126
|
+
)
|
|
127
|
+
|
|
128
|
+
async def load_links(self, url: str) -> list[dict]:
|
|
129
|
+
istek = await self.cffi.get(url)
|
|
130
|
+
secici = Selector(istek.text)
|
|
131
|
+
|
|
132
|
+
results = []
|
|
133
|
+
|
|
134
|
+
for player in secici.css("div#tv-spoox2"):
|
|
135
|
+
iframe = self.fix_url(player.css("iframe::attr(src)").get())
|
|
136
|
+
|
|
137
|
+
if iframe:
|
|
138
|
+
extractor = self.ex_manager.find_extractor(iframe)
|
|
139
|
+
results.append({
|
|
140
|
+
"name" : extractor.name if extractor else "Player",
|
|
141
|
+
"url" : iframe,
|
|
142
|
+
"referer" : f"{self.main_url}/"
|
|
143
|
+
})
|
|
144
|
+
|
|
145
|
+
return results
|
|
@@ -0,0 +1,164 @@
|
|
|
1
|
+
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
|
+
|
|
3
|
+
from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo, ExtractResult, Subtitle
|
|
4
|
+
from parsel import Selector
|
|
5
|
+
import re, base64
|
|
6
|
+
|
|
7
|
+
class FullHDFilm(PluginBase):
|
|
8
|
+
name = "FullHDFilm"
|
|
9
|
+
language = "tr"
|
|
10
|
+
main_url = "https://hdfilm.us"
|
|
11
|
+
favicon = f"https://www.google.com/s2/favicons?domain={main_url}&sz=64"
|
|
12
|
+
description = "Full HD Film izle, Türkçe Dublaj ve Altyazılı filmler."
|
|
13
|
+
|
|
14
|
+
main_page = {
|
|
15
|
+
f"{main_url}/tur/turkce-altyazili-film-izle" : "Altyazılı Filmler",
|
|
16
|
+
f"{main_url}/tur/netflix-filmleri-izle" : "Netflix",
|
|
17
|
+
f"{main_url}/category/aile-filmleri-izle" : "Aile",
|
|
18
|
+
f"{main_url}/category/aksiyon-filmleri-izle" : "Aksiyon",
|
|
19
|
+
f"{main_url}/category/animasyon-filmleri-izle" : "Animasyon",
|
|
20
|
+
f"{main_url}/category/belgesel-filmleri-izle" : "Belgesel",
|
|
21
|
+
f"{main_url}/category/bilim-kurgu-filmleri-izle" : "Bilim-Kurgu",
|
|
22
|
+
f"{main_url}/category/biyografi-filmleri-izle" : "Biyografi",
|
|
23
|
+
f"{main_url}/category/dram-filmleri-izle" : "Dram",
|
|
24
|
+
f"{main_url}/category/fantastik-filmler-izle" : "Fantastik",
|
|
25
|
+
f"{main_url}/category/gerilim-filmleri-izle" : "Gerilim",
|
|
26
|
+
f"{main_url}/category/gizem-filmleri-izle" : "Gizem",
|
|
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/romantik-filmler-izle" : "Romantik",
|
|
31
|
+
f"{main_url}/category/savas-filmleri-izle" : "Savaş",
|
|
32
|
+
f"{main_url}/category/suc-filmleri-izle" : "Suç",
|
|
33
|
+
f"{main_url}/tur/yerli-film-izle" : "Yerli Film",
|
|
34
|
+
}
|
|
35
|
+
|
|
36
|
+
async def get_main_page(self, page: int, url: str, category: str) -> list[MainPageResult]:
|
|
37
|
+
page_url = url if page == 1 else f"{url}/page/{page}"
|
|
38
|
+
|
|
39
|
+
self.cffi.headers.update({
|
|
40
|
+
"User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
|
|
41
|
+
"Referer" : f"{self.main_url}/"
|
|
42
|
+
})
|
|
43
|
+
|
|
44
|
+
istek = await self.cffi.get(page_url)
|
|
45
|
+
secici = Selector(istek.text)
|
|
46
|
+
|
|
47
|
+
return [
|
|
48
|
+
MainPageResult(
|
|
49
|
+
category = category,
|
|
50
|
+
title = veri.css("img::attr(alt)").get(),
|
|
51
|
+
url = self.fix_url(veri.css("a::attr(href)").get()),
|
|
52
|
+
poster = self.fix_url(veri.css("img::attr(src)").get()),
|
|
53
|
+
)
|
|
54
|
+
for veri in secici.css("div.movie-poster")
|
|
55
|
+
if veri.css("img::attr(alt)").get()
|
|
56
|
+
]
|
|
57
|
+
|
|
58
|
+
async def search(self, query: str) -> list[SearchResult]:
|
|
59
|
+
istek = await self.cffi.get(f"{self.main_url}/?s={query}")
|
|
60
|
+
secici = Selector(istek.text)
|
|
61
|
+
|
|
62
|
+
return [
|
|
63
|
+
SearchResult(
|
|
64
|
+
title = veri.css("img::attr(alt)").get(),
|
|
65
|
+
url = self.fix_url(veri.css("a::attr(href)").get()),
|
|
66
|
+
poster = self.fix_url(veri.css("img::attr(src)").get()),
|
|
67
|
+
)
|
|
68
|
+
for veri in secici.css("div.movie-poster")
|
|
69
|
+
if veri.css("img::attr(alt)").get()
|
|
70
|
+
]
|
|
71
|
+
|
|
72
|
+
async def load_item(self, url: str) -> MovieInfo:
|
|
73
|
+
istek = await self.cffi.get(url)
|
|
74
|
+
secici = Selector(istek.text)
|
|
75
|
+
|
|
76
|
+
title = secici.css("h1::text").get()
|
|
77
|
+
poster = self.fix_url(secici.css("div.poster img::attr(src)").get())
|
|
78
|
+
description = secici.css("div#details div.text::text").get() or \
|
|
79
|
+
secici.css("div#details div::text").get()
|
|
80
|
+
|
|
81
|
+
actors_text = secici.css("div.oyuncular.info::text").get()
|
|
82
|
+
if actors_text:
|
|
83
|
+
actors_text = actors_text.replace("Oyuncular:", "").strip()
|
|
84
|
+
actors = [a.strip() for a in actors_text.split(",")]
|
|
85
|
+
else:
|
|
86
|
+
actors = []
|
|
87
|
+
|
|
88
|
+
year = secici.css("div.yayin-tarihi.info::text").re_first(r"(\d{4})")
|
|
89
|
+
tags = secici.css("div.tur.info a::text").getall()
|
|
90
|
+
rating = secici.css("div.imdb::text").re_first(r"IMDb\s*([\d\.]+)")
|
|
91
|
+
|
|
92
|
+
# Açıklama usually above .others
|
|
93
|
+
description = secici.xpath("//div[contains(@class, 'others')]/preceding-sibling::div[1]//text()").getall()
|
|
94
|
+
description = "".join(description).strip() if description else None
|
|
95
|
+
|
|
96
|
+
return MovieInfo(
|
|
97
|
+
url = url,
|
|
98
|
+
poster = poster,
|
|
99
|
+
title = self.clean_title(title) if title else "",
|
|
100
|
+
description = description,
|
|
101
|
+
tags = tags,
|
|
102
|
+
year = year,
|
|
103
|
+
actors = actors,
|
|
104
|
+
rating = rating.strip() if rating else None,
|
|
105
|
+
)
|
|
106
|
+
|
|
107
|
+
def _get_iframe(self, source_code: str) -> str:
|
|
108
|
+
"""Base64 kodlu iframe'i çözümle"""
|
|
109
|
+
match = re.search(r'<script[^>]*>(PCEtLWJhc2xpazp[^<]*)</script>', source_code)
|
|
110
|
+
if not match:
|
|
111
|
+
return ""
|
|
112
|
+
|
|
113
|
+
try:
|
|
114
|
+
decoded_html = base64.b64decode(match[1]).decode("utf-8")
|
|
115
|
+
iframe_match = re.search(r'<iframe[^>]+src=["\']([^"\']+)["\']', decoded_html)
|
|
116
|
+
return self.fix_url(iframe_match[1]) if iframe_match else ""
|
|
117
|
+
except Exception:
|
|
118
|
+
return ""
|
|
119
|
+
|
|
120
|
+
def _extract_subtitle_url(self, source_code: str) -> str | None:
|
|
121
|
+
"""playerjsSubtitle değişkeninden .srt URL çıkar"""
|
|
122
|
+
patterns = [
|
|
123
|
+
r'var playerjsSubtitle = "\[Türkçe\](https?://[^\s"]+?\.srt)";',
|
|
124
|
+
r'var playerjsSubtitle = "(https?://[^\s"]+?\.srt)";',
|
|
125
|
+
r'subtitle:\s*"(https?://[^\s"]+?\.srt)"',
|
|
126
|
+
]
|
|
127
|
+
|
|
128
|
+
for pattern in patterns:
|
|
129
|
+
if match := re.search(pattern, source_code):
|
|
130
|
+
return match[1]
|
|
131
|
+
|
|
132
|
+
return None
|
|
133
|
+
|
|
134
|
+
async def load_links(self, url: str) -> list[dict]:
|
|
135
|
+
self.cffi.headers.update({
|
|
136
|
+
"User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36",
|
|
137
|
+
"Referer" : self.main_url
|
|
138
|
+
})
|
|
139
|
+
|
|
140
|
+
istek = await self.cffi.get(url)
|
|
141
|
+
source_code = istek.text
|
|
142
|
+
|
|
143
|
+
# Ana sayfadan altyazı URL'sini çek
|
|
144
|
+
subtitle_url = self._extract_subtitle_url(source_code)
|
|
145
|
+
|
|
146
|
+
# Iframe'den altyazı URL'sini çek
|
|
147
|
+
iframe_src = self._get_iframe(source_code)
|
|
148
|
+
|
|
149
|
+
if not subtitle_url and iframe_src:
|
|
150
|
+
iframe_istek = await self.cffi.get(iframe_src)
|
|
151
|
+
subtitle_url = self._extract_subtitle_url(iframe_istek.text)
|
|
152
|
+
|
|
153
|
+
results = []
|
|
154
|
+
|
|
155
|
+
if iframe_src:
|
|
156
|
+
extractor = self.ex_manager.find_extractor(iframe_src)
|
|
157
|
+
results.append({
|
|
158
|
+
"name" : extractor.name if extractor else "FullHDFilm Player",
|
|
159
|
+
"url" : iframe_src,
|
|
160
|
+
"referer" : self.main_url,
|
|
161
|
+
"subtitles" : [Subtitle(name="Türkçe", url=subtitle_url)] if subtitle_url else []
|
|
162
|
+
})
|
|
163
|
+
|
|
164
|
+
return results
|
|
@@ -66,10 +66,17 @@ class JetFilmizle(PluginBase):
|
|
|
66
66
|
secici = Selector(istek.text)
|
|
67
67
|
|
|
68
68
|
title = self.clean_title(secici.css("div.movie-exp-title::text").get())
|
|
69
|
-
|
|
70
|
-
|
|
69
|
+
poster_raw = secici.css("section.movie-exp img::attr(data-src), section.movie-exp img::attr(src)").get()
|
|
70
|
+
poster = poster_raw.strip() if poster_raw else None
|
|
71
|
+
|
|
72
|
+
desc_raw = secici.css("section.movie-exp p.aciklama::text").get()
|
|
73
|
+
description = desc_raw.strip() if desc_raw else None
|
|
74
|
+
|
|
71
75
|
tags = secici.css("section.movie-exp div.catss a::text").getall()
|
|
72
|
-
|
|
76
|
+
|
|
77
|
+
rating_raw = secici.css("section.movie-exp div.imdb_puan span::text").get()
|
|
78
|
+
rating = rating_raw.strip() if rating_raw else None
|
|
79
|
+
|
|
73
80
|
year = secici.xpath("//div[@class='yap' and (contains(., 'Vizyon') or contains(., 'Yapım'))]/text()").get()
|
|
74
81
|
year = year.strip() if year else None
|
|
75
82
|
actors = secici.css("div[itemprop='actor'] a span::text").getall()
|