KekikStream 2.4.6__py3-none-any.whl → 2.4.8__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/HTMLHelper.py +2 -2
- KekikStream/Core/Plugin/PluginBase.py +15 -4
- KekikStream/Extractors/Odnoklassniki.py +14 -2
- KekikStream/Extractors/YTDLP.py +2 -2
- KekikStream/Plugins/BelgeselX.py +30 -23
- KekikStream/Plugins/DiziBox.py +14 -11
- KekikStream/Plugins/DiziMom.py +110 -86
- KekikStream/Plugins/DiziPal.py +37 -23
- KekikStream/Plugins/DiziYou.py +23 -11
- KekikStream/Plugins/Dizilla.py +35 -30
- KekikStream/Plugins/FilmBip.py +83 -18
- KekikStream/Plugins/FilmEkseni.py +100 -58
- KekikStream/Plugins/FilmMakinesi.py +71 -19
- KekikStream/Plugins/FilmModu.py +17 -20
- KekikStream/Plugins/Filmatek.py +103 -98
- KekikStream/Plugins/{Full4kizle.py → FilmciBaba.py} +61 -80
- KekikStream/Plugins/FullHDFilmizlesene.py +12 -14
- KekikStream/Plugins/HDFilm.py +243 -0
- KekikStream/Plugins/HDFilmCehennemi.py +194 -125
- KekikStream/Plugins/JetFilmizle.py +5 -5
- KekikStream/Plugins/KultFilmler.py +6 -6
- KekikStream/Plugins/RoketDizi.py +5 -5
- KekikStream/Plugins/SelcukFlix.py +2 -2
- KekikStream/Plugins/SetFilmIzle.py +5 -5
- KekikStream/Plugins/SezonlukDizi.py +4 -4
- KekikStream/Plugins/Sinefy.py +5 -5
- KekikStream/Plugins/SinemaCX.py +5 -5
- KekikStream/Plugins/Sinezy.py +5 -5
- KekikStream/Plugins/SuperFilmGeldi.py +5 -5
- KekikStream/Plugins/UgurFilm.py +4 -4
- KekikStream/Plugins/YabanciDizi.py +5 -5
- {kekikstream-2.4.6.dist-info → kekikstream-2.4.8.dist-info}/METADATA +1 -1
- {kekikstream-2.4.6.dist-info → kekikstream-2.4.8.dist-info}/RECORD +37 -37
- KekikStream/Plugins/FullHDFilm.py +0 -179
- {kekikstream-2.4.6.dist-info → kekikstream-2.4.8.dist-info}/WHEEL +0 -0
- {kekikstream-2.4.6.dist-info → kekikstream-2.4.8.dist-info}/entry_points.txt +0 -0
- {kekikstream-2.4.6.dist-info → kekikstream-2.4.8.dist-info}/licenses/LICENSE +0 -0
- {kekikstream-2.4.6.dist-info → kekikstream-2.4.8.dist-info}/top_level.txt +0 -0
KekikStream/Core/HTMLHelper.py
CHANGED
|
@@ -41,14 +41,14 @@ class HTMLHelper:
|
|
|
41
41
|
val = el.text(strip=True)
|
|
42
42
|
return val or None
|
|
43
43
|
|
|
44
|
-
def select_texts(self, selector: str, element: Node | None = None) -> list[str]:
|
|
44
|
+
def select_texts(self, selector: str, element: Node | None = None) -> list[str] | None:
|
|
45
45
|
"""CSS selector ile tüm eşleşen elementlerin text içeriklerini döndür."""
|
|
46
46
|
out: list[str] = []
|
|
47
47
|
for el in self.select(selector, element):
|
|
48
48
|
txt = el.text(strip=True)
|
|
49
49
|
if txt:
|
|
50
50
|
out.append(txt)
|
|
51
|
-
return out
|
|
51
|
+
return out or None
|
|
52
52
|
|
|
53
53
|
def select_attr(self, selector: str | None, attr: str, element: Node | None = None) -> str | None:
|
|
54
54
|
"""CSS selector ile element bul ve attribute değerini döndür."""
|
|
@@ -106,7 +106,13 @@ class PluginBase(ABC):
|
|
|
106
106
|
url = f"https:{url}" if url.startswith("//") else urljoin(self.main_url, url)
|
|
107
107
|
return url.replace("\\", "")
|
|
108
108
|
|
|
109
|
-
async def extract(
|
|
109
|
+
async def extract(
|
|
110
|
+
self,
|
|
111
|
+
url: str,
|
|
112
|
+
referer: str = None,
|
|
113
|
+
prefix: str | None = None,
|
|
114
|
+
name_override: str | None = None
|
|
115
|
+
) -> ExtractResult | list[ExtractResult] | None:
|
|
110
116
|
"""
|
|
111
117
|
Extractor ile video URL'sini çıkarır.
|
|
112
118
|
|
|
@@ -114,6 +120,7 @@ class PluginBase(ABC):
|
|
|
114
120
|
url: Iframe veya video URL'si
|
|
115
121
|
referer: Referer header (varsayılan: plugin main_url)
|
|
116
122
|
prefix: İsmin başına eklenecek opsiyonel etiket (örn: "Türkçe Dublaj")
|
|
123
|
+
name_override: İsmi tamamen değiştirecek opsiyonel etiket (Extractor adını ezer)
|
|
117
124
|
|
|
118
125
|
Returns:
|
|
119
126
|
ExtractResult: Extractor sonucu (name prefix ile birleştirilmiş) veya None
|
|
@@ -131,15 +138,19 @@ class PluginBase(ABC):
|
|
|
131
138
|
try:
|
|
132
139
|
data = await extractor.extract(url, referer=referer)
|
|
133
140
|
|
|
134
|
-
# Liste ise her bir öğe için prefix ekle
|
|
141
|
+
# Liste ise her bir öğe için prefix/override ekle
|
|
135
142
|
if isinstance(data, list):
|
|
136
143
|
for item in data:
|
|
137
|
-
if
|
|
144
|
+
if name_override:
|
|
145
|
+
item.name = name_override
|
|
146
|
+
elif prefix and item.name:
|
|
138
147
|
item.name = f"{prefix} | {item.name}"
|
|
139
148
|
return data
|
|
140
149
|
|
|
141
150
|
# Tekil öğe ise
|
|
142
|
-
if
|
|
151
|
+
if name_override:
|
|
152
|
+
data.name = name_override
|
|
153
|
+
elif prefix and data.name:
|
|
143
154
|
data.name = f"{prefix} | {data.name}"
|
|
144
155
|
|
|
145
156
|
return data
|
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
2
|
|
|
3
3
|
from KekikStream.Core import ExtractorBase, ExtractResult, HTMLHelper
|
|
4
|
-
import json
|
|
4
|
+
import json, html
|
|
5
5
|
|
|
6
6
|
class Odnoklassniki(ExtractorBase):
|
|
7
7
|
name = "Odnoklassniki"
|
|
@@ -19,12 +19,18 @@ class Odnoklassniki(ExtractorBase):
|
|
|
19
19
|
resp = await self.httpx.get(url, follow_redirects=True)
|
|
20
20
|
sel = HTMLHelper(resp.text)
|
|
21
21
|
|
|
22
|
-
|
|
22
|
+
# Metadata içinden videos array'ini al (esnek regex)
|
|
23
|
+
v_data = sel.regex_first(r'videos[^:]+:(\[.*?\])')
|
|
23
24
|
if not v_data:
|
|
25
|
+
if "Видео заблокировано" in resp.text or "copyrightsRestricted" in resp.text:
|
|
26
|
+
raise ValueError("Odnoklassniki: Video telif nedeniyle silinmiş/erişilemiyor.")
|
|
24
27
|
raise ValueError(f"Odnoklassniki: Video verisi bulunamadı. {url}")
|
|
25
28
|
|
|
26
29
|
# Kalite sıralaması (En yüksekten düşüğe)
|
|
27
30
|
order = ["ULTRA", "QUAD", "FULL", "HD", "SD", "LOW", "MOBILE"]
|
|
31
|
+
# Escaped string'i temizle
|
|
32
|
+
v_data = html.unescape(v_data)
|
|
33
|
+
v_data = v_data.replace('\\"', '"').replace('\\/', '/')
|
|
28
34
|
videos = json.loads(v_data)
|
|
29
35
|
|
|
30
36
|
best_url = None
|
|
@@ -38,4 +44,10 @@ class Odnoklassniki(ExtractorBase):
|
|
|
38
44
|
if not best_url:
|
|
39
45
|
raise ValueError("Odnoklassniki: Geçerli video URL'si bulunamadı.")
|
|
40
46
|
|
|
47
|
+
# URL temizliği (u0026 -> & ve olası unicode kaçışları)
|
|
48
|
+
best_url = best_url.replace("u0026", "&").replace("\\u0026", "&")
|
|
49
|
+
# Eğer hala \uXXXX formatında unicode kaçışları varsa çöz
|
|
50
|
+
if "\\u" in best_url:
|
|
51
|
+
best_url = best_url.encode().decode('unicode-escape')
|
|
52
|
+
|
|
41
53
|
return ExtractResult(name=self.name, url=self.fix_url(best_url), referer=referer)
|
KekikStream/Extractors/YTDLP.py
CHANGED
|
@@ -151,8 +151,8 @@ class YTDLP(ExtractorBase):
|
|
|
151
151
|
ydl_opts = {
|
|
152
152
|
"quiet" : True,
|
|
153
153
|
"no_warnings" : True,
|
|
154
|
-
"extract_flat" : False,
|
|
155
|
-
"format" : "best", # En iyi kalite
|
|
154
|
+
"extract_flat" : False, # Tam bilgi al
|
|
155
|
+
"format" : "best/all", # En iyi kalite, yoksa herhangi biri
|
|
156
156
|
"no_check_certificates" : True,
|
|
157
157
|
"socket_timeout" : 3,
|
|
158
158
|
"retries" : 1
|
KekikStream/Plugins/BelgeselX.py
CHANGED
|
@@ -1,6 +1,7 @@
|
|
|
1
1
|
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
2
|
|
|
3
3
|
from KekikStream.Core import PluginBase, MainPageResult, SearchResult, SeriesInfo, Episode, ExtractResult, HTMLHelper
|
|
4
|
+
from contextlib import suppress
|
|
4
5
|
|
|
5
6
|
class BelgeselX(PluginBase):
|
|
6
7
|
name = "BelgeselX"
|
|
@@ -36,15 +37,15 @@ class BelgeselX(PluginBase):
|
|
|
36
37
|
"""Türkçe için title case dönüşümü."""
|
|
37
38
|
if not text:
|
|
38
39
|
return ""
|
|
39
|
-
|
|
40
|
-
words
|
|
40
|
+
|
|
41
|
+
words = text.split()
|
|
41
42
|
new_words = []
|
|
42
|
-
|
|
43
|
+
|
|
43
44
|
for word in words:
|
|
44
45
|
# Önce Türkçe karakterleri koruyarak küçült
|
|
45
46
|
# İ -> i, I -> ı
|
|
46
47
|
word = word.replace("İ", "i").replace("I", "ı").lower()
|
|
47
|
-
|
|
48
|
+
|
|
48
49
|
# Sonra ilk harfi Türkçe kurallarına göre büyüt
|
|
49
50
|
if word:
|
|
50
51
|
if word[0] == "i":
|
|
@@ -53,9 +54,9 @@ class BelgeselX(PluginBase):
|
|
|
53
54
|
word = "I" + word[1:]
|
|
54
55
|
else:
|
|
55
56
|
word = word[0].upper() + word[1:]
|
|
56
|
-
|
|
57
|
+
|
|
57
58
|
new_words.append(word)
|
|
58
|
-
|
|
59
|
+
|
|
59
60
|
return " ".join(new_words)
|
|
60
61
|
|
|
61
62
|
async def get_main_page(self, page: int, url: str, category: str) -> list[MainPageResult]:
|
|
@@ -63,21 +64,17 @@ class BelgeselX(PluginBase):
|
|
|
63
64
|
secici = HTMLHelper(istek.text)
|
|
64
65
|
|
|
65
66
|
results = []
|
|
66
|
-
# xpath kullanamıyoruz, en üst seviye gen-movie-contain'leri alıp içlerinden bilgileri çekelim
|
|
67
67
|
for container in secici.select("div.gen-movie-contain"):
|
|
68
|
-
# Poster için img'i container'ın içinden alalım
|
|
69
68
|
poster = secici.select_attr("div.gen-movie-img img", "src", container)
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
title = secici.select_text("div.gen-movie-info h3 a", container)
|
|
73
|
-
href = secici.select_attr("div.gen-movie-info h3 a", "href", container)
|
|
69
|
+
title = secici.select_text("div.gen-movie-info h3 a", container)
|
|
70
|
+
href = secici.select_attr("div.gen-movie-info h3 a", "href", container)
|
|
74
71
|
|
|
75
72
|
if title and href:
|
|
76
73
|
results.append(MainPageResult(
|
|
77
74
|
category = category,
|
|
78
75
|
title = self._to_title_case(title),
|
|
79
76
|
url = self.fix_url(href),
|
|
80
|
-
poster = self.fix_url(poster)
|
|
77
|
+
poster = self.fix_url(poster)
|
|
81
78
|
))
|
|
82
79
|
|
|
83
80
|
return results
|
|
@@ -117,7 +114,6 @@ class BelgeselX(PluginBase):
|
|
|
117
114
|
poster = images[i] if i < len(images) else None
|
|
118
115
|
|
|
119
116
|
if not url_val or "diziresimleri" not in url_val:
|
|
120
|
-
# URL'den belgesel linkini oluştur
|
|
121
117
|
if poster and "diziresimleri" in poster:
|
|
122
118
|
file_name = poster.rsplit("/", 1)[-1]
|
|
123
119
|
file_name = HTMLHelper(file_name).regex_replace(r"\.(jpe?g|png|webp)$", "")
|
|
@@ -154,6 +150,7 @@ class BelgeselX(PluginBase):
|
|
|
154
150
|
if not rating:
|
|
155
151
|
if r_match := secici.regex_first(r"%\s*(\d+)\s*Puan", item):
|
|
156
152
|
rating = float(r_match) / 10
|
|
153
|
+
rating = rating or None
|
|
157
154
|
|
|
158
155
|
episodes = []
|
|
159
156
|
for i, ep in enumerate(secici.select("div.gen-movie-contain")):
|
|
@@ -166,12 +163,23 @@ class BelgeselX(PluginBase):
|
|
|
166
163
|
final_url = self.fix_url(href)
|
|
167
164
|
if item_id:
|
|
168
165
|
final_url = f"{final_url}?id={item_id}"
|
|
169
|
-
|
|
170
|
-
episodes.append(Episode(
|
|
166
|
+
|
|
167
|
+
episodes.append(Episode(
|
|
168
|
+
season = s or 1,
|
|
169
|
+
episode = e or (i + 1),
|
|
170
|
+
title = name,
|
|
171
|
+
url = final_url
|
|
172
|
+
))
|
|
171
173
|
|
|
172
174
|
return SeriesInfo(
|
|
173
|
-
url=url,
|
|
174
|
-
|
|
175
|
+
url = url,
|
|
176
|
+
poster = self.fix_url(poster),
|
|
177
|
+
title = title,
|
|
178
|
+
description = description,
|
|
179
|
+
tags = tags,
|
|
180
|
+
year = year,
|
|
181
|
+
rating = rating,
|
|
182
|
+
episodes = episodes
|
|
175
183
|
)
|
|
176
184
|
|
|
177
185
|
async def load_links(self, url: str) -> list[ExtractResult]:
|
|
@@ -198,19 +206,18 @@ class BelgeselX(PluginBase):
|
|
|
198
206
|
|
|
199
207
|
for i, video_url in enumerate(files):
|
|
200
208
|
quality = labels[i] if i < len(labels) else "HD"
|
|
209
|
+
name = f"{'Google' if 'google' in video_url.lower() or 'blogspot' in video_url.lower() or quality == 'FULL' else self.name} | {'1080p' if quality == 'FULL' else quality}"
|
|
201
210
|
|
|
202
211
|
# belgeselx.php redirect'ini çöz
|
|
203
212
|
if "belgeselx.php" in video_url or "belgeselx2.php" in video_url:
|
|
204
|
-
|
|
213
|
+
with suppress(Exception):
|
|
205
214
|
# HEAD isteği ile lokasyonu alalım
|
|
206
|
-
resp
|
|
215
|
+
resp = await self.httpx.head(video_url, headers={"Referer": main_url}, follow_redirects=True)
|
|
207
216
|
video_url = str(resp.url)
|
|
208
|
-
except:
|
|
209
|
-
pass
|
|
210
217
|
|
|
211
218
|
links.append(ExtractResult(
|
|
212
219
|
url = video_url,
|
|
213
|
-
name =
|
|
220
|
+
name = name,
|
|
214
221
|
referer = main_url
|
|
215
222
|
))
|
|
216
223
|
|
KekikStream/Plugins/DiziBox.py
CHANGED
|
@@ -1,7 +1,7 @@
|
|
|
1
1
|
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
2
|
|
|
3
|
-
from KekikStream.Core
|
|
4
|
-
from Kekik.Sifreleme
|
|
3
|
+
from KekikStream.Core import PluginBase, MainPageResult, SearchResult, SeriesInfo, Episode, ExtractResult, HTMLHelper
|
|
4
|
+
from Kekik.Sifreleme import CryptoJS
|
|
5
5
|
import urllib.parse, base64, contextlib, asyncio, time
|
|
6
6
|
|
|
7
7
|
class DiziBox(PluginBase):
|
|
@@ -52,8 +52,8 @@ class DiziBox(PluginBase):
|
|
|
52
52
|
|
|
53
53
|
results = []
|
|
54
54
|
for veri in secici.select("article.detailed-article"):
|
|
55
|
-
title
|
|
56
|
-
href
|
|
55
|
+
title = secici.select_text("h3 a", veri)
|
|
56
|
+
href = secici.select_attr("h3 a", "href", veri)
|
|
57
57
|
poster = secici.select_attr("img", "src", veri)
|
|
58
58
|
|
|
59
59
|
if title and href:
|
|
@@ -61,7 +61,7 @@ class DiziBox(PluginBase):
|
|
|
61
61
|
category = category,
|
|
62
62
|
title = title,
|
|
63
63
|
url = self.fix_url(href),
|
|
64
|
-
poster = self.fix_url(poster)
|
|
64
|
+
poster = self.fix_url(poster),
|
|
65
65
|
))
|
|
66
66
|
|
|
67
67
|
return results
|
|
@@ -84,7 +84,7 @@ class DiziBox(PluginBase):
|
|
|
84
84
|
results.append(SearchResult(
|
|
85
85
|
title = title,
|
|
86
86
|
url = self.fix_url(href),
|
|
87
|
-
poster = self.fix_url(poster)
|
|
87
|
+
poster = self.fix_url(poster),
|
|
88
88
|
))
|
|
89
89
|
|
|
90
90
|
return results
|
|
@@ -114,12 +114,12 @@ class DiziBox(PluginBase):
|
|
|
114
114
|
|
|
115
115
|
return SeriesInfo(
|
|
116
116
|
url = url,
|
|
117
|
-
poster = self.fix_url(poster)
|
|
117
|
+
poster = self.fix_url(poster),
|
|
118
118
|
title = title,
|
|
119
119
|
description = description,
|
|
120
120
|
tags = tags,
|
|
121
121
|
rating = rating,
|
|
122
|
-
year =
|
|
122
|
+
year = year,
|
|
123
123
|
episodes = episodes,
|
|
124
124
|
actors = actors,
|
|
125
125
|
)
|
|
@@ -182,13 +182,16 @@ class DiziBox(PluginBase):
|
|
|
182
182
|
istek = await self.httpx.get(url)
|
|
183
183
|
secici = HTMLHelper(istek.text)
|
|
184
184
|
|
|
185
|
-
|
|
185
|
+
# Aktif kaynağın adını bul (DBX Pro vs.)
|
|
186
|
+
current_source_name = secici.select_text("div.video-toolbar option[selected]") or self.name
|
|
187
|
+
|
|
188
|
+
results = []
|
|
186
189
|
main_iframe = secici.select_attr("div#video-area iframe", "src")
|
|
187
190
|
|
|
188
191
|
if main_iframe:
|
|
189
192
|
if decoded := await self._iframe_decode(self.name, main_iframe, url):
|
|
190
193
|
for iframe in decoded:
|
|
191
|
-
data = await self.extract(iframe)
|
|
194
|
+
data = await self.extract(iframe, name_override=current_source_name)
|
|
192
195
|
if data:
|
|
193
196
|
results.append(data)
|
|
194
197
|
|
|
@@ -209,7 +212,7 @@ class DiziBox(PluginBase):
|
|
|
209
212
|
if alt_iframe:
|
|
210
213
|
if decoded := await self._iframe_decode(alt_name, alt_iframe, url):
|
|
211
214
|
for iframe in decoded:
|
|
212
|
-
data = await self.extract(iframe,
|
|
215
|
+
data = await self.extract(iframe, name_override=alt_name)
|
|
213
216
|
if data:
|
|
214
217
|
results.append(data)
|
|
215
218
|
|
KekikStream/Plugins/DiziMom.py
CHANGED
|
@@ -1,8 +1,6 @@
|
|
|
1
1
|
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
2
|
|
|
3
|
-
from KekikStream.Core import PluginBase, MainPageResult, SearchResult,
|
|
4
|
-
from json import dumps, loads
|
|
5
|
-
import re
|
|
3
|
+
from KekikStream.Core import PluginBase, MainPageResult, SearchResult, SeriesInfo, Episode, ExtractResult, HTMLHelper
|
|
6
4
|
|
|
7
5
|
class DiziMom(PluginBase):
|
|
8
6
|
name = "DiziMom"
|
|
@@ -12,134 +10,160 @@ class DiziMom(PluginBase):
|
|
|
12
10
|
description = "Binlerce yerli yabancı dizi arşivi, tüm sezonlar, kesintisiz bölümler. Sadece dizi izle, Dizimom heryerde seninle!"
|
|
13
11
|
|
|
14
12
|
main_page = {
|
|
15
|
-
f"{main_url}/tum-bolumler/page"
|
|
16
|
-
f"{main_url}/yerli-dizi-izle/page"
|
|
17
|
-
f"{main_url}/yabanci-dizi-izle/page"
|
|
18
|
-
f"{main_url}/tv-programlari-izle/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ı",
|
|
19
26
|
}
|
|
20
27
|
|
|
21
28
|
async def get_main_page(self, page: int, url: str, category: str) -> list[MainPageResult]:
|
|
22
|
-
|
|
23
|
-
|
|
24
|
-
helper = HTMLHelper(istek.text)
|
|
29
|
+
istek = await self.httpx.get(f"{url}/{page}/")
|
|
30
|
+
secici = HTMLHelper(istek.text)
|
|
25
31
|
|
|
26
32
|
results = []
|
|
27
33
|
# Eğer "tum-bolumler" ise Episode kutularını, değilse Dizi kutularını tara
|
|
28
34
|
if "/tum-bolumler/" in url:
|
|
29
|
-
for item in
|
|
30
|
-
title =
|
|
31
|
-
href =
|
|
32
|
-
img =
|
|
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)
|
|
33
39
|
if title and href:
|
|
34
|
-
results.append(MainPageResult(
|
|
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
|
+
))
|
|
35
46
|
else:
|
|
36
|
-
for item in
|
|
37
|
-
title =
|
|
38
|
-
href =
|
|
39
|
-
img =
|
|
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)
|
|
40
51
|
if title and href:
|
|
41
|
-
results.append(MainPageResult(
|
|
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
|
+
))
|
|
42
58
|
|
|
43
59
|
return results
|
|
44
60
|
|
|
45
61
|
async def search(self, query: str) -> list[SearchResult]:
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
|
|
49
|
-
|
|
50
|
-
|
|
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
|
+
|
|
51
66
|
return [
|
|
52
67
|
SearchResult(
|
|
53
|
-
title =
|
|
54
|
-
url = self.fix_url(
|
|
55
|
-
poster = self.fix_url(
|
|
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))
|
|
56
71
|
)
|
|
57
72
|
for item in items
|
|
58
73
|
]
|
|
59
74
|
|
|
60
75
|
async def load_item(self, url: str) -> SeriesInfo:
|
|
61
76
|
istek = await self.httpx.get(url)
|
|
62
|
-
|
|
77
|
+
secici = HTMLHelper(istek.text)
|
|
63
78
|
|
|
64
|
-
title = self.clean_title(
|
|
65
|
-
poster =
|
|
66
|
-
description =
|
|
67
|
-
tags =
|
|
68
|
-
rating =
|
|
69
|
-
year =
|
|
70
|
-
actors =
|
|
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")
|
|
71
86
|
|
|
72
87
|
episodes = []
|
|
73
|
-
for item in
|
|
74
|
-
name =
|
|
75
|
-
href =
|
|
88
|
+
for item in secici.select("div.bolumust"):
|
|
89
|
+
name = secici.select_text("div.baslik", item)
|
|
90
|
+
href = secici.select_attr("a", "href", item)
|
|
76
91
|
if name and href:
|
|
77
|
-
s, e =
|
|
92
|
+
s, e = secici.extract_season_episode(name)
|
|
78
93
|
episodes.append(Episode(
|
|
79
94
|
season = s or 1,
|
|
80
95
|
episode = e or 1,
|
|
81
|
-
title = self.clean_title(name.replace(title
|
|
96
|
+
title = self.clean_title(name.replace(title, "").strip()),
|
|
82
97
|
url = self.fix_url(href)
|
|
83
98
|
))
|
|
84
99
|
|
|
85
100
|
return SeriesInfo(
|
|
86
101
|
url = url,
|
|
87
|
-
poster = self.fix_url(poster)
|
|
88
|
-
title = title
|
|
102
|
+
poster = self.fix_url(poster),
|
|
103
|
+
title = title,
|
|
89
104
|
description = description,
|
|
90
105
|
tags = tags,
|
|
91
106
|
rating = rating,
|
|
92
|
-
year =
|
|
107
|
+
year = year,
|
|
93
108
|
actors = actors,
|
|
94
109
|
episodes = episodes
|
|
95
110
|
)
|
|
96
111
|
|
|
97
112
|
async def load_links(self, url: str) -> list[ExtractResult]:
|
|
98
|
-
|
|
99
|
-
|
|
100
|
-
|
|
101
|
-
|
|
102
|
-
|
|
103
|
-
|
|
104
|
-
|
|
105
|
-
|
|
106
|
-
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
|
|
114
|
-
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
122
|
-
|
|
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
|
+
|
|
123
142
|
if main_iframe:
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
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")
|
|
127
147
|
for source in sources:
|
|
128
|
-
href =
|
|
148
|
+
href = secici.select_attr(None, "href", source)
|
|
149
|
+
name = secici.select_text("span.dil", source)
|
|
129
150
|
if href:
|
|
130
|
-
|
|
151
|
+
# Part sayfasına git
|
|
152
|
+
sub_istek = await self.httpx.get(href)
|
|
131
153
|
sub_helper = HTMLHelper(sub_istek.text)
|
|
132
|
-
sub_iframe = sub_helper.select_attr("div.video p iframe", "src")
|
|
154
|
+
sub_iframe = sub_helper.select_attr("div.video p iframe", "src") or sub_helper.select_attr("iframe[src]", "src")
|
|
155
|
+
|
|
133
156
|
if sub_iframe:
|
|
134
|
-
|
|
135
|
-
|
|
157
|
+
iframe_data.append((sub_iframe, name or f"{len(iframe_data)+1}.Kısım"))
|
|
158
|
+
|
|
136
159
|
results = []
|
|
137
|
-
for iframe_url in
|
|
138
|
-
#
|
|
139
|
-
|
|
140
|
-
|
|
141
|
-
|
|
142
|
-
extract_result = await self.extract(iframe_url)
|
|
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
|
+
|
|
143
167
|
if extract_result:
|
|
144
168
|
if isinstance(extract_result, list):
|
|
145
169
|
results.extend(extract_result)
|
|
@@ -147,9 +171,9 @@ class DiziMom(PluginBase):
|
|
|
147
171
|
results.append(extract_result)
|
|
148
172
|
else:
|
|
149
173
|
results.append(ExtractResult(
|
|
150
|
-
url
|
|
151
|
-
name
|
|
174
|
+
url = iframe_url,
|
|
175
|
+
name = f"{source_name} | External",
|
|
152
176
|
referer = self.main_url
|
|
153
177
|
))
|
|
154
|
-
|
|
178
|
+
|
|
155
179
|
return results
|