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.
- KekikStream/Plugins/DiziYou.py +1 -1
- KekikStream/Plugins/Shorten.py +229 -0
- KekikStream/Plugins/SineWix.py +2 -1
- {KekikStream-0.8.7.dist-info → KekikStream-0.9.0.dist-info}/METADATA +1 -1
- {KekikStream-0.8.7.dist-info → KekikStream-0.9.0.dist-info}/RECORD +9 -8
- {KekikStream-0.8.7.dist-info → KekikStream-0.9.0.dist-info}/LICENSE +0 -0
- {KekikStream-0.8.7.dist-info → KekikStream-0.9.0.dist-info}/WHEEL +0 -0
- {KekikStream-0.8.7.dist-info → KekikStream-0.9.0.dist-info}/entry_points.txt +0 -0
- {KekikStream-0.8.7.dist-info → KekikStream-0.9.0.dist-info}/top_level.txt +0 -0
KekikStream/Plugins/DiziYou.py
CHANGED
@@ -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)
|
KekikStream/Plugins/SineWix.py
CHANGED
@@ -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.
|
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=
|
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/
|
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.
|
54
|
-
KekikStream-0.
|
55
|
-
KekikStream-0.
|
56
|
-
KekikStream-0.
|
57
|
-
KekikStream-0.
|
58
|
-
KekikStream-0.
|
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,,
|
File without changes
|
File without changes
|
File without changes
|
File without changes
|