KekikStream 1.7.2__py3-none-any.whl → 1.7.5__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 (61) hide show
  1. KekikStream/Core/Extractor/ExtractorBase.py +23 -6
  2. KekikStream/Core/Plugin/PluginBase.py +29 -8
  3. KekikStream/Extractors/CloseLoad.py +2 -2
  4. KekikStream/Extractors/ContentX.py +4 -4
  5. KekikStream/Extractors/DzenRu.py +39 -0
  6. KekikStream/Extractors/ExPlay.py +54 -0
  7. KekikStream/Extractors/FirePlayer.py +61 -0
  8. KekikStream/Extractors/HDPlayerSystem.py +42 -0
  9. KekikStream/Extractors/JetTv.py +46 -0
  10. KekikStream/Extractors/MailRu.py +2 -2
  11. KekikStream/Extractors/MixPlayHD.py +2 -2
  12. KekikStream/Extractors/MixTiger.py +61 -0
  13. KekikStream/Extractors/Odnoklassniki.py +2 -2
  14. KekikStream/Extractors/PeaceMakerst.py +4 -4
  15. KekikStream/Extractors/PixelDrain.py +1 -1
  16. KekikStream/Extractors/PlayerFilmIzle.py +62 -0
  17. KekikStream/Extractors/RapidVid.py +2 -2
  18. KekikStream/Extractors/SetPlay.py +58 -0
  19. KekikStream/Extractors/SetPrime.py +46 -0
  20. KekikStream/Extractors/SibNet.py +2 -2
  21. KekikStream/Extractors/Sobreatsesuyp.py +4 -4
  22. KekikStream/Extractors/TRsTX.py +4 -4
  23. KekikStream/Extractors/TauVideo.py +2 -2
  24. KekikStream/Extractors/TurboImgz.py +2 -2
  25. KekikStream/Extractors/TurkeyPlayer.py +34 -0
  26. KekikStream/Extractors/VidHide.py +72 -0
  27. KekikStream/Extractors/VidMoly.py +4 -4
  28. KekikStream/Extractors/VidMoxy.py +2 -2
  29. KekikStream/Extractors/VidPapi.py +90 -0
  30. KekikStream/Extractors/VideoSeyred.py +3 -3
  31. KekikStream/Extractors/YildizKisaFilm.py +42 -0
  32. KekikStream/Plugins/DiziBox.py +15 -15
  33. KekikStream/Plugins/DiziPal.py +11 -11
  34. KekikStream/Plugins/DiziYou.py +4 -4
  35. KekikStream/Plugins/Dizilla.py +10 -6
  36. KekikStream/Plugins/FilmBip.py +145 -0
  37. KekikStream/Plugins/FilmMakinesi.py +3 -3
  38. KekikStream/Plugins/FilmModu.py +6 -6
  39. KekikStream/Plugins/FullHDFilm.py +164 -0
  40. KekikStream/Plugins/FullHDFilmizlesene.py +3 -3
  41. KekikStream/Plugins/HDFilmCehennemi.py +3 -0
  42. KekikStream/Plugins/JetFilmizle.py +16 -9
  43. KekikStream/Plugins/KultFilmler.py +219 -0
  44. KekikStream/Plugins/RecTV.py +6 -6
  45. KekikStream/Plugins/RoketDizi.py +207 -0
  46. KekikStream/Plugins/SelcukFlix.py +216 -0
  47. KekikStream/Plugins/SezonlukDizi.py +11 -8
  48. KekikStream/Plugins/SineWix.py +4 -4
  49. KekikStream/Plugins/Sinefy.py +214 -0
  50. KekikStream/Plugins/SinemaCX.py +9 -9
  51. KekikStream/Plugins/Sinezy.py +99 -0
  52. KekikStream/Plugins/SuperFilmGeldi.py +121 -0
  53. KekikStream/Plugins/UgurFilm.py +6 -6
  54. KekikStream/requirements.txt +2 -2
  55. {kekikstream-1.7.2.dist-info → kekikstream-1.7.5.dist-info}/METADATA +2 -1
  56. kekikstream-1.7.5.dist-info/RECORD +85 -0
  57. kekikstream-1.7.2.dist-info/RECORD +0 -64
  58. {kekikstream-1.7.2.dist-info → kekikstream-1.7.5.dist-info}/WHEEL +0 -0
  59. {kekikstream-1.7.2.dist-info → kekikstream-1.7.5.dist-info}/entry_points.txt +0 -0
  60. {kekikstream-1.7.2.dist-info → kekikstream-1.7.5.dist-info}/licenses/LICENSE +0 -0
  61. {kekikstream-1.7.2.dist-info → kekikstream-1.7.5.dist-info}/top_level.txt +0 -0
@@ -23,7 +23,7 @@ class SezonlukDizi(PluginBase):
23
23
 
24
24
  #@kekik_cache(ttl=60*60)
25
25
  async def get_main_page(self, page: int, url: str, category: str) -> list[MainPageResult]:
26
- istek = await self.cffi.get(f"{url}{page}")
26
+ istek = await self.httpx.get(f"{url}{page}")
27
27
  secici = Selector(istek.text)
28
28
 
29
29
  return [
@@ -38,7 +38,7 @@ class SezonlukDizi(PluginBase):
38
38
 
39
39
  #@kekik_cache(ttl=60*60)
40
40
  async def search(self, query: str) -> list[SearchResult]:
41
- istek = await self.cffi.get(f"{self.main_url}/diziler.asp?adi={query}")
41
+ istek = await self.httpx.get(f"{self.main_url}/diziler.asp?adi={query}")
42
42
  secici = Selector(istek.text)
43
43
 
44
44
  return [
@@ -52,7 +52,7 @@ class SezonlukDizi(PluginBase):
52
52
 
53
53
  #@kekik_cache(ttl=60*60)
54
54
  async def load_item(self, url: str) -> SeriesInfo:
55
- istek = await self.cffi.get(url)
55
+ istek = await self.httpx.get(url)
56
56
  secici = Selector(istek.text)
57
57
 
58
58
  title = secici.css("div.header::text").get().strip()
@@ -63,14 +63,14 @@ class SezonlukDizi(PluginBase):
63
63
  rating = secici.css("div.dizipuani a div::text").re_first(r"[\d.,]+")
64
64
  actors = []
65
65
 
66
- actors_istek = await self.cffi.get(f"{self.main_url}/oyuncular/{url.split('/')[-1]}")
66
+ actors_istek = await self.httpx.get(f"{self.main_url}/oyuncular/{url.split('/')[-1]}")
67
67
  actors_secici = Selector(actors_istek.text)
68
68
  actors = [
69
69
  actor.css("div.header::text").get().strip()
70
70
  for actor in actors_secici.css("div.doubling div.ui")
71
71
  ]
72
72
 
73
- episodes_istek = await self.cffi.get(f"{self.main_url}/bolumler/{url.split('/')[-1]}")
73
+ episodes_istek = await self.httpx.get(f"{self.main_url}/bolumler/{url.split('/')[-1]}")
74
74
  episodes_secici = Selector(episodes_istek.text)
75
75
  episodes = []
76
76
 
@@ -104,7 +104,7 @@ class SezonlukDizi(PluginBase):
104
104
 
105
105
  #@kekik_cache(ttl=15*60)
106
106
  async def load_links(self, url: str) -> list[dict]:
107
- istek = await self.cffi.get(url)
107
+ istek = await self.httpx.get(url)
108
108
  secici = Selector(istek.text)
109
109
 
110
110
  bid = secici.css("div#dilsec::attr(data-id)").get()
@@ -113,7 +113,7 @@ class SezonlukDizi(PluginBase):
113
113
 
114
114
  results = []
115
115
  for dil, label in [("1", "Altyazı"), ("0", "Dublaj")]:
116
- dil_istek = await self.cffi.post(
116
+ dil_istek = await self.httpx.post(
117
117
  url = f"{self.main_url}/ajax/dataAlternatif22.asp",
118
118
  headers = {"X-Requested-With": "XMLHttpRequest"},
119
119
  data = {"bid": bid, "dil": dil},
@@ -126,7 +126,7 @@ class SezonlukDizi(PluginBase):
126
126
 
127
127
  if dil_json.get("status") == "success":
128
128
  for idx, veri in enumerate(dil_json.get("data", [])):
129
- veri_response = await self.cffi.post(
129
+ veri_response = await self.httpx.post(
130
130
  url = f"{self.main_url}/ajax/dataEmbed22.asp",
131
131
  headers = {"X-Requested-With": "XMLHttpRequest"},
132
132
  data = {"id": veri.get("id")},
@@ -134,6 +134,9 @@ class SezonlukDizi(PluginBase):
134
134
  secici = Selector(veri_response.text)
135
135
 
136
136
  if iframe := secici.css("iframe::attr(src)").get():
137
+ if "link.asp" in iframe:
138
+ continue
139
+
137
140
  extractor = self.ex_manager.find_extractor(self.fix_url(iframe))
138
141
  results.append({
139
142
  "url" : self.fix_url(iframe),
@@ -37,7 +37,7 @@ class SineWix(PluginBase):
37
37
 
38
38
  #@kekik_cache(ttl=60*60)
39
39
  async def get_main_page(self, page: int, url: str, category: str) -> list[MainPageResult]:
40
- istek = await self.cffi.get(f"{url}/{page}")
40
+ istek = await self.httpx.get(f"{url}/{page}")
41
41
  veriler = istek.json()
42
42
 
43
43
  return [
@@ -52,7 +52,7 @@ class SineWix(PluginBase):
52
52
 
53
53
  #@kekik_cache(ttl=60*60)
54
54
  async def search(self, query: str) -> list[SearchResult]:
55
- istek = await self.cffi.get(f"{self.main_url}/sinewix/search/{query}")
55
+ istek = await self.httpx.get(f"{self.main_url}/sinewix/search/{query}")
56
56
 
57
57
  return [
58
58
  SearchResult(
@@ -68,7 +68,7 @@ class SineWix(PluginBase):
68
68
  item_type = url.split("?type=")[-1].split("&id=")[0]
69
69
  item_id = url.split("&id=")[-1]
70
70
 
71
- istek = await self.cffi.get(f"{self.main_url}/sinewix/{item_type}/{item_id}")
71
+ istek = await self.httpx.get(f"{self.main_url}/sinewix/{item_type}/{item_id}")
72
72
  veri = istek.json()
73
73
 
74
74
  match item_type:
@@ -143,7 +143,7 @@ class SineWix(PluginBase):
143
143
  if not url.startswith(self.main_url) and not url.startswith("{"):
144
144
  return [{"url": url, "name": "Video"}]
145
145
 
146
- istek = await self.cffi.get(url)
146
+ istek = await self.httpx.get(url)
147
147
  veri = istek.json()
148
148
 
149
149
  org_title = veri.get("title")
@@ -0,0 +1,214 @@
1
+ # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
+
3
+ from KekikStream.Core import PluginBase, MainPageResult, SearchResult, SeriesInfo, Episode, MovieInfo
4
+ from parsel import Selector
5
+ import re, json, urllib.parse
6
+
7
+ class Sinefy(PluginBase):
8
+ name = "Sinefy"
9
+ main_url = "https://sinefy3.com"
10
+ lang = "tr"
11
+
12
+ main_page = {
13
+ "page/" : "Son Eklenenler",
14
+ "en-yenifilmler" : "Yeni Filmler",
15
+ "netflix-filmleri-izle" : "Netflix Filmleri",
16
+ "dizi-izle/netflix" : "Netflix Dizileri"
17
+ }
18
+
19
+ async def get_main_page(self, page: int, url: str, category: str) -> list[MainPageResult]:
20
+ if "page/" in url:
21
+ full_url = f"{self.main_url}/{url}{page}"
22
+ elif "en-yenifilmler" in url or "netflix" in url:
23
+ full_url = f"{self.main_url}/{url}/{page}"
24
+ else:
25
+ full_url = f"{self.main_url}/{url}&page={page}"
26
+
27
+ resp = await self.httpx.get(full_url)
28
+ sel = Selector(resp.text)
29
+
30
+ results = []
31
+ # Kotlin: div.poster-with-subject, div.dark-segment div.poster-md.poster
32
+ for item in sel.css("div.poster-with-subject, div.dark-segment div.poster-md.poster"):
33
+ title = item.css("h2::text").get()
34
+ href = item.css("a::attr(href)").get()
35
+ poster= item.css("img::attr(data-srcset)").get()
36
+ if poster:
37
+ poster = poster.split(",")[0].split(" ")[0]
38
+
39
+ if title and href:
40
+ results.append(MainPageResult(
41
+ category=category,
42
+ title=title,
43
+ url=self.fix_url(href),
44
+ poster=self.fix_url(poster)
45
+ ))
46
+ return results
47
+
48
+ async def search(self, query: str) -> list[SearchResult]:
49
+ # Try to get dynamic keys from main page first
50
+ c_key = "ca1d4a53d0f4761a949b85e51e18f096"
51
+ c_value = "MTc0NzI2OTAwMDU3ZTEwYmZjMDViNWFmOWIwZDViODg0MjU4MjA1ZmYxOThmZTYwMDdjMWQzMzliNzY5NzFlZmViMzRhMGVmNjgwODU3MGIyZA=="
52
+
53
+ try:
54
+ resp = await self.httpx.get(self.main_url)
55
+ sel = Selector(resp.text)
56
+ cke = sel.css("input[name='cKey']::attr(value)").get()
57
+ cval = sel.css("input[name='cValue']::attr(value)").get()
58
+ if cke and cval:
59
+ c_key = cke
60
+ c_value = cval
61
+ except Exception:
62
+ pass
63
+
64
+ post_url = f"{self.main_url}/bg/searchcontent"
65
+ data = {
66
+ "cKey": c_key,
67
+ "cValue": c_value,
68
+ "searchTerm": query
69
+ }
70
+
71
+ headers = {
72
+ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64; rv:134.0) Gecko/20100101 Firefox/134.0",
73
+ "Accept": "application/json, text/javascript, */*; q=0.01",
74
+ "X-Requested-With": "XMLHttpRequest",
75
+ "Content-Type": "application/x-www-form-urlencoded; charset=UTF-8"
76
+ }
77
+
78
+ response = await self.httpx.post(post_url, data=data, headers=headers)
79
+
80
+ try:
81
+ # Extract JSON data from response (might contain garbage chars at start)
82
+ raw = response.text
83
+ json_start = raw.find('{')
84
+ if json_start != -1:
85
+ clean_json = raw[json_start:]
86
+ data = json.loads(clean_json)
87
+
88
+ results = []
89
+ # Result array is in data['data']['result']
90
+ res_array = data.get("data", {}).get("result", [])
91
+
92
+ if not res_array:
93
+ # Fallback manual parsing ?
94
+ pass
95
+
96
+ for item in res_array:
97
+ name = item.get("object_name")
98
+ slug = item.get("used_slug")
99
+ poster = item.get("object_poster_url")
100
+
101
+ if name and slug:
102
+ if "cdn.ampproject.org" in poster:
103
+ poster = "https://images.macellan.online/images/movie/poster/180/275/80/" + poster.split("/")[-1]
104
+
105
+ results.append(SearchResult(
106
+ title=name,
107
+ url=self.fix_url(slug),
108
+ poster=self.fix_url(poster)
109
+ ))
110
+ return results
111
+
112
+ except Exception:
113
+ pass
114
+ return []
115
+
116
+ async def load_item(self, url: str) -> SeriesInfo:
117
+ resp = await self.httpx.get(url)
118
+ sel = Selector(resp.text)
119
+
120
+ title = sel.css("h1::text").get()
121
+ poster_info = sel.css("div.ui.items img::attr(data-srcset)").get()
122
+ poster = None
123
+ if poster_info:
124
+ # take 1x
125
+ parts = str(poster_info).split(",")
126
+ for p in parts:
127
+ if "1x" in p:
128
+ poster = p.strip().split(" ")[0]
129
+ break
130
+
131
+ description = sel.css("p#tv-series-desc::text").get()
132
+ tags = sel.css("div.item.categories a::text").getall()
133
+ rating = sel.css("span.color-imdb::text").get()
134
+ actors = sel.css("div.content h5::text").getall()
135
+
136
+ episodes = []
137
+ season_elements = sel.css("section.episodes-box")
138
+
139
+ if season_elements:
140
+ # Get season links
141
+ season_links = []
142
+ menu = sel.css("div.ui.vertical.fluid.tabular.menu a")
143
+ for link in menu:
144
+ href = link.css("::attr(href)").get()
145
+ if href:
146
+ season_links.append(self.fix_url(href))
147
+
148
+ for s_url in season_links:
149
+ target_url = s_url if "/bolum-" in s_url else f"{s_url}/bolum-1"
150
+
151
+ try:
152
+ s_resp = await self.httpx.get(target_url)
153
+ s_sel = Selector(s_resp.text)
154
+ ep_links = s_sel.css("div.ui.list.celled a.item")
155
+
156
+ current_season_no = 1
157
+ match = re.search(r"sezon-(\d+)", target_url)
158
+ if match:
159
+ current_season_no = int(match.group(1))
160
+
161
+ for ep_link in ep_links:
162
+ href = ep_link.css("::attr(href)").get()
163
+ name = ep_link.css("div.content div.header::text").get()
164
+
165
+ if href:
166
+ ep_no = 0
167
+ match_ep = re.search(r"bolum-(\d+)", href)
168
+ if match_ep:
169
+ ep_no = int(match_ep.group(1))
170
+
171
+ episodes.append(Episode(
172
+ season = current_season_no,
173
+ episode = ep_no,
174
+ title = name.strip() if name else "",
175
+ url = self.fix_url(href)
176
+ ))
177
+ except Exception:
178
+ pass
179
+
180
+ if episodes:
181
+ return SeriesInfo(
182
+ title=title,
183
+ url=url,
184
+ poster=self.fix_url(poster),
185
+ description=description,
186
+ rating=rating,
187
+ tags=tags,
188
+ actors=actors,
189
+ episodes=episodes
190
+ )
191
+ else:
192
+ return MovieInfo(
193
+ title=title,
194
+ url=url,
195
+ poster=self.fix_url(poster),
196
+ description=description,
197
+ rating=rating,
198
+ tags=tags,
199
+ actors=actors
200
+ )
201
+
202
+ async def load_links(self, url: str) -> list[dict]:
203
+ resp = await self.httpx.get(url)
204
+ sel = Selector(resp.text)
205
+
206
+ iframe = sel.css("iframe::attr(src)").get()
207
+ if iframe:
208
+ iframe = self.fix_url(iframe)
209
+ extractor = self.ex_manager.find_extractor(iframe)
210
+ return [{
211
+ "url": iframe,
212
+ "name": extractor.name if extractor else "Iframe"
213
+ }]
214
+ return []
@@ -29,7 +29,7 @@ class SinemaCX(PluginBase):
29
29
  }
30
30
 
31
31
  async def get_main_page(self, page: int, url: str, category: str) -> list[MainPageResult]:
32
- istek = await self.cffi.get(url.replace("SAYFA", str(page)))
32
+ istek = await self.httpx.get(url.replace("SAYFA", str(page)))
33
33
  secici = Selector(istek.text)
34
34
 
35
35
  return [
@@ -44,7 +44,7 @@ class SinemaCX(PluginBase):
44
44
  ]
45
45
 
46
46
  async def search(self, query: str) -> list[SearchResult]:
47
- istek = await self.cffi.get(f"{self.main_url}/?s={query}")
47
+ istek = await self.httpx.get(f"{self.main_url}/?s={query}")
48
48
  secici = Selector(istek.text)
49
49
 
50
50
  return [
@@ -58,7 +58,7 @@ class SinemaCX(PluginBase):
58
58
  ]
59
59
 
60
60
  async def load_item(self, url: str) -> MovieInfo:
61
- istek = await self.cffi.get(url)
61
+ istek = await self.httpx.get(url)
62
62
  secici = Selector(istek.text)
63
63
 
64
64
  duration_match = re.search(r"Süre:.*?(\d+)\s*Dakika", istek.text)
@@ -76,7 +76,7 @@ class SinemaCX(PluginBase):
76
76
  )
77
77
 
78
78
  async def load_links(self, url: str) -> list[dict]:
79
- istek = await self.cffi.get(url)
79
+ istek = await self.httpx.get(url)
80
80
  secici = Selector(istek.text)
81
81
 
82
82
  iframe_list = [iframe.css("::attr(data-vsrc)").get() for iframe in secici.css("iframe")]
@@ -90,7 +90,7 @@ class SinemaCX(PluginBase):
90
90
 
91
91
  if has_only_trailer:
92
92
  alt_url = url.rstrip("/") + "/2/"
93
- alt_istek = await self.cffi.get(alt_url)
93
+ alt_istek = await self.httpx.get(alt_url)
94
94
  alt_sec = Selector(alt_istek.text)
95
95
  iframe_list = [iframe.css("::attr(data-vsrc)").get() for iframe in alt_sec.css("iframe")]
96
96
  iframe_list = [i for i in iframe_list if i]
@@ -105,8 +105,8 @@ class SinemaCX(PluginBase):
105
105
  results = []
106
106
 
107
107
  # Altyazı kontrolü
108
- self.cffi.headers.update({"Referer": f"{self.main_url}/"})
109
- iframe_istek = await self.cffi.get(iframe)
108
+ self.httpx.headers.update({"Referer": f"{self.main_url}/"})
109
+ iframe_istek = await self.httpx.get(iframe)
110
110
  iframe_text = iframe_istek.text
111
111
 
112
112
  subtitles = []
@@ -123,8 +123,8 @@ class SinemaCX(PluginBase):
123
123
  base_url = base_match[1]
124
124
  vid_id = iframe.split("/")[-1]
125
125
 
126
- self.cffi.headers.update({"X-Requested-With": "XMLHttpRequest"})
127
- vid_istek = await self.cffi.post(
126
+ self.httpx.headers.update({"X-Requested-With": "XMLHttpRequest"})
127
+ vid_istek = await self.httpx.post(
128
128
  f"https://{base_url}/player/index.php?data={vid_id}&do=getVideo",
129
129
  )
130
130
  vid_data = vid_istek.json()
@@ -0,0 +1,99 @@
1
+ # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
+
3
+ from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo
4
+ from parsel import Selector
5
+ import re, base64
6
+
7
+ class Sinezy(PluginBase):
8
+ name = "Sinezy"
9
+ main_url = "https://sinezy.site"
10
+ lang = "tr"
11
+
12
+ main_page = {
13
+ "izle/en-yeni-filmler/" : "Yeni Filmler",
14
+ "izle/en-yi-filmler/" : "En İyi Filmler"
15
+ }
16
+
17
+ async def get_main_page(self, page: int, url: str, category: str) -> list[MainPageResult]:
18
+ full_url = f"{self.main_url}/{url}page/{page}/"
19
+ resp = await self.httpx.get(full_url)
20
+ sel = Selector(resp.text)
21
+
22
+ results = []
23
+ for item in sel.css("div.container div.content div.movie_box.move_k"):
24
+ title = item.css("a::attr(title)").get()
25
+ href = item.css("a::attr(href)").get()
26
+ poster= item.css("img::attr(data-src)").get()
27
+
28
+ if title and href:
29
+ results.append(MainPageResult(
30
+ category=category,
31
+ title=title,
32
+ url=self.fix_url(href),
33
+ poster=self.fix_url(poster)
34
+ ))
35
+ return results
36
+
37
+ async def search(self, query: str) -> list[SearchResult]:
38
+ url = f"{self.main_url}/arama/?s={query}"
39
+ resp = await self.httpx.get(url)
40
+ sel = Selector(resp.text)
41
+
42
+ results = []
43
+ for item in sel.css("div.movie_box.move_k"):
44
+ title = item.css("a::attr(title)").get()
45
+ href = item.css("a::attr(href)").get()
46
+ poster= item.css("img::attr(data-src)").get()
47
+
48
+ if title and href:
49
+ results.append(SearchResult(
50
+ title=title,
51
+ url=self.fix_url(href),
52
+ poster=self.fix_url(poster)
53
+ ))
54
+ return results
55
+
56
+ async def load_item(self, url: str) -> MovieInfo:
57
+ resp = await self.httpx.get(url)
58
+ sel = Selector(resp.text)
59
+
60
+ title = sel.css("div.detail::attr(title)").get()
61
+ poster = sel.css("div.move_k img::attr(data-src)").get()
62
+ description = sel.css("div.desc.yeniscroll p::text").get()
63
+ rating = sel.css("span.info span.imdb::text").get()
64
+
65
+ tags = sel.css("div.detail span a::text").getall()
66
+ actors = sel.css("span.oyn p::text").getall() # Might need splitting logic
67
+
68
+ return MovieInfo(
69
+ title=title,
70
+ url=url,
71
+ poster=self.fix_url(poster),
72
+ description=description,
73
+ tags=tags,
74
+ rating=rating,
75
+ actors=actors
76
+ )
77
+
78
+ async def load_links(self, url: str) -> list[dict]:
79
+ resp = await self.httpx.get(url)
80
+
81
+ match = re.search(r"ilkpartkod\s*=\s*'([^']+)'", resp.text, re.IGNORECASE)
82
+ if match:
83
+ encoded = match.group(1)
84
+ try:
85
+ decoded = base64.b64decode(encoded).decode('utf-8')
86
+ iframe_match = re.search(r'src="([^"]*)"', decoded)
87
+ if iframe_match:
88
+ iframe = iframe_match.group(1)
89
+ iframe = self.fix_url(iframe)
90
+
91
+ extractor = self.ex_manager.find_extractor(iframe)
92
+ return [{
93
+ "url": iframe,
94
+ "name": extractor.name if extractor else "Iframe"
95
+ }]
96
+ except Exception:
97
+ pass
98
+
99
+ return []
@@ -0,0 +1,121 @@
1
+ # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
+
3
+ from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo, ExtractResult, Subtitle
4
+ from parsel import Selector
5
+ import re
6
+
7
+ class SuperFilmGeldi(PluginBase):
8
+ name = "SuperFilmGeldi"
9
+ language = "tr"
10
+ main_url = "https://www.superfilmgeldi13.art"
11
+ favicon = f"https://www.google.com/s2/favicons?domain={main_url}&sz=64"
12
+ description = "Ücretsiz film izleme sitesi."
13
+
14
+ main_page = {
15
+ f"{main_url}/page/SAYFA" : "Son Eklenenler",
16
+ f"{main_url}/hdizle/category/aksiyon/page/SAYFA" : "Aksiyon",
17
+ f"{main_url}/hdizle/category/animasyon/page/SAYFA" : "Animasyon",
18
+ f"{main_url}/hdizle/category/belgesel/page/SAYFA" : "Belgesel",
19
+ f"{main_url}/hdizle/category/bilim-kurgu/page/SAYFA" : "Bilim Kurgu",
20
+ f"{main_url}/hdizle/category/fantastik/page/SAYFA" : "Fantastik",
21
+ f"{main_url}/hdizle/category/komedi-filmleri/page/SAYFA" : "Komedi Filmleri",
22
+ f"{main_url}/hdizle/category/macera/page/SAYFA" : "Macera",
23
+ f"{main_url}/hdizle/category/gerilim/page/SAYFA" : "Gerilim",
24
+ f"{main_url}/hdizle/category/suc/page/SAYFA" : "Suç",
25
+ f"{main_url}/hdizle/category/karete-filmleri/page/SAYFA" : "Karate Filmleri",
26
+ }
27
+
28
+ async def get_main_page(self, page: int, url: str, category: str) -> list[MainPageResult]:
29
+ istek = await self.httpx.get(url.replace("SAYFA", str(page)))
30
+ secici = Selector(istek.text)
31
+
32
+ return [
33
+ MainPageResult(
34
+ category = category,
35
+ title = self.clean_title(veri.css("span.movie-title a::text").get().split(" izle")[0]),
36
+ url = self.fix_url(veri.css("span.movie-title a::attr(href)").get()),
37
+ poster = self.fix_url(veri.css("img::attr(src)").get()),
38
+ )
39
+ for veri in secici.css("div.movie-preview-content")
40
+ if veri.css("span.movie-title a::text").get()
41
+ ]
42
+
43
+ async def search(self, query: str) -> list[SearchResult]:
44
+ istek = await self.httpx.get(f"{self.main_url}?s={query}")
45
+ secici = Selector(istek.text)
46
+
47
+ return [
48
+ SearchResult(
49
+ title = self.clean_title(veri.css("span.movie-title a::text").get().split(" izle")[0]),
50
+ url = self.fix_url(veri.css("span.movie-title a::attr(href)").get()),
51
+ poster = self.fix_url(veri.css("img::attr(src)").get()),
52
+ )
53
+ for veri in secici.css("div.movie-preview-content")
54
+ if veri.css("span.movie-title a::text").get()
55
+ ]
56
+
57
+ async def load_item(self, url: str) -> MovieInfo:
58
+ istek = await self.httpx.get(url)
59
+ secici = Selector(istek.text)
60
+
61
+ title = secici.css("div.title h1::text").get()
62
+ title = self.clean_title(title.split(" izle")[0]) if title else ""
63
+ poster = self.fix_url(secici.css("div.poster img::attr(src)").get())
64
+ year = secici.css("div.release a::text").re_first(r"(\d{4})")
65
+ description = secici.css("div.excerpt p::text").get()
66
+ tags = secici.css("div.categories a::text").getall()
67
+ actors = secici.css("div.actor a::text").getall()
68
+
69
+ return MovieInfo(
70
+ url = url,
71
+ poster = poster,
72
+ title = title,
73
+ description = description,
74
+ tags = tags,
75
+ year = year,
76
+ actors = actors,
77
+ )
78
+
79
+ async def load_links(self, url: str) -> list[dict]:
80
+ istek = await self.httpx.get(url)
81
+ secici = Selector(istek.text)
82
+
83
+ iframe = self.fix_url(secici.css("div#vast iframe::attr(src)").get())
84
+ if not iframe:
85
+ return []
86
+
87
+ results = []
88
+
89
+ # Mix player özel işleme
90
+ if "mix" in iframe and "index.php?data=" in iframe:
91
+ iframe_istek = await self.httpx.get(iframe, headers={"Referer": f"{self.main_url}/"})
92
+ mix_point = re.search(r'videoUrl":"(.*)","videoServer', iframe_istek.text)
93
+
94
+ if mix_point:
95
+ mix_point = mix_point[1].replace("\\", "")
96
+
97
+ # Endpoint belirleme
98
+ if "mixlion" in iframe:
99
+ end_point = "?s=3&d="
100
+ elif "mixeagle" in iframe:
101
+ end_point = "?s=1&d="
102
+ else:
103
+ end_point = "?s=0&d="
104
+
105
+ m3u_link = iframe.split("/player")[0] + mix_point + end_point
106
+
107
+ results.append({
108
+ "name" : f"{self.name} | Mix Player",
109
+ "url" : m3u_link,
110
+ "referer" : iframe,
111
+ "subtitles" : []
112
+ })
113
+ else:
114
+ extractor = self.ex_manager.find_extractor(iframe)
115
+ results.append({
116
+ "name" : extractor.name if extractor else "Player",
117
+ "url" : iframe,
118
+ "referer" : f"{self.main_url}/"
119
+ })
120
+
121
+ return results
@@ -25,7 +25,7 @@ class UgurFilm(PluginBase):
25
25
 
26
26
  #@kekik_cache(ttl=60*60)
27
27
  async def get_main_page(self, page: int, url: str, category: str) -> list[MainPageResult]:
28
- istek = await self.cffi.get(f"{url}{page}", allow_redirects=True)
28
+ istek = await self.httpx.get(f"{url}{page}", allow_redirects=True)
29
29
  secici = Selector(istek.text)
30
30
 
31
31
  return [
@@ -40,7 +40,7 @@ class UgurFilm(PluginBase):
40
40
 
41
41
  #@kekik_cache(ttl=60*60)
42
42
  async def search(self, query: str) -> list[SearchResult]:
43
- istek = await self.cffi.get(f"{self.main_url}/?s={query}")
43
+ istek = await self.httpx.get(f"{self.main_url}/?s={query}")
44
44
  secici = Selector(istek.text)
45
45
 
46
46
  results = []
@@ -62,7 +62,7 @@ class UgurFilm(PluginBase):
62
62
 
63
63
  #@kekik_cache(ttl=60*60)
64
64
  async def load_item(self, url: str) -> MovieInfo:
65
- istek = await self.cffi.get(url)
65
+ istek = await self.httpx.get(url)
66
66
  secici = Selector(istek.text)
67
67
 
68
68
  title = secici.css("div.bilgi h2::text").get().strip()
@@ -84,12 +84,12 @@ class UgurFilm(PluginBase):
84
84
 
85
85
  #@kekik_cache(ttl=15*60)
86
86
  async def load_links(self, url: str) -> list[dict]:
87
- istek = await self.cffi.get(url)
87
+ istek = await self.httpx.get(url)
88
88
  secici = Selector(istek.text)
89
89
  results = []
90
90
 
91
91
  for idx, part_link in enumerate(secici.css("li.parttab a::attr(href)").getall()):
92
- sub_response = await self.cffi.get(part_link)
92
+ sub_response = await self.httpx.get(part_link)
93
93
  sub_selector = Selector(sub_response.text)
94
94
 
95
95
  iframe = sub_selector.css("div#vast iframe::attr(src)").get()
@@ -99,7 +99,7 @@ class UgurFilm(PluginBase):
99
99
  "alternative" : "vidmoly",
100
100
  "ord" : "0",
101
101
  }
102
- player_response = await self.cffi.post(
102
+ player_response = await self.httpx.post(
103
103
  url = f"{self.main_url}/player/ajax_sources.php",
104
104
  data = post_data
105
105
  )
@@ -4,7 +4,7 @@ wheel
4
4
  Kekik
5
5
  curl-cffi
6
6
  cloudscraper
7
+ httpx
7
8
  parsel
8
-
9
9
  pydantic
10
- InquirerPy
10
+ InquirerPy