KekikStream 0.1.8__py3-none-any.whl → 0.1.9__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.
@@ -52,7 +52,7 @@ class SeriesInfo(BaseModel):
52
52
  title : Optional[str] = None
53
53
  description : Optional[str] = None
54
54
  tags : Optional[str] = None
55
- rating : Optional[float] = None
55
+ rating : Optional[str] = None
56
56
  year : Optional[str] = None
57
57
  actors : Optional[str] = None
58
58
  episodes : Optional[List[Episode]] = None
@@ -65,4 +65,9 @@ class SeriesInfo(BaseModel):
65
65
  @field_validator("actors", mode="before")
66
66
  @classmethod
67
67
  def convert_actors(cls, value):
68
- return ", ".join(value) if isinstance(value, list) else value
68
+ return ", ".join(value) if isinstance(value, list) else value
69
+
70
+ @field_validator("rating", mode="before")
71
+ @classmethod
72
+ def ensure_string(cls, value):
73
+ return str(value) if value is not None else value
@@ -0,0 +1,93 @@
1
+ # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
+ # ! https://github.com/recloudstream/cloudstream/blob/master/library/src/commonMain/kotlin/com/lagradost/cloudstream3/extractors/Vidmoly.kt
3
+
4
+ from KekikStream.Core import ExtractorBase, ExtractResult, Subtitle
5
+ import re
6
+ import asyncio
7
+ import json
8
+
9
+ class VidMoly(ExtractorBase):
10
+ name = "VidMoly"
11
+ main_url = "https://vidmoly.to"
12
+
13
+ async def extract(self, url: str, referer: str = None) -> ExtractResult:
14
+ if referer:
15
+ self.oturum.headers.update({"Referer": referer})
16
+
17
+ headers = {
18
+ "User-Agent": "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/91.0.4472.124 Safari/537.36",
19
+ "Sec-Fetch-Dest": "iframe",
20
+ }
21
+
22
+ # Embed URL oluştur
23
+ embed_url = (
24
+ url.replace("/w/", "/embed-") + "-920x360.html" if "/w/" in url else url
25
+ )
26
+ script_content = None
27
+ attempts = 0
28
+
29
+ # Script verisini almak için deneme yap
30
+ while attempts < 10 and not script_content:
31
+ attempts += 1
32
+ response = await self.oturum.get(embed_url, headers=headers)
33
+ response.raise_for_status()
34
+ script_match = re.search(r"sources:\s*\[(.*?)\],", response.text, re.DOTALL)
35
+ script_content = script_match.group(1) if script_match else None
36
+ if not script_content:
37
+ await asyncio.sleep(0.5)
38
+
39
+ if not script_content:
40
+ raise ValueError("Gerekli script bulunamadı.")
41
+
42
+ # Video kaynaklarını ayrıştır
43
+ video_data = self._add_marks(script_content, "file")
44
+ try:
45
+ video_sources = json.loads(f"[{video_data}]")
46
+ except json.JSONDecodeError:
47
+ raise ValueError("Video kaynakları ayrıştırılamadı.")
48
+
49
+ # Altyazı kaynaklarını ayrıştır
50
+ subtitles = []
51
+ subtitle_match = re.search(r"tracks:\s*\[(.*?)\]", response.text, re.DOTALL)
52
+ if subtitle_match:
53
+ subtitle_data = self._add_marks(subtitle_match.group(1), "file")
54
+ subtitle_data = self._add_marks(subtitle_data, "label")
55
+ subtitle_data = self._add_marks(subtitle_data, "kind")
56
+
57
+ try:
58
+ subtitle_sources = json.loads(f"[{subtitle_data}]")
59
+ subtitles = [
60
+ Subtitle(
61
+ name=sub.get("label"),
62
+ url=self.fix_url(sub.get("file")),
63
+ )
64
+ for sub in subtitle_sources
65
+ if sub.get("kind") == "captions"
66
+ ]
67
+ except json.JSONDecodeError:
68
+ pass
69
+
70
+ # İlk video kaynağını al
71
+ video_url = None
72
+ for source in video_sources:
73
+ file_url = source.get("file")
74
+ if file_url:
75
+ video_url = file_url
76
+ break
77
+
78
+ if not video_url:
79
+ raise ValueError("Video URL bulunamadı.")
80
+
81
+ await self.close()
82
+ return ExtractResult(
83
+ name=self.name,
84
+ url=video_url,
85
+ referer=self.main_url,
86
+ subtitles=subtitles,
87
+ )
88
+
89
+ def _add_marks(self, text: str, field: str) -> str:
90
+ """
91
+ Verilen alanı çift tırnak içine alır.
92
+ """
93
+ return re.sub(rf"\"?{field}\"?", f"\"{field}\"", text)
@@ -0,0 +1,108 @@
1
+ # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
+
3
+ from KekikStream.Core import PluginBase, SearchResult, SeriesInfo, Episode
4
+ from parsel import Selector
5
+
6
+ class SezonlukDizi(PluginBase):
7
+ name = "SezonlukDizi"
8
+ main_url = "https://sezonlukdizi6.com"
9
+
10
+ async def search(self, query: str) -> list[SearchResult]:
11
+ istek = await self.oturum.get(f"{self.main_url}/diziler.asp?adi={query}")
12
+ secici = Selector(istek.text)
13
+
14
+ return [
15
+ SearchResult(
16
+ title = afis.css("div.description::text").get(default="").strip(),
17
+ url = self.fix_url(afis.attrib.get("href")),
18
+ poster = self.fix_url(afis.css("img::attr(data-src)").get()),
19
+ )
20
+ for afis in secici.css("div.afis a")
21
+ ]
22
+
23
+ async def load_item(self, url: str) -> SeriesInfo:
24
+ istek = await self.oturum.get(url)
25
+ secici = Selector(istek.text)
26
+
27
+ title = secici.css("div.header::text").get(default="").strip()
28
+ poster = self.fix_url(secici.css("div.image img::attr(data-src)").get(default="").strip())
29
+ year = secici.css("div.extra span::text").re_first(r"(\d{4})")
30
+ description = secici.css("span#tartismayorum-konu::text").get(default="").strip()
31
+ tags = secici.css("div.labels a[href*='tur']::text").getall()
32
+ rating = secici.css("div.dizipuani a div::text").re_first(r"[\d.,]+")
33
+ actors = []
34
+
35
+ actors_istek = await self.oturum.get(f"{self.main_url}/oyuncular/{url.split('/')[-1]}")
36
+ actors_secici = Selector(actors_istek.text)
37
+ actors = [
38
+ actor.css("div.header::text").get().strip()
39
+ for actor in actors_secici.css("div.doubling div.ui")
40
+ ]
41
+
42
+ episodes_istek = await self.oturum.get(f"{self.main_url}/bolumler/{url.split('/')[-1]}")
43
+ episodes_secici = Selector(episodes_istek.text)
44
+ episodes = []
45
+
46
+ for sezon in episodes_secici.css("table.unstackable"):
47
+ for bolum in sezon.css("tbody tr"):
48
+ ep_name = bolum.css("td:nth-of-type(4) a::text").get(default="").strip()
49
+ ep_href = self.fix_url(bolum.css("td:nth-of-type(4) a::attr(href)").get())
50
+ ep_episode = bolum.css("td:nth-of-type(3) a::text").re_first(r"(\d+)")
51
+ ep_season = bolum.css("td:nth-of-type(2)::text").re_first(r"(\d+)")
52
+
53
+ if ep_name and ep_href:
54
+ episode = Episode(
55
+ season = ep_season,
56
+ episode = ep_episode,
57
+ title = ep_name,
58
+ url = ep_href,
59
+ )
60
+ episodes.append(episode)
61
+
62
+ return SeriesInfo(
63
+ url = url,
64
+ poster = poster,
65
+ title = title,
66
+ description = description,
67
+ tags = tags,
68
+ rating = rating,
69
+ year = year,
70
+ episodes = episodes,
71
+ actors = actors
72
+ )
73
+
74
+ async def load_links(self, url: str) -> list[str]:
75
+ istek = await self.oturum.get(url)
76
+ secici = Selector(istek.text)
77
+
78
+ bid = secici.css("div#dilsec::attr(data-id)").get()
79
+ if not bid:
80
+ return []
81
+
82
+ links = []
83
+ for dil, label in [("1", "AltYazı"), ("0", "Dublaj")]:
84
+ dil_istek = await self.oturum.post(
85
+ url = f"{self.main_url}/ajax/dataAlternatif2.asp",
86
+ headers = {"X-Requested-With": "XMLHttpRequest"},
87
+ data = {"bid": bid, "dil": dil},
88
+ )
89
+
90
+ try:
91
+ dil_json = dil_istek.json()
92
+ except Exception:
93
+ continue
94
+
95
+ if dil_json.get("status") == "success":
96
+ for veri in dil_json.get("data", []):
97
+ veri_response = await self.oturum.post(
98
+ url = f"{self.main_url}/ajax/dataEmbed.asp",
99
+ headers = {"X-Requested-With": "XMLHttpRequest"},
100
+ data = {"id": veri.get("id")},
101
+ )
102
+ secici = Selector(veri_response.text)
103
+
104
+ if iframe := secici.css("iframe::attr(src)").get():
105
+ video_url = self.fix_url(iframe)
106
+ links.append(video_url)
107
+
108
+ return links
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: KekikStream
3
- Version: 0.1.8
3
+ Version: 0.1.9
4
4
  Summary: terminal üzerinden medya içeriği aramanızı ve VLC/MPV gibi popüler medya oynatıcılar aracılığıyla doğrudan izlemenizi sağlayan modüler ve genişletilebilir bir bıdı bıdı
5
5
  Home-page: https://github.com/keyiflerolsun/KekikStream
6
6
  Author: keyiflerolsun
@@ -9,7 +9,7 @@ KekikStream/Core/ExtractorModels.py,sha256=vJeh4qd05K7nbqdCCGU29UkGQpce6jXfsCm7L
9
9
  KekikStream/Core/MediaHandler.py,sha256=Q_9LMc4Wnmv8PhMfoo2IgxpHLeikUgrqp_B_Rfs217U,3005
10
10
  KekikStream/Core/PluginBase.py,sha256=MmhGy0XtbkWxE5SNvsag0M_jNehMxPGtVyZFOKlJPM8,2304
11
11
  KekikStream/Core/PluginLoader.py,sha256=og5EPfnVqrb2kUkeGU65AY0fU43IbiUo_h3ix6ZiINY,2596
12
- KekikStream/Core/PluginModels.py,sha256=-V4Be9ebnUQsQtGzLxg0kGK13RJTmpB7bvAUwsE-ir0,2208
12
+ KekikStream/Core/PluginModels.py,sha256=WWPEz8PpZZ4bLMDJzTE19BsQEJObkyhaYjDkyLaF2Ck,2365
13
13
  KekikStream/Core/__init__.py,sha256=HZpXs3MKy4joO0sDpIGcZ2DrUKwK49IKG-GQgKbO2jk,416
14
14
  KekikStream/Extractors/CloseLoad.py,sha256=YmDB3YvuDaCUbQ0T_tmhnkEsC5mSdEN6GNoAR662fl8,990
15
15
  KekikStream/Extractors/MailRu.py,sha256=lB3Xy912EaSEUw7Im65L5TwtIeM7OLFV1_9lan39g40,1308
@@ -20,6 +20,7 @@ KekikStream/Extractors/Sobreatsesuyp.py,sha256=7JUbqHLMWFkHuzH3NG2ogaV53e9fUmGvA
20
20
  KekikStream/Extractors/TRsTX.py,sha256=jhPcQq7KPxL0SPvEFL4MG7oDXDpBbt6Qh8vRJ_bLQMU,2105
21
21
  KekikStream/Extractors/TauVideo.py,sha256=bBjrZFSi4QqSJhRB0sDWMA0Saio-zpoAb6Ss4QZmBeY,1045
22
22
  KekikStream/Extractors/TurboImgz.py,sha256=0d9t6bj4prVt1_LIbzwcfuqrSRB7SMvc4RKvE25BtW4,851
23
+ KekikStream/Extractors/VidMoly.py,sha256=a2ElfpEcTWBpBT0mADWcEF2T8l9WjAEuX8Dux0hiYrU,3390
23
24
  KekikStream/Extractors/VidMoxy.py,sha256=UnVrCEI4XNiONE2aLV9dGUhRqQ9ELJTnYVXyG81N11A,1800
24
25
  KekikStream/Managers/ExtractorManager.py,sha256=9rGlUsnedJ7fwIeObN5Vsm8H5VLal0ODO7F93dDRx8w,976
25
26
  KekikStream/Managers/MediaManager.py,sha256=F7mkSvAttAaMHRvnDcxnV2K1D_sK644BCSrEaAmMl_U,522
@@ -29,11 +30,12 @@ KekikStream/Managers/__init__.py,sha256=3085I_9Sa2L_Vq6Z-QvYUYn1BapkN4sQqBo8ITZo
29
30
  KekikStream/Plugins/FilmMakinesi.py,sha256=g4LRDP5Atn97PqbgnEdm0-wjVdXaJIVk1Ru0F8B66Ws,2902
30
31
  KekikStream/Plugins/FullHDFilmizlesene.py,sha256=HJzHDXHhhMpvXxiD2SjpoZEYs7dmnPymE8EXCSvLKVo,3106
31
32
  KekikStream/Plugins/JetFilmizle.py,sha256=DPdvTEns8r2MI9pHY8d9EEsUZmlQU7N2C9yr8ox80qU,4016
33
+ KekikStream/Plugins/SezonlukDizi.py,sha256=l_VTn45NTeuuW5Imjm3h_302npQ1MhJc_nFQpsijfC0,4470
32
34
  KekikStream/Plugins/SineWix.py,sha256=RJxggTrZxBimQHI4ehtJipVeIBpfHy85NW-ixE2iF2k,4762
33
35
  KekikStream/Plugins/UgurFilm.py,sha256=U7ryNWpjSZJWuYlMGX1Be9uuyiM3SfuI9VJcEiXedNs,2960
34
- KekikStream-0.1.8.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
35
- KekikStream-0.1.8.dist-info/METADATA,sha256=x9zouqWIPAlgPfpKwsqczRyIbquHJG6wM3ybNRqEgV8,3961
36
- KekikStream-0.1.8.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
37
- KekikStream-0.1.8.dist-info/entry_points.txt,sha256=dFwdiTx8djyehI0Gsz-rZwjAfZzUzoBSrmzRu9ubjJc,50
38
- KekikStream-0.1.8.dist-info/top_level.txt,sha256=DNmGJDXl27Drdfobrak8KYLmocW_uznVYFJOzcjUgmY,12
39
- KekikStream-0.1.8.dist-info/RECORD,,
36
+ KekikStream-0.1.9.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
37
+ KekikStream-0.1.9.dist-info/METADATA,sha256=5SDtM4OLVuftfTnRp8JYw8ULHnWAA9OKFZciFMIoQp0,3961
38
+ KekikStream-0.1.9.dist-info/WHEEL,sha256=PZUExdf71Ui_so67QXpySuHtCi3-J3wvF4ORK6k_S8U,91
39
+ KekikStream-0.1.9.dist-info/entry_points.txt,sha256=dFwdiTx8djyehI0Gsz-rZwjAfZzUzoBSrmzRu9ubjJc,50
40
+ KekikStream-0.1.9.dist-info/top_level.txt,sha256=DNmGJDXl27Drdfobrak8KYLmocW_uznVYFJOzcjUgmY,12
41
+ KekikStream-0.1.9.dist-info/RECORD,,