KekikStream 2.3.9__py3-none-any.whl → 2.5.3__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.
Files changed (85) hide show
  1. KekikStream/Core/Extractor/ExtractorBase.py +3 -2
  2. KekikStream/Core/Extractor/ExtractorLoader.py +8 -14
  3. KekikStream/Core/HTMLHelper.py +120 -49
  4. KekikStream/Core/Plugin/PluginBase.py +30 -12
  5. KekikStream/Core/Plugin/PluginLoader.py +12 -14
  6. KekikStream/Core/Plugin/PluginManager.py +2 -2
  7. KekikStream/Core/Plugin/PluginModels.py +0 -3
  8. KekikStream/Extractors/Abstream.py +27 -0
  9. KekikStream/Extractors/CloseLoad.py +30 -54
  10. KekikStream/Extractors/ContentX.py +27 -72
  11. KekikStream/Extractors/DonilasPlay.py +33 -77
  12. KekikStream/Extractors/DzenRu.py +10 -24
  13. KekikStream/Extractors/ExPlay.py +20 -38
  14. KekikStream/Extractors/Filemoon.py +21 -46
  15. KekikStream/Extractors/HDMomPlayer.py +30 -0
  16. KekikStream/Extractors/HDPlayerSystem.py +13 -31
  17. KekikStream/Extractors/HotStream.py +27 -0
  18. KekikStream/Extractors/JFVid.py +3 -24
  19. KekikStream/Extractors/JetTv.py +21 -34
  20. KekikStream/Extractors/JetV.py +55 -0
  21. KekikStream/Extractors/MailRu.py +11 -29
  22. KekikStream/Extractors/MixPlayHD.py +15 -28
  23. KekikStream/Extractors/MixTiger.py +17 -40
  24. KekikStream/Extractors/MolyStream.py +17 -21
  25. KekikStream/Extractors/Odnoklassniki.py +40 -104
  26. KekikStream/Extractors/PeaceMakerst.py +18 -45
  27. KekikStream/Extractors/PixelDrain.py +8 -16
  28. KekikStream/Extractors/PlayerFilmIzle.py +22 -41
  29. KekikStream/Extractors/RapidVid.py +21 -35
  30. KekikStream/Extractors/SetPlay.py +18 -43
  31. KekikStream/Extractors/SibNet.py +7 -17
  32. KekikStream/Extractors/Sobreatsesuyp.py +23 -45
  33. KekikStream/Extractors/TRsTX.py +23 -53
  34. KekikStream/Extractors/TurboImgz.py +7 -14
  35. KekikStream/Extractors/VCTPlay.py +10 -28
  36. KekikStream/Extractors/Veev.py +145 -0
  37. KekikStream/Extractors/VidBiz.py +62 -0
  38. KekikStream/Extractors/VidHide.py +58 -30
  39. KekikStream/Extractors/VidMoly.py +65 -99
  40. KekikStream/Extractors/VidMoxy.py +16 -27
  41. KekikStream/Extractors/VidPapi.py +24 -54
  42. KekikStream/Extractors/VideoSeyred.py +19 -40
  43. KekikStream/Extractors/Videostr.py +58 -0
  44. KekikStream/Extractors/Vidoza.py +18 -0
  45. KekikStream/Extractors/Vtbe.py +38 -0
  46. KekikStream/Extractors/YTDLP.py +2 -2
  47. KekikStream/Extractors/YildizKisaFilm.py +13 -31
  48. KekikStream/Extractors/Zeus.py +61 -0
  49. KekikStream/Plugins/BelgeselX.py +97 -77
  50. KekikStream/Plugins/DiziBox.py +28 -45
  51. KekikStream/Plugins/DiziMom.py +179 -0
  52. KekikStream/Plugins/DiziPal.py +95 -161
  53. KekikStream/Plugins/DiziYou.py +51 -147
  54. KekikStream/Plugins/Dizilla.py +40 -61
  55. KekikStream/Plugins/FilmBip.py +90 -39
  56. KekikStream/Plugins/FilmEkseni.py +199 -0
  57. KekikStream/Plugins/FilmMakinesi.py +72 -73
  58. KekikStream/Plugins/FilmModu.py +25 -35
  59. KekikStream/Plugins/Filmatek.py +184 -0
  60. KekikStream/Plugins/FilmciBaba.py +155 -0
  61. KekikStream/Plugins/FullHDFilmizlesene.py +16 -37
  62. KekikStream/Plugins/HDFilm.py +243 -0
  63. KekikStream/Plugins/HDFilmCehennemi.py +242 -189
  64. KekikStream/Plugins/JetFilmizle.py +101 -69
  65. KekikStream/Plugins/KultFilmler.py +138 -104
  66. KekikStream/Plugins/RecTV.py +52 -73
  67. KekikStream/Plugins/RoketDizi.py +18 -27
  68. KekikStream/Plugins/SelcukFlix.py +30 -48
  69. KekikStream/Plugins/SetFilmIzle.py +76 -104
  70. KekikStream/Plugins/SezonlukDizi.py +90 -94
  71. KekikStream/Plugins/Sinefy.py +195 -167
  72. KekikStream/Plugins/SinemaCX.py +148 -78
  73. KekikStream/Plugins/Sinezy.py +29 -31
  74. KekikStream/Plugins/SuperFilmGeldi.py +12 -17
  75. KekikStream/Plugins/UgurFilm.py +85 -38
  76. KekikStream/Plugins/Watch32.py +160 -0
  77. KekikStream/Plugins/YabanciDizi.py +176 -211
  78. {kekikstream-2.3.9.dist-info → kekikstream-2.5.3.dist-info}/METADATA +1 -1
  79. kekikstream-2.5.3.dist-info/RECORD +99 -0
  80. {kekikstream-2.3.9.dist-info → kekikstream-2.5.3.dist-info}/WHEEL +1 -1
  81. KekikStream/Plugins/FullHDFilm.py +0 -249
  82. kekikstream-2.3.9.dist-info/RECORD +0 -84
  83. {kekikstream-2.3.9.dist-info → kekikstream-2.5.3.dist-info}/entry_points.txt +0 -0
  84. {kekikstream-2.3.9.dist-info → kekikstream-2.5.3.dist-info}/licenses/LICENSE +0 -0
  85. {kekikstream-2.3.9.dist-info → kekikstream-2.5.3.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,179 @@
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
+
5
+ class DiziMom(PluginBase):
6
+ name = "DiziMom"
7
+ language = "tr"
8
+ main_url = "https://www.dizimom.one"
9
+ favicon = f"https://www.google.com/s2/favicons?domain={main_url}&sz=64"
10
+ description = "Binlerce yerli yabancı dizi arşivi, tüm sezonlar, kesintisiz bölümler. Sadece dizi izle, Dizimom heryerde seninle!"
11
+
12
+ main_page = {
13
+ f"{main_url}/tum-bolumler/page" : "Son Bölümler",
14
+ f"{main_url}/yerli-dizi-izle/page" : "Yerli Diziler",
15
+ f"{main_url}/yabanci-dizi-izle/page" : "Yabancı Diziler",
16
+ f"{main_url}/tv-programlari-izle/page" : "TV Programları",
17
+ f"{main_url}/netflix-dizileri-izle/page" : "Netflix Dizileri",
18
+ f"{main_url}/turkce-dublaj-diziler-hd/page" : "Dublajlı Diziler",
19
+ f"{main_url}/yerli-dizi-izle/page" : "Yerli Diziler",
20
+ f"{main_url}/anime-izle/page" : "Animeler",
21
+ f"{main_url}/yabanci-dizi-izle/page" : "Yabancı Diziler",
22
+ f"{main_url}/kore-dizileri-izle-hd/page" : "Kore Dizileri",
23
+ f"{main_url}/full-hd-hint-dizileri-izle/page" : "Hint Dizileri",
24
+ f"{main_url}/pakistan-dizileri-izle/page" : "Pakistan Dizileri",
25
+ f"{main_url}/tv-programlari-izle/page" : "Tv Programları",
26
+ }
27
+
28
+ async def get_main_page(self, page: int, url: str, category: str) -> list[MainPageResult]:
29
+ istek = await self.httpx.get(f"{url}/{page}/")
30
+ secici = HTMLHelper(istek.text)
31
+
32
+ results = []
33
+ # Eğer "tum-bolumler" ise Episode kutularını, değilse Dizi kutularını tara
34
+ if "/tum-bolumler/" in url:
35
+ for item in secici.select("div.episode-box"):
36
+ title = secici.select_text("div.episode-name a", item)
37
+ href = secici.select_attr("div.episode-name a", "href", item)
38
+ img = secici.select_poster("div.cat-img img", item)
39
+ if title and href:
40
+ results.append(MainPageResult(
41
+ category = category,
42
+ title = title.split(" izle")[0],
43
+ url = self.fix_url(href),
44
+ poster = self.fix_url(img)
45
+ ))
46
+ else:
47
+ for item in secici.select("div.single-item"):
48
+ title = secici.select_text("div.categorytitle a", item)
49
+ href = secici.select_attr("div.categorytitle a", "href", item)
50
+ img = secici.select_poster("div.cat-img img", item)
51
+ if title and href:
52
+ results.append(MainPageResult(
53
+ category = category,
54
+ title = title.split(" izle")[0],
55
+ url = self.fix_url(href),
56
+ poster = self.fix_url(img)
57
+ ))
58
+
59
+ return results
60
+
61
+ async def search(self, query: str) -> list[SearchResult]:
62
+ istek = await self.httpx.get(f"{self.main_url}/?s={query}")
63
+ secici = HTMLHelper(istek.text)
64
+ items = secici.select("div.single-item")
65
+
66
+ return [
67
+ SearchResult(
68
+ title = secici.select_text("div.categorytitle a", item).split(" izle")[0],
69
+ url = self.fix_url(secici.select_attr("div.categorytitle a", "href", item)),
70
+ poster = self.fix_url(secici.select_attr("div.cat-img img", "src", item))
71
+ )
72
+ for item in items
73
+ ]
74
+
75
+ async def load_item(self, url: str) -> SeriesInfo:
76
+ istek = await self.httpx.get(url)
77
+ secici = HTMLHelper(istek.text)
78
+
79
+ title = self.clean_title(secici.select_text("div.title h1"))
80
+ poster = secici.select_poster("div.category_image img")
81
+ description = secici.select_direct_text("div.category_desc")
82
+ tags = secici.select_texts("div.genres a")
83
+ rating = secici.regex_first(r"(?s)IMDB\s*:\s*(?:</span>)?\s*([\d\.]+)", secici.html)
84
+ year = secici.extract_year("div.category_text")
85
+ actors = secici.meta_list("Oyuncular", container_selector="div#icerikcat2")
86
+
87
+ episodes = []
88
+ for item in secici.select("div.bolumust"):
89
+ name = secici.select_text("div.baslik", item)
90
+ href = secici.select_attr("a", "href", item)
91
+ if name and href:
92
+ s, e = secici.extract_season_episode(name)
93
+ episodes.append(Episode(
94
+ season = s or 1,
95
+ episode = e or 1,
96
+ title = self.clean_title(name.replace(title, "").strip()),
97
+ url = self.fix_url(href)
98
+ ))
99
+
100
+ return SeriesInfo(
101
+ url = url,
102
+ poster = self.fix_url(poster),
103
+ title = title,
104
+ description = description,
105
+ tags = tags,
106
+ rating = rating,
107
+ year = year,
108
+ actors = actors,
109
+ episodes = episodes
110
+ )
111
+
112
+ async def load_links(self, url: str) -> list[ExtractResult]:
113
+ await self.httpx.post(
114
+ url = f"{self.main_url}/wp-login.php",
115
+ headers = {
116
+ "User-Agent" : "Mozilla/5.0 (Linux; Android 10; K) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/137.0.0.0 Safari/537.36",
117
+ "sec-ch-ua" : 'Not/A)Brand";v="8", "Chromium";v="137", "Google Chrome";v="137"',
118
+ "sec-ch-ua-mobile" : "?1",
119
+ "sec-ch-ua-platform" : "Android"
120
+ },
121
+ data = {
122
+ "log" : "keyiflerolsun",
123
+ "pwd" : "12345",
124
+ "rememberme" : "forever",
125
+ "redirect_to" : self.main_url
126
+ }
127
+ )
128
+
129
+ istek = await self.httpx.get(url)
130
+ secici = HTMLHelper(istek.text)
131
+
132
+ iframe_data = []
133
+
134
+ # Aktif kaynağın (main iframe) adını bul
135
+ current_name = secici.select_text("div.sources span.current_dil") or ""
136
+ main_iframe = secici.select_attr("iframe[src]", "src")
137
+
138
+ # Bazen iframe doğrudan video p içinde olabilir
139
+ if not main_iframe:
140
+ main_iframe = secici.select_attr("div.video p iframe", "src")
141
+
142
+ if main_iframe:
143
+ iframe_data.append((main_iframe, current_name))
144
+
145
+ # Diğer kaynakları (Partlar) gez
146
+ sources = secici.select("div.sources a.post-page-numbers")
147
+ for source in sources:
148
+ href = secici.select_attr(None, "href", source)
149
+ name = secici.select_text("span.dil", source)
150
+ if href:
151
+ # Part sayfasına git
152
+ sub_istek = await self.httpx.get(href)
153
+ sub_helper = HTMLHelper(sub_istek.text)
154
+ sub_iframe = sub_helper.select_attr("div.video p iframe", "src") or sub_helper.select_attr("iframe[src]", "src")
155
+
156
+ if sub_iframe:
157
+ iframe_data.append((sub_iframe, name or f"{len(iframe_data)+1}.Kısım"))
158
+
159
+ results = []
160
+ for iframe_url, source_name in iframe_data:
161
+ # URL düzeltme
162
+ iframe_url = self.fix_url(iframe_url)
163
+
164
+ # Prefix olarak kaynak adını kullan (1.Kısım | HDMomPlayer)
165
+ extract_result = await self.extract(iframe_url, prefix=source_name)
166
+
167
+ if extract_result:
168
+ if isinstance(extract_result, list):
169
+ results.extend(extract_result)
170
+ else:
171
+ results.append(extract_result)
172
+ else:
173
+ results.append(ExtractResult(
174
+ url = iframe_url,
175
+ name = f"{source_name} | External",
176
+ referer = self.main_url
177
+ ))
178
+
179
+ return results
@@ -1,223 +1,157 @@
1
1
  # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
2
 
3
- from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo, SeriesInfo, Episode, Subtitle, ExtractResult, HTMLHelper
3
+ from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo, SeriesInfo, Episode, Subtitle, ExtractResult, HTMLHelper
4
4
 
5
5
  class DiziPal(PluginBase):
6
6
  name = "DiziPal"
7
7
  language = "tr"
8
- main_url = "https://dizipal1225.com"
8
+ main_url = "https://dizipal.uk"
9
9
  favicon = f"https://www.google.com/s2/favicons?domain={main_url}&sz=64"
10
10
  description = "dizipal güncel, dizipal yeni ve gerçek adresi. dizipal en yeni dizi ve filmleri güvenli ve hızlı şekilde sunar."
11
11
 
12
12
  main_page = {
13
- f"{main_url}/diziler/son-bolumler" : "Son Bölümler",
14
- f"{main_url}/diziler" : "Yeni Diziler",
15
- f"{main_url}/filmler" : "Yeni Filmler",
16
- f"{main_url}/koleksiyon/netflix" : "Netflix",
17
- f"{main_url}/koleksiyon/exxen" : "Exxen",
18
- f"{main_url}/koleksiyon/blutv" : "BluTV",
19
- f"{main_url}/koleksiyon/disney" : "Disney+",
20
- f"{main_url}/koleksiyon/amazon-prime" : "Amazon Prime",
21
- f"{main_url}/koleksiyon/tod-bein" : "TOD (beIN)",
22
- f"{main_url}/koleksiyon/gain" : "Gain",
23
- f"{main_url}/tur/mubi" : "Mubi",
13
+ f"{main_url}/kategori/aile/page/" : "Aile",
14
+ f"{main_url}/kategori/aksiyon/page/" : "Aksiyon",
15
+ f"{main_url}/kategori/animasyon/page/" : "Animasyon",
16
+ f"{main_url}/kategori/belgesel/page/" : "Belgesel",
17
+ f"{main_url}/kategori/bilim-kurgu/page/" : "Bilim Kurgu",
18
+ f"{main_url}/kategori/dram/page/" : "Dram",
19
+ f"{main_url}/kategori/fantastik/page/" : "Fantastik",
20
+ f"{main_url}/kategori/gerilim/page/" : "Gerilim",
21
+ f"{main_url}/kategori/gizem/page/" : "Gizem",
22
+ f"{main_url}/kategori/komedi/page/" : "Komedi",
23
+ f"{main_url}/kategori/korku/page/" : "Korku",
24
+ f"{main_url}/kategori/macera/page/" : "Macera",
25
+ f"{main_url}/kategori/muzik/page/" : "Müzik",
26
+ f"{main_url}/kategori/romantik/page/" : "Romantik",
27
+ f"{main_url}/kategori/savas/page/" : "Savaş",
28
+ f"{main_url}/kategori/suc/page/" : "Suç",
29
+ f"{main_url}/kategori/tarih/page/" : "Tarih",
30
+ f"{main_url}/kategori/vahsi-bati/page/" : "Vahşi Batı",
31
+ f"{main_url}/kategori/yerli/page/" : "Yerli",
24
32
  }
25
33
 
26
34
  async def get_main_page(self, page: int, url: str, category: str) -> list[MainPageResult]:
27
- istek = await self.httpx.get(url)
35
+ istek = await self.httpx.get(f"{url}{page}/")
28
36
  secici = HTMLHelper(istek.text)
29
37
 
30
38
  results = []
31
-
32
- if "/son-bolumler" in url:
33
- for veri in secici.select("div.episode-item"):
34
- name = secici.select_text("div.name", veri)
35
- episode = secici.select_text("div.episode", veri)
36
- href = secici.select_attr("a", "href", veri)
37
- poster = secici.select_attr("img", "src", veri)
38
-
39
- if name and href:
40
- ep_text = episode.replace(". Sezon ", "x").replace(". Bölüm", "") if episode else ""
41
- title = f"{name} {ep_text}"
42
- # Son bölümler linkini dizi sayfasına çevir
43
- dizi_url = href.split("/sezon")[0] if "/sezon" in href else href
44
-
45
- results.append(MainPageResult(
46
- category = category,
47
- title = title,
48
- url = self.fix_url(dizi_url),
49
- poster = self.fix_url(poster) if poster else None,
50
- ))
51
- else:
52
- for veri in secici.select("article.type2 ul li"):
53
- title = secici.select_text("span.title", veri)
54
- href = secici.select_attr("a", "href", veri)
55
- poster = secici.select_attr("img", "src", veri)
56
-
57
- if title and href:
58
- results.append(MainPageResult(
59
- category = category,
60
- title = title,
61
- url = self.fix_url(href),
62
- poster = self.fix_url(poster) if poster else None,
63
- ))
39
+ for veri in secici.select("div.grid div.post-item"):
40
+ title = secici.select_attr("a", "title", veri)
41
+ href = secici.select_attr("a", "href", veri)
42
+ poster = secici.select_poster("div.poster img", veri)
43
+
44
+ if title and href:
45
+ results.append(MainPageResult(
46
+ category = category,
47
+ title = title,
48
+ url = self.fix_url(href),
49
+ poster = self.fix_url(poster),
50
+ ))
64
51
 
65
52
  return results
66
53
 
67
54
  async def search(self, query: str) -> list[SearchResult]:
68
- self.httpx.headers.update({
69
- "Accept" : "application/json, text/javascript, */*; q=0.01",
70
- "X-Requested-With" : "XMLHttpRequest"
71
- })
72
-
73
- istek = await self.httpx.post(
74
- url = f"{self.main_url}/api/search-autocomplete",
75
- data = {"query": query}
76
- )
77
-
78
- try:
79
- data = istek.json()
80
- except Exception:
81
- return []
55
+ istek = await self.httpx.get(f"{self.main_url}/?s={query}")
56
+ secici = HTMLHelper(istek.text)
82
57
 
83
58
  results = []
59
+ for veri in secici.select("div.grid div.post-item"):
60
+ title = secici.select_attr("a", "title", veri)
61
+ href = secici.select_attr("a", "href", veri)
62
+ poster = secici.select_poster("div.poster img", veri)
84
63
 
85
- # API bazen dict, bazen list döner
86
- items = data.values() if isinstance(data, dict) else data
87
-
88
- for item in items:
89
- if not isinstance(item, dict):
90
- continue
91
-
92
- title = item.get("title")
93
- url = item.get("url")
94
- poster = item.get("poster")
95
-
96
- if title and url:
64
+ if title and href:
97
65
  results.append(SearchResult(
98
66
  title = title,
99
- url = f"{self.main_url}{url}",
100
- poster = self.fix_url(poster) if poster else None,
67
+ url = self.fix_url(href),
68
+ poster = self.fix_url(poster),
101
69
  ))
102
70
 
103
71
  return results
104
72
 
105
- def _find_sibling_text(self, secici: HTMLHelper, label_text: str) -> str | None:
106
- """Bir label'ın kardeş div'inden text çıkarır (xpath yerine)"""
107
- for div in secici.select("div"):
108
- if secici.select_text(element=div) == label_text:
109
- # Sonraki kardeş elementi bul
110
- next_sibling = div.next
111
- while next_sibling:
112
- if hasattr(next_sibling, 'text') and next_sibling.text(strip=True):
113
- return next_sibling.text(strip=True)
114
- next_sibling = next_sibling.next if hasattr(next_sibling, 'next') else None
115
- return None
116
-
117
73
  async def load_item(self, url: str) -> MovieInfo | SeriesInfo:
118
- # Reset headers to get HTML response
119
- self.httpx.headers.update({
120
- "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
121
- })
122
- self.httpx.headers.pop("X-Requested-With", None)
123
-
124
74
  istek = await self.httpx.get(url)
125
75
  secici = HTMLHelper(istek.text)
126
- html_text = istek.text
127
76
 
128
- poster = self.fix_url(secici.select_attr("meta[property='og:image']", "content")) if secici.select_attr("meta[property='og:image']", "content") else None
129
-
130
- # Sidebar bilgilerini topla
131
- info = {}
132
- for li in secici.select("li"):
133
- key = secici.select_text("div.key", li)
134
- val = secici.select_text("div.value", li)
135
- if key and val:
136
- info[key.strip(":")] = val.strip()
137
-
138
- year = info.get("Yapım Yılı")
139
- rating = info.get("IMDB Puanı")
77
+ poster = self.fix_url(secici.select_attr("meta[property='og:image']", "content"))
78
+ description = secici.select_attr("meta[property='og:description']", "content")
79
+ title = secici.select_text("h1")
140
80
 
141
- tags_raw = info.get("Türler", "")
142
- tags = [t.strip() for t in tags_raw.split() if t.strip()] if tags_raw else None
143
-
144
- actors_raw = info.get("Oyuncular")
145
- actors = [a.strip() for a in actors_raw.split(",") if a.strip()] if actors_raw else None
146
-
147
- description = secici.select_text("div.summary p")
81
+ year = secici.meta_value("Yapım Yılı")
82
+ rating = secici.meta_value("IMDB Puanı")
83
+ duration_raw = secici.meta_value("Süre")
84
+ if duration_raw:
85
+ parts = duration_raw.split()
86
+ saat = 0
87
+ dakika = 0
88
+
89
+ for p in parts:
90
+ if "s" in p:
91
+ saat = int(p.replace("s", ""))
92
+ elif "dk" in p:
93
+ dakika = int(p.replace("dk", ""))
94
+
95
+ duration = saat * 60 + dakika
96
+ else:
97
+ duration = None
148
98
 
149
- duration_raw = info.get("Ortalama Süre")
150
- duration = int(secici.regex_first(r"(\d+)", duration_raw)) if duration_raw else None
99
+ tags = secici.meta_list("Tür")
100
+ actors = secici.meta_list("Oyuncular")
101
+ if not actors:
102
+ actors = secici.select_attrs("div.swiper-slide a", "title")
151
103
 
152
104
  if "/dizi/" in url:
153
- title = secici.select_text("div.cover h5")
154
-
155
105
  episodes = []
156
106
  for ep in secici.select("div.episode-item"):
157
- ep_name = secici.select_text("div.name", ep)
158
- ep_href = secici.select_attr("a", "href", ep)
159
- ep_text = secici.select_text("div.episode", ep)
160
- ep_parts = ep_text.split(" ")
107
+ name = secici.select_text("h4 a", ep)
108
+ href = secici.select_attr("a", "href", ep)
109
+ link_title = secici.select_attr("a", "title", ep)
110
+
111
+ h4_texts = secici.select_texts("h4", ep)
112
+ text = h4_texts[1] if len(h4_texts) > 1 else (h4_texts[0] if h4_texts else "")
161
113
 
162
- ep_season = None
163
- ep_episode = None
164
- if len(ep_parts) >= 4:
165
- try:
166
- ep_season = int(ep_parts[0].replace(".", ""))
167
- ep_episode = int(ep_parts[2].replace(".", ""))
168
- except ValueError:
169
- pass
114
+ full_text = f"{text} {link_title}" if link_title else text
170
115
 
171
- if ep_name and ep_href:
116
+ if name and href:
117
+ s, e = secici.extract_season_episode(full_text or "")
172
118
  episodes.append(Episode(
173
- season = ep_season,
174
- episode = ep_episode,
175
- title = ep_name,
176
- url = self.fix_url(ep_href),
119
+ season = s,
120
+ episode = e,
121
+ title = name,
122
+ url = self.fix_url(href)
177
123
  ))
178
124
 
179
125
  return SeriesInfo(
180
126
  url = url,
181
- poster = poster,
127
+ poster = poster.replace("https://test4test.online", self.main_url),
182
128
  title = title,
183
129
  description = description,
184
130
  tags = tags,
185
131
  rating = rating,
186
132
  year = year,
187
133
  duration = duration,
188
- episodes = episodes if episodes else None,
189
- actors = actors,
134
+ episodes = episodes,
135
+ actors = actors
190
136
  )
191
- else:
192
- # Film için title - g-title div'lerinin 2. olanı
193
- g_titles = secici.select("div.g-title div")
194
- title = secici.select_text(element=g_titles[1]) if len(g_titles) >= 2 else None
195
137
 
196
- return MovieInfo(
197
- url = url,
198
- poster = poster,
199
- title = title,
200
- description = description,
201
- tags = tags,
202
- rating = rating,
203
- year = year,
204
- duration = duration,
205
- actors = actors,
206
- )
138
+ return MovieInfo(
139
+ url = url,
140
+ poster = poster.replace("https://test4test.online", self.main_url),
141
+ title = title,
142
+ description = description,
143
+ tags = tags,
144
+ rating = rating,
145
+ year = year,
146
+ duration = duration,
147
+ actors = actors
148
+ )
207
149
 
208
150
  async def load_links(self, url: str) -> list[ExtractResult]:
209
- # Reset headers to get HTML response
210
- self.httpx.headers.update({
211
- "Accept": "text/html,application/xhtml+xml,application/xml;q=0.9,*/*;q=0.8"
212
- })
213
- self.httpx.headers.pop("X-Requested-With", None)
214
-
215
151
  istek = await self.httpx.get(url)
216
152
  secici = HTMLHelper(istek.text)
217
153
 
218
- # iframe presence checked via select_attr below
219
-
220
- iframe = secici.select_attr(".series-player-container iframe", "src") or secici.select_attr("div#vast_new iframe", "src")
154
+ iframe = secici.select_attr("div.video-player-area iframe", "src") or secici.select_attr("div.responsive-player iframe", "src")
221
155
  if not iframe:
222
156
  return []
223
157