wocli 0.2.0__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 (37) hide show
  1. wocli-0.2.0/LICENSE +21 -0
  2. wocli-0.2.0/PKG-INFO +16 -0
  3. wocli-0.2.0/README.md +0 -0
  4. wocli-0.2.0/pyproject.toml +28 -0
  5. wocli-0.2.0/setup.cfg +4 -0
  6. wocli-0.2.0/src/wocli/__init__.py +3 -0
  7. wocli-0.2.0/src/wocli/commands/__init__.py +1 -0
  8. wocli-0.2.0/src/wocli/commands/badapple.py +51 -0
  9. wocli-0.2.0/src/wocli/commands/battery.py +124 -0
  10. wocli-0.2.0/src/wocli/commands/cow.py +58 -0
  11. wocli-0.2.0/src/wocli/commands/dead.py +41 -0
  12. wocli-0.2.0/src/wocli/commands/dino.py +229 -0
  13. wocli-0.2.0/src/wocli/commands/glitch.py +52 -0
  14. wocli-0.2.0/src/wocli/commands/goodbye.py +40 -0
  15. wocli-0.2.0/src/wocli/commands/gpa.py +84 -0
  16. wocli-0.2.0/src/wocli/commands/hash_cmd.py +41 -0
  17. wocli-0.2.0/src/wocli/commands/ip.py +127 -0
  18. wocli-0.2.0/src/wocli/commands/lolcat.py +31 -0
  19. wocli-0.2.0/src/wocli/commands/luck.py +38 -0
  20. wocli-0.2.0/src/wocli/commands/matrix.py +77 -0
  21. wocli-0.2.0/src/wocli/commands/path_cmd.py +37 -0
  22. wocli-0.2.0/src/wocli/commands/port.py +101 -0
  23. wocli-0.2.0/src/wocli/commands/progress.py +68 -0
  24. wocli-0.2.0/src/wocli/commands/qr_cmd.py +50 -0
  25. wocli-0.2.0/src/wocli/commands/regex_cmd.py +39 -0
  26. wocli-0.2.0/src/wocli/commands/sys_cmd.py +157 -0
  27. wocli-0.2.0/src/wocli/commands/time_cmd.py +57 -0
  28. wocli-0.2.0/src/wocli/commands/tree.py +60 -0
  29. wocli-0.2.0/src/wocli/commands/typing_cmd.py +69 -0
  30. wocli-0.2.0/src/wocli/commands/wifi_cmd.py +117 -0
  31. wocli-0.2.0/src/wocli/main.py +129 -0
  32. wocli-0.2.0/src/wocli.egg-info/PKG-INFO +16 -0
  33. wocli-0.2.0/src/wocli.egg-info/SOURCES.txt +35 -0
  34. wocli-0.2.0/src/wocli.egg-info/dependency_links.txt +1 -0
  35. wocli-0.2.0/src/wocli.egg-info/entry_points.txt +2 -0
  36. wocli-0.2.0/src/wocli.egg-info/requires.txt +3 -0
  37. wocli-0.2.0/src/wocli.egg-info/top_level.txt +1 -0
wocli-0.2.0/LICENSE ADDED
@@ -0,0 +1,21 @@
1
+ MIT License
2
+
3
+ Copyright (c) 2026 Wojusensei
4
+
5
+ Permission is hereby granted, free of charge, to any person obtaining a copy
6
+ of this software and associated documentation files (the "Software"), to deal
7
+ in the Software without restriction, including without limitation the rights
8
+ to use, copy, modify, merge, publish, distribute, sublicense, and/or sell
9
+ copies of the Software, and to permit persons to whom the Software is
10
+ furnished to do so, subject to the following conditions:
11
+
12
+ The above copyright notice and this permission notice shall be included in all
13
+ copies or substantial portions of the Software.
14
+
15
+ THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR
16
+ IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY,
17
+ FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE
18
+ AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER
19
+ LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM,
20
+ OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE
21
+ SOFTWARE.
wocli-0.2.0/PKG-INFO ADDED
@@ -0,0 +1,16 @@
1
+ Metadata-Version: 2.4
2
+ Name: wocli
3
+ Version: 0.2.0
4
+ Summary: 一个为发电而生的何意味终端小工具
5
+ Author: Wojusensei
6
+ License: MIT
7
+ Classifier: Programming Language :: Python :: 3
8
+ Classifier: Operating System :: OS Independent
9
+ Classifier: License :: OSI Approved :: MIT License
10
+ Requires-Python: >=3.9
11
+ Description-Content-Type: text/markdown
12
+ License-File: LICENSE
13
+ Requires-Dist: qrcode>=7.4
14
+ Requires-Dist: Pillow>=10.0
15
+ Requires-Dist: requests>=2.31
16
+ Dynamic: license-file
wocli-0.2.0/README.md ADDED
File without changes
@@ -0,0 +1,28 @@
1
+ [build-system]
2
+ requires = ["setuptools>=68.0", "wheel"]
3
+ build-backend = "setuptools.build_meta"
4
+
5
+ [project]
6
+ name = "wocli"
7
+ version = "0.2.0"
8
+ description = "一个为发电而生的何意味终端小工具"
9
+ authors = [{name = "Wojusensei"}]
10
+ license = {text = "MIT"}
11
+ readme = "README.md"
12
+ requires-python = ">=3.9"
13
+ classifiers = [
14
+ "Programming Language :: Python :: 3",
15
+ "Operating System :: OS Independent",
16
+ "License :: OSI Approved :: MIT License",
17
+ ]
18
+ dependencies = [
19
+ "qrcode>=7.4",
20
+ "Pillow>=10.0",
21
+ "requests>=2.31",
22
+ ]
23
+
24
+ [project.scripts]
25
+ wocli = "wocli.main:main"
26
+
27
+ [tool.setuptools.package-dir]
28
+ "" = "src"
wocli-0.2.0/setup.cfg ADDED
@@ -0,0 +1,4 @@
1
+ [egg_info]
2
+ tag_build =
3
+ tag_date = 0
4
+
@@ -0,0 +1,3 @@
1
+ """wocli - 一个为发电而生的何意味终端小工具"""
2
+
3
+ __version__ = "0.1.0"
@@ -0,0 +1 @@
1
+ """wocli command modules."""
@@ -0,0 +1,51 @@
1
+ """wocli badapple - 播放 Bad Apple!! ASCII 动画"""
2
+ import sys
3
+ import os
4
+ import time
5
+
6
+ C_WHITE = "\033[97m"
7
+ C_RESET = "\033[0m"
8
+
9
+ FRAME_FILE = os.path.join(os.path.dirname(__file__), "frames.txt")
10
+
11
+
12
+ def load_frames():
13
+ """加载帧序列,返回帧列表"""
14
+ if not os.path.exists(FRAME_FILE):
15
+ print("\n frames.txt 未找到,请确保下载了 Bad Apple ASCII 帧序列并放到 commands/ 目录。")
16
+ print(" 下载地址: https://raw.githubusercontent.com/kevinjycui/bad-apple/main/frames.txt\n")
17
+ return None
18
+ with open(FRAME_FILE, "r", encoding="utf-8") as f:
19
+ data = f.read()
20
+ # 帧之间用 SPLIT 分隔,每一帧是一段文本
21
+ frames = data.split("\nSPLIT\n")
22
+ return frames
23
+
24
+
25
+ def run():
26
+ print("\n [ Bad Apple!! ]")
27
+ print(" 正在加载帧序列...")
28
+ frames = load_frames()
29
+ if not frames:
30
+ return
31
+ print(f" 共 {len(frames)} 帧,按 Enter 开始播放...")
32
+ input()
33
+
34
+ # 隐藏光标
35
+ sys.stdout.write("\033[?25l")
36
+ sys.stdout.flush()
37
+
38
+ try:
39
+ for frame in frames:
40
+ # 将光标移到终端左上角(不清屏,直接覆盖)
41
+ sys.stdout.write("\033[H")
42
+ sys.stdout.write(C_WHITE + frame + C_RESET)
43
+ sys.stdout.flush()
44
+ time.sleep(1 / 30) # 30fps,可根据机器性能调整
45
+ except KeyboardInterrupt:
46
+ pass
47
+ finally:
48
+ sys.stdout.write("\033[?25h") # 恢复光标
49
+ sys.stdout.write(C_RESET)
50
+ sys.stdout.flush()
51
+ print("\n 播放完毕。")
@@ -0,0 +1,124 @@
1
+ """wocli battery - 电池信息与健康度打分"""
2
+ import subprocess
3
+ import platform
4
+ import re
5
+
6
+
7
+ def get_battery_macos():
8
+ try:
9
+ result = subprocess.run(["pmset", "-g", "batt"], capture_output=True, text=True)
10
+ output = result.stdout
11
+ # 电量
12
+ pct_match = re.search(r"(\d{1,3})%", output)
13
+ percent = int(pct_match.group(1)) if pct_match else -1
14
+ # 充电状态
15
+ status = "未知"
16
+ if "charging" in output:
17
+ status = "充电中"
18
+ elif "discharging" in output:
19
+ status = "使用中"
20
+ elif "charged" in output:
21
+ status = "已充满"
22
+ # 健康度和循环次数
23
+ try:
24
+ health = subprocess.run(
25
+ ["system_profiler", "SPPowerDataType"],
26
+ capture_output=True, text=True
27
+ )
28
+ cycles_match = re.search(r"Cycle Count:\s*(\d+)", health.stdout)
29
+ cycles = int(cycles_match.group(1)) if cycles_match else -1
30
+ max_match = re.search(r"Maximum Capacity:\s*(\d+)%", health.stdout)
31
+ max_cap = int(max_match.group(1)) if max_match else 100
32
+ except:
33
+ cycles = -1
34
+ max_cap = 100
35
+ return percent, status, cycles, max_cap
36
+ except:
37
+ return -1, "未知", -1, 100
38
+
39
+
40
+ def get_battery_windows():
41
+ try:
42
+ result = subprocess.run(
43
+ ["wmic", "path", "Win32_Battery", "get", "EstimatedChargeRemaining,EstimatedRunTime,BatteryStatus"],
44
+ capture_output=True, text=True
45
+ )
46
+ lines = [l.strip() for l in result.stdout.split("\n") if l.strip()]
47
+ if len(lines) < 2:
48
+ return -1, "未知", -1, 100
49
+ parts = lines[1].split()
50
+ percent = int(parts[0]) if parts else -1
51
+ status_map = {"1": "使用中", "2": "充电中", "3": "已充满"}
52
+ status = status_map.get(parts[1], "未知") if len(parts) > 1 else "未知"
53
+ return percent, status, -1, 100
54
+ except:
55
+ return -1, "未知", -1, 100
56
+
57
+
58
+ def get_battery_linux():
59
+ try:
60
+ with open("/sys/class/power_supply/BAT0/capacity", "r") as f:
61
+ percent = int(f.read().strip())
62
+ with open("/sys/class/power_supply/BAT0/status", "r") as f:
63
+ raw = f.read().strip()
64
+ status_map = {"Discharging": "使用中", "Charging": "充电中", "Full": "已充满"}
65
+ status = status_map.get(raw, raw)
66
+ return percent, status, -1, 100
67
+ except:
68
+ return -1, "未知", -1, 100
69
+
70
+
71
+ def score_battery(percent, cycles, max_cap):
72
+ if percent < 0:
73
+ return 0, "无数据"
74
+ charge_score = percent
75
+ if cycles > 0:
76
+ cycle_score = max(0, 100 - cycles * 0.1)
77
+ else:
78
+ cycle_score = 100
79
+ health_score = max_cap
80
+ total = charge_score * 0.3 + cycle_score * 0.3 + health_score * 0.4
81
+ total = min(100, total)
82
+
83
+ if total >= 95:
84
+ grade = "S级 · 古希腊掌管电池的神"
85
+ elif total >= 85:
86
+ grade = "A级 · 还能战三年"
87
+ elif total >= 70:
88
+ grade = "B级 · 电池有点虚了"
89
+ elif total >= 50:
90
+ grade = "C级 · 已经离不开充电器"
91
+ else:
92
+ grade = "D级 · 电池这么老,零百加速只要三十分钟吧"
93
+
94
+ return round(total, 2), grade
95
+
96
+
97
+ def run():
98
+ system = platform.system()
99
+ if system == "Darwin":
100
+ percent, status, cycles, max_cap = get_battery_macos()
101
+ elif system == "Windows":
102
+ percent, status, cycles, max_cap = get_battery_windows()
103
+ else:
104
+ percent, status, cycles, max_cap = get_battery_linux()
105
+
106
+ if percent < 0:
107
+ print("\n 无法获取电池信息。\n")
108
+ return
109
+
110
+ score_val, grade = score_battery(percent, cycles, max_cap)
111
+ bar_len = 20
112
+ filled = int(bar_len * percent / 100)
113
+ bar = "=" * filled + "-" * (bar_len - filled)
114
+
115
+ print()
116
+ print(f" 当前电量:[{bar}] {percent}%")
117
+ print(f" 充电状态:{status}")
118
+ if cycles >= 0:
119
+ print(f" 循环次数:{cycles} 次")
120
+ if max_cap < 100:
121
+ print(f" 最大容量:{max_cap}%")
122
+ print(f" 健康评分:{score_val:.2f} / 100.00")
123
+ print(f" 评级:{grade}")
124
+ print()
@@ -0,0 +1,58 @@
1
+ """wocli cow - ASCII牛说你说的话."""
2
+
3
+ import sys
4
+
5
+
6
+ COW = r"""
7
+ \ ^__^
8
+ \ (oo)\_______
9
+ (__)\ )\/\
10
+ ||----w |
11
+ || ||
12
+ """
13
+
14
+
15
+ def make_bubble(text):
16
+ """生成对话气泡."""
17
+ lines = []
18
+ words = text.split()
19
+ line = ""
20
+ for word in words:
21
+ if len(line) + len(word) + 1 <= 36:
22
+ line += (" " + word) if line else word
23
+ else:
24
+ lines.append(line)
25
+ line = word
26
+ if line:
27
+ lines.append(line)
28
+
29
+ max_len = max(len(l) for l in lines) if lines else 0
30
+ top = " " + "_" * (max_len + 2)
31
+ bottom = " " + "-" * (max_len + 2)
32
+
33
+ bubble = [top]
34
+ if len(lines) == 1:
35
+ bubble.append(f" < {lines[0]} >")
36
+ else:
37
+ for i, l in enumerate(lines):
38
+ if i == 0:
39
+ bubble.append(f" / {l:<{max_len}} \\")
40
+ elif i == len(lines) - 1:
41
+ bubble.append(f" \\ {l:<{max_len}} /")
42
+ else:
43
+ bubble.append(f" | {l:<{max_len}} |")
44
+ bubble.append(bottom)
45
+ return "\n".join(bubble)
46
+
47
+
48
+ def run():
49
+ """运行 cow 命令."""
50
+ if len(sys.argv) > 1:
51
+ text = " ".join(sys.argv[1:])
52
+ else:
53
+ text = "哞————(无意味)"
54
+
55
+ print()
56
+ print(make_bubble(text))
57
+ print(COW)
58
+ print()
@@ -0,0 +1,41 @@
1
+ """wocli dead - 伪装终端死机"""
2
+ import sys
3
+ import time
4
+ import random
5
+
6
+
7
+ def run():
8
+ print()
9
+ print(" !! WARNING: Kernel panic detected !!")
10
+ time.sleep(1)
11
+
12
+ # 花屏
13
+ chars = "!@#$%^&*()_+-=[]{}|;:',.<>?/~`"
14
+ colors = [31, 32, 33, 34, 35, 36, 91, 92, 93, 94, 95, 96]
15
+ for _ in range(20):
16
+ line = " " + "".join(random.choice(chars) for _ in range(60))
17
+ color = random.choice(colors)
18
+ sys.stdout.write(f"\033[{color}m{line}\033[0m\n")
19
+ sys.stdout.flush()
20
+ time.sleep(0.05)
21
+
22
+ time.sleep(0.5)
23
+
24
+ # 蓝屏
25
+ sys.stdout.write("\033[44m\033[37m")
26
+ sys.stdout.write("\033[2J\033[H")
27
+ print()
28
+ print(" *** SYSTEM ERROR ***")
29
+ print()
30
+ print(" A fatal exception has occurred at 0xDEADBEEF")
31
+ print(" The system has been halted.")
32
+ print()
33
+ print(" Attempting to recover...")
34
+ sys.stdout.flush()
35
+
36
+ time.sleep(3)
37
+
38
+ # 恢复
39
+ sys.stdout.write("\033[0m\033[2J\033[H")
40
+ sys.stdout.write(" Just kidding. Your terminal is fine.\n\n")
41
+ sys.stdout.flush()
@@ -0,0 +1,229 @@
1
+ import sys, os, time, random, platform, signal
2
+
3
+ W, H = 70, 20
4
+ GROUND = H - 3
5
+ X0 = 10
6
+ C_ORANGE = "\033[38;5;214m"
7
+ C_GREEN = "\033[32m"
8
+ C_WHITE = "\033[97m"
9
+ C_RESET = "\033[0m"
10
+
11
+ CLAUDE_A = [" ▗ ▗ ", " ▘▘ ", " ▝▝ "]
12
+ CLAUDE_B = [" ▖ ▖ ", " ▝▝ ", " ▘▘ "]
13
+
14
+ # ---------- 跨平台终端控制 ----------
15
+ if platform.system() == "Windows":
16
+ import msvcrt
17
+ def setup_terminal(): pass
18
+ def restore_terminal(): pass
19
+ def get_key():
20
+ if msvcrt.kbhit():
21
+ ch = msvcrt.getch()
22
+ if ch == b'\xe0': return ''
23
+ try:
24
+ return ch.decode('utf-8', errors='ignore')
25
+ except:
26
+ return ''
27
+ return ''
28
+ else:
29
+ import termios, tty, fcntl
30
+ _old_term = None
31
+ _old_flags = None
32
+ _fd = sys.stdin.fileno()
33
+
34
+ def setup_terminal():
35
+ global _old_term, _old_flags
36
+ _old_term = termios.tcgetattr(_fd)
37
+ _old_flags = fcntl.fcntl(_fd, fcntl.F_GETFL)
38
+ tty.setraw(_fd)
39
+ fcntl.fcntl(_fd, fcntl.F_SETFL, _old_flags | os.O_NONBLOCK)
40
+
41
+ def restore_terminal():
42
+ if _old_term is not None:
43
+ termios.tcsetattr(_fd, termios.TCSADRAIN, _old_term)
44
+ if _old_flags is not None:
45
+ fcntl.fcntl(_fd, fcntl.F_SETFL, _old_flags)
46
+
47
+ def get_key():
48
+ try:
49
+ data = os.read(_fd, 1).decode('utf-8', errors='ignore')
50
+ return data
51
+ except BlockingIOError:
52
+ return ''
53
+
54
+ class Game:
55
+ def __init__(self):
56
+ self.score = 0
57
+ self.high = self._load_high()
58
+ self.ground_y = GROUND - len(CLAUDE_A)
59
+ self.y = float(self.ground_y)
60
+ self.vy = 0.0
61
+ self.objs = []
62
+ self.speed = 0.8
63
+ self.frame = 0
64
+ self.over = False
65
+ self._hide_cursor()
66
+ signal.signal(signal.SIGINT, self._stop)
67
+ signal.signal(signal.SIGTERM, self._stop)
68
+
69
+ def _stop(self, *args):
70
+ self.over = True
71
+
72
+ def _hide_cursor(self):
73
+ sys.stdout.write("\033[?25l")
74
+ sys.stdout.flush()
75
+
76
+ def _show_cursor(self):
77
+ sys.stdout.write("\033[?25h")
78
+ sys.stdout.flush()
79
+
80
+ def _load_high(self):
81
+ p = os.path.expanduser("~/.wocli_dino")
82
+ try:
83
+ with open(p) as f:
84
+ return int(f.read())
85
+ except:
86
+ return 0
87
+
88
+ def _save_high(self):
89
+ if self.score > self.high:
90
+ self.high = self.score
91
+ p = os.path.expanduser("~/.wocli_dino")
92
+ try:
93
+ with open(p, "w") as f:
94
+ f.write(str(self.score))
95
+ except:
96
+ pass
97
+
98
+ def jump(self):
99
+ if self.vy == 0 and self.y >= self.ground_y:
100
+ self.vy = -2.2
101
+
102
+ def update(self):
103
+ if self.over:
104
+ return
105
+ self.frame += 1
106
+ self.score += 1
107
+ if self.score % 600 == 0:
108
+ self.speed = min(2.0, self.speed * 1.05)
109
+
110
+ self.vy += 0.2
111
+ self.y += self.vy
112
+ if self.y >= self.ground_y:
113
+ self.y = self.ground_y
114
+ self.vy = 0
115
+
116
+ # 移除超出屏幕的障碍
117
+ self.objs = [o for o in self.objs if o[0] > -15]
118
+ for o in self.objs:
119
+ o[0] -= self.speed
120
+
121
+ # 生成障碍
122
+ if len(self.objs) < 3 and random.random() < 0.02:
123
+ last_x = max([o[0] for o in self.objs]) if self.objs else W
124
+ if last_x < W - 20:
125
+ if random.random() < 0.65:
126
+ h = random.randint(3, 4)
127
+ w = random.randint(5, 7)
128
+ cactus = []
129
+ for i in range(h):
130
+ line = ""
131
+ for j in range(w):
132
+ if i == 0 and j == w // 2: line += "┃"
133
+ elif i > 0 and (j == 0 or j == w - 1): line += "│"
134
+ elif i == h - 1: line += "━"
135
+ else: line += " " if random.random() < 0.7 else "╻"
136
+ cactus.append(line)
137
+ self.objs.append([W, w, h, GROUND - h, cactus, C_GREEN])
138
+ else:
139
+ bird_y = GROUND - random.randint(4, 7)
140
+ bird = [" ^^ ", " <^^> "]
141
+ self.objs.append([W, 6, 2, bird_y, bird, C_WHITE])
142
+
143
+ # 碰撞检测
144
+ claude_h = len(CLAUDE_A)
145
+ claude_w = max(len(r) for r in CLAUDE_A)
146
+ cx0, cy0 = X0, int(self.y)
147
+ for ox, ow, oh, oy, _, _ in self.objs:
148
+ if (cx0 + claude_w > ox and cx0 < ox + ow and
149
+ cy0 + claude_h > oy and cy0 < oy + oh):
150
+ self.over = True
151
+ self._save_high()
152
+ break
153
+
154
+ def render(self):
155
+ sys.stdout.write("\033[2J\033[H")
156
+ buf = [[" "] * W for _ in range(H)]
157
+ for x in range(W):
158
+ buf[GROUND][x] = "─"
159
+
160
+ frame_char = CLAUDE_A if (self.frame // 3) % 2 == 0 else CLAUDE_B
161
+ for dy, row in enumerate(frame_char):
162
+ y = int(self.y) + dy
163
+ if 0 <= y < H:
164
+ for dx, ch in enumerate(row):
165
+ x = X0 + dx
166
+ if 0 <= x < W and ch != " ":
167
+ buf[y][x] = f"{C_ORANGE}{ch}{C_RESET}"
168
+
169
+ for ox, ow, oh, oy, shape, col in self.objs:
170
+ for sy, row in enumerate(shape):
171
+ y = oy + sy
172
+ if 0 <= y < H:
173
+ for sx, ch in enumerate(row):
174
+ x = ox + sx
175
+ if 0 <= x < W and ch != " ":
176
+ buf[y][x] = f"{col}{ch}{C_RESET}"
177
+
178
+ for row in buf:
179
+ print(" " + "".join(row))
180
+
181
+ score_str = f"Score: {self.score:05d} High: {self.high:05d}"
182
+ hint = "Space:Jump Q:Quit" if not self.over else "GAME OVER R:Restart Q:Quit"
183
+ print(f" {C_ORANGE}{score_str}{C_RESET} {hint}")
184
+
185
+ def input_handle(self):
186
+ k = get_key()
187
+ while k:
188
+ if k == ' ':
189
+ self.jump()
190
+ elif k == 'q':
191
+ self.over = True
192
+ elif k == 'r' and self.over:
193
+ self._save_high()
194
+ self.__init__()
195
+ k = get_key()
196
+
197
+ def run(self):
198
+ try:
199
+ while not self.over:
200
+ self.input_handle()
201
+ self.update()
202
+ self.render()
203
+ time.sleep(0.04)
204
+ self.render()
205
+ time.sleep(1.5)
206
+ finally:
207
+ self._show_cursor()
208
+ self._save_high()
209
+
210
+
211
+ def main():
212
+ print(f"\n {C_ORANGE}╭─ Claude Run ──────────────────────────────╮{C_RESET}")
213
+ print(f" {C_ORANGE}│{C_RESET} 橙色小人跑酷,按任意键开始 {C_ORANGE}│{C_RESET}")
214
+ print(f" {C_ORANGE}╰──────────────────────────────────────────╯{C_RESET}")
215
+
216
+ setup_terminal()
217
+ try:
218
+ # 等待任意键
219
+ while True:
220
+ if get_key():
221
+ break
222
+ time.sleep(0.05)
223
+ g = Game()
224
+ g.run()
225
+ finally:
226
+ restore_terminal()
227
+
228
+ if __name__ == "__main__":
229
+ main()
@@ -0,0 +1,52 @@
1
+ """wocli glitch - 文字故障风效果."""
2
+
3
+ import sys
4
+ import random
5
+
6
+
7
+ def glitch_case(text):
8
+ return "".join(
9
+ c.upper() if random.random() > 0.5 else c.lower()
10
+ for c in text
11
+ )
12
+
13
+
14
+ def glitch_leet(text):
15
+ mapping = {
16
+ "a": "4", "A": "4",
17
+ "e": "3", "E": "3",
18
+ "i": "1", "I": "1",
19
+ "o": "0", "O": "0",
20
+ "s": "5", "S": "5",
21
+ "t": "7", "T": "7",
22
+ "l": "1", "L": "1",
23
+ }
24
+ return "".join(mapping.get(c, c) for c in text)
25
+
26
+
27
+ def glitch_zalgo(text):
28
+ up = "".join(random.choice("''^`") for _ in range(len(text)))
29
+ down = "".join(random.choice(",.;:") for _ in range(len(text)))
30
+ return up + "\n" + text + "\n" + down
31
+
32
+
33
+ def glitch_morse(text):
34
+ return " ".join(
35
+ "".join(random.choice([".", "-"]) for _ in range(random.randint(1, 4)))
36
+ for _ in text.split()
37
+ )
38
+
39
+
40
+ def run():
41
+ """运行 glitch 命令."""
42
+ if len(sys.argv) > 1:
43
+ text = " ".join(sys.argv[1:])
44
+ else:
45
+ text = "Hello World"
46
+
47
+ print()
48
+ print(f" Original : {text}")
49
+ print(f" Glitch 1 : {glitch_case(text)}")
50
+ print(f" Glitch 2 : {glitch_leet(text)}")
51
+ print(f" Glitch 3 : {glitch_zalgo(text)}")
52
+ print()
@@ -0,0 +1,40 @@
1
+ """wocli goodbye - 花式退出动画."""
2
+
3
+ import sys
4
+ import time
5
+ import random
6
+
7
+
8
+ MESSAGES = [
9
+ "明天又是充满 bug 的一天(目移)",
10
+ "记得 commit 和 push 哦",
11
+ "没人觉得 rust 很香吗",
12
+ "就当是为了我,对他使用force-push吧",
13
+ "Goodbye world!",
14
+ "本次编码结束,bug 数 +1。",
15
+ "代码能跑就行...",
16
+ "感谢使用awa",
17
+ "Ctrl+C 的人生不需要解释",
18
+ ]
19
+
20
+
21
+ def run():
22
+ """运行 goodbye 命令."""
23
+ msg = random.choice(MESSAGES)
24
+
25
+ print()
26
+ print(" System will shut down in 3 seconds...")
27
+ time.sleep(1)
28
+
29
+ width = 30
30
+ for i in range(width + 1):
31
+ bar = "=" * i + ">" + " " * (width - i)
32
+ pct = int(i / width * 100)
33
+ sys.stdout.write(f"\r [{bar}] {pct}%")
34
+ sys.stdout.flush()
35
+ time.sleep(0.08)
36
+
37
+ print()
38
+ print(f" {msg}")
39
+ print(" Bye!")
40
+ print()