Kekik 1.7.5__tar.gz → 1.7.9__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.
Potentially problematic release.
This version of Kekik might be problematic. Click here for more details.
- kekik-1.7.9/Kekik/Sifreleme/Packer.py +199 -0
- {kekik-1.7.5 → kekik-1.7.9}/Kekik/cache.py +169 -66
- {kekik-1.7.5 → kekik-1.7.9}/Kekik.egg-info/PKG-INFO +8 -2
- {kekik-1.7.5 → kekik-1.7.9}/PKG-INFO +8 -2
- {kekik-1.7.5 → kekik-1.7.9}/README.md +5 -0
- {kekik-1.7.5 → kekik-1.7.9}/setup.py +1 -1
- kekik-1.7.5/Kekik/Sifreleme/Packer.py +0 -62
- {kekik-1.7.5 → kekik-1.7.9}/Kekik/BIST.py +0 -0
- {kekik-1.7.5 → kekik-1.7.9}/Kekik/Domain2IP.py +0 -0
- {kekik-1.7.5 → kekik-1.7.9}/Kekik/Nesne.py +0 -0
- {kekik-1.7.5 → kekik-1.7.9}/Kekik/Sifreleme/AESManager.py +0 -0
- {kekik-1.7.5 → kekik-1.7.9}/Kekik/Sifreleme/CryptoJS.py +0 -0
- {kekik-1.7.5 → kekik-1.7.9}/Kekik/Sifreleme/HexCodec.py +0 -0
- {kekik-1.7.5 → kekik-1.7.9}/Kekik/Sifreleme/NaysHash.py +0 -0
- {kekik-1.7.5 → kekik-1.7.9}/Kekik/Sifreleme/StringCodec.py +0 -0
- {kekik-1.7.5 → kekik-1.7.9}/Kekik/Sifreleme/__init__.py +0 -0
- {kekik-1.7.5 → kekik-1.7.9}/Kekik/__init__.py +0 -0
- {kekik-1.7.5 → kekik-1.7.9}/Kekik/cli.py +0 -0
- {kekik-1.7.5 → kekik-1.7.9}/Kekik/csv2dict.py +0 -0
- {kekik-1.7.5 → kekik-1.7.9}/Kekik/dict2csv.py +0 -0
- {kekik-1.7.5 → kekik-1.7.9}/Kekik/dict2json.py +0 -0
- {kekik-1.7.5 → kekik-1.7.9}/Kekik/dosya2set.py +0 -0
- {kekik-1.7.5 → kekik-1.7.9}/Kekik/dosya_indir.py +0 -0
- {kekik-1.7.5 → kekik-1.7.9}/Kekik/hwid_kontrol.py +0 -0
- {kekik-1.7.5 → kekik-1.7.9}/Kekik/kisi_ver/__init__.py +0 -0
- {kekik-1.7.5 → kekik-1.7.9}/Kekik/kisi_ver/biyografiler.py +0 -0
- {kekik-1.7.5 → kekik-1.7.9}/Kekik/kisi_ver/isimler.py +0 -0
- {kekik-1.7.5 → kekik-1.7.9}/Kekik/kisi_ver/soyisimler.py +0 -0
- {kekik-1.7.5 → kekik-1.7.9}/Kekik/link_islemleri.py +0 -0
- {kekik-1.7.5 → kekik-1.7.9}/Kekik/list2html.py +0 -0
- {kekik-1.7.5 → kekik-1.7.9}/Kekik/liste_fetis.py +0 -0
- {kekik-1.7.5 → kekik-1.7.9}/Kekik/mail_gonder.py +0 -0
- {kekik-1.7.5 → kekik-1.7.9}/Kekik/okunabilir_byte.py +0 -0
- {kekik-1.7.5 → kekik-1.7.9}/Kekik/proxy_ver.py +0 -0
- {kekik-1.7.5 → kekik-1.7.9}/Kekik/qr_ver.py +0 -0
- {kekik-1.7.5 → kekik-1.7.9}/Kekik/ses_fetis.py +0 -0
- {kekik-1.7.5 → kekik-1.7.9}/Kekik/slugify.py +0 -0
- {kekik-1.7.5 → kekik-1.7.9}/Kekik/terminal_baslik.py +0 -0
- {kekik-1.7.5 → kekik-1.7.9}/Kekik/txt_fetis.py +0 -0
- {kekik-1.7.5 → kekik-1.7.9}/Kekik/unicode_tr.py +0 -0
- {kekik-1.7.5 → kekik-1.7.9}/Kekik/zaman_donustur.py +0 -0
- {kekik-1.7.5 → kekik-1.7.9}/Kekik.egg-info/SOURCES.txt +0 -0
- {kekik-1.7.5 → kekik-1.7.9}/Kekik.egg-info/dependency_links.txt +0 -0
- {kekik-1.7.5 → kekik-1.7.9}/Kekik.egg-info/entry_points.txt +0 -0
- {kekik-1.7.5 → kekik-1.7.9}/Kekik.egg-info/requires.txt +0 -0
- {kekik-1.7.5 → kekik-1.7.9}/Kekik.egg-info/top_level.txt +0 -0
- {kekik-1.7.5 → kekik-1.7.9}/LICENSE +0 -0
- {kekik-1.7.5 → kekik-1.7.9}/MANIFEST.in +0 -0
- {kekik-1.7.5 → kekik-1.7.9}/setup.cfg +0 -0
|
@@ -0,0 +1,199 @@
|
|
|
1
|
+
# ! Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
|
+
|
|
3
|
+
import re
|
|
4
|
+
|
|
5
|
+
class Packer:
|
|
6
|
+
"""
|
|
7
|
+
P.A.C.K.E.R. sıkıştırma ve çözme işlemleri için kapsamlı bir sınıf.
|
|
8
|
+
! » https://github.com/beautifier/js-beautify/blob/main/python/jsbeautifier/unpackers/packer.py
|
|
9
|
+
"""
|
|
10
|
+
|
|
11
|
+
# Regex kalıpları - daha gevşek, farklı varyasyonları yakalayabilecek şekilde
|
|
12
|
+
PACKED_PATTERN = re.compile(
|
|
13
|
+
r"\}\s*\(\s*['\"](.*?)['\"],\s*(\d+),\s*(\d+),\s*['\"](.+?)['\"]\.split\(['\"]\\?\|['\"]\)",
|
|
14
|
+
re.IGNORECASE | re.MULTILINE | re.DOTALL
|
|
15
|
+
)
|
|
16
|
+
|
|
17
|
+
# Alternatif regex pattern, farklı formatlarda paketlenmiş kodu yakalamak için
|
|
18
|
+
ALTERNATIVE_PATTERNS = [
|
|
19
|
+
# Standart pattern
|
|
20
|
+
re.compile(
|
|
21
|
+
r"\}\('(.*)',\s*(\d+),\s*(\d+),\s*'(.*?)'\.split\('\|'\)",
|
|
22
|
+
re.IGNORECASE | re.MULTILINE | re.DOTALL
|
|
23
|
+
),
|
|
24
|
+
# Daha gevşek pattern
|
|
25
|
+
re.compile(
|
|
26
|
+
r"\}\s*\(\s*['\"](.*?)['\"],\s*(\d+),\s*(\d+),\s*['\"](.+?)['\"]\.split\(['\"]\\?\|['\"]\)",
|
|
27
|
+
re.IGNORECASE | re.MULTILINE | re.DOTALL
|
|
28
|
+
),
|
|
29
|
+
# Eval formatı
|
|
30
|
+
re.compile(
|
|
31
|
+
r"eval\(function\(p,a,c,k,e,(?:r|d|)\)\{.*?return p\}(.*?\.split\('\|'\))",
|
|
32
|
+
re.IGNORECASE | re.MULTILINE | re.DOTALL
|
|
33
|
+
)
|
|
34
|
+
]
|
|
35
|
+
|
|
36
|
+
# Kelime değiştirme deseni
|
|
37
|
+
REPLACE_PATTERN = re.compile(
|
|
38
|
+
r"\b\w+\b",
|
|
39
|
+
re.IGNORECASE | re.MULTILINE
|
|
40
|
+
)
|
|
41
|
+
|
|
42
|
+
# Alfabeler
|
|
43
|
+
ALPHABET = {
|
|
44
|
+
52: "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOP",
|
|
45
|
+
54: "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQR",
|
|
46
|
+
62: "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ",
|
|
47
|
+
95: " !\"#$%&'()*+,-./0123456789:;<=>?@ABCDEFGHIJKLMNOPQRSTUVWXYZ[\\]^_`abcdefghijklmnopqrstuvwxyz{|}~"
|
|
48
|
+
}
|
|
49
|
+
|
|
50
|
+
@staticmethod
|
|
51
|
+
def clean_escape_sequences(source: str) -> str:
|
|
52
|
+
"""Kaçış dizilerini temizler."""
|
|
53
|
+
source = re.sub(r'\\\\', r'\\', source)
|
|
54
|
+
source = source.replace("\\'", "'")
|
|
55
|
+
source = source.replace('\\"', '"')
|
|
56
|
+
return source
|
|
57
|
+
|
|
58
|
+
@staticmethod
|
|
59
|
+
def extract_arguments(source: str) -> tuple[str, list[str], int, int]:
|
|
60
|
+
"""P.A.C.K.E.R. formatındaki kaynak koddan argümanları çıkarır."""
|
|
61
|
+
# Önce standart pattern ile dene
|
|
62
|
+
match = Packer.PACKED_PATTERN.search(source)
|
|
63
|
+
|
|
64
|
+
# Eğer bulunamazsa, alternatif pattern'leri dene
|
|
65
|
+
if not match:
|
|
66
|
+
for pattern in Packer.ALTERNATIVE_PATTERNS:
|
|
67
|
+
match = pattern.search(source)
|
|
68
|
+
if match:
|
|
69
|
+
break
|
|
70
|
+
|
|
71
|
+
if not match:
|
|
72
|
+
# Son çare: daha serbest bir string arama
|
|
73
|
+
if "'.split('|')" in source or '".split("|")' in source:
|
|
74
|
+
# Manuel olarak parçalama işlemi yap
|
|
75
|
+
try:
|
|
76
|
+
# Basit bir yaklaşım, çoğu vakada çalışır
|
|
77
|
+
parts = re.findall(r"\((['\"](.*?)['\"],\s*(\d+),\s*(\d+),\s*['\"](.*?)['\"]\.split", source)
|
|
78
|
+
if parts:
|
|
79
|
+
payload, radix, count, symtab = parts[0][1:]
|
|
80
|
+
return payload, symtab.split("|"), int(radix), int(count)
|
|
81
|
+
except Exception:
|
|
82
|
+
pass
|
|
83
|
+
|
|
84
|
+
raise ValueError("Invalid P.A.C.K.E.R. source format. Pattern not found.")
|
|
85
|
+
|
|
86
|
+
# Eval formatını işle
|
|
87
|
+
if len(match.groups()) == 1:
|
|
88
|
+
# Eval formatı yakalandı, içeriği çıkar
|
|
89
|
+
eval_content = match.group(1)
|
|
90
|
+
if inner_match := re.search(r"\('(.*)',(\d+),(\d+),'(.*)'\)", eval_content):
|
|
91
|
+
payload, radix, count, symtab = inner_match.groups()
|
|
92
|
+
else:
|
|
93
|
+
raise ValueError("Cannot extract arguments from eval pattern")
|
|
94
|
+
else:
|
|
95
|
+
# Standart format yakalandı
|
|
96
|
+
payload, radix, count, symtab = match.groups()
|
|
97
|
+
|
|
98
|
+
return payload, symtab.split("|"), int(radix), int(count)
|
|
99
|
+
|
|
100
|
+
@staticmethod
|
|
101
|
+
def unbase(value: str, base: int) -> int:
|
|
102
|
+
"""
|
|
103
|
+
Verilen değeri belirtilen tabandan ondalık sayıya dönüştürür.
|
|
104
|
+
Geniş taban desteği (2-95 arası) sağlar.
|
|
105
|
+
"""
|
|
106
|
+
# Standart Python taban dönüşümü (2-36 arası)
|
|
107
|
+
if 2 <= base <= 36:
|
|
108
|
+
try:
|
|
109
|
+
return int(value, base)
|
|
110
|
+
except ValueError:
|
|
111
|
+
return 0
|
|
112
|
+
|
|
113
|
+
# Geniş taban desteği (37-95 arası)
|
|
114
|
+
if base > 95:
|
|
115
|
+
raise ValueError(f"Desteklenmeyen taban: {base}")
|
|
116
|
+
|
|
117
|
+
# Uygun alfabeyi seç
|
|
118
|
+
if base > 62:
|
|
119
|
+
selector = 95
|
|
120
|
+
elif base > 54:
|
|
121
|
+
selector = 62
|
|
122
|
+
elif base > 52:
|
|
123
|
+
selector = 54
|
|
124
|
+
else:
|
|
125
|
+
selector = 52
|
|
126
|
+
|
|
127
|
+
# Alfabeden karakter-indeks sözlüğü oluştur
|
|
128
|
+
char_dict = {char: idx for idx, char in enumerate(Packer.ALPHABET[selector])}
|
|
129
|
+
|
|
130
|
+
# Değeri dönüştür
|
|
131
|
+
result = 0
|
|
132
|
+
for index, char in enumerate(reversed(value)):
|
|
133
|
+
digit = char_dict.get(char, 0)
|
|
134
|
+
result += digit * (base ** index)
|
|
135
|
+
|
|
136
|
+
return result
|
|
137
|
+
|
|
138
|
+
@staticmethod
|
|
139
|
+
def lookup_symbol(match: re.Match, symtab: list[str], radix: int) -> str:
|
|
140
|
+
"""Sembolleri arar ve yerine koyar."""
|
|
141
|
+
word = match[0]
|
|
142
|
+
|
|
143
|
+
try:
|
|
144
|
+
index = Packer.unbase(word, radix)
|
|
145
|
+
if 0 <= index < len(symtab):
|
|
146
|
+
replacement = symtab[index]
|
|
147
|
+
return replacement or word
|
|
148
|
+
except (ValueError, IndexError):
|
|
149
|
+
pass
|
|
150
|
+
|
|
151
|
+
return word
|
|
152
|
+
|
|
153
|
+
@staticmethod
|
|
154
|
+
def unpack(source: str) -> str:
|
|
155
|
+
"""
|
|
156
|
+
P.A.C.K.E.R. formatındaki sıkıştırılmış bir JavaScript kodunu çözer.
|
|
157
|
+
Birden fazla format ve varyasyonu destekler.
|
|
158
|
+
"""
|
|
159
|
+
# Kaçış dizilerini temizle
|
|
160
|
+
source = Packer.clean_escape_sequences(source)
|
|
161
|
+
|
|
162
|
+
# Argümanları çıkar
|
|
163
|
+
try:
|
|
164
|
+
payload, symtab, radix, count = Packer.extract_arguments(source)
|
|
165
|
+
|
|
166
|
+
# Sembol tablosunun doğruluğunu kontrol et (ancak sıkı değil)
|
|
167
|
+
if len(symtab) != count:
|
|
168
|
+
print(f"Uyarı: Sembol tablosu sayısı ({len(symtab)}) ile belirtilen sayı ({count}) eşleşmiyor, ancak devam ediliyor.")
|
|
169
|
+
|
|
170
|
+
# Kelimeleri değiştir ve sonucu döndür
|
|
171
|
+
return Packer.REPLACE_PATTERN.sub(
|
|
172
|
+
lambda match: Packer.lookup_symbol(match, symtab, radix),
|
|
173
|
+
payload
|
|
174
|
+
)
|
|
175
|
+
except Exception as e:
|
|
176
|
+
# Detaylı hata mesajı
|
|
177
|
+
raise ValueError(f"Unpacking failed: {str(e)}\nSource preview: {source[:100]}...")
|
|
178
|
+
|
|
179
|
+
@staticmethod
|
|
180
|
+
def detect_packed(source: str) -> bool:
|
|
181
|
+
"""Verilen kodun P.A.C.K.E.R. formatında sıkıştırılmış olup olmadığını kontrol eder."""
|
|
182
|
+
# Standart pattern'i kontrol et
|
|
183
|
+
if Packer.PACKED_PATTERN.search(source):
|
|
184
|
+
return True
|
|
185
|
+
|
|
186
|
+
# Alternatif pattern'leri kontrol et
|
|
187
|
+
for pattern in Packer.ALTERNATIVE_PATTERNS:
|
|
188
|
+
if pattern.search(source):
|
|
189
|
+
return True
|
|
190
|
+
|
|
191
|
+
# Yaygın belirteçleri kontrol et
|
|
192
|
+
indicators = [
|
|
193
|
+
".split('|')",
|
|
194
|
+
'.split("|")',
|
|
195
|
+
"function(p,a,c,k,e,",
|
|
196
|
+
"function(p, a, c, k, e, "
|
|
197
|
+
]
|
|
198
|
+
|
|
199
|
+
return any(indicator in source for indicator in indicators)
|
|
@@ -23,6 +23,10 @@ REDIS_PORT = 6379
|
|
|
23
23
|
REDIS_DB = 0
|
|
24
24
|
REDIS_PASS = None
|
|
25
25
|
|
|
26
|
+
# FastAPI için cache'ten hariç tutulacak parametreler ve HTTP status kodları
|
|
27
|
+
CACHE_IGNORE_PARAMS = {"kurek", "debug", "_", "t", "timestamp"}
|
|
28
|
+
CACHE_IGNORE_STATUS_CODES = {400, 401, 403, 404, 500, 501, 502, 503}
|
|
29
|
+
|
|
26
30
|
def normalize_for_key(value):
|
|
27
31
|
"""
|
|
28
32
|
Cache key oluşturma amacıyla verilen değeri normalize eder.
|
|
@@ -49,6 +53,7 @@ def simple_cache_key(func, args, kwargs) -> str:
|
|
|
49
53
|
Oluşturulan stringin sonuna MD5 hash eklenebilir.
|
|
50
54
|
"""
|
|
51
55
|
base_key = f"{func.__module__}.{func.__qualname__}"
|
|
56
|
+
base_key = "|".join(base_key.split("."))
|
|
52
57
|
|
|
53
58
|
if args:
|
|
54
59
|
norm_args = [normalize_for_key(arg) for arg in args]
|
|
@@ -61,11 +66,12 @@ def simple_cache_key(func, args, kwargs) -> str:
|
|
|
61
66
|
hashed = md5(base_key.encode('utf-8')).hexdigest()
|
|
62
67
|
return f"{base_key}" # |{hashed}
|
|
63
68
|
|
|
64
|
-
async def make_cache_key(func, args, kwargs, is_fastapi=False) -> str:
|
|
69
|
+
async def make_cache_key(func, args, kwargs, is_fastapi=False, include_auth=False) -> str:
|
|
65
70
|
"""
|
|
66
71
|
Cache key'ini oluşturur.
|
|
67
72
|
- is_fastapi=False ise simple_cache_key() kullanılır.
|
|
68
73
|
- True ise FastAPI Request nesnesine göre özel key oluşturulur.
|
|
74
|
+
- include_auth=True ise authorization header'ı key'e dahil edilir.
|
|
69
75
|
"""
|
|
70
76
|
if not is_fastapi:
|
|
71
77
|
return simple_cache_key(func, args, kwargs)
|
|
@@ -73,21 +79,40 @@ async def make_cache_key(func, args, kwargs, is_fastapi=False) -> str:
|
|
|
73
79
|
# FastAPI: request ilk argümandan ya da kwargs'dan alınır.
|
|
74
80
|
request = args[0] if args else kwargs.get("request")
|
|
75
81
|
|
|
76
|
-
|
|
77
|
-
|
|
78
|
-
|
|
79
|
-
else:
|
|
80
|
-
try:
|
|
81
|
-
veri = await request.json()
|
|
82
|
-
except Exception:
|
|
83
|
-
form_data = await request.form()
|
|
84
|
-
veri = dict(form_data.items())
|
|
85
|
-
|
|
86
|
-
# Eğer "kurek" gibi özel parametreler varsa temizleyebilirsiniz:
|
|
87
|
-
veri.pop("kurek", None)
|
|
82
|
+
# Request bulunamamışsa fallback
|
|
83
|
+
if request is None or not hasattr(request, 'method'):
|
|
84
|
+
return simple_cache_key(func, args, kwargs)
|
|
88
85
|
|
|
89
|
-
|
|
90
|
-
|
|
86
|
+
try:
|
|
87
|
+
if request.method == "GET":
|
|
88
|
+
# Eğer query_params boşsa {} olarak ayarla
|
|
89
|
+
veri = dict(request.query_params) if request.query_params else {}
|
|
90
|
+
else:
|
|
91
|
+
try:
|
|
92
|
+
content_type = request.headers.get("content-type", "")
|
|
93
|
+
if "application/json" in content_type:
|
|
94
|
+
veri = await request.json()
|
|
95
|
+
else:
|
|
96
|
+
form_data = await request.form()
|
|
97
|
+
veri = dict(form_data.items())
|
|
98
|
+
except Exception:
|
|
99
|
+
veri = {}
|
|
100
|
+
|
|
101
|
+
# Sistem parametrelerini temizle
|
|
102
|
+
for param in CACHE_IGNORE_PARAMS:
|
|
103
|
+
veri.pop(param, None)
|
|
104
|
+
|
|
105
|
+
# Authorization header'ı dahil et (user-specific cache için)
|
|
106
|
+
if include_auth and "authorization" in request.headers:
|
|
107
|
+
auth_hash = md5(request.headers["authorization"].encode()).hexdigest()
|
|
108
|
+
veri[f"_auth_hash"] = auth_hash
|
|
109
|
+
|
|
110
|
+
args_hash = md5(urlencode(veri).encode()).hexdigest() if veri else ""
|
|
111
|
+
return f"{request.url.path}|{veri}" if veri else f"{request.url.path}"
|
|
112
|
+
except Exception as e:
|
|
113
|
+
# Herhangi bir hata durumunda fallback
|
|
114
|
+
konsol.log(f"[yellow]FastAPI cache key oluşturma hatası: {e}, basit key kullanılıyor")
|
|
115
|
+
return simple_cache_key(func, args, kwargs)
|
|
91
116
|
|
|
92
117
|
# -----------------------------------------------------
|
|
93
118
|
# Senkron Cache (RAM) Sınıfı
|
|
@@ -96,29 +121,35 @@ async def make_cache_key(func, args, kwargs, is_fastapi=False) -> str:
|
|
|
96
121
|
class SyncCache:
|
|
97
122
|
"""
|
|
98
123
|
Senkron fonksiyonlar için basit in-memory cache.
|
|
99
|
-
TTL süresi dolan veriler periyodik olarak arka plan thread
|
|
124
|
+
TTL süresi dolan veriler periyodik olarak arka plan thread'iyle temizlenir.
|
|
100
125
|
"""
|
|
101
|
-
def __init__(self, ttl=UNLIMITED, cleanup_interval=60 * 60):
|
|
102
|
-
self._ttl
|
|
103
|
-
self._data
|
|
104
|
-
self._times
|
|
126
|
+
def __init__(self, ttl=UNLIMITED, cleanup_interval=60 * 60, max_size=10000):
|
|
127
|
+
self._ttl = ttl
|
|
128
|
+
self._data = {}
|
|
129
|
+
self._times = {}
|
|
130
|
+
self._access_counts = {} # LRU tracker
|
|
131
|
+
self._max_size = max_size
|
|
105
132
|
|
|
106
|
-
# TTL sınırsız değilse, cleanup_interval
|
|
107
|
-
self._cleanup_interval =
|
|
133
|
+
# TTL sınırsız değilse, cleanup_interval kullanıyoruz.
|
|
134
|
+
self._cleanup_interval = cleanup_interval if ttl is UNLIMITED else min(ttl, cleanup_interval)
|
|
108
135
|
|
|
109
136
|
# Arka planda çalışan ve periyodik olarak expired entry'leri temizleyen thread başlatılıyor.
|
|
110
|
-
self._lock
|
|
111
|
-
self._cleanup_thread
|
|
137
|
+
self._lock = threading.RLock()
|
|
138
|
+
self._cleanup_thread = threading.Thread(target=self._auto_cleanup, daemon=True)
|
|
139
|
+
self._cleanup_thread.daemon = True
|
|
112
140
|
self._cleanup_thread.start()
|
|
113
141
|
|
|
114
142
|
def _auto_cleanup(self):
|
|
115
143
|
"""Belirlenen aralıklarla cache içerisindeki süresi dolmuş entry'leri temizler."""
|
|
116
144
|
while True:
|
|
117
|
-
|
|
118
|
-
|
|
119
|
-
|
|
120
|
-
|
|
121
|
-
|
|
145
|
+
try:
|
|
146
|
+
time.sleep(self._cleanup_interval)
|
|
147
|
+
with self._lock:
|
|
148
|
+
keys = list(self._data.keys())
|
|
149
|
+
for key in keys:
|
|
150
|
+
self.remove_if_expired(key)
|
|
151
|
+
except Exception as e:
|
|
152
|
+
konsol.log(f"[red]Cache cleanup hatası: {e}")
|
|
122
153
|
|
|
123
154
|
def _is_expired(self, key):
|
|
124
155
|
"""Belirtilen key'in süresi dolmuşsa True döner."""
|
|
@@ -144,12 +175,24 @@ class SyncCache:
|
|
|
144
175
|
with self._lock:
|
|
145
176
|
self.remove_if_expired(key)
|
|
146
177
|
veri = self._data[key]
|
|
178
|
+
# LRU tracker'ı güncelle
|
|
179
|
+
self._access_counts[key] = self._access_counts.get(key, 0) + 1
|
|
147
180
|
# konsol.log(f"[yellow][~] {key}")
|
|
148
181
|
return veri
|
|
149
182
|
|
|
150
183
|
def __setitem__(self, key, value):
|
|
151
184
|
with self._lock:
|
|
152
|
-
|
|
185
|
+
# Kapasite kontrolü - LRU temizlemesi
|
|
186
|
+
if len(self._data) >= self._max_size and key not in self._data:
|
|
187
|
+
# En az kullanılan key'i bul ve sil
|
|
188
|
+
lru_key = min(self._access_counts, key=self._access_counts.get)
|
|
189
|
+
self._data.pop(lru_key, None)
|
|
190
|
+
self._times.pop(lru_key, None)
|
|
191
|
+
self._access_counts.pop(lru_key, None)
|
|
192
|
+
# konsol.log(f"[red][-] LRU eviction: {lru_key}")
|
|
193
|
+
|
|
194
|
+
self._data[key] = value
|
|
195
|
+
self._access_counts[key] = 0
|
|
153
196
|
if self._ttl is not UNLIMITED:
|
|
154
197
|
self._times[key] = time.time()
|
|
155
198
|
|
|
@@ -158,8 +201,9 @@ class HybridSyncCache:
|
|
|
158
201
|
Senkron işlemler için, öncelikle Redis cache kullanılmaya çalışılır.
|
|
159
202
|
Redis'ten veri alınamazsa ya da hata oluşursa, SyncCache (in-memory) fallback uygulanır.
|
|
160
203
|
"""
|
|
161
|
-
def __init__(self, ttl=None):
|
|
204
|
+
def __init__(self, ttl=None, max_size=10000):
|
|
162
205
|
self._ttl = ttl
|
|
206
|
+
self._max_size = max_size
|
|
163
207
|
|
|
164
208
|
try:
|
|
165
209
|
self.redis = redis.Redis(
|
|
@@ -170,25 +214,28 @@ class HybridSyncCache:
|
|
|
170
214
|
decode_responses = False
|
|
171
215
|
)
|
|
172
216
|
self.redis.ping()
|
|
173
|
-
except Exception:
|
|
217
|
+
except Exception as e:
|
|
218
|
+
konsol.log(f"[yellow]Redis bağlantısı başarısız, in-memory cache kullanılıyor: {e}")
|
|
174
219
|
self.redis = None
|
|
175
220
|
|
|
176
|
-
self.memory = SyncCache(ttl)
|
|
221
|
+
self.memory = SyncCache(ttl, max_size=max_size)
|
|
177
222
|
|
|
178
223
|
def get(self, key):
|
|
179
224
|
# Önce Redis ile deniyoruz:
|
|
180
225
|
if self.redis:
|
|
181
226
|
try:
|
|
182
227
|
data = self.redis.get(key)
|
|
183
|
-
except Exception:
|
|
228
|
+
except Exception as e:
|
|
229
|
+
# konsol.log(f"[yellow]Redis get hatası: {e}")
|
|
184
230
|
data = None
|
|
185
231
|
if data is not None:
|
|
186
232
|
try:
|
|
187
233
|
result = pickle.loads(data)
|
|
188
234
|
# konsol.log(f"[yellow][~] {key}")
|
|
189
235
|
return result
|
|
190
|
-
except Exception:
|
|
236
|
+
except Exception as e:
|
|
191
237
|
# Deserialize hatası durumunda fallback'e geç
|
|
238
|
+
# konsol.log(f"[yellow]Pickle deserialize hatası: {e}")
|
|
192
239
|
pass
|
|
193
240
|
|
|
194
241
|
# Redis'te veri yoksa, yerel cache'ten alıyoruz.
|
|
@@ -200,8 +247,10 @@ class HybridSyncCache:
|
|
|
200
247
|
def set(self, key, value):
|
|
201
248
|
try:
|
|
202
249
|
ser = pickle.dumps(value)
|
|
203
|
-
except Exception:
|
|
250
|
+
except Exception as e:
|
|
204
251
|
# Serialization hatası durumunda yerel cache'e yazalım.
|
|
252
|
+
# (TemplateResponse, FileResponse gibi pickle'lanamayan objeler için)
|
|
253
|
+
# konsol.log(f"[yellow]Pickle serialize hatası: {e}, in-memory cache kullanılıyor")
|
|
205
254
|
self.memory[key] = value
|
|
206
255
|
return
|
|
207
256
|
|
|
@@ -212,8 +261,9 @@ class HybridSyncCache:
|
|
|
212
261
|
else:
|
|
213
262
|
self.redis.set(key, ser)
|
|
214
263
|
return
|
|
215
|
-
except Exception:
|
|
264
|
+
except Exception as e:
|
|
216
265
|
# Redis'e yazılamazsa yerel cache'e geçelim.
|
|
266
|
+
# konsol.log(f"[yellow]Redis set hatası: {e}, in-memory cache kullanılıyor")
|
|
217
267
|
self.memory[key] = value
|
|
218
268
|
return
|
|
219
269
|
else:
|
|
@@ -235,18 +285,21 @@ class AsyncCache:
|
|
|
235
285
|
"""
|
|
236
286
|
Temel in-memory asenkron cache.
|
|
237
287
|
"""
|
|
238
|
-
def __init__(self, ttl=UNLIMITED, cleanup_interval=60 * 60):
|
|
288
|
+
def __init__(self, ttl=UNLIMITED, cleanup_interval=60 * 60, max_size=10000):
|
|
239
289
|
"""
|
|
240
290
|
:param ttl: Her entry için geçerli süre (saniye). Örneğin 3600 saniye 1 saattir.
|
|
241
291
|
:param cleanup_interval: Otomatik temizleme görevinin kaç saniyede bir çalışacağını belirler.
|
|
292
|
+
:param max_size: Maksimum cache boyutu (en eski entry'ler silinir).
|
|
242
293
|
"""
|
|
243
|
-
self._ttl
|
|
244
|
-
self._data
|
|
245
|
-
self._times
|
|
246
|
-
self.
|
|
294
|
+
self._ttl = ttl
|
|
295
|
+
self._data = {}
|
|
296
|
+
self._times = {}
|
|
297
|
+
self._access_counts = {} # LRU tracker
|
|
298
|
+
self.futures = {}
|
|
299
|
+
self._max_size = max_size
|
|
247
300
|
|
|
248
|
-
# TTL sınırsız değilse, cleanup_interval
|
|
249
|
-
self._cleanup_interval =
|
|
301
|
+
# TTL sınırsız değilse, cleanup_interval kullanıyoruz.
|
|
302
|
+
self._cleanup_interval = cleanup_interval if ttl is UNLIMITED else min(ttl, cleanup_interval)
|
|
250
303
|
|
|
251
304
|
# Aktif bir event loop varsa otomatik temizlik görevini başlatıyoruz.
|
|
252
305
|
try:
|
|
@@ -257,9 +310,12 @@ class AsyncCache:
|
|
|
257
310
|
async def _auto_cleanup(self):
|
|
258
311
|
"""Belirlenen aralıklarla cache içerisindeki süresi dolmuş entry'leri temizler."""
|
|
259
312
|
while True:
|
|
260
|
-
|
|
261
|
-
|
|
262
|
-
self.
|
|
313
|
+
try:
|
|
314
|
+
await asyncio.sleep(self._cleanup_interval)
|
|
315
|
+
for key in list(self._data.keys()):
|
|
316
|
+
self.remove_if_expired(key)
|
|
317
|
+
except Exception as e:
|
|
318
|
+
konsol.log(f"[red]Async cache cleanup hatası: {e}")
|
|
263
319
|
|
|
264
320
|
def ensure_cleanup_task(self):
|
|
265
321
|
"""Event loop mevcutsa, cleanup task henüz başlatılmadıysa oluştur."""
|
|
@@ -294,6 +350,8 @@ class AsyncCache:
|
|
|
294
350
|
try:
|
|
295
351
|
# Cache içerisinde key varsa direkt değeri döndür.
|
|
296
352
|
value = self._data[key]
|
|
353
|
+
# LRU tracker'ı güncelle
|
|
354
|
+
self._access_counts[key] = self._access_counts.get(key, 0) + 1
|
|
297
355
|
# konsol.log(f"[yellow][~] {key}")
|
|
298
356
|
return value
|
|
299
357
|
except KeyError:
|
|
@@ -311,17 +369,30 @@ class AsyncCache:
|
|
|
311
369
|
async def set(self, key, value):
|
|
312
370
|
"""Belirtilen key için cache'e değer ekler."""
|
|
313
371
|
self.ensure_cleanup_task()
|
|
314
|
-
|
|
372
|
+
|
|
373
|
+
# Kapasite kontrolü - LRU temizlemesi
|
|
374
|
+
if len(self._data) >= self._max_size and key not in self._data:
|
|
375
|
+
# En az kullanılan key'i bul ve sil
|
|
376
|
+
lru_key = min(self._access_counts, key=self._access_counts.get)
|
|
377
|
+
self._data.pop(lru_key, None)
|
|
378
|
+
self._times.pop(lru_key, None)
|
|
379
|
+
self._access_counts.pop(lru_key, None)
|
|
380
|
+
self.futures.pop(lru_key, None)
|
|
381
|
+
# konsol.log(f"[red][-] Async LRU eviction: {lru_key}")
|
|
382
|
+
|
|
383
|
+
self._data[key] = value
|
|
384
|
+
self._access_counts[key] = 0
|
|
315
385
|
if self._ttl is not UNLIMITED:
|
|
316
386
|
self._times[key] = time.time()
|
|
317
387
|
|
|
318
388
|
class HybridAsyncCache:
|
|
319
389
|
"""
|
|
320
390
|
Öncelikle Redis cache kullanılmaya çalışılır.
|
|
321
|
-
Hata durumunda veya Redis erişilemiyorsa in-memory AsyncCache
|
|
391
|
+
Hata durumunda veya Redis erişilemiyorsa in-memory AsyncCache'e geçilir.
|
|
322
392
|
"""
|
|
323
|
-
def __init__(self, ttl=UNLIMITED):
|
|
393
|
+
def __init__(self, ttl=UNLIMITED, max_size=10000):
|
|
324
394
|
self._ttl = ttl
|
|
395
|
+
self._max_size = max_size
|
|
325
396
|
|
|
326
397
|
try:
|
|
327
398
|
self.redis = redisAsync.Redis(
|
|
@@ -331,10 +402,11 @@ class HybridAsyncCache:
|
|
|
331
402
|
password = REDIS_PASS,
|
|
332
403
|
decode_responses = False
|
|
333
404
|
)
|
|
334
|
-
except Exception:
|
|
405
|
+
except Exception as e:
|
|
406
|
+
konsol.log(f"[yellow]Async Redis bağlantısı başarısız, in-memory cache kullanılıyor: {e}")
|
|
335
407
|
self.redis = None
|
|
336
408
|
|
|
337
|
-
self.memory = AsyncCache(ttl)
|
|
409
|
+
self.memory = AsyncCache(ttl, max_size=max_size)
|
|
338
410
|
self.futures = {}
|
|
339
411
|
|
|
340
412
|
async def get(self, key):
|
|
@@ -347,15 +419,17 @@ class HybridAsyncCache:
|
|
|
347
419
|
if self.redis:
|
|
348
420
|
try:
|
|
349
421
|
data = await self.redis.get(key)
|
|
350
|
-
except Exception:
|
|
422
|
+
except Exception as e:
|
|
423
|
+
konsol.log(f"[yellow]Async Redis get hatası: {e}")
|
|
351
424
|
return await self.memory.get(key)
|
|
352
425
|
if data is not None:
|
|
353
426
|
try:
|
|
354
427
|
result = pickle.loads(data)
|
|
355
428
|
# konsol.log(f"[yellow][~] {key}")
|
|
356
429
|
return result
|
|
357
|
-
except Exception:
|
|
430
|
+
except Exception as e:
|
|
358
431
|
# Deserialize hatası durumunda in-memory cache'ten dene
|
|
432
|
+
konsol.log(f"[yellow]Async pickle deserialize hatası: {e}")
|
|
359
433
|
return await self.memory.get(key)
|
|
360
434
|
else:
|
|
361
435
|
# Redis'te veri yoksa, in-memory cache'e bak
|
|
@@ -368,8 +442,10 @@ class HybridAsyncCache:
|
|
|
368
442
|
# Önce veriyi pickle etmeyi deniyoruz.
|
|
369
443
|
try:
|
|
370
444
|
ser = pickle.dumps(value)
|
|
371
|
-
except Exception:
|
|
445
|
+
except Exception as e:
|
|
372
446
|
# Serialization hatası durumunda sadece in-memory cache'e yaz
|
|
447
|
+
# (TemplateResponse, FileResponse gibi pickle'lanamayan objeler için)
|
|
448
|
+
# konsol.log(f"[yellow]Async pickle serialize hatası: {e}, in-memory cache kullanılıyor")
|
|
373
449
|
await self.memory.set(key, value)
|
|
374
450
|
return
|
|
375
451
|
|
|
@@ -380,8 +456,9 @@ class HybridAsyncCache:
|
|
|
380
456
|
else:
|
|
381
457
|
await self.redis.set(key, ser)
|
|
382
458
|
return
|
|
383
|
-
except Exception:
|
|
459
|
+
except Exception as e:
|
|
384
460
|
# Redis yazma hatası durumunda in-memory fallback
|
|
461
|
+
# konsol.log(f"[yellow]Async Redis set hatası: {e}, in-memory cache kullanılıyor")
|
|
385
462
|
await self.memory.set(key, value)
|
|
386
463
|
return
|
|
387
464
|
else:
|
|
@@ -436,35 +513,61 @@ async def _async_compute_and_cache(func, key, unless, *args, **kwargs):
|
|
|
436
513
|
# kekik_cache Dekoratörü (Senkrondan Asenkrona)
|
|
437
514
|
# -----------------------------------------------------
|
|
438
515
|
|
|
439
|
-
def kekik_cache(ttl=UNLIMITED, unless=None, is_fastapi=
|
|
516
|
+
def kekik_cache(ttl=UNLIMITED, unless=None, use_redis=True, max_size=10000, is_fastapi=None, include_auth=False):
|
|
440
517
|
"""
|
|
441
518
|
Bir fonksiyonun (senkron/asenkron) sonucunu cache'ler.
|
|
519
|
+
FastAPI endpoint'leri otomatik detekt edilir (is_fastapi=None ise) veya manuel olarak belirtilebilir.
|
|
442
520
|
|
|
443
521
|
Parametreler:
|
|
444
522
|
- ttl: Cache'in geçerlilik süresi (saniye). UNLIMITED ise süresizdir.
|
|
445
523
|
- unless: Sonuç alınmadan önce çağrılan, True dönerse cache'e alınmaz.
|
|
446
|
-
- is_fastapi: True
|
|
524
|
+
- is_fastapi: True/False ile açıkça belirt, None ise otomatik detekt (Request nesnesine bakarak).
|
|
447
525
|
- use_redis: Asenkron fonksiyonlarda Redis kullanımı (Hybrid cache) için True verilebilir.
|
|
526
|
+
- max_size: Cache'in maksimum boyutu. Kapasiteyi aşarsa LRU temizlemesi yapılır.
|
|
527
|
+
- include_auth: Authorization header'ını key'e dahil et (user-specific cache).
|
|
448
528
|
|
|
449
529
|
Örnek Kullanım:
|
|
450
530
|
|
|
451
|
-
|
|
452
|
-
|
|
453
|
-
|
|
531
|
+
# Basit fonksiyon
|
|
532
|
+
@kekik_cache(ttl=300)
|
|
533
|
+
async def hesapla(param):
|
|
534
|
+
return param * 2
|
|
535
|
+
|
|
536
|
+
# FastAPI endpoint (otomatik detekt)
|
|
537
|
+
@app.get("/users/{user_id}")
|
|
538
|
+
@kekik_cache(ttl=300, include_auth=True)
|
|
539
|
+
async def get_user(user_id: int, request: Request):
|
|
540
|
+
return {"id": user_id, "name": "..."}
|
|
541
|
+
|
|
542
|
+
# FastAPI endpoint (manuel belirtim)
|
|
543
|
+
@app.get("/data")
|
|
544
|
+
@kekik_cache(ttl=600, is_fastapi=True)
|
|
545
|
+
async def get_data(request: Request):
|
|
546
|
+
return {"data": "..."}
|
|
547
|
+
|
|
548
|
+
# Hata response'larını cache'leme
|
|
549
|
+
@app.get("/data")
|
|
550
|
+
@kekik_cache(ttl=300, unless=lambda r: r.status_code >= 400)
|
|
551
|
+
async def get_data(request: Request):
|
|
552
|
+
return {}
|
|
454
553
|
"""
|
|
455
554
|
# Parametresiz kullanım durumunda
|
|
456
555
|
if callable(ttl):
|
|
457
|
-
return kekik_cache(UNLIMITED, unless=unless, is_fastapi=is_fastapi,
|
|
556
|
+
return kekik_cache(UNLIMITED, unless=unless, use_redis=use_redis, max_size=max_size, is_fastapi=is_fastapi, include_auth=include_auth)(ttl)
|
|
458
557
|
|
|
459
558
|
def decorator(func):
|
|
460
559
|
if asyncio.iscoroutinefunction(func):
|
|
461
560
|
# Asenkron fonksiyonlar için cache türünü seçelim:
|
|
462
|
-
|
|
463
|
-
func.__cache = HybridAsyncCache(ttl) if use_redis else AsyncCache(ttl)
|
|
561
|
+
func.__cache = HybridAsyncCache(ttl, max_size=max_size) if use_redis else AsyncCache(ttl, max_size=max_size)
|
|
464
562
|
|
|
465
563
|
@wraps(func)
|
|
466
564
|
async def async_wrapper(*args, **kwargs):
|
|
467
|
-
|
|
565
|
+
# is_fastapi otomatik deteksiyon (None ise) ya da manuel belirtim
|
|
566
|
+
detect_fastapi = is_fastapi
|
|
567
|
+
if detect_fastapi is None:
|
|
568
|
+
detect_fastapi = args and hasattr(args[0], "url") and hasattr(args[0], "method")
|
|
569
|
+
|
|
570
|
+
key = await make_cache_key(func, args, kwargs, detect_fastapi, include_auth=include_auth)
|
|
468
571
|
|
|
469
572
|
try:
|
|
470
573
|
return await func.__cache.get(key)
|
|
@@ -474,7 +577,7 @@ def kekik_cache(ttl=UNLIMITED, unless=None, is_fastapi=False, use_redis=True):
|
|
|
474
577
|
return async_wrapper
|
|
475
578
|
else:
|
|
476
579
|
# Senkron fonksiyonlar için
|
|
477
|
-
func.__cache = HybridSyncCache(ttl) if use_redis else SyncCache(ttl)
|
|
580
|
+
func.__cache = HybridSyncCache(ttl, max_size=max_size) if use_redis else SyncCache(ttl, max_size=max_size)
|
|
478
581
|
|
|
479
582
|
@wraps(func)
|
|
480
583
|
def sync_wrapper(*args, **kwargs):
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: Kekik
|
|
3
|
-
Version: 1.7.
|
|
3
|
+
Version: 1.7.9
|
|
4
4
|
Summary: İşlerimizi kolaylaştıracak fonksiyonların el altında durduğu kütüphane..
|
|
5
5
|
Home-page: https://github.com/keyiflerolsun/Kekik
|
|
6
6
|
Author: keyiflerolsun
|
|
@@ -35,6 +35,7 @@ Dynamic: description-content-type
|
|
|
35
35
|
Dynamic: home-page
|
|
36
36
|
Dynamic: keywords
|
|
37
37
|
Dynamic: license
|
|
38
|
+
Dynamic: license-file
|
|
38
39
|
Dynamic: requires-dist
|
|
39
40
|
Dynamic: requires-python
|
|
40
41
|
Dynamic: summary
|
|
@@ -316,6 +317,11 @@ var played = 0;
|
|
|
316
317
|
eval_jwSetup = re.compile(r'\};\s*(eval\(function[\s\S]*?)var played = \d+;').findall(veri)[0]
|
|
317
318
|
print(Packer.unpack(Packer.unpack(eval_jwSetup)))
|
|
318
319
|
# jwSetup.sources=[{"default":true,"file":"\x68\x74\x74\x70\x73\x3a\x2f\x2f\x64\x32\x2e\x69\x6d\x61\x67\x65\x73\x70\x6f\x74\x2e\x62\x75\x7a\x7a\x2f\x66\x32\x2f\x4e\x74\x4f\x31\x4e\x51\x5a\x6a\x44\x51\x41\x6b\x78\x6c\x58\x45\x47\x33\x6c\x62\x66\x62\x30\x31\x79\x74\x70\x57\x66\x4e\x30\x66\x62\x66\x50\x58\x5a\x55\x31\x6a\x50\x77\x5a\x6d\x48\x71\x58\x41\x37\x6c\x6d\x6d\x4b\x67\x47\x59\x31\x66\x47\x42\x6d\x6c\x38\x68\x32\x7a\x33\x4f\x5a\x69\x4f\x63\x4c\x6b\x51\x70\x7a\x57\x78\x4b\x45\x4c\x57\x42\x63\x79\x4d\x74\x75\x55\x44\x57\x46\x4e\x6c\x69\x64\x70\x46\x46\x65\x6e\x65\x64\x66\x48\x30\x69\x74\x66\x59\x67\x38\x52\x47\x41\x6b\x38\x6c\x76\x72\x31","label":"0","type":"hls","preload":"none"}];var mu=getLocation(jwSetup.sources[0].file);
|
|
320
|
+
|
|
321
|
+
# ! Veya
|
|
322
|
+
|
|
323
|
+
while Packer.detect_packed(veri):
|
|
324
|
+
veri = Packer.unpack(veri)
|
|
319
325
|
```
|
|
320
326
|
|
|
321
327
|
### **[CryptoJS](https://github.com/keyiflerolsun/Kekik/blob/main/Kekik/Sifreleme/CryptoJS.py)**
|
|
@@ -1,6 +1,6 @@
|
|
|
1
|
-
Metadata-Version: 2.
|
|
1
|
+
Metadata-Version: 2.4
|
|
2
2
|
Name: Kekik
|
|
3
|
-
Version: 1.7.
|
|
3
|
+
Version: 1.7.9
|
|
4
4
|
Summary: İşlerimizi kolaylaştıracak fonksiyonların el altında durduğu kütüphane..
|
|
5
5
|
Home-page: https://github.com/keyiflerolsun/Kekik
|
|
6
6
|
Author: keyiflerolsun
|
|
@@ -35,6 +35,7 @@ Dynamic: description-content-type
|
|
|
35
35
|
Dynamic: home-page
|
|
36
36
|
Dynamic: keywords
|
|
37
37
|
Dynamic: license
|
|
38
|
+
Dynamic: license-file
|
|
38
39
|
Dynamic: requires-dist
|
|
39
40
|
Dynamic: requires-python
|
|
40
41
|
Dynamic: summary
|
|
@@ -316,6 +317,11 @@ var played = 0;
|
|
|
316
317
|
eval_jwSetup = re.compile(r'\};\s*(eval\(function[\s\S]*?)var played = \d+;').findall(veri)[0]
|
|
317
318
|
print(Packer.unpack(Packer.unpack(eval_jwSetup)))
|
|
318
319
|
# jwSetup.sources=[{"default":true,"file":"\x68\x74\x74\x70\x73\x3a\x2f\x2f\x64\x32\x2e\x69\x6d\x61\x67\x65\x73\x70\x6f\x74\x2e\x62\x75\x7a\x7a\x2f\x66\x32\x2f\x4e\x74\x4f\x31\x4e\x51\x5a\x6a\x44\x51\x41\x6b\x78\x6c\x58\x45\x47\x33\x6c\x62\x66\x62\x30\x31\x79\x74\x70\x57\x66\x4e\x30\x66\x62\x66\x50\x58\x5a\x55\x31\x6a\x50\x77\x5a\x6d\x48\x71\x58\x41\x37\x6c\x6d\x6d\x4b\x67\x47\x59\x31\x66\x47\x42\x6d\x6c\x38\x68\x32\x7a\x33\x4f\x5a\x69\x4f\x63\x4c\x6b\x51\x70\x7a\x57\x78\x4b\x45\x4c\x57\x42\x63\x79\x4d\x74\x75\x55\x44\x57\x46\x4e\x6c\x69\x64\x70\x46\x46\x65\x6e\x65\x64\x66\x48\x30\x69\x74\x66\x59\x67\x38\x52\x47\x41\x6b\x38\x6c\x76\x72\x31","label":"0","type":"hls","preload":"none"}];var mu=getLocation(jwSetup.sources[0].file);
|
|
320
|
+
|
|
321
|
+
# ! Veya
|
|
322
|
+
|
|
323
|
+
while Packer.detect_packed(veri):
|
|
324
|
+
veri = Packer.unpack(veri)
|
|
319
325
|
```
|
|
320
326
|
|
|
321
327
|
### **[CryptoJS](https://github.com/keyiflerolsun/Kekik/blob/main/Kekik/Sifreleme/CryptoJS.py)**
|
|
@@ -275,6 +275,11 @@ var played = 0;
|
|
|
275
275
|
eval_jwSetup = re.compile(r'\};\s*(eval\(function[\s\S]*?)var played = \d+;').findall(veri)[0]
|
|
276
276
|
print(Packer.unpack(Packer.unpack(eval_jwSetup)))
|
|
277
277
|
# jwSetup.sources=[{"default":true,"file":"\x68\x74\x74\x70\x73\x3a\x2f\x2f\x64\x32\x2e\x69\x6d\x61\x67\x65\x73\x70\x6f\x74\x2e\x62\x75\x7a\x7a\x2f\x66\x32\x2f\x4e\x74\x4f\x31\x4e\x51\x5a\x6a\x44\x51\x41\x6b\x78\x6c\x58\x45\x47\x33\x6c\x62\x66\x62\x30\x31\x79\x74\x70\x57\x66\x4e\x30\x66\x62\x66\x50\x58\x5a\x55\x31\x6a\x50\x77\x5a\x6d\x48\x71\x58\x41\x37\x6c\x6d\x6d\x4b\x67\x47\x59\x31\x66\x47\x42\x6d\x6c\x38\x68\x32\x7a\x33\x4f\x5a\x69\x4f\x63\x4c\x6b\x51\x70\x7a\x57\x78\x4b\x45\x4c\x57\x42\x63\x79\x4d\x74\x75\x55\x44\x57\x46\x4e\x6c\x69\x64\x70\x46\x46\x65\x6e\x65\x64\x66\x48\x30\x69\x74\x66\x59\x67\x38\x52\x47\x41\x6b\x38\x6c\x76\x72\x31","label":"0","type":"hls","preload":"none"}];var mu=getLocation(jwSetup.sources[0].file);
|
|
278
|
+
|
|
279
|
+
# ! Veya
|
|
280
|
+
|
|
281
|
+
while Packer.detect_packed(veri):
|
|
282
|
+
veri = Packer.unpack(veri)
|
|
278
283
|
```
|
|
279
284
|
|
|
280
285
|
### **[CryptoJS](https://github.com/keyiflerolsun/Kekik/blob/main/Kekik/Sifreleme/CryptoJS.py)**
|
|
@@ -6,7 +6,7 @@ from io import open
|
|
|
6
6
|
setup(
|
|
7
7
|
# ? Genel Bilgiler
|
|
8
8
|
name = "Kekik",
|
|
9
|
-
version = "1.7.
|
|
9
|
+
version = "1.7.9",
|
|
10
10
|
url = "https://github.com/keyiflerolsun/Kekik",
|
|
11
11
|
description = "İşlerimizi kolaylaştıracak fonksiyonların el altında durduğu kütüphane..",
|
|
12
12
|
keywords = ["Kekik", "KekikAkademi", "keyiflerolsun"],
|
|
@@ -1,62 +0,0 @@
|
|
|
1
|
-
# ! Bu araç @keyiflerolsun tarafından | @KekikAkademi için yazılmıştır.
|
|
2
|
-
|
|
3
|
-
import re
|
|
4
|
-
|
|
5
|
-
class Packer:
|
|
6
|
-
"""
|
|
7
|
-
P.A.C.K.E.R. sıkıştırma ve çözme işlemleri için bir sınıf.
|
|
8
|
-
! » https://github.com/beautifier/js-beautify/blob/main/python/jsbeautifier/unpackers/packer.py
|
|
9
|
-
"""
|
|
10
|
-
@staticmethod
|
|
11
|
-
def clean_escape_sequences(source: str) -> str:
|
|
12
|
-
"""Kaçış dizilerini temizler."""
|
|
13
|
-
source = re.sub(r'\\\\', r'\\', source)
|
|
14
|
-
source = source.replace("\\'", "'")
|
|
15
|
-
source = source.replace('\\"', '"')
|
|
16
|
-
return source
|
|
17
|
-
|
|
18
|
-
@staticmethod
|
|
19
|
-
def extract_arguments(source: str) -> tuple[str, list[str], int, int]:
|
|
20
|
-
"""P.A.C.K.E.R. formatındaki kaynak koddan argümanları çıkarır."""
|
|
21
|
-
match = re.search(r"}\('(.*)',(\d+),(\d+),'(.*)'\.split\('\|'\)", source, re.DOTALL)
|
|
22
|
-
|
|
23
|
-
if not match:
|
|
24
|
-
raise ValueError("Invalid P.A.C.K.E.R. source format.")
|
|
25
|
-
|
|
26
|
-
payload, radix, count, symtab = match.groups()
|
|
27
|
-
|
|
28
|
-
return payload, symtab.split("|"), int(radix), int(count)
|
|
29
|
-
|
|
30
|
-
@staticmethod
|
|
31
|
-
def convert_base(s: str, base: int) -> int:
|
|
32
|
-
"""Bir sayıyı belirli bir tabandan ondalık tabana çevirir."""
|
|
33
|
-
alphabet = "0123456789abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ"
|
|
34
|
-
|
|
35
|
-
return sum(alphabet.index(char) * (base**idx) for idx, char in enumerate(reversed(s)))
|
|
36
|
-
|
|
37
|
-
@staticmethod
|
|
38
|
-
def lookup_symbol(match: re.Match, symtab: list[str], radix: int) -> str:
|
|
39
|
-
"""Sembolleri arar ve yerine koyar."""
|
|
40
|
-
word = match[0]
|
|
41
|
-
|
|
42
|
-
return symtab[Packer.convert_base(word, radix)] or word
|
|
43
|
-
|
|
44
|
-
@staticmethod
|
|
45
|
-
def unpack(source: str) -> str:
|
|
46
|
-
"""P.A.C.K.E.R. formatındaki sıkıştırılmış bir kaynağı çözer."""
|
|
47
|
-
source = Packer.clean_escape_sequences(source)
|
|
48
|
-
|
|
49
|
-
payload, symtab, radix, count = Packer.extract_arguments(source)
|
|
50
|
-
|
|
51
|
-
if count != len(symtab):
|
|
52
|
-
raise ValueError("Malformed P.A.C.K.E.R. symtab.")
|
|
53
|
-
|
|
54
|
-
return re.sub(r"\b\w+\b", lambda match: Packer.lookup_symbol(match, symtab, radix), payload)
|
|
55
|
-
|
|
56
|
-
@staticmethod
|
|
57
|
-
def pack(source: str, radix: int = 62) -> str:
|
|
58
|
-
"""Bir metni P.A.C.K.E.R. formatında sıkıştırır."""
|
|
59
|
-
# Bu işlev, simgeleri ve sıkıştırılmış metni yeniden oluşturmak için bir yol sağlar.
|
|
60
|
-
# Ancak bu, belirli bir algoritma veya sıkıştırma tekniğine bağlıdır.
|
|
61
|
-
# Gerçekleştirilmesi zor olabilir çünkü P.A.C.K.E.R.'ın spesifik sıkıştırma mantığını takip etmek gerekir.
|
|
62
|
-
raise NotImplementedError("Packing function is not implemented.")
|
|
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
|