absfuyu 4.1.1__py3-none-any.whl → 4.2.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.
- absfuyu/__init__.py +1 -1
- absfuyu/cli/__init__.py +4 -2
- absfuyu/cli/do_group.py +14 -61
- absfuyu/cli/tool_group.py +136 -0
- absfuyu/core.py +3 -3
- absfuyu/extensions/__init__.py +1 -0
- absfuyu/pkg_data/__init__.py +2 -1
- absfuyu/pkg_data/passwordlib_lzma.pkl +0 -0
- absfuyu/tools/checksum.py +15 -4
- absfuyu/tools/converter.py +36 -7
- absfuyu/{extensions/dev → tools}/passwordlib.py +52 -50
- absfuyu/tools/shutdownizer.py +266 -0
- absfuyu/util/shorten_number.py +1 -1
- {absfuyu-4.1.1.dist-info → absfuyu-4.2.0.dist-info}/METADATA +13 -18
- {absfuyu-4.1.1.dist-info → absfuyu-4.2.0.dist-info}/RECORD +19 -21
- absfuyu/extensions/dev/__init__.py +0 -244
- absfuyu/extensions/dev/password_hash.py +0 -80
- absfuyu/extensions/dev/project_starter.py +0 -60
- absfuyu/extensions/dev/shutdownizer.py +0 -156
- absfuyu/extensions/extra/__init__.py +0 -24
- /absfuyu/extensions/{extra/data_analysis.py → data_analysis.py} +0 -0
- {absfuyu-4.1.1.dist-info → absfuyu-4.2.0.dist-info}/WHEEL +0 -0
- {absfuyu-4.1.1.dist-info → absfuyu-4.2.0.dist-info}/entry_points.txt +0 -0
- {absfuyu-4.1.1.dist-info → absfuyu-4.2.0.dist-info}/licenses/LICENSE +0 -0
|
@@ -0,0 +1,266 @@
|
|
|
1
|
+
"""
|
|
2
|
+
Absfuyu: Shutdownizer
|
|
3
|
+
---------------------
|
|
4
|
+
This shutdowns
|
|
5
|
+
|
|
6
|
+
Version: 1.0.0
|
|
7
|
+
Date updated: 07/02/2025 (dd/mm/yyyy)
|
|
8
|
+
"""
|
|
9
|
+
|
|
10
|
+
# Module level
|
|
11
|
+
###########################################################################
|
|
12
|
+
__all__ = ["ShutDownizer", "ShutdownEngine"]
|
|
13
|
+
|
|
14
|
+
|
|
15
|
+
# Library
|
|
16
|
+
###########################################################################
|
|
17
|
+
import os
|
|
18
|
+
import subprocess
|
|
19
|
+
import sys
|
|
20
|
+
from abc import ABC, abstractmethod
|
|
21
|
+
from datetime import datetime, time, timedelta
|
|
22
|
+
from pathlib import Path
|
|
23
|
+
from typing import Annotated
|
|
24
|
+
|
|
25
|
+
from absfuyu.logger import logger
|
|
26
|
+
|
|
27
|
+
# TODO: Schedule shutdown, random time shutdown, test
|
|
28
|
+
|
|
29
|
+
|
|
30
|
+
# Class
|
|
31
|
+
###########################################################################
|
|
32
|
+
class ShutDownizer:
|
|
33
|
+
"""
|
|
34
|
+
ShutDownizer
|
|
35
|
+
|
|
36
|
+
Shutdown tool because why not
|
|
37
|
+
"""
|
|
38
|
+
|
|
39
|
+
def __init__(self) -> None:
|
|
40
|
+
self.os: str = sys.platform
|
|
41
|
+
logger.debug(f"Current OS: {self.os}")
|
|
42
|
+
|
|
43
|
+
if self.os in ["win32", "cygwin"]: # Windows
|
|
44
|
+
self.engine = ShutdownEngineWin() # type: ignore
|
|
45
|
+
elif self.os == "darwin": # MacOS
|
|
46
|
+
self.engine = ShutdownEngineMac() # type: ignore
|
|
47
|
+
elif self.os == "linux": # Linux
|
|
48
|
+
self.engine = ShutdownEngineLinux() # type: ignore
|
|
49
|
+
else:
|
|
50
|
+
raise SystemError("OS not supported")
|
|
51
|
+
|
|
52
|
+
def __str__(self) -> str:
|
|
53
|
+
return f"{self.__class__.__name__}({self.os})"
|
|
54
|
+
|
|
55
|
+
def __repr__(self) -> str:
|
|
56
|
+
return self.__str__()
|
|
57
|
+
|
|
58
|
+
def shutdown(self) -> None:
|
|
59
|
+
"""Shutdown"""
|
|
60
|
+
self.engine.shutdown()
|
|
61
|
+
|
|
62
|
+
def restart(self) -> None:
|
|
63
|
+
"""Restart"""
|
|
64
|
+
self.engine.restart()
|
|
65
|
+
|
|
66
|
+
def cancel(self) -> None:
|
|
67
|
+
"""Cancel"""
|
|
68
|
+
self.engine.cancel()
|
|
69
|
+
|
|
70
|
+
|
|
71
|
+
class ShutdownEngine(ABC):
|
|
72
|
+
"""
|
|
73
|
+
Abstract shutdown class for different type of OS
|
|
74
|
+
"""
|
|
75
|
+
|
|
76
|
+
def __str__(self) -> str:
|
|
77
|
+
return f"{self.__class__.__name__}()"
|
|
78
|
+
|
|
79
|
+
def __repr__(self) -> str:
|
|
80
|
+
return self.__str__()
|
|
81
|
+
|
|
82
|
+
def _execute_cmd(self, cmd: str | list) -> None:
|
|
83
|
+
"""Execute the cmd"""
|
|
84
|
+
try:
|
|
85
|
+
if isinstance(cmd, str):
|
|
86
|
+
subprocess.run(cmd.split())
|
|
87
|
+
elif isinstance(cmd, list):
|
|
88
|
+
subprocess.run(cmd)
|
|
89
|
+
except Exception:
|
|
90
|
+
logger.error(f'"{cmd}" failed to run')
|
|
91
|
+
raise ValueError(f'"{cmd}" failed to run') # noqa
|
|
92
|
+
|
|
93
|
+
def _execute_multiple_cmds(self, cmds: list) -> None:
|
|
94
|
+
if not isinstance(cmds, list):
|
|
95
|
+
raise ValueError("cmds must be a <list>")
|
|
96
|
+
for cmd in cmds:
|
|
97
|
+
try:
|
|
98
|
+
logger.debug(f"Executing: {cmd}")
|
|
99
|
+
self._execute_cmd(cmd)
|
|
100
|
+
break
|
|
101
|
+
except Exception:
|
|
102
|
+
logger.error(f'"{cmd}" failed to run')
|
|
103
|
+
|
|
104
|
+
@abstractmethod
|
|
105
|
+
def shutdown(self) -> None:
|
|
106
|
+
"""Shutdown"""
|
|
107
|
+
pass
|
|
108
|
+
|
|
109
|
+
@abstractmethod
|
|
110
|
+
def restart(self) -> None:
|
|
111
|
+
"""Restart"""
|
|
112
|
+
pass
|
|
113
|
+
|
|
114
|
+
@abstractmethod
|
|
115
|
+
def sleep(self) -> None:
|
|
116
|
+
"""Sleep"""
|
|
117
|
+
pass
|
|
118
|
+
|
|
119
|
+
@abstractmethod
|
|
120
|
+
def abort(self) -> None:
|
|
121
|
+
"""Abort/Cancel"""
|
|
122
|
+
pass
|
|
123
|
+
|
|
124
|
+
def cancel(self) -> None:
|
|
125
|
+
"""Abort/Cancel"""
|
|
126
|
+
self.abort()
|
|
127
|
+
|
|
128
|
+
def _calculate_time(
|
|
129
|
+
self,
|
|
130
|
+
h: Annotated[int, "positive"] = 0,
|
|
131
|
+
m: Annotated[int, "positive"] = 0,
|
|
132
|
+
aggregate: bool = True,
|
|
133
|
+
) -> int:
|
|
134
|
+
"""This calculate time for schedule shutdown
|
|
135
|
+
|
|
136
|
+
Parameters
|
|
137
|
+
----------
|
|
138
|
+
h : int, optional
|
|
139
|
+
Hours to add (24h format), by default 0
|
|
140
|
+
m : int, optional
|
|
141
|
+
Minutes to add (24h format), by default 0
|
|
142
|
+
aggregate : bool, optional
|
|
143
|
+
| This add hours and and minutes to `time.now()`, by default ``True``
|
|
144
|
+
| - ``True`` : Add hours and minutes to current time
|
|
145
|
+
| - ``False``: Use ``h`` and ``m`` as fixed time point to shutdown
|
|
146
|
+
|
|
147
|
+
Returns
|
|
148
|
+
-------
|
|
149
|
+
int
|
|
150
|
+
Seconds left to shutdown
|
|
151
|
+
"""
|
|
152
|
+
now = datetime.now()
|
|
153
|
+
if aggregate:
|
|
154
|
+
delta = timedelta(hours=h, minutes=m)
|
|
155
|
+
out = delta.seconds
|
|
156
|
+
else:
|
|
157
|
+
new_time = datetime.combine(now.date(), time(hour=h, minute=m))
|
|
158
|
+
diff = new_time - now
|
|
159
|
+
out = diff.seconds
|
|
160
|
+
return out
|
|
161
|
+
|
|
162
|
+
|
|
163
|
+
class ShutdownEngineWin(ShutdownEngine):
|
|
164
|
+
"""ShutDownizer - Windows"""
|
|
165
|
+
|
|
166
|
+
def shutdown(self) -> None:
|
|
167
|
+
cmds = ["shutdown -f -s -t 0"]
|
|
168
|
+
self._execute_multiple_cmds(cmds)
|
|
169
|
+
|
|
170
|
+
def restart(self) -> None:
|
|
171
|
+
cmds = ["shutdown -r"]
|
|
172
|
+
self._execute_multiple_cmds(cmds)
|
|
173
|
+
|
|
174
|
+
def sleep(self) -> None:
|
|
175
|
+
cmds = ["rundll32.exe powrprof.dll,SetSuspendState 0,1,0"]
|
|
176
|
+
self._execute_multiple_cmds(cmds)
|
|
177
|
+
|
|
178
|
+
def abort(self) -> None:
|
|
179
|
+
cmds = ["shutdown -a"]
|
|
180
|
+
self._execute_multiple_cmds(cmds)
|
|
181
|
+
|
|
182
|
+
def _punish(self, *, are_you_sure_about_this: bool = False) -> None:
|
|
183
|
+
"""Create a `batch` script that shut down computer when boot up"""
|
|
184
|
+
if not are_you_sure_about_this:
|
|
185
|
+
return None
|
|
186
|
+
try:
|
|
187
|
+
startup_folder_win = Path(os.getenv("appdata")).joinpath( # type: ignore
|
|
188
|
+
"Microsoft", "Windows", "Start Menu", "Programs", "Startup"
|
|
189
|
+
)
|
|
190
|
+
with open(startup_folder_win.joinpath("system.bat"), "w") as f:
|
|
191
|
+
f.write("shutdown -f -s -t 0")
|
|
192
|
+
except Exception:
|
|
193
|
+
logger.error("Cannot write file to startup folder")
|
|
194
|
+
|
|
195
|
+
|
|
196
|
+
class ShutdownEngineMac(ShutdownEngine):
|
|
197
|
+
"""ShutDownizer - MacOS"""
|
|
198
|
+
|
|
199
|
+
def shutdown(self) -> None:
|
|
200
|
+
cmds = [
|
|
201
|
+
["osascript", "-e", 'tell application "System Events" to shut down'],
|
|
202
|
+
"pmset sleepnow",
|
|
203
|
+
"shutdown -h now",
|
|
204
|
+
"sudo shutdown -h now",
|
|
205
|
+
]
|
|
206
|
+
self._execute_multiple_cmds(cmds)
|
|
207
|
+
|
|
208
|
+
def restart(self) -> None:
|
|
209
|
+
cmds = [
|
|
210
|
+
["osascript", "-e", 'tell application "System Events" to restart'],
|
|
211
|
+
"shutdown -r now",
|
|
212
|
+
"sudo shutdown -r now",
|
|
213
|
+
]
|
|
214
|
+
self._execute_multiple_cmds(cmds)
|
|
215
|
+
|
|
216
|
+
def sleep(self) -> None:
|
|
217
|
+
cmds = [
|
|
218
|
+
["osascript", "-e", 'tell application "System Events" to sleep'],
|
|
219
|
+
"pmset sleepnow",
|
|
220
|
+
"shutdown -s now",
|
|
221
|
+
"sudo shutdown -s now",
|
|
222
|
+
]
|
|
223
|
+
self._execute_multiple_cmds(cmds)
|
|
224
|
+
|
|
225
|
+
def abort(self) -> None:
|
|
226
|
+
cmds = [
|
|
227
|
+
["osascript", "-e", 'tell application "System Events" to cancel shutdown'],
|
|
228
|
+
"killall shutdown",
|
|
229
|
+
"shutdown -c",
|
|
230
|
+
"sudo shutdown -c",
|
|
231
|
+
]
|
|
232
|
+
self._execute_multiple_cmds(cmds)
|
|
233
|
+
|
|
234
|
+
|
|
235
|
+
class ShutdownEngineLinux(ShutdownEngine):
|
|
236
|
+
"""ShutDownizer - Linux"""
|
|
237
|
+
|
|
238
|
+
def shutdown(self) -> None:
|
|
239
|
+
cmds = [
|
|
240
|
+
"gnome-session-quit --power-off",
|
|
241
|
+
"systemctl --user poweroff",
|
|
242
|
+
"sudo shutdown -h now",
|
|
243
|
+
]
|
|
244
|
+
self._execute_multiple_cmds(cmds)
|
|
245
|
+
|
|
246
|
+
def restart(self) -> None:
|
|
247
|
+
cmds = [
|
|
248
|
+
"gnome-session-quit --reboot",
|
|
249
|
+
"systemctl reboot",
|
|
250
|
+
"sudo shutdown -r now",
|
|
251
|
+
]
|
|
252
|
+
self._execute_multiple_cmds(cmds)
|
|
253
|
+
|
|
254
|
+
def sleep(self) -> None:
|
|
255
|
+
cmds = ["systemctl suspend", "sudo shutdown -s now"]
|
|
256
|
+
self._execute_multiple_cmds(cmds)
|
|
257
|
+
|
|
258
|
+
def abort(self) -> None:
|
|
259
|
+
cmds = ["sudo shutdown -c"]
|
|
260
|
+
self._execute_multiple_cmds(cmds)
|
|
261
|
+
|
|
262
|
+
|
|
263
|
+
# Run
|
|
264
|
+
###########################################################################
|
|
265
|
+
if __name__ == "__main__":
|
|
266
|
+
pass
|
absfuyu/util/shorten_number.py
CHANGED
|
@@ -1,6 +1,6 @@
|
|
|
1
1
|
Metadata-Version: 2.4
|
|
2
2
|
Name: absfuyu
|
|
3
|
-
Version: 4.
|
|
3
|
+
Version: 4.2.0
|
|
4
4
|
Summary: A small collection of code
|
|
5
5
|
Project-URL: Homepage, https://github.com/AbsoluteWinter/absfuyu-public
|
|
6
6
|
Project-URL: Documentation, https://absolutewinter.github.io/absfuyu-docs/
|
|
@@ -42,30 +42,26 @@ Provides-Extra: extra
|
|
|
42
42
|
Requires-Dist: numpy; extra == 'extra'
|
|
43
43
|
Requires-Dist: pandas; extra == 'extra'
|
|
44
44
|
Provides-Extra: full
|
|
45
|
-
Requires-Dist: absfuyu-res; extra == 'full'
|
|
46
45
|
Requires-Dist: numpy; extra == 'full'
|
|
47
46
|
Requires-Dist: pandas; extra == 'full'
|
|
48
47
|
Requires-Dist: rich; extra == 'full'
|
|
49
48
|
Requires-Dist: tqdm; extra == 'full'
|
|
50
|
-
Provides-Extra: res
|
|
51
|
-
Requires-Dist: absfuyu-res; extra == 'res'
|
|
52
49
|
Description-Content-Type: text/markdown
|
|
53
50
|
|
|
54
51
|
<div align="center">
|
|
55
|
-
|
|
56
|
-
|
|
57
|
-
|
|
58
|
-
|
|
59
|
-
|
|
60
|
-
|
|
61
|
-
|
|
62
|
-
|
|
63
|
-
|
|
64
|
-
|
|
65
|
-
|
|
52
|
+
<h1 align="center">
|
|
53
|
+
<img src="https://github.com/AbsoluteWinter/AbsoluteWinter.github.io/blob/main/absfuyu/images/repository-image-crop.png?raw=true" alt="absfuyu"/>
|
|
54
|
+
</h1>
|
|
55
|
+
<p align="center">
|
|
56
|
+
<a href="https://pypi.org/project/absfuyu/"><img src="https://img.shields.io/pypi/pyversions/absfuyu?style=flat-square&logo=python" alt="PyPI Supported Versions"/></a>
|
|
57
|
+
<a href="https://pypi.org/project/absfuyu/"><img src="https://img.shields.io/pypi/dm/absfuyu?style=flat-square&color=blue" alt="PyPI Downloads"/></a>
|
|
58
|
+
<a href="https://pypi.org/project/absfuyu/"><img src="https://img.shields.io/pypi/v/absfuyu?style=flat-square&logo=pypi" /></a>
|
|
59
|
+
<a><img src="https://img.shields.io/pypi/l/absfuyu?style=flat-square&logo=github&color=blue"/></a>
|
|
60
|
+
<a><img src="https://img.shields.io/badge/code%20style-black-black?style=flat-square"/></a>
|
|
61
|
+
<a href="https://github.com/astral-sh/ruff"><img src="https://img.shields.io/endpoint?url=https://raw.githubusercontent.com/astral-sh/ruff/main/assets/badge/v2.json&style=flat-square" alt="Ruff" style="max-width:100%;"></a>
|
|
62
|
+
</p>
|
|
66
63
|
</div>
|
|
67
64
|
|
|
68
|
-
|
|
69
65
|
---
|
|
70
66
|
|
|
71
67
|
## **SUMMARY:**
|
|
@@ -75,7 +71,7 @@ Description-Content-Type: text/markdown
|
|
|
75
71
|
## **INSTALLATION:**
|
|
76
72
|
|
|
77
73
|
```bash
|
|
78
|
-
|
|
74
|
+
pip install -U absfuyu
|
|
79
75
|
```
|
|
80
76
|
|
|
81
77
|
## **USAGE:**
|
|
@@ -115,7 +111,6 @@ python -m pip install -e .[full,dev]
|
|
|
115
111
|
hatch env show
|
|
116
112
|
```
|
|
117
113
|
|
|
118
|
-
|
|
119
114
|
## **LICENSE:**
|
|
120
115
|
|
|
121
116
|
MIT License
|
|
@@ -1,27 +1,22 @@
|
|
|
1
|
-
absfuyu/__init__.py,sha256=
|
|
1
|
+
absfuyu/__init__.py,sha256=pCNxLstlkcm5DQrRNeNbP_U_9QssMWcUpS9SHvjE33k,638
|
|
2
2
|
absfuyu/__main__.py,sha256=OpMwc35W5VANzw6gvlqJaJOl2H89i_frFZbleUQwDss,163
|
|
3
|
-
absfuyu/core.py,sha256=
|
|
3
|
+
absfuyu/core.py,sha256=J7XASHaSjhVyf9qtDU8LDMyJrUgW-yEecgxZP16u7PI,1233
|
|
4
4
|
absfuyu/everything.py,sha256=PGIXlqgxyADFPygohVYVIb7fZz72L_xXrlLX0WImuYg,788
|
|
5
5
|
absfuyu/logger.py,sha256=Pue3oWYYSF03A-fVp3E137jzlZVI71mYqddic8myauQ,13141
|
|
6
6
|
absfuyu/py.typed,sha256=47DEQpj8HBSa-_TImW-5JCeuQeRkm5NMpJWZG3hSuFU,0
|
|
7
7
|
absfuyu/sort.py,sha256=Z9nK15WehmZjlUNwvAOwF4FhV-rFcqlXkCcehNYmo78,6827
|
|
8
8
|
absfuyu/version.py,sha256=KMaeXNl93L4VU2RnTySoFv23IDyTvHfy84nyatFcKaE,14128
|
|
9
|
-
absfuyu/cli/__init__.py,sha256=
|
|
9
|
+
absfuyu/cli/__init__.py,sha256=mYX6lVAat9UOI9qR-ZDFw_4WOLVA9r-jTtW8d2fBEKM,1181
|
|
10
10
|
absfuyu/cli/color.py,sha256=7M3XqFllt26tv_NR5qKgyTId6wnVADtUB74cDYy8pOQ,497
|
|
11
11
|
absfuyu/cli/config_group.py,sha256=FsyYm2apSyAA2PAD12CpHAizenRds_QlLf8j0AlLuVo,1230
|
|
12
|
-
absfuyu/cli/do_group.py,sha256=
|
|
12
|
+
absfuyu/cli/do_group.py,sha256=8LdDgx3BYfhpM2d4q-SO9jA_ZcenNKLYr0Q7Hgj4TPg,2919
|
|
13
13
|
absfuyu/cli/game_group.py,sha256=ySpL2hm4VCplhNY0s22kBGI5eFCdJj9fm1T58yftU74,2348
|
|
14
|
+
absfuyu/cli/tool_group.py,sha256=JcmzcXMcMc1OVhAkcKeUPujVlsWyn_DafsrB_1f9rD8,3155
|
|
14
15
|
absfuyu/config/__init__.py,sha256=4r77tFm3mgHX8H1uWWNXC_FZ8hiSJzsYAyiStZiVj5w,8641
|
|
15
16
|
absfuyu/config/config.json,sha256=-ZQnmDuLq0aAFfsrQbSNR3tq5k9Eu9IVUQgYD9htIQM,646
|
|
16
|
-
absfuyu/extensions/__init__.py,sha256=
|
|
17
|
+
absfuyu/extensions/__init__.py,sha256=gt9YF5R5O7Pavqc8Hne0LFe0B4YOYV8gqfsiAyHqkD0,190
|
|
17
18
|
absfuyu/extensions/beautiful.py,sha256=eGfmJ72UQTVvevMCr80RoyYuCYxLaHkvAm1Kk2pkqc0,5331
|
|
18
|
-
absfuyu/extensions/
|
|
19
|
-
absfuyu/extensions/dev/password_hash.py,sha256=AO8VSW9s9VyrTCGgrN-HLqYIUWAYFSds6vLYrhH-ako,1826
|
|
20
|
-
absfuyu/extensions/dev/passwordlib.py,sha256=RvN-AOYann_K-OXVJOmtfTi38uYlcr7Gd2OnGe0I1og,6812
|
|
21
|
-
absfuyu/extensions/dev/project_starter.py,sha256=RkTHwMXdChB45d7rrDuDMzo3a34-P514JlOmYHHNads,1593
|
|
22
|
-
absfuyu/extensions/dev/shutdownizer.py,sha256=Vm9AUsUGyvRWRYAl4fp4CriSmixzBtV8ZGvqmNjdEvo,4027
|
|
23
|
-
absfuyu/extensions/extra/__init__.py,sha256=gUB8fIOz4V9xQxk689dMe7NFFu_r-CneCsi32DtjQAo,552
|
|
24
|
-
absfuyu/extensions/extra/data_analysis.py,sha256=JR8smS6gVRZ4jJtboshCpC3jFabVLQ8LBhWOA-sfIG4,32969
|
|
19
|
+
absfuyu/extensions/data_analysis.py,sha256=JR8smS6gVRZ4jJtboshCpC3jFabVLQ8LBhWOA-sfIG4,32969
|
|
25
20
|
absfuyu/fun/WGS.py,sha256=Aug9BsLTawBDkjdCQ3oqWAfGGeY6ZSBV1kENrTVnlUA,9461
|
|
26
21
|
absfuyu/fun/__init__.py,sha256=AOaq3NdgaK7e5hk622Wspiu6Z2biVK-jpk2FChn05rA,6366
|
|
27
22
|
absfuyu/fun/tarot.py,sha256=Y0z5rNWLOmqfJV961L_9LzUORRNR89Vegy7KqgNR9xs,2539
|
|
@@ -35,14 +30,17 @@ absfuyu/general/content.py,sha256=IfX5SkgoD-sjYJrbRHRIS5-g6fGp_X65A07ViB0zLpk,17
|
|
|
35
30
|
absfuyu/general/data_extension.py,sha256=tvZM4moHNxqOh_iT6ekFELZgfhiIoZ8SUqm9wUIaokU,48938
|
|
36
31
|
absfuyu/general/generator.py,sha256=PW_4Z-YZ30StwDuUUfHD7B0qnVKMo_ZZHHKj54BzgXk,9731
|
|
37
32
|
absfuyu/general/human.py,sha256=drZT1nI_YwGMOwZu8pbzf3frM-SUY15cOcnUpc4pzQk,12241
|
|
38
|
-
absfuyu/pkg_data/__init__.py,sha256=
|
|
33
|
+
absfuyu/pkg_data/__init__.py,sha256=8iHOGp-MWSao_u6a6-iQmSfMReinwbWbjR7EdrWmQeY,4867
|
|
39
34
|
absfuyu/pkg_data/chemistry.pkl,sha256=kYWNa_PVffoDnzT8b9Jvimmf_GZshPe1D-SnEKERsLo,4655
|
|
35
|
+
absfuyu/pkg_data/passwordlib_lzma.pkl,sha256=rT5lJT8t42BATU5Cp2qFwbnZkbx-QlUgodSvR0wFY6I,891877
|
|
40
36
|
absfuyu/pkg_data/tarot.pkl,sha256=ssXTCC_BQgslO5F-3a9HivbxFQ6BioIe2E1frPVi2m0,56195
|
|
41
37
|
absfuyu/tools/__init__.py,sha256=VDmmMLEfiRyUWPVrPYc8JUEa5TXjLguKVnyI3YavFv0,118
|
|
42
|
-
absfuyu/tools/checksum.py,sha256=
|
|
43
|
-
absfuyu/tools/converter.py,sha256=
|
|
38
|
+
absfuyu/tools/checksum.py,sha256=gB8LvOeQRRuI1dYMmNZINF0QyUKyQZiZ7oJJ0m7QMDY,4807
|
|
39
|
+
absfuyu/tools/converter.py,sha256=STA5NZZt5Xj0YRTup8tvh1YE2z7Y1AWRbEbU3EAS0TY,11589
|
|
44
40
|
absfuyu/tools/keygen.py,sha256=drj8OUDCXrLvcVf9_Shd5UMShm_mBTxa9Sg_BrAT5yM,7356
|
|
45
41
|
absfuyu/tools/obfuscator.py,sha256=kiaFvMw2RwEfZvXKdbUrEYA_AuVETivoL2eVmtUWU4w,8669
|
|
42
|
+
absfuyu/tools/passwordlib.py,sha256=q-KOGld-LN6ndv8HLs5Yq6iJEI9lrb_fDc4kFwh9M8c,7104
|
|
43
|
+
absfuyu/tools/shutdownizer.py,sha256=W5sYoqvumTKj8fYIt1D0f5BtWCHUNBB9IO65f3P4G5w,7674
|
|
46
44
|
absfuyu/tools/stats.py,sha256=zZNK59qn0xqQlyw5CP3MP5WRMSxncdKZythqvgNR1lQ,5191
|
|
47
45
|
absfuyu/tools/web.py,sha256=Mb5RYj1Fu5eB-mYMusyrE2JG6_ZPEf8WT72Z8q6Ep74,1406
|
|
48
46
|
absfuyu/util/__init__.py,sha256=1V2DwIUt-bSiSURnk6AzfKB0HRLHwoi8_6RaIvywlzU,3716
|
|
@@ -52,10 +50,10 @@ absfuyu/util/lunar.py,sha256=xW7HcgyIRjWBhQv36RimNZIT8Ed_X83moqr5h5-Ku9k,13750
|
|
|
52
50
|
absfuyu/util/path.py,sha256=p4Ac98FfW5pXLNRRuQ_QEx_G7-UOSBKABAg_xrOq7u4,16628
|
|
53
51
|
absfuyu/util/performance.py,sha256=F-aLJ-5wmwkiOdl9_wZcFRKifL9zOahw52JeL4TbCuQ,9105
|
|
54
52
|
absfuyu/util/pkl.py,sha256=ZZf6-PFC2uRGXqARNi0PGH3A0IXwMP0sYPWZJXENvak,1559
|
|
55
|
-
absfuyu/util/shorten_number.py,sha256=
|
|
53
|
+
absfuyu/util/shorten_number.py,sha256=CZRG0fh9y3bpmFnY9xy5gWEv1kceD1nJmQGKDxPbwCQ,6574
|
|
56
54
|
absfuyu/util/zipped.py,sha256=CU_le1MynFwHfpajCRRJ7_A-r1jfMjt9uu72jLooW6w,3111
|
|
57
|
-
absfuyu-4.
|
|
58
|
-
absfuyu-4.
|
|
59
|
-
absfuyu-4.
|
|
60
|
-
absfuyu-4.
|
|
61
|
-
absfuyu-4.
|
|
55
|
+
absfuyu-4.2.0.dist-info/METADATA,sha256=6uiXP8Ru7sBlWoFQmoqC2sJdBO9qu3fo5sER0rnAnu0,3737
|
|
56
|
+
absfuyu-4.2.0.dist-info/WHEEL,sha256=qtCwoSJWgHk21S1Kb4ihdzI2rlJ1ZKaIurTj_ngOhyQ,87
|
|
57
|
+
absfuyu-4.2.0.dist-info/entry_points.txt,sha256=bW5CgJRTTWJ2Pywojo07sf-YucRPcnHzMmETh5avbX0,79
|
|
58
|
+
absfuyu-4.2.0.dist-info/licenses/LICENSE,sha256=pFCHBSNSzdXwYG1AHpq7VcofI1NMQ1Fc77RzZ4Ln2O4,1097
|
|
59
|
+
absfuyu-4.2.0.dist-info/RECORD,,
|
|
@@ -1,244 +0,0 @@
|
|
|
1
|
-
# type: ignore
|
|
2
|
-
# flake8: noqa
|
|
3
|
-
|
|
4
|
-
"""
|
|
5
|
-
Absfuyu: Development
|
|
6
|
-
--------------------
|
|
7
|
-
Some stuffs that are not ready to use yet.
|
|
8
|
-
Use at your own risk, everything is subject to change
|
|
9
|
-
|
|
10
|
-
Version: 2.0.0
|
|
11
|
-
Date updated: 23/11/2023 (dd/mm/yyyy)
|
|
12
|
-
"""
|
|
13
|
-
|
|
14
|
-
# Module level
|
|
15
|
-
###########################################################################
|
|
16
|
-
__all__ = [
|
|
17
|
-
"password_check",
|
|
18
|
-
"fib",
|
|
19
|
-
]
|
|
20
|
-
|
|
21
|
-
|
|
22
|
-
# Library
|
|
23
|
-
###########################################################################
|
|
24
|
-
import base64
|
|
25
|
-
import re
|
|
26
|
-
from collections import deque
|
|
27
|
-
from functools import lru_cache
|
|
28
|
-
from typing import Dict, Final, List, NamedTuple
|
|
29
|
-
|
|
30
|
-
|
|
31
|
-
# PASSWORD CHECKER
|
|
32
|
-
def password_check(password: str) -> bool:
|
|
33
|
-
"""
|
|
34
|
-
Verify the strength of 'password'.
|
|
35
|
-
Returns a dict indicating the wrong criteria.
|
|
36
|
-
A password is considered strong if:
|
|
37
|
-
- 8 characters length or more
|
|
38
|
-
- 1 digit or more
|
|
39
|
-
- 1 symbol or more
|
|
40
|
-
- 1 uppercase letter or more
|
|
41
|
-
- 1 lowercase letter or more
|
|
42
|
-
"""
|
|
43
|
-
|
|
44
|
-
# calculating the length
|
|
45
|
-
length_error = len(password) < 8
|
|
46
|
-
|
|
47
|
-
# searching for digits
|
|
48
|
-
digit_error = re.search(r"\d", password) is None
|
|
49
|
-
|
|
50
|
-
# searching for uppercase
|
|
51
|
-
uppercase_error = re.search(r"[A-Z]", password) is None
|
|
52
|
-
|
|
53
|
-
# searching for lowercase
|
|
54
|
-
lowercase_error = re.search(r"[a-z]", password) is None
|
|
55
|
-
|
|
56
|
-
# searching for symbols
|
|
57
|
-
symbols = re.compile(r"[ !#$%&'()*+,-./[\\\]^_`{|}~" + r'"]')
|
|
58
|
-
symbol_error = symbols.search(password) is None
|
|
59
|
-
|
|
60
|
-
detail = {
|
|
61
|
-
"password_ok": not any(
|
|
62
|
-
[ # overall result
|
|
63
|
-
length_error,
|
|
64
|
-
digit_error,
|
|
65
|
-
uppercase_error,
|
|
66
|
-
lowercase_error,
|
|
67
|
-
symbol_error,
|
|
68
|
-
]
|
|
69
|
-
),
|
|
70
|
-
"length_error": length_error,
|
|
71
|
-
"digit_error": digit_error,
|
|
72
|
-
"uppercase_error": uppercase_error,
|
|
73
|
-
"lowercase_error": lowercase_error,
|
|
74
|
-
"symbol_error": symbol_error,
|
|
75
|
-
}
|
|
76
|
-
|
|
77
|
-
return detail["password_ok"]
|
|
78
|
-
|
|
79
|
-
|
|
80
|
-
# FIBONACCI WITH CACHE
|
|
81
|
-
@lru_cache(maxsize=5)
|
|
82
|
-
def fib(n: int) -> int:
|
|
83
|
-
"""Fibonacci (recursive)"""
|
|
84
|
-
# max recursion is 484
|
|
85
|
-
if n < 2:
|
|
86
|
-
return n
|
|
87
|
-
return fib(n - 1) + fib(n - 2)
|
|
88
|
-
|
|
89
|
-
|
|
90
|
-
# https://stackoverflow.com/questions/563022/whats-python-good-practice-for-importing-and-offering-optional-features
|
|
91
|
-
def optional_import(module: str, name: str = None, package: str = None):
|
|
92
|
-
import importlib
|
|
93
|
-
|
|
94
|
-
try:
|
|
95
|
-
module = importlib.import_module(module)
|
|
96
|
-
return module if name is None else getattr(module, name)
|
|
97
|
-
except ImportError as e:
|
|
98
|
-
if package is None:
|
|
99
|
-
package = module
|
|
100
|
-
msg = f"install the '{package}' package to make use of this feature"
|
|
101
|
-
import_error = e
|
|
102
|
-
|
|
103
|
-
def _failed_import(*args):
|
|
104
|
-
raise ValueError(msg) from import_error
|
|
105
|
-
|
|
106
|
-
return _failed_import
|
|
107
|
-
|
|
108
|
-
|
|
109
|
-
def load_toml_file(toml_file: str):
|
|
110
|
-
"""
|
|
111
|
-
Load ``.toml`` file
|
|
112
|
-
|
|
113
|
-
:param toml_file: Path to ``.toml`` file
|
|
114
|
-
"""
|
|
115
|
-
from sys import version_info as _python_version
|
|
116
|
-
|
|
117
|
-
if _python_version.minor < 11:
|
|
118
|
-
try:
|
|
119
|
-
import tomli as tomllib # type: ignore
|
|
120
|
-
except ImportError:
|
|
121
|
-
raise ImportError("Please install tomli python package")
|
|
122
|
-
except:
|
|
123
|
-
raise SystemExit
|
|
124
|
-
else:
|
|
125
|
-
import tomllib
|
|
126
|
-
|
|
127
|
-
with open(toml_file, "rb") as file:
|
|
128
|
-
toml_data = tomllib.load(file)
|
|
129
|
-
return toml_data
|
|
130
|
-
|
|
131
|
-
|
|
132
|
-
def get_sitemap(url: str):
|
|
133
|
-
import re
|
|
134
|
-
|
|
135
|
-
import requests
|
|
136
|
-
|
|
137
|
-
class Url(NamedTuple):
|
|
138
|
-
base: str
|
|
139
|
-
extra: str
|
|
140
|
-
|
|
141
|
-
def __str__(self) -> str:
|
|
142
|
-
return f"{self.base}{self.extra}"
|
|
143
|
-
|
|
144
|
-
def __repr__(self) -> str:
|
|
145
|
-
return f"{self.__class__.__name__}({self.base}{self.extra})"
|
|
146
|
-
|
|
147
|
-
# robots.txt
|
|
148
|
-
# sitemap.xml
|
|
149
|
-
if not url.endswith("/"):
|
|
150
|
-
url += "/"
|
|
151
|
-
pattern = re.compile(
|
|
152
|
-
r"([(http(s)?):\/\/(www\.)?a-zA-Z0-9@:%._\+~#=]{2,256}\.[a-z]{2,6}\b)([-a-zA-Z0-9@:%_\+.~#?&//=]*)",
|
|
153
|
-
re.IGNORECASE,
|
|
154
|
-
)
|
|
155
|
-
try:
|
|
156
|
-
url += "sitemap.xml"
|
|
157
|
-
res = requests.get(url).text
|
|
158
|
-
except:
|
|
159
|
-
# W.I.P
|
|
160
|
-
url += "robots.txt"
|
|
161
|
-
res = requests.get(url).text
|
|
162
|
-
regex = re.findall(pattern, res)
|
|
163
|
-
return list(map(Url._make, regex))
|
|
164
|
-
|
|
165
|
-
|
|
166
|
-
from absfuyu.general import ClassBase
|
|
167
|
-
|
|
168
|
-
|
|
169
|
-
class SimpleStrEncrypt(ClassBase):
|
|
170
|
-
"""
|
|
171
|
-
Simple Encryption
|
|
172
|
-
|
|
173
|
-
Logic:
|
|
174
|
-
- Base64
|
|
175
|
-
- Shift characters
|
|
176
|
-
"""
|
|
177
|
-
|
|
178
|
-
def __init__(self, times_to_base64_encode: int = 10, shift: int = 13) -> None:
|
|
179
|
-
"""
|
|
180
|
-
:param times_to_base64_encode: How many time to base64 encode
|
|
181
|
-
:type times_to_base64_encode: int
|
|
182
|
-
:param shift: Shift characters to the right for how many position
|
|
183
|
-
:type shift: int
|
|
184
|
-
"""
|
|
185
|
-
self.times_to_base64_encode = times_to_base64_encode
|
|
186
|
-
self.shift = shift
|
|
187
|
-
|
|
188
|
-
# Support
|
|
189
|
-
def _convert_table(self, text: str, shift: int) -> Dict[str, str]:
|
|
190
|
-
data = text
|
|
191
|
-
|
|
192
|
-
data = deque(sorted(list(set(data))))
|
|
193
|
-
translate = data.copy()
|
|
194
|
-
translate.rotate(shift)
|
|
195
|
-
convert_table = dict(zip(data, translate))
|
|
196
|
-
|
|
197
|
-
return convert_table
|
|
198
|
-
|
|
199
|
-
@staticmethod
|
|
200
|
-
def _use_convert_table(text: str, convert_table: Dict[str, str]) -> str:
|
|
201
|
-
"""Use convert table"""
|
|
202
|
-
data = list(text)
|
|
203
|
-
for i, x in enumerate(data):
|
|
204
|
-
data[i] = convert_table[x]
|
|
205
|
-
return "".join(data)
|
|
206
|
-
|
|
207
|
-
@staticmethod
|
|
208
|
-
def _b64encode(text: str) -> str:
|
|
209
|
-
return base64.b64encode(text.encode()).decode()
|
|
210
|
-
|
|
211
|
-
@staticmethod
|
|
212
|
-
def _b64decode(text: str) -> str:
|
|
213
|
-
return base64.b64decode(text).decode()
|
|
214
|
-
|
|
215
|
-
# Main
|
|
216
|
-
def encode(self, text: str) -> str:
|
|
217
|
-
# Base64
|
|
218
|
-
data = text
|
|
219
|
-
for _ in range(self.times_to_base64_encode):
|
|
220
|
-
data = self._b64encode(data)
|
|
221
|
-
|
|
222
|
-
# Shift
|
|
223
|
-
convert_table = self._convert_table(data, self.shift)
|
|
224
|
-
return self._use_convert_table(data, convert_table)
|
|
225
|
-
|
|
226
|
-
def decode(self, text: str) -> str:
|
|
227
|
-
# Shift back
|
|
228
|
-
data = text
|
|
229
|
-
convert_table = self._convert_table(data, -self.shift)
|
|
230
|
-
data = self._use_convert_table(data, convert_table)
|
|
231
|
-
|
|
232
|
-
# Base64
|
|
233
|
-
for _ in range(self.times_to_base64_encode):
|
|
234
|
-
data = self._b64decode(data)
|
|
235
|
-
|
|
236
|
-
return data
|
|
237
|
-
|
|
238
|
-
|
|
239
|
-
# testing
|
|
240
|
-
CON_VAR: Final[List[str]] = ["a", "b"] # Declare as final
|
|
241
|
-
|
|
242
|
-
|
|
243
|
-
if __name__ == "__main__":
|
|
244
|
-
print(get_sitemap("https://kingdomality.com/"))
|