KekikStream 2.3.9__py3-none-any.whl → 2.5.4__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.

Potentially problematic release.


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

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 +35 -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.4.dist-info}/METADATA +1 -1
  79. kekikstream-2.5.4.dist-info/RECORD +99 -0
  80. {kekikstream-2.3.9.dist-info → kekikstream-2.5.4.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.4.dist-info}/entry_points.txt +0 -0
  84. {kekikstream-2.3.9.dist-info → kekikstream-2.5.4.dist-info}/licenses/LICENSE +0 -0
  85. {kekikstream-2.3.9.dist-info → kekikstream-2.5.4.dist-info}/top_level.txt +0 -0
@@ -2,6 +2,7 @@
2
2
 
3
3
  from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo, Episode, SeriesInfo, ExtractResult, HTMLHelper
4
4
  from json import dumps, loads
5
+ import re, contextlib
5
6
 
6
7
  class RecTV(PluginBase):
7
8
  name = "RecTV"
@@ -64,82 +65,60 @@ class RecTV(PluginBase):
64
65
  for veri in tum_veri
65
66
  ]
66
67
 
67
- async def load_item(self, url: str) -> MovieInfo:
68
+ async def load_item(self, url: str) -> MovieInfo | SeriesInfo:
68
69
  self.httpx.headers.update({"user-agent": "okhttp/4.12.0"})
69
70
  veri = loads(url)
70
71
 
71
- match veri.get("type"):
72
- case "serie":
73
- dizi_istek = await self.httpx.get(f"{self.main_url}/api/season/by/serie/{veri.get('id')}/{self.sw_key}/")
74
- dizi_veri = dizi_istek.json()
75
-
76
- episodes = []
77
- for season in dizi_veri:
78
- for episode in season.get("episodes"):
79
- # Bölüm için gerekli bilgileri JSON olarak sakla
80
- ep_data = {
81
- "url" : self.fix_url(episode.get("sources")[0].get("url")),
82
- "title" : f"{veri.get('title')} | {season.get('title', '1. Sezon')} {episode.get('title', '1. Bölüm')}",
83
- "is_episode" : True
84
- }
85
-
86
- # Extract season/episode numbers using helper
87
- s1, _ = HTMLHelper.extract_season_episode(season.get("title") or "")
88
- _, e2 = HTMLHelper.extract_season_episode(episode.get("title") or "")
89
-
90
- ep_model = Episode(
91
- season = s1 or 1,
92
- episode = e2 or 1,
93
- title = episode.get("title"),
94
- url = dumps(ep_data),
95
- )
96
-
97
- episodes.append(ep_model)
98
-
99
- # Süreyi dakikaya çevir (Örn: "1h 59min")
100
- duration_raw = veri.get("duration")
101
- duration = None
102
- if duration_raw:
103
- try:
104
- h = int(HTMLHelper(duration_raw).regex_first(r"(\d+)h") or 0)
105
- m = int(HTMLHelper(duration_raw).regex_first(r"(\d+)min") or 0)
106
- duration = h * 60 + m
107
- except: pass
108
-
109
- return SeriesInfo(
110
- url = url,
111
- poster = self.fix_url(veri.get("image")),
112
- title = veri.get("title"),
113
- description = veri.get("description"),
114
- tags = [genre.get("title") for genre in veri.get("genres")] if veri.get("genres") else [],
115
- rating = str(veri.get("imdb") or veri.get("rating") or ""),
116
- year = str(veri.get("year") or ""),
117
- actors = [],
118
- duration = duration,
119
- episodes = episodes
120
- )
121
- case _:
122
- # Süreyi dakikaya çevir
123
- duration_raw = veri.get("duration")
124
- duration = None
125
- if duration_raw:
126
- try:
127
- h = int(HTMLHelper(duration_raw).regex_first(r"(\d+)h") or 0)
128
- m = int(HTMLHelper(duration_raw).regex_first(r"(\d+)min") or 0)
129
- duration = h * 60 + m
130
- except: pass
131
-
132
- return MovieInfo(
133
- url = url,
134
- poster = self.fix_url(veri.get("image")),
135
- title = veri.get("title"),
136
- description = veri.get("description"),
137
- tags = [genre.get("title") for genre in veri.get("genres")] if veri.get("genres") else [],
138
- rating = str(veri.get("imdb") or veri.get("rating") or ""),
139
- year = str(veri.get("year") or ""),
140
- actors = [],
141
- duration = duration
142
- )
72
+ # Süreyi dakikaya çevir (Örn: "1h 59min")
73
+ duration_raw = veri.get("duration")
74
+ duration = None
75
+ if duration_raw:
76
+ with contextlib.suppress(Exception):
77
+ h = int(HTMLHelper(duration_raw).regex_first(r"(\d+)h") or 0)
78
+ m = int(HTMLHelper(duration_raw).regex_first(r"(\d+)min") or 0)
79
+ duration = h * 60 + m
80
+
81
+ common_info = {
82
+ "url" : url,
83
+ "poster" : self.fix_url(veri.get("image")),
84
+ "title" : veri.get("title"),
85
+ "description" : veri.get("description"),
86
+ "tags" : [genre.get("title") for genre in veri.get("genres")] if veri.get("genres") else [],
87
+ "rating" : str(veri.get("imdb") or veri.get("rating") or ""),
88
+ "year" : str(veri.get("year") or ""),
89
+ "duration" : duration
90
+ }
91
+
92
+ if veri.get("type") == "serie":
93
+ dizi_istek = await self.httpx.get(f"{self.main_url}/api/season/by/serie/{veri.get('id')}/{self.sw_key}/")
94
+ dizi_veri = dizi_istek.json()
95
+
96
+ episodes = []
97
+ for season in dizi_veri:
98
+ s_title = season.get("title", "").strip()
99
+ s, _ = HTMLHelper.extract_season_episode(s_title)
100
+ for ep in season.get("episodes"):
101
+ e_title = ep.get("title", "").strip()
102
+ _, e = HTMLHelper.extract_season_episode(e_title)
103
+ for source in ep.get("sources"):
104
+ tag = ""
105
+ clean_s = s_title
106
+ if "dublaj" in s_title.lower():
107
+ tag = " (Dublaj)"; clean_s = re.sub(r"\s*dublaj\s*", "", s_title, flags=re.I).strip()
108
+ elif "altyaz" in s_title.lower():
109
+ tag = " (Altyazı)"; clean_s = re.sub(r"\s*altyaz[ıi]\s*", "", s_title, flags=re.I).strip()
110
+
111
+ ep_data = {"url": self.fix_url(source.get("url")), "title": f"{veri.get('title')} | {s_title} {e_title} - {source.get('title')}", "is_episode": True}
112
+ episodes.append(Episode(
113
+ season = s or 1,
114
+ episode = e or 1,
115
+ title = f"{clean_s} {e_title}{tag} - {source.get('title')}",
116
+ url = dumps(ep_data)
117
+ ))
118
+
119
+ return SeriesInfo(**common_info, episodes=episodes, actors=[])
120
+
121
+ return MovieInfo(**common_info, actors=[])
143
122
 
144
123
  async def load_links(self, url: str) -> list[ExtractResult]:
145
124
  try:
@@ -1,6 +1,6 @@
1
1
  # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
2
 
3
- from KekikStream.Core import PluginBase, MainPageResult, SearchResult, SeriesInfo, Episode, ExtractResult, MovieInfo, HTMLHelper
3
+ from KekikStream.Core import PluginBase, MainPageResult, SearchResult, SeriesInfo, Episode, ExtractResult, MovieInfo, HTMLHelper
4
4
  import base64, json
5
5
 
6
6
  class RoketDizi(PluginBase):
@@ -26,8 +26,6 @@ class RoketDizi(PluginBase):
26
26
  secici = HTMLHelper(istek.text)
27
27
 
28
28
  results = []
29
-
30
- # Use div.new-added-list to find the container, then get items
31
29
  for item in secici.select("div.new-added-list > span"):
32
30
  title = secici.select_text("span.line-clamp-1", item)
33
31
  href = secici.select_attr("a", "href", item)
@@ -38,7 +36,7 @@ class RoketDizi(PluginBase):
38
36
  category = category,
39
37
  title = self.clean_title(title),
40
38
  url = self.fix_url(href),
41
- poster = self.fix_url(poster) if poster else None
39
+ poster = self.fix_url(poster)
42
40
  ))
43
41
 
44
42
  return results
@@ -52,7 +50,7 @@ class RoketDizi(PluginBase):
52
50
  "Referer" : f"{self.main_url}/",
53
51
  }
54
52
  )
55
-
53
+
56
54
  try:
57
55
  veri = istek.json()
58
56
  encoded = veri.get("response", "")
@@ -76,7 +74,7 @@ class RoketDizi(PluginBase):
76
74
  results.append(SearchResult(
77
75
  title = self.clean_title(title.strip()),
78
76
  url = self.fix_url(f"{self.main_url}/{slug}"),
79
- poster = self.fix_url(poster) if poster else None
77
+ poster = self.fix_url(poster)
80
78
  ))
81
79
 
82
80
  return results
@@ -87,39 +85,33 @@ class RoketDizi(PluginBase):
87
85
  async def load_item(self, url: str) -> MovieInfo | SeriesInfo:
88
86
  resp = await self.httpx.get(url)
89
87
  sel = HTMLHelper(resp.text)
90
-
88
+
91
89
  next_data_text = sel.select_text("script#__NEXT_DATA__")
92
90
  if not next_data_text:
93
91
  return SeriesInfo(url=url, title=sel.select_text("h1") or "Bilinmeyen")
94
92
 
95
93
  try:
96
- next_data = json.loads(next_data_text)
94
+ next_data = json.loads(next_data_text)
97
95
  secure_data_raw = next_data["props"]["pageProps"]["secureData"]
98
- secure_data = json.loads(base64.b64decode(secure_data_raw).decode('utf-8'))
99
-
96
+ secure_data = json.loads(base64.b64decode(secure_data_raw).decode('utf-8'))
97
+
100
98
  content_item = secure_data.get("contentItem", {})
101
99
  content = secure_data.get("content", {}).get("result", {})
102
-
100
+
103
101
  title = content_item.get("original_title") or content_item.get("culture_title")
104
102
  poster = content_item.get("poster_url") or content_item.get("face_url")
105
103
  description = content_item.get("description")
106
104
  rating = str(content_item.get("imdb_point") or "")
107
105
  year = str(content_item.get("release_year") or "")
108
106
  tags = content_item.get("categories", "").split(",")
109
-
110
- # Actors extraction from getSerieCastsById or getMovieCastsById
107
+
111
108
  actors = []
112
109
  casts_data = content.get("getSerieCastsById") or content.get("getMovieCastsById")
113
110
  if casts_data and casts_data.get("result"):
114
111
  actors = [cast.get("name") for cast in casts_data["result"] if cast.get("name")]
115
112
 
116
- # Episodes extraction
117
113
  episodes = []
118
114
  if "Series" in str(content.get("FindedType")):
119
- # Check for episodes in SecureData -> RelatedResults -> getEpisodeSources (this might be for the current episode)
120
- # Usually full episode list isn't in secureData, but we can get it from HTML or another API
121
- # However, many times Next.js pages have them in props
122
- # Let's fallback to the previous regex method for episodes if not in JSON
123
115
  all_urls = HTMLHelper(resp.text).regex_all(r'"url":"([^"]*)"')
124
116
  episodes_dict = {}
125
117
  for u in all_urls:
@@ -138,7 +130,7 @@ class RoketDizi(PluginBase):
138
130
 
139
131
  return SeriesInfo(
140
132
  url = url,
141
- poster = self.fix_url(poster) if poster else None,
133
+ poster = self.fix_url(poster),
142
134
  title = self.clean_title(title),
143
135
  description = description,
144
136
  tags = tags,
@@ -150,7 +142,7 @@ class RoketDizi(PluginBase):
150
142
  else:
151
143
  return MovieInfo(
152
144
  url = url,
153
- poster = self.fix_url(poster) if poster else None,
145
+ poster = self.fix_url(poster),
154
146
  title = self.clean_title(title),
155
147
  description = description,
156
148
  tags = tags,
@@ -169,17 +161,16 @@ class RoketDizi(PluginBase):
169
161
  async def load_links(self, url: str) -> list[ExtractResult]:
170
162
  resp = await self.httpx.get(url)
171
163
  sel = HTMLHelper(resp.text)
172
-
164
+
173
165
  next_data = sel.select_text("script#__NEXT_DATA__")
174
166
  if not next_data:
175
167
  return []
176
168
 
177
169
  try:
178
- data = json.loads(next_data)
179
- secure_data = data["props"]["pageProps"]["secureData"]
170
+ data = json.loads(next_data)
171
+ secure_data = data["props"]["pageProps"]["secureData"]
180
172
  decoded_json = json.loads(base64.b64decode(secure_data).decode('utf-8'))
181
173
 
182
- # secureData içindeki RelatedResults -> getEpisodeSources -> result dizisini al
183
174
  sources = decoded_json.get("RelatedResults", {}).get("getEpisodeSources", {}).get("result", [])
184
175
 
185
176
  seen_urls = set()
@@ -191,7 +182,7 @@ class RoketDizi(PluginBase):
191
182
  iframe_url = HTMLHelper(source_content).regex_first(r'<iframe[^>]*src=["\']([^"\']*)["\']')
192
183
  if not iframe_url:
193
184
  continue
194
-
185
+
195
186
  # Fix URL protocol
196
187
  if not iframe_url.startswith("http"):
197
188
  if iframe_url.startswith("//"):
@@ -200,8 +191,8 @@ class RoketDizi(PluginBase):
200
191
  iframe_url = "https://" + iframe_url
201
192
 
202
193
  iframe_url = self.fix_url(iframe_url)
203
-
204
- # Deduplicate
194
+
195
+ # Deduplicate
205
196
  if iframe_url in seen_urls:
206
197
  continue
207
198
  seen_urls.add(iframe_url)
@@ -52,7 +52,7 @@ class SelcukFlix(PluginBase):
52
52
  category = category,
53
53
  title = title,
54
54
  url = final_url,
55
- poster = self.fix_url(poster) if poster else None
55
+ poster = self.fix_url(poster)
56
56
  ))
57
57
  except Exception:
58
58
  pass
@@ -187,54 +187,55 @@ class SelcukFlix(PluginBase):
187
187
 
188
188
  next_data_text = sel.select_text("script#__NEXT_DATA__")
189
189
  if not next_data_text:
190
- return SeriesInfo(url=url, title=sel.select_text("h1") or "Bilinmeyen")
190
+ return SeriesInfo(url=url, title=self.clean_title(sel.select_text("h1")) or "Bilinmeyen")
191
191
 
192
192
  try:
193
193
  next_data = json.loads(next_data_text)
194
194
  secure_data_raw = next_data["props"]["pageProps"].get("secureData")
195
195
  if not secure_data_raw:
196
- return SeriesInfo(url=url, title=sel.select_text("h1") or "Bilinmeyen")
196
+ return SeriesInfo(url=url, title=self.clean_title(sel.select_text("h1")) or "Bilinmeyen")
197
197
 
198
198
  # Clean possible quotes from string before decoding
199
199
  if isinstance(secure_data_raw, str):
200
200
  secure_data_raw = secure_data_raw.strip('"')
201
201
 
202
- decoded_str = base64.b64decode(secure_data_raw).decode('utf-8')
203
- content_details = json.loads(decoded_str)
204
-
205
- # Sometimes content_details might be a string (double encoded)
206
- if isinstance(content_details, str):
207
- content_details = json.loads(content_details)
202
+ content_details = json.loads(base64.b64decode(secure_data_raw).decode('utf-8'))
203
+ if isinstance(content_details, str): content_details = json.loads(content_details)
208
204
 
209
- print(f"DEBUG: type(content_details)={type(content_details)}")
210
205
  item = content_details.get("contentItem", {})
211
- print(f"DEBUG: type(item)={type(item)}")
212
206
  related_results = content_details.get("RelatedResults", {})
213
207
 
214
- title = item.get("original_title") or item.get("culture_title") or item.get("originalTitle") or ""
215
- poster = self.clean_image_url(item.get("poster_url") or item.get("posterUrl") or item.get("face_url"))
216
- description = item.get("description") or item.get("used_description")
217
- rating = str(item.get("imdb_point") or item.get("imdbPoint") or "")
218
- year = str(item.get("release_year") or item.get("releaseYear") or "")
219
- duration = item.get("total_minutes") or item.get("totalMinutes")
208
+ title = self.clean_title(item.get("original_title") or item.get("culture_title") or item.get("originalTitle") or "")
209
+ poster = self.clean_image_url(item.get("poster_url") or item.get("posterUrl") or item.get("face_url"))
210
+ description = item.get("description") or item.get("used_description")
211
+ rating = str(item.get("imdb_point") or item.get("imdbPoint") or "")
212
+ year = str(item.get("release_year") or item.get("releaseYear") or "")
213
+ duration = item.get("total_minutes") or item.get("totalMinutes")
220
214
 
221
215
  tags = []
222
216
  tags_raw = item.get("category_names") or item.get("categoryNames") or item.get("categories")
223
217
  if isinstance(tags_raw, str):
224
- tags = [t.strip() for t in tags_raw.split(",")]
218
+ tags = [t.strip() for t in tags_raw.split(",") if t.strip()]
225
219
  elif isinstance(tags_raw, list):
226
220
  tags = [c.get("title") if isinstance(c, dict) else str(c) for c in tags_raw]
227
221
 
228
222
  actors = []
229
- actors_raw = item.get("actor_names") or item.get("actorNames")
230
- if isinstance(actors_raw, str):
231
- actors = [a.strip() for a in actors_raw.split(",")]
232
-
233
- # Casts from RelatedResults
234
223
  casts_data = related_results.get("getSerieCastsById") or related_results.get("getMovieCastsById")
235
224
  if casts_data and isinstance(casts_data, dict) and casts_data.get("result"):
236
225
  actors = [cast.get("name") for cast in casts_data["result"] if cast.get("name")]
237
226
 
227
+ common_info = {
228
+ "url" : url,
229
+ "poster" : poster,
230
+ "title" : title,
231
+ "description" : description,
232
+ "tags" : tags,
233
+ "rating" : rating,
234
+ "year" : year,
235
+ "actors" : actors,
236
+ "duration" : duration
237
+ }
238
+
238
239
  series_data = related_results.get("getSerieSeasonAndEpisodes")
239
240
  if series_data and isinstance(series_data, dict) and series_data.get("result"):
240
241
  episodes = []
@@ -249,31 +250,12 @@ class SelcukFlix(PluginBase):
249
250
  title = ep.get("ep_text") or ep.get("epText") or "",
250
251
  url = self.fix_url(ep_slug)
251
252
  ))
252
-
253
- return SeriesInfo(
254
- url = url,
255
- poster = poster,
256
- title = self.clean_title(title),
257
- description = description,
258
- tags = tags,
259
- rating = rating,
260
- year = year,
261
- actors = actors,
262
- duration = duration,
263
- episodes = episodes
264
- )
265
- else:
266
- return MovieInfo(
267
- url = url,
268
- poster = poster,
269
- title = self.clean_title(title),
270
- description = description,
271
- tags = tags,
272
- rating = rating,
273
- year = year,
274
- actors = actors,
275
- duration = duration
276
- )
253
+ return SeriesInfo(**common_info, episodes=episodes)
254
+
255
+ return MovieInfo(**common_info)
256
+
257
+ except Exception:
258
+ return SeriesInfo(url=url, title=self.clean_title(sel.select_text("h1")) or "Bilinmeyen")
277
259
 
278
260
  except Exception:
279
261
  return SeriesInfo(url=url, title=self.clean_title(sel.select_text("h1")) or "Bilinmeyen")