KekikStream 2.4.4__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.
@@ -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, strip: bool = True) -> str | 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=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, strip: bool = True) -> list[str]:
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=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, strip: bool = True) -> str | 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
- # 1) Bazı sürümlerde var: sadece direct text
84
- try:
85
- val = el.text(strip=strip, deep=False) # type: ignore[call-arg]
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, strip: bool = True) -> str | 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=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=strip).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=strip).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 _regex_flags(self, target: str | int | None, flags: int) -> int:
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), self._regex_flags(target, flags))
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, flags: int = 0) -> list[str]:
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), self._regex_flags(target, flags))
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, flags: int = 0) -> str:
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), flags=self._regex_flags(target, flags))
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*\[(.*?)\]", flags=re.DOTALL):
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*\[(.*?)\],", flags=re.DOTALL):
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}]")
@@ -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
- return " ".join(
38
- word.lower().replace("i", "İ").capitalize() if word.lower().startswith("i") else word.capitalize()
39
- for word in text.split()
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}")
@@ -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, flags=re.DOTALL)
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
 
@@ -78,13 +78,26 @@ class DiziPal(PluginBase):
78
78
  description = secici.select_attr("meta[property='og:description']", "content")
79
79
  title = secici.select_text("h1")
80
80
 
81
- year = secici.meta_value("Yapım Yılı")
82
- rating = secici.meta_value("IMDB Puanı")
83
- duration = secici.meta_value("Süre")
84
- duration = int(secici.regex_first(r"(\d+)", duration)) if duration else None
85
- tags = secici.meta_list("Tür")
86
-
87
- actors = secici.meta_list("Oyuncular")
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
98
+
99
+ tags = secici.meta_list("Tür")
100
+ actors = secici.meta_list("Oyuncular")
88
101
  if not actors:
89
102
  actors = secici.select_attrs("div.swiper-slide a", "title")
90
103
 
@@ -105,12 +118,12 @@ class DiziPal(PluginBase):
105
118
  episodes.append(Episode(season=s, episode=e, title=name, url=self.fix_url(href)))
106
119
 
107
120
  return SeriesInfo(
108
- url=url, poster=poster, title=title, description=description, tags=tags,
121
+ url=url, poster=poster.replace("https://test4test.online", self.main_url), title=title, description=description, tags=tags,
109
122
  rating=rating, year=year, duration=duration, episodes=episodes or None, actors=actors
110
123
  )
111
124
 
112
125
  return MovieInfo(
113
- url=url, poster=poster, title=title, description=description, tags=tags,
126
+ url=url, poster=poster.replace("https://test4test.online", self.main_url), title=title, description=description, tags=tags,
114
127
  rating=rating, year=year, duration=duration, actors=actors
115
128
  )
116
129
 
@@ -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
- alt_istek = await self.httpx.get(alt_url)
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.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=JI677_XerQc6ZwKDpwoCzfyHlKDekEWDuHgsEFOPu50,9792
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=awrjBtxtP2xEr8xRTCH1JcnRattzIAdxGE2rDd9czDg,4132
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,10 +55,10 @@ 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=0LZYeV8ve2HGsNvuqACltP7eI_nZyjoCBjeYWMokUXY,9175
58
+ KekikStream/Plugins/BelgeselX.py,sha256=4uGc8bClk68fUU5RxpIB8ENVL6WDFYzXzsQzWmmtFd4,9724
59
59
  KekikStream/Plugins/DiziBox.py,sha256=F0X_vUVFbzFIgo504dyXjJkJIB6OxoHRxD3CCBUNsxg,10087
60
- KekikStream/Plugins/DiziMom.py,sha256=0kOXekDk9-I-rRgQZmKH0pZmYDgfdkS2PXOBbTlhI0g,6776
61
- KekikStream/Plugins/DiziPal.py,sha256=gDj_7iJaP5WIoRWKZmvF6Q6nbPm8TBw9jAjbk_E75NA,7352
60
+ KekikStream/Plugins/DiziMom.py,sha256=o2OW3eKXxUADm4z9StSdUFzmrjCtKAQmov_4_wHjLQc,6763
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
64
64
  KekikStream/Plugins/FilmBip.py,sha256=gHdYHEZjDBPkajQjqBZGVhbs97zDr5mF_cVSUKn8ljE,6018
@@ -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=q9ZNnkUxGotTzjslzoJu1GzZDF31J3RayzeUAfAsGzw,7688
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.4.dist-info/licenses/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
89
- kekikstream-2.4.4.dist-info/METADATA,sha256=LuV2Kn0ryFqkcYJXMYXpUheRWJRsD8rTpAJRY0baJFw,10745
90
- kekikstream-2.4.4.dist-info/WHEEL,sha256=wUyA8OaulRlbfwMtmQsvNngGrxQHAvkKcvRmdizlJi0,92
91
- kekikstream-2.4.4.dist-info/entry_points.txt,sha256=dFwdiTx8djyehI0Gsz-rZwjAfZzUzoBSrmzRu9ubjJc,50
92
- kekikstream-2.4.4.dist-info/top_level.txt,sha256=DNmGJDXl27Drdfobrak8KYLmocW_uznVYFJOzcjUgmY,12
93
- kekikstream-2.4.4.dist-info/RECORD,,
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,,