KekikStream 2.2.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.

Potentially problematic release.


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

Files changed (88) hide show
  1. KekikStream/Core/Extractor/ExtractorBase.py +3 -2
  2. KekikStream/Core/Extractor/ExtractorLoader.py +8 -14
  3. KekikStream/Core/HTMLHelper.py +205 -0
  4. KekikStream/Core/Plugin/PluginBase.py +48 -12
  5. KekikStream/Core/Plugin/PluginLoader.py +13 -14
  6. KekikStream/Core/Plugin/PluginManager.py +2 -2
  7. KekikStream/Core/Plugin/PluginModels.py +0 -3
  8. KekikStream/Core/__init__.py +2 -0
  9. KekikStream/Extractors/Abstream.py +27 -0
  10. KekikStream/Extractors/CloseLoad.py +31 -56
  11. KekikStream/Extractors/ContentX.py +28 -71
  12. KekikStream/Extractors/DonilasPlay.py +34 -78
  13. KekikStream/Extractors/DzenRu.py +11 -25
  14. KekikStream/Extractors/ExPlay.py +20 -38
  15. KekikStream/Extractors/Filemoon.py +23 -53
  16. KekikStream/Extractors/HDMomPlayer.py +30 -0
  17. KekikStream/Extractors/HDPlayerSystem.py +13 -31
  18. KekikStream/Extractors/HotStream.py +27 -0
  19. KekikStream/Extractors/JFVid.py +3 -24
  20. KekikStream/Extractors/JetTv.py +21 -34
  21. KekikStream/Extractors/JetV.py +55 -0
  22. KekikStream/Extractors/MailRu.py +11 -29
  23. KekikStream/Extractors/MixPlayHD.py +17 -31
  24. KekikStream/Extractors/MixTiger.py +17 -40
  25. KekikStream/Extractors/MolyStream.py +25 -22
  26. KekikStream/Extractors/Odnoklassniki.py +41 -105
  27. KekikStream/Extractors/PeaceMakerst.py +20 -47
  28. KekikStream/Extractors/PixelDrain.py +9 -16
  29. KekikStream/Extractors/PlayerFilmIzle.py +23 -46
  30. KekikStream/Extractors/RapidVid.py +23 -36
  31. KekikStream/Extractors/SetPlay.py +19 -44
  32. KekikStream/Extractors/SetPrime.py +3 -6
  33. KekikStream/Extractors/SibNet.py +8 -19
  34. KekikStream/Extractors/Sobreatsesuyp.py +25 -47
  35. KekikStream/Extractors/TRsTX.py +25 -55
  36. KekikStream/Extractors/TurboImgz.py +8 -16
  37. KekikStream/Extractors/TurkeyPlayer.py +5 -5
  38. KekikStream/Extractors/VCTPlay.py +10 -28
  39. KekikStream/Extractors/Veev.py +145 -0
  40. KekikStream/Extractors/VidBiz.py +62 -0
  41. KekikStream/Extractors/VidHide.py +59 -34
  42. KekikStream/Extractors/VidMoly.py +67 -89
  43. KekikStream/Extractors/VidMoxy.py +17 -29
  44. KekikStream/Extractors/VidPapi.py +26 -58
  45. KekikStream/Extractors/VideoSeyred.py +21 -42
  46. KekikStream/Extractors/Videostr.py +58 -0
  47. KekikStream/Extractors/Vidoza.py +18 -0
  48. KekikStream/Extractors/Vtbe.py +38 -0
  49. KekikStream/Extractors/YTDLP.py +2 -2
  50. KekikStream/Extractors/YildizKisaFilm.py +13 -31
  51. KekikStream/Extractors/Zeus.py +61 -0
  52. KekikStream/Plugins/BelgeselX.py +108 -99
  53. KekikStream/Plugins/DiziBox.py +61 -106
  54. KekikStream/Plugins/DiziMom.py +179 -0
  55. KekikStream/Plugins/DiziPal.py +104 -192
  56. KekikStream/Plugins/DiziYou.py +66 -149
  57. KekikStream/Plugins/Dizilla.py +93 -126
  58. KekikStream/Plugins/FilmBip.py +102 -72
  59. KekikStream/Plugins/FilmEkseni.py +199 -0
  60. KekikStream/Plugins/FilmMakinesi.py +101 -64
  61. KekikStream/Plugins/FilmModu.py +35 -59
  62. KekikStream/Plugins/Filmatek.py +184 -0
  63. KekikStream/Plugins/FilmciBaba.py +155 -0
  64. KekikStream/Plugins/FullHDFilmizlesene.py +32 -78
  65. KekikStream/Plugins/HDFilm.py +243 -0
  66. KekikStream/Plugins/HDFilmCehennemi.py +261 -222
  67. KekikStream/Plugins/JetFilmizle.py +117 -98
  68. KekikStream/Plugins/KultFilmler.py +153 -143
  69. KekikStream/Plugins/RecTV.py +53 -49
  70. KekikStream/Plugins/RoketDizi.py +92 -123
  71. KekikStream/Plugins/SelcukFlix.py +86 -95
  72. KekikStream/Plugins/SetFilmIzle.py +105 -143
  73. KekikStream/Plugins/SezonlukDizi.py +106 -128
  74. KekikStream/Plugins/Sinefy.py +194 -166
  75. KekikStream/Plugins/SinemaCX.py +159 -113
  76. KekikStream/Plugins/Sinezy.py +44 -73
  77. KekikStream/Plugins/SuperFilmGeldi.py +28 -52
  78. KekikStream/Plugins/UgurFilm.py +94 -72
  79. KekikStream/Plugins/Watch32.py +160 -0
  80. KekikStream/Plugins/YabanciDizi.py +250 -0
  81. {kekikstream-2.2.9.dist-info → kekikstream-2.5.3.dist-info}/METADATA +1 -1
  82. kekikstream-2.5.3.dist-info/RECORD +99 -0
  83. {kekikstream-2.2.9.dist-info → kekikstream-2.5.3.dist-info}/WHEEL +1 -1
  84. KekikStream/Plugins/FullHDFilm.py +0 -254
  85. kekikstream-2.2.9.dist-info/RECORD +0 -82
  86. {kekikstream-2.2.9.dist-info → kekikstream-2.5.3.dist-info}/entry_points.txt +0 -0
  87. {kekikstream-2.2.9.dist-info → kekikstream-2.5.3.dist-info}/licenses/LICENSE +0 -0
  88. {kekikstream-2.2.9.dist-info → kekikstream-2.5.3.dist-info}/top_level.txt +0 -0
@@ -1,9 +1,8 @@
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, ExtractResult
4
- from selectolax.parser import HTMLParser
3
+ from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo, ExtractResult, HTMLHelper
5
4
  from Kekik.Sifreleme import StringCodec
6
- import json, re
5
+ import json
7
6
 
8
7
  class FullHDFilmizlesene(PluginBase):
9
8
  name = "FullHDFilmizlesene"
@@ -42,102 +41,59 @@ class FullHDFilmizlesene(PluginBase):
42
41
 
43
42
  async def get_main_page(self, page: int, url: str, category: str) -> list[MainPageResult]:
44
43
  istek = self.cloudscraper.get(f"{url}{page}")
45
- secici = HTMLParser(istek.text)
44
+ secici = HTMLHelper(istek.text)
46
45
 
47
46
  results = []
48
- for veri in secici.css("li.film"):
49
- title_el = veri.css_first("span.film-title")
50
- link_el = veri.css_first("a")
51
- img_el = veri.css_first("img")
52
-
53
- title = title_el.text(strip=True) if title_el else None
54
- href = link_el.attrs.get("href") if link_el else None
55
- poster = img_el.attrs.get("data-src") if img_el else None
47
+ for veri in secici.select("li.film"):
48
+ title = secici.select_text("span.film-title", veri)
49
+ href = secici.select_attr("a", "href", veri)
50
+ poster = secici.select_attr("img", "data-src", veri)
56
51
 
57
52
  if title and href:
58
53
  results.append(MainPageResult(
59
54
  category = category,
60
55
  title = title,
61
56
  url = self.fix_url(href),
62
- poster = self.fix_url(poster) if poster else None,
57
+ poster = self.fix_url(poster),
63
58
  ))
64
59
 
65
60
  return results
66
61
 
67
62
  async def search(self, query: str) -> list[SearchResult]:
68
63
  istek = await self.httpx.get(f"{self.main_url}/arama/{query}")
69
- secici = HTMLParser(istek.text)
64
+ secici = HTMLHelper(istek.text)
70
65
 
71
66
  results = []
72
- for film in secici.css("li.film"):
73
- title_el = film.css_first("span.film-title")
74
- link_el = film.css_first("a")
75
- img_el = film.css_first("img")
76
-
77
- title = title_el.text(strip=True) if title_el else None
78
- href = link_el.attrs.get("href") if link_el else None
79
- poster = img_el.attrs.get("data-src") if img_el else None
67
+ for film in secici.select("li.film"):
68
+ title = secici.select_text("span.film-title", film)
69
+ href = secici.select_attr("a", "href", film)
70
+ poster = secici.select_attr("img", "data-src", film)
80
71
 
81
72
  if title and href:
82
73
  results.append(SearchResult(
83
74
  title = title,
84
75
  url = self.fix_url(href),
85
- poster = self.fix_url(poster) if poster else None,
76
+ poster = self.fix_url(poster),
86
77
  ))
87
78
 
88
79
  return results
89
80
 
90
81
  async def load_item(self, url: str) -> MovieInfo:
91
82
  istek = await self.httpx.get(url)
92
- secici = HTMLParser(istek.text)
93
- html_text = istek.text
94
-
95
- # Title: normalize-space yerine doğrudan class ile
96
- title_el = secici.css_first("div.izle-titles")
97
- title = title_el.text(strip=True) if title_el else ""
98
-
99
- img_el = secici.css_first("div img[data-src]")
100
- poster = img_el.attrs.get("data-src", "").strip() if img_el else ""
101
-
102
- desc_el = secici.css_first("div.ozet-ic p")
103
- description = desc_el.text(strip=True) if desc_el else ""
104
-
105
- tags = [a.text(strip=True) for a in secici.css("a[rel='category tag']") if a.text(strip=True)]
106
-
107
- # Rating: normalize-space yerine doğrudan class ile ve son kelimeyi al
108
- rating_el = secici.css_first("div.puanx-puan")
109
- rating = None
110
- if rating_el:
111
- rating_text = rating_el.text(strip=True)
112
- if rating_text:
113
- parts = rating_text.split()
114
- rating = parts[-1] if parts else None
115
-
116
- # Year: ilk yıl formatında değer
117
- year_el = secici.css_first("div.dd a.category")
118
- year = None
119
- if year_el:
120
- year_text = year_el.text(strip=True)
121
- if year_text:
122
- parts = year_text.split()
123
- year = parts[0] if parts else None
124
-
125
- # Actors: nth-child yerine tüm li'leri alıp 2. index
126
- lis = secici.css("div.film-info ul li")
127
- actors = []
128
- if len(lis) >= 2:
129
- actors = [a.text(strip=True) for a in lis[1].css("a > span") if a.text(strip=True)]
130
-
131
- duration_el = secici.css_first("span.sure")
132
- duration = "0"
133
- if duration_el:
134
- duration_text = duration_el.text(strip=True)
135
- duration_parts = duration_text.split()
136
- duration = duration_parts[0] if duration_parts else "0"
83
+ secici = HTMLHelper(istek.text)
84
+
85
+ title = self.clean_title(secici.select_text("div.izle-titles"))
86
+ poster = secici.select_poster("div img[data-src]")
87
+ description = secici.select_text("div.ozet-ic")
88
+ tags = secici.select_texts("a[rel='category tag']")
89
+ rating = secici.regex_first(r"(\d+\.\d+|\d+)", secici.select_text("div.puanx-puan"))
90
+ year = secici.extract_year("div.dd a.category")
91
+ actors = secici.select_texts("a > span", secici.select_first("div.film-info ul li:nth-child(2)"))
92
+ duration = secici.regex_first(r"Süre: (\d+)\s*dk", secici.select_text("div.ozet-ic"))
137
93
 
138
94
  return MovieInfo(
139
95
  url = url,
140
- poster = self.fix_url(poster) if poster else None,
96
+ poster = self.fix_url(poster),
141
97
  title = title,
142
98
  description = description,
143
99
  tags = tags,
@@ -149,18 +105,17 @@ class FullHDFilmizlesene(PluginBase):
149
105
 
150
106
  async def load_links(self, url: str) -> list[ExtractResult]:
151
107
  istek = await self.httpx.get(url)
152
- secici = HTMLParser(istek.text)
153
- html_text = istek.text
108
+ secici = HTMLHelper(istek.text)
154
109
 
155
110
  # İlk script'i al (xpath (//script)[1] yerine)
156
- scripts = secici.css("script")
111
+ scripts = secici.select("script")
157
112
  script_content = scripts[0].text() if scripts else ""
158
113
 
159
- scx_match = re.search(r"scx = (.*?);", script_content)
160
- if not scx_match:
114
+ scx_json = HTMLHelper(script_content).regex_first(r"scx = (.*?);")
115
+ if not scx_json:
161
116
  return []
162
117
 
163
- scx_data = json.loads(scx_match.group(1))
118
+ scx_data = json.loads(scx_json)
164
119
  scx_keys = list(scx_data.keys())
165
120
 
166
121
  link_list = []
@@ -173,9 +128,8 @@ class FullHDFilmizlesene(PluginBase):
173
128
 
174
129
  response = []
175
130
  for link in link_list:
176
- link = f"https:{link}" if link.startswith("//") else link
177
- data = await self.extract(link)
131
+ data = await self.extract(self.fix_url(link))
178
132
  if data:
179
133
  response.append(data)
180
134
 
181
- return response
135
+ return response
@@ -0,0 +1,243 @@
1
+ # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
+
3
+ from KekikStream.Core import PluginBase, MainPageResult, SearchResult, MovieInfo, SeriesInfo, Episode, ExtractResult, Subtitle, HTMLHelper
4
+ import base64, asyncio, contextlib
5
+
6
+ class HDFilm(PluginBase):
7
+ name = "HDFilm"
8
+ language = "tr"
9
+ main_url = "https://hdfilm.us"
10
+ favicon = f"https://www.google.com/s2/favicons?domain={main_url}&sz=64"
11
+ description = "Full HD Film izle, Türkçe Dublaj ve Altyazılı filmler."
12
+
13
+ main_page = {
14
+ f"{main_url}/tur/turkce-altyazili-film-izle" : "Altyazılı Filmler",
15
+ f"{main_url}/tur/netflix-filmleri-izle" : "Netflix",
16
+ f"{main_url}/tur/yerli-film-izle" : "Yerli Film",
17
+ f"{main_url}/category/aile-filmleri-izle" : "Aile",
18
+ f"{main_url}/category/aksiyon-filmleri-izle" : "Aksiyon",
19
+ f"{main_url}/category/animasyon-filmleri-izle" : "Animasyon",
20
+ f"{main_url}/category/belgesel-filmleri-izle" : "Belgesel",
21
+ f"{main_url}/category/bilim-kurgu-filmleri-izle" : "Bilim Kurgu",
22
+ f"{main_url}/category/biyografi-filmleri-izle" : "Biyografi",
23
+ f"{main_url}/category/dram-filmleri-izle" : "Dram",
24
+ f"{main_url}/category/fantastik-filmler-izle" : "Fantastik",
25
+ f"{main_url}/category/gerilim-filmleri-izle" : "Gerilim",
26
+ f"{main_url}/category/gizem-filmleri-izle" : "Gizem",
27
+ f"{main_url}/category/kisa" : "Kısa",
28
+ f"{main_url}/category/komedi-filmleri-izle" : "Komedi",
29
+ f"{main_url}/category/korku-filmleri-izle" : "Korku",
30
+ f"{main_url}/category/macera-filmleri-izle" : "Macera",
31
+ f"{main_url}/category/muzik" : "Müzik",
32
+ f"{main_url}/category/muzikal-filmleri-izle" : "Müzikal",
33
+ f"{main_url}/category/romantik-filmler-izle" : "Romantik",
34
+ f"{main_url}/category/savas-filmleri-izle" : "Savaş",
35
+ f"{main_url}/category/spor-filmleri-izle" : "Spor",
36
+ f"{main_url}/category/suc-filmleri-izle" : "Suç",
37
+ f"{main_url}/category/tarih-filmleri-izle" : "Tarih",
38
+ f"{main_url}/category/western-filmleri-izle" : "Western",
39
+ }
40
+
41
+ async def get_main_page(self, page: int, url: str, category: str) -> list[MainPageResult]:
42
+ istek = await self.httpx.get(url if page == 1 else f"{url}/page/{page}")
43
+ secici = HTMLHelper(istek.text)
44
+
45
+ results = []
46
+ for veri in secici.select("div.movie-poster"):
47
+ title = secici.select_attr("img", "alt", veri)
48
+ poster = secici.select_attr("img", "src", veri)
49
+ href = secici.select_attr("a", "href", veri)
50
+
51
+ if title and href:
52
+ results.append(MainPageResult(
53
+ category = category,
54
+ title = self.clean_title(title),
55
+ url = self.fix_url(href),
56
+ poster = self.fix_url(poster)
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
+
65
+ results = []
66
+ for veri in secici.select("div.movie-poster"):
67
+ title = secici.select_attr("img", "alt", veri)
68
+ poster = secici.select_attr("img", "src", veri)
69
+ href = secici.select_attr("a", "href", veri)
70
+
71
+ if title and href:
72
+ results.append(SearchResult(
73
+ title = self.clean_title(title),
74
+ url = self.fix_url(href),
75
+ poster = self.fix_url(poster)
76
+ ))
77
+
78
+ return results
79
+
80
+ async def load_item(self, url: str) -> MovieInfo | SeriesInfo:
81
+ istek = await self.httpx.get(url)
82
+ secici = HTMLHelper(istek.text)
83
+
84
+ title = self.clean_title(secici.select_text("h1"))
85
+ poster = secici.select_poster("div.poster img")
86
+ description = secici.select_text("div.film") or secici.select_attr("meta[property='og:description']", "content")
87
+ year = secici.extract_year("div.yayin-tarihi.info") or secici.regex_first(r"\((\d{4})\)")
88
+ tags = secici.select_texts("div.tur.info a")
89
+ rating = secici.regex_first(r"IMDb\s*([\d\.]+)", secici.select_text("div.imdb"))
90
+ actors = secici.select_direct_text("div.oyuncular")
91
+
92
+ is_series = "-dizi" in url.lower() or any("dizi" in tag.lower() for tag in tags)
93
+ if is_series:
94
+ episodes = []
95
+ for idx, el in enumerate(secici.select("li.psec")):
96
+ part_id = el.attrs.get("id")
97
+ part_name = secici.select_text("a", el) or ""
98
+ if not part_name or "fragman" in part_name.lower():
99
+ continue
100
+
101
+ s, e = secici.extract_season_episode(f"{part_id} {part_name}")
102
+ episodes.append(Episode(
103
+ season = s or 1,
104
+ episode = e or (idx+1),
105
+ title = f"{s or 1}. Sezon {e or idx+1}. Bölüm",
106
+ url = url
107
+ ))
108
+
109
+ return SeriesInfo(
110
+ url = url,
111
+ poster = self.fix_url(poster),
112
+ title = title,
113
+ description = description,
114
+ tags = tags,
115
+ year = year,
116
+ actors = actors,
117
+ rating = rating,
118
+ episodes = episodes
119
+ )
120
+
121
+ return MovieInfo(
122
+ url = url,
123
+ poster = self.fix_url(poster),
124
+ title = title,
125
+ description = description,
126
+ tags = tags,
127
+ year = year,
128
+ actors = actors,
129
+ rating = rating
130
+ )
131
+
132
+ def _get_iframe(self, source_code: str) -> str:
133
+ """Base64 kodlu iframe'i çözümle"""
134
+ script_val = HTMLHelper(source_code).regex_first(r'<script[^>]*>(PCEtLWJhc2xpazp[^<]*)</script>')
135
+ if not script_val:
136
+ return ""
137
+
138
+ try:
139
+ decoded_html = base64.b64decode(script_val).decode("utf-8")
140
+ iframe_src = HTMLHelper(decoded_html).regex_first(r'<iframe[^>]+src=["\']([^"\']+)["\']')
141
+ return self.fix_url(iframe_src) if iframe_src else ""
142
+ except Exception:
143
+ return ""
144
+
145
+ def _extract_subtitle_url(self, source_code: str) -> str | None:
146
+ """playerjsSubtitle değişkeninden .srt URL çıkar"""
147
+ patterns = [
148
+ r'var playerjsSubtitle = "\[Türkçe\](https?://[^\s"]+?\.srt)";',
149
+ r'var playerjsSubtitle = "(https?://[^\s"]+?\.srt)";',
150
+ r'subtitle:\s*"(https?://[^\s"]+?\.srt)"',
151
+ ]
152
+
153
+ for pattern in patterns:
154
+ val = HTMLHelper(source_code).regex_first(pattern)
155
+ if val:
156
+ return val
157
+
158
+ return None
159
+
160
+ async def _get_source_links(self, url: str, initial_text: str | None = None) -> list[ExtractResult]:
161
+ results = []
162
+ try:
163
+ if initial_text:
164
+ source_code = initial_text
165
+ secici = HTMLHelper(source_code)
166
+ else:
167
+ resp = await self.httpx.get(url)
168
+ source_code = resp.text
169
+ secici = HTMLHelper(source_code)
170
+
171
+ iframe_src = self._get_iframe(source_code)
172
+ subtitle_url = self._extract_subtitle_url(source_code)
173
+
174
+ # İsim Oluştur (Dil | Player)
175
+ parts = []
176
+
177
+ if action_parts := secici.select_first("div#action-parts"):
178
+ # Aktif olan wrapper'ları bul
179
+ for wrapper in secici.select("div.button-custom-wrapper", action_parts):
180
+ # Aktif buton/link
181
+ active_el = secici.select_first("button", wrapper) or secici.select_first("a.button", wrapper)
182
+ if active_el:
183
+ parts.append(active_el.text(strip=True))
184
+
185
+ final_name = " | ".join(parts) if parts else "HDFilm"
186
+
187
+ if not subtitle_url and iframe_src:
188
+ with contextlib.suppress(Exception):
189
+ iframe_istek = await self.httpx.get(iframe_src)
190
+ subtitle_url = self._extract_subtitle_url(iframe_istek.text)
191
+
192
+ if iframe_src:
193
+ data = await self.extract(iframe_src, name_override=final_name)
194
+ if data:
195
+ sub = Subtitle(name="Türkçe", url=subtitle_url) if subtitle_url else None
196
+ if isinstance(data, list):
197
+ for d in data:
198
+ if sub:
199
+ d.subtitles.append(sub)
200
+ results.append(d)
201
+ else:
202
+ if sub:
203
+ data.subtitles.append(sub)
204
+ results.append(data)
205
+
206
+ return results
207
+ except Exception:
208
+ return []
209
+
210
+ async def load_links(self, url: str) -> list[ExtractResult]:
211
+ initial_istek = await self.httpx.get(url)
212
+ initial_text = initial_istek.text
213
+ secici = HTMLHelper(initial_text)
214
+
215
+ base_url = url.split("?")[0].rstrip("/")
216
+ unique_urls = {base_url} # ?page=1 varsa da base_url olarak sakla
217
+
218
+ if action_parts := secici.select_first("div#action-parts"):
219
+ for link in secici.select("a[href]", action_parts):
220
+ href = link.attrs.get("href", "")
221
+ if "?page=" in href:
222
+ if href.endswith("?page=1") or href == "?page=1":
223
+ unique_urls.add(base_url)
224
+ elif href.startswith("?"):
225
+ unique_urls.add(f"{base_url}{href}")
226
+ else:
227
+ unique_urls.add(self.fix_url(href))
228
+
229
+ tasks = []
230
+ for p_url in unique_urls:
231
+ # Eğer p_url şu anki url ile eşleşiyorsa (veya ?page=1 farkı varsa) metni kullan
232
+ # Basit eşleşme: Eğer p_url == base_url ve (url == base_url veya url == base_url + "?page=1")
233
+
234
+ use_initial = False
235
+ if p_url == base_url:
236
+ if url.rstrip("/") == base_url or url.rstrip("/") == f"{base_url}?page=1":
237
+ use_initial = True
238
+ elif p_url == url.rstrip("/"):
239
+ use_initial = True
240
+
241
+ tasks.append(self._get_source_links(p_url, initial_text if use_initial else None))
242
+
243
+ return [item for sublist in await asyncio.gather(*tasks) for item in sublist]