absfuyu 4.1.1__py3-none-any.whl → 5.0.0__py3-none-any.whl

This diff represents the content of publicly available package versions that have been released to one of the supported registries. The information contained in this diff is provided for informational purposes only and reflects changes between package versions as they appear in their respective public registries.

Potentially problematic release.


This version of absfuyu might be problematic. Click here for more details.

Files changed (76) hide show
  1. absfuyu/__init__.py +4 -4
  2. absfuyu/__main__.py +13 -1
  3. absfuyu/cli/__init__.py +4 -2
  4. absfuyu/cli/color.py +7 -0
  5. absfuyu/cli/do_group.py +9 -91
  6. absfuyu/cli/tool_group.py +136 -0
  7. absfuyu/config/__init__.py +17 -34
  8. absfuyu/core/__init__.py +49 -0
  9. absfuyu/core/baseclass.py +299 -0
  10. absfuyu/core/baseclass2.py +165 -0
  11. absfuyu/core/decorator.py +67 -0
  12. absfuyu/core/docstring.py +163 -0
  13. absfuyu/core/dummy_cli.py +67 -0
  14. absfuyu/core/dummy_func.py +47 -0
  15. absfuyu/dxt/__init__.py +42 -0
  16. absfuyu/dxt/dictext.py +201 -0
  17. absfuyu/dxt/dxt_support.py +79 -0
  18. absfuyu/dxt/intext.py +586 -0
  19. absfuyu/dxt/listext.py +508 -0
  20. absfuyu/dxt/strext.py +530 -0
  21. absfuyu/{extensions → extra}/__init__.py +3 -2
  22. absfuyu/extra/beautiful.py +251 -0
  23. absfuyu/{extensions/extra → extra}/data_analysis.py +51 -82
  24. absfuyu/fun/__init__.py +110 -135
  25. absfuyu/fun/tarot.py +9 -17
  26. absfuyu/game/__init__.py +6 -0
  27. absfuyu/game/game_stat.py +6 -0
  28. absfuyu/game/sudoku.py +7 -1
  29. absfuyu/game/tictactoe.py +12 -5
  30. absfuyu/game/wordle.py +14 -8
  31. absfuyu/general/__init__.py +6 -79
  32. absfuyu/general/content.py +22 -36
  33. absfuyu/general/generator.py +17 -42
  34. absfuyu/general/human.py +108 -228
  35. absfuyu/general/shape.py +1334 -0
  36. absfuyu/logger.py +8 -13
  37. absfuyu/pkg_data/__init__.py +137 -99
  38. absfuyu/pkg_data/deprecated.py +133 -0
  39. absfuyu/pkg_data/passwordlib_lzma.pkl +0 -0
  40. absfuyu/sort.py +6 -130
  41. absfuyu/tools/__init__.py +2 -2
  42. absfuyu/tools/checksum.py +44 -22
  43. absfuyu/tools/converter.py +82 -50
  44. absfuyu/tools/keygen.py +25 -30
  45. absfuyu/tools/obfuscator.py +246 -112
  46. absfuyu/tools/passwordlib.py +330 -0
  47. absfuyu/tools/shutdownizer.py +287 -0
  48. absfuyu/tools/web.py +2 -9
  49. absfuyu/util/__init__.py +15 -15
  50. absfuyu/util/api.py +10 -15
  51. absfuyu/util/json_method.py +7 -24
  52. absfuyu/util/lunar.py +3 -9
  53. absfuyu/util/path.py +22 -27
  54. absfuyu/util/performance.py +43 -67
  55. absfuyu/util/shorten_number.py +65 -14
  56. absfuyu/util/zipped.py +9 -15
  57. absfuyu-5.0.0.dist-info/METADATA +143 -0
  58. absfuyu-5.0.0.dist-info/RECORD +68 -0
  59. absfuyu/core.py +0 -57
  60. absfuyu/everything.py +0 -32
  61. absfuyu/extensions/beautiful.py +0 -188
  62. absfuyu/extensions/dev/__init__.py +0 -244
  63. absfuyu/extensions/dev/password_hash.py +0 -80
  64. absfuyu/extensions/dev/passwordlib.py +0 -258
  65. absfuyu/extensions/dev/project_starter.py +0 -60
  66. absfuyu/extensions/dev/shutdownizer.py +0 -156
  67. absfuyu/extensions/extra/__init__.py +0 -24
  68. absfuyu/fun/WGS.py +0 -134
  69. absfuyu/general/data_extension.py +0 -1796
  70. absfuyu/tools/stats.py +0 -226
  71. absfuyu/util/pkl.py +0 -67
  72. absfuyu-4.1.1.dist-info/METADATA +0 -121
  73. absfuyu-4.1.1.dist-info/RECORD +0 -61
  74. {absfuyu-4.1.1.dist-info → absfuyu-5.0.0.dist-info}/WHEEL +0 -0
  75. {absfuyu-4.1.1.dist-info → absfuyu-5.0.0.dist-info}/entry_points.txt +0 -0
  76. {absfuyu-4.1.1.dist-info → absfuyu-5.0.0.dist-info}/licenses/LICENSE +0 -0
@@ -3,38 +3,121 @@ Absfuyu: Obfuscator
3
3
  -------------------
4
4
  Obfuscate code
5
5
 
6
- Version: 2.0.2
7
- Date updated: 05/04/2024 (dd/mm/yyyy)
6
+ Version: 5.0.0
7
+ Date updated: 23/02/2025 (dd/mm/yyyy)
8
8
  """
9
9
 
10
10
  # Module level
11
- ###########################################################################
12
- __all__ = ["Obfuscator"]
11
+ # ---------------------------------------------------------------------------
12
+ __all__ = ["Obfuscator", "StrShifter"]
13
13
 
14
14
 
15
15
  # Library
16
- ###########################################################################
16
+ # ---------------------------------------------------------------------------
17
17
  import base64
18
18
  import codecs
19
19
  import random
20
20
  import zlib
21
+ from collections import deque
22
+ from string import Template
23
+ from typing import ClassVar
21
24
 
22
- from absfuyu.general.data_extension import Text
23
- from absfuyu.general.generator import Charset
24
- from absfuyu.general.generator import Generator as gen
25
+ from absfuyu.core import BaseClass, ShowAllMethodsMixin, versionadded
26
+ from absfuyu.dxt import Text
27
+ from absfuyu.general.generator import Charset, Generator
25
28
  from absfuyu.logger import logger
26
29
 
27
30
 
28
31
  # Class
29
- ###########################################################################
30
- class ObfuscatorLibraryList:
31
- BASE64_ONLY = ["base64"]
32
- FULL = ["base64", "codecs", "zlib"]
32
+ # ---------------------------------------------------------------------------
33
+ @versionadded("5.0.0")
34
+ class StrShifter(BaseClass):
35
+ """Shift characters in a string by a specified number of positions."""
33
36
 
37
+ __slots__ = ("_str_to_shift", "shift_by")
34
38
 
35
- class Obfuscator:
39
+ def __init__(self, str_to_shift: str, shift_by: int = 5) -> None:
40
+ """
41
+ Initialize the StrShifter with the string to shift and the shift amount.
42
+
43
+ Parameters
44
+ ----------
45
+ str_to_shift : str
46
+ The string whose characters will be shifted.
47
+
48
+ shift_by : int, optional
49
+ The number of positions to shift the characters, by default ``5``.
50
+ """
51
+ if not isinstance(str_to_shift, str):
52
+ raise TypeError("Value must be an instance of str")
53
+ self._str_to_shift = str_to_shift
54
+ self.shift_by = shift_by
55
+
56
+ def _make_convert_table(self) -> dict[str, str]:
57
+ """
58
+ Create a translation table for shifting characters.
59
+
60
+ Returns
61
+ -------
62
+ dict[str, str]
63
+ A dictionary mapping each character to its shifted counterpart.
64
+ """
65
+ data = self._str_to_shift # Make a copy
66
+
67
+ unique_char_sorted = deque(sorted(list(set(data))))
68
+ translate = unique_char_sorted.copy()
69
+ translate.rotate(self.shift_by)
70
+ convert_table = dict(zip(unique_char_sorted, translate))
71
+
72
+ return convert_table
73
+
74
+ def _use_convert_table(self, convert_table: dict[str, str]) -> str:
75
+ """
76
+ Convert the original string using the provided conversion table.
77
+
78
+ Parameters
79
+ ----------
80
+ convert_table : dict[str, str]
81
+ The conversion table mapping original characters to shifted characters.
82
+
83
+ Returns
84
+ -------
85
+ str
86
+ The transformed string after applying the conversion table.
87
+ """
88
+ return "".join([convert_table[char] for char in list(self._str_to_shift)])
89
+
90
+ def shift(self) -> str:
91
+ """
92
+ Shift the characters in the string and return the new string.
93
+
94
+ Returns
95
+ -------
96
+ str
97
+ The resulting string after shifting.
98
+ """
99
+ return self._use_convert_table(self._make_convert_table())
100
+
101
+
102
+ class Obfuscator(ShowAllMethodsMixin):
36
103
  """Obfuscate code"""
37
104
 
105
+ # Var
106
+ LIB_BASE64_ONLY: ClassVar[list[str]] = ["base64"]
107
+ LIB_FULL: ClassVar[list[str]] = ["base64", "codecs", "zlib"]
108
+
109
+ # Template
110
+ SINGLE_LINE_TEMPLATE: ClassVar[Template] = Template(
111
+ "exec(bytes.fromhex('$one_line_code').decode('utf-8'))"
112
+ )
113
+ PRE_HEX_B64_TEMPLATE: ClassVar[Template] = Template(
114
+ "eval(compile(base64.b64decode($encoded_string),$type_var,$execute))"
115
+ )
116
+ PRE_HEX_FULL_TEMPLATE: ClassVar[Template] = Template(
117
+ "eval(compile(base64.b64decode(zlib.decompress(base64.b64decode(codecs."
118
+ "encode($encoded_string,$codec_to_decode).encode()))),$type_var,$execute))"
119
+ )
120
+
38
121
  def __init__(
39
122
  self,
40
123
  code: str,
@@ -45,56 +128,73 @@ class Obfuscator:
45
128
  fake_data: bool = False,
46
129
  ) -> None:
47
130
  """
48
- code: Code text
49
- base64_only: False: base64, compress, rot13 (default) | True: encode in base64 form only
50
- split_every: Split the long line of code every `x` character
51
- variable_length: Length of variable name (when data string split). Minimum is 7
52
- fake_data: Generate additional meaningless data
131
+ Obfuscator
132
+
133
+ Parameters
134
+ ----------
135
+ code : str
136
+ Code text
137
+
138
+ base64_only : bool, optional
139
+ - ``True``: encode in base64 form only
140
+ - ``False``: base64, compress, rot13 (default)
141
+
142
+ split_every : int, optional
143
+ Split the long line of code every ``x`` character.
144
+ Minimum is ``1``, by default ``60``
145
+
146
+ variable_length : int, optional
147
+ Length of variable name (when data string split).
148
+ Minimum is ``7``, by default ``12``
149
+
150
+ fake_data : bool, optional
151
+ Generate additional meaningless data, by default ``False``
53
152
  """
54
153
  self.base_code = code
55
154
  self.base64_only = base64_only
56
- self.split_every_length = split_every
57
- self.variable_length = variable_length if variable_length > 6 else 7
155
+ self.split_every_length = max(1, split_every)
156
+ self.variable_length = max(7, variable_length)
58
157
  self.fake_data = fake_data
59
158
 
60
159
  # Setting
61
160
  self._library_import_variable_length = self.variable_length - 1
62
161
  self._splited_variable_length = self.variable_length
63
162
  self._decode_variable_length = self.variable_length + 3
64
- # logger.debug("Class initiated.")
65
163
 
66
164
  def __str__(self) -> str:
67
- # temp = self.__dict__
68
- temp = {
165
+ return self.__repr__()
166
+
167
+ def __repr__(self) -> str:
168
+ repr_out_dict = {
69
169
  "base_code": "...",
70
170
  "base64_only": self.base64_only,
71
171
  "split_every_length": self.split_every_length,
72
172
  "variable_length": self.variable_length,
73
173
  "fake_data": self.fake_data,
74
174
  }
75
- return f"{self.__class__.__name__}({temp})"
76
-
77
- def __repr__(self) -> str:
78
- return self.__str__()
175
+ repr_out = ", ".join([f"{k}={repr(v)}" for k, v in repr_out_dict.items()])
176
+ return f"{self.__class__.__name__}({repr_out})"
79
177
 
80
178
  def to_single_line(self) -> str:
81
179
  """
82
180
  Convert multiple lines of code into one line
83
181
 
84
- :returns: Converted code
85
- :rtype: str
182
+ Returns
183
+ -------
184
+ str
185
+ Converted code.
86
186
  """
87
187
  newcode = self.base_code.encode("utf-8").hex()
88
- logger.debug(newcode)
89
- output = f"exec(bytes.fromhex('{newcode}').decode('utf-8'))"
188
+ output = self.SINGLE_LINE_TEMPLATE.substitute(one_line_code=newcode)
90
189
  return output
91
190
 
191
+ # Obfuscate original code
92
192
  def _obfuscate(self) -> str:
93
193
  """
94
194
  Convert multiple lines of code through multiple transformation
95
195
  (base64 -> compress -> base64 -> caesar (13))
96
196
  """
97
- code = self.base_code
197
+ code = self.base_code # Make a copy
98
198
  logger.debug("Encoding...")
99
199
 
100
200
  b64_encode = base64.b64encode(code.encode())
@@ -102,12 +202,12 @@ class Obfuscator:
102
202
  output = b64_encode.decode()
103
203
  else:
104
204
  compressed_data = zlib.compress(b64_encode)
105
- # log_debug(compressed_data)
106
- logger.debug(f"Compressed data: {compressed_data}") # type: ignore
107
- b64_encode_2 = base64.b64encode(compressed_data)
108
- # log_debug(b64_encode_2)
109
- logger.debug(f"Base64 encode 2: {b64_encode_2}") # type: ignore
110
- caesar_data = codecs.encode(b64_encode_2.decode(), "rot_13")
205
+ logger.debug(
206
+ f"Compressed data: {str(compressed_data)} | Len: {len(str(compressed_data))}"
207
+ )
208
+ b64_encode_2 = base64.b64encode(compressed_data).decode()
209
+ logger.debug(f"Base64 encode 2: {b64_encode_2} | Len: {len(b64_encode_2)}")
210
+ caesar_data = codecs.encode(b64_encode_2, "rot_13")
111
211
  output = caesar_data
112
212
 
113
213
  logger.debug(f"Output: {output}")
@@ -122,16 +222,100 @@ class Obfuscator:
122
222
  text: Code that need to convert
123
223
  raw: Return hex form only
124
224
  """
125
- encode_codec = "rot_13"
126
- b64_encode_codec = base64.b64encode(encode_codec.encode()).decode()
127
- b64_decode_codec = f"base64.b64decode('{b64_encode_codec}'.encode())"
225
+ b64_encode_codec = base64.b64encode(text.encode()).decode()
226
+ b64_decode_codec = f"base64.b64decode('{b64_encode_codec}'.encode()).decode()"
128
227
  hex = Text(b64_decode_codec).to_hex()
129
- out = f"eval('{hex}').decode()"
228
+ out = f"eval('{hex}')"
130
229
  if raw:
131
230
  return hex
132
231
  return out
133
232
 
134
- def _obfuscate_out(self) -> list: # type: ignore
233
+ # Generate output (decode obfuscated code)
234
+ def _make_output_lib(self) -> list[str]:
235
+ """Obfuscate the `import <lib>`"""
236
+ output = []
237
+
238
+ # Make import lib
239
+ library_list = self.LIB_BASE64_ONLY if self.base64_only else self.LIB_FULL
240
+ imports = [f"import {lib}" for lib in library_list]
241
+ logger.debug(f"Lib: {imports}")
242
+
243
+ # Convert to hex
244
+ lib_hex = Text("\n".join(imports)).to_hex()
245
+ output.append(f"exec('{lib_hex}')")
246
+ logger.debug(f"Current output (import library): {output}")
247
+
248
+ return output
249
+
250
+ def _make_prep_for_decode_var(self) -> tuple[list[str], list[str]]:
251
+ """
252
+ ``<var> = "rot_13"``
253
+ ``<var> = "<string>"``
254
+ ``<var> = "exec"``
255
+
256
+ Returns
257
+ -------
258
+ tuple[list[str], list[str]]
259
+ - tuple[0]: output
260
+ - tuple[1]: decode var name
261
+ """
262
+ output = []
263
+
264
+ # Make variables for "rot_13", "<string>", "exec"
265
+ dc_name_lst: list[str] = Generator.generate_string(
266
+ charset=Charset.ALPHABET,
267
+ size=self._decode_variable_length,
268
+ times=3,
269
+ unique=True,
270
+ )
271
+
272
+ # Assign and convert to hex
273
+ encode_codec = "rot_13" # full
274
+ if not self.base64_only: # full
275
+ hex_0 = self._convert_to_base64_decode(encode_codec)
276
+ output.append(f"{dc_name_lst[0]}={hex_0}")
277
+
278
+ for i, x in enumerate(["<string>", "exec"], start=1):
279
+ # hex_str = Text(x).to_hex()
280
+ hex_str = self._convert_to_base64_decode(x)
281
+ output.append(f"{dc_name_lst[i]}={hex_str}")
282
+ logger.debug(f"Current output (decode variables): {output}")
283
+
284
+ return output, dc_name_lst
285
+
286
+ def _make_fake_output(self, input_size: int) -> list[str]:
287
+ """Fake data"""
288
+ output = []
289
+
290
+ f1 = Generator.generate_string(
291
+ charset=Charset.DEFAULT,
292
+ size=input_size,
293
+ times=1,
294
+ string_type_if_1=True,
295
+ ) # Generate fake data with len of original data
296
+ f2 = Text(f1).divide_with_variable(
297
+ self.split_every_length, self._splited_variable_length
298
+ )
299
+ output.extend(f2[:-1])
300
+
301
+ # Random data
302
+ bait_lst = Generator.generate_string(
303
+ charset=Charset.ALPHABET, size=self._splited_variable_length, times=25
304
+ )
305
+ for x in bait_lst:
306
+ output.append(
307
+ f"{x}='{Generator.generate_string(charset=Charset.DEFAULT, size=self.split_every_length, times=1, string_type_if_1=True)}'"
308
+ )
309
+
310
+ random_eval_text = str(random.randint(1, 100))
311
+ for _ in range(random.randint(10, 50)):
312
+ random_eval_text += f"+{random.randint(1, 100)}"
313
+ random_eval_text_final = Text(random_eval_text).to_hex()
314
+ output.append(f"eval('{random_eval_text_final}')")
315
+
316
+ return output
317
+
318
+ def _make_obfuscate_output(self) -> list[str]:
135
319
  """
136
320
  Convert multiple lines of code through multiple transformation
137
321
  (base64 -> compress -> base64 -> caesar (13))
@@ -146,16 +330,7 @@ class Obfuscator:
146
330
  output = []
147
331
 
148
332
  # Import library
149
- library_list = (
150
- ObfuscatorLibraryList.BASE64_ONLY
151
- if self.base64_only
152
- else ObfuscatorLibraryList.FULL
153
- )
154
- temp = [f"import {lib}" for lib in library_list]
155
- logger.debug(f"Lib: {temp}")
156
- lib_hex = Text("\n".join(temp)).to_hex() # Convert to hex
157
- output.append(f"exec('{lib_hex}')")
158
- logger.debug(f"Current output (import library): {output}")
333
+ output.extend(self._make_output_lib())
159
334
 
160
335
  # Append divided long text list
161
336
  input_list = input_str.divide_with_variable(
@@ -167,64 +342,30 @@ class Obfuscator:
167
342
  logger.debug(f"Current output (encoded code): {output}")
168
343
 
169
344
  # Decode: encoded_str
170
- dc_name_lst = gen.generate_string(
171
- charset=Charset.ALPHABET, size=self._decode_variable_length, times=3
172
- )
173
- encode_codec = "rot_13" # full
174
- if not self.base64_only: # full
175
- hex_0 = self._convert_to_base64_decode(encode_codec)
176
- output.append(f"{dc_name_lst[0]}={hex_0}")
177
- hex_1 = Text("<string>").to_hex()
178
- output.append(f"{dc_name_lst[1]}='{hex_1}'")
179
- hex_2 = Text("exec").to_hex()
180
- output.append(f"{dc_name_lst[2]}='{hex_2}'")
181
- logger.debug(f"Current output (decode variables): {output}")
345
+ dc_out, dc_name_lst = self._make_prep_for_decode_var()
346
+ output.extend(dc_out)
182
347
 
183
348
  if self.base64_only: # b64
184
- pre_hex = (
185
- f"eval(compile(base64."
186
- f"b64decode({encoded_str}),{dc_name_lst[1]},"
187
- f"{dc_name_lst[2]}))"
349
+ pre_hex = self.PRE_HEX_B64_TEMPLATE.substitute(
350
+ encoded_string=encoded_str,
351
+ type_var=dc_name_lst[1],
352
+ execute=dc_name_lst[2],
188
353
  )
189
354
  else: # full
190
- pre_hex = (
191
- f"eval(compile(base64."
192
- f"b64decode(zlib.decompress(base64."
193
- f"b64decode(codecs."
194
- f"encode({encoded_str},{dc_name_lst[0]})."
195
- f"encode()))),{dc_name_lst[1]},{dc_name_lst[2]}))"
355
+ pre_hex = self.PRE_HEX_FULL_TEMPLATE.substitute(
356
+ encoded_string=encoded_str,
357
+ codec_to_decode=dc_name_lst[0],
358
+ type_var=dc_name_lst[1],
359
+ execute=dc_name_lst[2],
196
360
  )
361
+
197
362
  t_hex = Text(pre_hex).to_hex()
198
363
  output.append(f"exec('{t_hex}')")
199
364
  logger.debug(f"Current output (decode code): {output}")
200
365
 
201
366
  # Fake data
202
367
  if self.fake_data:
203
- f1 = gen.generate_string(
204
- charset=Charset.DEFAULT,
205
- size=len(input_str),
206
- times=1,
207
- string_type_if_1=True,
208
- ) # Generate fake data with len of original data
209
- f2 = Text(f1).divide_with_variable(
210
- self.split_every_length, self._splited_variable_length
211
- )
212
- output.extend(f2[:-1])
213
-
214
- # Random data
215
- bait_lst = gen.generate_string(
216
- charset=Charset.ALPHABET, size=self._splited_variable_length, times=25
217
- )
218
- for x in bait_lst:
219
- output.append(
220
- f"{x}='{gen.generate_string(charset=Charset.DEFAULT, size=self.split_every_length, times=1, string_type_if_1=True)}'"
221
- )
222
-
223
- random_eval_text = str(random.randint(1, 100))
224
- for _ in range(random.randint(10, 50)):
225
- random_eval_text += f"+{random.randint(1, 100)}"
226
- random_eval_text_final = Text(random_eval_text).to_hex()
227
- output.append(f"eval('{random_eval_text_final}')")
368
+ output.extend(self._make_fake_output(len(input_str)))
228
369
 
229
370
  logger.debug("Code obfuscated.")
230
371
  return output
@@ -233,16 +374,9 @@ class Obfuscator:
233
374
  """
234
375
  Obfuscate code
235
376
 
236
- :returns: Obfuscated code
237
- :rtype: str
377
+ Returns
378
+ -------
379
+ str
380
+ Obfuscated code
238
381
  """
239
- return "\n".join(self._obfuscate_out())
240
-
241
-
242
- # Run
243
- ###########################################################################
244
- if __name__ == "__main__":
245
- logger.setLevel(10)
246
- code = "print('Hello World')"
247
- test = Obfuscator(code, fake_data=True)
248
- print(test.obfuscate())
382
+ return "\n".join(self._make_obfuscate_output())