KekikStream 2.3.8__tar.gz → 2.3.9__tar.gz

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 (92) hide show
  1. kekikstream-2.3.9/KekikStream/Extractors/MolyStream.py +42 -0
  2. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Plugins/DiziBox.py +15 -25
  3. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream.egg-info/PKG-INFO +1 -1
  4. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream.egg-info/SOURCES.txt +0 -1
  5. {kekikstream-2.3.8 → kekikstream-2.3.9}/PKG-INFO +1 -1
  6. {kekikstream-2.3.8 → kekikstream-2.3.9}/setup.py +1 -1
  7. kekikstream-2.3.8/KekikStream/Extractors/MolyStream.py +0 -83
  8. kekikstream-2.3.8/KekikStream/Plugins/DiziWatch.py +0 -212
  9. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/CLI/__init__.py +0 -0
  10. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/CLI/pypi_kontrol.py +0 -0
  11. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Core/Extractor/ExtractorBase.py +0 -0
  12. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Core/Extractor/ExtractorLoader.py +0 -0
  13. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Core/Extractor/ExtractorManager.py +0 -0
  14. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Core/Extractor/ExtractorModels.py +0 -0
  15. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Core/Extractor/YTDLPCache.py +0 -0
  16. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Core/HTMLHelper.py +0 -0
  17. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Core/Media/MediaHandler.py +0 -0
  18. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Core/Media/MediaManager.py +0 -0
  19. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Core/Plugin/PluginBase.py +0 -0
  20. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Core/Plugin/PluginLoader.py +0 -0
  21. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Core/Plugin/PluginManager.py +0 -0
  22. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Core/Plugin/PluginModels.py +0 -0
  23. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Core/UI/UIManager.py +0 -0
  24. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Core/__init__.py +0 -0
  25. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Extractors/CloseLoad.py +0 -0
  26. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Extractors/ContentX.py +0 -0
  27. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Extractors/DonilasPlay.py +0 -0
  28. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Extractors/DzenRu.py +0 -0
  29. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Extractors/ExPlay.py +0 -0
  30. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Extractors/Filemoon.py +0 -0
  31. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Extractors/HDPlayerSystem.py +0 -0
  32. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Extractors/JFVid.py +0 -0
  33. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Extractors/JetTv.py +0 -0
  34. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Extractors/MailRu.py +0 -0
  35. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Extractors/MixPlayHD.py +0 -0
  36. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Extractors/MixTiger.py +0 -0
  37. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Extractors/Odnoklassniki.py +0 -0
  38. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Extractors/PeaceMakerst.py +0 -0
  39. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Extractors/PixelDrain.py +0 -0
  40. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Extractors/PlayerFilmIzle.py +0 -0
  41. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Extractors/RapidVid.py +0 -0
  42. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Extractors/SetPlay.py +0 -0
  43. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Extractors/SetPrime.py +0 -0
  44. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Extractors/SibNet.py +0 -0
  45. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Extractors/Sobreatsesuyp.py +0 -0
  46. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Extractors/TRsTX.py +0 -0
  47. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Extractors/TauVideo.py +0 -0
  48. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Extractors/TurboImgz.py +0 -0
  49. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Extractors/TurkeyPlayer.py +0 -0
  50. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Extractors/VCTPlay.py +0 -0
  51. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Extractors/VidHide.py +0 -0
  52. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Extractors/VidMoly.py +0 -0
  53. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Extractors/VidMoxy.py +0 -0
  54. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Extractors/VidPapi.py +0 -0
  55. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Extractors/VideoSeyred.py +0 -0
  56. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Extractors/YTDLP.py +0 -0
  57. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Extractors/YildizKisaFilm.py +0 -0
  58. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Plugins/BelgeselX.py +0 -0
  59. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Plugins/DiziPal.py +0 -0
  60. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Plugins/DiziYou.py +0 -0
  61. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Plugins/Dizilla.py +0 -0
  62. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Plugins/FilmBip.py +0 -0
  63. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Plugins/FilmMakinesi.py +0 -0
  64. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Plugins/FilmModu.py +0 -0
  65. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Plugins/FullHDFilm.py +0 -0
  66. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Plugins/FullHDFilmizlesene.py +0 -0
  67. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Plugins/HDFilmCehennemi.py +0 -0
  68. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Plugins/JetFilmizle.py +0 -0
  69. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Plugins/KultFilmler.py +0 -0
  70. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Plugins/RecTV.py +0 -0
  71. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Plugins/RoketDizi.py +0 -0
  72. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Plugins/SelcukFlix.py +0 -0
  73. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Plugins/SetFilmIzle.py +0 -0
  74. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Plugins/SezonlukDizi.py +0 -0
  75. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Plugins/SineWix.py +0 -0
  76. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Plugins/Sinefy.py +0 -0
  77. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Plugins/SinemaCX.py +0 -0
  78. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Plugins/Sinezy.py +0 -0
  79. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Plugins/SuperFilmGeldi.py +0 -0
  80. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Plugins/UgurFilm.py +0 -0
  81. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/Plugins/YabanciDizi.py +0 -0
  82. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/__init__.py +0 -0
  83. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/__main__.py +0 -0
  84. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream/requirements.txt +0 -0
  85. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream.egg-info/dependency_links.txt +0 -0
  86. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream.egg-info/entry_points.txt +0 -0
  87. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream.egg-info/requires.txt +0 -0
  88. {kekikstream-2.3.8 → kekikstream-2.3.9}/KekikStream.egg-info/top_level.txt +0 -0
  89. {kekikstream-2.3.8 → kekikstream-2.3.9}/LICENSE +0 -0
  90. {kekikstream-2.3.8 → kekikstream-2.3.9}/MANIFEST.in +0 -0
  91. {kekikstream-2.3.8 → kekikstream-2.3.9}/README.md +0 -0
  92. {kekikstream-2.3.8 → kekikstream-2.3.9}/setup.cfg +0 -0
@@ -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, Subtitle, HTMLHelper
4
+ import re
5
+
6
+ class MolyStream(ExtractorBase):
7
+ name = "MolyStream"
8
+ main_url = "https://dbx.molystream.org"
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
+
21
+ async def extract(self, url, referer=None) -> ExtractResult:
22
+ if "doctype html" in url:
23
+ secici = HTMLHelper(url)
24
+ video = secici.select_attr("video#sheplayer source", "src")
25
+ else:
26
+ video = url
27
+
28
+ resp_sec = HTMLHelper(url)
29
+ matches = resp_sec.regex_all(r"addSrtFile\(['\"]([^'\"]+\.srt)['\"]\s*,\s*['\"][a-z]{2}['\"]\s*,\s*['\"]([^'\"]+)['\"]")
30
+
31
+ subtitles = [
32
+ Subtitle(name = name, url = self.fix_url(url))
33
+ for url, name in matches
34
+ ]
35
+
36
+ return ExtractResult(
37
+ name = self.name,
38
+ url = video,
39
+ referer = video.replace("/sheila", "") if video else None,
40
+ user_agent = "Mozilla/5.0 (X11; Linux x86_64; rv:101.0) Gecko/20100101 Firefox/101.0",
41
+ subtitles = subtitles
42
+ )
@@ -167,44 +167,34 @@ class DiziBox(PluginBase):
167
167
 
168
168
  crypt_data = iframe_secici.regex_first(r"CryptoJS\.AES\.decrypt\(\"(.*)\",\"", iframe_istek.text)
169
169
  crypt_pass = iframe_secici.regex_first(r"\",\"(.*)\"\);", iframe_istek.text)
170
- if crypt_data and crypt_pass:
171
- decode = CryptoJS.decrypt(crypt_pass, crypt_data)
172
- if video_match := iframe_secici.regex_first(r"file: '(.*)',", decode):
173
- results.append(video_match)
174
- else:
175
- results.append(decode)
170
+ decode = CryptoJS.decrypt(crypt_pass, crypt_data)
171
+
172
+ if video_match := iframe_secici.regex_first(r"file: '(.*)',", decode):
173
+ results.append(video_match)
174
+ else:
175
+ results.append(decode)
176
176
 
177
177
  elif "/player/moly/moly.php" in iframe_link:
178
178
  iframe_link = iframe_link.replace("moly.php?h=", "moly.php?wmode=opaque&h=")
179
- for _ in range(3): # Max 3 attempts
179
+ while True:
180
180
  await asyncio.sleep(.3)
181
181
  with contextlib.suppress(Exception):
182
182
  moly_istek = await self.httpx.get(iframe_link)
183
183
  moly_secici = HTMLHelper(moly_istek.text)
184
184
 
185
- if atob_data := moly_secici.regex_first(r"unescape\(\"(.*)\"\)"):
185
+ if atob_data := moly_secici.regex_first(r"unescape\(\"(.*)\"\)", moly_istek.text):
186
186
  decoded_atob = urllib.parse.unquote(atob_data)
187
187
  str_atob = base64.b64decode(decoded_atob).decode("utf-8")
188
188
 
189
- iframe_src = HTMLHelper(str_atob).select_attr("div#Player iframe", "src")
190
- if iframe_src:
191
- # ! Sheila replacement (Kotlin referansı)
192
- if "/embed/" in iframe_src:
193
- iframe_src = iframe_src.replace("/embed/", "/embed/sheila/").replace("vidmoly.me", "vidmoly.net")
194
-
195
- results.append(iframe_src)
196
- break
197
- elif embed_matches := moly_secici.regex_all(r'iframe.*?src="(.*?)"'):
198
- for src in embed_matches:
199
- if "/embed/" in src:
200
- src = src.replace("/embed/", "/embed/sheila/").replace("vidmoly.me", "vidmoly.net")
201
- results.append(src)
202
- break
189
+ iframe_src = HTMLHelper(str_atob).select_attr("div#Player iframe", "src")
190
+ if iframe_src:
191
+ results.append(iframe_src)
192
+
193
+ break
203
194
 
204
195
  elif "/player/haydi.php" in iframe_link:
205
- with contextlib.suppress(Exception):
206
- okru_url = base64.b64decode(iframe_link.split("?v=")[-1]).decode("utf-8")
207
- results.append(okru_url)
196
+ okru_url = base64.b64decode(iframe_link.split("?v=")[-1]).decode("utf-8")
197
+ results.append(okru_url)
208
198
 
209
199
  return results
210
200
 
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: KekikStream
3
- Version: 2.3.8
3
+ Version: 2.3.9
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
@@ -64,7 +64,6 @@ KekikStream/Extractors/YildizKisaFilm.py
64
64
  KekikStream/Plugins/BelgeselX.py
65
65
  KekikStream/Plugins/DiziBox.py
66
66
  KekikStream/Plugins/DiziPal.py
67
- KekikStream/Plugins/DiziWatch.py
68
67
  KekikStream/Plugins/DiziYou.py
69
68
  KekikStream/Plugins/Dizilla.py
70
69
  KekikStream/Plugins/FilmBip.py
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.4
2
2
  Name: KekikStream
3
- Version: 2.3.8
3
+ Version: 2.3.9
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
@@ -6,7 +6,7 @@ from io import open
6
6
  setup(
7
7
  # ? Genel Bilgiler
8
8
  name = "KekikStream",
9
- version = "2.3.8",
9
+ version = "2.3.9",
10
10
  url = "https://github.com/keyiflerolsun/KekikStream",
11
11
  description = "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ı",
12
12
  keywords = ["KekikStream", "KekikAkademi", "keyiflerolsun"],
@@ -1,83 +0,0 @@
1
- # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
-
3
- from KekikStream.Core import ExtractorBase, ExtractResult, Subtitle, HTMLHelper
4
- import re
5
-
6
- class MolyStream(ExtractorBase):
7
- name = "MolyStream"
8
- main_url = "https://dbx.molystream.org"
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
-
21
- async def extract(self, url, referer=None) -> ExtractResult:
22
- if "doctype html" in url.lower():
23
- text = url
24
- else:
25
- # Sheila-style referer fix
26
- if "/embed/sheila/" in url:
27
- referer = url.replace("/embed/sheila/", "/embed/")
28
-
29
- self.httpx.headers.update({
30
- "User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
31
- "Referer" : referer or self.main_url
32
- })
33
- istek = await self.httpx.get(url, follow_redirects=True)
34
- text = istek.text
35
-
36
- # 1. Sheila-style links often have the m3u8 directly as the first http line or in script
37
- m3u8 = None
38
- if "#EXTM3U" in text:
39
- for line in text.splitlines():
40
- line = line.strip().replace('"', '').replace("'", "")
41
- if line.startswith("http"):
42
- m3u8 = line
43
- break
44
-
45
- if not m3u8:
46
- for line in text.splitlines():
47
- line = line.strip().replace('"', '').replace("'", "")
48
- if line.startswith("http") and ".m3u8" in line:
49
- m3u8 = line
50
- break
51
-
52
- if not m3u8:
53
- secici = HTMLHelper(text)
54
- # 2. Try video tag
55
- m3u8 = secici.select_attr("video#sheplayer source", "src") or secici.select_attr("video source", "src")
56
-
57
- if not m3u8:
58
- # 3. Try regex
59
- m3u8 = HTMLHelper(text).regex_first(r'["\'](https?://[^"\']+\.m3u8[^"\']*)["\']')
60
-
61
- if not m3u8:
62
- # Fallback to any http link in a script if it looks like a video link
63
- m3u8 = HTMLHelper(text).regex_first(r'["\'](https?://[^"\']+/q/\d+)["\']')
64
-
65
- if not m3u8:
66
- m3u8 = url # Final fallback
67
-
68
- # Subtitles (Sheila style addSrtFile)
69
- resp_sec = HTMLHelper(text)
70
- matches = resp_sec.regex_all(r"addSrtFile\(['\"]([^'\"]+\.srt)['\"]\s*,\s*['\"][a-z]{2}['\"]\s*,\s*['\"]([^'\"]+)['\"]")
71
-
72
- subtitles = [
73
- Subtitle(name = name, url = self.fix_url(url))
74
- for url, name in matches
75
- ]
76
-
77
- return ExtractResult(
78
- name = self.name,
79
- url = m3u8,
80
- referer = url,
81
- user_agent = "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/120.0.0.0 Safari/537.36",
82
- subtitles = subtitles
83
- )
@@ -1,212 +0,0 @@
1
- # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
-
3
- from KekikStream.Core import PluginBase, MainPageResult, SearchResult, SeriesInfo, Episode, ExtractResult, HTMLHelper
4
- import urllib.parse
5
-
6
- class DiziWatch(PluginBase):
7
- name = "DiziWatch"
8
- language = "tr"
9
- main_url = "https://diziwatch.to"
10
- favicon = f"https://www.google.com/s2/favicons?domain={main_url}&sz=64"
11
- description = "Diziwatch; en güncel yabancı dizileri ve animeleri, Türkçe altyazılı ve dublaj seçenekleriyle izleyebileceğiniz platform."
12
-
13
- main_page = {
14
- f"{main_url}/episodes" : "Yeni Bölümler",
15
- "9" : "Aksiyon",
16
- "17" : "Animasyon",
17
- "5" : "Bilim Kurgu",
18
- "2" : "Dram",
19
- "12" : "Fantastik",
20
- "3" : "Gizem",
21
- "4" : "Komedi",
22
- "8" : "Korku",
23
- "24" : "Macera",
24
- "14" : "Müzik",
25
- "7" : "Romantik",
26
- "23" : "Spor",
27
- "1" : "Suç",
28
- }
29
-
30
- c_key = ""
31
- c_value = ""
32
-
33
- async def _init_session(self):
34
- # Fetch anime-arsivi to get CSRF tokens
35
- resp = await self.httpx.get(f"{self.main_url}/anime-arsivi")
36
- sel = HTMLHelper(resp.text)
37
-
38
- # form.bg-[rgba(255,255,255,.15)] > input
39
- # We can just look for the first two inputs in that specific form
40
- inputs = sel.select("form.bg-\\[rgba\\(255\\,255\\,255\\,\\.15\\)\\] input")
41
- if len(inputs) >= 2:
42
- self.c_key = inputs[0].attrs.get("value")
43
- self.c_value = inputs[1].attrs.get("value")
44
-
45
- async def get_main_page(self, page: int, url: str, category: str) -> list[MainPageResult]:
46
- await self._init_session()
47
-
48
- if url.startswith("https://"):
49
- full_url = f"{url}?page={page}"
50
- resp = await self.httpx.get(full_url, headers={"Referer": f"{self.main_url}/"})
51
- sel = HTMLHelper(resp.text)
52
- items = sel.select("div.swiper-slide a")
53
- else:
54
- # Category ID based
55
- full_url = f"{self.main_url}/anime-arsivi?category={url}&minImdb=&name=&release_year=&sort=date_desc&page={page}"
56
- resp = await self.httpx.get(full_url, headers={"Referer": f"{self.main_url}/"})
57
- sel = HTMLHelper(resp.text)
58
- items = sel.select("div.content-inner a")
59
-
60
- results = []
61
- for item in items:
62
- title = sel.select_text("h2", item)
63
- href = item.attrs.get("href") if item.tag == "a" else sel.select_attr("a", "href", item)
64
- poster = sel.select_attr("img", "src", item) or sel.select_attr("img", "data-src", item)
65
-
66
- if title and href:
67
- # If it's an episode link, clean it to get show link
68
- # Regex in Kotlin: /sezon-\d+/bolum-\d+/?$
69
- clean_href = HTMLHelper(href).regex_replace(r"/sezon-\d+/bolum-\d+/?$", "")
70
-
71
- # If cleaning changed something, it was an episode link, maybe add it to title
72
- if clean_href != href:
73
- se_info = sel.select_text("div.flex.gap-1.items-center", item)
74
- if se_info:
75
- title = f"{title} - {se_info}"
76
-
77
- results.append(MainPageResult(
78
- category = category,
79
- title = title,
80
- url = self.fix_url(clean_href),
81
- poster = self.fix_url(poster) if poster else None
82
- ))
83
-
84
- return results
85
-
86
- async def search(self, query: str) -> list[SearchResult]:
87
- await self._init_session()
88
-
89
- post_url = f"{self.main_url}/bg/searchcontent"
90
- data = {
91
- "cKey" : self.c_key,
92
- "cValue" : self.c_value,
93
- "searchterm" : query
94
- }
95
-
96
- headers = {
97
- "X-Requested-With" : "XMLHttpRequest",
98
- "Accept" : "application/json, text/javascript, */*; q=0.01",
99
- "Referer" : f"{self.main_url}/"
100
- }
101
-
102
- resp = await self.httpx.post(post_url, data=data, headers=headers)
103
-
104
- try:
105
- raw = resp.json()
106
- # Kotlin maps this to ApiResponse -> DataWrapper -> Icerikler
107
- res_array = raw.get("data", {}).get("result", [])
108
-
109
- results = []
110
- for item in res_array:
111
- title = item.get("object_name", "").replace("\\", "")
112
- slug = item.get("used_slug", "").replace("\\", "")
113
- poster = item.get("object_poster_url", "")
114
-
115
- # Cleanup poster URL as in Kotlin
116
- if poster:
117
- poster = poster.replace("images-macellan-online.cdn.ampproject.org/i/s/", "") \
118
- .replace("file.dizilla.club", "file.macellan.online") \
119
- .replace("images.dizilla.club", "images.macellan.online") \
120
- .replace("images.dizimia4.com", "images.macellan.online") \
121
- .replace("file.dizimia4.com", "file.macellan.online")
122
- poster = HTMLHelper(poster).regex_replace(r"(file\.)[\w\.]+\/?", r"\1macellan.online/")
123
- poster = HTMLHelper(poster).regex_replace(r"(images\.)[\w\.]+\/?", r"\1macellan.online/")
124
- poster = poster.replace("/f/f/", "/630/910/")
125
-
126
- if title and slug:
127
- results.append(SearchResult(
128
- title = title,
129
- url = self.fix_url(slug),
130
- poster = self.fix_url(poster) if poster else None
131
- ))
132
- return results
133
- except Exception:
134
- return []
135
-
136
- async def load_item(self, url: str) -> SeriesInfo:
137
- resp = await self.httpx.get(url)
138
- sel = HTMLHelper(resp.text)
139
-
140
- title = sel.select_text("h2") or sel.select_text("h1")
141
- poster = sel.select_attr("img.rounded-md", "src") or sel.select_attr("meta[property='og:image']", "content")
142
- description = sel.select_text("div.text-sm") or sel.select_text("div.summary")
143
-
144
- year = sel.regex_first(r"Yap\u0131m Y\u0131l\u0131\s*:\s*(\d+)", resp.text)
145
-
146
- tags = []
147
- tags_raw = sel.regex_first(r"T\u00fcr\s*:\s*([^<]+)", resp.text)
148
- if tags_raw:
149
- tags = [t.strip() for t in tags_raw.split(",")]
150
-
151
- rating = sel.select_text(".font-semibold.text-white")
152
- if rating:
153
- rating = rating.replace(",", ".").strip()
154
-
155
- actors = [a.text(strip=True) for a in sel.select("span.valor a")]
156
-
157
- trailer_match = sel.regex_first(r"embed\/(.*)\?rel", resp.text)
158
- trailer = f"https://www.youtube.com/embed/{trailer_match}" if trailer_match else None
159
-
160
- duration_text = sel.select_text("span.runtime")
161
- duration = duration_text.split(" ")[0] if duration_text else None
162
-
163
- episodes = []
164
- # ul a handles episodes
165
- for ep_link in sel.select("ul a"):
166
- href = ep_link.attrs.get("href")
167
- if not href or "/sezon-" not in href:
168
- continue
169
-
170
- ep_name = sel.select_text("span.hidden.sm\\:block", ep_link)
171
-
172
- season_match = sel.regex_first(r"sezon-(\d+)", href)
173
- episode_match = sel.regex_first(r"bolum-(\d+)", href)
174
-
175
- season = season_match if season_match else None
176
- episode_num = episode_match if episode_match else None
177
-
178
- episodes.append(Episode(
179
- season = int(season) if season and season.isdigit() else None,
180
- episode = int(episode_num) if episode_num and episode_num.isdigit() else None,
181
- title = ep_name if ep_name else f"{season}x{episode_num}",
182
- url = self.fix_url(href)
183
- ))
184
-
185
- return SeriesInfo(
186
- title = title,
187
- url = url,
188
- poster = self.fix_url(poster) if poster else None,
189
- description = description,
190
- rating = rating,
191
- tags = tags,
192
- actors = actors,
193
- year = year,
194
- episodes = episodes,
195
- duration = int(duration) if duration and str(duration).isdigit() else None
196
- )
197
-
198
- async def load_links(self, url: str) -> list[ExtractResult]:
199
- resp = await self.httpx.get(url)
200
- sel = HTMLHelper(resp.text)
201
-
202
- iframe = sel.select_attr("iframe", "src")
203
- if not iframe:
204
- return []
205
-
206
- iframe_url = self.fix_url(iframe)
207
- data = await self.extract(iframe_url, referer=f"{self.main_url}/")
208
-
209
- if not data:
210
- return []
211
-
212
- return data if isinstance(data, list) else [data]
File without changes
File without changes
File without changes
File without changes