KekikStream 2.2.9__py3-none-any.whl → 2.5.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.
Potentially problematic release.
This version of KekikStream might be problematic. Click here for more details.
- KekikStream/Core/Extractor/ExtractorBase.py +3 -2
- KekikStream/Core/Extractor/ExtractorLoader.py +8 -14
- KekikStream/Core/HTMLHelper.py +205 -0
- KekikStream/Core/Plugin/PluginBase.py +48 -12
- KekikStream/Core/Plugin/PluginLoader.py +13 -14
- KekikStream/Core/Plugin/PluginManager.py +2 -2
- KekikStream/Core/Plugin/PluginModels.py +0 -3
- KekikStream/Core/__init__.py +2 -0
- KekikStream/Extractors/Abstream.py +27 -0
- KekikStream/Extractors/CloseLoad.py +31 -56
- KekikStream/Extractors/ContentX.py +28 -71
- KekikStream/Extractors/DonilasPlay.py +34 -78
- KekikStream/Extractors/DzenRu.py +11 -25
- KekikStream/Extractors/ExPlay.py +20 -38
- KekikStream/Extractors/Filemoon.py +23 -53
- KekikStream/Extractors/HDMomPlayer.py +30 -0
- KekikStream/Extractors/HDPlayerSystem.py +13 -31
- KekikStream/Extractors/HotStream.py +27 -0
- KekikStream/Extractors/JFVid.py +3 -24
- KekikStream/Extractors/JetTv.py +21 -34
- KekikStream/Extractors/JetV.py +55 -0
- KekikStream/Extractors/MailRu.py +11 -29
- KekikStream/Extractors/MixPlayHD.py +17 -31
- KekikStream/Extractors/MixTiger.py +17 -40
- KekikStream/Extractors/MolyStream.py +25 -22
- KekikStream/Extractors/Odnoklassniki.py +41 -105
- KekikStream/Extractors/PeaceMakerst.py +20 -47
- KekikStream/Extractors/PixelDrain.py +9 -16
- KekikStream/Extractors/PlayerFilmIzle.py +23 -46
- KekikStream/Extractors/RapidVid.py +23 -36
- KekikStream/Extractors/SetPlay.py +19 -44
- KekikStream/Extractors/SetPrime.py +3 -6
- KekikStream/Extractors/SibNet.py +8 -19
- KekikStream/Extractors/Sobreatsesuyp.py +25 -47
- KekikStream/Extractors/TRsTX.py +25 -55
- KekikStream/Extractors/TurboImgz.py +8 -16
- KekikStream/Extractors/TurkeyPlayer.py +5 -5
- KekikStream/Extractors/VCTPlay.py +10 -28
- KekikStream/Extractors/Veev.py +145 -0
- KekikStream/Extractors/VidBiz.py +62 -0
- KekikStream/Extractors/VidHide.py +59 -34
- KekikStream/Extractors/VidMoly.py +67 -89
- KekikStream/Extractors/VidMoxy.py +17 -29
- KekikStream/Extractors/VidPapi.py +26 -58
- KekikStream/Extractors/VideoSeyred.py +21 -42
- KekikStream/Extractors/Videostr.py +58 -0
- KekikStream/Extractors/Vidoza.py +18 -0
- KekikStream/Extractors/Vtbe.py +38 -0
- KekikStream/Extractors/YTDLP.py +2 -2
- KekikStream/Extractors/YildizKisaFilm.py +13 -31
- KekikStream/Extractors/Zeus.py +61 -0
- KekikStream/Plugins/BelgeselX.py +108 -99
- KekikStream/Plugins/DiziBox.py +61 -106
- KekikStream/Plugins/DiziMom.py +179 -0
- KekikStream/Plugins/DiziPal.py +104 -192
- KekikStream/Plugins/DiziYou.py +66 -149
- KekikStream/Plugins/Dizilla.py +93 -126
- KekikStream/Plugins/FilmBip.py +102 -72
- KekikStream/Plugins/FilmEkseni.py +199 -0
- KekikStream/Plugins/FilmMakinesi.py +101 -64
- KekikStream/Plugins/FilmModu.py +35 -59
- KekikStream/Plugins/Filmatek.py +184 -0
- KekikStream/Plugins/FilmciBaba.py +155 -0
- KekikStream/Plugins/FullHDFilmizlesene.py +32 -78
- KekikStream/Plugins/HDFilm.py +243 -0
- KekikStream/Plugins/HDFilmCehennemi.py +261 -222
- KekikStream/Plugins/JetFilmizle.py +117 -98
- KekikStream/Plugins/KultFilmler.py +153 -143
- KekikStream/Plugins/RecTV.py +53 -49
- KekikStream/Plugins/RoketDizi.py +92 -123
- KekikStream/Plugins/SelcukFlix.py +86 -95
- KekikStream/Plugins/SetFilmIzle.py +105 -143
- KekikStream/Plugins/SezonlukDizi.py +106 -128
- KekikStream/Plugins/Sinefy.py +194 -166
- KekikStream/Plugins/SinemaCX.py +159 -113
- KekikStream/Plugins/Sinezy.py +44 -73
- KekikStream/Plugins/SuperFilmGeldi.py +28 -52
- KekikStream/Plugins/UgurFilm.py +94 -72
- KekikStream/Plugins/Watch32.py +160 -0
- KekikStream/Plugins/YabanciDizi.py +250 -0
- {kekikstream-2.2.9.dist-info → kekikstream-2.5.3.dist-info}/METADATA +1 -1
- kekikstream-2.5.3.dist-info/RECORD +99 -0
- {kekikstream-2.2.9.dist-info → kekikstream-2.5.3.dist-info}/WHEEL +1 -1
- KekikStream/Plugins/FullHDFilm.py +0 -254
- kekikstream-2.2.9.dist-info/RECORD +0 -82
- {kekikstream-2.2.9.dist-info → kekikstream-2.5.3.dist-info}/entry_points.txt +0 -0
- {kekikstream-2.2.9.dist-info → kekikstream-2.5.3.dist-info}/licenses/LICENSE +0 -0
- {kekikstream-2.2.9.dist-info → kekikstream-2.5.3.dist-info}/top_level.txt +0 -0
|
@@ -0,0 +1,179 @@
|
|
|
1
|
+
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
|
+
|
|
3
|
+
from KekikStream.Core import PluginBase, MainPageResult, SearchResult, SeriesInfo, Episode, ExtractResult, HTMLHelper
|
|
4
|
+
|
|
5
|
+
class DiziMom(PluginBase):
|
|
6
|
+
name = "DiziMom"
|
|
7
|
+
language = "tr"
|
|
8
|
+
main_url = "https://www.dizimom.one"
|
|
9
|
+
favicon = f"https://www.google.com/s2/favicons?domain={main_url}&sz=64"
|
|
10
|
+
description = "Binlerce yerli yabancı dizi arşivi, tüm sezonlar, kesintisiz bölümler. Sadece dizi izle, Dizimom heryerde seninle!"
|
|
11
|
+
|
|
12
|
+
main_page = {
|
|
13
|
+
f"{main_url}/tum-bolumler/page" : "Son Bölümler",
|
|
14
|
+
f"{main_url}/yerli-dizi-izle/page" : "Yerli Diziler",
|
|
15
|
+
f"{main_url}/yabanci-dizi-izle/page" : "Yabancı Diziler",
|
|
16
|
+
f"{main_url}/tv-programlari-izle/page" : "TV Programları",
|
|
17
|
+
f"{main_url}/netflix-dizileri-izle/page" : "Netflix Dizileri",
|
|
18
|
+
f"{main_url}/turkce-dublaj-diziler-hd/page" : "Dublajlı Diziler",
|
|
19
|
+
f"{main_url}/yerli-dizi-izle/page" : "Yerli Diziler",
|
|
20
|
+
f"{main_url}/anime-izle/page" : "Animeler",
|
|
21
|
+
f"{main_url}/yabanci-dizi-izle/page" : "Yabancı Diziler",
|
|
22
|
+
f"{main_url}/kore-dizileri-izle-hd/page" : "Kore Dizileri",
|
|
23
|
+
f"{main_url}/full-hd-hint-dizileri-izle/page" : "Hint Dizileri",
|
|
24
|
+
f"{main_url}/pakistan-dizileri-izle/page" : "Pakistan Dizileri",
|
|
25
|
+
f"{main_url}/tv-programlari-izle/page" : "Tv Programları",
|
|
26
|
+
}
|
|
27
|
+
|
|
28
|
+
async def get_main_page(self, page: int, url: str, category: str) -> list[MainPageResult]:
|
|
29
|
+
istek = await self.httpx.get(f"{url}/{page}/")
|
|
30
|
+
secici = HTMLHelper(istek.text)
|
|
31
|
+
|
|
32
|
+
results = []
|
|
33
|
+
# Eğer "tum-bolumler" ise Episode kutularını, değilse Dizi kutularını tara
|
|
34
|
+
if "/tum-bolumler/" in url:
|
|
35
|
+
for item in secici.select("div.episode-box"):
|
|
36
|
+
title = secici.select_text("div.episode-name a", item)
|
|
37
|
+
href = secici.select_attr("div.episode-name a", "href", item)
|
|
38
|
+
img = secici.select_poster("div.cat-img img", item)
|
|
39
|
+
if title and href:
|
|
40
|
+
results.append(MainPageResult(
|
|
41
|
+
category = category,
|
|
42
|
+
title = title.split(" izle")[0],
|
|
43
|
+
url = self.fix_url(href),
|
|
44
|
+
poster = self.fix_url(img)
|
|
45
|
+
))
|
|
46
|
+
else:
|
|
47
|
+
for item in secici.select("div.single-item"):
|
|
48
|
+
title = secici.select_text("div.categorytitle a", item)
|
|
49
|
+
href = secici.select_attr("div.categorytitle a", "href", item)
|
|
50
|
+
img = secici.select_poster("div.cat-img img", item)
|
|
51
|
+
if title and href:
|
|
52
|
+
results.append(MainPageResult(
|
|
53
|
+
category = category,
|
|
54
|
+
title = title.split(" izle")[0],
|
|
55
|
+
url = self.fix_url(href),
|
|
56
|
+
poster = self.fix_url(img)
|
|
57
|
+
))
|
|
58
|
+
|
|
59
|
+
return results
|
|
60
|
+
|
|
61
|
+
async def search(self, query: str) -> list[SearchResult]:
|
|
62
|
+
istek = await self.httpx.get(f"{self.main_url}/?s={query}")
|
|
63
|
+
secici = HTMLHelper(istek.text)
|
|
64
|
+
items = secici.select("div.single-item")
|
|
65
|
+
|
|
66
|
+
return [
|
|
67
|
+
SearchResult(
|
|
68
|
+
title = secici.select_text("div.categorytitle a", item).split(" izle")[0],
|
|
69
|
+
url = self.fix_url(secici.select_attr("div.categorytitle a", "href", item)),
|
|
70
|
+
poster = self.fix_url(secici.select_attr("div.cat-img img", "src", item))
|
|
71
|
+
)
|
|
72
|
+
for item in items
|
|
73
|
+
]
|
|
74
|
+
|
|
75
|
+
async def load_item(self, url: str) -> SeriesInfo:
|
|
76
|
+
istek = await self.httpx.get(url)
|
|
77
|
+
secici = HTMLHelper(istek.text)
|
|
78
|
+
|
|
79
|
+
title = self.clean_title(secici.select_text("div.title h1"))
|
|
80
|
+
poster = secici.select_poster("div.category_image img")
|
|
81
|
+
description = secici.select_direct_text("div.category_desc")
|
|
82
|
+
tags = secici.select_texts("div.genres a")
|
|
83
|
+
rating = secici.regex_first(r"(?s)IMDB\s*:\s*(?:</span>)?\s*([\d\.]+)", secici.html)
|
|
84
|
+
year = secici.extract_year("div.category_text")
|
|
85
|
+
actors = secici.meta_list("Oyuncular", container_selector="div#icerikcat2")
|
|
86
|
+
|
|
87
|
+
episodes = []
|
|
88
|
+
for item in secici.select("div.bolumust"):
|
|
89
|
+
name = secici.select_text("div.baslik", item)
|
|
90
|
+
href = secici.select_attr("a", "href", item)
|
|
91
|
+
if name and href:
|
|
92
|
+
s, e = secici.extract_season_episode(name)
|
|
93
|
+
episodes.append(Episode(
|
|
94
|
+
season = s or 1,
|
|
95
|
+
episode = e or 1,
|
|
96
|
+
title = self.clean_title(name.replace(title, "").strip()),
|
|
97
|
+
url = self.fix_url(href)
|
|
98
|
+
))
|
|
99
|
+
|
|
100
|
+
return SeriesInfo(
|
|
101
|
+
url = url,
|
|
102
|
+
poster = self.fix_url(poster),
|
|
103
|
+
title = title,
|
|
104
|
+
description = description,
|
|
105
|
+
tags = tags,
|
|
106
|
+
rating = rating,
|
|
107
|
+
year = year,
|
|
108
|
+
actors = actors,
|
|
109
|
+
episodes = episodes
|
|
110
|
+
)
|
|
111
|
+
|
|
112
|
+
async def load_links(self, url: str) -> list[ExtractResult]:
|
|
113
|
+
await self.httpx.post(
|
|
114
|
+
url = f"{self.main_url}/wp-login.php",
|
|
115
|
+
headers = {
|
|
116
|
+
"User-Agent" : "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36",
|
|
117
|
+
"sec-ch-ua" : 'Not/A)Brand";v="8", "Chromium";v="137", "Google Chrome";v="137"',
|
|
118
|
+
"sec-ch-ua-mobile" : "?1",
|
|
119
|
+
"sec-ch-ua-platform" : "Android"
|
|
120
|
+
},
|
|
121
|
+
data = {
|
|
122
|
+
"log" : "keyiflerolsun",
|
|
123
|
+
"pwd" : "12345",
|
|
124
|
+
"rememberme" : "forever",
|
|
125
|
+
"redirect_to" : self.main_url
|
|
126
|
+
}
|
|
127
|
+
)
|
|
128
|
+
|
|
129
|
+
istek = await self.httpx.get(url)
|
|
130
|
+
secici = HTMLHelper(istek.text)
|
|
131
|
+
|
|
132
|
+
iframe_data = []
|
|
133
|
+
|
|
134
|
+
# Aktif kaynağın (main iframe) adını bul
|
|
135
|
+
current_name = secici.select_text("div.sources span.current_dil") or ""
|
|
136
|
+
main_iframe = secici.select_attr("iframe[src]", "src")
|
|
137
|
+
|
|
138
|
+
# Bazen iframe doğrudan video p içinde olabilir
|
|
139
|
+
if not main_iframe:
|
|
140
|
+
main_iframe = secici.select_attr("div.video p iframe", "src")
|
|
141
|
+
|
|
142
|
+
if main_iframe:
|
|
143
|
+
iframe_data.append((main_iframe, current_name))
|
|
144
|
+
|
|
145
|
+
# Diğer kaynakları (Partlar) gez
|
|
146
|
+
sources = secici.select("div.sources a.post-page-numbers")
|
|
147
|
+
for source in sources:
|
|
148
|
+
href = secici.select_attr(None, "href", source)
|
|
149
|
+
name = secici.select_text("span.dil", source)
|
|
150
|
+
if href:
|
|
151
|
+
# Part sayfasına git
|
|
152
|
+
sub_istek = await self.httpx.get(href)
|
|
153
|
+
sub_helper = HTMLHelper(sub_istek.text)
|
|
154
|
+
sub_iframe = sub_helper.select_attr("div.video p iframe", "src") or sub_helper.select_attr("iframe[src]", "src")
|
|
155
|
+
|
|
156
|
+
if sub_iframe:
|
|
157
|
+
iframe_data.append((sub_iframe, name or f"{len(iframe_data)+1}.Kısım"))
|
|
158
|
+
|
|
159
|
+
results = []
|
|
160
|
+
for iframe_url, source_name in iframe_data:
|
|
161
|
+
# URL düzeltme
|
|
162
|
+
iframe_url = self.fix_url(iframe_url)
|
|
163
|
+
|
|
164
|
+
# Prefix olarak kaynak adını kullan (1.Kısım | HDMomPlayer)
|
|
165
|
+
extract_result = await self.extract(iframe_url, prefix=source_name)
|
|
166
|
+
|
|
167
|
+
if extract_result:
|
|
168
|
+
if isinstance(extract_result, list):
|
|
169
|
+
results.extend(extract_result)
|
|
170
|
+
else:
|
|
171
|
+
results.append(extract_result)
|
|
172
|
+
else:
|
|
173
|
+
results.append(ExtractResult(
|
|
174
|
+
url = iframe_url,
|
|
175
|
+
name = f"{source_name} | External",
|
|
176
|
+
referer = self.main_url
|
|
177
|
+
))
|
|
178
|
+
|
|
179
|
+
return results
|
KekikStream/Plugins/DiziPal.py
CHANGED
|
@@ -1,243 +1,157 @@
|
|
|
1
1
|
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
2
|
|
|
3
|
-
from KekikStream.Core
|
|
4
|
-
from selectolax.parser import HTMLParser
|
|
5
|
-
import re
|
|
3
|
+
from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo, SeriesInfo, Episode, Subtitle, ExtractResult, HTMLHelper
|
|
6
4
|
|
|
7
5
|
class DiziPal(PluginBase):
|
|
8
6
|
name = "DiziPal"
|
|
9
7
|
language = "tr"
|
|
10
|
-
main_url = "https://
|
|
8
|
+
main_url = "https://dizipal.uk"
|
|
11
9
|
favicon = f"https://www.google.com/s2/favicons?domain={main_url}&sz=64"
|
|
12
10
|
description = "dizipal güncel, dizipal yeni ve gerçek adresi. dizipal en yeni dizi ve filmleri güvenli ve hızlı şekilde sunar."
|
|
13
11
|
|
|
14
12
|
main_page = {
|
|
15
|
-
f"{main_url}/
|
|
16
|
-
f"{main_url}/
|
|
17
|
-
f"{main_url}/
|
|
18
|
-
f"{main_url}/
|
|
19
|
-
f"{main_url}/
|
|
20
|
-
f"{main_url}/
|
|
21
|
-
f"{main_url}/
|
|
22
|
-
f"{main_url}/
|
|
23
|
-
f"{main_url}/
|
|
24
|
-
f"{main_url}/
|
|
25
|
-
f"{main_url}/
|
|
13
|
+
f"{main_url}/kategori/aile/page/" : "Aile",
|
|
14
|
+
f"{main_url}/kategori/aksiyon/page/" : "Aksiyon",
|
|
15
|
+
f"{main_url}/kategori/animasyon/page/" : "Animasyon",
|
|
16
|
+
f"{main_url}/kategori/belgesel/page/" : "Belgesel",
|
|
17
|
+
f"{main_url}/kategori/bilim-kurgu/page/" : "Bilim Kurgu",
|
|
18
|
+
f"{main_url}/kategori/dram/page/" : "Dram",
|
|
19
|
+
f"{main_url}/kategori/fantastik/page/" : "Fantastik",
|
|
20
|
+
f"{main_url}/kategori/gerilim/page/" : "Gerilim",
|
|
21
|
+
f"{main_url}/kategori/gizem/page/" : "Gizem",
|
|
22
|
+
f"{main_url}/kategori/komedi/page/" : "Komedi",
|
|
23
|
+
f"{main_url}/kategori/korku/page/" : "Korku",
|
|
24
|
+
f"{main_url}/kategori/macera/page/" : "Macera",
|
|
25
|
+
f"{main_url}/kategori/muzik/page/" : "Müzik",
|
|
26
|
+
f"{main_url}/kategori/romantik/page/" : "Romantik",
|
|
27
|
+
f"{main_url}/kategori/savas/page/" : "Savaş",
|
|
28
|
+
f"{main_url}/kategori/suc/page/" : "Suç",
|
|
29
|
+
f"{main_url}/kategori/tarih/page/" : "Tarih",
|
|
30
|
+
f"{main_url}/kategori/vahsi-bati/page/" : "Vahşi Batı",
|
|
31
|
+
f"{main_url}/kategori/yerli/page/" : "Yerli",
|
|
26
32
|
}
|
|
27
33
|
|
|
28
34
|
async def get_main_page(self, page: int, url: str, category: str) -> list[MainPageResult]:
|
|
29
|
-
istek = await self.httpx.get(url)
|
|
30
|
-
secici =
|
|
35
|
+
istek = await self.httpx.get(f"{url}{page}/")
|
|
36
|
+
secici = HTMLHelper(istek.text)
|
|
31
37
|
|
|
32
38
|
results = []
|
|
33
|
-
|
|
34
|
-
|
|
35
|
-
|
|
36
|
-
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
|
|
41
|
-
|
|
42
|
-
|
|
43
|
-
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
if name and href:
|
|
47
|
-
ep_text = episode.replace(". Sezon ", "x").replace(". Bölüm", "") if episode else ""
|
|
48
|
-
title = f"{name} {ep_text}"
|
|
49
|
-
# Son bölümler linkini dizi sayfasına çevir
|
|
50
|
-
dizi_url = href.split("/sezon")[0] if "/sezon" in href else href
|
|
51
|
-
|
|
52
|
-
results.append(MainPageResult(
|
|
53
|
-
category = category,
|
|
54
|
-
title = title,
|
|
55
|
-
url = self.fix_url(dizi_url),
|
|
56
|
-
poster = self.fix_url(poster) if poster else None,
|
|
57
|
-
))
|
|
58
|
-
else:
|
|
59
|
-
for veri in secici.css("article.type2 ul li"):
|
|
60
|
-
title_el = veri.css_first("span.title")
|
|
61
|
-
link_el = veri.css_first("a")
|
|
62
|
-
img_el = veri.css_first("img")
|
|
63
|
-
|
|
64
|
-
title = title_el.text(strip=True) if title_el else None
|
|
65
|
-
href = link_el.attrs.get("href") if link_el else None
|
|
66
|
-
poster = img_el.attrs.get("src") if img_el else None
|
|
67
|
-
|
|
68
|
-
if title and href:
|
|
69
|
-
results.append(MainPageResult(
|
|
70
|
-
category = category,
|
|
71
|
-
title = title,
|
|
72
|
-
url = self.fix_url(href),
|
|
73
|
-
poster = self.fix_url(poster) if poster else None,
|
|
74
|
-
))
|
|
39
|
+
for veri in secici.select("div.grid div.post-item"):
|
|
40
|
+
title = secici.select_attr("a", "title", veri)
|
|
41
|
+
href = secici.select_attr("a", "href", veri)
|
|
42
|
+
poster = secici.select_poster("div.poster img", veri)
|
|
43
|
+
|
|
44
|
+
if title and href:
|
|
45
|
+
results.append(MainPageResult(
|
|
46
|
+
category = category,
|
|
47
|
+
title = title,
|
|
48
|
+
url = self.fix_url(href),
|
|
49
|
+
poster = self.fix_url(poster),
|
|
50
|
+
))
|
|
75
51
|
|
|
76
52
|
return results
|
|
77
53
|
|
|
78
54
|
async def search(self, query: str) -> list[SearchResult]:
|
|
79
|
-
self.httpx.
|
|
80
|
-
|
|
81
|
-
"X-Requested-With" : "XMLHttpRequest"
|
|
82
|
-
})
|
|
83
|
-
|
|
84
|
-
istek = await self.httpx.post(
|
|
85
|
-
url = f"{self.main_url}/api/search-autocomplete",
|
|
86
|
-
data = {"query": query}
|
|
87
|
-
)
|
|
88
|
-
|
|
89
|
-
try:
|
|
90
|
-
data = istek.json()
|
|
91
|
-
except Exception:
|
|
92
|
-
return []
|
|
55
|
+
istek = await self.httpx.get(f"{self.main_url}/?s={query}")
|
|
56
|
+
secici = HTMLHelper(istek.text)
|
|
93
57
|
|
|
94
58
|
results = []
|
|
59
|
+
for veri in secici.select("div.grid div.post-item"):
|
|
60
|
+
title = secici.select_attr("a", "title", veri)
|
|
61
|
+
href = secici.select_attr("a", "href", veri)
|
|
62
|
+
poster = secici.select_poster("div.poster img", veri)
|
|
95
63
|
|
|
96
|
-
|
|
97
|
-
items = data.values() if isinstance(data, dict) else data
|
|
98
|
-
|
|
99
|
-
for item in items:
|
|
100
|
-
if not isinstance(item, dict):
|
|
101
|
-
continue
|
|
102
|
-
|
|
103
|
-
title = item.get("title")
|
|
104
|
-
url = item.get("url")
|
|
105
|
-
poster = item.get("poster")
|
|
106
|
-
|
|
107
|
-
if title and url:
|
|
64
|
+
if title and href:
|
|
108
65
|
results.append(SearchResult(
|
|
109
66
|
title = title,
|
|
110
|
-
url =
|
|
111
|
-
poster = self.fix_url(poster)
|
|
67
|
+
url = self.fix_url(href),
|
|
68
|
+
poster = self.fix_url(poster),
|
|
112
69
|
))
|
|
113
70
|
|
|
114
71
|
return results
|
|
115
72
|
|
|
116
|
-
def _find_sibling_text(self, secici: HTMLParser, label_text: str) -> str | None:
|
|
117
|
-
"""Bir label'ın kardeş div'inden text çıkarır (xpath yerine)"""
|
|
118
|
-
for div in secici.css("div"):
|
|
119
|
-
if div.text(strip=True) == label_text:
|
|
120
|
-
# Sonraki kardeş elementi bul
|
|
121
|
-
next_sibling = div.next
|
|
122
|
-
while next_sibling:
|
|
123
|
-
if hasattr(next_sibling, 'text') and next_sibling.text(strip=True):
|
|
124
|
-
return next_sibling.text(strip=True)
|
|
125
|
-
next_sibling = next_sibling.next if hasattr(next_sibling, 'next') else None
|
|
126
|
-
return None
|
|
127
|
-
|
|
128
73
|
async def load_item(self, url: str) -> MovieInfo | SeriesInfo:
|
|
129
|
-
# Reset headers to get HTML response
|
|
130
|
-
self.httpx.headers.update({
|
|
131
|
-
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
|
|
132
|
-
})
|
|
133
|
-
self.httpx.headers.pop("X-Requested-With", None)
|
|
134
|
-
|
|
135
74
|
istek = await self.httpx.get(url)
|
|
136
|
-
secici =
|
|
137
|
-
|
|
138
|
-
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
|
|
143
|
-
|
|
144
|
-
|
|
145
|
-
if
|
|
146
|
-
|
|
147
|
-
|
|
148
|
-
|
|
149
|
-
|
|
150
|
-
|
|
151
|
-
|
|
152
|
-
|
|
153
|
-
|
|
154
|
-
|
|
155
|
-
|
|
156
|
-
|
|
157
|
-
|
|
158
|
-
|
|
159
|
-
tags_raw = tags_match.group(1)
|
|
160
|
-
tags = [t.strip() for t in tags_raw.split() if t.strip()]
|
|
75
|
+
secici = HTMLHelper(istek.text)
|
|
76
|
+
|
|
77
|
+
poster = self.fix_url(secici.select_attr("meta[property='og:image']", "content"))
|
|
78
|
+
description = secici.select_attr("meta[property='og:description']", "content")
|
|
79
|
+
title = secici.select_text("h1")
|
|
80
|
+
|
|
81
|
+
year = secici.meta_value("Yapım Yılı")
|
|
82
|
+
rating = secici.meta_value("IMDB Puanı")
|
|
83
|
+
duration_raw = secici.meta_value("Süre")
|
|
84
|
+
if duration_raw:
|
|
85
|
+
parts = duration_raw.split()
|
|
86
|
+
saat = 0
|
|
87
|
+
dakika = 0
|
|
88
|
+
|
|
89
|
+
for p in parts:
|
|
90
|
+
if "s" in p:
|
|
91
|
+
saat = int(p.replace("s", ""))
|
|
92
|
+
elif "dk" in p:
|
|
93
|
+
dakika = int(p.replace("dk", ""))
|
|
94
|
+
|
|
95
|
+
duration = saat * 60 + dakika
|
|
96
|
+
else:
|
|
97
|
+
duration = None
|
|
161
98
|
|
|
162
|
-
|
|
163
|
-
|
|
164
|
-
if
|
|
165
|
-
|
|
99
|
+
tags = secici.meta_list("Tür")
|
|
100
|
+
actors = secici.meta_list("Oyuncular")
|
|
101
|
+
if not actors:
|
|
102
|
+
actors = secici.select_attrs("div.swiper-slide a", "title")
|
|
166
103
|
|
|
167
104
|
if "/dizi/" in url:
|
|
168
|
-
title_el = secici.css_first("div.cover h5")
|
|
169
|
-
title = title_el.text(strip=True) if title_el else None
|
|
170
|
-
|
|
171
105
|
episodes = []
|
|
172
|
-
for ep in secici.
|
|
173
|
-
|
|
174
|
-
|
|
175
|
-
|
|
106
|
+
for ep in secici.select("div.episode-item"):
|
|
107
|
+
name = secici.select_text("h4 a", ep)
|
|
108
|
+
href = secici.select_attr("a", "href", ep)
|
|
109
|
+
link_title = secici.select_attr("a", "title", ep)
|
|
176
110
|
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
ep_text = ep_episode_el.text(strip=True) if ep_episode_el else ""
|
|
180
|
-
ep_parts = ep_text.split(" ")
|
|
111
|
+
h4_texts = secici.select_texts("h4", ep)
|
|
112
|
+
text = h4_texts[1] if len(h4_texts) > 1 else (h4_texts[0] if h4_texts else "")
|
|
181
113
|
|
|
182
|
-
|
|
183
|
-
ep_episode = None
|
|
184
|
-
if len(ep_parts) >= 4:
|
|
185
|
-
try:
|
|
186
|
-
ep_season = int(ep_parts[0].replace(".", ""))
|
|
187
|
-
ep_episode = int(ep_parts[2].replace(".", ""))
|
|
188
|
-
except ValueError:
|
|
189
|
-
pass
|
|
114
|
+
full_text = f"{text} {link_title}" if link_title else text
|
|
190
115
|
|
|
191
|
-
if
|
|
116
|
+
if name and href:
|
|
117
|
+
s, e = secici.extract_season_episode(full_text or "")
|
|
192
118
|
episodes.append(Episode(
|
|
193
|
-
season =
|
|
194
|
-
episode =
|
|
195
|
-
title =
|
|
196
|
-
url = self.fix_url(
|
|
119
|
+
season = s,
|
|
120
|
+
episode = e,
|
|
121
|
+
title = name,
|
|
122
|
+
url = self.fix_url(href)
|
|
197
123
|
))
|
|
198
124
|
|
|
199
125
|
return SeriesInfo(
|
|
200
126
|
url = url,
|
|
201
|
-
poster = poster,
|
|
127
|
+
poster = poster.replace("https://test4test.online", self.main_url),
|
|
202
128
|
title = title,
|
|
203
129
|
description = description,
|
|
204
130
|
tags = tags,
|
|
205
131
|
rating = rating,
|
|
206
132
|
year = year,
|
|
207
133
|
duration = duration,
|
|
208
|
-
episodes = episodes
|
|
134
|
+
episodes = episodes,
|
|
135
|
+
actors = actors
|
|
209
136
|
)
|
|
210
|
-
else:
|
|
211
|
-
# Film için title - g-title div'lerinin 2. olanı
|
|
212
|
-
g_titles = secici.css("div.g-title div")
|
|
213
|
-
title = g_titles[1].text(strip=True) if len(g_titles) >= 2 else None
|
|
214
137
|
|
|
215
|
-
|
|
216
|
-
|
|
217
|
-
|
|
218
|
-
|
|
219
|
-
|
|
220
|
-
|
|
221
|
-
|
|
222
|
-
|
|
223
|
-
|
|
224
|
-
|
|
138
|
+
return MovieInfo(
|
|
139
|
+
url = url,
|
|
140
|
+
poster = poster.replace("https://test4test.online", self.main_url),
|
|
141
|
+
title = title,
|
|
142
|
+
description = description,
|
|
143
|
+
tags = tags,
|
|
144
|
+
rating = rating,
|
|
145
|
+
year = year,
|
|
146
|
+
duration = duration,
|
|
147
|
+
actors = actors
|
|
148
|
+
)
|
|
225
149
|
|
|
226
150
|
async def load_links(self, url: str) -> list[ExtractResult]:
|
|
227
|
-
# Reset headers to get HTML response
|
|
228
|
-
self.httpx.headers.update({
|
|
229
|
-
"Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
|
|
230
|
-
})
|
|
231
|
-
self.httpx.headers.pop("X-Requested-With", None)
|
|
232
|
-
|
|
233
151
|
istek = await self.httpx.get(url)
|
|
234
|
-
secici =
|
|
235
|
-
|
|
236
|
-
iframe_el = secici.css_first(".series-player-container iframe")
|
|
237
|
-
if not iframe_el:
|
|
238
|
-
iframe_el = secici.css_first("div#vast_new iframe")
|
|
152
|
+
secici = HTMLHelper(istek.text)
|
|
239
153
|
|
|
240
|
-
iframe =
|
|
154
|
+
iframe = secici.select_attr("div.video-player-area iframe", "src") or secici.select_attr("div.responsive-player iframe", "src")
|
|
241
155
|
if not iframe:
|
|
242
156
|
return []
|
|
243
157
|
|
|
@@ -248,15 +162,13 @@ class DiziPal(PluginBase):
|
|
|
248
162
|
i_text = i_istek.text
|
|
249
163
|
|
|
250
164
|
# m3u link çıkar
|
|
251
|
-
|
|
252
|
-
if
|
|
253
|
-
m3u_link = m3u_match[1]
|
|
165
|
+
m3u_link = secici.regex_first(r'file:"([^"]+)"', target=i_text)
|
|
166
|
+
if m3u_link:
|
|
254
167
|
|
|
255
168
|
# Altyazıları çıkar
|
|
169
|
+
sub_text = secici.regex_first(r'"subtitle":"([^"]+)"', target=i_text)
|
|
256
170
|
subtitles = []
|
|
257
|
-
|
|
258
|
-
if sub_match:
|
|
259
|
-
sub_text = sub_match[1]
|
|
171
|
+
if sub_text:
|
|
260
172
|
if "," in sub_text:
|
|
261
173
|
for sub in sub_text.split(","):
|
|
262
174
|
lang = sub.split("[")[1].split("]")[0] if "[" in sub else "Türkçe"
|