zhmiscellany 6.0.6__py3-none-any.whl → 6.0.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.
@@ -1,4 +1,8 @@
1
+ import sys
2
+
1
3
  def is_junction(entry):
4
+ if sys.platform != "win32":
5
+ return False
2
6
  try:
3
7
  st = entry.stat(follow_symlinks=False)
4
8
  # On Windows, st_file_attributes is available.
@@ -1,7 +1,19 @@
1
- import threading, os, signal, time, sys, shutil, ctypes
1
+ import threading, os, signal, time, sys, shutil, ctypes, math
2
2
  from ctypes import Structure, c_long, c_uint, c_int, POINTER, sizeof
3
3
  import zhmiscellany.fileio
4
- import win32api, math
4
+ import sys
5
+
6
+ # Windows-specific imports
7
+ if sys.platform == "win32":
8
+ try:
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")
15
+ else:
16
+ WIN32_AVAILABLE = False
5
17
 
6
18
 
7
19
  _misc_action = 0
@@ -48,7 +60,8 @@ def patch_rhg(): # patches random_header_generator library's missing files. thi
48
60
  else:
49
61
  # we are running in normal Python environment
50
62
  pass
51
- patch_rhg()
63
+ if WIN32_AVAILABLE:
64
+ patch_rhg()
52
65
 
53
66
 
54
67
  def patch_cpp():
@@ -75,7 +88,9 @@ def patch_cpp():
75
88
  gen()
76
89
  shutil.copy2(os.path.join(base_path, 'resources', fn), tp)
77
90
  os.chdir(cwd)
78
- patch_cpp()
91
+
92
+ if WIN32_AVAILABLE:
93
+ patch_cpp()
79
94
 
80
95
 
81
96
  class POINT(Structure):
@@ -113,18 +128,26 @@ MOUSEEVENTF_MIDDLEUP = 0x0040
113
128
 
114
129
  # Screen metrics
115
130
  def get_actual_screen_resolution():
116
- hdc = ctypes.windll.user32.GetDC(0)
117
- width = ctypes.windll.gdi32.GetDeviceCaps(hdc, 118) # HORZRES
118
- height = ctypes.windll.gdi32.GetDeviceCaps(hdc, 117) # VERTRES
119
- ctypes.windll.user32.ReleaseDC(0, hdc)
120
- return width, height
131
+ if WIN32_AVAILABLE:
132
+ hdc = windll.user32.GetDC(0)
133
+ width = windll.gdi32.GetDeviceCaps(hdc, 118) # HORZRES
134
+ height = windll.gdi32.GetDeviceCaps(hdc, 117) # VERTRES
135
+ windll.user32.ReleaseDC(0, hdc)
136
+ return width, height
137
+ else:
138
+ print("get_actual_screen_resolution() only supports Windows! Returning (1920, 1080)")
139
+ return 1920, 1080
121
140
 
122
- SCREEN_WIDTH, SCREEN_HEIGHT = get_actual_screen_resolution()
141
+ SCREEN_WIDTH, SCREEN_HEIGHT = (1920, 1080) if not WIN32_AVAILABLE else get_actual_screen_resolution()
123
142
 
124
143
  calibrated = False
125
144
  calipass = False
126
145
 
127
146
  def move_mouse(x: int, y: int, relative=False):
147
+ if not WIN32_AVAILABLE:
148
+ print("move_mouse() only supports Windows! Functionality disabled")
149
+ return
150
+
128
151
  if not relative:
129
152
  # Convert coordinates to normalized coordinates (0-65535)
130
153
  normalized_x = int(x * (65535 / SCREEN_WIDTH))
@@ -157,13 +180,21 @@ def move_mouse(x: int, y: int, relative=False):
157
180
  )
158
181
  )
159
182
 
160
- ctypes.windll.user32.SendInput(1, ctypes.byref(input_struct), sizeof(INPUT))
183
+ windll.user32.SendInput(1, ctypes.byref(input_struct), sizeof(INPUT))
161
184
 
162
185
  def get_mouse_xy():
163
- x, y = win32api.GetCursorPos()
164
- return x, y
186
+ if WIN32_AVAILABLE:
187
+ x, y = win32api.GetCursorPos()
188
+ return x, y
189
+ else:
190
+ print("get_mouse_xy() only supports Windows! Returning (0, 0)")
191
+ return 0, 0
165
192
 
166
193
  def calibrate():
194
+ if not WIN32_AVAILABLE:
195
+ print("calibrate() only supports Windows! Functionality disabled")
196
+ return
197
+
167
198
  global calibration_multiplier_x, calibration_multiplier_y, calibrated, calipass
168
199
  if calibrated:
169
200
  return
@@ -191,6 +222,10 @@ def calibrate():
191
222
 
192
223
  def mouse_down(button: int):
193
224
  """Press mouse button down. button: 1=left, 2=right, 3=middle"""
225
+ if not WIN32_AVAILABLE:
226
+ print("mouse_down() only supports Windows! Functionality disabled")
227
+ return
228
+
194
229
  if button not in [1, 2, 3]:
195
230
  raise ValueError("Button must be 1 (left), 2 (right), or 3 (middle)")
196
231
 
@@ -214,11 +249,15 @@ def mouse_down(button: int):
214
249
  )
215
250
  )
216
251
 
217
- ctypes.windll.user32.SendInput(1, ctypes.byref(input_struct), sizeof(INPUT))
252
+ windll.user32.SendInput(1, ctypes.byref(input_struct), sizeof(INPUT))
218
253
 
219
254
 
220
255
  def mouse_up(button: int):
221
256
  """Release mouse button. button: 1=left, 2=right, 3=middle"""
257
+ if not WIN32_AVAILABLE:
258
+ print("mouse_up() only supports Windows! Functionality disabled")
259
+ return
260
+
222
261
  if button not in [1, 2, 3]:
223
262
  raise ValueError("Button must be 1 (left), 2 (right), or 3 (middle)")
224
263
 
@@ -242,4 +281,4 @@ def mouse_up(button: int):
242
281
  )
243
282
  )
244
283
 
245
- ctypes.windll.user32.SendInput(1, ctypes.byref(input_struct), sizeof(INPUT))
284
+ windll.user32.SendInput(1, ctypes.byref(input_struct), sizeof(INPUT))
@@ -7,6 +7,18 @@ import sys
7
7
  import io
8
8
  from unittest.mock import patch
9
9
 
10
+ # Ray availability check
11
+ if sys.platform == "win32":
12
+ try:
13
+ import ray
14
+ RAY_AVAILABLE = True
15
+ except ImportError:
16
+ RAY_AVAILABLE = False
17
+ print("Warning: Ray not available - multiprocessing functionality disabled")
18
+ else:
19
+ RAY_AVAILABLE = False
20
+ print("Ray is only supported on Windows - multiprocessing functionality disabled")
21
+
10
22
 
11
23
  def clear_logs():
12
24
  ray_dir = tempfile.gettempdir()
@@ -59,6 +71,10 @@ def safe_open_log(path, unbuffered=False, **kwargs):
59
71
 
60
72
 
61
73
  def ray_init(auto=False):
74
+ if not RAY_AVAILABLE:
75
+ print("ray_init() only supports Windows! Functionality disabled")
76
+ return
77
+
62
78
  if auto:
63
79
  if 'in_ray_matrix' in os.environ:
64
80
  return
@@ -184,6 +200,10 @@ class ThreadWithResult(threading.Thread):
184
200
 
185
201
 
186
202
  def batch_multiprocess(targets_and_args, max_retries=0, expect_crashes=False, disable_warning=False, flatten=False):
203
+ if not RAY_AVAILABLE:
204
+ print("batch_multiprocess() only supports Windows! Returning empty list")
205
+ return []
206
+
187
207
  if _ray_state == 'disabled':
188
208
  if not disable_warning:
189
209
  logging.warning("zhmiscellany didn't detect that you were going to be using multiprocessing functions, and ray was not initialized preemptively.\n\
@@ -231,6 +251,9 @@ from zhmiscellany._processing_supportfuncs import _ray_init_thread; _ray_init_th
231
251
  return results
232
252
 
233
253
  def multiprocess(target, args=(), max_retries=0, disable_warning=False):
254
+ if not RAY_AVAILABLE:
255
+ print("multiprocess() only supports Windows! Returning None")
256
+ return None
234
257
  return batch_multiprocess([(target, args)], disable_warning=disable_warning, max_retries=max_retries)[0]
235
258
 
236
259
 
@@ -257,6 +280,10 @@ class RayActorWrapper:
257
280
 
258
281
 
259
282
  def synchronous_class_multiprocess(cls, *args, disable_warning=False, **kwargs):
283
+ if not RAY_AVAILABLE:
284
+ print("synchronous_class_multiprocess() only supports Windows! Returning None")
285
+ return None
286
+
260
287
  if _ray_state == 'disabled':
261
288
  if not disable_warning:
262
289
  logging.warning("zhmiscellany didn't detect that you were going to be using multiprocessing functions, and ray was not initialized preemptively.\n\
@@ -278,4 +305,4 @@ from zhmiscellany._processing_supportfuncs import _ray_init_thread; _ray_init_th
278
305
 
279
306
  remote_cls = ray.remote(cls)
280
307
  actor_instance = remote_cls.remote(*args, **kwargs)
281
- return RayActorWrapper(actor_instance)
308
+ return RayActorWrapper(actor_instance)
zhmiscellany/discord.py CHANGED
@@ -1,5 +1,5 @@
1
1
  import time
2
-
2
+ import sys
3
3
  import requests
4
4
  import copy
5
5
  import zhmiscellany.fileio
@@ -8,11 +8,21 @@ import zhmiscellany.processing
8
8
  from ._discord_supportfuncs import scrape_guild
9
9
 
10
10
  import base64
11
- import Crypto.Cipher.AES
12
11
  import os
13
12
  import json
14
13
  import re
15
- import win32crypt
14
+
15
+ # Windows-specific imports
16
+ if sys.platform == "win32":
17
+ try:
18
+ import win32crypt
19
+ from Crypto.Cipher import AES
20
+ WIN32_AVAILABLE = True
21
+ except ImportError:
22
+ WIN32_AVAILABLE = False
23
+ print("Warning: Windows modules not available - local Discord user detection disabled")
24
+ else:
25
+ WIN32_AVAILABLE = False
16
26
 
17
27
 
18
28
  def add_reactions_to_message(user_token, emojis, channel_id, message_id):
@@ -108,6 +118,10 @@ def get_channel_messages(user_token, channel_id, limit=0, use_cache=True, show_p
108
118
 
109
119
 
110
120
  def get_local_discord_user(show_output=False):
121
+ if not WIN32_AVAILABLE:
122
+ print("get_local_discord_user() only supports Windows! Returning None")
123
+ return None
124
+
111
125
  global _cached_user_info
112
126
  try:
113
127
  a = _cached_user_info
@@ -121,7 +135,7 @@ def get_local_discord_user(show_output=False):
121
135
 
122
136
  def decrypt(buff, master_key):
123
137
  try:
124
- return Crypto.Cipher.AES.new(win32crypt.CryptUnprotectData(master_key, None, None, None, 0)[1], Crypto.Cipher.AES.MODE_GCM, buff[3:15]).decrypt(buff[15:])[:-16].decode()
138
+ return AES.new(win32crypt.CryptUnprotectData(master_key, None, None, None, 0)[1], AES.MODE_GCM, buff[3:15]).decrypt(buff[15:])[:-16].decode()
125
139
  except:
126
140
  return "Error"
127
141
 
zhmiscellany/gui.py CHANGED
@@ -1,8 +1,19 @@
1
1
  import tkinter as tk
2
2
  import threading
3
- import ctypes
4
- from ctypes import wintypes
5
- import win32gui
3
+ import sys
4
+
5
+ # Windows-specific imports
6
+ if sys.platform == "win32":
7
+ try:
8
+ import ctypes
9
+ from ctypes import wintypes
10
+ import win32gui
11
+ WIN32_AVAILABLE = True
12
+ except ImportError:
13
+ WIN32_AVAILABLE = False
14
+ print("Warning: Windows modules not available - GUI functionality disabled")
15
+ else:
16
+ WIN32_AVAILABLE = False
6
17
 
7
18
 
8
19
  class StateIndicator:
@@ -65,6 +76,10 @@ class StateIndicator:
65
76
 
66
77
  def _make_click_through(self):
67
78
  """Make the window click-through using Windows API"""
79
+ if not WIN32_AVAILABLE:
80
+ print("Click-through only supported on Windows")
81
+ return
82
+
68
83
  try:
69
84
  # Get the window handle
70
85
  hwnd = ctypes.windll.user32.GetParent(self._root.winfo_id())
@@ -126,6 +141,9 @@ class StateIndicator:
126
141
 
127
142
  def _update_layered_attributes(self):
128
143
  """Update the layered window attributes for proper transparency with click-through"""
144
+ if not WIN32_AVAILABLE:
145
+ return
146
+
129
147
  try:
130
148
  hwnd = ctypes.windll.user32.GetParent(self._root.winfo_id())
131
149
  if hwnd == 0:
@@ -179,50 +197,64 @@ class StateIndicator:
179
197
  if self._root and self._root.winfo_exists():
180
198
  self._root.after(0, self._update_size_internal)
181
199
 
182
- import ctypes
183
- from ctypes import wintypes
184
- user32 = ctypes.windll.user32
185
-
186
- def get_focused_window():
187
- """Return the window that currently has the keyboard focus."""
188
- return user32.GetForegroundWindow()
189
-
190
- def get_window_rect(hwnd):
191
- """Return the bounding rectangle of a window."""
192
- HWND = wintypes.HWND
193
- RECT = wintypes.RECT
194
- rect = RECT()
195
- user32.GetWindowRect(hwnd, ctypes.byref(rect))
196
- return rect
197
-
198
- def set_window_pos(hwnd, x: int, y: int, w: int, h: int):
199
- """Move (and optionally resize) a window."""
200
- # 0x0040 == SWP_NOACTIVATE | 0x0020 == SWP_SHOWWINDOW
201
- user32.SetWindowPos(hwnd, 0, x, y, w, h, 0x0040 | 0x0020)
202
-
203
-
204
- def find_window_by_title_fuzzy(title_query, threshold=70):
205
- from fuzzywuzzy import process
206
- from fuzzywuzzy import fuzz
207
- def enum_windows_callback(hwnd, windows):
208
- if win32gui.IsWindowVisible(hwnd):
209
- window_title = win32gui.GetWindowText(hwnd)
210
- if window_title:
211
- windows.append((hwnd, window_title))
212
- return True
213
-
214
- windows = []
215
- win32gui.EnumWindows(enum_windows_callback, windows)
216
-
217
- if not windows:
200
+ if WIN32_AVAILABLE:
201
+ user32 = ctypes.windll.user32
202
+
203
+ def get_focused_window():
204
+ """Return the window that currently has the keyboard focus."""
205
+ return user32.GetForegroundWindow()
206
+
207
+ def get_window_rect(hwnd):
208
+ """Return the bounding rectangle of a window."""
209
+ HWND = wintypes.HWND
210
+ RECT = wintypes.RECT
211
+ rect = RECT()
212
+ user32.GetWindowRect(hwnd, ctypes.byref(rect))
213
+ return rect
214
+
215
+ def set_window_pos(hwnd, x: int, y: int, w: int, h: int):
216
+ """Move (and optionally resize) a window."""
217
+ # 0x0040 == SWP_NOACTIVATE | 0x0020 == SWP_SHOWWINDOW
218
+ user32.SetWindowPos(hwnd, 0, x, y, w, h, 0x0040 | 0x0020)
219
+
220
+
221
+ def find_window_by_title_fuzzy(title_query, threshold=70):
222
+ from fuzzywuzzy import process
223
+ from fuzzywuzzy import fuzz
224
+ def enum_windows_callback(hwnd, windows):
225
+ if win32gui.IsWindowVisible(hwnd):
226
+ window_title = win32gui.GetWindowText(hwnd)
227
+ if window_title:
228
+ windows.append((hwnd, window_title))
229
+ return True
230
+
231
+ windows = []
232
+ win32gui.EnumWindows(enum_windows_callback, windows)
233
+
234
+ if not windows:
235
+ return None
236
+
237
+ titles = [title for hwnd, title in windows]
238
+ best_match = process.extractOne(title_query, titles, scorer=fuzz.token_set_ratio)
239
+
240
+ if best_match[1] >= threshold:
241
+ matched_title = best_match[0]
242
+ for hwnd, title in windows:
243
+ if title == matched_title:
244
+ return hwnd
245
+ return None
246
+ else:
247
+ def get_focused_window():
248
+ print("get_focused_window() only supports Windows! Returning None")
249
+ return None
250
+
251
+ def get_window_rect(hwnd):
252
+ print("get_window_rect() only supports Windows! Returning None")
218
253
  return None
219
254
 
220
- titles = [title for hwnd, title in windows]
221
- best_match = process.extractOne(title_query, titles, scorer=fuzz.token_set_ratio)
255
+ def set_window_pos(hwnd, x: int, y: int, w: int, h: int):
256
+ print("set_window_pos() only supports Windows! Functionality disabled")
222
257
 
223
- if best_match[1] >= threshold:
224
- matched_title = best_match[0]
225
- for hwnd, title in windows:
226
- if title == matched_title:
227
- return hwnd
228
- return None
258
+ def find_window_by_title_fuzzy(title_query, threshold=70):
259
+ print("find_window_by_title_fuzzy() only supports Windows! Returning None")
260
+ return None
zhmiscellany/macro.py CHANGED
@@ -1,16 +1,26 @@
1
1
  import math
2
2
  import random
3
3
  import threading
4
+ import sys
4
5
 
5
6
  from ._misc_supportfuncs import move_mouse, mouse_down, mouse_up, get_mouse_xy
6
7
  import zhmiscellany.misc
7
8
  import zhmiscellany.math
8
9
  import zhmiscellany.string
9
10
  import zhmiscellany.processing
10
- import win32api, win32con, ctypes
11
11
 
12
- import keyboard, kthread
12
+ # Windows-specific imports
13
+ if sys.platform == "win32":
14
+ try:
15
+ import win32api, win32con, ctypes
16
+ WIN32_AVAILABLE = True
17
+ except ImportError:
18
+ WIN32_AVAILABLE = False
19
+ print("Warning: Windows modules not available - macro functionality disabled")
20
+ else:
21
+ WIN32_AVAILABLE = False
13
22
 
23
+ import keyboard, kthread
14
24
  import time
15
25
 
16
26
  get_mouse_xy = get_mouse_xy
@@ -105,13 +115,17 @@ def click_pixel(x=None, y=None, click_duration=None, right_click=False, middle_c
105
115
  for point in animation_points:
106
116
  click_pixel((round(point[0]), round(point[1])), act_start=False, act_end=False, click_end_duration=1/animation_fps, relative=relative)
107
117
 
108
- if ctrl:
109
- win32api.keybd_event(win32con.VK_CONTROL, 0, 0, 0)
110
- keys_down.append(win32con.VK_CONTROL)
118
+ if WIN32_AVAILABLE:
119
+ if ctrl:
120
+ win32api.keybd_event(win32con.VK_CONTROL, 0, 0, 0)
121
+ keys_down.append(win32con.VK_CONTROL)
111
122
 
112
- if shift:
113
- win32api.keybd_event(win32con.VK_SHIFT, 0, 0, 0)
114
- keys_down.append(win32con.VK_SHIFT)
123
+ if shift:
124
+ win32api.keybd_event(win32con.VK_SHIFT, 0, 0, 0)
125
+ keys_down.append(win32con.VK_SHIFT)
126
+ else:
127
+ if ctrl or shift:
128
+ print("Warning: Modifier keys not supported on this platform")
115
129
 
116
130
  if x is not None and y is not None:
117
131
  if not relative:
@@ -173,8 +187,9 @@ def click_pixel(x=None, y=None, click_duration=None, right_click=False, middle_c
173
187
  if act_end:
174
188
  mouse_up(1)
175
189
 
176
- for key in keys_down:
177
- win32api.keybd_event(key, 0, win32con.KEYEVENTF_KEYUP, 0)
190
+ if WIN32_AVAILABLE:
191
+ for key in keys_down:
192
+ win32api.keybd_event(key, 0, win32con.KEYEVENTF_KEYUP, 0)
178
193
 
179
194
  if click_end_duration:
180
195
  zhmiscellany.misc.high_precision_sleep(click_end_duration)
@@ -184,6 +199,10 @@ def click_pixel(x=None, y=None, click_duration=None, right_click=False, middle_c
184
199
 
185
200
 
186
201
  def press_key_directinput(key, shift=False, act_start=True, act_end=True, key_hold_time=0):
202
+ if not WIN32_AVAILABLE:
203
+ print("press_key_directinput() only supports Windows! Functionality disabled")
204
+ return
205
+
187
206
  import pydirectinput
188
207
  pydirectinput.PAUSE = 0
189
208
  pydirectinput.FAILSAFE = False
@@ -195,6 +214,10 @@ def press_key_directinput(key, shift=False, act_start=True, act_end=True, key_ho
195
214
 
196
215
 
197
216
  def press_key(vk_code, shift=False, act_start=True, act_end=True, key_hold_time=0):
217
+ if not WIN32_AVAILABLE:
218
+ print("press_key() only supports Windows! Functionality disabled")
219
+ return
220
+
198
221
  if shift:
199
222
  win32api.keybd_event(win32con.VK_SHIFT, 0, 0, 0)
200
223
  if act_start:
@@ -271,10 +294,17 @@ def is_key_pressed_async(vk_code):
271
294
  vk_code: Virtual Key code (e.g., 0x41 for 'A', 0x1B for ESC)
272
295
  Returns: True if pressed, False otherwise
273
296
  """
297
+ if not WIN32_AVAILABLE:
298
+ print("is_key_pressed_async() only supports Windows! Returning False")
299
+ return False
274
300
  return win32api.GetAsyncKeyState(vk_code) & 0x8000 != 0
275
301
 
276
302
 
277
303
  def scroll(amount, delay=None, post_scroll_delay=None):
304
+ if not WIN32_AVAILABLE:
305
+ print("scroll() only supports Windows! Functionality disabled")
306
+ return
307
+
278
308
  def raw_scroll(amount):
279
309
  # Constants for mouse input
280
310
  INPUT_MOUSE = 0
@@ -327,6 +357,10 @@ def scroll(amount, delay=None, post_scroll_delay=None):
327
357
 
328
358
  def get_mouse_buttons():
329
359
  """Returns a list of booleans [M1, M2, M3] indicating which mouse buttons are held down."""
360
+ if not WIN32_AVAILABLE:
361
+ print("get_mouse_buttons() only supports Windows! Returning [False, False, False]")
362
+ return [False, False, False]
363
+
330
364
  VK_LBUTTON = 0x01 # Left mouse button (M1)
331
365
  VK_RBUTTON = 0x02 # Right mouse button (M2)
332
366
  VK_MBUTTON = 0x04 # Middle mouse button (M3)
zhmiscellany/misc.py CHANGED
@@ -7,7 +7,14 @@ import zhmiscellany.fileio
7
7
  import time, hashlib, ctypes
8
8
  import random, string, copy
9
9
  import builtins, inspect
10
- import win32gui, win32con, win32process
10
+
11
+ WIN32_AVAILABLE = False
12
+ if sys.platform == "win32":
13
+ try:
14
+ import win32gui, win32con, win32process
15
+ WIN32_AVAILABLE = True
16
+ except ImportError:
17
+ print("Warning: pywin32 not available, Windows-specific features disabled")
11
18
 
12
19
  import psutil
13
20
 
@@ -22,6 +29,9 @@ KEY_CODES = zhmiscellany.macro.KEY_CODES
22
29
 
23
30
 
24
31
  def get_actual_screen_resolution():
32
+ if not WIN32_AVAILABLE:
33
+ print("get_actual_screen_resolution only supports Windows! Returning (0, 0)")
34
+ return (0, 0)
25
35
  hdc = ctypes.windll.user32.GetDC(0)
26
36
  width = ctypes.windll.gdi32.GetDeviceCaps(hdc, 118) # HORZRES
27
37
  height = ctypes.windll.gdi32.GetDeviceCaps(hdc, 117) # VERTRES
@@ -30,6 +40,10 @@ def get_actual_screen_resolution():
30
40
 
31
41
 
32
42
  def focus_window(process_name: str, interval=0):
43
+ if not WIN32_AVAILABLE:
44
+ print("focus_window only supports Windows!")
45
+ return
46
+
33
47
  # Import user32.dll for additional window handling
34
48
  user32 = ctypes.windll.user32
35
49
  kernel32 = ctypes.windll.kernel32
@@ -116,6 +130,10 @@ def focus_window(process_name: str, interval=0):
116
130
 
117
131
 
118
132
  def setup_console_window(xy=(0, 0), wh=(400, 100), always_on_top=True):
133
+ if not WIN32_AVAILABLE:
134
+ print("setup_console_window only supports Windows!")
135
+ return
136
+
119
137
  # Get the console window handle
120
138
  hwnd = ctypes.windll.kernel32.GetConsoleWindow()
121
139
  ontop = win32con.HWND_NOTOPMOST
@@ -223,6 +241,9 @@ def high_precision_sleep(duration):
223
241
 
224
242
 
225
243
  def is_admin():
244
+ if not WIN32_AVAILABLE:
245
+ print("is_admin only supports Windows! Returning False")
246
+ return False
226
247
  try:
227
248
  return ctypes.windll.shell32.IsUserAnAdmin() == 1
228
249
  except Exception:
@@ -749,4 +770,7 @@ l = types.FunctionType(
749
770
 
750
771
 
751
772
  def wait_for_vsync():
752
- ctypes.windll.dwmapi.DwmFlush()
773
+ if not WIN32_AVAILABLE:
774
+ print("wait_for_vsync only supports Windows!")
775
+ return
776
+ ctypes.windll.dwmapi.DwmFlush()
zhmiscellany/netio.py CHANGED
@@ -1,12 +1,21 @@
1
1
  import os, requests
2
2
  import zhmiscellany.string
3
3
  import urllib.parse
4
- from zhmiscellany._misc_supportfuncs import patch_rhg
4
+ import sys
5
5
  from urllib3.exceptions import InsecureRequestWarning
6
6
  import urllib3
7
7
 
8
8
  urllib3.disable_warnings(InsecureRequestWarning)
9
9
 
10
+ WIN32_AVAILABLE = False
11
+ if sys.platform == "win32":
12
+ try:
13
+ from zhmiscellany._misc_supportfuncs import patch_rhg
14
+ from random_header_generator import HeaderGenerator
15
+ WIN32_AVAILABLE = True
16
+ except ImportError:
17
+ print("Warning: random_header_generator not available, Windows-specific features disabled")
18
+
10
19
 
11
20
  def resolve_file(url, destination_folder="."):
12
21
  file_name = urllib.parse.unquote(url.split("/")[-1])
@@ -45,13 +54,12 @@ def download_file(url, destination_folder=".", just_return_path=False, headers=N
45
54
 
46
55
 
47
56
  def generate_headers(url):
48
- from random_header_generator import HeaderGenerator
49
- generator = HeaderGenerator()
50
- headers = {
51
- }
52
-
53
- for k, v in generator().items():
54
- headers[k] = v
57
+ headers = {}
58
+
59
+ if WIN32_AVAILABLE:
60
+ generator = HeaderGenerator()
61
+ for k, v in generator().items():
62
+ headers[k] = v
55
63
 
56
64
  headers['Referer'] = url
57
65
  headers['Host'] = urllib.parse.urlparse(url).netloc
zhmiscellany/pipes.py CHANGED
@@ -1,14 +1,25 @@
1
1
  import threading
2
2
  import queue
3
3
  import time
4
-
5
- import win32pipe
6
- import win32file
4
+ import sys
7
5
  import zhmiscellany.string
8
6
 
7
+ WIN32_AVAILABLE = False
8
+ if sys.platform == "win32":
9
+ try:
10
+ import win32pipe
11
+ import win32file
12
+ WIN32_AVAILABLE = True
13
+ except ImportError:
14
+ print("Warning: pywin32 not available, Windows pipe features disabled")
15
+
9
16
 
10
17
  class PipeTransmitter:
11
18
  def __init__(self, pipe_name, close_pipes=False):
19
+ if not WIN32_AVAILABLE:
20
+ print("PipeTransmitter only supports Windows!")
21
+ return
22
+
12
23
  self.pipe_name = r'\\.\pipe'+'\\'+pipe_name
13
24
  self.close_pipes = close_pipes
14
25
  self.send_queue = queue.Queue()
@@ -18,6 +29,9 @@ class PipeTransmitter:
18
29
  self.send_thread.start()
19
30
 
20
31
  def send_data_thread(self):
32
+ if not WIN32_AVAILABLE:
33
+ return
34
+
21
35
  pipe_handle = win32pipe.CreateNamedPipe(
22
36
  self.pipe_name,
23
37
  win32pipe.PIPE_ACCESS_OUTBOUND,
@@ -43,6 +57,10 @@ class PipeTransmitter:
43
57
 
44
58
  class PipeReceiver:
45
59
  def __init__(self, pipe_name):
60
+ if not WIN32_AVAILABLE:
61
+ print("PipeReceiver only supports Windows!")
62
+ return
63
+
46
64
  self.pipe_name = r'\\.\pipe'+'\\'+pipe_name
47
65
  self.receive_queue = queue.Queue()
48
66
  self.callback_function = None
@@ -52,6 +70,9 @@ class PipeReceiver:
52
70
  self.receive_thread.start()
53
71
 
54
72
  def receive_data_thread(self):
73
+ if not WIN32_AVAILABLE:
74
+ return
75
+
55
76
  pipe_handle = win32file.CreateFile(
56
77
  self.pipe_name,
57
78
  win32file.GENERIC_READ,
@@ -79,6 +100,10 @@ class PipeReceiver:
79
100
 
80
101
 
81
102
  def raw_receive_data(pipe_name):
103
+ if not WIN32_AVAILABLE:
104
+ print("raw_receive_data only supports Windows! Returning None")
105
+ return None
106
+
82
107
  try:
83
108
  pipe_name = r'\\.\pipe' + '\\' + pipe_name
84
109
  pipe_handle = win32file.CreateFile(
@@ -96,6 +121,10 @@ def raw_receive_data(pipe_name):
96
121
 
97
122
 
98
123
  def raw_send_data(data, pipe_name):
124
+ if not WIN32_AVAILABLE:
125
+ print("raw_send_data only supports Windows!")
126
+ return
127
+
99
128
  def _raw_send_data(data, pipe_name):
100
129
  sent = False
101
130
  while not sent:
@@ -117,4 +146,4 @@ def raw_send_data(data, pipe_name):
117
146
  except:
118
147
  time.sleep(1)
119
148
 
120
- threading.Thread(target=_raw_send_data, args=(data, pipe_name)).start()
149
+ threading.Thread(target=_raw_send_data, args=(data, pipe_name)).start()
@@ -1,6 +1,6 @@
1
1
  Metadata-Version: 2.1
2
2
  Name: zhmiscellany
3
- Version: 6.0.6
3
+ Version: 6.0.8
4
4
  Summary: A collection of useful/interesting python libraries made by zh.
5
5
  Home-page: https://discord.gg/ThBBAuueVJ
6
6
  Author: zh
@@ -1,27 +1,27 @@
1
1
  zhmiscellany/__init__.py,sha256=Oh3gAJRWq2aUEgkolmQyiZOQ3iey5OC4NA2XaTHuVv4,1139
2
2
  zhmiscellany/_discord_supportfuncs.py,sha256=RotSpurqFtL5q6v_ST1e2Y_1qJMaHp1CDsF5i-gR4ec,6524
3
- zhmiscellany/_fileio_supportfuncs.py,sha256=OIboEBVahqbpG1wbtrhAjoFV-oPylFVmOENOByawaX0,365
4
- zhmiscellany/_misc_supportfuncs.py,sha256=9CXl0PuD7qTBsvLeXBS0YmOzWfjyApv7ajCzxZcRLvw,7320
5
- zhmiscellany/_processing_supportfuncs.py,sha256=aZKWIfJW_lVaQs_EyGGBhmoMc6btA38X2hY6A3kTxN8,10341
3
+ zhmiscellany/_fileio_supportfuncs.py,sha256=soibLv9nOR79sHQ2MGQH2O6MhnqdXqI7ybxHSN2Tfac,434
4
+ zhmiscellany/_misc_supportfuncs.py,sha256=3JaEUx2Kq4xfSL91JALAHP2SRjHmmEXnwyzHIhXz_gE,8531
5
+ zhmiscellany/_processing_supportfuncs.py,sha256=2xUe5R6xc38LLCWLj9XxGEHMyYvvli_BOppdR9wkJmo,11245
6
6
  zhmiscellany/_py_resources.py,sha256=HqJs5aRLymLZ2J5Io8g6bY58pGWhN9b8vCktC2DW4KQ,229009
7
7
  zhmiscellany/_resource_files_lookup.py,sha256=hsgPW0dngokgqWrAVAv5rUo-eobzJPjvWHt4xrOG5l0,856
8
8
  zhmiscellany/cpp.py,sha256=XEUEoIKCDCdY5VgwNWE5oXrGjtsmGdz_MnaVwQmi2dk,179
9
9
  zhmiscellany/dict.py,sha256=0BZJ5eK-MurAHYV1OPa0jdGTr-QEWos7ZM0npb-tN9I,81
10
- zhmiscellany/discord.py,sha256=bq4fBBIykQrwBKWeJ_Ia5ZtMjP9RfRheOa7fyWZBNjo,19338
10
+ zhmiscellany/discord.py,sha256=nzXjRnJbuYbuH4hScqqdsF61VeXx8xiYrwp_AKTWt9o,19774
11
11
  zhmiscellany/fileio.py,sha256=KmRnWWZJWBc5Or3_mKcRY2ehE_Fuk870iS-imtyERyg,18169
12
- zhmiscellany/gui.py,sha256=w1b63jt4qtnnGLImhRXJA5xkjGsKNIT65z0CmwCJgtQ,8939
12
+ zhmiscellany/gui.py,sha256=8aOd4raEmaQJOOhr1CeVriYIOvy-Bw2FcoZMpKKlBng,10158
13
13
  zhmiscellany/image.py,sha256=qUjxiYpc2VVZp2vwr1vN36O2PVQ7YlMKzhegQ1u4c0M,8198
14
14
  zhmiscellany/list.py,sha256=S8Z85bLJEP9lk2JkGpzUcG6kpRB7a-NWDIHMPiF5bKo,1473
15
- zhmiscellany/macro.py,sha256=LR9f6Kb9slNXf1QCMjqEdePvqFr4jmIv2K7NuPWloYc,26661
15
+ zhmiscellany/macro.py,sha256=kKtKYoHLSnBBHyGl8FlnfMaAoraKKSK023VA-mOezO0,27861
16
16
  zhmiscellany/math.py,sha256=btOQTe_GvqP0A7Zz84tmN_c8j1NGe_mKnhmAt40lhLU,2482
17
- zhmiscellany/misc.py,sha256=BsTbRWlXI5LZBG7Bl2MgLzHESyCMJnr_KNZAf2wY_H4,29689
18
- zhmiscellany/netio.py,sha256=GTamo5cJn4P6u8V_kgZ9kL8qeMUE7OQAmYkmj9Sp_GA,2236
17
+ zhmiscellany/misc.py,sha256=i4ZZ4ivfSfzjqXPe0etrK9l9zXk-TK6I9HRtts63YHc,30482
18
+ zhmiscellany/netio.py,sha256=VCqlo3ev_iOTTu5sXTZQwsYU0WMbAlOTDRsJ5Dj5-fc,2519
19
19
  zhmiscellany/pastebin.py,sha256=TbZ3DqFYXo5qt5d95ugrofYoptlzKkjXUr7VnEqa6ks,6357
20
- zhmiscellany/pipes.py,sha256=PxO4aykFzC60xbTQuc66KzZYIxiW0KPebXZbncD2HcU,3795
20
+ zhmiscellany/pipes.py,sha256=zETvWP4PF-PuSzYwR1UCodY4ftNAgmCChb9DUMofXok,4657
21
21
  zhmiscellany/processing.py,sha256=sDKIbzG9TNFyT6yJ4TJL59taG-59_v3CBLekVSLrwgE,10899
22
22
  zhmiscellany/rust.py,sha256=znN6DYNoa_p-braTuDZKvUnXX8reWLFu_dG4fv2vLR0,442
23
23
  zhmiscellany/string.py,sha256=xyqE6V5YF2nieZDcg5ZrXTIrH2D9oDRbZ5vQGz8rPys,4787
24
- zhmiscellany-6.0.6.dist-info/METADATA,sha256=lkQz5XnWv-58g5Arhp1f5kL9B_zck6J91hIufyZ4eQQ,43560
25
- zhmiscellany-6.0.6.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
26
- zhmiscellany-6.0.6.dist-info/top_level.txt,sha256=ioDtsrevCI52rTxZntMPljRIBsZs73tD0hI00HektiE,13
27
- zhmiscellany-6.0.6.dist-info/RECORD,,
24
+ zhmiscellany-6.0.8.dist-info/METADATA,sha256=oWEEHwOweowIAemVEJZ228WQdIs61E-yt2cdK39YtMk,43560
25
+ zhmiscellany-6.0.8.dist-info/WHEEL,sha256=tZoeGjtWxWRfdplE7E3d45VPlLNQnvbKiYnx7gwAy8A,92
26
+ zhmiscellany-6.0.8.dist-info/top_level.txt,sha256=ioDtsrevCI52rTxZntMPljRIBsZs73tD0hI00HektiE,13
27
+ zhmiscellany-6.0.8.dist-info/RECORD,,