KekikStream 2.3.9__py3-none-any.whl → 2.5.3__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 (85) hide show
  1. KekikStream/Core/Extractor/ExtractorBase.py +3 -2
  2. KekikStream/Core/Extractor/ExtractorLoader.py +8 -14
  3. KekikStream/Core/HTMLHelper.py +120 -49
  4. KekikStream/Core/Plugin/PluginBase.py +30 -12
  5. KekikStream/Core/Plugin/PluginLoader.py +12 -14
  6. KekikStream/Core/Plugin/PluginManager.py +2 -2
  7. KekikStream/Core/Plugin/PluginModels.py +0 -3
  8. KekikStream/Extractors/Abstream.py +27 -0
  9. KekikStream/Extractors/CloseLoad.py +30 -54
  10. KekikStream/Extractors/ContentX.py +27 -72
  11. KekikStream/Extractors/DonilasPlay.py +33 -77
  12. KekikStream/Extractors/DzenRu.py +10 -24
  13. KekikStream/Extractors/ExPlay.py +20 -38
  14. KekikStream/Extractors/Filemoon.py +21 -46
  15. KekikStream/Extractors/HDMomPlayer.py +30 -0
  16. KekikStream/Extractors/HDPlayerSystem.py +13 -31
  17. KekikStream/Extractors/HotStream.py +27 -0
  18. KekikStream/Extractors/JFVid.py +3 -24
  19. KekikStream/Extractors/JetTv.py +21 -34
  20. KekikStream/Extractors/JetV.py +55 -0
  21. KekikStream/Extractors/MailRu.py +11 -29
  22. KekikStream/Extractors/MixPlayHD.py +15 -28
  23. KekikStream/Extractors/MixTiger.py +17 -40
  24. KekikStream/Extractors/MolyStream.py +17 -21
  25. KekikStream/Extractors/Odnoklassniki.py +40 -104
  26. KekikStream/Extractors/PeaceMakerst.py +18 -45
  27. KekikStream/Extractors/PixelDrain.py +8 -16
  28. KekikStream/Extractors/PlayerFilmIzle.py +22 -41
  29. KekikStream/Extractors/RapidVid.py +21 -35
  30. KekikStream/Extractors/SetPlay.py +18 -43
  31. KekikStream/Extractors/SibNet.py +7 -17
  32. KekikStream/Extractors/Sobreatsesuyp.py +23 -45
  33. KekikStream/Extractors/TRsTX.py +23 -53
  34. KekikStream/Extractors/TurboImgz.py +7 -14
  35. KekikStream/Extractors/VCTPlay.py +10 -28
  36. KekikStream/Extractors/Veev.py +145 -0
  37. KekikStream/Extractors/VidBiz.py +62 -0
  38. KekikStream/Extractors/VidHide.py +58 -30
  39. KekikStream/Extractors/VidMoly.py +65 -99
  40. KekikStream/Extractors/VidMoxy.py +16 -27
  41. KekikStream/Extractors/VidPapi.py +24 -54
  42. KekikStream/Extractors/VideoSeyred.py +19 -40
  43. KekikStream/Extractors/Videostr.py +58 -0
  44. KekikStream/Extractors/Vidoza.py +18 -0
  45. KekikStream/Extractors/Vtbe.py +38 -0
  46. KekikStream/Extractors/YTDLP.py +2 -2
  47. KekikStream/Extractors/YildizKisaFilm.py +13 -31
  48. KekikStream/Extractors/Zeus.py +61 -0
  49. KekikStream/Plugins/BelgeselX.py +97 -77
  50. KekikStream/Plugins/DiziBox.py +28 -45
  51. KekikStream/Plugins/DiziMom.py +179 -0
  52. KekikStream/Plugins/DiziPal.py +95 -161
  53. KekikStream/Plugins/DiziYou.py +51 -147
  54. KekikStream/Plugins/Dizilla.py +40 -61
  55. KekikStream/Plugins/FilmBip.py +90 -39
  56. KekikStream/Plugins/FilmEkseni.py +199 -0
  57. KekikStream/Plugins/FilmMakinesi.py +72 -73
  58. KekikStream/Plugins/FilmModu.py +25 -35
  59. KekikStream/Plugins/Filmatek.py +184 -0
  60. KekikStream/Plugins/FilmciBaba.py +155 -0
  61. KekikStream/Plugins/FullHDFilmizlesene.py +16 -37
  62. KekikStream/Plugins/HDFilm.py +243 -0
  63. KekikStream/Plugins/HDFilmCehennemi.py +242 -189
  64. KekikStream/Plugins/JetFilmizle.py +101 -69
  65. KekikStream/Plugins/KultFilmler.py +138 -104
  66. KekikStream/Plugins/RecTV.py +52 -73
  67. KekikStream/Plugins/RoketDizi.py +18 -27
  68. KekikStream/Plugins/SelcukFlix.py +30 -48
  69. KekikStream/Plugins/SetFilmIzle.py +76 -104
  70. KekikStream/Plugins/SezonlukDizi.py +90 -94
  71. KekikStream/Plugins/Sinefy.py +195 -167
  72. KekikStream/Plugins/SinemaCX.py +148 -78
  73. KekikStream/Plugins/Sinezy.py +29 -31
  74. KekikStream/Plugins/SuperFilmGeldi.py +12 -17
  75. KekikStream/Plugins/UgurFilm.py +85 -38
  76. KekikStream/Plugins/Watch32.py +160 -0
  77. KekikStream/Plugins/YabanciDizi.py +176 -211
  78. {kekikstream-2.3.9.dist-info → kekikstream-2.5.3.dist-info}/METADATA +1 -1
  79. kekikstream-2.5.3.dist-info/RECORD +99 -0
  80. {kekikstream-2.3.9.dist-info → kekikstream-2.5.3.dist-info}/WHEEL +1 -1
  81. KekikStream/Plugins/FullHDFilm.py +0 -249
  82. kekikstream-2.3.9.dist-info/RECORD +0 -84
  83. {kekikstream-2.3.9.dist-info → kekikstream-2.5.3.dist-info}/entry_points.txt +0 -0
  84. {kekikstream-2.3.9.dist-info → kekikstream-2.5.3.dist-info}/licenses/LICENSE +0 -0
  85. {kekikstream-2.3.9.dist-info → kekikstream-2.5.3.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,62 @@
1
+ # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
+
3
+ from KekikStream.Core import ExtractorBase, ExtractResult, HTMLHelper
4
+ from Kekik.Sifreleme import Packer
5
+
6
+ class VidBiz(ExtractorBase):
7
+ name = "VidBiz"
8
+ main_url = "https://videolar.biz"
9
+
10
+ async def extract(self, url: str, referer: str = None) -> list[ExtractResult]:
11
+ istek = await self.httpx.get(url, headers={"Referer": referer} if referer else None)
12
+ text = istek.text
13
+
14
+ # Eval script bul (kaken içeriyor olmalı)
15
+ eval_script = HTMLHelper(text).regex_first(r'(eval\(function[\s\S]+?)<\/script>') or \
16
+ HTMLHelper(text).regex_first(r'(eval\(function[\s\S]+)')
17
+ if not eval_script:
18
+ raise ValueError(f"VidBiz: Packed script bulunamadı. {url}")
19
+
20
+ unpacked = ""
21
+ try:
22
+ unpacked = Packer.unpack(eval_script)
23
+ except:
24
+ raise ValueError("VidBiz: Unpack hatası")
25
+
26
+ # window.kaken="..."
27
+ kaken = HTMLHelper(unpacked).regex_first(r'window\.kaken\s*=\s*"([^"]+)"')
28
+ if not kaken:
29
+ raise ValueError("VidBiz: Kaken token bulunamadı")
30
+
31
+ # API POST
32
+ # Content-Type: text/plain önemli olabilir
33
+ resp = await self.httpx.post(
34
+ url = "https://s2.videolar.biz/api/",
35
+ content = kaken, # data yerine content=raw string
36
+ headers = {"Content-Type": "text/plain", "Referer": url}
37
+ )
38
+
39
+ try:
40
+ data = resp.json()
41
+ except:
42
+ raise ValueError("VidBiz: API yanıtı JSON değil")
43
+
44
+ if data.get("status") != "ok":
45
+ raise ValueError(f"VidBiz: API hatası {data}")
46
+
47
+ results = []
48
+ for source in data.get("sources", []):
49
+ file_url = source.get("file")
50
+ label = source.get("label", "Unknown")
51
+
52
+ if not file_url:
53
+ continue
54
+
55
+ results.append(ExtractResult(
56
+ name = f"{self.name} | {label}",
57
+ url = self.fix_url(file_url),
58
+ referer = url,
59
+ user_agent = self.httpx.headers.get("User-Agent", "")
60
+ ))
61
+
62
+ return results
@@ -9,7 +9,16 @@ class VidHide(ExtractorBase):
9
9
  main_url = "https://vidhidepro.com"
10
10
 
11
11
  # Birden fazla domain destekle
12
- supported_domains = ["vidhidepro.com", "vidhide.com", "rubyvidhub.com"]
12
+ supported_domains = [
13
+ "vidhidepro.com", "vidhide.com", "rubyvidhub.com",
14
+ "vidhidevip.com", "vidhideplus.com", "vidhidepre.com",
15
+ "movearnpre.com", "oneupload.to",
16
+ "filelions.live", "filelions.online", "filelions.to",
17
+ "kinoger.be",
18
+ "smoothpre.com",
19
+ "dhtpre.com",
20
+ "peytonepre.com"
21
+ ]
13
22
 
14
23
  def can_handle_url(self, url: str) -> bool:
15
24
  return any(domain in url for domain in self.supported_domains)
@@ -21,50 +30,70 @@ class VidHide(ExtractorBase):
21
30
  return url.replace("/download/", "/v/")
22
31
  elif "/file/" in url:
23
32
  return url.replace("/file/", "/v/")
33
+ elif "/embed/" in url:
34
+ return url.replace("/embed/", "/v/")
24
35
  else:
25
36
  return url.replace("/f/", "/v/")
26
37
 
27
38
  async def extract(self, url: str, referer: str = None) -> ExtractResult:
28
- # Dinamik base URL kullan
29
39
  base_url = self.get_base_url(url)
30
-
31
- if referer:
32
- self.httpx.headers.update({"Referer": referer})
33
-
34
40
  self.httpx.headers.update({
35
- "Sec-Fetch-Dest" : "empty",
36
- "Sec-Fetch-Mode" : "cors",
37
- "Sec-Fetch-Site" : "cross-site",
38
- "Origin" : base_url,
41
+ "Referer" : referer or base_url,
42
+ "Origin" : base_url,
39
43
  })
40
44
 
41
45
  embed_url = self.get_embed_url(url)
42
- istek = await self.httpx.get(embed_url)
43
- response = istek.text
46
+ istek = await self.httpx.get(embed_url, follow_redirects=True)
47
+ text = istek.text
48
+
49
+ # Silinmiş dosya kontrolü
50
+ if "File is no longer available" in text or "File Not Found" in text:
51
+ raise ValueError(f"VidHide: Video silinmiş. {url}")
52
+
53
+ # JS Redirect Kontrolü (OneUpload vb.)
54
+ if js_redirect := HTMLHelper(text).regex_first(r"window\.location\.replace\(['\"]([^'\"]+)['\"]\)") or \
55
+ HTMLHelper(text).regex_first(r"window\.location\.href\s*=\s*['\"]([^'\"]+)['\"]"):
56
+ # Redirect url'i al
57
+ target_url = js_redirect
58
+ # Bazen path relative olabilir ama genelde full url
59
+ if not target_url.startswith("http"):
60
+ # urljoin gerekebilir ama şimdilik doğrudan deneyelim veya fix_url
61
+ target_url = self.fix_url(target_url) # fix_url base'e göre düzeltebilir mi? ExtractorBase.fix_url genelde şema ekler.
62
+ pass
63
+
64
+ # Yeniden istek at
65
+ istek = await self.httpx.get(target_url, headers={"Referer": embed_url}, follow_redirects=True)
66
+ text = istek.text
44
67
 
45
- script = None
46
- if "eval(function" in response:
68
+ sel = HTMLHelper(text)
69
+
70
+ unpacked = ""
71
+ # Eval script bul (regex ile daha sağlam)
72
+ if eval_match := sel.regex_first(r'(eval\s*\(\s*function[\s\S]+?)<\/script>'):
47
73
  try:
48
- unpacked = Packer.unpack(response)
74
+ unpacked = Packer.unpack(eval_match)
49
75
  if "var links" in unpacked:
50
- script = unpacked.split("var links")[1]
51
- else:
52
- script = unpacked
53
- except Exception:
76
+ unpacked = unpacked.split("var links")[1]
77
+ except:
54
78
  pass
55
79
 
56
- if not script:
57
- script = HTMLHelper(response).regex_first(r'(?s)sources:\s*(\[.*?\])')
80
+ content = unpacked or text
58
81
 
59
- m3u8_url = None
60
- if script:
61
- # m3u8 urls could be prefixed by 'file:', 'hls2:' or 'hls4:', so we just match ':'
62
- m3u8_url = HTMLHelper(script).regex_first(r':\s*"([^\"]*?m3u8[^\"]*?)"')
82
+ # Regex: Kotlin mantığı (: "url")
83
+ # Ayrıca sources: [...] mantığını da ekle
84
+ m3u8_url = HTMLHelper(content).regex_first(r'sources:\s*\[\s*\{\s*file:\s*"([^"]+)"')
63
85
 
64
86
  if not m3u8_url:
65
- # Fallback direct search in response if unpacking failed or structure changed
66
- m3u8_url = HTMLHelper(response).regex_first(r'file:"(.*?\.m3u8.*?)"')
67
-
87
+ # Genel arama (hls:, file: vb.)
88
+ # Kotlin Regex: :\s*"(.*?m3u8.*?)"
89
+ match = HTMLHelper(content).regex_first(r':\s*["\']([^"\']+\.m3u8[^"\']*)["\']')
90
+ if match:
91
+ m3u8_url = match
92
+
93
+ if not m3u8_url:
94
+ # Son şans: herhangi bir m3u8 linki
95
+ m3u8_url = HTMLHelper(content).regex_first(r'["\']([^"\']+\.m3u8[^"\']*)["\']')
96
+
68
97
  if not m3u8_url:
69
98
  raise ValueError(f"VidHide: Video URL bulunamadı. {url}")
70
99
 
@@ -72,6 +101,5 @@ class VidHide(ExtractorBase):
72
101
  name = self.name,
73
102
  url = self.fix_url(m3u8_url),
74
103
  referer = f"{base_url}/",
75
- user_agent = self.httpx.headers.get("User-Agent", ""),
76
- subtitles = []
104
+ user_agent = self.httpx.headers.get("User-Agent", "")
77
105
  )
@@ -9,7 +9,7 @@ class VidMoly(ExtractorBase):
9
9
  main_url = "https://vidmoly.to"
10
10
 
11
11
  # Birden fazla domain destekle
12
- supported_domains = ["vidmoly.to", "vidmoly.me", "vidmoly.net"]
12
+ supported_domains = ["vidmoly.to", "vidmoly.me", "vidmoly.net", "vidmoly.biz"]
13
13
 
14
14
  def can_handle_url(self, url: str) -> bool:
15
15
  return any(domain in url for domain in self.supported_domains)
@@ -18,112 +18,78 @@ class VidMoly(ExtractorBase):
18
18
  if referer:
19
19
  self.httpx.headers.update({"Referer": referer})
20
20
 
21
- self.httpx.headers.update({
22
- "Sec-Fetch-Dest" : "iframe",
23
- })
24
-
25
- if ".me" in url:
26
- url = url.replace(".me", ".net")
27
- if ".to" in url:
28
- url = url.replace(".to", ".net")
29
-
30
- # VidMoly bazen redirect ediyor, takip et
31
- response = await self.httpx.get(url, follow_redirects=True)
32
- if "Select number" in response.text:
33
- secici = HTMLHelper(response.text)
34
-
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")
41
-
42
- response = await self.httpx.post(
43
- url = url,
44
- data = {
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
51
- },
52
- follow_redirects=True
53
- )
54
-
21
+ self.httpx.headers.update({"Sec-Fetch-Dest" : "iframe"})
22
+
23
+ # Domain normalleştirme
24
+ url = url.replace(".me", ".net").replace(".to", ".net")
25
+
26
+ resp = await self.httpx.get(url, follow_redirects=True)
27
+ sel = HTMLHelper(resp.text)
28
+
29
+ # "Select number" kontrolü (Bot koruması)
30
+ if "Select number" in resp.text:
31
+ op_val = sel.select_attr("input[name='op']", "value")
32
+ file_code_val = sel.select_attr("input[name='file_code']", "value")
33
+ answer_val = sel.select_text("div.vhint b")
34
+ ts_val = sel.select_attr("input[name='ts']", "value")
35
+ nonce_val = sel.select_attr("input[name='nonce']", "value")
36
+ ctok_val = sel.select_attr("input[name='ctok']", "value")
37
+
38
+ resp = await self.httpx.post(url, data={
39
+ "op" : op_val,
40
+ "file_code" : file_code_val,
41
+ "answer" : answer_val,
42
+ "ts" : ts_val,
43
+ "nonce" : nonce_val,
44
+ "ctok" : ctok_val
45
+ }, follow_redirects=True)
46
+ sel = HTMLHelper(resp.text)
55
47
 
56
48
  # Altyazı kaynaklarını ayrıştır
57
49
  subtitles = []
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")
61
- subtitle_data = self._add_marks(subtitle_data, "label")
62
- subtitle_data = self._add_marks(subtitle_data, "kind")
50
+ if sub_str := sel.regex_first(r"(?s)tracks:\s*\[(.*?)\]"):
51
+ sub_data = self._add_marks(sub_str, "file")
52
+ sub_data = self._add_marks(sub_data, "label")
53
+ sub_data = self._add_marks(sub_data, "kind")
63
54
 
64
55
  with contextlib.suppress(json.JSONDecodeError):
65
- subtitle_sources = json.loads(f"[{subtitle_data}]")
56
+ sub_sources = json.loads(f"[{sub_data}]")
66
57
  subtitles = [
67
- Subtitle(
68
- name = sub.get("label"),
69
- url = self.fix_url(sub.get("file")),
70
- )
71
- for sub in subtitle_sources
72
- if sub.get("kind") == "captions"
58
+ Subtitle(name=sub.get("label"), url=self.fix_url(sub.get("file")))
59
+ for sub in sub_sources if sub.get("kind") == "captions"
73
60
  ]
74
61
 
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
88
- # Video kaynaklarını ayrıştır
89
- video_data = self._add_marks(script_content, "file")
90
- try:
91
- video_sources = json.loads(f"[{video_data}]")
92
- # İlk video kaynağını al
93
- for source in video_sources:
94
- if file_url := source.get("file"):
95
- return ExtractResult(
96
- name = self.name,
97
- url = file_url,
98
- referer = self.main_url,
99
- subtitles = subtitles
100
- )
101
- except json.JSONDecodeError:
102
- pass
103
-
104
- # Fallback: Doğrudan file regex ile ara (Kotlin mantığı)
105
- # file:"..." veya file: "..."
106
- if file_match := resp_sec.regex_first(r'file\s*:\s*["\']([^"\']+\.m3u8[^"\']*)["\']'):
107
- return ExtractResult(
108
- name = self.name,
109
- url = file_match,
110
- referer = self.main_url,
111
- subtitles = subtitles
112
- )
113
-
114
- # Fallback 2: Herhangi bir file (m3u8 olma şartı olmadan ama tercihen)
115
- if file_match := resp_sec.regex_first(r'file\s*:\s*["\']([^"\']+)["\']'):
116
- url_candidate = file_match
117
- # Resim dosyalarını hariç tut
118
- if not url_candidate.endswith(('.jpg', '.png', '.jpeg')):
119
- return ExtractResult(
120
- name = self.name,
121
- url = url_candidate,
122
- referer = self.main_url,
123
- subtitles = subtitles
124
- )
125
-
126
- raise ValueError("Video URL bulunamadı.")
62
+ # Video URL Bulma
63
+ video_url = None
64
+ if "#EXTM3U" in resp.text:
65
+ for line in resp.text.splitlines():
66
+ if line.strip().startswith("http"):
67
+ video_url = line.strip().replace('"', '').replace("'", "")
68
+ break
69
+
70
+ if not video_url:
71
+ if src_str := sel.regex_first(r"(?s)sources:\s*\[(.*?)\],"):
72
+ vid_data = self._add_marks(src_str, "file")
73
+ with contextlib.suppress(json.JSONDecodeError):
74
+ vid_sources = json.loads(f"[{vid_data}]")
75
+ for source in vid_sources:
76
+ if source.get("file"):
77
+ video_url = source.get("file")
78
+ break
79
+
80
+ if not video_url:
81
+ video_url = sel.regex_first(r'file\s*:\s*["\']([^"\']+\.m3u8[^"\']*)["\']') or \
82
+ sel.regex_first(r'file\s*:\s*["\']([^"\']+\.mp4[^"\']*)["\']')
83
+
84
+ if not video_url:
85
+ raise ValueError(f"VidMoly: Video URL bulunamadı. {url}")
86
+
87
+ return ExtractResult(
88
+ name = self.name,
89
+ url = video_url,
90
+ referer = f"{self.get_base_url(url)}/",
91
+ subtitles = subtitles
92
+ )
127
93
 
128
94
  def _add_marks(self, text: str, field: str) -> str:
129
95
  """
@@ -7,42 +7,31 @@ class VidMoxy(ExtractorBase):
7
7
  name = "VidMoxy"
8
8
  main_url = "https://vidmoxy.com"
9
9
 
10
- async def extract(self, url, referer=None) -> ExtractResult:
10
+ async def extract(self, url: str, referer: str = None) -> ExtractResult:
11
11
  if referer:
12
12
  self.httpx.headers.update({"Referer": referer})
13
13
 
14
- istek = await self.httpx.get(url)
15
- istek.raise_for_status()
14
+ resp = await self.httpx.get(url)
15
+ sel = HTMLHelper(resp.text)
16
16
 
17
- subtitles = []
18
- subtitle_matches = HTMLHelper(istek.text).regex_all(r'captions","file":"([^\"]+)","label":"([^\"]+)"')
19
- seen_subtitles = set()
17
+ subtitles = []
18
+ for s_url, s_lang in sel.regex_all(r'captions","file":"([^\"]+)","label":"([^\"]+)"'):
19
+ decoded_lang = s_lang.encode().decode('unicode_escape')
20
+ subtitles.append(Subtitle(name=decoded_lang, url=s_url.replace("\\", "")))
20
21
 
21
- for sub_url, sub_lang in subtitle_matches:
22
- if sub_url in seen_subtitles:
23
- continue
22
+ hex_data = sel.regex_first(r'file": "(.*)",')
23
+ if not hex_data:
24
+ eval_data = sel.regex_first(r'\};\s*(eval\(function[\s\S]*?)var played = \d+;')
25
+ if eval_data:
26
+ unpacked = Packer.unpack(Packer.unpack(eval_data))
27
+ hex_data = HTMLHelper(unpacked).regex_first(r'file":"(.*)","label')
24
28
 
25
- seen_subtitles.add(sub_url)
26
- decoded_lang = (
27
- sub_lang.replace("\\u0131", "ı")
28
- .replace("\\u0130", "İ")
29
- .replace("\\u00fc", "ü")
30
- .replace("\\u00e7", "ç")
31
- )
32
- subtitles.append(Subtitle(name=decoded_lang, url=sub_url.replace("\\", "")))
33
-
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')
40
-
41
- m3u_link = HexCodec.decode(escaped_hex)
29
+ if not hex_data:
30
+ raise ValueError(f"VidMoxy: Hex data bulunamadı. {url}")
42
31
 
43
32
  return ExtractResult(
44
33
  name = self.name,
45
- url = m3u_link,
34
+ url = HexCodec.decode(hex_data),
46
35
  referer = self.main_url,
47
36
  subtitles = subtitles
48
37
  )
@@ -4,84 +4,54 @@ from KekikStream.Core import ExtractorBase, ExtractResult, Subtitle, HTMLHelper
4
4
 
5
5
 
6
6
  class VidPapi(ExtractorBase):
7
- name = "VidApi"
7
+ name = "VidPapi"
8
8
  main_url = "https://vidpapi.xyz"
9
9
 
10
- async def extract(self, url, referer=None) -> ExtractResult:
11
- ext_ref = referer or ""
10
+ async def extract(self, url: str, referer: str = None) -> ExtractResult:
11
+ ref = referer or self.main_url
12
12
 
13
- # URL parsing
13
+ # ID tespiti
14
14
  if "video/" in url:
15
15
  vid_id = url.split("video/")[-1]
16
16
  else:
17
17
  vid_id = url.split("?data=")[-1]
18
18
 
19
- # 1. Altyazıları çek
20
- sub_url = f"{self.main_url}/player/index.php?data={vid_id}"
21
- sub_headers = {
19
+ headers = {
22
20
  "Content-Type" : "application/x-www-form-urlencoded; charset=UTF-8",
23
21
  "X-Requested-With" : "XMLHttpRequest",
24
- "User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:137.0) Gecko/20100101 Firefox/137.0",
25
- "Referer" : ext_ref or "https://kultfilmler.pro/"
22
+ "Referer" : ref
26
23
  }
27
24
 
25
+ # 1. Altyazıları çek
28
26
  subtitles = []
29
27
  try:
30
- sub_istek = await self.httpx.post(
31
- url = sub_url,
32
- headers = sub_headers,
33
- data = {"hash": vid_id, "r": "https://kultfilmler.pro/"}
28
+ sub_resp = await self.httpx.post(
29
+ f"{self.main_url}/player/index.php?data={vid_id}",
30
+ headers = headers,
31
+ data = {"hash": vid_id, "r": ref}
34
32
  )
35
-
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'\[(.*?)\](.*?)(?:,|$)')
39
- for lang, sub_link in found_subs:
40
- lang = lang.strip()
41
- if "Türkçe" in lang:
42
- lang_code = "tr"
43
- lang_name = "Turkish"
44
- elif "İngilizce" in lang:
45
- lang_code = "en"
46
- lang_name = "English"
47
- else:
48
- lang_code = lang[:2].lower()
49
- lang_name = lang
50
-
51
- subtitles.append(Subtitle(
52
- name = lang_name,
53
- url = sub_link.strip()
54
- ))
55
-
56
- except Exception as e:
33
+ sel = HTMLHelper(sub_resp.text)
34
+ if raw_subs := sel.regex_first(r'var playerjsSubtitle\s*=\s*"([^"]*)"'):
35
+ for lang, link in HTMLHelper(raw_subs).regex_all(r'\[(.*?)\](https?://[^\s\",]+)'):
36
+ subtitles.append(Subtitle(name=lang.strip(), url=link.strip()))
37
+ except:
57
38
  pass
58
39
 
59
40
  # 2. Videoyu çek
60
- video_url = f"{self.main_url}/player/index.php?data={vid_id}&do=getVideo"
61
- video_headers = sub_headers.copy()
62
-
63
- response = await self.httpx.post(
64
- url = video_url,
65
- headers = video_headers,
66
- data = {"hash": vid_id, "r": "https://kultfilmler.pro/"}
41
+ resp = await self.httpx.post(
42
+ f"{self.main_url}/player/index.php?data={vid_id}&do=getVideo",
43
+ headers = headers,
44
+ data = {"hash": vid_id, "r": ref}
67
45
  )
68
- response.raise_for_status()
69
-
70
- try:
71
- video_data = response.json()
72
- except Exception:
73
- return None
46
+ data = resp.json()
74
47
 
75
- stream_url = video_data.get("securedLink")
76
- if not stream_url or not stream_url.strip():
77
- stream_url = video_data.get("videoSource")
78
-
48
+ stream_url = data.get("securedLink") or data.get("videoSource")
79
49
  if not stream_url:
80
- raise ValueError("No video link found in VidPapi response")
50
+ raise ValueError(f"VidPapi: Video URL bulunamadı. {url}")
81
51
 
82
52
  return ExtractResult(
83
53
  name = self.name,
84
54
  url = stream_url,
85
- referer = ext_ref or self.main_url,
55
+ referer = ref,
86
56
  subtitles = subtitles
87
57
  )
@@ -1,4 +1,4 @@
1
- # ! Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
1
+ # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
2
 
3
3
  from KekikStream.Core import ExtractorBase, ExtractResult, Subtitle, HTMLHelper
4
4
  import json
@@ -7,47 +7,26 @@ class VideoSeyred(ExtractorBase):
7
7
  name = "VideoSeyred"
8
8
  main_url = "https://videoseyred.in"
9
9
 
10
- async def extract(self, url, referer=None) -> ExtractResult:
11
- if referer:
12
- self.httpx.headers.update({"Referer": referer})
10
+ async def extract(self, url: str, referer: str = None) -> list[ExtractResult] | ExtractResult:
11
+ v_id = url.split("embed/")[1].split("?")[0]
12
+ if len(v_id) > 10:
13
+ resp = await self.httpx.get(url)
14
+ v_id = HTMLHelper(resp.text).regex_first(r"playlist\/(.*)\.json")
13
15
 
14
- video_id = url.split("embed/")[1].split("?")[0]
15
- if len(video_id) > 10:
16
- kontrol = await self.httpx.get(url)
17
- kontrol.raise_for_status()
18
-
19
- video_id = HTMLHelper(kontrol.text).regex_first(r"playlist\/(.*)\.json")
20
-
21
- video_url = f"{self.main_url}/playlist/{video_id}.json"
22
-
23
- response = await self.httpx.get(video_url)
24
- response.raise_for_status()
25
-
26
- try:
27
- if response_list := json.loads(response.text):
28
- response_data = response_list[0]
29
- else:
30
- raise ValueError("Empty response from VideoSeyred.")
31
-
32
- except (json.JSONDecodeError, IndexError) as hata:
33
- raise RuntimeError(f"Failed to parse response: {hata}") from hata
16
+ json_resp = await self.httpx.get(f"{self.main_url}/playlist/{v_id}.json")
17
+ data = json_resp.json()[0]
34
18
 
35
19
  subtitles = [
36
- Subtitle(name=track["label"], url=self.fix_url(track["file"]))
37
- for track in response_data.get("tracks", [])
38
- if track.get("kind") == "captions" and track.get("label")
20
+ Subtitle(name=t["label"], url=self.fix_url(t["file"]))
21
+ for t in data.get("tracks", []) if t.get("kind") == "captions"
22
+ ]
23
+
24
+ results = [
25
+ ExtractResult(name=self.name, url=self.fix_url(s["file"]), referer=self.main_url, subtitles=subtitles)
26
+ for s in data.get("sources", [])
39
27
  ]
40
28
 
41
- if video_links := [
42
- ExtractResult(
43
- name = self.name,
44
- url = self.fix_url(source["file"]),
45
- referer = self.main_url,
46
- subtitles = subtitles,
47
- )
48
- for source in response_data.get("sources", [])
49
- ]:
50
- # En yüksek kaliteli videoyu döndür (varsayılan olarak ilk video)
51
- return video_links[0] if len(video_links) == 1 else video_links
52
- else:
53
- raise ValueError("No video links found in the response.")
29
+ if not results:
30
+ raise ValueError(f"VideoSeyred: Video bulunamadı. {url}")
31
+
32
+ return results[0] if len(results) == 1 else results