KekikStream 2.2.8__py3-none-any.whl → 2.3.9__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.
Files changed (62) hide show
  1. KekikStream/Core/HTMLHelper.py +134 -0
  2. KekikStream/Core/Plugin/PluginBase.py +22 -4
  3. KekikStream/Core/Plugin/PluginLoader.py +3 -2
  4. KekikStream/Core/Plugin/PluginManager.py +2 -2
  5. KekikStream/Core/__init__.py +2 -0
  6. KekikStream/Extractors/CloseLoad.py +12 -13
  7. KekikStream/Extractors/ContentX.py +33 -31
  8. KekikStream/Extractors/DonilasPlay.py +10 -10
  9. KekikStream/Extractors/DzenRu.py +3 -3
  10. KekikStream/Extractors/ExPlay.py +10 -10
  11. KekikStream/Extractors/Filemoon.py +47 -37
  12. KekikStream/Extractors/JetTv.py +4 -4
  13. KekikStream/Extractors/MixPlayHD.py +10 -11
  14. KekikStream/Extractors/MolyStream.py +16 -9
  15. KekikStream/Extractors/Odnoklassniki.py +4 -4
  16. KekikStream/Extractors/PeaceMakerst.py +3 -3
  17. KekikStream/Extractors/PixelDrain.py +6 -5
  18. KekikStream/Extractors/PlayerFilmIzle.py +6 -10
  19. KekikStream/Extractors/RapidVid.py +8 -7
  20. KekikStream/Extractors/SetPlay.py +10 -10
  21. KekikStream/Extractors/SetPrime.py +3 -6
  22. KekikStream/Extractors/SibNet.py +4 -5
  23. KekikStream/Extractors/Sobreatsesuyp.py +5 -5
  24. KekikStream/Extractors/TRsTX.py +5 -5
  25. KekikStream/Extractors/TurboImgz.py +3 -4
  26. KekikStream/Extractors/TurkeyPlayer.py +5 -5
  27. KekikStream/Extractors/VidHide.py +4 -7
  28. KekikStream/Extractors/VidMoly.py +37 -25
  29. KekikStream/Extractors/VidMoxy.py +8 -9
  30. KekikStream/Extractors/VidPapi.py +5 -7
  31. KekikStream/Extractors/VideoSeyred.py +3 -3
  32. KekikStream/Plugins/BelgeselX.py +40 -51
  33. KekikStream/Plugins/DiziBox.py +53 -81
  34. KekikStream/Plugins/DiziPal.py +50 -72
  35. KekikStream/Plugins/DiziYou.py +96 -83
  36. KekikStream/Plugins/Dizilla.py +101 -86
  37. KekikStream/Plugins/FilmBip.py +29 -50
  38. KekikStream/Plugins/FilmMakinesi.py +84 -46
  39. KekikStream/Plugins/FilmModu.py +27 -41
  40. KekikStream/Plugins/FullHDFilm.py +57 -62
  41. KekikStream/Plugins/FullHDFilmizlesene.py +32 -57
  42. KekikStream/Plugins/HDFilmCehennemi.py +51 -65
  43. KekikStream/Plugins/JetFilmizle.py +38 -51
  44. KekikStream/Plugins/KultFilmler.py +43 -67
  45. KekikStream/Plugins/RecTV.py +34 -9
  46. KekikStream/Plugins/RoketDizi.py +89 -111
  47. KekikStream/Plugins/SelcukFlix.py +102 -93
  48. KekikStream/Plugins/SetFilmIzle.py +110 -117
  49. KekikStream/Plugins/SezonlukDizi.py +88 -106
  50. KekikStream/Plugins/Sinefy.py +70 -70
  51. KekikStream/Plugins/SinemaCX.py +31 -55
  52. KekikStream/Plugins/Sinezy.py +27 -54
  53. KekikStream/Plugins/SuperFilmGeldi.py +25 -44
  54. KekikStream/Plugins/UgurFilm.py +23 -48
  55. KekikStream/Plugins/YabanciDizi.py +285 -0
  56. {kekikstream-2.2.8.dist-info → kekikstream-2.3.9.dist-info}/METADATA +1 -1
  57. kekikstream-2.3.9.dist-info/RECORD +84 -0
  58. kekikstream-2.2.8.dist-info/RECORD +0 -82
  59. {kekikstream-2.2.8.dist-info → kekikstream-2.3.9.dist-info}/WHEEL +0 -0
  60. {kekikstream-2.2.8.dist-info → kekikstream-2.3.9.dist-info}/entry_points.txt +0 -0
  61. {kekikstream-2.2.8.dist-info → kekikstream-2.3.9.dist-info}/licenses/LICENSE +0 -0
  62. {kekikstream-2.2.8.dist-info → kekikstream-2.3.9.dist-info}/top_level.txt +0 -0
@@ -1,8 +1,8 @@
1
1
  # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
2
 
3
- from KekikStream.Core import ExtractorBase, ExtractResult
3
+ from KekikStream.Core import ExtractorBase, ExtractResult, HTMLHelper
4
4
  from Kekik.Sifreleme import AESManager
5
- import re, json
5
+ import json
6
6
 
7
7
  class MixPlayHD(ExtractorBase):
8
8
  name = "MixPlayHD"
@@ -15,12 +15,12 @@ class MixPlayHD(ExtractorBase):
15
15
  istek = await self.httpx.get(url)
16
16
  istek.raise_for_status()
17
17
 
18
- be_player_match = re.search(r"bePlayer\('([^']+)',\s*'(\{[^\}]+\})'\);", istek.text)
19
- if not be_player_match:
18
+ hp = HTMLHelper(istek.text)
19
+ be_player_matches = hp.regex_all(r"bePlayer\('([^']+)',\s*'(\{[^\}]+\})'\);")
20
+ if not be_player_matches:
20
21
  raise ValueError("bePlayer not found in the response.")
21
22
 
22
- be_player_pass = be_player_match[1]
23
- be_player_data = be_player_match[2]
23
+ be_player_pass, be_player_data = be_player_matches[0]
24
24
 
25
25
  try:
26
26
  decrypted_data = AESManager.decrypt(be_player_data, be_player_pass).replace("\\", "")
@@ -28,13 +28,12 @@ class MixPlayHD(ExtractorBase):
28
28
  except Exception as hata:
29
29
  raise RuntimeError(f"Decryption failed: {hata}") from hata
30
30
 
31
- if video_url_match := re.search(
32
- pattern = r'"video_location":"([^"]+)"',
33
- string = decrypted_json.get("schedule", {}).get("client", ""),
34
- ):
31
+ client_str = decrypted_json.get("schedule", {}).get("client", "")
32
+ video_url = HTMLHelper(client_str).regex_first(r'"video_location":"([^"]+)"')
33
+ if video_url:
35
34
  return ExtractResult(
36
35
  name = self.name,
37
- url = video_url_match[1],
36
+ url = video_url,
38
37
  referer = self.main_url,
39
38
  subtitles = []
40
39
  )
@@ -1,25 +1,32 @@
1
1
  # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
2
 
3
- from KekikStream.Core import ExtractorBase, ExtractResult, Subtitle
4
- from selectolax.parser import HTMLParser
3
+ from KekikStream.Core import ExtractorBase, ExtractResult, Subtitle, HTMLHelper
5
4
  import re
6
5
 
7
6
  class MolyStream(ExtractorBase):
8
7
  name = "MolyStream"
9
8
  main_url = "https://dbx.molystream.org"
10
9
 
10
+ # Birden fazla domain destekle
11
+ supported_domains = [
12
+ "dbx.molystream.org",
13
+ "ydx.molystream.org",
14
+ "yd.sheila.stream",
15
+ "ydf.popcornvakti.net",
16
+ ]
17
+
18
+ def can_handle_url(self, url: str) -> bool:
19
+ return any(domain in url for domain in self.supported_domains)
20
+
11
21
  async def extract(self, url, referer=None) -> ExtractResult:
12
22
  if "doctype html" in url:
13
- secici = HTMLParser(url)
14
- video_el = secici.css_first("video#sheplayer source")
15
- video = video_el.attrs.get("src") if video_el else None
23
+ secici = HTMLHelper(url)
24
+ video = secici.select_attr("video#sheplayer source", "src")
16
25
  else:
17
26
  video = url
18
27
 
19
- matches = re.findall(
20
- pattern = r"addSrtFile\(['\"]([^'\"]+\.srt)['\"]\s*,\s*['\"][a-z]{2}['\"]\s*,\s*['\"]([^'\"]+)['\"]",
21
- string = url
22
- )
28
+ resp_sec = HTMLHelper(url)
29
+ matches = resp_sec.regex_all(r"addSrtFile\(['\"]([^'\"]+\.srt)['\"]\s*,\s*['\"][a-z]{2}['\"]\s*,\s*['\"]([^'\"]+)['\"]")
23
30
 
24
31
  subtitles = [
25
32
  Subtitle(name = name, url = self.fix_url(url))
@@ -1,6 +1,6 @@
1
1
  # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
2
 
3
- from KekikStream.Core import ExtractorBase, ExtractResult
3
+ from KekikStream.Core import ExtractorBase, ExtractResult, HTMLHelper
4
4
  import re, json
5
5
 
6
6
  class Odnoklassniki(ExtractorBase):
@@ -45,12 +45,12 @@ class Odnoklassniki(ExtractorBase):
45
45
  response_text
46
46
  )
47
47
 
48
- videos_match = re.search(r'"videos":(\[.*?\])', response_text)
49
- if not videos_match:
48
+ videos_json = HTMLHelper(response_text).regex_first(r'"videos":(\[.*?\])')
49
+ if not videos_json:
50
50
  raise ValueError("No video data found in the response.")
51
51
 
52
52
  try:
53
- videos = json.loads(videos_match[1])
53
+ videos = json.loads(videos_json)
54
54
  except json.JSONDecodeError as hata:
55
55
  raise ValueError("Failed to parse video data.") from hata
56
56
 
@@ -1,7 +1,7 @@
1
1
  # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
2
 
3
- from KekikStream.Core import ExtractorBase, ExtractResult
4
- import re, json
3
+ from KekikStream.Core import ExtractorBase, ExtractResult, HTMLHelper
4
+ import json
5
5
 
6
6
  class PeaceMakerst(ExtractorBase):
7
7
  name = "PeaceMakerst"
@@ -36,7 +36,7 @@ class PeaceMakerst(ExtractorBase):
36
36
  m3u_link = None
37
37
 
38
38
  if "teve2.com.tr\\/embed\\/" in response_text:
39
- teve2_id = re.search(r"teve2\.com\.tr\\\/embed\\\/(\d+)", response_text)[1]
39
+ teve2_id = HTMLHelper(response_text).regex_first(r"teve2\.com\.tr\\\/embed\\\/(\d+)")
40
40
  teve2_url = f"https://www.teve2.com.tr/action/media/{teve2_id}"
41
41
 
42
42
  teve2_response = await self.httpx.get(teve2_url, headers={"Referer": f"https://www.teve2.com.tr/embed/{teve2_id}"})
@@ -1,7 +1,6 @@
1
1
  # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
2
 
3
- from KekikStream.Core import ExtractorBase, ExtractResult
4
- import re
3
+ from KekikStream.Core import ExtractorBase, ExtractResult, HTMLHelper
5
4
 
6
5
  class PixelDrain(ExtractorBase):
7
6
  name = "PixelDrain"
@@ -11,11 +10,13 @@ class PixelDrain(ExtractorBase):
11
10
  if referer:
12
11
  self.httpx.headers.update({"Referer": referer})
13
12
 
14
- pixel_id_match = re.search(r"/u/([^/?]+)|([^\/]+)(?=\?download)", url)
15
- if not pixel_id_match:
13
+ hp = HTMLHelper(url)
14
+ matches = hp.regex_all(r"/u/([^/?]+)|([^\/]+)(?=\?download)")
15
+ if not matches:
16
16
  raise ValueError("PixelDrain bağlantısından ID çıkarılamadı.")
17
17
 
18
- pixel_id = pixel_id_match[1]
18
+ m = matches[0]
19
+ pixel_id = next((g for g in m if g), None)
19
20
  download_link = f"{self.main_url}/api/file/{pixel_id}?download"
20
21
  referer_link = f"{self.main_url}/u/{pixel_id}?download"
21
22
 
@@ -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 ExtractorBase, ExtractResult, Subtitle
3
+ from KekikStream.Core import ExtractorBase, ExtractResult, Subtitle, HTMLHelper
4
4
  from Kekik.Sifreleme import Packer
5
- import re
6
5
 
7
6
  class PlayerFilmIzle(ExtractorBase):
8
7
  name = "PlayerFilmIzle"
@@ -20,11 +19,10 @@ class PlayerFilmIzle(ExtractorBase):
20
19
  video_req = istek.text
21
20
 
22
21
  subtitles = []
23
- if sub_match := re.search(r'playerjsSubtitle = "([^"]*)"', video_req, re.IGNORECASE):
24
- sub_yakala = sub_match.group(1)
22
+ hp = HTMLHelper(video_req)
23
+ sub_yakala = hp.regex_first(r'(?i)playerjsSubtitle = "([^"]*)"')
24
+ if sub_yakala:
25
25
  # Format örneği: [dil]url
26
- # Kotlin kodunda: subYakala.substringAfter("]") -> url
27
- # subYakala.substringBefore("]").removePrefix("[") -> lang
28
26
  if "]" in sub_yakala:
29
27
  sub_lang_raw, sub_url = sub_yakala.split("]", 1)
30
28
  sub_lang = sub_lang_raw.replace("[", "")
@@ -34,8 +32,7 @@ class PlayerFilmIzle(ExtractorBase):
34
32
  unpacked = Packer.unpack(video_req) if Packer.detect_packed(video_req) else video_req
35
33
 
36
34
  # Data yakalama: FirePlayer("DATA", ...) formatından
37
- data_match = re.search(r'FirePlayer\s*\(\s*["\']([a-f0-9]+)["\']', unpacked, re.IGNORECASE)
38
- data_val = data_match.group(1) if data_match else None
35
+ data_val = HTMLHelper(unpacked).regex_first(r'(?i)FirePlayer\s*\(\s*["\']([a-f0-9]+)["\']')
39
36
 
40
37
  if not data_val:
41
38
  raise ValueError("PlayerFilmIzle: Data bulunamadı")
@@ -54,8 +51,7 @@ class PlayerFilmIzle(ExtractorBase):
54
51
  get_url = response.text.replace("\\", "")
55
52
 
56
53
  m3u8_url = ""
57
- if url_yakala := re.search(r'"securedLink":"([^"]*)"', get_url, re.IGNORECASE):
58
- m3u8_url = url_yakala.group(1)
54
+ m3u8_url = HTMLHelper(get_url).regex_first(r'(?i)"securedLink":"([^\\"]*)"') or m3u8_url
59
55
 
60
56
  if not m3u8_url:
61
57
  raise ValueError("PlayerFilmIzle: M3U8 linki bulunamadı")
@@ -1,8 +1,8 @@
1
1
  # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
2
 
3
- from KekikStream.Core import ExtractorBase, ExtractResult, Subtitle
3
+ from KekikStream.Core import ExtractorBase, ExtractResult, Subtitle, HTMLHelper
4
4
  from Kekik.Sifreleme import Packer, HexCodec, StreamDecoder
5
- import re, base64
5
+ import base64
6
6
 
7
7
  class RapidVid(ExtractorBase):
8
8
  name = "RapidVid"
@@ -22,7 +22,8 @@ class RapidVid(ExtractorBase):
22
22
  istek.raise_for_status()
23
23
 
24
24
  subtitles = []
25
- subtitle_matches = re.findall(r'captions\",\"file\":\"([^\"]+)\",\"label\":\"([^\"]+)\"', istek.text)
25
+ hp = HTMLHelper(istek.text)
26
+ subtitle_matches = hp.regex_all(r'captions\",\"file\":\"([^\"]+)\",\"label\":\"([^\"]+)\"')
26
27
  seen_subtitles = set()
27
28
 
28
29
  for sub_url, sub_lang in subtitle_matches:
@@ -42,13 +43,13 @@ class RapidVid(ExtractorBase):
42
43
  decoded_url = None
43
44
 
44
45
  # Method 1: file": "..." pattern (HexCodec)
45
- if extracted_value := re.search(r'file": "(.*)",', istek.text):
46
- escaped_hex = extracted_value[1]
46
+ if extracted_value := hp.regex_first(r'file": "(.*)",'):
47
+ escaped_hex = extracted_value
47
48
  decoded_url = HexCodec.decode(escaped_hex)
48
49
 
49
50
  # Method 2: av('...') pattern
50
- elif av_encoded := re.search(r"av\('([^']+)'\)", istek.text):
51
- decoded_url = self.decode_secret(av_encoded[1])
51
+ elif av_encoded := hp.regex_first(r"av\('([^']+)'\)"):
52
+ decoded_url = self.decode_secret(av_encoded)
52
53
 
53
54
  # Method 3: Packed script with dc_* function (StreamDecoder)
54
55
  elif Packer.detect_packed(istek.text):
@@ -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 ExtractorBase, ExtractResult
3
+ from KekikStream.Core import ExtractorBase, ExtractResult, HTMLHelper
4
4
  from urllib.parse import urlparse, parse_qs
5
- import re
6
5
 
7
6
  class SetPlay(ExtractorBase):
8
7
  name = "SetPlay"
@@ -26,21 +25,22 @@ class SetPlay(ExtractorBase):
26
25
  istek = await self.httpx.get(url)
27
26
  istek.raise_for_status()
28
27
 
28
+ hp = HTMLHelper(istek.text)
29
+
29
30
  # videoUrl çıkar
30
- video_url_match = re.search(r'videoUrl":"([^",]+)"', istek.text)
31
- if not video_url_match:
31
+ video_url = hp.regex_first(r'videoUrl":"([^",]+)"')
32
+ if not video_url:
32
33
  raise ValueError("videoUrl not found")
33
- video_url = video_url_match[1].replace("\\", "")
34
+ video_url = video_url.replace("\\", "")
34
35
 
35
36
  # videoServer çıkar
36
- video_server_match = re.search(r'videoServer":"([^",]+)"', istek.text)
37
- if not video_server_match:
37
+ video_server = hp.regex_first(r'videoServer":"([^",]+)"')
38
+ if not video_server:
38
39
  raise ValueError("videoServer not found")
39
- video_server = video_server_match[1]
40
40
 
41
41
  # title çıkar (opsiyonel)
42
- title_match = re.search(r'title":"([^",]+)"', istek.text)
43
- title_base = title_match[1].split(".")[-1] if title_match else "Unknown"
42
+ title_base = hp.regex_first(r'title":"([^",]+)"')
43
+ title_base = title_base.split(".")[-1] if title_base else "Unknown"
44
44
 
45
45
  # partKey logic
46
46
  parsed = urlparse(url)
@@ -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 ExtractorBase, ExtractResult
3
+ from KekikStream.Core import ExtractorBase, ExtractResult, HTMLHelper
4
4
  from urllib.parse import urlparse, parse_qs
5
- import re
6
5
 
7
6
  class SetPrime(ExtractorBase):
8
7
  name = "SetPrime"
@@ -25,11 +24,9 @@ class SetPrime(ExtractorBase):
25
24
  response.raise_for_status()
26
25
 
27
26
  # Links parse
28
- links_match = re.search(r'Links":\["([^"\]]+)"', response.text)
29
- if not links_match:
27
+ link_suffix = HTMLHelper(response.text).regex_first(r'Links":\["([^"\]]+)"')
28
+ if not link_suffix:
30
29
  raise ValueError("Links not found in SetPrime response")
31
-
32
- link_suffix = links_match.group(1)
33
30
  if not link_suffix.startswith("/"):
34
31
  raise ValueError("Links not valid (must start with /)")
35
32
 
@@ -1,7 +1,6 @@
1
1
  # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
2
 
3
- from KekikStream.Core import ExtractorBase, ExtractResult
4
- import re
3
+ from KekikStream.Core import ExtractorBase, ExtractResult, HTMLHelper
5
4
 
6
5
  class SibNet(ExtractorBase):
7
6
  name = "SibNet"
@@ -14,11 +13,11 @@ class SibNet(ExtractorBase):
14
13
  response = await self.httpx.get(url)
15
14
  response.raise_for_status()
16
15
 
17
- match = re.search(r'player\.src\(\[\{src: \"([^\"]+)\"', response.text)
18
- if not match:
16
+ m3u_suffix = HTMLHelper(response.text).regex_first(r'player\.src\(\[\{src: "([^\"]+)"')
17
+ if not m3u_suffix:
19
18
  raise ValueError("m3u bağlantısı bulunamadı.")
20
19
 
21
- m3u_link = f"{self.main_url}{match[1]}"
20
+ m3u_link = f"{self.main_url}{m3u_suffix}"
22
21
 
23
22
  return ExtractResult(
24
23
  name = self.name,
@@ -1,7 +1,7 @@
1
1
  # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
2
 
3
- from KekikStream.Core import ExtractorBase, ExtractResult
4
- import re, json
3
+ from KekikStream.Core import ExtractorBase, ExtractResult, HTMLHelper
4
+ import json
5
5
 
6
6
  class Sobreatsesuyp(ExtractorBase):
7
7
  name = "Sobreatsesuyp"
@@ -14,11 +14,11 @@ class Sobreatsesuyp(ExtractorBase):
14
14
  istek = await self.httpx.get(url)
15
15
  istek.raise_for_status()
16
16
 
17
- file_match = re.search(r'file\":\"([^\"]+)', istek.text)
18
- if not file_match:
17
+ file_path = HTMLHelper(istek.text).regex_first(r'file":"([^\"]+)')
18
+ if not file_path:
19
19
  raise ValueError("File not found in response.")
20
20
 
21
- file_path = file_match[1].replace("\\", "")
21
+ file_path = file_path.replace("\\", "")
22
22
  post_link = f"{self.main_url}/{file_path}"
23
23
 
24
24
  post_istek = await self.httpx.post(post_link)
@@ -1,7 +1,7 @@
1
1
  # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
2
 
3
- from KekikStream.Core import ExtractorBase, ExtractResult
4
- import re, json
3
+ from KekikStream.Core import ExtractorBase, ExtractResult, HTMLHelper
4
+ import json
5
5
 
6
6
  class TRsTX(ExtractorBase):
7
7
  name = "TRsTX"
@@ -14,11 +14,11 @@ class TRsTX(ExtractorBase):
14
14
  istek = await self.httpx.get(url)
15
15
  istek.raise_for_status()
16
16
 
17
- file_match = re.search(r'file\":\"([^\"]+)', istek.text)
18
- if not file_match:
17
+ file_path = HTMLHelper(istek.text).regex_first(r'file":"([^\"]+)')
18
+ if not file_path:
19
19
  raise ValueError("File not found in response.")
20
20
 
21
- file_path = file_match[1].replace("\\", "")
21
+ file_path = file_path.replace("\\", "")
22
22
  post_link = f"{self.main_url}/{file_path}"
23
23
 
24
24
  post_istek = await self.httpx.post(post_link)
@@ -1,7 +1,6 @@
1
1
  # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
2
 
3
- from KekikStream.Core import ExtractorBase, ExtractResult
4
- import re
3
+ from KekikStream.Core import ExtractorBase, ExtractResult, HTMLHelper
5
4
 
6
5
  class TurboImgz(ExtractorBase):
7
6
  name = "TurboImgz"
@@ -14,10 +13,10 @@ class TurboImgz(ExtractorBase):
14
13
  istek = await self.httpx.get(url)
15
14
  istek.raise_for_status()
16
15
 
17
- if video_match := re.search(r'file: "(.*)",', istek.text):
16
+ if video := HTMLHelper(istek.text).regex_first(r'file: "(.*)",'):
18
17
  return ExtractResult(
19
18
  name = self.name,
20
- url = video_match[1],
19
+ url = video,
21
20
  referer = referer or self.main_url,
22
21
  subtitles = []
23
22
  )
@@ -1,7 +1,7 @@
1
1
  # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
2
 
3
- from KekikStream.Core import ExtractorBase, ExtractResult, Subtitle
4
- import re, json
3
+ from KekikStream.Core import ExtractorBase, ExtractResult, Subtitle, HTMLHelper
4
+ import json
5
5
 
6
6
  class TurkeyPlayer(ExtractorBase):
7
7
  name = "TurkeyPlayer"
@@ -14,11 +14,11 @@ class TurkeyPlayer(ExtractorBase):
14
14
  istek = await self.httpx.get(url)
15
15
  page_content = istek.text
16
16
 
17
- video_json_match = re.search(r'var\s+video\s*=\s*(\{.*?\});', page_content, re.DOTALL)
18
- if not video_json_match:
17
+ video_json_str = HTMLHelper(page_content).regex_first(r'(?s)var\s+video\s*=\s*(\{.*?\});')
18
+ if not video_json_str:
19
19
  raise ValueError("TurkeyPlayer: Video JSON bulunamadı")
20
20
 
21
- video_data = json.loads(video_json_match.group(1))
21
+ video_data = json.loads(video_json_str)
22
22
 
23
23
  video_id = video_data.get("id")
24
24
  video_md5 = video_data.get("md5")
@@ -1,6 +1,6 @@
1
1
  # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
2
 
3
- from KekikStream.Core import ExtractorBase, ExtractResult, Subtitle
3
+ from KekikStream.Core import ExtractorBase, ExtractResult, Subtitle, HTMLHelper
4
4
  from Kekik.Sifreleme import Packer
5
5
  import re
6
6
 
@@ -54,19 +54,16 @@ class VidHide(ExtractorBase):
54
54
  pass
55
55
 
56
56
  if not script:
57
- if matches := re.search(r'sources:\s*(\[.*?\])', response, re.DOTALL):
58
- script = matches.group(1)
57
+ script = HTMLHelper(response).regex_first(r'(?s)sources:\s*(\[.*?\])')
59
58
 
60
59
  m3u8_url = None
61
60
  if script:
62
61
  # m3u8 urls could be prefixed by 'file:', 'hls2:' or 'hls4:', so we just match ':'
63
- if match := re.search(r':\s*"([^"]*?m3u8[^"]*?)"', script):
64
- m3u8_url = match.group(1)
62
+ m3u8_url = HTMLHelper(script).regex_first(r':\s*"([^\"]*?m3u8[^\"]*?)"')
65
63
 
66
64
  if not m3u8_url:
67
65
  # Fallback direct search in response if unpacking failed or structure changed
68
- if match := re.search(r'file:"(.*?\.m3u8.*?)"', response):
69
- m3u8_url = match.group(1)
66
+ m3u8_url = HTMLHelper(response).regex_first(r'file:"(.*?\.m3u8.*?)"')
70
67
 
71
68
  if not m3u8_url:
72
69
  raise ValueError(f"VidHide: Video URL bulunamadı. {url}")
@@ -1,8 +1,7 @@
1
1
  # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
2
  # ! https://github.com/recloudstream/cloudstream/blob/master/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/Vidmoly.kt
3
3
 
4
- from KekikStream.Core import ExtractorBase, ExtractResult, Subtitle
5
- from selectolax.parser import HTMLParser
4
+ from KekikStream.Core import ExtractorBase, ExtractResult, Subtitle, HTMLHelper
6
5
  import re, contextlib, json
7
6
 
8
7
  class VidMoly(ExtractorBase):
@@ -25,28 +24,30 @@ class VidMoly(ExtractorBase):
25
24
 
26
25
  if ".me" in url:
27
26
  url = url.replace(".me", ".net")
27
+ if ".to" in url:
28
+ url = url.replace(".to", ".net")
28
29
 
29
30
  # VidMoly bazen redirect ediyor, takip et
30
31
  response = await self.httpx.get(url, follow_redirects=True)
31
32
  if "Select number" in response.text:
32
- secici = HTMLParser(response.text)
33
+ secici = HTMLHelper(response.text)
33
34
 
34
- op_el = secici.css_first("input[name='op']")
35
- file_code_el = secici.css_first("input[name='file_code']")
36
- answer_el = secici.css_first("div.vhint b")
37
- ts_el = secici.css_first("input[name='ts']")
38
- nonce_el = secici.css_first("input[name='nonce']")
39
- ctok_el = secici.css_first("input[name='ctok']")
35
+ op_val = secici.select_attr("input[name='op']", "value")
36
+ file_code_val = secici.select_attr("input[name='file_code']", "value")
37
+ answer_val = secici.select_text("div.vhint b")
38
+ ts_val = secici.select_attr("input[name='ts']", "value")
39
+ nonce_val = secici.select_attr("input[name='nonce']", "value")
40
+ ctok_val = secici.select_attr("input[name='ctok']", "value")
40
41
 
41
42
  response = await self.httpx.post(
42
43
  url = url,
43
44
  data = {
44
- "op" : op_el.attrs.get("value") if op_el else None,
45
- "file_code" : file_code_el.attrs.get("value") if file_code_el else None,
46
- "answer" : answer_el.text(strip=True) if answer_el else None,
47
- "ts" : ts_el.attrs.get("value") if ts_el else None,
48
- "nonce" : nonce_el.attrs.get("value") if nonce_el else None,
49
- "ctok" : ctok_el.attrs.get("value") if ctok_el else None
45
+ "op" : op_val,
46
+ "file_code" : file_code_val,
47
+ "answer" : answer_val,
48
+ "ts" : ts_val,
49
+ "nonce" : nonce_val,
50
+ "ctok" : ctok_val
50
51
  },
51
52
  follow_redirects=True
52
53
  )
@@ -54,8 +55,9 @@ class VidMoly(ExtractorBase):
54
55
 
55
56
  # Altyazı kaynaklarını ayrıştır
56
57
  subtitles = []
57
- if subtitle_match := re.search(r"tracks:\s*\[(.*?)\]", response.text, re.DOTALL):
58
- subtitle_data = self._add_marks(subtitle_match[1], "file")
58
+ resp_sec = HTMLHelper(response.text)
59
+ if subtitle_str := resp_sec.regex_first(r"tracks:\s*\[(.*?)\]", flags= re.DOTALL):
60
+ subtitle_data = self._add_marks(subtitle_str, "file")
59
61
  subtitle_data = self._add_marks(subtitle_data, "label")
60
62
  subtitle_data = self._add_marks(subtitle_data, "kind")
61
63
 
@@ -70,9 +72,19 @@ class VidMoly(ExtractorBase):
70
72
  if sub.get("kind") == "captions"
71
73
  ]
72
74
 
73
- script_match = re.search(r"sources:\s*\[(.*?)\],", response.text, re.DOTALL)
74
- if script_match:
75
- script_content = script_match[1]
75
+ if "#EXTM3U" in response.text:
76
+ for line in response.text.splitlines():
77
+ line = line.strip().replace('"', '').replace("'", "")
78
+ if line.startswith("http"):
79
+ return ExtractResult(
80
+ name = self.name,
81
+ url = line,
82
+ referer = self.main_url,
83
+ subtitles = subtitles
84
+ )
85
+
86
+ if script_str := resp_sec.regex_first(r"sources:\s*\[(.*?)\],", flags= re.DOTALL):
87
+ script_content = script_str
76
88
  # Video kaynaklarını ayrıştır
77
89
  video_data = self._add_marks(script_content, "file")
78
90
  try:
@@ -91,17 +103,17 @@ class VidMoly(ExtractorBase):
91
103
 
92
104
  # Fallback: Doğrudan file regex ile ara (Kotlin mantığı)
93
105
  # file:"..." veya file: "..."
94
- if file_match := re.search(r'file\s*:\s*["\']([^"\']+\.m3u8[^"\']*)["\']', response.text):
106
+ if file_match := resp_sec.regex_first(r'file\s*:\s*["\']([^"\']+\.m3u8[^"\']*)["\']'):
95
107
  return ExtractResult(
96
108
  name = self.name,
97
- url = file_match.group(1),
109
+ url = file_match,
98
110
  referer = self.main_url,
99
111
  subtitles = subtitles
100
112
  )
101
113
 
102
114
  # Fallback 2: Herhangi bir file (m3u8 olma şartı olmadan ama tercihen)
103
- if file_match := re.search(r'file\s*:\s*["\']([^"\']+)["\']', response.text):
104
- url_candidate = file_match.group(1)
115
+ if file_match := resp_sec.regex_first(r'file\s*:\s*["\']([^"\']+)["\']'):
116
+ url_candidate = file_match
105
117
  # Resim dosyalarını hariç tut
106
118
  if not url_candidate.endswith(('.jpg', '.png', '.jpeg')):
107
119
  return ExtractResult(
@@ -117,4 +129,4 @@ class VidMoly(ExtractorBase):
117
129
  """
118
130
  Verilen alanı çift tırnak içine alır.
119
131
  """
120
- return re.sub(rf"\"?{field}\"?", f"\"{field}\"", text)
132
+ return HTMLHelper(text).regex_replace(rf"\"?{field}\"?", f"\"{field}\"")
@@ -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 ExtractorBase, ExtractResult, Subtitle
3
+ from KekikStream.Core import ExtractorBase, ExtractResult, Subtitle, HTMLHelper
4
4
  from Kekik.Sifreleme import Packer, HexCodec
5
- import re
6
5
 
7
6
  class VidMoxy(ExtractorBase):
8
7
  name = "VidMoxy"
@@ -16,7 +15,7 @@ class VidMoxy(ExtractorBase):
16
15
  istek.raise_for_status()
17
16
 
18
17
  subtitles = []
19
- subtitle_matches = re.findall(r'captions","file":"([^"]+)","label":"([^"]+)"', istek.text)
18
+ subtitle_matches = HTMLHelper(istek.text).regex_all(r'captions","file":"([^\"]+)","label":"([^\"]+)"')
20
19
  seen_subtitles = set()
21
20
 
22
21
  for sub_url, sub_lang in subtitle_matches:
@@ -32,12 +31,12 @@ class VidMoxy(ExtractorBase):
32
31
  )
33
32
  subtitles.append(Subtitle(name=decoded_lang, url=sub_url.replace("\\", "")))
34
33
 
35
- try:
36
- escaped_hex = re.findall(r'file": "(.*)",', istek.text)[0]
37
- except Exception:
38
- eval_jwsetup = re.compile(r'\};\s*(eval\(function[\s\S]*?)var played = \d+;').findall(istek.text)[0]
39
- jwsetup = Packer.unpack(Packer.unpack(eval_jwsetup))
40
- escaped_hex = re.findall(r'file":"(.*)","label', jwsetup)[0]
34
+ escaped_hex = HTMLHelper(istek.text).regex_first(r'file": "(.*)",')
35
+ if not escaped_hex:
36
+ eval_jwsetup = HTMLHelper(istek.text).regex_first(r'\};\s*(eval\(function[\s\S]*?)var played = \d+;')
37
+ jwsetup = Packer.unpack(Packer.unpack(eval_jwsetup)) if eval_jwsetup else None
38
+ if jwsetup:
39
+ escaped_hex = HTMLHelper(jwsetup).regex_first(r'file":"(.*)","label')
41
40
 
42
41
  m3u_link = HexCodec.decode(escaped_hex)
43
42
 
@@ -1,7 +1,7 @@
1
1
  # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
2
 
3
- from KekikStream.Core import ExtractorBase, ExtractResult, Subtitle
4
- import re
3
+ from KekikStream.Core import ExtractorBase, ExtractResult, Subtitle, HTMLHelper
4
+
5
5
 
6
6
  class VidPapi(ExtractorBase):
7
7
  name = "VidApi"
@@ -33,11 +33,9 @@ class VidPapi(ExtractorBase):
33
33
  data = {"hash": vid_id, "r": "https://kultfilmler.pro/"}
34
34
  )
35
35
 
36
- subtitle_match = re.search(r'var playerjsSubtitle = "([^"]*)"', sub_istek.text, re.IGNORECASE)
37
- if subtitle_match and subtitle_match.group(1):
38
- raw_subs = subtitle_match.group(1)
39
-
40
- found_subs = re.findall(r'\[(.*?)\](.*?)(?:,|$)', raw_subs)
36
+ raw_subs = HTMLHelper(sub_istek.text).regex_first(r'var playerjsSubtitle\s*=\s*"([^"]*)"', flags=0)
37
+ if raw_subs:
38
+ found_subs = HTMLHelper(raw_subs).regex_all(r'\[(.*?)\](.*?)(?:,|$)')
41
39
  for lang, sub_link in found_subs:
42
40
  lang = lang.strip()
43
41
  if "Türkçe" in lang: