KekikStream 1.8.1__tar.gz → 1.8.2__tar.gz
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-1.8.1 → kekikstream-1.8.2}/KekikStream/Plugins/DiziPal.py +1 -1
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream/Plugins/DiziYou.py +40 -11
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream/Plugins/Dizilla.py +8 -5
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream/Plugins/FilmBip.py +1 -1
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream/Plugins/RoketDizi.py +76 -37
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream.egg-info/PKG-INFO +1 -1
- {kekikstream-1.8.1 → kekikstream-1.8.2}/PKG-INFO +1 -1
- {kekikstream-1.8.1 → kekikstream-1.8.2}/setup.py +1 -1
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream/CLI/__init__.py +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream/CLI/pypi_kontrol.py +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream/Core/Extractor/ExtractorBase.py +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream/Core/Extractor/ExtractorLoader.py +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream/Core/Extractor/ExtractorManager.py +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream/Core/Extractor/ExtractorModels.py +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream/Core/Media/MediaHandler.py +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream/Core/Media/MediaManager.py +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream/Core/Plugin/PluginBase.py +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream/Core/Plugin/PluginLoader.py +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream/Core/Plugin/PluginManager.py +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream/Core/Plugin/PluginModels.py +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream/Core/UI/UIManager.py +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream/Core/__init__.py +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream/Extractors/CloseLoad.py +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream/Extractors/ContentX.py +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream/Extractors/DzenRu.py +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream/Extractors/ExPlay.py +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream/Extractors/FirePlayer.py +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream/Extractors/FourCX.py +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream/Extractors/FourPichive.py +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream/Extractors/FourPlayRu.py +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream/Extractors/HDPlayerSystem.py +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream/Extractors/HDStreamAble.py +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream/Extractors/Hotlinger.py +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream/Extractors/JetTv.py +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream/Extractors/MailRu.py +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream/Extractors/MixPlayHD.py +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream/Extractors/MixTiger.py +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream/Extractors/MolyStream.py +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream/Extractors/Odnoklassniki.py +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream/Extractors/OkRuHTTP.py +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream/Extractors/OkRuSSL.py +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream/Extractors/PeaceMakerst.py +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream/Extractors/Pichive.py +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream/Extractors/PixelDrain.py +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream/Extractors/PlayRu.py +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream/Extractors/PlayerFilmIzle.py +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream/Extractors/RapidVid.py +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream/Extractors/SetPlay.py +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream/Extractors/SetPrime.py +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream/Extractors/SibNet.py +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream/Extractors/Sobreatsesuyp.py +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream/Extractors/TRsTX.py +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream/Extractors/TauVideo.py +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream/Extractors/TurboImgz.py +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream/Extractors/TurkeyPlayer.py +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream/Extractors/VidHide.py +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream/Extractors/VidMoly.py +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream/Extractors/VidMolyMe.py +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream/Extractors/VidMoxy.py +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream/Extractors/VidPapi.py +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream/Extractors/VideoSeyred.py +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream/Extractors/YildizKisaFilm.py +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream/Plugins/DiziBox.py +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream/Plugins/FilmMakinesi.py +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream/Plugins/FilmModu.py +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream/Plugins/FullHDFilm.py +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream/Plugins/FullHDFilmizlesene.py +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream/Plugins/HDFilmCehennemi.py +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream/Plugins/JetFilmizle.py +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream/Plugins/KultFilmler.py +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream/Plugins/RecTV.py +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream/Plugins/SelcukFlix.py +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream/Plugins/SezonlukDizi.py +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream/Plugins/SineWix.py +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream/Plugins/Sinefy.py +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream/Plugins/SinemaCX.py +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream/Plugins/Sinezy.py +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream/Plugins/SuperFilmGeldi.py +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream/Plugins/UgurFilm.py +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream/__init__.py +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream/__main__.py +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream/requirements.txt +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream.egg-info/SOURCES.txt +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream.egg-info/dependency_links.txt +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream.egg-info/entry_points.txt +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream.egg-info/requires.txt +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/KekikStream.egg-info/top_level.txt +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/LICENSE +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/MANIFEST.in +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/README.md +0 -0
- {kekikstream-1.8.1 → kekikstream-1.8.2}/setup.cfg +0 -0
|
@@ -9,7 +9,7 @@ class DiziPal(PluginBase):
|
|
|
9
9
|
language = "tr"
|
|
10
10
|
main_url = "https://dizipal1223.com"
|
|
11
11
|
favicon = f"https://www.google.com/s2/favicons?domain={main_url}&sz=64"
|
|
12
|
-
description = "
|
|
12
|
+
description = "dizipal güncel, dizipal yeni ve gerçek adresi. dizipal en yeni dizi ve filmleri güvenli ve hızlı şekilde sunar."
|
|
13
13
|
|
|
14
14
|
main_page = {
|
|
15
15
|
f"{main_url}/diziler/son-bolumler" : "Son Bölümler",
|
|
@@ -53,7 +53,7 @@ class DiziYou(PluginBase):
|
|
|
53
53
|
SearchResult(
|
|
54
54
|
title = afis.css("div#categorytitle a::text").get().strip(),
|
|
55
55
|
url = self.fix_url(afis.css("div#categorytitle a::attr(href)").get()),
|
|
56
|
-
poster = self.fix_url(afis.css("img::attr(src)").get())
|
|
56
|
+
poster = self.fix_url(afis.css("img::attr(src)").get() or afis.css("img::attr(data-src)").get())
|
|
57
57
|
)
|
|
58
58
|
for afis in secici.css("div.incontent div#list-series")
|
|
59
59
|
]
|
|
@@ -63,8 +63,19 @@ class DiziYou(PluginBase):
|
|
|
63
63
|
istek = await self.httpx.get(url)
|
|
64
64
|
secici = Selector(istek.text)
|
|
65
65
|
|
|
66
|
-
title
|
|
67
|
-
|
|
66
|
+
# Title - div.title h1 içinde
|
|
67
|
+
title_raw = secici.css("div.title h1::text").get()
|
|
68
|
+
title = title_raw.strip() if title_raw else ""
|
|
69
|
+
|
|
70
|
+
# Fallback: Eğer title boşsa URL'den çıkar (telif kısıtlaması olan sayfalar için)
|
|
71
|
+
if not title:
|
|
72
|
+
# URL'den slug'ı al: https://www.diziyou.one/jasmine/ -> jasmine -> Jasmine
|
|
73
|
+
slug = url.rstrip('/').split('/')[-1]
|
|
74
|
+
title = slug.replace('-', ' ').title()
|
|
75
|
+
|
|
76
|
+
# Poster
|
|
77
|
+
poster_raw = secici.css("div.category_image img::attr(src)").get()
|
|
78
|
+
poster = self.fix_url(poster_raw) if poster_raw else ""
|
|
68
79
|
year = secici.xpath("//span[contains(., 'Yapım Yılı')]/following-sibling::text()[1]").get()
|
|
69
80
|
description = secici.css("div.diziyou_desc::text").get()
|
|
70
81
|
if description:
|
|
@@ -75,13 +86,21 @@ class DiziYou(PluginBase):
|
|
|
75
86
|
actors = [actor.strip() for actor in _actors.split(",")] if _actors else []
|
|
76
87
|
|
|
77
88
|
episodes = []
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
|
|
81
|
-
|
|
89
|
+
# Episodes - bolumust her bölüm için bir <a> içinde
|
|
90
|
+
# :has() parsel'de çalışmıyor, XPath kullanıyoruz
|
|
91
|
+
for link in secici.xpath('//a[div[@class="bolumust"]]'):
|
|
92
|
+
ep_name_raw = link.css("div.baslik::text").get()
|
|
93
|
+
if not ep_name_raw:
|
|
94
|
+
continue
|
|
95
|
+
ep_name = ep_name_raw.strip()
|
|
96
|
+
|
|
97
|
+
ep_href = self.fix_url(link.css("::attr(href)").get())
|
|
98
|
+
if not ep_href:
|
|
82
99
|
continue
|
|
83
100
|
|
|
84
|
-
|
|
101
|
+
# Bölüm ismi varsa al
|
|
102
|
+
ep_name_raw_clean = link.css("div.bolumismi::text").get()
|
|
103
|
+
ep_name_clean = ep_name_raw_clean.strip().replace("(", "").replace(")", "").strip() if ep_name_raw_clean else ep_name
|
|
85
104
|
|
|
86
105
|
ep_episode = re.search(r"(\d+)\. Bölüm", ep_name)[1]
|
|
87
106
|
ep_season = re.search(r"(\d+)\. Sezon", ep_name)[1]
|
|
@@ -112,9 +131,19 @@ class DiziYou(PluginBase):
|
|
|
112
131
|
istek = await self.httpx.get(url)
|
|
113
132
|
secici = Selector(istek.text)
|
|
114
133
|
|
|
115
|
-
|
|
116
|
-
|
|
117
|
-
|
|
134
|
+
# Title ve episode name - None kontrolü ekle
|
|
135
|
+
item_title_raw = secici.css("div.title h1::text").get()
|
|
136
|
+
item_title = item_title_raw.strip() if item_title_raw else ""
|
|
137
|
+
|
|
138
|
+
ep_name_raw = secici.css("div#bolum-ismi::text").get()
|
|
139
|
+
ep_name = ep_name_raw.strip() if ep_name_raw else ""
|
|
140
|
+
|
|
141
|
+
# Player src'den item_id çıkar
|
|
142
|
+
player_src = secici.css("iframe#diziyouPlayer::attr(src)").get()
|
|
143
|
+
if not player_src:
|
|
144
|
+
return [] # Player bulunamadıysa boş liste döndür
|
|
145
|
+
|
|
146
|
+
item_id = player_src.split("/")[-1].replace(".html", "")
|
|
118
147
|
|
|
119
148
|
subtitles = []
|
|
120
149
|
stream_urls = []
|
|
@@ -16,7 +16,6 @@ class Dizilla(PluginBase):
|
|
|
16
16
|
|
|
17
17
|
main_page = {
|
|
18
18
|
f"{main_url}/tum-bolumler" : "Altyazılı Bölümler",
|
|
19
|
-
f"{main_url}/dublaj-bolumler" : "Dublaj Bölümler",
|
|
20
19
|
f"{main_url}/dizi-turu/aile" : "Aile",
|
|
21
20
|
f"{main_url}/dizi-turu/aksiyon" : "Aksiyon",
|
|
22
21
|
f"{main_url}/dizi-turu/bilim-kurgu" : "Bilim Kurgu",
|
|
@@ -35,11 +34,11 @@ class Dizilla(PluginBase):
|
|
|
35
34
|
ana_sayfa.extend([
|
|
36
35
|
MainPageResult(
|
|
37
36
|
category = category,
|
|
38
|
-
title = veri.css("
|
|
39
|
-
url = self.fix_url(veri.css("::attr(href)").get()),
|
|
37
|
+
title = veri.css("span.font-normal::text").get(),
|
|
38
|
+
url = self.fix_url(veri.css("a::attr(href)").get()),
|
|
40
39
|
poster = self.fix_url(veri.css("img::attr(src)").get() or veri.css("img::attr(data-src)").get())
|
|
41
40
|
)
|
|
42
|
-
for veri in secici.css("
|
|
41
|
+
for veri in secici.css("span.watchlistitem-")
|
|
43
42
|
])
|
|
44
43
|
else:
|
|
45
44
|
for veri in secici.css("div.tab-content > div.grid a"):
|
|
@@ -127,7 +126,11 @@ class Dizilla(PluginBase):
|
|
|
127
126
|
poster = self.fix_url(veri.get("image"))
|
|
128
127
|
description = veri.get("description")
|
|
129
128
|
year = veri.get("datePublished").split("-")[0]
|
|
130
|
-
|
|
129
|
+
|
|
130
|
+
# Tags extraction from page content (h3 tag)
|
|
131
|
+
tags_raw = secici.css("h3.text-white.opacity-60::text").get()
|
|
132
|
+
tags = [t.strip() for t in tags_raw.split(",")] if tags_raw else []
|
|
133
|
+
|
|
131
134
|
rating = veri.get("aggregateRating", {}).get("ratingValue")
|
|
132
135
|
actors = [actor.get("name") for actor in veri.get("actor", []) if actor.get("name")]
|
|
133
136
|
|
|
@@ -8,7 +8,7 @@ class FilmBip(PluginBase):
|
|
|
8
8
|
language = "tr"
|
|
9
9
|
main_url = "https://filmbip.com"
|
|
10
10
|
favicon = f"https://www.google.com/s2/favicons?domain={main_url}&sz=64"
|
|
11
|
-
description = "
|
|
11
|
+
description = "FilmBip adlı film sitemizde Full HD film izle. Yerli ve yabancı filmleri Türkçe dublaj veya altyazılı şekilde 1080p yüksek kalite film izle"
|
|
12
12
|
|
|
13
13
|
main_page = {
|
|
14
14
|
f"{main_url}/filmler/SAYFA" : "Yeni Filmler",
|
|
@@ -2,12 +2,14 @@
|
|
|
2
2
|
|
|
3
3
|
from KekikStream.Core import PluginBase, MainPageResult, SearchResult, SeriesInfo, Episode, MovieInfo
|
|
4
4
|
from parsel import Selector
|
|
5
|
-
import re, base64, json
|
|
5
|
+
import re, base64, json
|
|
6
6
|
|
|
7
7
|
class RoketDizi(PluginBase):
|
|
8
8
|
name = "RoketDizi"
|
|
9
9
|
lang = "tr"
|
|
10
10
|
main_url = "https://roketdizi.to"
|
|
11
|
+
favicon = f"https://www.google.com/s2/favicons?domain={main_url}&sz=64"
|
|
12
|
+
description = "Türkiye'nin en tatlış yabancı dizi izleme sitesi. Türkçe dublaj, altyazılı, eski ve yeni yabancı dizilerin yanı sıra kore (asya) dizileri izleyebilirsiniz."
|
|
11
13
|
|
|
12
14
|
# Domain doğrulama ve anti-bot mekanizmaları var
|
|
13
15
|
requires_cffi = True
|
|
@@ -45,45 +47,50 @@ class RoketDizi(PluginBase):
|
|
|
45
47
|
return results
|
|
46
48
|
|
|
47
49
|
async def search(self, query: str) -> list[SearchResult]:
|
|
48
|
-
# Get Cookies and Keys
|
|
49
|
-
main_req = await self.cffi.get(self.main_url)
|
|
50
|
-
sel = Selector(main_req.text)
|
|
51
|
-
|
|
52
|
-
c_key = sel.css("input[name='cKey']::attr(value)").get()
|
|
53
|
-
c_value = sel.css("input[name='cValue']::attr(value)").get()
|
|
54
|
-
|
|
55
50
|
post_url = f"{self.main_url}/api/bg/searchContent?searchterm={query}"
|
|
56
51
|
|
|
57
52
|
headers = {
|
|
58
53
|
"Accept" : "application/json, text/javascript, */*; q=0.01",
|
|
59
54
|
"X-Requested-With" : "XMLHttpRequest",
|
|
60
55
|
"Referer" : f"{self.main_url}/",
|
|
61
|
-
"CNT" : "vakTR"
|
|
62
56
|
}
|
|
63
|
-
|
|
64
|
-
data = {}
|
|
65
|
-
if c_key and c_value:
|
|
66
|
-
data = {"cKey": c_key, "cValue": c_value}
|
|
67
57
|
|
|
68
|
-
search_req = await self.cffi.post(post_url,
|
|
58
|
+
search_req = await self.cffi.post(post_url, headers=headers)
|
|
69
59
|
|
|
70
60
|
try:
|
|
71
61
|
resp_json = search_req.json()
|
|
72
|
-
|
|
62
|
+
|
|
63
|
+
# Response is base64 encoded!
|
|
64
|
+
if not resp_json.get("success"):
|
|
65
|
+
return []
|
|
66
|
+
|
|
67
|
+
encoded_response = resp_json.get("response", "")
|
|
68
|
+
if not encoded_response:
|
|
69
|
+
return []
|
|
70
|
+
|
|
71
|
+
# Decode base64
|
|
72
|
+
decoded = base64.b64decode(encoded_response).decode('utf-8')
|
|
73
|
+
data = json.loads(decoded)
|
|
74
|
+
|
|
75
|
+
if not data.get("state"):
|
|
73
76
|
return []
|
|
74
77
|
|
|
75
|
-
html_content = resp_json.get("html", "").strip()
|
|
76
|
-
sel_results = Selector(html_content)
|
|
77
|
-
|
|
78
78
|
results = []
|
|
79
|
-
|
|
79
|
+
result_items = data.get("result", [])
|
|
80
80
|
|
|
81
|
-
for
|
|
82
|
-
|
|
83
|
-
|
|
84
|
-
|
|
85
|
-
|
|
86
|
-
|
|
81
|
+
for item in result_items:
|
|
82
|
+
title = item.get("object_name", "")
|
|
83
|
+
slug = item.get("used_slug", "")
|
|
84
|
+
poster = item.get("object_poster_url", "")
|
|
85
|
+
|
|
86
|
+
if title and slug:
|
|
87
|
+
# Construct full URL from slug
|
|
88
|
+
full_url = f"{self.main_url}/{slug}"
|
|
89
|
+
results.append(SearchResult(
|
|
90
|
+
title = title.strip(),
|
|
91
|
+
url = full_url,
|
|
92
|
+
poster = self.fix_url(poster) if poster else None
|
|
93
|
+
))
|
|
87
94
|
|
|
88
95
|
return results
|
|
89
96
|
|
|
@@ -99,14 +106,41 @@ class RoketDizi(PluginBase):
|
|
|
99
106
|
poster = sel.css("div.w-full.page-top img::attr(src)").get()
|
|
100
107
|
description = sel.css("div.mt-2.text-sm::text").get()
|
|
101
108
|
|
|
102
|
-
|
|
109
|
+
# Tags - genre bilgileri (Detaylar bölümünde)
|
|
110
|
+
tags = []
|
|
111
|
+
genre_text = sel.css("h3.text-white.opacity-90::text").get()
|
|
112
|
+
if genre_text:
|
|
113
|
+
tags = [t.strip() for t in genre_text.split(",")]
|
|
103
114
|
|
|
104
|
-
|
|
105
|
-
if tags:
|
|
106
|
-
tags = [t.strip() for t in tags.split(",")]
|
|
107
|
-
|
|
115
|
+
# Rating
|
|
108
116
|
rating = sel.css("div.flex.items-center span.text-white.text-sm::text").get()
|
|
109
|
-
|
|
117
|
+
|
|
118
|
+
# Year ve Actors - Detaylar (Details) bölümünden
|
|
119
|
+
year = None
|
|
120
|
+
actors = []
|
|
121
|
+
|
|
122
|
+
# Detaylar bölümündeki tüm flex-col div'leri al
|
|
123
|
+
detail_items = sel.css("div.flex.flex-col")
|
|
124
|
+
for item in detail_items:
|
|
125
|
+
# Label ve value yapısı: span.text-base ve span.text-sm.opacity-90
|
|
126
|
+
label = item.css("span.text-base::text").get()
|
|
127
|
+
value = item.css("span.text-sm.opacity-90::text").get()
|
|
128
|
+
|
|
129
|
+
if label and value:
|
|
130
|
+
label = label.strip()
|
|
131
|
+
value = value.strip()
|
|
132
|
+
|
|
133
|
+
# Yayın tarihi (yıl)
|
|
134
|
+
if label == "Yayın tarihi":
|
|
135
|
+
# "16 Ekim 2018" formatından yılı çıkar
|
|
136
|
+
year_match = re.search(r'\d{4}', value)
|
|
137
|
+
if year_match:
|
|
138
|
+
year = year_match.group()
|
|
139
|
+
|
|
140
|
+
# Yaratıcılar veya Oyuncular
|
|
141
|
+
elif label in ["Yaratıcılar", "Oyuncular"]:
|
|
142
|
+
if value:
|
|
143
|
+
actors.append(value)
|
|
110
144
|
|
|
111
145
|
# Check urls for episodes
|
|
112
146
|
all_urls = re.findall(r'"url":"([^"]*)"', resp.text)
|
|
@@ -114,22 +148,27 @@ class RoketDizi(PluginBase):
|
|
|
114
148
|
|
|
115
149
|
episodes = []
|
|
116
150
|
if is_series:
|
|
117
|
-
|
|
151
|
+
# Dict kullanarak duplicate'leri önle ama sıralı tut
|
|
152
|
+
episodes_dict = {}
|
|
118
153
|
for u in all_urls:
|
|
119
|
-
if "bolum" in u and u not in
|
|
120
|
-
seen_eps.add(u)
|
|
154
|
+
if "bolum" in u and u not in episodes_dict:
|
|
121
155
|
season_match = re.search(r'/sezon-(\d+)', u)
|
|
122
156
|
ep_match = re.search(r'/bolum-(\d+)', u)
|
|
123
157
|
|
|
124
158
|
season = int(season_match.group(1)) if season_match else 1
|
|
125
159
|
episode_num = int(ep_match.group(1)) if ep_match else 1
|
|
126
160
|
|
|
127
|
-
|
|
161
|
+
# Key olarak (season, episode) tuple kullan
|
|
162
|
+
key = (season, episode_num)
|
|
163
|
+
episodes_dict[key] = Episode(
|
|
128
164
|
season = season,
|
|
129
165
|
episode = episode_num,
|
|
130
|
-
title = f"{season}. Sezon {episode_num}. Bölüm",
|
|
166
|
+
title = f"{season}. Sezon {episode_num}. Bölüm",
|
|
131
167
|
url = self.fix_url(u)
|
|
132
|
-
)
|
|
168
|
+
)
|
|
169
|
+
|
|
170
|
+
# Sıralı liste oluştur
|
|
171
|
+
episodes = [episodes_dict[key] for key in sorted(episodes_dict.keys())]
|
|
133
172
|
|
|
134
173
|
return SeriesInfo(
|
|
135
174
|
title = title,
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: KekikStream
|
|
3
|
-
Version: 1.8.
|
|
3
|
+
Version: 1.8.2
|
|
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
|
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: KekikStream
|
|
3
|
-
Version: 1.8.
|
|
3
|
+
Version: 1.8.2
|
|
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
|
|
@@ -6,7 +6,7 @@ from io import open
|
|
|
6
6
|
setup(
|
|
7
7
|
# ? Genel Bilgiler
|
|
8
8
|
name = "KekikStream",
|
|
9
|
-
version = "1.8.
|
|
9
|
+
version = "1.8.2",
|
|
10
10
|
url = "https://github.com/keyiflerolsun/KekikStream",
|
|
11
11
|
description = "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ı",
|
|
12
12
|
keywords = ["KekikStream", "KekikAkademi", "keyiflerolsun"],
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|
|
File without changes
|