KekikStream 1.2.9__tar.gz → 1.3.1__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.
Files changed (71) hide show
  1. {kekikstream-1.2.9 → kekikstream-1.3.1}/KekikStream/Core/__init__.py +2 -0
  2. kekikstream-1.3.1/KekikStream/Extractors/CloseLoad.py +47 -0
  3. kekikstream-1.3.1/KekikStream/Helpers/Unpack.py +75 -0
  4. {kekikstream-1.2.9 → kekikstream-1.3.1}/KekikStream/Plugins/DiziBox.py +7 -7
  5. {kekikstream-1.2.9 → kekikstream-1.3.1}/KekikStream/Plugins/DiziYou.py +42 -3
  6. {kekikstream-1.2.9 → kekikstream-1.3.1}/KekikStream/Plugins/Dizilla.py +6 -1
  7. kekikstream-1.3.1/KekikStream/Plugins/FilmMakinesi.py +112 -0
  8. {kekikstream-1.2.9 → kekikstream-1.3.1}/KekikStream/Plugins/FullHDFilmizlesene.py +4 -2
  9. {kekikstream-1.2.9 → kekikstream-1.3.1}/KekikStream/Plugins/HDFilmCehennemi.py +4 -1
  10. {kekikstream-1.2.9 → kekikstream-1.3.1}/KekikStream/Plugins/JetFilmizle.py +4 -1
  11. {kekikstream-1.2.9 → kekikstream-1.3.1}/KekikStream/Plugins/RecTV.py +4 -3
  12. {kekikstream-1.2.9 → kekikstream-1.3.1}/KekikStream/Plugins/SezonlukDizi.py +4 -1
  13. {kekikstream-1.2.9 → kekikstream-1.3.1}/KekikStream/Plugins/Shorten.py +4 -2
  14. {kekikstream-1.2.9 → kekikstream-1.3.1}/KekikStream/Plugins/SineWix.py +5 -1
  15. {kekikstream-1.2.9 → kekikstream-1.3.1}/KekikStream/Plugins/UgurFilm.py +4 -1
  16. {kekikstream-1.2.9 → kekikstream-1.3.1}/KekikStream.egg-info/PKG-INFO +1 -1
  17. {kekikstream-1.2.9 → kekikstream-1.3.1}/KekikStream.egg-info/SOURCES.txt +1 -0
  18. {kekikstream-1.2.9 → kekikstream-1.3.1}/PKG-INFO +1 -1
  19. {kekikstream-1.2.9 → kekikstream-1.3.1}/setup.py +1 -1
  20. kekikstream-1.2.9/KekikStream/Extractors/CloseLoad.py +0 -31
  21. kekikstream-1.2.9/KekikStream/Plugins/FilmMakinesi.py +0 -65
  22. {kekikstream-1.2.9 → kekikstream-1.3.1}/KekikStream/CLI/__init__.py +0 -0
  23. {kekikstream-1.2.9 → kekikstream-1.3.1}/KekikStream/CLI/pypi_kontrol.py +0 -0
  24. {kekikstream-1.2.9 → kekikstream-1.3.1}/KekikStream/Core/Extractor/ExtractorBase.py +0 -0
  25. {kekikstream-1.2.9 → kekikstream-1.3.1}/KekikStream/Core/Extractor/ExtractorLoader.py +0 -0
  26. {kekikstream-1.2.9 → kekikstream-1.3.1}/KekikStream/Core/Extractor/ExtractorManager.py +0 -0
  27. {kekikstream-1.2.9 → kekikstream-1.3.1}/KekikStream/Core/Extractor/ExtractorModels.py +0 -0
  28. {kekikstream-1.2.9 → kekikstream-1.3.1}/KekikStream/Core/Media/MediaHandler.py +0 -0
  29. {kekikstream-1.2.9 → kekikstream-1.3.1}/KekikStream/Core/Media/MediaManager.py +0 -0
  30. {kekikstream-1.2.9 → kekikstream-1.3.1}/KekikStream/Core/Plugin/PluginBase.py +0 -0
  31. {kekikstream-1.2.9 → kekikstream-1.3.1}/KekikStream/Core/Plugin/PluginLoader.py +0 -0
  32. {kekikstream-1.2.9 → kekikstream-1.3.1}/KekikStream/Core/Plugin/PluginManager.py +0 -0
  33. {kekikstream-1.2.9 → kekikstream-1.3.1}/KekikStream/Core/Plugin/PluginModels.py +0 -0
  34. {kekikstream-1.2.9 → kekikstream-1.3.1}/KekikStream/Core/UI/UIManager.py +0 -0
  35. {kekikstream-1.2.9 → kekikstream-1.3.1}/KekikStream/Extractors/ContentX.py +0 -0
  36. {kekikstream-1.2.9 → kekikstream-1.3.1}/KekikStream/Extractors/FourCX.py +0 -0
  37. {kekikstream-1.2.9 → kekikstream-1.3.1}/KekikStream/Extractors/FourPichive.py +0 -0
  38. {kekikstream-1.2.9 → kekikstream-1.3.1}/KekikStream/Extractors/FourPlayRu.py +0 -0
  39. {kekikstream-1.2.9 → kekikstream-1.3.1}/KekikStream/Extractors/HDStreamAble.py +0 -0
  40. {kekikstream-1.2.9 → kekikstream-1.3.1}/KekikStream/Extractors/Hotlinger.py +0 -0
  41. {kekikstream-1.2.9 → kekikstream-1.3.1}/KekikStream/Extractors/MailRu.py +0 -0
  42. {kekikstream-1.2.9 → kekikstream-1.3.1}/KekikStream/Extractors/MixPlayHD.py +0 -0
  43. {kekikstream-1.2.9 → kekikstream-1.3.1}/KekikStream/Extractors/MolyStream.py +0 -0
  44. {kekikstream-1.2.9 → kekikstream-1.3.1}/KekikStream/Extractors/Odnoklassniki.py +0 -0
  45. {kekikstream-1.2.9 → kekikstream-1.3.1}/KekikStream/Extractors/OkRuHTTP.py +0 -0
  46. {kekikstream-1.2.9 → kekikstream-1.3.1}/KekikStream/Extractors/OkRuSSL.py +0 -0
  47. {kekikstream-1.2.9 → kekikstream-1.3.1}/KekikStream/Extractors/PeaceMakerst.py +0 -0
  48. {kekikstream-1.2.9 → kekikstream-1.3.1}/KekikStream/Extractors/Pichive.py +0 -0
  49. {kekikstream-1.2.9 → kekikstream-1.3.1}/KekikStream/Extractors/PixelDrain.py +0 -0
  50. {kekikstream-1.2.9 → kekikstream-1.3.1}/KekikStream/Extractors/PlayRu.py +0 -0
  51. {kekikstream-1.2.9 → kekikstream-1.3.1}/KekikStream/Extractors/RapidVid.py +0 -0
  52. {kekikstream-1.2.9 → kekikstream-1.3.1}/KekikStream/Extractors/SibNet.py +0 -0
  53. {kekikstream-1.2.9 → kekikstream-1.3.1}/KekikStream/Extractors/Sobreatsesuyp.py +0 -0
  54. {kekikstream-1.2.9 → kekikstream-1.3.1}/KekikStream/Extractors/TRsTX.py +0 -0
  55. {kekikstream-1.2.9 → kekikstream-1.3.1}/KekikStream/Extractors/TauVideo.py +0 -0
  56. {kekikstream-1.2.9 → kekikstream-1.3.1}/KekikStream/Extractors/TurboImgz.py +0 -0
  57. {kekikstream-1.2.9 → kekikstream-1.3.1}/KekikStream/Extractors/VidMoly.py +0 -0
  58. {kekikstream-1.2.9 → kekikstream-1.3.1}/KekikStream/Extractors/VidMolyMe.py +0 -0
  59. {kekikstream-1.2.9 → kekikstream-1.3.1}/KekikStream/Extractors/VidMoxy.py +0 -0
  60. {kekikstream-1.2.9 → kekikstream-1.3.1}/KekikStream/Extractors/VideoSeyred.py +0 -0
  61. {kekikstream-1.2.9 → kekikstream-1.3.1}/KekikStream/__init__.py +0 -0
  62. {kekikstream-1.2.9 → kekikstream-1.3.1}/KekikStream/__main__.py +0 -0
  63. {kekikstream-1.2.9 → kekikstream-1.3.1}/KekikStream/requirements.txt +0 -0
  64. {kekikstream-1.2.9 → kekikstream-1.3.1}/KekikStream.egg-info/dependency_links.txt +0 -0
  65. {kekikstream-1.2.9 → kekikstream-1.3.1}/KekikStream.egg-info/entry_points.txt +0 -0
  66. {kekikstream-1.2.9 → kekikstream-1.3.1}/KekikStream.egg-info/requires.txt +0 -0
  67. {kekikstream-1.2.9 → kekikstream-1.3.1}/KekikStream.egg-info/top_level.txt +0 -0
  68. {kekikstream-1.2.9 → kekikstream-1.3.1}/LICENSE +0 -0
  69. {kekikstream-1.2.9 → kekikstream-1.3.1}/MANIFEST.in +0 -0
  70. {kekikstream-1.2.9 → kekikstream-1.3.1}/README.md +0 -0
  71. {kekikstream-1.2.9 → kekikstream-1.3.1}/setup.cfg +0 -0
@@ -1,5 +1,7 @@
1
1
  # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
2
 
3
+ from Kekik.cache import kekik_cache
4
+
3
5
  from .UI.UIManager import UIManager
4
6
 
5
7
  from .Plugin.PluginManager import PluginManager
@@ -0,0 +1,47 @@
1
+ # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
+
3
+ from KekikStream.Core import ExtractorBase, ExtractResult
4
+ from KekikStream.Helpers.Unpack import unpack
5
+ import re, base64
6
+
7
+ def get_m3u_link(data: str) -> str:
8
+ first = base64.b64decode(data)
9
+ first_reversed = first[::-1]
10
+
11
+ second = base64.b64decode(first_reversed)
12
+
13
+ parts = second.decode('utf-8').split("|")
14
+ if len(parts) < 2:
15
+ raise ValueError("Decoded data has an unexpected format.")
16
+
17
+ return parts[1]
18
+
19
+ def extract_data(raw_script: str) -> str:
20
+ pattern = re.compile(r'return result\}var .*?=.*?\("(.*?)"\)')
21
+ if match := pattern.search(raw_script):
22
+ return match[1]
23
+ else:
24
+ raise Exception("data not found")
25
+
26
+ class CloseLoadExtractor(ExtractorBase):
27
+ name = "CloseLoad"
28
+ main_url = "https://closeload.filmmakinesi.de"
29
+
30
+ async def extract(self, url, referer=None) -> ExtractResult:
31
+ if referer:
32
+ self.httpx.headers.update({"Referer": referer})
33
+
34
+ istek = await self.httpx.get(url)
35
+ istek.raise_for_status()
36
+
37
+ eval_func = re.compile(r'\s*(eval\(function[\s\S].*)\s*').findall(istek.text)[0]
38
+ m3u_link = get_m3u_link(extract_data(unpack(eval_func)))
39
+ print(m3u_link)
40
+
41
+ await self.close()
42
+ return ExtractResult(
43
+ name = self.name,
44
+ url = m3u_link,
45
+ referer = self.main_url,
46
+ subtitles = []
47
+ )
@@ -0,0 +1,75 @@
1
+ # ! https://github.com/keyiflerolsun/Kekik-cloudstream/blob/master/FilmMakinesi/src/main/kotlin/com/keyiflerolsun/CloseLoadUnpacker.kt
2
+
3
+ import re
4
+
5
+ packed_extract_regex = re.compile(
6
+ r"\}\('(.*)',\s*(\d+),\s*(\d+),\s*'(.*?)'\.split\('\|'\)",
7
+ re.IGNORECASE | re.MULTILINE
8
+ )
9
+
10
+ unpack_replace_regex = re.compile(
11
+ r"\b\w+\b",
12
+ re.IGNORECASE | re.MULTILINE
13
+ )
14
+
15
+ class Unbaser:
16
+ ALPHABET = {
17
+ 52: "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP",
18
+ 54: "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQR",
19
+ 62: "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
20
+ 95: " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"
21
+ }
22
+
23
+ def __init__(self, base: int):
24
+ self.base = base
25
+
26
+ if base > 62:
27
+ self.selector = 95
28
+ elif base > 54:
29
+ self.selector = 62
30
+ elif base > 52:
31
+ self.selector = 54
32
+ else:
33
+ self.selector = 52
34
+
35
+ self.dict = {char: idx for idx, char in enumerate(Unbaser.ALPHABET[self.selector])}
36
+
37
+ def unbase(self, value: str) -> int:
38
+ if 2 <= self.base <= 36:
39
+ try:
40
+ return int(value, self.base)
41
+ except ValueError:
42
+ return 0
43
+ else:
44
+ result = 0
45
+
46
+ for index, c in enumerate(reversed(value)):
47
+ digit = self.dict.get(c, 0)
48
+ result += digit * (self.base ** index)
49
+
50
+ return result
51
+
52
+ def unpack(script_block: str) -> str:
53
+ match = packed_extract_regex.search(script_block)
54
+ if not match:
55
+ raise ValueError("Packed script not found")
56
+
57
+ payload, radix_str, count_str, symtab_str = match.groups()
58
+
59
+ radix = int(radix_str)
60
+ count = int(count_str)
61
+ symtab = symtab_str.split('|')
62
+
63
+ if len(symtab) != count:
64
+ raise ValueError("there is an error in the packed script")
65
+
66
+ unbaser = Unbaser(radix)
67
+
68
+ def replacer(match_obj):
69
+ word = match_obj.group(0)
70
+ index = unbaser.unbase(word)
71
+ replacement = symtab[index] if index < len(symtab) else word
72
+
73
+ return replacement or word
74
+
75
+ return unpack_replace_regex.sub(replacer, payload)
@@ -1,6 +1,6 @@
1
1
  # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
2
 
3
- from KekikStream.Core import PluginBase, MainPageResult, SearchResult, SeriesInfo, Episode
3
+ from KekikStream.Core import kekik_cache, PluginBase, MainPageResult, SearchResult, SeriesInfo, Episode
4
4
  from Kekik.Sifreleme import CryptoJS
5
5
  from parsel import Selector
6
6
  import re, urllib.parse, base64, contextlib, asyncio
@@ -40,14 +40,10 @@ class DiziBox(PluginBase):
40
40
  f"{main_url}/dizi-arsivi/page/SAYFA/?tur[0]=yarisma&yil&imdb" : "Yarışma"
41
41
  }
42
42
 
43
+ @kekik_cache(ttl=60*60)
43
44
  async def get_main_page(self, page: int, url: str, category: str) -> list[MainPageResult]:
44
45
  istek = await self.httpx.get(
45
- url = f"{url.replace('SAYFA', str(page))}",
46
- cookies = {
47
- "LockUser" : "true",
48
- "isTrustedUser" : "true",
49
- "dbxu" : "1722403730363"
50
- },
46
+ url = f"{url.replace('SAYFA', str(page))}",
51
47
  follow_redirects = True
52
48
  )
53
49
  secici = Selector(istek.text)
@@ -62,6 +58,7 @@ class DiziBox(PluginBase):
62
58
  for veri in secici.css("article.detailed-article")
63
59
  ]
64
60
 
61
+ @kekik_cache(ttl=60*60)
65
62
  async def search(self, query: str) -> list[SearchResult]:
66
63
  self.httpx.cookies.update({
67
64
  "LockUser" : "true",
@@ -80,6 +77,7 @@ class DiziBox(PluginBase):
80
77
  for item in secici.css("article.detailed-article")
81
78
  ]
82
79
 
80
+ @kekik_cache(ttl=60*60)
83
81
  async def load_item(self, url: str) -> SeriesInfo:
84
82
  istek = await self.httpx.get(url)
85
83
  secici = Selector(istek.text)
@@ -126,6 +124,7 @@ class DiziBox(PluginBase):
126
124
  actors = actors,
127
125
  )
128
126
 
127
+ @kekik_cache(ttl=60*60)
129
128
  async def _iframe_decode(self, name:str, iframe_link:str, referer:str) -> list[str]:
130
129
  results = []
131
130
 
@@ -172,6 +171,7 @@ class DiziBox(PluginBase):
172
171
 
173
172
  return results
174
173
 
174
+ @kekik_cache(ttl=15*60)
175
175
  async def load_links(self, url: str) -> list[str]:
176
176
  istek = await self.httpx.get(url)
177
177
  secici = Selector(istek.text)
@@ -1,13 +1,50 @@
1
1
  # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
2
 
3
- from KekikStream.Core import PluginBase, SearchResult, SeriesInfo, Episode, Subtitle, ExtractResult
3
+ from KekikStream.Core import kekik_cache, PluginBase, MainPageResult, SearchResult, SeriesInfo, Episode, Subtitle, ExtractResult
4
4
  from parsel import Selector
5
5
  import re
6
6
 
7
7
  class DiziYou(PluginBase):
8
- name = "DiziYou"
9
- main_url = "https://www.diziyou1.com"
8
+ name = "DiziYou"
9
+ language = "tr"
10
+ main_url = "https://www.diziyou1.com"
11
+ favicon = f"https://www.google.com/s2/favicons?domain={main_url}&sz=64"
12
+ description = "Diziyou en kaliteli Türkçe dublaj ve altyazılı yabancı dizi izleme sitesidir. Güncel ve efsanevi dizileri 1080p Full HD kalitede izlemek için hemen tıkla!"
13
+
14
+ main_page = {
15
+ f"{main_url}/dizi-arsivi/page/SAYFA/?tur=Aile" : "Aile",
16
+ f"{main_url}/dizi-arsivi/page/SAYFA/?tur=Aksiyon" : "Aksiyon",
17
+ f"{main_url}/dizi-arsivi/page/SAYFA/?tur=Animasyon" : "Animasyon",
18
+ f"{main_url}/dizi-arsivi/page/SAYFA/?tur=Belgesel" : "Belgesel",
19
+ f"{main_url}/dizi-arsivi/page/SAYFA/?tur=Bilim+Kurgu" : "Bilim Kurgu",
20
+ f"{main_url}/dizi-arsivi/page/SAYFA/?tur=Dram" : "Dram",
21
+ f"{main_url}/dizi-arsivi/page/SAYFA/?tur=Fantazi" : "Fantazi",
22
+ f"{main_url}/dizi-arsivi/page/SAYFA/?tur=Gerilim" : "Gerilim",
23
+ f"{main_url}/dizi-arsivi/page/SAYFA/?tur=Gizem" : "Gizem",
24
+ f"{main_url}/dizi-arsivi/page/SAYFA/?tur=Komedi" : "Komedi",
25
+ f"{main_url}/dizi-arsivi/page/SAYFA/?tur=Korku" : "Korku",
26
+ f"{main_url}/dizi-arsivi/page/SAYFA/?tur=Macera" : "Macera",
27
+ f"{main_url}/dizi-arsivi/page/SAYFA/?tur=Sava%C5%9F" : "Savaş",
28
+ f"{main_url}/dizi-arsivi/page/SAYFA/?tur=Su%C3%A7" : "Suç",
29
+ f"{main_url}/dizi-arsivi/page/SAYFA/?tur=Vah%C5%9Fi+Bat%C4%B1" : "Vahşi Batı"
30
+ }
31
+
32
+ @kekik_cache(ttl=60*60)
33
+ async def get_main_page(self, page: int, url: str, category: str) -> list[MainPageResult]:
34
+ istek = await self.httpx.get(f"{url.replace('SAYFA', str(page))}")
35
+ secici = Selector(istek.text)
36
+
37
+ return [
38
+ MainPageResult(
39
+ category = category,
40
+ title = veri.css("div#categorytitle a::text").get(),
41
+ url = self.fix_url(veri.css("div#categorytitle a::attr(href)").get()),
42
+ poster = self.fix_url(veri.css("img::attr(src)").get()),
43
+ )
44
+ for veri in secici.css("div.single-item")
45
+ ]
10
46
 
47
+ @kekik_cache(ttl=60*60)
11
48
  async def search(self, query: str) -> list[SearchResult]:
12
49
  istek = await self.httpx.get(f"{self.main_url}/?s={query}")
13
50
  secici = Selector(istek.text)
@@ -21,6 +58,7 @@ class DiziYou(PluginBase):
21
58
  for afis in secici.css("div.incontent div#list-series")
22
59
  ]
23
60
 
61
+ @kekik_cache(ttl=60*60)
24
62
  async def load_item(self, url: str) -> SeriesInfo:
25
63
  istek = await self.httpx.get(url)
26
64
  secici = Selector(istek.text)
@@ -67,6 +105,7 @@ class DiziYou(PluginBase):
67
105
  actors = actors
68
106
  )
69
107
 
108
+ @kekik_cache(ttl=15*60)
70
109
  async def load_links(self, url: str) -> list[str]:
71
110
  istek = await self.httpx.get(url)
72
111
  secici = Selector(istek.text)
@@ -1,6 +1,6 @@
1
1
  # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
2
 
3
- from KekikStream.Core import PluginBase, MainPageResult, SearchResult, SeriesInfo, Episode
3
+ from KekikStream.Core import kekik_cache, PluginBase, MainPageResult, SearchResult, SeriesInfo, Episode
4
4
  from parsel import Selector
5
5
  from json import loads
6
6
  from urllib.parse import urlparse, urlunparse
@@ -22,6 +22,7 @@ class Dizilla(PluginBase):
22
22
  f"{main_url}/dizi-turu/komedi" : "Komedi"
23
23
  }
24
24
 
25
+ @kekik_cache(ttl=60*60)
25
26
  async def get_main_page(self, page: int, url: str, category: str) -> list[MainPageResult]:
26
27
  istek = await self.httpx.get(url)
27
28
  secici = Selector(istek.text)
@@ -64,6 +65,7 @@ class Dizilla(PluginBase):
64
65
 
65
66
  return ana_sayfa
66
67
 
68
+ @kekik_cache(ttl=60*60)
67
69
  async def search(self, query: str) -> list[SearchResult]:
68
70
  ilk_istek = await self.httpx.get(self.main_url)
69
71
  ilk_secici = Selector(ilk_istek.text)
@@ -99,6 +101,7 @@ class Dizilla(PluginBase):
99
101
  for veri in arama_veri
100
102
  ]
101
103
 
104
+ @kekik_cache(ttl=60*60)
102
105
  async def url_base_degis(self, eski_url:str, yeni_base:str) -> str:
103
106
  parsed_url = urlparse(eski_url)
104
107
  parsed_yeni_base = urlparse(yeni_base)
@@ -109,6 +112,7 @@ class Dizilla(PluginBase):
109
112
 
110
113
  return urlunparse(yeni_url)
111
114
 
115
+ @kekik_cache(ttl=60*60)
112
116
  async def load_item(self, url: str) -> SeriesInfo:
113
117
  istek = await self.httpx.get(url)
114
118
  secici = Selector(istek.text)
@@ -148,6 +152,7 @@ class Dizilla(PluginBase):
148
152
  actors = actors
149
153
  )
150
154
 
155
+ @kekik_cache(ttl=15*60)
151
156
  async def load_links(self, url: str) -> list[str]:
152
157
  istek = await self.httpx.get(url)
153
158
  secici = Selector(istek.text)
@@ -0,0 +1,112 @@
1
+ # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
+
3
+ from KekikStream.Core import kekik_cache, PluginBase, MainPageResult, SearchResult, MovieInfo
4
+ from parsel import Selector
5
+
6
+ class FilmMakinesi(PluginBase):
7
+ name = "FilmMakinesi"
8
+ language = "tr"
9
+ main_url = "https://filmmakinesi.de"
10
+ favicon = f"https://www.google.com/s2/favicons?domain={main_url}&sz=64"
11
+ description = "Diziyou en kaliteli Türkçe dublaj ve altyazılı yabancı dizi izleme sitesidir. Güncel ve efsanevi dizileri 1080p Full HD kalitede izlemek için hemen tıkla!"
12
+
13
+ main_page = {
14
+ f"{main_url}/page/" : "Son Filmler",
15
+ f"{main_url}/film-izle/olmeden-izlenmesi-gerekenler/page/" : "Ölmeden İzle",
16
+ f"{main_url}/film-izle/aksiyon-filmleri-izle/page/" : "Aksiyon",
17
+ f"{main_url}/film-izle/bilim-kurgu-filmi-izle/page/" : "Bilim Kurgu",
18
+ f"{main_url}/film-izle/macera-filmleri/page/" : "Macera",
19
+ f"{main_url}/film-izle/komedi-filmi-izle/page/" : "Komedi",
20
+ f"{main_url}/film-izle/romantik-filmler-izle/page/" : "Romantik",
21
+ f"{main_url}/film-izle/belgesel/page/" : "Belgesel",
22
+ f"{main_url}/film-izle/fantastik-filmler-izle/page/" : "Fantastik",
23
+ f"{main_url}/film-izle/polisiye-filmleri-izle/page/" : "Polisiye Suç",
24
+ f"{main_url}/film-izle/korku-filmleri-izle-hd/page/" : "Korku",
25
+ f"{main_url}/film-izle/savas/page/" : "Tarihi ve Savaş",
26
+ f"{main_url}/film-izle/gerilim-filmleri-izle/page/" : "Gerilim Heyecan",
27
+ f"{main_url}/film-izle/gizemli/page/" : "Gizem",
28
+ f"{main_url}/film-izle/aile-filmleri/page/" : "Aile",
29
+ f"{main_url}/film-izle/animasyon-filmler/page/" : "Animasyon",
30
+ f"{main_url}/film-izle/western/page/" : "Western",
31
+ f"{main_url}/film-izle/biyografi/page/" : "Biyografik",
32
+ f"{main_url}/film-izle/dram/page/" : "Dram",
33
+ f"{main_url}/film-izle/muzik/page/" : "Müzik",
34
+ f"{main_url}/film-izle/spor/page/" : "Spor"
35
+ }
36
+
37
+ @kekik_cache(ttl=60*60)
38
+ async def get_main_page(self, page: int, url: str, category: str) -> list[MainPageResult]:
39
+ istek = self.cloudscraper.get(f"{url}{page}")
40
+ secici = Selector(istek.text)
41
+
42
+ veriler = secici.css("section#film_posts article") if "/film-izle/" in url else secici.css("section#film_posts div.tooltip")
43
+
44
+ return [
45
+ MainPageResult(
46
+ category = category,
47
+ title = veri.css("h6 a::text").get(),
48
+ url = self.fix_url(veri.css("h6 a::attr(href)").get()),
49
+ poster = self.fix_url(veri.css("img::attr(data-src)").get() or veri.css("img::attr(src)").get()),
50
+ )
51
+ for veri in veriler
52
+ ]
53
+
54
+ @kekik_cache(ttl=60*60)
55
+ async def search(self, query: str) -> list[SearchResult]:
56
+ istek = await self.httpx.get(f"{self.main_url}/?s={query}")
57
+ secici = Selector(istek.text)
58
+
59
+ results = []
60
+ for article in secici.css("section#film_posts article"):
61
+ title = article.css("h6 a::text").get()
62
+ href = article.css("h6 a::attr(href)").get()
63
+ poster = article.css("img::attr(data-src)").get() or article.css("img::attr(src)").get()
64
+
65
+ if title and href:
66
+ results.append(
67
+ SearchResult(
68
+ title = title.strip(),
69
+ url = self.fix_url(href.strip()),
70
+ poster = self.fix_url(poster.strip()) if poster else None,
71
+ )
72
+ )
73
+
74
+ return results
75
+
76
+ @kekik_cache(ttl=60*60)
77
+ async def load_item(self, url: str) -> MovieInfo:
78
+ istek = await self.httpx.get(url)
79
+ secici = Selector(istek.text)
80
+
81
+ title = secici.css("h1.single_h1 a::text").get().strip()
82
+ poster = secici.css("[property='og:image']::attr(content)").get().strip()
83
+ description = secici.css("section#film_single article p:last-of-type::text").get().strip()
84
+ tags = secici.css("dt:contains('Tür:') + dd a::text").get().strip()
85
+ rating = secici.css("dt:contains('IMDB Puanı:') + dd::text").get().strip()
86
+ year = secici.css("dt:contains('Yapım Yılı:') + dd a::text").get().strip()
87
+ actors = secici.css("dt:contains('Oyuncular:') + dd::text").get().strip()
88
+ duration = secici.css("dt:contains('Film Süresi:') + dd time::attr(datetime)").get().strip()
89
+
90
+ duration_minutes = 0
91
+ if duration and duration.startswith("PT") and duration.endswith("M"):
92
+ duration_minutes = int(duration[2:-1])
93
+
94
+ return MovieInfo(
95
+ url = url,
96
+ poster = self.fix_url(poster),
97
+ title = title,
98
+ description = description,
99
+ tags = tags,
100
+ rating = rating,
101
+ year = year,
102
+ actors = actors,
103
+ duration = duration_minutes
104
+ )
105
+
106
+ @kekik_cache(ttl=15*60)
107
+ async def load_links(self, url: str) -> list[str]:
108
+ istek = await self.httpx.get(url)
109
+ secici = Selector(istek.text)
110
+
111
+ iframe_src = secici.css("div.player-div iframe::attr(src)").get() or secici.css("div.player-div iframe::attr(data-src)").get()
112
+ return [self.fix_url(iframe_src)] if iframe_src else []
@@ -1,7 +1,6 @@
1
1
  # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
2
 
3
- from KekikStream.CLI import konsol
4
- from KekikStream.Core import PluginBase, SearchResult, MovieInfo
3
+ from KekikStream.Core import kekik_cache, PluginBase, SearchResult, MovieInfo
5
4
  from parsel import Selector
6
5
  from Kekik.Sifreleme import StringCodec
7
6
  import json, re
@@ -10,6 +9,7 @@ class FullHDFilmizlesene(PluginBase):
10
9
  name = "FullHDFilmizlesene"
11
10
  main_url = "https://www.fullhdfilmizlesene.de"
12
11
 
12
+ @kekik_cache(ttl=60*60)
13
13
  async def search(self, query: str) -> list[SearchResult]:
14
14
  istek = await self.httpx.get(f"{self.main_url}/arama/{query}")
15
15
  secici = Selector(istek.text)
@@ -31,6 +31,7 @@ class FullHDFilmizlesene(PluginBase):
31
31
 
32
32
  return results
33
33
 
34
+ @kekik_cache(ttl=60*60)
34
35
  async def load_item(self, url: str) -> MovieInfo:
35
36
  istek = await self.httpx.get(url)
36
37
  secici = Selector(istek.text)
@@ -56,6 +57,7 @@ class FullHDFilmizlesene(PluginBase):
56
57
  duration = duration
57
58
  )
58
59
 
60
+ @kekik_cache(ttl=15*60)
59
61
  async def load_links(self, url: str) -> list[str]:
60
62
  istek = await self.httpx.get(url)
61
63
  secici = Selector(istek.text)
@@ -1,6 +1,6 @@
1
1
  # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
2
 
3
- from KekikStream.Core import PluginBase, SearchResult, MovieInfo, ExtractResult, Subtitle
3
+ from KekikStream.Core import kekik_cache, PluginBase, SearchResult, MovieInfo, ExtractResult, Subtitle
4
4
  from parsel import Selector
5
5
  import random, string
6
6
 
@@ -8,6 +8,7 @@ class HDFilmCehennemi(PluginBase):
8
8
  name = "HDFilmCehennemi"
9
9
  main_url = "https://www.hdfilmcehennemi.nl"
10
10
 
11
+ @kekik_cache(ttl=60*60)
11
12
  async def search(self, query: str) -> list[SearchResult]:
12
13
  istek = await self.httpx.get(
13
14
  url = f"{self.main_url}/search?q={query}",
@@ -36,6 +37,7 @@ class HDFilmCehennemi(PluginBase):
36
37
 
37
38
  return results
38
39
 
40
+ @kekik_cache(ttl=60*60)
39
41
  async def load_item(self, url: str) -> MovieInfo:
40
42
  istek = await self.httpx.get(url, headers = {"Referer": f"{self.main_url}/"})
41
43
  secici = Selector(istek.text)
@@ -70,6 +72,7 @@ class HDFilmCehennemi(PluginBase):
70
72
  def generate_random_cookie(self):
71
73
  return "".join(random.choices(string.ascii_letters + string.digits, k=16))
72
74
 
75
+ @kekik_cache(ttl=15*60)
73
76
  async def load_links(self, url: str) -> list[str]:
74
77
  self._data.clear()
75
78
 
@@ -1,12 +1,13 @@
1
1
  # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
2
 
3
- from KekikStream.Core import PluginBase, SearchResult, MovieInfo
3
+ from KekikStream.Core import kekik_cache, PluginBase, SearchResult, MovieInfo
4
4
  from parsel import Selector
5
5
 
6
6
  class JetFilmizle(PluginBase):
7
7
  name = "JetFilmizle"
8
8
  main_url = "https://jetfilmizle.io"
9
9
 
10
+ @kekik_cache(ttl=60*60)
10
11
  async def search(self, query: str) -> list[SearchResult]:
11
12
  istek = await self.httpx.post(
12
13
  url = f"{self.main_url}/filmara.php",
@@ -32,6 +33,7 @@ class JetFilmizle(PluginBase):
32
33
 
33
34
  return results
34
35
 
36
+ @kekik_cache(ttl=60*60)
35
37
  async def load_item(self, url: str) -> MovieInfo:
36
38
  istek = await self.httpx.get(url)
37
39
  secici = Selector(istek.text)
@@ -55,6 +57,7 @@ class JetFilmizle(PluginBase):
55
57
  actors = actors
56
58
  )
57
59
 
60
+ @kekik_cache(ttl=15*60)
58
61
  async def load_links(self, url: str) -> list[str]:
59
62
  istek = await self.httpx.get(url)
60
63
  secici = Selector(istek.text)
@@ -1,12 +1,10 @@
1
1
  # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
2
 
3
- from KekikStream.CLI import konsol
4
- from KekikStream.Core import PluginBase, SearchResult, MovieInfo, Episode, SeriesInfo, ExtractResult, Subtitle
3
+ from KekikStream.Core import kekik_cache, PluginBase, SearchResult, MovieInfo, Episode, SeriesInfo, ExtractResult, Subtitle
5
4
  from httpx import AsyncClient
6
5
  from json import dumps, loads
7
6
  import re
8
7
 
9
-
10
8
  class RecTV(PluginBase):
11
9
  name = "RecTV"
12
10
  main_url = "https://a.prectv35.sbs"
@@ -15,6 +13,7 @@ class RecTV(PluginBase):
15
13
  http2 = AsyncClient(http2=True)
16
14
  http2.headers.update({"user-agent": "okhttp/4.12.0"})
17
15
 
16
+ kekik_cache(ttl=60*60)
18
17
  async def search(self, query: str) -> list[SearchResult]:
19
18
  self.media_handler.headers.update({"User-Agent": "googleusercontent"})
20
19
 
@@ -36,6 +35,7 @@ class RecTV(PluginBase):
36
35
  for veri in tum_veri
37
36
  ]
38
37
 
38
+ kekik_cache(ttl=60*60)
39
39
  async def load_item(self, url: str) -> MovieInfo:
40
40
  veri = loads(url)
41
41
 
@@ -86,6 +86,7 @@ class RecTV(PluginBase):
86
86
  actors = []
87
87
  )
88
88
 
89
+ kekik_cache(ttl=15*60)
89
90
  async def load_links(self, url: str) -> list[str]:
90
91
  try:
91
92
  veri = loads(url)
@@ -1,12 +1,13 @@
1
1
  # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
2
 
3
- from KekikStream.Core import PluginBase, SearchResult, SeriesInfo, Episode
3
+ from KekikStream.Core import kekik_cache, PluginBase, SearchResult, SeriesInfo, Episode
4
4
  from parsel import Selector
5
5
 
6
6
  class SezonlukDizi(PluginBase):
7
7
  name = "SezonlukDizi"
8
8
  main_url = "https://sezonlukdizi6.com"
9
9
 
10
+ kekik_cache(ttl=60*60)
10
11
  async def search(self, query: str) -> list[SearchResult]:
11
12
  istek = await self.httpx.get(f"{self.main_url}/diziler.asp?adi={query}")
12
13
  secici = Selector(istek.text)
@@ -20,6 +21,7 @@ class SezonlukDizi(PluginBase):
20
21
  for afis in secici.css("div.afis a.column")
21
22
  ]
22
23
 
24
+ kekik_cache(ttl=60*60)
23
25
  async def load_item(self, url: str) -> SeriesInfo:
24
26
  istek = await self.httpx.get(url)
25
27
  secici = Selector(istek.text)
@@ -71,6 +73,7 @@ class SezonlukDizi(PluginBase):
71
73
  actors = actors
72
74
  )
73
75
 
76
+ kekik_cache(ttl=15*60)
74
77
  async def load_links(self, url: str) -> list[str]:
75
78
  istek = await self.httpx.get(url)
76
79
  secici = Selector(istek.text)
@@ -1,7 +1,6 @@
1
1
  # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
2
 
3
- from KekikStream.Core import PluginBase, SearchResult, MovieInfo, Episode, SeriesInfo, ExtractResult, Subtitle
4
-
3
+ from KekikStream.Core import kekik_cache, PluginBase, SearchResult, MovieInfo, Episode, SeriesInfo, ExtractResult, Subtitle
5
4
  from Kekik.unicode_tr import unicode_tr
6
5
  import re, json, base64
7
6
 
@@ -156,6 +155,7 @@ class Shorten(PluginBase):
156
155
 
157
156
  return veriler["data"]
158
157
 
158
+ kekik_cache(ttl=60*60)
159
159
  async def search(self, query: str) -> list[SearchResult]:
160
160
  veriler = await self.raw_diziler()
161
161
 
@@ -168,6 +168,7 @@ class Shorten(PluginBase):
168
168
  for veri in veriler
169
169
  ]
170
170
 
171
+ kekik_cache(ttl=60*60)
171
172
  async def load_item(self, url: str) -> MovieInfo:
172
173
  veri = await self.bolumler(url)
173
174
 
@@ -204,6 +205,7 @@ class Shorten(PluginBase):
204
205
  episodes = episodes,
205
206
  )
206
207
 
208
+ kekik_cache(ttl=15*60)
207
209
  async def load_links(self, url: str) -> list[str]:
208
210
  return [url]
209
211
 
@@ -1,6 +1,6 @@
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, Episode, SeriesInfo, ExtractResult, Subtitle
3
+ from KekikStream.Core import kekik_cache, PluginBase, MainPageResult, SearchResult, MovieInfo, Episode, SeriesInfo, ExtractResult, Subtitle
4
4
 
5
5
  class SineWix(PluginBase):
6
6
  name = "SineWix"
@@ -34,6 +34,7 @@ class SineWix(PluginBase):
34
34
  f"{main_url}/sinewix/movies/36" : "Tarih",
35
35
  }
36
36
 
37
+ kekik_cache(ttl=60*60)
37
38
  async def get_main_page(self, page: int, url: str, category: str) -> list[MainPageResult]:
38
39
  istek = await self.httpx.get(f"{url}/{page}")
39
40
  veriler = istek.json()
@@ -48,6 +49,7 @@ class SineWix(PluginBase):
48
49
  for veri in veriler.get("data")
49
50
  ]
50
51
 
52
+ kekik_cache(ttl=60*60)
51
53
  async def search(self, query: str) -> list[SearchResult]:
52
54
  istek = await self.httpx.get(f"{self.main_url}/sinewix/search/{query}")
53
55
 
@@ -60,6 +62,7 @@ class SineWix(PluginBase):
60
62
  for veri in istek.json().get("search")
61
63
  ]
62
64
 
65
+ kekik_cache(ttl=60*60)
63
66
  async def load_item(self, url: str) -> MovieInfo | SeriesInfo:
64
67
  item_type = url.split("?type=")[-1].split("&id=")[0]
65
68
  item_id = url.split("&id=")[-1]
@@ -122,6 +125,7 @@ class SineWix(PluginBase):
122
125
  episodes = episodes,
123
126
  )
124
127
 
128
+ kekik_cache(ttl=15*60)
125
129
  async def load_links(self, url: str) -> list[str]:
126
130
  if not url.startswith(self.main_url):
127
131
  return [url]
@@ -1,12 +1,13 @@
1
1
  # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
2
 
3
- from KekikStream.Core import PluginBase, SearchResult, MovieInfo
3
+ from KekikStream.Core import kekik_cache, PluginBase, SearchResult, MovieInfo
4
4
  from parsel import Selector
5
5
 
6
6
  class UgurFilm(PluginBase):
7
7
  name = "UgurFilm"
8
8
  main_url = "https://ugurfilm8.com"
9
9
 
10
+ kekik_cache(ttl=60*60)
10
11
  async def search(self, query: str) -> list[SearchResult]:
11
12
  istek = await self.httpx.get(f"{self.main_url}/?s={query}")
12
13
  secici = Selector(istek.text)
@@ -28,6 +29,7 @@ class UgurFilm(PluginBase):
28
29
 
29
30
  return results
30
31
 
32
+ kekik_cache(ttl=60*60)
31
33
  async def load_item(self, url: str) -> MovieInfo:
32
34
  istek = await self.httpx.get(url)
33
35
  secici = Selector(istek.text)
@@ -49,6 +51,7 @@ class UgurFilm(PluginBase):
49
51
  actors = actors,
50
52
  )
51
53
 
54
+ kekik_cache(ttl=15*60)
52
55
  async def load_links(self, url: str) -> list[str]:
53
56
  istek = await self.httpx.get(url)
54
57
  secici = Selector(istek.text)
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: KekikStream
3
- Version: 1.2.9
3
+ Version: 1.3.1
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
@@ -52,6 +52,7 @@ KekikStream/Extractors/VidMoly.py
52
52
  KekikStream/Extractors/VidMolyMe.py
53
53
  KekikStream/Extractors/VidMoxy.py
54
54
  KekikStream/Extractors/VideoSeyred.py
55
+ KekikStream/Helpers/Unpack.py
55
56
  KekikStream/Plugins/DiziBox.py
56
57
  KekikStream/Plugins/DiziYou.py
57
58
  KekikStream/Plugins/Dizilla.py
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.2
2
2
  Name: KekikStream
3
- Version: 1.2.9
3
+ Version: 1.3.1
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.2.9",
9
+ version = "1.3.1",
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"],
@@ -1,31 +0,0 @@
1
- # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
-
3
- from KekikStream.Core import ExtractorBase, ExtractResult
4
- from parsel import Selector
5
- from base64 import b64decode
6
-
7
- class CloseLoadExtractor(ExtractorBase):
8
- name = "CloseLoad"
9
- main_url = "https://closeload.filmmakinesi.de"
10
-
11
- async def extract(self, url, referer=None) -> ExtractResult:
12
- if referer:
13
- self.httpx.headers.update({"Referer": referer})
14
-
15
- istek = await self.httpx.get(url)
16
- istek.raise_for_status()
17
-
18
- secici = Selector(istek.text)
19
- atob = secici.re(r"aHR0[0-9a-zA-Z+/=]*")
20
- if not atob:
21
- raise ValueError("Base64 kodu bulunamadı.")
22
-
23
- m3u_link = b64decode(f"{atob[0]}===").decode("utf-8")
24
-
25
- await self.close()
26
- return ExtractResult(
27
- name = self.name,
28
- url = m3u_link,
29
- referer = self.main_url,
30
- subtitles = []
31
- )
@@ -1,65 +0,0 @@
1
- # Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
2
-
3
- from KekikStream.Core import PluginBase, SearchResult, MovieInfo
4
- from parsel import Selector
5
-
6
- class FilmMakinesi(PluginBase):
7
- name = "FilmMakinesi"
8
- main_url = "https://filmmakinesi.de"
9
-
10
- async def search(self, query: str) -> list[SearchResult]:
11
- istek = await self.httpx.get(f"{self.main_url}/?s={query}")
12
- secici = Selector(istek.text)
13
-
14
- results = []
15
- for article in secici.css("section#film_posts article"):
16
- title = article.css("h6 a::text").get()
17
- href = article.css("h6 a::attr(href)").get()
18
- poster = article.css("img::attr(data-src)").get() or article.css("img::attr(src)").get()
19
-
20
- if title and href:
21
- results.append(
22
- SearchResult(
23
- title = title.strip(),
24
- url = self.fix_url(href.strip()),
25
- poster = self.fix_url(poster.strip()) if poster else None,
26
- )
27
- )
28
-
29
- return results
30
-
31
- async def load_item(self, url: str) -> MovieInfo:
32
- istek = await self.httpx.get(url)
33
- secici = Selector(istek.text)
34
-
35
- title = secici.css("h1.single_h1 a::text").get().strip()
36
- poster = secici.css("[property='og:image']::attr(content)").get().strip()
37
- description = secici.css("section#film_single article p:last-of-type::text").get().strip()
38
- tags = secici.css("dt:contains('Tür:') + dd a::text").get().strip()
39
- rating = secici.css("dt:contains('IMDB Puanı:') + dd::text").get().strip()
40
- year = secici.css("dt:contains('Yapım Yılı:') + dd a::text").get().strip()
41
- actors = secici.css("dt:contains('Oyuncular:') + dd::text").get().strip()
42
- duration = secici.css("dt:contains('Film Süresi:') + dd time::attr(datetime)").get().strip()
43
-
44
- duration_minutes = 0
45
- if duration and duration.startswith("PT") and duration.endswith("M"):
46
- duration_minutes = int(duration[2:-1])
47
-
48
- return MovieInfo(
49
- url = url,
50
- poster = self.fix_url(poster),
51
- title = title,
52
- description = description,
53
- tags = tags,
54
- rating = rating,
55
- year = year,
56
- actors = actors,
57
- duration = duration_minutes
58
- )
59
-
60
- async def load_links(self, url: str) -> list[str]:
61
- istek = await self.httpx.get(url)
62
- secici = Selector(istek.text)
63
-
64
- iframe_src = secici.css("div.player-div iframe::attr(src)").get() or secici.css("div.player-div iframe::attr(data-src)").get()
65
- return [self.fix_url(iframe_src)] if iframe_src else []
File without changes
File without changes
File without changes
File without changes