[go: up one dir, main page]

Menu

[4440c6]: / utils.py  Maximize  Restore  History

Download this file

102 lines (87 with data), 4.2 kB

  1
  2
  3
  4
  5
  6
  7
  8
  9
 10
 11
 12
 13
 14
 15
 16
 17
 18
 19
 20
 21
 22
 23
 24
 25
 26
 27
 28
 29
 30
 31
 32
 33
 34
 35
 36
 37
 38
 39
 40
 41
 42
 43
 44
 45
 46
 47
 48
 49
 50
 51
 52
 53
 54
 55
 56
 57
 58
 59
 60
 61
 62
 63
 64
 65
 66
 67
 68
 69
 70
 71
 72
 73
 74
 75
 76
 77
 78
 79
 80
 81
 82
 83
 84
 85
 86
 87
 88
 89
 90
 91
 92
 93
 94
 95
 96
 97
 98
 99
100
101
from pathlib import Path
import re
import locale
import threading
import time
import pyperclip
import screeninfo
def clamp(v: int, x: int, y: int) -> int:
return min(max(v, x), y)
def get_ip_from_addr_str(addr: str) -> str:
match = re.match(r'\[?([a-fA-F0-9:.]+)\]?:\d+$', addr)
if match:
return match.group(1)
else:
raise ValueError("Invalid IP address format")
def is_valid_ipv4_addr(ipv4_addr: str) -> bool:
pattern = r'^((25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)\.){3}(25[0-5]|2[0-4][0-9]|[01]?[0-9][0-9]?)(:[0-9]{1,5})$'
return re.match(pattern, ipv4_addr) is not None
def is_valid_ipv6_addr(ip_str):
# Regular expression for validating an IPv6 address
perlipv6regex = r'^\s*((([0-9A-Fa-f]{1,4}:){7}([0-9A-Fa-f]{1,4}|:))|' \
r'(([0-9A-Fa-f]{1,4}:){6}(:[0-9A-Fa-f]{1,4}|((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)' \
r'(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|' \
r'(([0-9A-Fa-f]{1,4}:){5}(((:[0-9A-Fa-f]{1,4}){1,2})|:((25[0-5]|2[0-4]\d|1\d\d|' \
r'[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3})|:))|' \
r'(([0-9A-Fa-f]{1,4}:){4}(((:[0-9A-Fa-f]{1,4}){1,3})|((:[0-9A-Fa-f]{1,4})?:' \
r'((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|' \
r'(([0-9A-Fa-f]{1,4}:){3}(((:[0-9A-Fa-f]{1,4}){1,4})|((:[0-9A-Fa-f]{1,4}){0,2}:' \
r'((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|' \
r'(([0-9A-Fa-f]{1,4}:){2}(((:[0-9A-Fa-f]{1,4}){1,5})|((:[0-9A-Fa-f]{1,4}){0,3}:' \
r'((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|' \
r'(([0-9A-Fa-f]{1,4}:){1}(((:[0-9A-Fa-f]{1,4}){1,6})|((:[0-9A-Fa-f]{1,4}){0,4}:' \
r'((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:))|' \
r'(:(((:[0-9A-Fa-f]{1,4}){1,7})|((:[0-9A-Fa-f]{1,4}){0,5}:' \
r'((25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)(\.(25[0-5]|2[0-4]\d|1\d\d|[1-9]?\d)){3}))|:)))\s*$'
# Compile the regex pattern
ipv6_regex = re.compile(perlipv6regex)
# Test the input string against the compiled regex pattern
return bool(ipv6_regex.match(ip_str))
def screen_size() -> tuple[int, int]:
monitor = screeninfo.get_monitors()[0]
return monitor.width, monitor.height
def script_abs_path(_file: str) -> Path:
return Path(_file).resolve().parent
def i18n_factory():
user_language = locale.getdefaultlocale()[0]
language_index = 0
if user_language in ["zh", "zh_CN", "zh_HK", "zh_MO", "zh_SG", "zh_TW"]:
language_index = 1
def i18n_instance(candidates: list):
if len(candidates) == 0:
raise Exception("Empty i18n candidates")
if language_index < len(candidates):
return candidates[language_index]
return candidates[0]
return i18n_instance
i18n = i18n_factory()
class Clipboard:
wait_time_second = 0.1
retry_times = 5
clipboard_lock = threading.Lock()
sync_clipboard = True
@staticmethod
def safe_paste() -> str | None:
with Clipboard.clipboard_lock:
for _ in range(Clipboard.retry_times):
try:
return pyperclip.paste()
except pyperclip.PyperclipWindowsException:
time.sleep(Clipboard.wait_time_second)
print("[Error] Failed to access clipboard after several attempts.")
return None
@staticmethod
def safe_copy(text: str):
with Clipboard.clipboard_lock:
for _ in range(Clipboard.retry_times):
try:
pyperclip.copy(text)
return
except pyperclip.PyperclipWindowsException:
time.sleep(Clipboard.wait_time_second)
print("[Error] Failed to copy to clipboard after several attempts.")
class StopException(Exception):
"""If an event listener callback raises this exception, the current
listener is stopped.
"""
pass