KekikStream 2.3.3__py3-none-any.whl → 2.3.4__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 +134 -0
- KekikStream/Core/Plugin/PluginBase.py +4 -1
- KekikStream/Core/__init__.py +2 -0
- KekikStream/Extractors/CloseLoad.py +12 -13
- KekikStream/Extractors/ContentX.py +12 -15
- KekikStream/Extractors/DonilasPlay.py +10 -10
- KekikStream/Extractors/DzenRu.py +3 -3
- KekikStream/Extractors/ExPlay.py +10 -10
- KekikStream/Extractors/Filemoon.py +11 -16
- KekikStream/Extractors/JetTv.py +4 -4
- KekikStream/Extractors/MixPlayHD.py +10 -11
- KekikStream/Extractors/MolyStream.py +5 -9
- KekikStream/Extractors/Odnoklassniki.py +4 -4
- KekikStream/Extractors/PeaceMakerst.py +3 -3
- KekikStream/Extractors/PixelDrain.py +6 -5
- KekikStream/Extractors/PlayerFilmIzle.py +6 -10
- KekikStream/Extractors/RapidVid.py +8 -7
- KekikStream/Extractors/SetPlay.py +10 -10
- KekikStream/Extractors/SetPrime.py +3 -6
- KekikStream/Extractors/SibNet.py +4 -5
- KekikStream/Extractors/Sobreatsesuyp.py +5 -5
- KekikStream/Extractors/TRsTX.py +5 -5
- KekikStream/Extractors/TurboImgz.py +3 -4
- KekikStream/Extractors/TurkeyPlayer.py +5 -5
- KekikStream/Extractors/VidHide.py +4 -7
- KekikStream/Extractors/VidMoly.py +24 -25
- KekikStream/Extractors/VidMoxy.py +8 -9
- KekikStream/Extractors/VidPapi.py +5 -7
- KekikStream/Extractors/VideoSeyred.py +3 -3
- KekikStream/Plugins/BelgeselX.py +40 -51
- KekikStream/Plugins/DiziBox.py +53 -81
- KekikStream/Plugins/DiziPal.py +41 -74
- KekikStream/Plugins/DiziYou.py +95 -88
- KekikStream/Plugins/Dizilla.py +51 -71
- KekikStream/Plugins/FilmBip.py +24 -49
- KekikStream/Plugins/FilmMakinesi.py +35 -52
- KekikStream/Plugins/FilmModu.py +27 -41
- KekikStream/Plugins/FullHDFilm.py +50 -72
- KekikStream/Plugins/FullHDFilmizlesene.py +35 -51
- KekikStream/Plugins/HDFilmCehennemi.py +48 -62
- KekikStream/Plugins/JetFilmizle.py +32 -50
- KekikStream/Plugins/KultFilmler.py +42 -67
- KekikStream/Plugins/RecTV.py +7 -4
- KekikStream/Plugins/RoketDizi.py +30 -50
- KekikStream/Plugins/SelcukFlix.py +15 -29
- KekikStream/Plugins/SetFilmIzle.py +41 -70
- KekikStream/Plugins/SezonlukDizi.py +47 -65
- KekikStream/Plugins/Sinefy.py +34 -50
- KekikStream/Plugins/SinemaCX.py +31 -55
- KekikStream/Plugins/Sinezy.py +27 -54
- KekikStream/Plugins/SuperFilmGeldi.py +25 -44
- KekikStream/Plugins/UgurFilm.py +23 -48
- {kekikstream-2.3.3.dist-info → kekikstream-2.3.4.dist-info}/METADATA +1 -1
- kekikstream-2.3.4.dist-info/RECORD +83 -0
- kekikstream-2.3.3.dist-info/RECORD +0 -82
- {kekikstream-2.3.3.dist-info → kekikstream-2.3.4.dist-info}/WHEEL +0 -0
- {kekikstream-2.3.3.dist-info → kekikstream-2.3.4.dist-info}/entry_points.txt +0 -0
- {kekikstream-2.3.3.dist-info → kekikstream-2.3.4.dist-info}/licenses/LICENSE +0 -0
- {kekikstream-2.3.3.dist-info → kekikstream-2.3.4.dist-info}/top_level.txt +0 -0
|
@@ -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, MovieInfo, SeriesInfo, Episode, ExtractResult
|
|
4
|
-
from selectolax.parser import HTMLParser
|
|
5
|
-
import re
|
|
3
|
+
from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo, SeriesInfo, Episode, ExtractResult, HTMLHelper
|
|
6
4
|
|
|
7
5
|
class FilmMakinesi(PluginBase):
|
|
8
6
|
name = "FilmMakinesi"
|
|
@@ -37,17 +35,13 @@ class FilmMakinesi(PluginBase):
|
|
|
37
35
|
|
|
38
36
|
async def get_main_page(self, page: int, url: str, category: str) -> list[MainPageResult]:
|
|
39
37
|
istek = self.cloudscraper.get(f"{url}{'' if page == 1 else f'page/{page}/'}")
|
|
40
|
-
secici =
|
|
38
|
+
secici = HTMLHelper(istek.text)
|
|
41
39
|
|
|
42
40
|
results = []
|
|
43
|
-
for veri in secici.
|
|
44
|
-
|
|
45
|
-
|
|
46
|
-
|
|
47
|
-
|
|
48
|
-
title = title_el.text(strip=True) if title_el else None
|
|
49
|
-
href = link_el.attrs.get("href") if link_el else None
|
|
50
|
-
poster = (img_el.attrs.get("data-src") or img_el.attrs.get("src")) if img_el else None
|
|
41
|
+
for veri in secici.select("div.item-relative"):
|
|
42
|
+
title = secici.select_text("div.title", veri)
|
|
43
|
+
href = secici.select_attr("a", "href", veri)
|
|
44
|
+
poster = secici.select_poster("img", veri)
|
|
51
45
|
|
|
52
46
|
if title and href:
|
|
53
47
|
results.append(MainPageResult(
|
|
@@ -61,17 +55,13 @@ class FilmMakinesi(PluginBase):
|
|
|
61
55
|
|
|
62
56
|
async def search(self, query: str) -> list[SearchResult]:
|
|
63
57
|
istek = await self.httpx.get(f"{self.main_url}/arama/?s={query}")
|
|
64
|
-
secici =
|
|
58
|
+
secici = HTMLHelper(istek.text)
|
|
65
59
|
|
|
66
60
|
results = []
|
|
67
|
-
for article in secici.
|
|
68
|
-
|
|
69
|
-
|
|
70
|
-
|
|
71
|
-
|
|
72
|
-
title = title_el.text(strip=True) if title_el else None
|
|
73
|
-
href = link_el.attrs.get("href") if link_el else None
|
|
74
|
-
poster = (img_el.attrs.get("data-src") or img_el.attrs.get("src")) if img_el else None
|
|
61
|
+
for article in secici.select("div.item-relative"):
|
|
62
|
+
title = secici.select_text("div.title", article)
|
|
63
|
+
href = secici.select_attr("a", "href", article)
|
|
64
|
+
poster = secici.select_poster("img", article)
|
|
75
65
|
|
|
76
66
|
if title and href:
|
|
77
67
|
results.append(SearchResult(
|
|
@@ -84,48 +74,42 @@ class FilmMakinesi(PluginBase):
|
|
|
84
74
|
|
|
85
75
|
async def load_item(self, url: str) -> MovieInfo | SeriesInfo:
|
|
86
76
|
istek = await self.httpx.get(url)
|
|
87
|
-
secici =
|
|
77
|
+
secici = HTMLHelper(istek.text)
|
|
88
78
|
|
|
89
|
-
|
|
90
|
-
title = title_el.text(strip=True) if title_el else ""
|
|
79
|
+
title = secici.select_text("h1.title") or ""
|
|
91
80
|
|
|
92
|
-
|
|
93
|
-
poster
|
|
81
|
+
poster = secici.select_attr("img.cover-img", "src") or ""
|
|
82
|
+
poster = poster.strip()
|
|
94
83
|
|
|
95
|
-
|
|
96
|
-
description = desc_el.text(strip=True) if desc_el else ""
|
|
84
|
+
description = secici.select_text("div.info-description p") or ""
|
|
97
85
|
|
|
98
|
-
|
|
99
|
-
rating
|
|
100
|
-
if
|
|
101
|
-
|
|
102
|
-
if rating_text:
|
|
103
|
-
rating = rating_text.split()[0]
|
|
86
|
+
rating_text = secici.select_text("div.score") or ""
|
|
87
|
+
rating = None
|
|
88
|
+
if rating_text:
|
|
89
|
+
rating = rating_text.split()[0]
|
|
104
90
|
|
|
105
|
-
|
|
106
|
-
year = year_el.text(strip=True) if year_el else ""
|
|
91
|
+
year = secici.select_text("span.date a") or ""
|
|
107
92
|
|
|
108
|
-
actors =
|
|
109
|
-
tags
|
|
93
|
+
actors = secici.select_all_text("div.cast-name")
|
|
94
|
+
tags = secici.select_all_text("div.genre a")
|
|
110
95
|
|
|
111
|
-
|
|
112
|
-
|
|
113
|
-
if
|
|
114
|
-
duration_text = duration_el.text(strip=True)
|
|
96
|
+
duration = None
|
|
97
|
+
duration_text = secici.select_text("div.time") or None
|
|
98
|
+
if duration_text:
|
|
115
99
|
parts = duration_text.split()
|
|
116
100
|
if len(parts) > 1:
|
|
117
101
|
duration = parts[1].strip()
|
|
118
102
|
|
|
119
103
|
# Dizi mi kontrol et - sezon/bölüm linkleri var mı?
|
|
120
104
|
episodes = []
|
|
121
|
-
all_links = secici.
|
|
105
|
+
all_links = secici.select("a[href]")
|
|
122
106
|
for link in all_links:
|
|
123
107
|
href = link.attrs.get("href", "")
|
|
124
|
-
|
|
125
|
-
if
|
|
126
|
-
season_no = int(
|
|
127
|
-
ep_no = int(
|
|
128
|
-
|
|
108
|
+
pairs = HTMLHelper(href).regex_all(r"/sezon-(\d+)/bolum-(\d+)")
|
|
109
|
+
if pairs:
|
|
110
|
+
season_no = int(pairs[0][0])
|
|
111
|
+
ep_no = int(pairs[0][1])
|
|
112
|
+
|
|
129
113
|
# Bölüm başlığını çıkar - text'ten gerçek ismi al
|
|
130
114
|
# Format: "22 Eylül 2014 / 44 dk /1. Sezon / 1. BölümPilot"
|
|
131
115
|
full_text = link.text(strip=True)
|
|
@@ -184,12 +168,12 @@ class FilmMakinesi(PluginBase):
|
|
|
184
168
|
|
|
185
169
|
async def load_links(self, url: str) -> list[ExtractResult]:
|
|
186
170
|
istek = await self.httpx.get(url)
|
|
187
|
-
secici =
|
|
171
|
+
secici = HTMLHelper(istek.text)
|
|
188
172
|
|
|
189
173
|
response = []
|
|
190
174
|
|
|
191
175
|
# Video parts linklerini ve etiketlerini al
|
|
192
|
-
for link in secici.
|
|
176
|
+
for link in secici.select("div.video-parts a[data-video_url]"):
|
|
193
177
|
video_url = link.attrs.get("data-video_url")
|
|
194
178
|
label = link.text(strip=True) if link.text(strip=True) else ""
|
|
195
179
|
|
|
@@ -200,8 +184,7 @@ class FilmMakinesi(PluginBase):
|
|
|
200
184
|
|
|
201
185
|
# Eğer video-parts yoksa iframe kullan
|
|
202
186
|
if not response:
|
|
203
|
-
|
|
204
|
-
iframe_src = iframe_el.attrs.get("data-src") if iframe_el else None
|
|
187
|
+
iframe_src = secici.select_attr("iframe", "data-src")
|
|
205
188
|
if iframe_src:
|
|
206
189
|
data = await self.extract(iframe_src)
|
|
207
190
|
if data:
|
KekikStream/Plugins/FilmModu.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, MovieInfo, Subtitle, ExtractResult
|
|
4
|
-
from selectolax.parser import HTMLParser
|
|
5
|
-
import re
|
|
3
|
+
from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo, Subtitle, ExtractResult, HTMLHelper
|
|
6
4
|
|
|
7
5
|
class FilmModu(PluginBase):
|
|
8
6
|
name = "FilmModu"
|
|
@@ -42,16 +40,13 @@ class FilmModu(PluginBase):
|
|
|
42
40
|
|
|
43
41
|
async def get_main_page(self, page: int, url: str, category: str) -> list[MainPageResult]:
|
|
44
42
|
istek = await self.httpx.get(url.replace("SAYFA", str(page)))
|
|
45
|
-
secici =
|
|
43
|
+
secici = HTMLHelper(istek.text)
|
|
46
44
|
|
|
47
45
|
results = []
|
|
48
|
-
for veri in secici.
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
title = link_el.text(strip=True) if link_el else None
|
|
53
|
-
href = link_el.attrs.get("href") if link_el else None
|
|
54
|
-
poster = img_el.attrs.get("data-src") if img_el else None
|
|
46
|
+
for veri in secici.select("div.movie"):
|
|
47
|
+
title = secici.select_text("a", veri)
|
|
48
|
+
href = secici.select_attr("a", "href", veri)
|
|
49
|
+
poster = secici.select_attr("picture img", "data-src", veri)
|
|
55
50
|
|
|
56
51
|
if title and href:
|
|
57
52
|
results.append(MainPageResult(
|
|
@@ -65,16 +60,13 @@ class FilmModu(PluginBase):
|
|
|
65
60
|
|
|
66
61
|
async def search(self, query: str) -> list[SearchResult]:
|
|
67
62
|
istek = await self.httpx.get(f"{self.main_url}/film-ara?term={query}")
|
|
68
|
-
secici =
|
|
63
|
+
secici = HTMLHelper(istek.text)
|
|
69
64
|
|
|
70
65
|
results = []
|
|
71
|
-
for veri in secici.
|
|
72
|
-
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
title = link_el.text(strip=True) if link_el else None
|
|
76
|
-
href = link_el.attrs.get("href") if link_el else None
|
|
77
|
-
poster = img_el.attrs.get("data-src") if img_el else None
|
|
66
|
+
for veri in secici.select("div.movie"):
|
|
67
|
+
title = secici.select_text("a", veri)
|
|
68
|
+
href = secici.select_attr("a", "href", veri)
|
|
69
|
+
poster = secici.select_attr("picture img", "data-src", veri)
|
|
78
70
|
|
|
79
71
|
if title and href:
|
|
80
72
|
results.append(SearchResult(
|
|
@@ -87,31 +79,25 @@ class FilmModu(PluginBase):
|
|
|
87
79
|
|
|
88
80
|
async def load_item(self, url: str) -> MovieInfo:
|
|
89
81
|
istek = await self.httpx.get(url)
|
|
90
|
-
secici =
|
|
91
|
-
|
|
92
|
-
org_title_el = secici.css_first("div.titles h1")
|
|
93
|
-
alt_title_el = secici.css_first("div.titles h2")
|
|
82
|
+
secici = HTMLHelper(istek.text)
|
|
94
83
|
|
|
95
|
-
org_title =
|
|
96
|
-
alt_title =
|
|
84
|
+
org_title = secici.select_text("div.titles h1") or ""
|
|
85
|
+
alt_title = secici.select_text("div.titles h2") or ""
|
|
97
86
|
title = f"{org_title} - {alt_title}" if alt_title else org_title
|
|
98
87
|
|
|
99
|
-
|
|
100
|
-
poster = poster_el.attrs.get("src") if poster_el else None
|
|
88
|
+
poster = secici.select_attr("img.img-responsive", "src") if secici.select_attr("img.img-responsive", "src") else None
|
|
101
89
|
|
|
102
|
-
|
|
103
|
-
description = desc_el.text(strip=True) if desc_el else None
|
|
90
|
+
description = secici.select_text("p[itemprop='description']") or None
|
|
104
91
|
|
|
105
|
-
tags =
|
|
92
|
+
tags = secici.select_all_text("a[href*='film-tur/']")
|
|
106
93
|
|
|
107
|
-
|
|
108
|
-
year = year_el.text(strip=True) if year_el else None
|
|
94
|
+
year = secici.select_text("span[itemprop='dateCreated']") or None
|
|
109
95
|
|
|
110
96
|
actors = []
|
|
111
|
-
for a in secici.
|
|
112
|
-
|
|
113
|
-
if
|
|
114
|
-
actors.append(
|
|
97
|
+
for a in secici.select("a[itemprop='actor']"):
|
|
98
|
+
name = secici.select_text("span", a)
|
|
99
|
+
if name:
|
|
100
|
+
actors.append(name)
|
|
115
101
|
|
|
116
102
|
return MovieInfo(
|
|
117
103
|
url = url,
|
|
@@ -125,9 +111,9 @@ class FilmModu(PluginBase):
|
|
|
125
111
|
|
|
126
112
|
async def load_links(self, url: str) -> list[ExtractResult]:
|
|
127
113
|
istek = await self.httpx.get(url)
|
|
128
|
-
secici =
|
|
114
|
+
secici = HTMLHelper(istek.text)
|
|
129
115
|
|
|
130
|
-
alternates = secici.
|
|
116
|
+
alternates = secici.select("div.alternates a")
|
|
131
117
|
if not alternates:
|
|
132
118
|
return []
|
|
133
119
|
|
|
@@ -144,14 +130,14 @@ class FilmModu(PluginBase):
|
|
|
144
130
|
alt_istek = await self.httpx.get(alt_link)
|
|
145
131
|
alt_text = alt_istek.text
|
|
146
132
|
|
|
147
|
-
vid_id =
|
|
148
|
-
vid_type =
|
|
133
|
+
vid_id = HTMLHelper(alt_text).regex_first(r"var videoId = '([^']*)'")
|
|
134
|
+
vid_type = HTMLHelper(alt_text).regex_first(r"var videoType = '([^']*)'")
|
|
149
135
|
|
|
150
136
|
if not vid_id or not vid_type:
|
|
151
137
|
continue
|
|
152
138
|
|
|
153
139
|
source_istek = await self.httpx.get(
|
|
154
|
-
f"{self.main_url}/get-source?movie_id={vid_id
|
|
140
|
+
f"{self.main_url}/get-source?movie_id={vid_id}&type={vid_type}"
|
|
155
141
|
)
|
|
156
142
|
source_data = source_istek.json()
|
|
157
143
|
|
|
@@ -1,8 +1,7 @@
|
|
|
1
1
|
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
2
|
|
|
3
|
-
from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo, SeriesInfo, Episode, ExtractResult, Subtitle
|
|
4
|
-
|
|
5
|
-
import re, base64
|
|
3
|
+
from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo, SeriesInfo, Episode, ExtractResult, Subtitle, HTMLHelper
|
|
4
|
+
import base64
|
|
6
5
|
|
|
7
6
|
class FullHDFilm(PluginBase):
|
|
8
7
|
name = "FullHDFilm"
|
|
@@ -48,16 +47,13 @@ class FullHDFilm(PluginBase):
|
|
|
48
47
|
})
|
|
49
48
|
|
|
50
49
|
istek = await self.httpx.get(page_url)
|
|
51
|
-
secici =
|
|
50
|
+
secici = HTMLHelper(istek.text)
|
|
52
51
|
|
|
53
52
|
results = []
|
|
54
|
-
for veri in secici.
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
alt = img_el.attrs.get("alt") if img_el else None
|
|
59
|
-
poster = img_el.attrs.get("src") if img_el else None
|
|
60
|
-
href = link_el.attrs.get("href") if link_el else None
|
|
53
|
+
for veri in secici.select("div.movie-poster"):
|
|
54
|
+
alt = secici.select_attr("img", "alt", veri)
|
|
55
|
+
poster = secici.select_attr("img", "src", veri)
|
|
56
|
+
href = secici.select_attr("a", "href", veri)
|
|
61
57
|
|
|
62
58
|
if alt and href:
|
|
63
59
|
results.append(MainPageResult(
|
|
@@ -71,16 +67,13 @@ class FullHDFilm(PluginBase):
|
|
|
71
67
|
|
|
72
68
|
async def search(self, query: str) -> list[SearchResult]:
|
|
73
69
|
istek = await self.httpx.get(f"{self.main_url}/?s={query}")
|
|
74
|
-
secici =
|
|
70
|
+
secici = HTMLHelper(istek.text)
|
|
75
71
|
|
|
76
72
|
results = []
|
|
77
|
-
for veri in secici.
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
alt = img_el.attrs.get("alt") if img_el else None
|
|
82
|
-
poster = img_el.attrs.get("src") if img_el else None
|
|
83
|
-
href = link_el.attrs.get("href") if link_el else None
|
|
73
|
+
for veri in secici.select("div.movie-poster"):
|
|
74
|
+
alt = secici.select_attr("img", "alt", veri)
|
|
75
|
+
poster = secici.select_attr("img", "src", veri)
|
|
76
|
+
href = secici.select_attr("a", "href", veri)
|
|
84
77
|
|
|
85
78
|
if alt and href:
|
|
86
79
|
results.append(SearchResult(
|
|
@@ -93,75 +86,59 @@ class FullHDFilm(PluginBase):
|
|
|
93
86
|
|
|
94
87
|
async def load_item(self, url: str) -> MovieInfo | SeriesInfo:
|
|
95
88
|
istek = await self.httpx.get(url)
|
|
96
|
-
secici =
|
|
89
|
+
secici = HTMLHelper(istek.text)
|
|
97
90
|
html_text = istek.text
|
|
98
91
|
|
|
99
|
-
|
|
100
|
-
title = title_el.text(strip=True) if title_el else ""
|
|
92
|
+
title = secici.select_text("h1") or ""
|
|
101
93
|
|
|
102
|
-
|
|
103
|
-
poster
|
|
94
|
+
poster = secici.select_attr("div.poster img", "src") or ""
|
|
95
|
+
poster = self.fix_url(poster)
|
|
104
96
|
|
|
105
|
-
actors_el = secici.css_first("div.oyuncular.info")
|
|
106
97
|
actors = []
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
|
|
110
|
-
|
|
111
|
-
actors = [a.strip() for a in actors_text.split(",")]
|
|
98
|
+
actors_text = secici.select_text("div.oyuncular.info")
|
|
99
|
+
if actors_text:
|
|
100
|
+
actors_text = actors_text.replace("Oyuncular:", "").strip()
|
|
101
|
+
actors = [a.strip() for a in actors_text.split(",")]
|
|
112
102
|
|
|
113
103
|
# Year: önce div.yayin-tarihi.info dene
|
|
114
|
-
year =
|
|
115
|
-
|
|
116
|
-
if year_el:
|
|
117
|
-
year_text = year_el.text(strip=True)
|
|
118
|
-
year_match = re.search(r"(\d{4})", year_text)
|
|
119
|
-
if year_match:
|
|
120
|
-
year = year_match.group(1)
|
|
121
|
-
|
|
104
|
+
year = secici.extract_year("div.yayin-tarihi.info")
|
|
105
|
+
|
|
122
106
|
# Fallback: h1'in parent'ından (2019) formatında ara
|
|
123
|
-
if not year
|
|
124
|
-
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
|
|
128
|
-
|
|
129
|
-
year = year_match.group(1)
|
|
107
|
+
if not year:
|
|
108
|
+
# Parent'ın tüm text içeriğinden yıl çıkar
|
|
109
|
+
title_text = secici.select_text("h1")
|
|
110
|
+
if title_text:
|
|
111
|
+
# h1 parent'ındaki (2019) gibi text'i bul
|
|
112
|
+
year = secici.regex_first(r"\((\d{4})\)")
|
|
130
113
|
|
|
131
|
-
tags =
|
|
114
|
+
tags = secici.select_all_text("div.tur.info a")
|
|
132
115
|
|
|
133
116
|
# Rating: regex
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
rating_match = re.search(r"IMDb\s*([\d\.]+)", rating_text)
|
|
137
|
-
rating = rating_match.group(1) if rating_match else None
|
|
117
|
+
rating_text = secici.select_text("div.imdb") or ""
|
|
118
|
+
rating = HTMLHelper(rating_text).regex_first(r"IMDb\s*([\d\.]+)")
|
|
138
119
|
|
|
139
120
|
# Description: önce div.film dene, yoksa og:description meta tag'ını kullan
|
|
140
|
-
description =
|
|
141
|
-
desc_el = secici.css_first("div.film")
|
|
142
|
-
if desc_el:
|
|
143
|
-
description = desc_el.text(strip=True)
|
|
121
|
+
description = secici.select_text("div.film")
|
|
144
122
|
|
|
145
123
|
# Fallback: og:description meta tag'ı
|
|
146
124
|
if not description:
|
|
147
|
-
og_desc = secici.
|
|
125
|
+
og_desc = secici.select_attr("meta[property='og:description']", "content")
|
|
148
126
|
if og_desc:
|
|
149
|
-
description = og_desc
|
|
127
|
+
description = og_desc
|
|
150
128
|
|
|
151
129
|
# Kotlin referansı: URL'de -dizi kontrolü veya tags içinde "dizi" kontrolü
|
|
152
130
|
is_series = "-dizi" in url.lower() or any("dizi" in tag.lower() for tag in tags)
|
|
153
131
|
|
|
154
132
|
if is_series:
|
|
155
133
|
episodes = []
|
|
156
|
-
part_elements = secici.
|
|
134
|
+
part_elements = secici.select("li.psec")
|
|
157
135
|
|
|
158
136
|
# pdata değerlerini çıkar
|
|
159
|
-
pdata_matches =
|
|
137
|
+
pdata_matches = HTMLHelper(html_text).regex_all(r"pdata\['([^']+)'\]\s*=\s*'([^']+)'")
|
|
160
138
|
|
|
161
139
|
for idx, el in enumerate(part_elements):
|
|
162
140
|
part_id = el.attrs.get("id")
|
|
163
|
-
|
|
164
|
-
part_name = link_el.text(strip=True) if link_el else None
|
|
141
|
+
part_name = secici.select_text("a", el)
|
|
165
142
|
|
|
166
143
|
if not part_name:
|
|
167
144
|
continue
|
|
@@ -171,11 +148,11 @@ class FullHDFilm(PluginBase):
|
|
|
171
148
|
continue
|
|
172
149
|
|
|
173
150
|
# Sezon ve bölüm numarası çıkar
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
sz_num = int(
|
|
178
|
-
ep_num = int(
|
|
151
|
+
sz_val = HTMLHelper(part_id.lower() if part_id else "").regex_first(r'(\d+)\s*sezon')
|
|
152
|
+
ep_val = HTMLHelper(part_name).regex_first(r'^(\d+)\.')
|
|
153
|
+
|
|
154
|
+
sz_num = int(sz_val) if sz_val and sz_val.isdigit() else 1
|
|
155
|
+
ep_num = int(ep_val) if ep_val and ep_val.isdigit() else idx + 1
|
|
179
156
|
|
|
180
157
|
# pdata'dan video URL'si çık (varsa)
|
|
181
158
|
video_url = url # Varsayılan olarak ana URL kullan
|
|
@@ -214,14 +191,14 @@ class FullHDFilm(PluginBase):
|
|
|
214
191
|
|
|
215
192
|
def _get_iframe(self, source_code: str) -> str:
|
|
216
193
|
"""Base64 kodlu iframe'i çözümle"""
|
|
217
|
-
|
|
218
|
-
if not
|
|
194
|
+
script_val = HTMLHelper(source_code).regex_first(r'<script[^>]*>(PCEtLWJhc2xpazp[^<]*)</script>')
|
|
195
|
+
if not script_val:
|
|
219
196
|
return ""
|
|
220
197
|
|
|
221
198
|
try:
|
|
222
|
-
decoded_html = base64.b64decode(
|
|
223
|
-
|
|
224
|
-
return self.fix_url(
|
|
199
|
+
decoded_html = base64.b64decode(script_val).decode("utf-8")
|
|
200
|
+
iframe_src = HTMLHelper(decoded_html).regex_first(r'<iframe[^>]+src=["\']([^"\']+)["\']')
|
|
201
|
+
return self.fix_url(iframe_src) if iframe_src else ""
|
|
225
202
|
except Exception:
|
|
226
203
|
return ""
|
|
227
204
|
|
|
@@ -234,8 +211,9 @@ class FullHDFilm(PluginBase):
|
|
|
234
211
|
]
|
|
235
212
|
|
|
236
213
|
for pattern in patterns:
|
|
237
|
-
|
|
238
|
-
|
|
214
|
+
val = HTMLHelper(source_code).regex_first(pattern)
|
|
215
|
+
if val:
|
|
216
|
+
return val
|
|
239
217
|
|
|
240
218
|
return None
|
|
241
219
|
|
|
@@ -1,9 +1,8 @@
|
|
|
1
1
|
# Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
2
|
|
|
3
|
-
from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo, ExtractResult
|
|
4
|
-
from selectolax.parser import HTMLParser
|
|
3
|
+
from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo, ExtractResult, HTMLHelper
|
|
5
4
|
from Kekik.Sifreleme import StringCodec
|
|
6
|
-
import json
|
|
5
|
+
import json
|
|
7
6
|
|
|
8
7
|
class FullHDFilmizlesene(PluginBase):
|
|
9
8
|
name = "FullHDFilmizlesene"
|
|
@@ -42,17 +41,13 @@ class FullHDFilmizlesene(PluginBase):
|
|
|
42
41
|
|
|
43
42
|
async def get_main_page(self, page: int, url: str, category: str) -> list[MainPageResult]:
|
|
44
43
|
istek = self.cloudscraper.get(f"{url}{page}")
|
|
45
|
-
secici =
|
|
44
|
+
secici = HTMLHelper(istek.text)
|
|
46
45
|
|
|
47
46
|
results = []
|
|
48
|
-
for veri in secici.
|
|
49
|
-
|
|
50
|
-
|
|
51
|
-
|
|
52
|
-
|
|
53
|
-
title = title_el.text(strip=True) if title_el else None
|
|
54
|
-
href = link_el.attrs.get("href") if link_el else None
|
|
55
|
-
poster = img_el.attrs.get("data-src") if img_el else None
|
|
47
|
+
for veri in secici.select("li.film"):
|
|
48
|
+
title = secici.select_text("span.film-title", veri)
|
|
49
|
+
href = secici.select_attr("a", "href", veri)
|
|
50
|
+
poster = secici.select_attr("img", "data-src", veri)
|
|
56
51
|
|
|
57
52
|
if title and href:
|
|
58
53
|
results.append(MainPageResult(
|
|
@@ -66,17 +61,13 @@ class FullHDFilmizlesene(PluginBase):
|
|
|
66
61
|
|
|
67
62
|
async def search(self, query: str) -> list[SearchResult]:
|
|
68
63
|
istek = await self.httpx.get(f"{self.main_url}/arama/{query}")
|
|
69
|
-
secici =
|
|
64
|
+
secici = HTMLHelper(istek.text)
|
|
70
65
|
|
|
71
66
|
results = []
|
|
72
|
-
for film in secici.
|
|
73
|
-
|
|
74
|
-
|
|
75
|
-
|
|
76
|
-
|
|
77
|
-
title = title_el.text(strip=True) if title_el else None
|
|
78
|
-
href = link_el.attrs.get("href") if link_el else None
|
|
79
|
-
poster = img_el.attrs.get("data-src") if img_el else None
|
|
67
|
+
for film in secici.select("li.film"):
|
|
68
|
+
title = secici.select_text("span.film-title", film)
|
|
69
|
+
href = secici.select_attr("a", "href", film)
|
|
70
|
+
poster = secici.select_attr("img", "data-src", film)
|
|
80
71
|
|
|
81
72
|
if title and href:
|
|
82
73
|
results.append(SearchResult(
|
|
@@ -89,49 +80,42 @@ class FullHDFilmizlesene(PluginBase):
|
|
|
89
80
|
|
|
90
81
|
async def load_item(self, url: str) -> MovieInfo:
|
|
91
82
|
istek = await self.httpx.get(url)
|
|
92
|
-
secici =
|
|
83
|
+
secici = HTMLHelper(istek.text)
|
|
93
84
|
html_text = istek.text
|
|
94
85
|
|
|
95
86
|
# Title: normalize-space yerine doğrudan class ile
|
|
96
|
-
|
|
97
|
-
title = title_el.text(strip=True) if title_el else ""
|
|
87
|
+
title = secici.select_text("div.izle-titles") or ""
|
|
98
88
|
|
|
99
|
-
|
|
100
|
-
poster =
|
|
89
|
+
poster = secici.select_attr("div img[data-src]", "data-src") or ""
|
|
90
|
+
poster = poster.strip()
|
|
101
91
|
|
|
102
|
-
|
|
103
|
-
description = desc_el.text(strip=True) if desc_el else ""
|
|
92
|
+
description = secici.select_text("div.ozet-ic p") or ""
|
|
104
93
|
|
|
105
|
-
tags =
|
|
94
|
+
tags = secici.select_all_text("a[rel='category tag']")
|
|
106
95
|
|
|
107
96
|
# Rating: normalize-space yerine doğrudan class ile ve son kelimeyi al
|
|
108
|
-
|
|
97
|
+
rating_text = secici.select_text("div.puanx-puan") or None
|
|
109
98
|
rating = None
|
|
110
|
-
if
|
|
111
|
-
|
|
112
|
-
if
|
|
113
|
-
parts = rating_text.split()
|
|
114
|
-
rating = parts[-1] if parts else None
|
|
99
|
+
if rating_text:
|
|
100
|
+
parts = rating_text.split()
|
|
101
|
+
rating = parts[-1] if parts else None
|
|
115
102
|
|
|
116
103
|
# Year: ilk yıl formatında değer
|
|
117
|
-
|
|
104
|
+
year_text = secici.select_text("div.dd a.category") or None
|
|
118
105
|
year = None
|
|
119
|
-
if
|
|
120
|
-
|
|
121
|
-
if
|
|
122
|
-
parts = year_text.split()
|
|
123
|
-
year = parts[0] if parts else None
|
|
106
|
+
if year_text:
|
|
107
|
+
parts = year_text.split()
|
|
108
|
+
year = parts[0] if parts else None
|
|
124
109
|
|
|
125
110
|
# Actors: nth-child yerine tüm li'leri alıp 2. index
|
|
126
|
-
lis = secici.
|
|
111
|
+
lis = secici.select("div.film-info ul li")
|
|
127
112
|
actors = []
|
|
128
113
|
if len(lis) >= 2:
|
|
129
|
-
actors =
|
|
114
|
+
actors = secici.select_all_text("a > span", lis[1])
|
|
130
115
|
|
|
131
|
-
duration_el = secici.css_first("span.sure")
|
|
132
116
|
duration = "0"
|
|
133
|
-
|
|
134
|
-
|
|
117
|
+
duration_text = secici.select_text("span.sure") or None
|
|
118
|
+
if duration_text:
|
|
135
119
|
duration_parts = duration_text.split()
|
|
136
120
|
duration = duration_parts[0] if duration_parts else "0"
|
|
137
121
|
|
|
@@ -149,18 +133,18 @@ class FullHDFilmizlesene(PluginBase):
|
|
|
149
133
|
|
|
150
134
|
async def load_links(self, url: str) -> list[ExtractResult]:
|
|
151
135
|
istek = await self.httpx.get(url)
|
|
152
|
-
secici =
|
|
136
|
+
secici = HTMLHelper(istek.text)
|
|
153
137
|
html_text = istek.text
|
|
154
138
|
|
|
155
139
|
# İlk script'i al (xpath (//script)[1] yerine)
|
|
156
|
-
scripts = secici.
|
|
140
|
+
scripts = secici.select("script")
|
|
157
141
|
script_content = scripts[0].text() if scripts else ""
|
|
158
142
|
|
|
159
|
-
|
|
160
|
-
if not
|
|
143
|
+
scx_json = HTMLHelper(script_content).regex_first(r"scx = (.*?);")
|
|
144
|
+
if not scx_json:
|
|
161
145
|
return []
|
|
162
146
|
|
|
163
|
-
scx_data = json.loads(
|
|
147
|
+
scx_data = json.loads(scx_json)
|
|
164
148
|
scx_keys = list(scx_data.keys())
|
|
165
149
|
|
|
166
150
|
link_list = []
|