KekikStream 0.8.7__py3-none-any.whl → 0.9.0__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.
@@ -113,8 +113,8 @@ class DiziYou(PluginBase):
113
113
 
114
114
  for stream in stream_urls:
115
115
  self._data[stream.get("url")] = {
116
- "name" : f"{self.name} | {stream.get('dil')} | {item_title}",
117
116
  "ext_name" : f"{self.name} | {stream.get('dil')}",
117
+ "name" : f"{self.name} | {stream.get('dil')} | {item_title}",
118
118
  "referer" : url,
119
119
  "subtitles" : subtitles
120
120
  }
@@ -0,0 +1,229 @@
1
+ # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
+
3
+ from KekikStream.Core import PluginBase, SearchResult, MovieInfo, Episode, SeriesInfo, ExtractResult, Subtitle
4
+
5
+ from Kekik.unicode_tr import unicode_tr
6
+ import re, json, base64
7
+
8
+ async def extract_next_f_push_data(source_code):
9
+ """
10
+ Kaynak kod içerisindeki self.__next_f.push(...) çağrılarını yakalayıp,
11
+ içlerindeki key-value bilgilerini tek bir sözlükte birleştirir.
12
+ """
13
+ # self.__next_f.push( ... ) içindeki array'i yakalayan regex (DOTALL ile çok satırlı aramalarda)
14
+ pattern = r"self\.__next_f\.push\(\s*(\[[\s\S]*?\])\s*\)"
15
+ matches = re.findall(pattern, source_code, re.DOTALL)
16
+
17
+ combined = {}
18
+
19
+ for match in matches:
20
+ try:
21
+ # Yakalanan array'i JSON olarak ayrıştırıyoruz
22
+ arr = json.loads(match)
23
+ except json.JSONDecodeError as e:
24
+ print("JSON ayrıştırma hatası:", e)
25
+ continue
26
+
27
+ # Eğer push çağrısı iki elemanlı ve ikinci eleman string ise işleme alalım.
28
+ if isinstance(arr, list) and len(arr) == 2 and isinstance(arr[1], str):
29
+ data_str = arr[1]
30
+ # String içerisindeki satırları ayırıyoruz
31
+ for line in data_str.splitlines():
32
+ line = line.strip()
33
+ if not line:
34
+ continue
35
+ # Beklenen format: key:değer şeklinde
36
+ if ':' in line:
37
+ key, value = line.split(':', 1)
38
+ key = key.strip()
39
+ value = value.strip()
40
+
41
+ # Eğer değer HL[...] veya I[...] gibi bir formatta ise
42
+ m = re.match(r'^(HL|I)(\[[\s\S]*\])$', value)
43
+ if m:
44
+ prefix = m.group(1)
45
+ json_part = m.group(2)
46
+ try:
47
+ parsed_val = json.loads(json_part)
48
+ value = {prefix: parsed_val}
49
+ except json.JSONDecodeError:
50
+ # Ayrıştırılamazsa orijinal değeri bırakıyoruz.
51
+ pass
52
+ else:
53
+ # Değerin tamamı [ ... ] veya { ... } şeklinde ise JSON ayrıştırmayı deniyoruz.
54
+ if (value.startswith('[') and value.endswith(']')) or (value.startswith('{') and value.endswith('}')):
55
+ try:
56
+ value = json.loads(value)
57
+ except json.JSONDecodeError:
58
+ pass
59
+ # Eğer aynı anahtar daha önce varsa üzerine yazar.
60
+ combined[key] = value
61
+ # Eğer push çağrısı farklı bir formatta ise (örneğin [0] veya [2, null]),
62
+ # ihtiyaca göre burada ek işleme yapabilirsiniz.
63
+
64
+ return combined
65
+
66
+ class Shorten(PluginBase):
67
+ name = "Shorten"
68
+ main_url = "http://localhost:8080"
69
+ token = None
70
+
71
+ async def __giris(self):
72
+ await self.oturum.get("https://shorten.com/tr", follow_redirects=True)
73
+
74
+ self.token = await self.oturum.get("https://shorten.com/api/session")
75
+ self.token = self.token.json().get("token")
76
+
77
+ self.oturum.headers.update({"Authorization": f"Bearer {self.token}"})
78
+
79
+ async def raw_diziler(self):
80
+ if not self.token:
81
+ await self.__giris()
82
+
83
+ veriler = await self.oturum.get("https://api.shorten.watch/api/series/you-might-like?page=1&per_page=100")
84
+ veriler = veriler.json()
85
+
86
+ return [
87
+ {
88
+ "title" : unicode_tr(veri.get("title")).title(),
89
+ "slug" : veri.get("slug"),
90
+ } for veri in veriler.get("data")
91
+ ]
92
+
93
+ async def raw_bolumler(self, slug):
94
+ if not self.token:
95
+ await self.__giris()
96
+
97
+ istek = await self.oturum.get(f"https://shorten.com/tr/series/{slug}", follow_redirects=True)
98
+ veriler = await extract_next_f_push_data(istek.text)
99
+ veriler = veriler["8"][-1]["children"][-2][-1]["children"][-1]["data"]
100
+ return [
101
+ {
102
+ "number" : veri.get("number"),
103
+ "hash" : veri.get("hash")
104
+ } for veri in veriler.get("episodes")
105
+ ]
106
+
107
+ async def hls_decode_video(self, token):
108
+ token = base64.b64decode(token).decode("utf-8")
109
+ token = json.loads(token).get("GetPlayInfoToken")
110
+
111
+ istek = self.cloudscraper.get(
112
+ url = f"https://vod.byteplusapi.com/?{token}",
113
+ headers = {
114
+ "User-Agent" : "Mozilla/5.0 (Windows NT 10.0; Win64; x64) AppleWebKit/537.36 (KHTML, like Gecko) Chrome/121.0.0.0 Safari/537.36",
115
+ "Content-Type" : "application/json",
116
+ "Origin" : "https://vod.byteplusapi.com",
117
+ "Referer" : "https://shorten.com/",
118
+ }
119
+ )
120
+
121
+ veriler = istek.json()
122
+ return veriler["Result"]["PlayInfoList"][-1]["MainPlayUrl"]
123
+
124
+ async def bolumler(self, slug):
125
+ if not self.token:
126
+ await self.__giris()
127
+
128
+ raw_req = await self.raw_bolumler(slug)
129
+ number, _hash = raw_req[0].values()
130
+
131
+ istek = await self.oturum.get(f"https://shorten.com/tr/series/{slug}/episode-{number}-{_hash}", follow_redirects=True)
132
+ veriler = await extract_next_f_push_data(istek.text)
133
+ veriler = veriler["b"][3]["children"][1][3]["children"][3]["children"][3]["children"][-1]
134
+
135
+ for index, video in enumerate(veriler["videos"]):
136
+ copy = veriler["data"]["episodes"][index].copy()
137
+ for key in copy.keys():
138
+ del veriler["data"]["episodes"][index][key]
139
+
140
+ for sub in copy.get("subtitles"):
141
+ for sil in ["id", "format", "sub_id"]:
142
+ del sub[sil]
143
+ sub["url"] = f"https://cdn.shorten.watch/{sub['url']}"
144
+
145
+ veriler["data"]["episodes"][index] = {
146
+ "number" : copy.get("number"),
147
+ "image" : copy.get("cover_image"),
148
+ "hls" : video["hashHls"],
149
+ "subtitles" : copy.get("subtitles")
150
+ }
151
+
152
+ veriler["data"]["episode"] = veriler["data"]["episode"]["total"]
153
+ del veriler["data"]["is_favorite"]
154
+
155
+ veriler["data"]["title"] = unicode_tr(veriler["data"]["title"]).title()
156
+
157
+ return veriler["data"]
158
+
159
+ async def search(self, query: str) -> list[SearchResult]:
160
+ veriler = await self.raw_diziler()
161
+
162
+ return [
163
+ SearchResult(
164
+ title = veri.get("title"),
165
+ url = veri.get("slug"),
166
+ poster = "",
167
+ )
168
+ for veri in veriler
169
+ ]
170
+
171
+ async def load_item(self, url: str) -> MovieInfo:
172
+ veri = await self.bolumler(url)
173
+
174
+ episodes = []
175
+ for episode in veri.get("episodes"):
176
+ episode["name"] = veri["title"] + f" | {episode.get('number')}. Bölüm"
177
+
178
+ ep_model = Episode(
179
+ season = 1,
180
+ episode = episode.get("number"),
181
+ title = f"{episode.get('number')}. Bölüm",
182
+ url = json.dumps(episode),
183
+ )
184
+
185
+ episodes.append(ep_model)
186
+ subtitles = [
187
+ Subtitle(
188
+ name = subtitle.get("language"),
189
+ url = subtitle.get("url"),
190
+ )
191
+ for subtitle in episode.get("subtitles")
192
+ ]
193
+
194
+ self._data[ep_model.url] = {
195
+ "ext_name" : self.name,
196
+ "name" : f"{ep_model.title}",
197
+ "referer" : "https://shorten.com/tr",
198
+ "subtitles" : subtitles
199
+ }
200
+
201
+ return SeriesInfo(
202
+ url = url,
203
+ poster = veri.get("image"),
204
+ title = veri.get("title"),
205
+ description = veri.get("description"),
206
+ tags = [genre.get("static_key") for genre in veri.get("categories")],
207
+ rating = 0,
208
+ year = 0,
209
+ actors = [],
210
+ episodes = episodes,
211
+ )
212
+
213
+ async def load_links(self, url: str) -> list[str]:
214
+ return [url]
215
+
216
+ async def play(self, name: str, url: str, referer: str, subtitles: list[Subtitle]):
217
+ veri = json.loads(url)
218
+ name = veri.get("name")
219
+ url = await self.hls_decode_video(veri.get("hls"))
220
+ subtitles = [
221
+ Subtitle(
222
+ name = subtitle.get("language"),
223
+ url = subtitle.get("url"),
224
+ )
225
+ for subtitle in veri.get("subtitles")
226
+ ]
227
+ extract_result = ExtractResult(name=name, url=url, referer=referer, subtitles=subtitles)
228
+ self.media_handler.title = name
229
+ self.media_handler.play_media(extract_result)
@@ -62,6 +62,7 @@ class SineWix(PluginBase):
62
62
  episodes.append(ep_model)
63
63
 
64
64
  self._data[ep_model.url] = {
65
+ "ext_name" : self.name,
65
66
  "name" : f"{ep_model.season}. Sezon {ep_model.episode}. Bölüm - {ep_model.title}",
66
67
  "referer" : self.main_url,
67
68
  "subtitles" : []
@@ -93,8 +94,8 @@ class SineWix(PluginBase):
93
94
  for video in veri.get("videos"):
94
95
  video_link = video.get("link").split("_blank\">")[-1]
95
96
  self._data[video_link] = {
96
- "name" : f"{self.name} | {title}",
97
97
  "ext_name" : self.name,
98
+ "name" : f"{self.name} | {title}",
98
99
  "referer" : self.main_url,
99
100
  "subtitles" : []
100
101
  }
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: KekikStream
3
- Version: 0.8.7
3
+ Version: 0.9.0
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
@@ -41,18 +41,19 @@ KekikStream/Extractors/VidMoly.py,sha256=BKJgk60GomFYiLFsRQSR2sOYP105Aix5y5XLazB
41
41
  KekikStream/Extractors/VidMoxy.py,sha256=_K6BA7Uo59DA3ty_tsayCUZjXmRoDBTghekVNXiuZ7g,1800
42
42
  KekikStream/Extractors/VideoSeyred.py,sha256=otyGi1zdY_JPrXJjoZjesCQDiOkxFdaWiXQ9mOmrygA,1780
43
43
  KekikStream/Plugins/DiziBox.py,sha256=i_73VNXk2eM7xTg-6a0Xk2Yts2c9grWbRVVHhxFgoic,5935
44
- KekikStream/Plugins/DiziYou.py,sha256=XxcTPckzQofSnJ2OzFwKQ-06biUjxJ8M5zzoY758PRM,5382
44
+ KekikStream/Plugins/DiziYou.py,sha256=zvhdJzjGEHosS_kIqXCc3aRJPESsP-BZ6FzhokThCjs,5382
45
45
  KekikStream/Plugins/Dizilla.py,sha256=evWYvETw1c4RY0GB5P20cB_I_U7ZxzzvnG7RLNGJRPs,4258
46
46
  KekikStream/Plugins/FilmMakinesi.py,sha256=rz8TQeL41PJbeEmksgPHIhp6J-4vbSCBTeEH0ukExz4,2822
47
47
  KekikStream/Plugins/FullHDFilmizlesene.py,sha256=Fa0gRP_NoMfPC8HIKRxERjQVOv8Fyb-ayMJ2EooZ7BE,3080
48
48
  KekikStream/Plugins/JetFilmizle.py,sha256=Gu4Ums-88x7jNKAtKkdSXyMaOyLv0_Kb6jnomhAWhM0,3916
49
49
  KekikStream/Plugins/RecTV.py,sha256=7hxlt3Rvm1gV2lF6dFLOxiK_CjNng_7a02l0YkMuNZc,4886
50
50
  KekikStream/Plugins/SezonlukDizi.py,sha256=5BZVzQ2eQtymHxO0bzjA2ho4FFNahPFQly4hoHuH8lo,4441
51
- KekikStream/Plugins/SineWix.py,sha256=VvFeAS2-Y-KJ1Od16yZjUJLiESwsBBGb2GNG3BLLupU,4806
51
+ KekikStream/Plugins/Shorten.py,sha256=C539XC6VUk-FxZixyNDfPpYhO8mZAvhwEGhtOtLl0aY,8946
52
+ KekikStream/Plugins/SineWix.py,sha256=WxlGoE8GMWr7S7Htu_Bh_OP4qIav1igHLJ3GWzP8ttQ,4859
52
53
  KekikStream/Plugins/UgurFilm.py,sha256=yYXee5uxwNnPqFJZ6s6cRkmUyqS3Vv8x-iesPalc4j4,2930
53
- KekikStream-0.8.7.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
54
- KekikStream-0.8.7.dist-info/METADATA,sha256=9nQ_kJBmqSz9O7kR7sUWHXbw1X3HfHG3eABwQKDlUwQ,4226
55
- KekikStream-0.8.7.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
56
- KekikStream-0.8.7.dist-info/entry_points.txt,sha256=dFwdiTx8djyehI0Gsz-rZwjAfZzUzoBSrmzRu9ubjJc,50
57
- KekikStream-0.8.7.dist-info/top_level.txt,sha256=DNmGJDXl27Drdfobrak8KYLmocW_uznVYFJOzcjUgmY,12
58
- KekikStream-0.8.7.dist-info/RECORD,,
54
+ KekikStream-0.9.0.dist-info/LICENSE,sha256=OXLcl0T2SZ8Pmy2_dmlvKuetivmyPd5m1q-Gyd-zaYY,35149
55
+ KekikStream-0.9.0.dist-info/METADATA,sha256=H2sh8-Y1nQQpyEZTyzaGz-E4vnei23WyLyCp1DvIp8s,4226
56
+ KekikStream-0.9.0.dist-info/WHEEL,sha256=In9FTNxeP60KnTkGw7wk6mJPYd_dQSjEZmXdBdMCI-8,91
57
+ KekikStream-0.9.0.dist-info/entry_points.txt,sha256=dFwdiTx8djyehI0Gsz-rZwjAfZzUzoBSrmzRu9ubjJc,50
58
+ KekikStream-0.9.0.dist-info/top_level.txt,sha256=DNmGJDXl27Drdfobrak8KYLmocW_uznVYFJOzcjUgmY,12
59
+ KekikStream-0.9.0.dist-info/RECORD,,