KekikStream 2.4.5__py3-none-any.whl → 2.4.6__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/HTMLHelper.py +19 -42
- KekikStream/Extractors/VidMoly.py +2 -2
- KekikStream/Plugins/BelgeselX.py +23 -4
- KekikStream/Plugins/DiziMom.py +1 -1
- KekikStream/Plugins/SinemaCX.py +1 -1
- {kekikstream-2.4.5.dist-info → kekikstream-2.4.6.dist-info}/METADATA +1 -1
- {kekikstream-2.4.5.dist-info → kekikstream-2.4.6.dist-info}/RECORD +11 -11
- {kekikstream-2.4.5.dist-info → kekikstream-2.4.6.dist-info}/WHEEL +0 -0
- {kekikstream-2.4.5.dist-info → kekikstream-2.4.6.dist-info}/entry_points.txt +0 -0
- {kekikstream-2.4.5.dist-info → kekikstream-2.4.6.dist-info}/licenses/LICENSE +0 -0
- {kekikstream-2.4.5.dist-info → kekikstream-2.4.6.dist-info}/top_level.txt +0 -0
KekikStream/Core/HTMLHelper.py
CHANGED
|
@@ -33,19 +33,19 @@ class HTMLHelper:
|
|
|
33
33
|
return element
|
|
34
34
|
return self._root(element).css_first(selector)
|
|
35
35
|
|
|
36
|
-
def select_text(self, selector: str | None = None, element: Node | None = None
|
|
36
|
+
def select_text(self, selector: str | None = None, element: Node | None = None) -> str | None:
|
|
37
37
|
"""CSS selector ile element bul ve text içeriğini döndür."""
|
|
38
38
|
el = self.select_first(selector, element)
|
|
39
39
|
if not el:
|
|
40
40
|
return None
|
|
41
|
-
val = el.text(strip=
|
|
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
|
|
44
|
+
def select_texts(self, selector: str, element: Node | None = None) -> list[str]:
|
|
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
|
-
txt = el.text(strip=
|
|
48
|
+
txt = el.text(strip=True)
|
|
49
49
|
if txt:
|
|
50
50
|
out.append(txt)
|
|
51
51
|
return out
|
|
@@ -71,42 +71,23 @@ class HTMLHelper:
|
|
|
71
71
|
return None
|
|
72
72
|
return el.attrs.get("data-src") or el.attrs.get("src")
|
|
73
73
|
|
|
74
|
-
def select_direct_text(self, selector: str, element: Node | None = None
|
|
74
|
+
def select_direct_text(self, selector: str, element: Node | None = None) -> str | None:
|
|
75
75
|
"""
|
|
76
76
|
Elementin yalnızca "kendi" düz metnini döndürür (child elementlerin text'ini katmadan).
|
|
77
|
-
Selectolax sürüm farklarına göre deep=False dene, yoksa node sibling-walk ile fallback yapar.
|
|
78
77
|
"""
|
|
79
78
|
el = self.select_first(selector, element)
|
|
80
79
|
if not el:
|
|
81
80
|
return None
|
|
82
81
|
|
|
83
|
-
#
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
return val or None
|
|
87
|
-
except TypeError:
|
|
88
|
-
pass # deep parametresi yok, fallback'e geç
|
|
89
|
-
|
|
90
|
-
# 2) Fallback: direct children'ı el.child + next ile dolaş
|
|
91
|
-
parts: list[str] = []
|
|
92
|
-
ch = el.child
|
|
93
|
-
while ch is not None:
|
|
94
|
-
if ch.tag == "-text":
|
|
95
|
-
t = ch.text(strip=strip)
|
|
96
|
-
if t:
|
|
97
|
-
parts.append(t)
|
|
98
|
-
elif ch.tag == "br":
|
|
99
|
-
parts.append("\n")
|
|
100
|
-
ch = ch.next
|
|
101
|
-
|
|
102
|
-
out = "".join(parts).strip()
|
|
103
|
-
return out or None
|
|
82
|
+
# type: ignore[call-arg]
|
|
83
|
+
val = el.text(strip=True, deep=False)
|
|
84
|
+
return val or None
|
|
104
85
|
|
|
105
86
|
# ========================
|
|
106
87
|
# META (LABEL -> VALUE) İŞLEMLERİ
|
|
107
88
|
# ========================
|
|
108
89
|
|
|
109
|
-
def meta_value(self, label: str, container_selector: str | None = None
|
|
90
|
+
def meta_value(self, label: str, container_selector: str | None = None) -> str | None:
|
|
110
91
|
"""
|
|
111
92
|
Herhangi bir container içinde: LABEL metnini içeren bir elementten SONRA gelen metni döndürür.
|
|
112
93
|
label örn: "Oyuncular", "Yapım Yılı", "IMDB"
|
|
@@ -127,7 +108,7 @@ class HTMLHelper:
|
|
|
127
108
|
|
|
128
109
|
# 1) Elementin kendi içindeki text'te LABEL: VALUE formatı olabilir
|
|
129
110
|
# "Oyuncular: Brad Pitt" gibi. LABEL: sonrasını al.
|
|
130
|
-
full_txt = label_el.text(strip=
|
|
111
|
+
full_txt = label_el.text(strip=True)
|
|
131
112
|
if ":" in full_txt and needle in full_txt.split(":")[0].casefold():
|
|
132
113
|
val = full_txt.split(":", 1)[1].strip()
|
|
133
114
|
if val: return val
|
|
@@ -136,10 +117,10 @@ class HTMLHelper:
|
|
|
136
117
|
curr = label_el.next
|
|
137
118
|
while curr:
|
|
138
119
|
if curr.tag == "-text":
|
|
139
|
-
val = curr.text(strip=
|
|
120
|
+
val = curr.text(strip=True).strip(" :")
|
|
140
121
|
if val: return val
|
|
141
122
|
elif curr.tag != "br":
|
|
142
|
-
val = curr.text(strip=
|
|
123
|
+
val = curr.text(strip=True).strip(" :")
|
|
143
124
|
if val: return val
|
|
144
125
|
else: # <br> gördüysek satır bitmiştir
|
|
145
126
|
break
|
|
@@ -175,29 +156,25 @@ class HTMLHelper:
|
|
|
175
156
|
"""Regex için kaynak metni döndürür."""
|
|
176
157
|
return target if isinstance(target, str) else self.html
|
|
177
158
|
|
|
178
|
-
def
|
|
179
|
-
"""Regex flags değerini döndürür."""
|
|
180
|
-
return target if isinstance(target, int) else flags
|
|
181
|
-
|
|
182
|
-
def regex_first(self, pattern: str, target: str | int | None = None, flags: int = 0, group: int | None = 1) -> str | tuple | None:
|
|
159
|
+
def regex_first(self, pattern: str, target: str | int | None = None, group: int | None = 1) -> str | tuple | None:
|
|
183
160
|
"""Regex ile arama yap, istenen grubu döndür (group=None ise tüm grupları tuple olarak döndür)."""
|
|
184
|
-
match = re.search(pattern, self._regex_source(target)
|
|
161
|
+
match = re.search(pattern, self._regex_source(target))
|
|
185
162
|
if not match:
|
|
186
163
|
return None
|
|
187
|
-
|
|
164
|
+
|
|
188
165
|
if group is None:
|
|
189
166
|
return match.groups()
|
|
190
167
|
|
|
191
168
|
last_idx = match.lastindex or 0
|
|
192
169
|
return match.group(group) if last_idx >= group else match.group(0)
|
|
193
170
|
|
|
194
|
-
def regex_all(self, pattern: str, target: str | int | None = None
|
|
171
|
+
def regex_all(self, pattern: str, target: str | int | None = None) -> list[str] | list[tuple]:
|
|
195
172
|
"""Regex ile tüm eşleşmeleri döndür."""
|
|
196
|
-
return re.findall(pattern, self._regex_source(target)
|
|
173
|
+
return re.findall(pattern, self._regex_source(target))
|
|
197
174
|
|
|
198
|
-
def regex_replace(self, pattern: str, repl: str, target: str | int | None = None
|
|
175
|
+
def regex_replace(self, pattern: str, repl: str, target: str | int | None = None) -> str:
|
|
199
176
|
"""Regex ile replace yap."""
|
|
200
|
-
return re.sub(pattern, repl, self._regex_source(target)
|
|
177
|
+
return re.sub(pattern, repl, self._regex_source(target))
|
|
201
178
|
|
|
202
179
|
# ========================
|
|
203
180
|
# ÖZEL AYIKLAYICILAR
|
|
@@ -47,7 +47,7 @@ class VidMoly(ExtractorBase):
|
|
|
47
47
|
|
|
48
48
|
# Altyazı kaynaklarını ayrıştır
|
|
49
49
|
subtitles = []
|
|
50
|
-
if sub_str := sel.regex_first(r"tracks:\s*\[(.*?)\]"
|
|
50
|
+
if sub_str := sel.regex_first(r"(?s)tracks:\s*\[(.*?)\]"):
|
|
51
51
|
sub_data = self._add_marks(sub_str, "file")
|
|
52
52
|
sub_data = self._add_marks(sub_data, "label")
|
|
53
53
|
sub_data = self._add_marks(sub_data, "kind")
|
|
@@ -68,7 +68,7 @@ class VidMoly(ExtractorBase):
|
|
|
68
68
|
break
|
|
69
69
|
|
|
70
70
|
if not video_url:
|
|
71
|
-
if src_str := sel.regex_first(r"sources:\s*\[(.*?)\],"
|
|
71
|
+
if src_str := sel.regex_first(r"(?s)sources:\s*\[(.*?)\],"):
|
|
72
72
|
vid_data = self._add_marks(src_str, "file")
|
|
73
73
|
with contextlib.suppress(json.JSONDecodeError):
|
|
74
74
|
vid_sources = json.loads(f"[{vid_data}]")
|
KekikStream/Plugins/BelgeselX.py
CHANGED
|
@@ -34,10 +34,29 @@ class BelgeselX(PluginBase):
|
|
|
34
34
|
@staticmethod
|
|
35
35
|
def _to_title_case(text: str) -> str:
|
|
36
36
|
"""Türkçe için title case dönüşümü."""
|
|
37
|
-
|
|
38
|
-
|
|
39
|
-
|
|
40
|
-
)
|
|
37
|
+
if not text:
|
|
38
|
+
return ""
|
|
39
|
+
|
|
40
|
+
words = text.split()
|
|
41
|
+
new_words = []
|
|
42
|
+
|
|
43
|
+
for word in words:
|
|
44
|
+
# Önce Türkçe karakterleri koruyarak küçült
|
|
45
|
+
# İ -> i, I -> ı
|
|
46
|
+
word = word.replace("İ", "i").replace("I", "ı").lower()
|
|
47
|
+
|
|
48
|
+
# Sonra ilk harfi Türkçe kurallarına göre büyüt
|
|
49
|
+
if word:
|
|
50
|
+
if word[0] == "i":
|
|
51
|
+
word = "İ" + word[1:]
|
|
52
|
+
elif word[0] == "ı":
|
|
53
|
+
word = "I" + word[1:]
|
|
54
|
+
else:
|
|
55
|
+
word = word[0].upper() + word[1:]
|
|
56
|
+
|
|
57
|
+
new_words.append(word)
|
|
58
|
+
|
|
59
|
+
return " ".join(new_words)
|
|
41
60
|
|
|
42
61
|
async def get_main_page(self, page: int, url: str, category: str) -> list[MainPageResult]:
|
|
43
62
|
istek = self.cloudscraper.get(f"{url}{page}")
|
KekikStream/Plugins/DiziMom.py
CHANGED
|
@@ -65,7 +65,7 @@ class DiziMom(PluginBase):
|
|
|
65
65
|
poster = helper.select_poster("div.category_image img")
|
|
66
66
|
description = helper.select_direct_text("div.category_desc")
|
|
67
67
|
tags = helper.select_texts("div.genres a")
|
|
68
|
-
rating = helper.regex_first(r"IMDB\s*:\s*(?:</span>)?\s*([\d\.]+)", helper.html
|
|
68
|
+
rating = helper.regex_first(r"(?s)IMDB\s*:\s*(?:</span>)?\s*([\d\.]+)", helper.html)
|
|
69
69
|
year = helper.extract_year("div.category_text")
|
|
70
70
|
actors = helper.meta_list("Oyuncular", container_selector="div#icerikcat2")
|
|
71
71
|
|
KekikStream/Plugins/SinemaCX.py
CHANGED
|
@@ -117,7 +117,7 @@ class SinemaCX(PluginBase):
|
|
|
117
117
|
if has_only_trailer:
|
|
118
118
|
alt_url = url.rstrip("/") + "/2/"
|
|
119
119
|
alt_istek = await self.httpx.get(alt_url)
|
|
120
|
-
|
|
120
|
+
|
|
121
121
|
alt_sec = HTMLHelper(alt_istek.text)
|
|
122
122
|
iframe_list = alt_sec.select_attrs("iframe", "data-vsrc")
|
|
123
123
|
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: KekikStream
|
|
3
|
-
Version: 2.4.
|
|
3
|
+
Version: 2.4.6
|
|
4
4
|
Summary: terminal üzerinden medya içeriği aramanızı ve VLC/MPV gibi popüler medya oynatıcılar aracılığıyla doğrudan izlemenizi sağlayan modüler ve genişletilebilir bir bıdı bıdı
|
|
5
5
|
Home-page: https://github.com/keyiflerolsun/KekikStream
|
|
6
6
|
Author: keyiflerolsun
|
|
@@ -3,7 +3,7 @@ KekikStream/__main__.py,sha256=B81dQoeGEb-T5Sycs3eNAmW7unvx0Mef0syCjs4nPds,137
|
|
|
3
3
|
KekikStream/requirements.txt,sha256=V-Rk-4DnK8B-HRR6RtSKmTR3sHfaYgOrnBj8kmVz17w,80
|
|
4
4
|
KekikStream/CLI/__init__.py,sha256=U6oLq_O7u5y2eHhBnmfhZNns_EqHHJXJmzl8jvZFUNY,230
|
|
5
5
|
KekikStream/CLI/pypi_kontrol.py,sha256=q6fNs6EKJDc5VuUFig9DBzLzNPp_kMD1vOVgLElcii8,1487
|
|
6
|
-
KekikStream/Core/HTMLHelper.py,sha256
|
|
6
|
+
KekikStream/Core/HTMLHelper.py,sha256=-01qnBw-TaIi9NShb7b47rMSXx0bFn0z0KZ9ar0hEy0,8682
|
|
7
7
|
KekikStream/Core/__init__.py,sha256=sk2pWup1_jsGB43HJzbbqgQYFDZpf2TquEBYUhqOdN4,807
|
|
8
8
|
KekikStream/Core/Extractor/ExtractorBase.py,sha256=9Q79wULey2Nl254MUkiulhxZzGyb2C1H3mOUh4t0MN0,2077
|
|
9
9
|
KekikStream/Core/Extractor/ExtractorLoader.py,sha256=GPGCmgFpDBywR8CsNw43-ddseZhSKTjAUETp1Ohbi6E,4796
|
|
@@ -47,7 +47,7 @@ KekikStream/Extractors/TurboImgz.py,sha256=-RyC4EWtJdK85Ei01lntqivnSmk4tXOlmSXv7
|
|
|
47
47
|
KekikStream/Extractors/TurkeyPlayer.py,sha256=zdX0IOO3M-kgAYWex2WwJJu9aGf8WhOY-ZIrRmZRiC0,1246
|
|
48
48
|
KekikStream/Extractors/VCTPlay.py,sha256=MdCH9GhhKod4oPT3ePH8rhicUWuNT-GsE42S72o1NJ4,876
|
|
49
49
|
KekikStream/Extractors/VidHide.py,sha256=xJSferkaCLOQ-kLgsA_eDZCmGagiL2711boOdogOlWw,1918
|
|
50
|
-
KekikStream/Extractors/VidMoly.py,sha256=
|
|
50
|
+
KekikStream/Extractors/VidMoly.py,sha256=LUUomzPvf4J7PG3rf7drV4WM-sBHOupsllj017eluew,4106
|
|
51
51
|
KekikStream/Extractors/VidMoxy.py,sha256=qTkTFRqTgQVi-E94zY5lQC2-AYFhkl8LqaOJpgGdErc,1452
|
|
52
52
|
KekikStream/Extractors/VidPapi.py,sha256=yqjA5gadCE2lZ9ksT6zZOz-1zCcCYJxZsg0Ccgz2X10,1988
|
|
53
53
|
KekikStream/Extractors/VideoSeyred.py,sha256=sNxw5OHQ8AzRJIRGXGjql8nK1E6Cbg9qhKP5PuOyeM8,1216
|
|
@@ -55,9 +55,9 @@ KekikStream/Extractors/Videostr.py,sha256=CGL9GDzN0QzDir6ss8oUvDYYbGt2k8323P2_z5
|
|
|
55
55
|
KekikStream/Extractors/Vidoza.py,sha256=VSqCI-SYnLh6COnLHpg0feRX37t2WhPxbo08us5wCcc,655
|
|
56
56
|
KekikStream/Extractors/YTDLP.py,sha256=Hy8loCSFSquu2zaL3INord-Jm6T8CM6K2-VcDA2K79g,7390
|
|
57
57
|
KekikStream/Extractors/YildizKisaFilm.py,sha256=jeCCSIwZvQUr-CSylleUIP--JtN18_wUGl0vQXMCsV4,936
|
|
58
|
-
KekikStream/Plugins/BelgeselX.py,sha256=
|
|
58
|
+
KekikStream/Plugins/BelgeselX.py,sha256=4uGc8bClk68fUU5RxpIB8ENVL6WDFYzXzsQzWmmtFd4,9724
|
|
59
59
|
KekikStream/Plugins/DiziBox.py,sha256=F0X_vUVFbzFIgo504dyXjJkJIB6OxoHRxD3CCBUNsxg,10087
|
|
60
|
-
KekikStream/Plugins/DiziMom.py,sha256=
|
|
60
|
+
KekikStream/Plugins/DiziMom.py,sha256=o2OW3eKXxUADm4z9StSdUFzmrjCtKAQmov_4_wHjLQc,6763
|
|
61
61
|
KekikStream/Plugins/DiziPal.py,sha256=i3LLoEb4SGQPpR5KoFBlHHFKsnSqBvwlI3FueG-qckc,7745
|
|
62
62
|
KekikStream/Plugins/DiziYou.py,sha256=ZgHVTEeXhLC5aNP7MeeIcmLxqAPPzj0WWOiZHHpkAho,6550
|
|
63
63
|
KekikStream/Plugins/Dizilla.py,sha256=GmA__LCUAMTQ0tbbeWiH8h_aA6Rw7k2chAJZRsDifjg,12908
|
|
@@ -79,15 +79,15 @@ KekikStream/Plugins/SetFilmIzle.py,sha256=oj32n7QWersZMymjfwt9QPxWhWj2YlIhOtehnM
|
|
|
79
79
|
KekikStream/Plugins/SezonlukDizi.py,sha256=WCfMqoCX3_4mVF6_N5K5WzJIveb4jNmd0IrfM8pxqQ8,8511
|
|
80
80
|
KekikStream/Plugins/SineWix.py,sha256=z0r90lggAugEWE1g9vg8gZsInBObUZPnVFQwq7GYmJs,7052
|
|
81
81
|
KekikStream/Plugins/Sinefy.py,sha256=oLp2jtNa-3l_vS1Z8sqcsTyKmiY-xJq0-cFQ6KC8L4c,8603
|
|
82
|
-
KekikStream/Plugins/SinemaCX.py,sha256=
|
|
82
|
+
KekikStream/Plugins/SinemaCX.py,sha256=_CR90KWtdb9itQ4wzCVc21ZzE7oIAnp2lcOK0Jj2_f0,7635
|
|
83
83
|
KekikStream/Plugins/Sinezy.py,sha256=KHo8_vIW-aJh2ix72kGB54Wdw8PLmik78zzIwAxrspA,5811
|
|
84
84
|
KekikStream/Plugins/SuperFilmGeldi.py,sha256=wfhbZLNAuiz57KOarSrsoMLLpr9-zd6zjp7AmUisaBY,6402
|
|
85
85
|
KekikStream/Plugins/UgurFilm.py,sha256=WIdyu8X1ZdixigumEwEpZjtbM-melHfvT_u5N349oN4,5116
|
|
86
86
|
KekikStream/Plugins/Watch32.py,sha256=NeESk1unb5SYs6kwkb3dDymv2yYOkRU2QJCPI9izXKk,7915
|
|
87
87
|
KekikStream/Plugins/YabanciDizi.py,sha256=cTAREfia6df-rLeXDhxLCrKRHeZI_l_-nhjgIAD1jNA,9975
|
|
88
|
-
kekikstream-2.4.
|
|
89
|
-
kekikstream-2.4.
|
|
90
|
-
kekikstream-2.4.
|
|
91
|
-
kekikstream-2.4.
|
|
92
|
-
kekikstream-2.4.
|
|
93
|
-
kekikstream-2.4.
|
|
88
|
+
kekikstream-2.4.6.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
|
|
89
|
+
kekikstream-2.4.6.dist-info/METADATA,sha256=YnTe8qZ9P1nOlcLZxSDISmC5ZjK18fFsJcpccyPv3aM,10745
|
|
90
|
+
kekikstream-2.4.6.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
|
|
91
|
+
kekikstream-2.4.6.dist-info/entry_points.txt,sha256=dFwdiTx8djyehI0Gsz-rZwjAfZzUzoBSrmzRu9ubjJc,50
|
|
92
|
+
kekikstream-2.4.6.dist-info/top_level.txt,sha256=DNmGJDXl27Drdfobrak8KYLmocW_uznVYFJOzcjUgmY,12
|
|
93
|
+
kekikstream-2.4.6.dist-info/RECORD,,
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|