zhmiscellany 6.2.4__py3-none-any.whl → 6.2.5__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.
- zhmiscellany/__init__.py +2 -2
- zhmiscellany/_discord_supportfuncs.py +7 -10
- zhmiscellany/_fileio_supportfuncs.py +1 -2
- zhmiscellany/_misc_supportfuncs.py +247 -146
- zhmiscellany/_processing_supportfuncs.py +28 -8
- zhmiscellany/_py_resources.py +1 -1
- zhmiscellany/dict.py +1 -3
- zhmiscellany/discord.py +45 -22
- zhmiscellany/fileio.py +70 -29
- zhmiscellany/gui.py +19 -12
- zhmiscellany/image.py +2 -4
- zhmiscellany/list.py +1 -2
- zhmiscellany/macro.py +40 -44
- zhmiscellany/math.py +3 -3
- zhmiscellany/misc.py +43 -18
- zhmiscellany/netio.py +5 -8
- zhmiscellany/pastebin.py +9 -8
- zhmiscellany/pipes.py +13 -14
- zhmiscellany/processing.py +23 -7
- zhmiscellany/rust.py +3 -1
- zhmiscellany/string.py +3 -3
- {zhmiscellany-6.2.4.dist-info → zhmiscellany-6.2.5.dist-info}/METADATA +1 -1
- zhmiscellany-6.2.5.dist-info/RECORD +27 -0
- zhmiscellany-6.2.4.dist-info/RECORD +0 -27
- {zhmiscellany-6.2.4.dist-info → zhmiscellany-6.2.5.dist-info}/WHEEL +0 -0
- {zhmiscellany-6.2.4.dist-info → zhmiscellany-6.2.5.dist-info}/top_level.txt +0 -0
zhmiscellany/__init__.py
CHANGED
|
@@ -1,7 +1,5 @@
|
|
|
1
1
|
from . import processing, misc, macro, discord, fileio, netio, string, math, image, list, dict, pipes, pastebin, cpp, gui
|
|
2
2
|
|
|
3
|
-
import importlib
|
|
4
|
-
import inspect
|
|
5
3
|
import sys
|
|
6
4
|
|
|
7
5
|
_MODULES = [
|
|
@@ -18,6 +16,8 @@ class z:
|
|
|
18
16
|
|
|
19
17
|
|
|
20
18
|
def _collect_functions():
|
|
19
|
+
import inspect
|
|
20
|
+
import importlib
|
|
21
21
|
all_funcs = []
|
|
22
22
|
for mod_name in _MODULES:
|
|
23
23
|
module = importlib.import_module(f'.{mod_name}', __package__)
|
|
@@ -1,16 +1,9 @@
|
|
|
1
|
-
import sys
|
|
2
|
-
import time
|
|
3
|
-
import re
|
|
4
|
-
import zhmiscellany.fileio
|
|
5
|
-
import zhmiscellany.string
|
|
6
|
-
import os
|
|
7
|
-
|
|
8
|
-
|
|
9
1
|
def calculateOption(guild_id, action): # action == 'append' or 'replace'
|
|
2
|
+
import re
|
|
10
3
|
if action == 'append':
|
|
11
4
|
lastUserIDs = _bot.gateway.guildMemberSearches[guild_id]["queries"][''.join(_Queries.qList)]
|
|
12
5
|
data = [_bot.gateway.session.guild(guild_id).members[i] for i in _bot.gateway.session.guild(guild_id).members if i in lastUserIDs]
|
|
13
|
-
lastName = sorted(set([re.sub(' +', ' ', j['nick'].lower()) if (j.get('nick') and re.sub(' +', ' ', j.get('nick').lower()
|
|
6
|
+
lastName = sorted(set([re.sub(' +', ' ', j['nick'].lower()) if (j.get('nick') and re.sub(' +', ' ', j.get('nick')).lower().startswith(''.join(_Queries.qList))) else re.sub(' +', ' ', j['username'].lower()) for j in data]))[-1]
|
|
14
7
|
try:
|
|
15
8
|
option = lastName[len(_Queries.qList)]
|
|
16
9
|
return option
|
|
@@ -34,6 +27,7 @@ def findReplaceableIndex(guild_id):
|
|
|
34
27
|
|
|
35
28
|
|
|
36
29
|
def bruteForceTest(resp, guild_id, wait):
|
|
30
|
+
import time
|
|
37
31
|
if resp.event.guild_members_chunk:
|
|
38
32
|
remove = False
|
|
39
33
|
if len(_bot.gateway.guildMemberSearches[guild_id]["queries"][''.join(_Queries.qList)]) == 100: # append
|
|
@@ -107,6 +101,8 @@ def scrape_guild_internal(guild_id, channel_id, user_token, console=False, extra
|
|
|
107
101
|
|
|
108
102
|
|
|
109
103
|
def scrape_guild(guild_id, channel_id, user_token, use_cache=True, console=False, extra_scrape=True):
|
|
104
|
+
import os
|
|
105
|
+
import zhmiscellany.fileio
|
|
110
106
|
if use_cache:
|
|
111
107
|
cache_folder = 'zhmiscellany_cache'
|
|
112
108
|
potential_path = os.path.join(cache_folder, f'{guild_id}_members.json')
|
|
@@ -122,5 +118,6 @@ def scrape_guild(guild_id, channel_id, user_token, use_cache=True, console=False
|
|
|
122
118
|
|
|
123
119
|
|
|
124
120
|
def print_str_if(string, print_it):
|
|
121
|
+
import sys
|
|
125
122
|
if print_it:
|
|
126
|
-
sys.stdout.write(string+'\n')
|
|
123
|
+
sys.stdout.write(string+'\n')
|
|
@@ -1,26 +1,19 @@
|
|
|
1
|
-
import
|
|
2
|
-
from ctypes import Structure, c_long, c_uint, c_int, POINTER, sizeof
|
|
3
|
-
import zhmiscellany.fileio
|
|
4
|
-
import sys
|
|
1
|
+
import sys # this one cannot be moved unfortunately
|
|
5
2
|
|
|
6
3
|
# Windows-specific imports
|
|
7
4
|
if sys.platform == "win32":
|
|
8
|
-
|
|
9
|
-
import win32api
|
|
10
|
-
from ctypes import windll
|
|
11
|
-
WIN32_AVAILABLE = True
|
|
12
|
-
except ImportError:
|
|
13
|
-
WIN32_AVAILABLE = False
|
|
14
|
-
print("Warning: Windows modules not available - Windows functionality disabled")
|
|
5
|
+
WIN32_AVAILABLE = True
|
|
15
6
|
else:
|
|
16
7
|
WIN32_AVAILABLE = False
|
|
17
8
|
|
|
18
|
-
|
|
19
9
|
_misc_action = 0
|
|
20
10
|
_misc_timeout_exists = 0
|
|
21
11
|
|
|
22
12
|
|
|
23
13
|
def do_timeout(timeout):
|
|
14
|
+
import time
|
|
15
|
+
import os
|
|
16
|
+
import signal
|
|
24
17
|
global _misc_action, _misc_timeout_exists
|
|
25
18
|
self_time = time.time()
|
|
26
19
|
_misc_timeout_exists = self_time
|
|
@@ -33,17 +26,23 @@ def do_timeout(timeout):
|
|
|
33
26
|
|
|
34
27
|
|
|
35
28
|
def set_activity_timeout(timeout):
|
|
29
|
+
import time
|
|
30
|
+
import threading
|
|
36
31
|
global _misc_action
|
|
37
32
|
_misc_action = time.time()
|
|
38
33
|
threading.Thread(target=do_timeout, args=timeout).start()
|
|
39
34
|
|
|
40
35
|
|
|
41
36
|
def activity():
|
|
37
|
+
import time
|
|
42
38
|
global _misc_action
|
|
43
39
|
_misc_action = time.time()
|
|
44
40
|
|
|
45
41
|
|
|
46
42
|
def patch_rhg(): # patches random_header_generator library's missing files. this only matters if zhmiscellany has been compiled into a pyinstaller executable. zhmiscellany chooses to patch this broken package for the benefit of the user.
|
|
43
|
+
import os
|
|
44
|
+
import shutil
|
|
45
|
+
import zhmiscellany.fileio
|
|
47
46
|
if getattr(sys, 'frozen', False):
|
|
48
47
|
# we are running in a PyInstaller bundle
|
|
49
48
|
base_path = sys._MEIPASS
|
|
@@ -61,11 +60,15 @@ def patch_rhg(): # patches random_header_generator library's missing files. thi
|
|
|
61
60
|
else:
|
|
62
61
|
# we are running in normal Python environment
|
|
63
62
|
pass
|
|
63
|
+
|
|
64
|
+
_ = None
|
|
64
65
|
if WIN32_AVAILABLE:
|
|
65
|
-
patch_rhg()
|
|
66
|
+
_ = patch_rhg()
|
|
66
67
|
|
|
67
68
|
|
|
68
69
|
def patch_cpp():
|
|
70
|
+
import os
|
|
71
|
+
import shutil
|
|
69
72
|
if getattr(sys, 'frozen', False):
|
|
70
73
|
base_path = sys._MEIPASS
|
|
71
74
|
else:
|
|
@@ -90,62 +93,14 @@ def patch_cpp():
|
|
|
90
93
|
shutil.copy2(os.path.join(base_path, 'resources', fn), tp)
|
|
91
94
|
os.chdir(cwd)
|
|
92
95
|
|
|
93
|
-
if WIN32_AVAILABLE:
|
|
94
|
-
patch_cpp()
|
|
95
96
|
|
|
96
|
-
# Linux specific imports
|
|
97
|
-
if not WIN32_AVAILABLE:
|
|
98
|
-
try:
|
|
99
|
-
try:
|
|
100
|
-
import pyautogui
|
|
101
|
-
|
|
102
|
-
# Optimize PyAutoGUI for speed to match ctypes performance
|
|
103
|
-
pyautogui.FAILSAFE = False
|
|
104
|
-
pyautogui.PAUSE = 0
|
|
105
|
-
pyautogui.MINIMUM_DURATION = 0
|
|
106
|
-
except KeyError:
|
|
107
|
-
pass
|
|
108
|
-
except ImportError:
|
|
109
|
-
raise ImportError("Linux support requires pyautogui. Install it via: pip install pyautogui")
|
|
110
|
-
|
|
111
|
-
# Windows specific imports and Structs
|
|
112
97
|
if WIN32_AVAILABLE:
|
|
113
|
-
|
|
114
|
-
_fields_ = [("x", c_long),
|
|
115
|
-
("y", c_long)]
|
|
116
|
-
|
|
117
|
-
|
|
118
|
-
class MOUSEINPUT(Structure):
|
|
119
|
-
_fields_ = [("dx", c_long),
|
|
120
|
-
("dy", c_long),
|
|
121
|
-
("mouseData", c_uint),
|
|
122
|
-
("dwFlags", c_uint),
|
|
123
|
-
("time", c_uint),
|
|
124
|
-
("dwExtraInfo", POINTER(c_uint))]
|
|
125
|
-
|
|
126
|
-
|
|
127
|
-
class INPUT_UNION(ctypes.Union):
|
|
128
|
-
_fields_ = [("mi", MOUSEINPUT)]
|
|
129
|
-
|
|
130
|
-
|
|
131
|
-
class INPUT(Structure):
|
|
132
|
-
_fields_ = [("type", c_int),
|
|
133
|
-
("union", INPUT_UNION)]
|
|
134
|
-
|
|
135
|
-
|
|
136
|
-
# Constants
|
|
137
|
-
MOUSEEVENTF_ABSOLUTE = 0x8000
|
|
138
|
-
MOUSEEVENTF_MOVE = 0x0001
|
|
139
|
-
MOUSEEVENTF_LEFTDOWN = 0x0002
|
|
140
|
-
MOUSEEVENTF_LEFTUP = 0x0004
|
|
141
|
-
MOUSEEVENTF_RIGHTDOWN = 0x0008
|
|
142
|
-
MOUSEEVENTF_RIGHTUP = 0x0010
|
|
143
|
-
MOUSEEVENTF_MIDDLEDOWN = 0x0020
|
|
144
|
-
MOUSEEVENTF_MIDDLEUP = 0x0040
|
|
98
|
+
patch_cpp()
|
|
145
99
|
|
|
146
100
|
|
|
147
101
|
def get_actual_screen_resolution():
|
|
148
102
|
if WIN32_AVAILABLE:
|
|
103
|
+
from ctypes import windll
|
|
149
104
|
hdc = windll.user32.GetDC(0)
|
|
150
105
|
width = windll.gdi32.GetDeviceCaps(hdc, 118) # HORZRES
|
|
151
106
|
height = windll.gdi32.GetDeviceCaps(hdc, 117) # VERTRES
|
|
@@ -154,6 +109,13 @@ def get_actual_screen_resolution():
|
|
|
154
109
|
else:
|
|
155
110
|
# Linux implementation using pyautogui
|
|
156
111
|
try:
|
|
112
|
+
try:
|
|
113
|
+
import pyautogui
|
|
114
|
+
pyautogui.FAILSAFE = False
|
|
115
|
+
pyautogui.PAUSE = 0
|
|
116
|
+
pyautogui.MINIMUM_DURATION = 0
|
|
117
|
+
except KeyError:
|
|
118
|
+
pass
|
|
157
119
|
return pyautogui.size()
|
|
158
120
|
except Exception:
|
|
159
121
|
# Could not determine screen resolution on Linux, defaulting to 1920x1080
|
|
@@ -171,53 +133,108 @@ calibration_multiplier_y = 1.0
|
|
|
171
133
|
def move_mouse(x: int, y: int, relative=False):
|
|
172
134
|
# --- LINUX IMPLEMENTATION ---
|
|
173
135
|
if not WIN32_AVAILABLE:
|
|
174
|
-
|
|
175
|
-
|
|
176
|
-
|
|
177
|
-
|
|
178
|
-
|
|
179
|
-
|
|
180
|
-
|
|
181
|
-
|
|
182
|
-
|
|
183
|
-
|
|
184
|
-
|
|
185
|
-
|
|
136
|
+
try:
|
|
137
|
+
try:
|
|
138
|
+
import pyautogui
|
|
139
|
+
pyautogui.FAILSAFE = False
|
|
140
|
+
pyautogui.PAUSE = 0
|
|
141
|
+
pyautogui.MINIMUM_DURATION = 0
|
|
142
|
+
except KeyError:
|
|
143
|
+
pass
|
|
144
|
+
# PyAutoGUI handles relative/absolute logic natively
|
|
145
|
+
if relative:
|
|
146
|
+
pyautogui.move(x, y)
|
|
147
|
+
else:
|
|
148
|
+
pyautogui.moveTo(x, y)
|
|
149
|
+
return
|
|
150
|
+
except ImportError:
|
|
151
|
+
raise ImportError("Linux support requires pyautogui. Install it via: pip install pyautogui")
|
|
186
152
|
else:
|
|
187
|
-
|
|
188
|
-
|
|
189
|
-
|
|
190
|
-
|
|
153
|
+
from ctypes import windll
|
|
154
|
+
from ctypes import Structure, c_long, c_uint, c_int, POINTER, sizeof
|
|
155
|
+
import ctypes
|
|
156
|
+
import math
|
|
157
|
+
|
|
158
|
+
class POINT(Structure):
|
|
159
|
+
_fields_ = [("x", c_long),
|
|
160
|
+
("y", c_long)]
|
|
161
|
+
|
|
162
|
+
class MOUSEINPUT(Structure):
|
|
163
|
+
_fields_ = [("dx", c_long),
|
|
164
|
+
("dy", c_long),
|
|
165
|
+
("mouseData", c_uint),
|
|
166
|
+
("dwFlags", c_uint),
|
|
167
|
+
("time", c_uint),
|
|
168
|
+
("dwExtraInfo", POINTER(c_uint))]
|
|
169
|
+
|
|
170
|
+
class INPUT_UNION(ctypes.Union):
|
|
171
|
+
_fields_ = [("mi", MOUSEINPUT)]
|
|
172
|
+
|
|
173
|
+
class INPUT(Structure):
|
|
174
|
+
_fields_ = [("type", c_int),
|
|
175
|
+
("union", INPUT_UNION)]
|
|
176
|
+
|
|
177
|
+
# Constants
|
|
178
|
+
MOUSEEVENTF_ABSOLUTE = 0x8000
|
|
179
|
+
MOUSEEVENTF_MOVE = 0x0001
|
|
180
|
+
MOUSEEVENTF_LEFTDOWN = 0x0002
|
|
181
|
+
MOUSEEVENTF_LEFTUP = 0x0004
|
|
182
|
+
MOUSEEVENTF_RIGHTDOWN = 0x0008
|
|
183
|
+
MOUSEEVENTF_RIGHTUP = 0x0010
|
|
184
|
+
MOUSEEVENTF_MIDDLEDOWN = 0x0020
|
|
185
|
+
MOUSEEVENTF_MIDDLEUP = 0x0040
|
|
186
|
+
|
|
187
|
+
if not relative:
|
|
188
|
+
# Convert coordinates to normalized coordinates (0-65535)
|
|
189
|
+
normalized_x = int(x * (65535 / SCREEN_WIDTH))
|
|
190
|
+
normalized_y = int(y * (65535 / SCREEN_HEIGHT))
|
|
191
191
|
else:
|
|
192
|
-
|
|
193
|
-
|
|
194
|
-
|
|
195
|
-
|
|
196
|
-
|
|
197
|
-
|
|
198
|
-
|
|
199
|
-
|
|
200
|
-
|
|
201
|
-
|
|
202
|
-
|
|
203
|
-
|
|
204
|
-
|
|
205
|
-
|
|
206
|
-
|
|
207
|
-
|
|
208
|
-
|
|
209
|
-
|
|
192
|
+
calibrate()
|
|
193
|
+
if calibrated:
|
|
194
|
+
normalized_x = math.ceil(x * calibration_multiplier_x)
|
|
195
|
+
normalized_y = math.ceil(y * calibration_multiplier_y)
|
|
196
|
+
else:
|
|
197
|
+
normalized_x = x
|
|
198
|
+
normalized_y = y
|
|
199
|
+
|
|
200
|
+
if not relative:
|
|
201
|
+
dwflags = MOUSEEVENTF_ABSOLUTE | MOUSEEVENTF_MOVE
|
|
202
|
+
else:
|
|
203
|
+
dwflags = MOUSEEVENTF_MOVE
|
|
204
|
+
|
|
205
|
+
input_struct = INPUT(
|
|
206
|
+
type=0, # INPUT_MOUSE
|
|
207
|
+
union=INPUT_UNION(
|
|
208
|
+
mi=MOUSEINPUT(
|
|
209
|
+
dx=normalized_x,
|
|
210
|
+
dy=normalized_y,
|
|
211
|
+
mouseData=0,
|
|
212
|
+
dwFlags=dwflags,
|
|
213
|
+
time=0,
|
|
214
|
+
dwExtraInfo=None
|
|
215
|
+
)
|
|
210
216
|
)
|
|
211
217
|
)
|
|
212
|
-
)
|
|
213
218
|
|
|
214
|
-
|
|
219
|
+
windll.user32.SendInput(1, ctypes.byref(input_struct), sizeof(INPUT))
|
|
215
220
|
|
|
216
221
|
|
|
217
222
|
def get_mouse_xy():
|
|
218
223
|
# --- LINUX IMPLEMENTATION ---
|
|
219
224
|
if not WIN32_AVAILABLE:
|
|
220
|
-
|
|
225
|
+
try:
|
|
226
|
+
try:
|
|
227
|
+
import pyautogui
|
|
228
|
+
pyautogui.FAILSAFE = False
|
|
229
|
+
pyautogui.PAUSE = 0
|
|
230
|
+
pyautogui.MINIMUM_DURATION = 0
|
|
231
|
+
except KeyError:
|
|
232
|
+
pass
|
|
233
|
+
return pyautogui.position()
|
|
234
|
+
except ImportError:
|
|
235
|
+
raise ImportError("Linux support requires pyautogui. Install it via: pip install pyautogui")
|
|
236
|
+
else:
|
|
237
|
+
import win32api
|
|
221
238
|
|
|
222
239
|
# --- WINDOWS IMPLEMENTATION ---
|
|
223
240
|
x, y = win32api.GetCursorPos()
|
|
@@ -272,32 +289,74 @@ def mouse_down(button: int):
|
|
|
272
289
|
|
|
273
290
|
# --- LINUX IMPLEMENTATION ---
|
|
274
291
|
if not WIN32_AVAILABLE:
|
|
275
|
-
|
|
276
|
-
|
|
277
|
-
|
|
278
|
-
|
|
279
|
-
|
|
280
|
-
|
|
281
|
-
|
|
282
|
-
|
|
283
|
-
|
|
284
|
-
|
|
285
|
-
|
|
286
|
-
|
|
287
|
-
|
|
288
|
-
|
|
289
|
-
|
|
290
|
-
|
|
291
|
-
|
|
292
|
-
|
|
293
|
-
|
|
294
|
-
|
|
295
|
-
|
|
292
|
+
try:
|
|
293
|
+
try:
|
|
294
|
+
import pyautogui
|
|
295
|
+
pyautogui.FAILSAFE = False
|
|
296
|
+
pyautogui.PAUSE = 0
|
|
297
|
+
pyautogui.MINIMUM_DURATION = 0
|
|
298
|
+
except KeyError:
|
|
299
|
+
pass
|
|
300
|
+
btn_map = {1: 'left', 2: 'right', 3: 'middle'}
|
|
301
|
+
pyautogui.mouseDown(button=btn_map[button])
|
|
302
|
+
return
|
|
303
|
+
except ImportError:
|
|
304
|
+
raise ImportError("Linux support requires pyautogui. Install it via: pip install pyautogui")
|
|
305
|
+
else:
|
|
306
|
+
from ctypes import windll
|
|
307
|
+
from ctypes import Structure, c_long, c_uint, c_int, POINTER, sizeof
|
|
308
|
+
import ctypes
|
|
309
|
+
|
|
310
|
+
class POINT(Structure):
|
|
311
|
+
_fields_ = [("x", c_long),
|
|
312
|
+
("y", c_long)]
|
|
313
|
+
|
|
314
|
+
class MOUSEINPUT(Structure):
|
|
315
|
+
_fields_ = [("dx", c_long),
|
|
316
|
+
("dy", c_long),
|
|
317
|
+
("mouseData", c_uint),
|
|
318
|
+
("dwFlags", c_uint),
|
|
319
|
+
("time", c_uint),
|
|
320
|
+
("dwExtraInfo", POINTER(c_uint))]
|
|
321
|
+
|
|
322
|
+
class INPUT_UNION(ctypes.Union):
|
|
323
|
+
_fields_ = [("mi", MOUSEINPUT)]
|
|
324
|
+
|
|
325
|
+
class INPUT(Structure):
|
|
326
|
+
_fields_ = [("type", c_int),
|
|
327
|
+
("union", INPUT_UNION)]
|
|
328
|
+
|
|
329
|
+
# Constants
|
|
330
|
+
MOUSEEVENTF_ABSOLUTE = 0x8000
|
|
331
|
+
MOUSEEVENTF_MOVE = 0x0001
|
|
332
|
+
MOUSEEVENTF_LEFTDOWN = 0x0002
|
|
333
|
+
MOUSEEVENTF_LEFTUP = 0x0004
|
|
334
|
+
MOUSEEVENTF_RIGHTDOWN = 0x0008
|
|
335
|
+
MOUSEEVENTF_RIGHTUP = 0x0010
|
|
336
|
+
MOUSEEVENTF_MIDDLEDOWN = 0x0020
|
|
337
|
+
MOUSEEVENTF_MIDDLEUP = 0x0040
|
|
338
|
+
|
|
339
|
+
flags = {
|
|
340
|
+
1: MOUSEEVENTF_LEFTDOWN,
|
|
341
|
+
2: MOUSEEVENTF_RIGHTDOWN,
|
|
342
|
+
3: MOUSEEVENTF_MIDDLEDOWN
|
|
343
|
+
}
|
|
344
|
+
|
|
345
|
+
input_struct = INPUT(
|
|
346
|
+
type=0, # INPUT_MOUSE
|
|
347
|
+
union=INPUT_UNION(
|
|
348
|
+
mi=MOUSEINPUT(
|
|
349
|
+
dx=0,
|
|
350
|
+
dy=0,
|
|
351
|
+
mouseData=0,
|
|
352
|
+
dwFlags=flags[button],
|
|
353
|
+
time=0,
|
|
354
|
+
dwExtraInfo=None
|
|
355
|
+
)
|
|
296
356
|
)
|
|
297
357
|
)
|
|
298
|
-
)
|
|
299
358
|
|
|
300
|
-
|
|
359
|
+
windll.user32.SendInput(1, ctypes.byref(input_struct), sizeof(INPUT))
|
|
301
360
|
|
|
302
361
|
|
|
303
362
|
def mouse_up(button: int):
|
|
@@ -307,29 +366,71 @@ def mouse_up(button: int):
|
|
|
307
366
|
|
|
308
367
|
# --- LINUX IMPLEMENTATION ---
|
|
309
368
|
if not WIN32_AVAILABLE:
|
|
310
|
-
|
|
311
|
-
|
|
312
|
-
|
|
313
|
-
|
|
314
|
-
|
|
315
|
-
|
|
316
|
-
|
|
317
|
-
|
|
318
|
-
|
|
319
|
-
|
|
320
|
-
|
|
321
|
-
|
|
322
|
-
|
|
323
|
-
|
|
324
|
-
|
|
325
|
-
|
|
326
|
-
|
|
327
|
-
|
|
328
|
-
|
|
329
|
-
|
|
330
|
-
|
|
369
|
+
try:
|
|
370
|
+
try:
|
|
371
|
+
import pyautogui
|
|
372
|
+
pyautogui.FAILSAFE = False
|
|
373
|
+
pyautogui.PAUSE = 0
|
|
374
|
+
pyautogui.MINIMUM_DURATION = 0
|
|
375
|
+
except KeyError:
|
|
376
|
+
pass
|
|
377
|
+
btn_map = {1: 'left', 2: 'right', 3: 'middle'}
|
|
378
|
+
pyautogui.mouseUp(button=btn_map[button])
|
|
379
|
+
return
|
|
380
|
+
except ImportError:
|
|
381
|
+
raise ImportError("Linux support requires pyautogui. Install it via: pip install pyautogui")
|
|
382
|
+
else:
|
|
383
|
+
from ctypes import windll
|
|
384
|
+
from ctypes import Structure, c_long, c_uint, c_int, POINTER, sizeof
|
|
385
|
+
import ctypes
|
|
386
|
+
|
|
387
|
+
class POINT(Structure):
|
|
388
|
+
_fields_ = [("x", c_long),
|
|
389
|
+
("y", c_long)]
|
|
390
|
+
|
|
391
|
+
class MOUSEINPUT(Structure):
|
|
392
|
+
_fields_ = [("dx", c_long),
|
|
393
|
+
("dy", c_long),
|
|
394
|
+
("mouseData", c_uint),
|
|
395
|
+
("dwFlags", c_uint),
|
|
396
|
+
("time", c_uint),
|
|
397
|
+
("dwExtraInfo", POINTER(c_uint))]
|
|
398
|
+
|
|
399
|
+
class INPUT_UNION(ctypes.Union):
|
|
400
|
+
_fields_ = [("mi", MOUSEINPUT)]
|
|
401
|
+
|
|
402
|
+
class INPUT(Structure):
|
|
403
|
+
_fields_ = [("type", c_int),
|
|
404
|
+
("union", INPUT_UNION)]
|
|
405
|
+
|
|
406
|
+
# Constants
|
|
407
|
+
MOUSEEVENTF_ABSOLUTE = 0x8000
|
|
408
|
+
MOUSEEVENTF_MOVE = 0x0001
|
|
409
|
+
MOUSEEVENTF_LEFTDOWN = 0x0002
|
|
410
|
+
MOUSEEVENTF_LEFTUP = 0x0004
|
|
411
|
+
MOUSEEVENTF_RIGHTDOWN = 0x0008
|
|
412
|
+
MOUSEEVENTF_RIGHTUP = 0x0010
|
|
413
|
+
MOUSEEVENTF_MIDDLEDOWN = 0x0020
|
|
414
|
+
MOUSEEVENTF_MIDDLEUP = 0x0040
|
|
415
|
+
|
|
416
|
+
flags = {
|
|
417
|
+
1: MOUSEEVENTF_LEFTUP,
|
|
418
|
+
2: MOUSEEVENTF_RIGHTUP,
|
|
419
|
+
3: MOUSEEVENTF_MIDDLEUP
|
|
420
|
+
}
|
|
421
|
+
|
|
422
|
+
input_struct = INPUT(
|
|
423
|
+
type=0, # INPUT_MOUSE
|
|
424
|
+
union=INPUT_UNION(
|
|
425
|
+
mi=MOUSEINPUT(
|
|
426
|
+
dx=0,
|
|
427
|
+
dy=0,
|
|
428
|
+
mouseData=0,
|
|
429
|
+
dwFlags=flags[button],
|
|
430
|
+
time=0,
|
|
431
|
+
dwExtraInfo=None
|
|
432
|
+
)
|
|
331
433
|
)
|
|
332
434
|
)
|
|
333
|
-
)
|
|
334
435
|
|
|
335
|
-
|
|
436
|
+
windll.user32.SendInput(1, ctypes.byref(input_struct), sizeof(INPUT))
|