KekikStream 0.7.1__py3-none-any.whl

Sign up to get free protection for your applications and to get access to all the features.

Potentially problematic release.


This version of KekikStream might be problematic. Click here for more details.

Files changed (59) hide show
  1. KekikStream/CLI/__init__.py +4 -0
  2. KekikStream/CLI/pypi_kontrol.py +30 -0
  3. KekikStream/Core/ExtractorBase.py +42 -0
  4. KekikStream/Core/ExtractorLoader.py +82 -0
  5. KekikStream/Core/ExtractorModels.py +19 -0
  6. KekikStream/Core/MediaHandler.py +142 -0
  7. KekikStream/Core/PluginBase.py +80 -0
  8. KekikStream/Core/PluginLoader.py +61 -0
  9. KekikStream/Core/PluginModels.py +63 -0
  10. KekikStream/Core/__init__.py +9 -0
  11. KekikStream/Extractors/CloseLoad.py +31 -0
  12. KekikStream/Extractors/ContentX.py +80 -0
  13. KekikStream/Extractors/FourCX.py +7 -0
  14. KekikStream/Extractors/FourPichive.py +7 -0
  15. KekikStream/Extractors/FourPlayRu.py +7 -0
  16. KekikStream/Extractors/HDStreamAble.py +7 -0
  17. KekikStream/Extractors/Hotlinger.py +7 -0
  18. KekikStream/Extractors/MailRu.py +40 -0
  19. KekikStream/Extractors/MixPlayHD.py +42 -0
  20. KekikStream/Extractors/Odnoklassniki.py +106 -0
  21. KekikStream/Extractors/OkRuHTTP.py +7 -0
  22. KekikStream/Extractors/OkRuSSL.py +7 -0
  23. KekikStream/Extractors/PeaceMakerst.py +57 -0
  24. KekikStream/Extractors/Pichive.py +7 -0
  25. KekikStream/Extractors/PixelDrain.py +28 -0
  26. KekikStream/Extractors/PlayRu.py +7 -0
  27. KekikStream/Extractors/RapidVid.py +60 -0
  28. KekikStream/Extractors/SibNet.py +29 -0
  29. KekikStream/Extractors/Sobreatsesuyp.py +59 -0
  30. KekikStream/Extractors/TRsTX.py +67 -0
  31. KekikStream/Extractors/TauVideo.py +34 -0
  32. KekikStream/Extractors/TurboImgz.py +25 -0
  33. KekikStream/Extractors/VidMoly.py +85 -0
  34. KekikStream/Extractors/VidMoxy.py +50 -0
  35. KekikStream/Extractors/VideoSeyred.py +47 -0
  36. KekikStream/Managers/ExtractorManager.py +27 -0
  37. KekikStream/Managers/MediaManager.py +19 -0
  38. KekikStream/Managers/PluginManager.py +19 -0
  39. KekikStream/Managers/UIManager.py +49 -0
  40. KekikStream/Managers/__init__.py +6 -0
  41. KekikStream/Plugins/DiziBox.py +143 -0
  42. KekikStream/Plugins/DiziYou.py +127 -0
  43. KekikStream/Plugins/Dizilla.py +106 -0
  44. KekikStream/Plugins/FilmMakinesi.py +65 -0
  45. KekikStream/Plugins/FullHDFilmizlesene.py +78 -0
  46. KekikStream/Plugins/JetFilmizle.py +92 -0
  47. KekikStream/Plugins/RecTV.py +113 -0
  48. KekikStream/Plugins/SezonlukDizi.py +108 -0
  49. KekikStream/Plugins/SineWix.py +108 -0
  50. KekikStream/Plugins/UgurFilm.py +75 -0
  51. KekikStream/__init__.py +255 -0
  52. KekikStream/__main__.py +6 -0
  53. KekikStream/requirements.txt +10 -0
  54. KekikStream-0.7.1.dist-info/LICENSE +674 -0
  55. KekikStream-0.7.1.dist-info/METADATA +94 -0
  56. KekikStream-0.7.1.dist-info/RECORD +59 -0
  57. KekikStream-0.7.1.dist-info/WHEEL +5 -0
  58. KekikStream-0.7.1.dist-info/entry_points.txt +2 -0
  59. KekikStream-0.7.1.dist-info/top_level.txt +1 -0
@@ -0,0 +1,7 @@
1
+ # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
+
3
+ from KekikStream.Extractors.ContentX import ContentX
4
+
5
+ class FourPlayRu(ContentX):
6
+ name = "FourPlayRu"
7
+ main_url = "https://four.playru.net"
@@ -0,0 +1,7 @@
1
+ # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
+
3
+ from KekikStream.Extractors.PeaceMakerst import PeaceMakerst
4
+
5
+ class HDStreamAble(PeaceMakerst):
6
+ name = "HDStreamAble"
7
+ main_url = "https://hdstreamable.com"
@@ -0,0 +1,7 @@
1
+ # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
+
3
+ from KekikStream.Extractors.ContentX import ContentX
4
+
5
+ class Hotlinger(ContentX):
6
+ name = "Hotlinger"
7
+ main_url = "https://hotlinger.com"
@@ -0,0 +1,40 @@
1
+ # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
+
3
+ from KekikStream.Core import ExtractorBase, ExtractResult
4
+
5
+ class MailRuExtractor(ExtractorBase):
6
+ name = "MailRu"
7
+ main_url = "https://my.mail.ru"
8
+
9
+ async def extract(self, url, referer=None) -> ExtractResult:
10
+ vid_id = url.split("video/embed/")[-1].strip()
11
+ video_meta_url = f"{self.main_url}/+/video/meta/{vid_id}"
12
+
13
+ if referer:
14
+ self.oturum.headers.update({"Referer": referer})
15
+
16
+ istek = await self.oturum.get(video_meta_url)
17
+ istek.raise_for_status()
18
+
19
+ video_key = istek.cookies.get("video_key")
20
+ if not video_key:
21
+ raise ValueError("Video key bulunamadı.")
22
+
23
+ video_data = istek.json()
24
+ videos = video_data.get("videos", [])
25
+ if not videos:
26
+ raise ValueError("Videolar bulunamadı.")
27
+
28
+ video = videos[0]
29
+ video_url = video["url"]
30
+ if video_url.startswith("//"):
31
+ video_url = f"https:{video_url}"
32
+
33
+ await self.close()
34
+ return ExtractResult(
35
+ name = self.name,
36
+ url = video_url,
37
+ referer = self.main_url,
38
+ subtitles = [],
39
+ headers = {"Cookie": f"video_key={video_key}"}
40
+ )
@@ -0,0 +1,42 @@
1
+ # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
+
3
+ from KekikStream.Core import ExtractorBase, ExtractResult
4
+ from Kekik.Sifreleme import AESManager
5
+ import re, json
6
+
7
+ class MixPlayHD(ExtractorBase):
8
+ name = "MixPlayHD"
9
+ main_url = "https://mixplayhd.com"
10
+
11
+ async def extract(self, url, referer=None) -> ExtractResult:
12
+ if referer:
13
+ self.oturum.headers.update({"Referer": referer})
14
+
15
+ istek = await self.oturum.get(url)
16
+ istek.raise_for_status()
17
+
18
+ be_player_match = re.search(r"bePlayer\('([^']+)',\s*'(\{[^\}]+\})'\);", istek.text)
19
+ if not be_player_match:
20
+ raise ValueError("bePlayer not found in the response.")
21
+
22
+ be_player_pass = be_player_match[1]
23
+ be_player_data = be_player_match[2]
24
+
25
+ try:
26
+ decrypted_data = AESManager.decrypt(be_player_data, be_player_pass).replace("\\", "")
27
+ decrypted_json = json.loads(decrypted_data)
28
+ except Exception as hata:
29
+ raise RuntimeError(f"Decryption failed: {hata}") from hata
30
+
31
+ if video_url_match := re.search(
32
+ pattern = r'"video_location":"([^"]+)"',
33
+ string = decrypted_json.get("schedule", {}).get("client", ""),
34
+ ):
35
+ return ExtractResult(
36
+ name = self.name,
37
+ url = video_url_match[1],
38
+ referer = self.main_url,
39
+ subtitles = []
40
+ )
41
+ else:
42
+ raise ValueError("M3U8 video URL not found in the decrypted data.")
@@ -0,0 +1,106 @@
1
+ # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
+
3
+ from KekikStream.Core import ExtractorBase, ExtractResult
4
+ import re, json
5
+
6
+ class Odnoklassniki(ExtractorBase):
7
+ name = "Odnoklassniki"
8
+ main_url = "https://odnoklassniki.ru"
9
+
10
+ async def extract(self, url, referer=None) -> ExtractResult:
11
+ if referer:
12
+ self.oturum.headers.update({"Referer": referer})
13
+
14
+ self.oturum.headers.update({
15
+ "User-Agent": "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/114.0.0.0 Mobile Safari/537.36"
16
+ })
17
+
18
+ if "/video/" in url:
19
+ url = url.replace("/video/", "/videoembed/")
20
+
21
+ try:
22
+ istek = await self.fetch_with_redirects(url)
23
+ istek.raise_for_status()
24
+ except Exception as hata:
25
+ raise RuntimeError(f"Failed to fetch the URL: {url}, Error: {hata}") from hata
26
+
27
+ response_text = (
28
+ istek.text.replace("\\"", "\"")
29
+ .replace("\\\\", "\\")
30
+ .replace(r"\\u", "\\u")
31
+ )
32
+ response_text = re.sub(
33
+ r"\\u([0-9A-Fa-f]{4})",
34
+ lambda match: chr(int(match[1], 16)),
35
+ response_text
36
+ )
37
+
38
+ videos_match = re.search(r'"videos":(\[.*?\])', response_text)
39
+ if not videos_match:
40
+ raise ValueError("No video data found in the response.")
41
+
42
+ try:
43
+ videos = json.loads(videos_match[1])
44
+ except json.JSONDecodeError as hata:
45
+ raise ValueError("Failed to parse video data.") from hata
46
+
47
+ quality_order = {
48
+ "ULTRA": 6, # 4K veya daha yüksek
49
+ "QUAD": 5, # 1440p
50
+ "FULL": 4, # 1080p
51
+ "HD": 3, # 720p
52
+ "SD": 2, # 480p
53
+ "LOW": 1, # 360p
54
+ "MOBILE": 0 # 144p
55
+ }
56
+
57
+ # Kaliteye göre en iyi videoyu seçme
58
+ best_video = None
59
+ best_quality_score = -1
60
+
61
+ for video in videos:
62
+ video_url = video.get("url")
63
+ quality_name = video.get("name", "").upper()
64
+
65
+ if not video_url or not quality_name:
66
+ continue
67
+
68
+ # Kalite sıralamasına göre puanla
69
+ quality_score = quality_order.get(quality_name, -1)
70
+ if quality_score > best_quality_score:
71
+ best_quality_score = quality_score
72
+ best_video = video_url
73
+
74
+ if not best_video:
75
+ raise ValueError("No valid video URLs found.")
76
+
77
+ if best_video.startswith("//"):
78
+ best_video = f"https:{best_video}"
79
+
80
+ return ExtractResult(
81
+ name = self.name,
82
+ url = best_video,
83
+ referer = self.main_url,
84
+ subtitles = []
85
+ )
86
+
87
+ async def fetch_with_redirects(self, url, max_redirects=5):
88
+ """Yönlendirmeleri takip eden bir fonksiyon"""
89
+ redirects = 0
90
+ while redirects < max_redirects:
91
+ istek = await self.oturum.get(url, follow_redirects=False)
92
+
93
+ if istek.status_code not in [301, 302]:
94
+ break # Yönlendirme yoksa çık
95
+
96
+ redirected_url = istek.headers.get("Location")
97
+ if not redirected_url:
98
+ raise ValueError("Redirect location not found.")
99
+
100
+ url = redirected_url if redirected_url.startswith("http") else f"https://{redirected_url}"
101
+ redirects += 1
102
+
103
+ if redirects == max_redirects:
104
+ raise RuntimeError(f"Max redirects ({max_redirects}) reached.")
105
+
106
+ return istek
@@ -0,0 +1,7 @@
1
+ # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
+
3
+ from KekikStream.Extractors.Odnoklassniki import Odnoklassniki
4
+
5
+ class OkRuHTTP(Odnoklassniki):
6
+ name = "OkRuHTTP"
7
+ main_url = "http://ok.ru"
@@ -0,0 +1,7 @@
1
+ # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
+
3
+ from KekikStream.Extractors.Odnoklassniki import Odnoklassniki
4
+
5
+ class OkRuSSL(Odnoklassniki):
6
+ name = "OkRuSSL"
7
+ main_url = "https://ok.ru"
@@ -0,0 +1,57 @@
1
+ # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
+
3
+ from KekikStream.Core import ExtractorBase, ExtractResult
4
+ import re, json
5
+
6
+ class PeaceMakerst(ExtractorBase):
7
+ name = "PeaceMakerst"
8
+ main_url = "https://peacemakerst.com"
9
+
10
+ async def extract(self, url, referer=None) -> ExtractResult:
11
+ if referer:
12
+ self.oturum.headers.update({"Referer": referer})
13
+
14
+ self.oturum.headers.update({
15
+ "Content-Type" : "application/x-www-form-urlencoded; charset=UTF-8",
16
+ "X-Requested-With" : "XMLHttpRequest"
17
+ })
18
+
19
+ response = await self.oturum.post(
20
+ url = f"{url}?do=getVideo",
21
+ data = {
22
+ "hash" : url.split("video/")[-1],
23
+ "r" : referer or "",
24
+ "s" : ""
25
+ }
26
+ )
27
+ response.raise_for_status()
28
+
29
+ response_text = response.text
30
+ m3u_link = None
31
+
32
+ if "teve2.com.tr\\/embed\\/" in response_text:
33
+ teve2_id = re.search(r"teve2\.com\.tr\\\/embed\\\/(\d+)", response_text)[1]
34
+ teve2_url = f"https://www.teve2.com.tr/action/media/{teve2_id}"
35
+
36
+ teve2_response = await self.oturum.get(teve2_url, headers={"Referer": f"https://www.teve2.com.tr/embed/{teve2_id}"})
37
+ teve2_response.raise_for_status()
38
+ teve2_json = teve2_response.json()
39
+
40
+ m3u_link = f"{teve2_json['Media']['Link']['ServiceUrl']}//{teve2_json['Media']['Link']['SecurePath']}"
41
+ else:
42
+ try:
43
+ video_response = response.json()
44
+ if video_sources := video_response.get("videoSources", []):
45
+ m3u_link = video_sources[-1]["file"]
46
+ except (json.JSONDecodeError, KeyError) as hata:
47
+ raise ValueError("Peace response is invalid or null.") from hata
48
+
49
+ if not m3u_link:
50
+ raise ValueError("m3u link not found.")
51
+
52
+ return ExtractResult(
53
+ name = self.name,
54
+ url = m3u_link,
55
+ referer = url,
56
+ subtitles = []
57
+ )
@@ -0,0 +1,7 @@
1
+ # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
+
3
+ from KekikStream.Extractors.ContentX import ContentX
4
+
5
+ class Pichive(ContentX):
6
+ name = "Pichive"
7
+ main_url = "https://pichive.online"
@@ -0,0 +1,28 @@
1
+ # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
+
3
+ from KekikStream.Core import ExtractorBase, ExtractResult
4
+ import re
5
+
6
+ class PixelDrain(ExtractorBase):
7
+ name = "PixelDrain"
8
+ main_url = "https://pixeldrain.com"
9
+
10
+ async def extract(self, url, referer=None) -> ExtractResult:
11
+ if referer:
12
+ self.oturum.headers.update({"Referer": referer})
13
+
14
+ pixel_id_match = re.search(r"/u/([^/?]+)|([^\/]+)(?=\?download)", url)
15
+ if not pixel_id_match:
16
+ raise ValueError("PixelDrain bağlantısından ID çıkarılamadı.")
17
+
18
+ pixel_id = pixel_id_match[1]
19
+ download_link = f"{self.main_url}/api/file/{pixel_id}?download"
20
+ referer_link = f"{self.main_url}/u/{pixel_id}?download"
21
+
22
+ await self.close()
23
+ return ExtractResult(
24
+ name = f"{self.name} - {pixel_id}",
25
+ url = download_link,
26
+ referer = referer_link,
27
+ subtitles = []
28
+ )
@@ -0,0 +1,7 @@
1
+ # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
+
3
+ from KekikStream.Extractors.ContentX import ContentX
4
+
5
+ class PlayRu(ContentX):
6
+ name = "PlayRu"
7
+ main_url = "https://playru.net"
@@ -0,0 +1,60 @@
1
+ # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
+
3
+ from KekikStream.Core import ExtractorBase, ExtractResult, Subtitle
4
+ from Kekik.Sifreleme import Packer, HexCodec
5
+ import re
6
+
7
+ class RapidVid(ExtractorBase):
8
+ name = "RapidVid"
9
+ main_url = "https://rapidvid.net"
10
+
11
+ async def extract(self, url, referer=None) -> ExtractResult:
12
+ if referer:
13
+ self.oturum.headers.update({"Referer": referer})
14
+
15
+ istek = await self.oturum.get(url)
16
+ istek.raise_for_status()
17
+
18
+ subtitles = []
19
+ subtitle_matches = re.findall(r'captions\",\"file\":\"([^\"]+)\",\"label\":\"([^\"]+)\"', istek.text)
20
+ seen_subtitles = set()
21
+
22
+ for sub_url, sub_lang in subtitle_matches:
23
+ if sub_url in seen_subtitles:
24
+ continue
25
+
26
+ seen_subtitles.add(sub_url)
27
+ decoded_lang = (
28
+ sub_lang.replace("\\u0131", "ı")
29
+ .replace("\\u0130", "İ")
30
+ .replace("\\u00fc", "ü")
31
+ .replace("\\u00e7", "ç")
32
+ )
33
+ subtitles.append(Subtitle(name=decoded_lang, url=sub_url.replace("\\", "")))
34
+
35
+ try:
36
+ if extracted_value := re.search(r'file": "(.*)",', istek.text):
37
+ escaped_hex = extracted_value[1]
38
+ decoded_url = HexCodec.decode(escaped_hex)
39
+ else:
40
+ eval_jwsetup = re.search(r'\};\s*(eval\(function[\s\S]*?)var played = \d+;', istek.text)
41
+ if not eval_jwsetup:
42
+ raise ValueError("JWPlayer setup not found.")
43
+
44
+ unpacked_jwsetup = Packer.unpack(Packer.unpack(eval_jwsetup[1]))
45
+ extracted_value = re.search(r'file":"(.*)","label', unpacked_jwsetup)
46
+ if not extracted_value:
47
+ raise ValueError("File URL not found in unpacked JWPlayer setup.")
48
+
49
+ escaped_hex = extracted_value[1].replace("\\\\x", "")
50
+ decoded_url = bytes.fromhex(escaped_hex).decode("utf-8")
51
+ except Exception as hata:
52
+ raise RuntimeError(f"Extraction failed: {hata}") from hata
53
+
54
+ await self.close()
55
+ return ExtractResult(
56
+ name = self.name,
57
+ url = decoded_url,
58
+ referer = self.main_url,
59
+ subtitles = subtitles
60
+ )
@@ -0,0 +1,29 @@
1
+ # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
+
3
+ from KekikStream.Core import ExtractorBase, ExtractResult
4
+ import re
5
+
6
+ class SibNet(ExtractorBase):
7
+ name = "SibNet"
8
+ main_url = "https://video.sibnet.ru"
9
+
10
+ async def extract(self, url, referer=None) -> ExtractResult:
11
+ if referer:
12
+ self.oturum.headers.update({"Referer": referer})
13
+
14
+ response = await self.oturum.get(url)
15
+ response.raise_for_status()
16
+
17
+ match = re.search(r'player\.src\(\[\{src: \"([^\"]+)\"', response.text)
18
+ if not match:
19
+ raise ValueError("m3u bağlantısı bulunamadı.")
20
+
21
+ m3u_link = f"{self.main_url}{match[1]}"
22
+
23
+ await self.close()
24
+ return ExtractResult(
25
+ name = self.name,
26
+ url = m3u_link,
27
+ referer = url,
28
+ subtitles = []
29
+ )
@@ -0,0 +1,59 @@
1
+ # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
+
3
+ from KekikStream.Core import ExtractorBase, ExtractResult
4
+ import re, json
5
+
6
+ class Sobreatsesuyp(ExtractorBase):
7
+ name = "Sobreatsesuyp"
8
+ main_url = "https://sobreatsesuyp.com"
9
+
10
+ async def extract(self, url, referer=None) -> ExtractResult:
11
+ if referer:
12
+ self.oturum.headers.update({"Referer": referer})
13
+
14
+ istek = await self.oturum.get(url)
15
+ istek.raise_for_status()
16
+
17
+ file_match = re.search(r'file\":\"([^\"]+)', istek.text)
18
+ if not file_match:
19
+ raise ValueError("File not found in response.")
20
+
21
+ file_path = file_match[1].replace("\\", "")
22
+ post_link = f"{self.main_url}/{file_path}"
23
+
24
+ post_istek = await self.oturum.post(post_link)
25
+ post_istek.raise_for_status()
26
+
27
+ try:
28
+ post_json = json.loads(post_istek.text)
29
+ except json.JSONDecodeError as hata:
30
+ raise ValueError("Failed to parse JSON response.") from hata
31
+
32
+ video_data_list = post_json[1:] if isinstance(post_json, list) else []
33
+
34
+ all_results = []
35
+
36
+ for item in video_data_list:
37
+ title = item.get("title")
38
+ file = item.get("file")
39
+
40
+ if not title or not file:
41
+ continue
42
+
43
+ playlist_url = f"{self.main_url}/playlist/{file.lstrip('/')}.txt"
44
+ playlist_request = await self.oturum.post(playlist_url, headers={"Referer": referer or self.main_url})
45
+ playlist_request.raise_for_status()
46
+
47
+ all_results.append(
48
+ ExtractResult(
49
+ name = f"{self.name} - {title}",
50
+ url = playlist_request.text,
51
+ referer = self.main_url,
52
+ subtitles = []
53
+ )
54
+ )
55
+
56
+ if not all_results:
57
+ raise ValueError("No videos found in response.")
58
+
59
+ return all_results[0] if len(all_results) == 1 else all_results
@@ -0,0 +1,67 @@
1
+ # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
+
3
+ from KekikStream.Core import ExtractorBase, ExtractResult
4
+ import re, json
5
+
6
+ class TRsTX(ExtractorBase):
7
+ name = "TRsTX"
8
+ main_url = "https://trstx.org"
9
+
10
+ async def extract(self, url, referer=None) -> list[ExtractResult]:
11
+ if referer:
12
+ self.oturum.headers.update({"Referer": referer})
13
+
14
+ istek = await self.oturum.get(url)
15
+ istek.raise_for_status()
16
+
17
+ file_match = re.search(r'file\":\"([^\"]+)', istek.text)
18
+ if not file_match:
19
+ raise ValueError("File not found in response.")
20
+
21
+ file_path = file_match[1].replace("\\", "")
22
+ post_link = f"{self.main_url}/{file_path}"
23
+
24
+ post_istek = await self.oturum.post(post_link)
25
+ post_istek.raise_for_status()
26
+
27
+ try:
28
+ post_json = json.loads(post_istek.text)
29
+ except json.JSONDecodeError as hata:
30
+ raise ValueError("Failed to parse JSON response.") from hata
31
+
32
+ video_data_list = post_json[1:] if isinstance(post_json, list) else []
33
+
34
+ video_links = set()
35
+ all_results = []
36
+
37
+ for item in video_data_list:
38
+ title = item.get("title")
39
+ file = item.get("file")
40
+
41
+ if not title or not file:
42
+ continue
43
+
44
+ playlist_url = f"{self.main_url}/playlist/{file.lstrip('/')}.txt"
45
+ playlist_request = await self.oturum.post(playlist_url, headers={"Referer": referer or self.main_url})
46
+ playlist_request.raise_for_status()
47
+
48
+ video_data = playlist_request.text
49
+
50
+ if video_data in video_links:
51
+ continue
52
+
53
+ video_links.add(video_data)
54
+
55
+ all_results.append(
56
+ ExtractResult(
57
+ name = f"{self.name} - {title}",
58
+ url = video_data,
59
+ referer = self.main_url,
60
+ subtitles = []
61
+ )
62
+ )
63
+
64
+ if not all_results:
65
+ raise ValueError("No videos found in response.")
66
+
67
+ return all_results[0] if len(all_results) == 1 else all_results
@@ -0,0 +1,34 @@
1
+ # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
+
3
+ from KekikStream.Core import ExtractorBase, ExtractResult
4
+
5
+ class TauVideo(ExtractorBase):
6
+ name = "TauVideo"
7
+ main_url = "https://tau-video.xyz"
8
+
9
+ async def extract(self, url, referer=None) -> list[ExtractResult]:
10
+ if referer:
11
+ self.oturum.headers.update({"Referer": referer})
12
+
13
+ video_key = url.split("/")[-1]
14
+ api_url = f"{self.main_url}/api/video/{video_key}"
15
+
16
+ response = await self.oturum.get(api_url)
17
+ response.raise_for_status()
18
+
19
+ api_data = response.json()
20
+
21
+ if "urls" not in api_data:
22
+ raise ValueError("API yanıtında 'urls' bulunamadı.")
23
+
24
+ results = [
25
+ ExtractResult(
26
+ name = f"{self.name} - {video['label']}",
27
+ url = video["url"],
28
+ referer = referer or self.main_url,
29
+ subtitles = []
30
+ )
31
+ for video in api_data["urls"]
32
+ ]
33
+
34
+ return results[0] if len(results) == 1 else results
@@ -0,0 +1,25 @@
1
+ # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
+
3
+ from KekikStream.Core import ExtractorBase, ExtractResult
4
+ import re
5
+
6
+ class TurboImgz(ExtractorBase):
7
+ name = "TurboImgz"
8
+ main_url = "https://turbo.imgz.me"
9
+
10
+ async def extract(self, url, referer=None) -> ExtractResult:
11
+ if referer:
12
+ self.oturum.headers.update({"Referer": referer})
13
+
14
+ istek = await self.oturum.get(url)
15
+ istek.raise_for_status()
16
+
17
+ if video_match := re.search(r'file: "(.*)",', istek.text):
18
+ return ExtractResult(
19
+ name = self.name,
20
+ url = video_match[1],
21
+ referer = referer or self.main_url,
22
+ subtitles = []
23
+ )
24
+ else:
25
+ raise ValueError("File not found in response.")