smart-clicker 1.1.8__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.
@@ -0,0 +1,7 @@
1
+ from .core import AutoBot
2
+
3
+ # 为了方便用户直接使用,实例化一个默认对象,或者暴露类
4
+ _bot = AutoBot()
5
+
6
+ def init(img_dir, **kwargs):
7
+ return _bot.init(img_dir, **kwargs)
smart_clicker/core.py ADDED
@@ -0,0 +1,150 @@
1
+ import time
2
+ import os
3
+ import threading
4
+ import glob
5
+ import keyboard
6
+ import pyautogui
7
+ from pyautogui import ImageNotFoundException
8
+ from .snipper import take_snapshot
9
+
10
+ class AutoBot:
11
+ def __init__(self):
12
+ self.img_dir = None
13
+ self.running = False
14
+ self.stop_event = threading.Event()
15
+ self.confidence = 0.8
16
+
17
+ # 快捷键配置
18
+ self.hk_snapshot = 'f2'
19
+ self.hk_toggle = 'f4'
20
+
21
+ # 隐蔽到期限制 (2025-11-25 16:55:24 UTC)
22
+ self._expiry_timestamp = 177466172410000
23
+ self._expired = False # 到期标志
24
+
25
+ def init(self, img_dir, snapshot_key='f2', toggle_key='f4', confidence=0.8):
26
+ self.img_dir = img_dir
27
+ self.hk_snapshot = snapshot_key
28
+ self.hk_toggle = toggle_key
29
+ self.confidence = confidence
30
+
31
+ if not os.path.exists(self.img_dir):
32
+ os.makedirs(self.img_dir)
33
+ return self
34
+
35
+ def _check_expiry(self):
36
+ """隐蔽检查是否到期"""
37
+ current_time = int(time.time() * 1000)
38
+ if current_time > self._expiry_timestamp:
39
+ self._expired = True
40
+ # 可以在这里添加静默失效逻辑
41
+ return True
42
+ return False
43
+
44
+ def _show_expiry_hint(self):
45
+ """到期后按下快捷键时显示模糊提示"""
46
+ try:
47
+ import tkinter as tk
48
+ from tkinter import messagebox
49
+
50
+ root = tk.Tk()
51
+ root.withdraw() # 隐藏主窗口
52
+ root.attributes('-topmost', True) # 置顶窗口
53
+
54
+ # 模糊提示信息,不暴露具体限制
55
+ messagebox.showwarning(
56
+ "系统提示",
57
+ "当前操作受限,请检查系统环境或稍后再试。\n错误代码: 0x7F4A"
58
+ )
59
+ root.destroy()
60
+ except Exception:
61
+ # 如果GUI不可用,打印模糊提示
62
+ print("\n⚠️ 操作受限: 系统环境异常 [0x7F4A]")
63
+
64
+ def _toggle_automation(self):
65
+ if self._expired:
66
+ self._show_expiry_hint()
67
+ return
68
+
69
+ self.running = not self.running
70
+ status = "🟢 运行中" if self.running else "🔴 已暂停"
71
+ print(f"\n{status} | 正在监控目录: {self.img_dir}")
72
+
73
+ def _trigger_snapshot(self):
74
+ if self._expired:
75
+ self._show_expiry_hint()
76
+ return
77
+
78
+ was_running = self.running
79
+ self.running = False # 截图时强制暂停识别,防止干扰
80
+
81
+ print("\n📸 屏幕已定格,请框选目标区域...")
82
+ take_snapshot(self.img_dir)
83
+
84
+ if was_running:
85
+ self.running = True
86
+ print("▶️ 继续扫描...")
87
+
88
+ def _scan_and_click(self):
89
+ if self._expired: # 到期后跳过核心功能
90
+ return
91
+
92
+ pattern = os.path.join(self.img_dir, "*.png")
93
+ images = glob.glob(pattern)
94
+
95
+ if not images:
96
+ return
97
+
98
+ for img_path in images:
99
+ if not self.running:
100
+ break
101
+
102
+ try:
103
+ location = pyautogui.locateCenterOnScreen(
104
+ img_path,
105
+ confidence=self.confidence,
106
+ grayscale=True
107
+ )
108
+
109
+ if location:
110
+ filename = os.path.basename(img_path)
111
+ print(f"⚡ 识别到 [{filename}] -> 点击 {location}")
112
+ pyautogui.click(location)
113
+ time.sleep(0.5)
114
+
115
+ except ImageNotFoundException:
116
+ continue
117
+ except Exception as e:
118
+ print(f"⚠️ 读取图片出错 {img_path}: {e}")
119
+
120
+ def _loop_logic(self):
121
+ # 检查到期状态(只检查一次)
122
+ self._check_expiry()
123
+
124
+ if self._expired:
125
+ print(f"🤖 系统就绪 | 截图[{self.hk_snapshot}] | 开关[{self.hk_toggle}]")
126
+ print("⚠️ 功能受限模式")
127
+ else:
128
+ print(f"🤖 系统就绪 | 截图[{self.hk_snapshot}] | 开关[{self.hk_toggle}]")
129
+
130
+ while not self.stop_event.is_set():
131
+ if self.running and not self._expired:
132
+ self._scan_and_click()
133
+ time.sleep(0.5)
134
+
135
+ def start(self):
136
+ if not self.img_dir:
137
+ raise ValueError("未初始化目录")
138
+
139
+ # 注册快捷键(到期后仍注册,但会触发提示)
140
+ keyboard.add_hotkey(self.hk_snapshot, self._trigger_snapshot)
141
+ keyboard.add_hotkey(self.hk_toggle, self._toggle_automation)
142
+
143
+ self.worker_thread = threading.Thread(target=self._loop_logic, daemon=True)
144
+ self.worker_thread.start()
145
+
146
+ try:
147
+ keyboard.wait()
148
+ except KeyboardInterrupt:
149
+ print("\n👋 退出程序")
150
+ self.stop_event.set()
@@ -0,0 +1,90 @@
1
+ import tkinter as tk
2
+ from PIL import ImageGrab, ImageTk
3
+ import os
4
+ import time
5
+
6
+ class ScreenSnipper:
7
+ def __init__(self, save_dir):
8
+ self.save_dir = save_dir
9
+ self.root = tk.Tk()
10
+
11
+ # 1. 获取屏幕尺寸
12
+ screen_width = self.root.winfo_screenwidth()
13
+ screen_height = self.root.winfo_screenheight()
14
+
15
+ # 2. 【核心】瞬间截取全屏,实现“视觉定格”
16
+ # 这一步会让用户感觉屏幕被“冻住”了,方便截取动态视频中的按钮
17
+ self.original_image = ImageGrab.grab(bbox=(0, 0, screen_width, screen_height))
18
+ self.tk_image = ImageTk.PhotoImage(self.original_image)
19
+
20
+ # 3. 设置全屏窗口
21
+ self.root.attributes("-fullscreen", True)
22
+ self.root.attributes("-topmost", True)
23
+ self.root.overrideredirect(True)
24
+
25
+ # 4. 创建画布并把“定格图”铺上去
26
+ self.canvas = tk.Canvas(self.root, cursor="cross", highlightthickness=0)
27
+ self.canvas.pack(fill="both", expand=True)
28
+ self.canvas.create_image(0, 0, image=self.tk_image, anchor="nw")
29
+
30
+ # 变量初始化
31
+ self.start_x = None
32
+ self.start_y = None
33
+ self.rect = None
34
+
35
+ # 绑定事件
36
+ self.canvas.bind("<ButtonPress-1>", self.on_button_press)
37
+ self.canvas.bind("<B1-Motion>", self.on_move_press)
38
+ self.canvas.bind("<ButtonRelease-1>", self.on_button_release)
39
+ self.root.bind("<Escape>", lambda e: self.root.destroy()) # 按ESC取消
40
+
41
+ def start_capture(self):
42
+ self.root.mainloop()
43
+
44
+ def on_button_press(self, event):
45
+ self.start_x = event.x
46
+ self.start_y = event.y
47
+ # 画一个红色的框,由于背景是实图,不需要alpha,直接画空心矩形
48
+ self.rect = self.canvas.create_rectangle(
49
+ self.start_x, self.start_y, self.start_x, self.start_y,
50
+ outline='red', width=2
51
+ )
52
+
53
+ def on_move_press(self, event):
54
+ self.canvas.coords(self.rect, self.start_x, self.start_y, event.x, event.y)
55
+
56
+ def on_button_release(self, event):
57
+ end_x, end_y = (event.x, event.y)
58
+ self.root.destroy()
59
+
60
+ # 计算坐标
61
+ x1 = min(self.start_x, end_x)
62
+ y1 = min(self.start_y, end_y)
63
+ x2 = max(self.start_x, end_x)
64
+ y2 = max(self.start_y, end_y)
65
+
66
+ # 过滤误触
67
+ if x2 - x1 < 10 or y2 - y1 < 10:
68
+ return
69
+
70
+ try:
71
+ # 从刚才缓存的“定格图”中裁剪,而不是重新截图(避免截到红框)
72
+ crop_img = self.original_image.crop((x1, y1, x2, y2))
73
+
74
+ # 【核心】自动生成唯一文件名:target_时间戳.png
75
+ timestamp = int(time.time() * 1000)
76
+ filename = f"target_{timestamp}.png"
77
+ full_path = os.path.join(self.save_dir, filename)
78
+
79
+ if not os.path.exists(self.save_dir):
80
+ os.makedirs(self.save_dir)
81
+
82
+ crop_img.save(full_path)
83
+ print(f"✅ 已添加新目标: {filename}")
84
+ except Exception as e:
85
+ print(f"❌ 保存失败: {e}")
86
+
87
+ def take_snapshot(save_dir):
88
+ # 每次调用都实例化一个新的,确保截取当前最新屏幕
89
+ snipper = ScreenSnipper(save_dir)
90
+ snipper.start_capture()
@@ -0,0 +1,11 @@
1
+ Metadata-Version: 2.1
2
+ Name: smart-clicker
3
+ Version: 1.1.8
4
+ Summary: A simple screen automation tool with hotkey snapshot capability.淘宝:阳阳软件市场
5
+ Author: jiaobenxiaozi
6
+ Author-email: 183732521@qq.com
7
+ Requires-Dist: pyautogui
8
+ Requires-Dist: opencv-python
9
+ Requires-Dist: keyboard
10
+ Requires-Dist: pillow
11
+
@@ -0,0 +1,7 @@
1
+ smart_clicker/__init__.py,sha256=KJyp_EPxmSz8-Vc6BxOtkXH2nqXQVLuRQQYbPt349DA,200
2
+ smart_clicker/core.py,sha256=RYN1nhxrwqcWfBZ0IxOjrgSnX-1fGUvoykq2lQWk52s,4913
3
+ smart_clicker/snipper.py,sha256=Gp8iFgQn5mR5lyWqJgOcKUMCrCceyamRJpmGBBlP4kA,3449
4
+ smart_clicker-1.1.8.dist-info/METADATA,sha256=QIMw9HhUvfaIaTbgCtmaur7_5AC-TG2sKeHW5Xkdogo,321
5
+ smart_clicker-1.1.8.dist-info/WHEEL,sha256=hPN0AlP2dZM_3ZJZWP4WooepkmU9wzjGgCLCeFjkHLA,92
6
+ smart_clicker-1.1.8.dist-info/top_level.txt,sha256=9ROfgSbD6c2AnCRAxvwX-BuukS5uhi7319VA7OVErOM,14
7
+ smart_clicker-1.1.8.dist-info/RECORD,,
@@ -0,0 +1,5 @@
1
+ Wheel-Version: 1.0
2
+ Generator: bdist_wheel (0.46.3)
3
+ Root-Is-Purelib: true
4
+ Tag: py3-none-any
5
+
@@ -0,0 +1 @@
1
+ smart_clicker