gomyck-tools 1.3.7__py3-none-any.whl → 1.3.9__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.
- ctools/ai/env_config.py +2 -0
- ctools/ai/llm_chat.py +27 -26
- ctools/ai/llm_client.py +87 -66
- ctools/ai/llm_exception.py +17 -0
- ctools/ai/mcp/mcp_client.py +5 -1
- ctools/ai/tools/quick_tools.py +99 -0
- ctools/ai/tools/xml_extract.py +0 -1
- ctools/application.py +46 -44
- ctools/auto/__init__.py +4 -0
- ctools/{browser_element_tools.py → auto/browser_element.py} +3 -2
- ctools/{plan_area_tools.py → auto/plan_area.py} +3 -0
- ctools/{resource_bundle_tools.py → auto/resource_bundle.py} +3 -3
- ctools/{screenshot_tools.py → auto/screenshot.py} +3 -2
- ctools/{win_control.py → auto/win_control.py} +5 -2
- ctools/cid.py +18 -0
- ctools/cipher/__init__.py +4 -0
- ctools/{rsa.py → cipher/rsa.py} +2 -2
- ctools/database/__init__.py +4 -0
- ctools/{database.py → database/database.py} +4 -3
- ctools/geo/__init__.py +4 -0
- ctools/metrics.py +2 -2
- ctools/office/__init__.py +4 -0
- ctools/{word_fill.py → office/word_fill.py} +1 -1
- ctools/pools/__init__.py +4 -0
- ctools/similar.py +22 -0
- ctools/stream/__init__.py +4 -0
- ctools/{credis.py → stream/credis.py} +5 -4
- ctools/{mqtt_utils.py → stream/mqtt_utils.py} +13 -10
- ctools/sys_info.py +5 -4
- ctools/sys_log.py +32 -31
- ctools/util/__init__.py +4 -0
- ctools/{http_utils.py → util/http_util.py} +0 -1
- ctools/{snow_id.py → util/snow_id.py} +2 -2
- ctools/web/__init__.py +4 -0
- ctools/{aio_web_server.py → web/aio_web_server.py} +23 -4
- ctools/{bottle_web_base.py → web/bottle_web_base.py} +2 -2
- ctools/{download_tools.py → web/download_util.py} +3 -2
- ctools/web/params_util.py +42 -0
- ctools/{upload_tools.py → web/upload_util.py} +3 -2
- {gomyck_tools-1.3.7.dist-info → gomyck_tools-1.3.9.dist-info}/METADATA +1 -1
- gomyck_tools-1.3.9.dist-info/RECORD +82 -0
- ctools/bashPath.py +0 -13
- ctools/console.py +0 -55
- ctools/enums.py +0 -4
- ctools/excelOpt.py +0 -36
- ctools/imgDialog.py +0 -45
- ctools/obj.py +0 -20
- ctools/str_diff.py +0 -20
- ctools/string_tools.py +0 -85
- gomyck_tools-1.3.7.dist-info/RECORD +0 -76
- /ctools/{pacth.py → auto/pacth.py} +0 -0
- /ctools/{pty_tools.py → auto/pty_process.py} +0 -0
- /ctools/{win_canvas.py → auto/win_canvas.py} +0 -0
- /ctools/{date_utils.py → cdate.py} +0 -0
- /ctools/{aes_tools.py → cipher/aes_util.py} +0 -0
- /ctools/{b64.py → cipher/b64.py} +0 -0
- /ctools/{czip.py → cipher/czip.py} +0 -0
- /ctools/{sign.py → cipher/sign.py} +0 -0
- /ctools/{sm_tools.py → cipher/sm_util.py} +0 -0
- /ctools/{coord_trans.py → geo/coord_trans.py} +0 -0
- /ctools/{douglas_rarefy.py → geo/douglas_rarefy.py} +0 -0
- /ctools/{cword.py → office/cword.py} +0 -0
- /ctools/{word_fill_entity.py → office/word_fill_entity.py} +0 -0
- /ctools/{work_path.py → path_info.py} +0 -0
- /ctools/{process_pool.py → pools/process_pool.py} +0 -0
- /ctools/{thread_pool.py → pools/thread_pool.py} +0 -0
- /ctools/{ckafka.py → stream/ckafka.py} +0 -0
- /ctools/{cftp.py → util/cftp.py} +0 -0
- /ctools/{compile_tools.py → util/compile_util.py} +0 -0
- /ctools/{html_soup.py → util/html_soup.py} +0 -0
- /ctools/{images_tools.py → util/image_process.py} +0 -0
- /ctools/{api_result.py → web/api_result.py} +0 -0
- /ctools/{bottle_webserver.py → web/bottle_webserver.py} +0 -0
- /ctools/{bottle_websocket.py → web/bottle_websocket.py} +0 -0
- /ctools/{ctoken.py → web/ctoken.py} +0 -0
- {gomyck_tools-1.3.7.dist-info → gomyck_tools-1.3.9.dist-info}/WHEEL +0 -0
- {gomyck_tools-1.3.7.dist-info → gomyck_tools-1.3.9.dist-info}/licenses/LICENSE +0 -0
- {gomyck_tools-1.3.7.dist-info → gomyck_tools-1.3.9.dist-info}/top_level.txt +0 -0
ctools/application.py
CHANGED
@@ -8,7 +8,9 @@ from configparser import ConfigParser
|
|
8
8
|
|
9
9
|
from PIL import Image
|
10
10
|
|
11
|
-
from ctools import
|
11
|
+
from ctools import path_info, call
|
12
|
+
from ctools.cipher import sign
|
13
|
+
from ctools.pools import thread_pool
|
12
14
|
from ctools.sys_info import get_os_architecture, get_os_architecture4x
|
13
15
|
|
14
16
|
"""
|
@@ -23,9 +25,9 @@ class Server:
|
|
23
25
|
metricsPort = 8011 # 获取指标信息端口
|
24
26
|
wsPort = 8012 # websocket服务端口
|
25
27
|
startTime = time.time() # 系统启动时间
|
26
|
-
baseWorkPath =
|
28
|
+
baseWorkPath = path_info.get_user_path_info('rpa') # 基础的工作目录
|
27
29
|
sysLogPath = os.path.join(baseWorkPath, ".logs") # 系统日志存储目录
|
28
|
-
pythonHome = os.path.join(
|
30
|
+
pythonHome = os.path.join(path_info.get_Users_path(), 'Public/python-3.8.9') # python根目录
|
29
31
|
indicatorsPath = os.path.join(baseWorkPath, "indicators") # 指标信息存储目录
|
30
32
|
screenshotPath = os.path.join(baseWorkPath, "screenshot") # 截图存储目录
|
31
33
|
controlServerAddr = None
|
@@ -37,9 +39,9 @@ class Authorization:
|
|
37
39
|
|
38
40
|
|
39
41
|
class Database:
|
40
|
-
url_biz = os.path.join(
|
41
|
-
url_func = os.path.join(
|
42
|
-
url_auth = os.path.join(
|
42
|
+
url_biz = os.path.join(path_info.get_user_path_info(), "AppData/Local/SystemWin32Core", 'systemRDB') # 数据库文件地址
|
43
|
+
url_func = os.path.join(path_info.get_user_path_info(), "AppData/Local/SystemWin32Core", 'explorerSearch') # 函数库地址
|
44
|
+
url_auth = os.path.join(path_info.get_user_path_info(), "AppData/Local/SystemWin32Core", 'tmp') # 授权库地址
|
43
45
|
pool_size = 5
|
44
46
|
max_overflow = 25
|
45
47
|
|
@@ -52,14 +54,14 @@ class Upload:
|
|
52
54
|
|
53
55
|
|
54
56
|
class Schedule:
|
55
|
-
rpa_script_path = os.path.join(
|
57
|
+
rpa_script_path = os.path.join(path_info.get_user_path_info(), ".cache/.tmp") # 执行流程存储目录
|
56
58
|
template_output_path = os.path.join(Server.baseWorkPath, 'document') # 使用模板生成的文档存储目录
|
57
59
|
play_wright_slow_mo = 0 # play wright每一步执行延时时间, 单位毫秒
|
58
60
|
|
59
61
|
|
60
62
|
@call.once
|
61
63
|
def sync_config():
|
62
|
-
path = os.path.join(
|
64
|
+
path = os.path.join(path_info.get_app_path(), "application.ini")
|
63
65
|
conf = ConfigParser()
|
64
66
|
if os.path.exists(path):
|
65
67
|
conf.read(path)
|
@@ -69,7 +71,7 @@ def sync_config():
|
|
69
71
|
server_conf = conf['Server']
|
70
72
|
Server.version = server_conf['version']
|
71
73
|
Server.port = int(server_conf['port'])
|
72
|
-
Server.baseWorkPath =
|
74
|
+
Server.baseWorkPath = path_info.get_user_path_info(server_conf['baseWorkPath'])
|
73
75
|
Server.sysLogPath = os.path.join(Server.baseWorkPath, ".logs")
|
74
76
|
######### Server 必须放在第一个初始化的位置 ########
|
75
77
|
if "Database" in sections:
|
@@ -106,18 +108,18 @@ def sync_config():
|
|
106
108
|
|
107
109
|
|
108
110
|
def check_database():
|
109
|
-
db_file = os.path.join(
|
111
|
+
db_file = os.path.join(path_info.get_user_path_info(), "AppData/Local/SystemWin32Core", 'systemRDB')
|
110
112
|
if os.path.exists(db_file):
|
111
113
|
db_size = os.path.getsize(db_file)
|
112
114
|
if db_size < 2000 * 1024: os.remove(db_file)
|
113
|
-
db_file = os.path.join(
|
115
|
+
db_file = os.path.join(path_info.get_user_path_info(), "AppData/Local/SystemWin32Core", 'tmp')
|
114
116
|
if os.path.exists(db_file):
|
115
117
|
db_size = os.path.getsize(db_file)
|
116
118
|
if db_size < 2000 * 1024: os.remove(db_file)
|
117
119
|
|
118
120
|
def validate_sign():
|
119
|
-
sign_app_val = sign.generate_signature(
|
120
|
-
with open(
|
121
|
+
sign_app_val = sign.generate_signature(path_info.get_install_path('rpa-server.exe'))
|
122
|
+
with open(path_info.get_install_path('rpa-server.sign')) as sign_file:
|
121
123
|
sign_file_val = sign_file.readline()
|
122
124
|
if 'rpa-dev-sign' == sign_file_val.strip(): return
|
123
125
|
if sign_app_val != sign_file_val: raise Exception('程序签名验证失败!!!')
|
@@ -126,9 +128,9 @@ def validate_sign():
|
|
126
128
|
def path_config():
|
127
129
|
print('start config path')
|
128
130
|
driverPath = Upload.driver_path
|
129
|
-
pythonPath = os.path.join(
|
130
|
-
hplPath = os.path.join(
|
131
|
-
taguiPath = os.path.join(
|
131
|
+
pythonPath = os.path.join(path_info.get_Users_path(), 'Public/python-3.8.9')
|
132
|
+
hplPath = os.path.join(path_info.get_user_path_info(), 'AppData/Local/ms-playwright')
|
133
|
+
taguiPath = os.path.join(path_info.get_user_path_info(), 'AppData/Roaming/tagui')
|
132
134
|
os.environ['PATH'] = os.pathsep.join([pythonPath, os.path.join(pythonPath, 'Scripts'), driverPath, os.path.join(hplPath, 'chromium-920619\chrome-win'), taguiPath, os.environ['PATH']])
|
133
135
|
print('end config path')
|
134
136
|
|
@@ -136,9 +138,9 @@ def path_config():
|
|
136
138
|
def sync_version(callFunc):
|
137
139
|
destFilePath = os.path.join(Server.baseWorkPath, "version")
|
138
140
|
driverPath = Upload.driver_path
|
139
|
-
pythonPath = os.path.join(
|
140
|
-
msPlayPath = os.path.join(
|
141
|
-
taguiPath = os.path.join(
|
141
|
+
pythonPath = os.path.join(path_info.get_Users_path(), 'Public/python-3.8.9')
|
142
|
+
msPlayPath = os.path.join(path_info.get_user_path_info(), 'AppData/Local/ms-playwright')
|
143
|
+
taguiPath = os.path.join(path_info.get_user_path_info(), 'AppData/Roaming/tagui')
|
142
144
|
if not os.path.exists(destFilePath):
|
143
145
|
try:
|
144
146
|
shutil.rmtree(pythonPath)
|
@@ -156,7 +158,7 @@ def sync_version(callFunc):
|
|
156
158
|
shutil.rmtree(taguiPath)
|
157
159
|
except Exception:
|
158
160
|
pass
|
159
|
-
from ctools.pacth import Patch
|
161
|
+
from ctools.auto.pacth import Patch
|
160
162
|
patch = Patch(oldVersion='V1.0.0', newVersion=Server.version, pythonPath=pythonPath, playwrightPath=msPlayPath, driverPath=driverPath)
|
161
163
|
patch.apply_patch()
|
162
164
|
if callFunc: callFunc()
|
@@ -171,7 +173,7 @@ def sync_version(callFunc):
|
|
171
173
|
oldVersion.close()
|
172
174
|
if oldV == Server.version and '-snapshot' not in oldV: return
|
173
175
|
print('开始升级本地程序..')
|
174
|
-
from ctools.pacth import Patch
|
176
|
+
from ctools.auto.pacth import Patch
|
175
177
|
patch = Patch(oldVersion=oldV, newVersion=Server.version, pythonPath=pythonPath, playwrightPath=msPlayPath, driverPath=driverPath)
|
176
178
|
patch.apply_patch()
|
177
179
|
if callFunc: callFunc()
|
@@ -183,8 +185,8 @@ def sync_version(callFunc):
|
|
183
185
|
|
184
186
|
def sync_database():
|
185
187
|
for db in [['simpleYWI', 'systemRDB', False], ['simpleHSI', 'explorerSearch', True], ['simpleSQI', 'tmp', False]]:
|
186
|
-
dbPath = os.path.join(
|
187
|
-
destDBPath = os.path.join(
|
188
|
+
dbPath = os.path.join(path_info.get_app_path(), "extension", db[0])
|
189
|
+
destDBPath = os.path.join(path_info.get_user_path_info(), "AppData/Local/SystemWin32Core")
|
188
190
|
os.makedirs(destDBPath, exist_ok=True)
|
189
191
|
destFilePath = os.path.join(destDBPath, db[1])
|
190
192
|
try:
|
@@ -199,9 +201,9 @@ def sync_database():
|
|
199
201
|
|
200
202
|
def sync_python_env():
|
201
203
|
print('SDK 开始安装...')
|
202
|
-
sourcePath = os.path.join(
|
203
|
-
destPLPath = os.path.join(
|
204
|
-
unzipPLPath = os.path.join(
|
204
|
+
sourcePath = os.path.join(path_info.get_install_path(), "sources", 'python-3.8.9-{}.zip'.format(get_os_architecture()))
|
205
|
+
destPLPath = os.path.join(path_info.get_Users_path(), 'Public/python-3.8.9')
|
206
|
+
unzipPLPath = os.path.join(path_info.get_Users_path(), 'Public')
|
205
207
|
if not os.path.exists(destPLPath):
|
206
208
|
with zipfile.ZipFile(sourcePath, 'r') as zip_ref:
|
207
209
|
zip_ref.extractall(unzipPLPath)
|
@@ -220,7 +222,7 @@ def sync_python_module():
|
|
220
222
|
m_path = os.path.join(Upload.module_path, file_name)
|
221
223
|
module_list.append(m_path)
|
222
224
|
|
223
|
-
upgrade_module_path = os.path.join(
|
225
|
+
upgrade_module_path = os.path.join(path_info.get_install_path(), "sources/UpgradeModule")
|
224
226
|
init_flag = os.path.join(upgrade_module_path, "init")
|
225
227
|
upgrade_module_path = os.path.join(upgrade_module_path, get_os_architecture4x())
|
226
228
|
if not os.path.exists(init_flag) and os.path.exists(upgrade_module_path):
|
@@ -267,12 +269,12 @@ def sync_python_module():
|
|
267
269
|
|
268
270
|
|
269
271
|
def sync_python_interpreter():
|
270
|
-
destPLPath = os.path.join(
|
271
|
-
enhancePath = os.path.join(
|
272
|
-
originPath = os.path.join(
|
273
|
-
initFlag = os.path.join(
|
272
|
+
destPLPath = os.path.join(path_info.get_Users_path(), 'Public/python-3.8.9')
|
273
|
+
enhancePath = os.path.join(path_info.get_Users_path(), "Public/enhance", 'enhance-{}.zip'.format(get_os_architecture()))
|
274
|
+
originPath = os.path.join(path_info.get_Users_path(), "Public/enhance", 'origin-{}.zip'.format(get_os_architecture()))
|
275
|
+
initFlag = os.path.join(path_info.get_Users_path(), "Public/enhance", 'init')
|
274
276
|
flagValue = 'can not find dest dir'
|
275
|
-
os.makedirs(os.path.join(
|
277
|
+
os.makedirs(os.path.join(path_info.get_Users_path(), "Public/enhance"), exist_ok=True)
|
276
278
|
if not os.path.exists(initFlag):
|
277
279
|
try:
|
278
280
|
if os.path.exists(enhancePath):
|
@@ -300,7 +302,7 @@ def sync_python_interpreter():
|
|
300
302
|
|
301
303
|
def sync_driver():
|
302
304
|
print('DRIVER 开始安装...')
|
303
|
-
sourcePath = os.path.join(
|
305
|
+
sourcePath = os.path.join(path_info.get_install_path(), "sources", 'uploadDriver.zip')
|
304
306
|
destPLPath = Upload.driver_path
|
305
307
|
unzipPLPath = Upload.driver_path
|
306
308
|
if not os.path.exists(os.path.join(destPLPath)):
|
@@ -315,9 +317,9 @@ def sync_driver():
|
|
315
317
|
|
316
318
|
def sync_tagui():
|
317
319
|
print('HTG ENGINE 开始安装...')
|
318
|
-
plPath = os.path.join(
|
319
|
-
destPLPath = os.path.join(
|
320
|
-
unzipPLPath = os.path.join(
|
320
|
+
plPath = os.path.join(path_info.get_install_path(), "sources", 'htg-source.zip')
|
321
|
+
destPLPath = os.path.join(path_info.get_user_path_info(), 'AppData/Roaming/tagui')
|
322
|
+
unzipPLPath = os.path.join(path_info.get_user_path_info(), 'AppData/Roaming/')
|
321
323
|
if not os.path.exists(os.path.join(destPLPath)):
|
322
324
|
with zipfile.ZipFile(plPath, 'r') as zip_ref:
|
323
325
|
zip_ref.extractall(unzipPLPath)
|
@@ -328,9 +330,9 @@ def sync_tagui():
|
|
328
330
|
|
329
331
|
def sync_playwright():
|
330
332
|
print('HPL ENGINE 开始安装...')
|
331
|
-
plPath = os.path.join(
|
332
|
-
destPLPath = os.path.join(
|
333
|
-
unzipPLPath = os.path.join(
|
333
|
+
plPath = os.path.join(path_info.get_install_path(), "sources", 'ms-playwright.zip')
|
334
|
+
destPLPath = os.path.join(path_info.get_user_path_info(), 'AppData/Local/ms-playwright')
|
335
|
+
unzipPLPath = os.path.join(path_info.get_user_path_info(), 'AppData/Local/')
|
334
336
|
if not os.path.exists(os.path.join(destPLPath)):
|
335
337
|
with zipfile.ZipFile(plPath, 'r') as zip_ref:
|
336
338
|
zip_ref.extractall(unzipPLPath)
|
@@ -339,8 +341,8 @@ def sync_playwright():
|
|
339
341
|
print('HPL ENGINE 依赖安装成功(1)')
|
340
342
|
|
341
343
|
def sync_paddleocr_model():
|
342
|
-
model_path = os.path.join(
|
343
|
-
paddleocr_path =
|
344
|
+
model_path = os.path.join(path_info.get_install_path(), "sources", 'paddleocr-model.zip')
|
345
|
+
paddleocr_path = path_info.get_user_path_info(".paddleocr")
|
344
346
|
if not os.path.exists(paddleocr_path) and os.path.exists(model_path) and get_os_architecture() == "64":
|
345
347
|
print('安装paddleocr模型文件开始')
|
346
348
|
with zipfile.ZipFile(model_path, 'r') as zip_ref:
|
@@ -349,13 +351,13 @@ def sync_paddleocr_model():
|
|
349
351
|
|
350
352
|
|
351
353
|
def clean_temp_dir(target_file='rpa_ident'):
|
352
|
-
root_folder =
|
354
|
+
root_folder = path_info.get_user_temp_path()
|
353
355
|
print("Start clear cache...")
|
354
356
|
for folder_name in os.listdir(root_folder):
|
355
357
|
folder_path = os.path.join(root_folder, folder_name)
|
356
358
|
if os.path.isdir(folder_path):
|
357
359
|
file_path = os.path.join(folder_path, target_file)
|
358
|
-
if os.path.exists(file_path) and os.path.normpath(folder_path) != os.path.normpath(
|
360
|
+
if os.path.exists(file_path) and os.path.normpath(folder_path) != os.path.normpath(path_info.get_app_path()):
|
359
361
|
try:
|
360
362
|
shutil.rmtree(folder_path)
|
361
363
|
except Exception:
|
@@ -376,7 +378,7 @@ def system_tray(app_server):
|
|
376
378
|
thread_pool.submit(app_server.stop)
|
377
379
|
app_icon.stop()
|
378
380
|
|
379
|
-
image = Image.open(os.path.join(
|
381
|
+
image = Image.open(os.path.join(path_info.get_app_path(), "images/ico.png"))
|
380
382
|
menu = (
|
381
383
|
pystray.MenuItem(text='退出', action=on_quit_clicked),
|
382
384
|
)
|
ctools/auto/__init__.py
ADDED
@@ -12,7 +12,8 @@ from selenium.webdriver.chrome.service import Service
|
|
12
12
|
from selenium.webdriver.common.by import By
|
13
13
|
from urllib3.exceptions import MaxRetryError
|
14
14
|
|
15
|
-
from ctools import application
|
15
|
+
from ctools import application
|
16
|
+
from ctools.util import cid
|
16
17
|
|
17
18
|
keyboard_listener = None
|
18
19
|
ctrl_pressed = None
|
@@ -116,7 +117,7 @@ def on_press(key):
|
|
116
117
|
if g_result:
|
117
118
|
try:
|
118
119
|
select_element = g_driver.find_element(By.XPATH, g_result[0])
|
119
|
-
picture_path = "%s.png" % os.path.join(application.Server.screenshotPath, "element-"+
|
120
|
+
picture_path = "%s.png" % os.path.join(application.Server.screenshotPath, "element-"+cid.get_uuid())
|
120
121
|
select_element.screenshot(picture_path)
|
121
122
|
except Exception:
|
122
123
|
pass
|
@@ -11,7 +11,7 @@ from Crypto.Hash import MD5
|
|
11
11
|
from Crypto.PublicKey import RSA
|
12
12
|
from Crypto.Signature import pkcs1_15
|
13
13
|
|
14
|
-
from ctools import sys_log,
|
14
|
+
from ctools import sys_log, application, path_info
|
15
15
|
|
16
16
|
log = sys_log.flog
|
17
17
|
|
@@ -39,7 +39,7 @@ def signature(manifest: dict):
|
|
39
39
|
:param manifest: 元数据字典
|
40
40
|
:return:
|
41
41
|
"""
|
42
|
-
with open(
|
42
|
+
with open(path_info.get_app_path() + '/keys/resource_private_key.pem', 'r') as pri:
|
43
43
|
private_key = RSA.import_key(pri.read())
|
44
44
|
digest = MD5.new(data_layout(manifest).encode('utf-8'))
|
45
45
|
return b64encode(pkcs1_15.new(private_key).sign(digest)).decode()
|
@@ -52,7 +52,7 @@ def sign_verify(manifest: dict, sign_val: str):
|
|
52
52
|
:param sign_val: 对比的签名值
|
53
53
|
:return:
|
54
54
|
"""
|
55
|
-
with open(
|
55
|
+
with open(path_info.get_app_path() + '/keys/resource_public_key.pem', 'r') as pub:
|
56
56
|
public_key = RSA.import_key(pub.read())
|
57
57
|
digest = MD5.new(data_layout(manifest).encode('utf-8'))
|
58
58
|
try:
|
@@ -4,7 +4,8 @@ import tkinter as tk
|
|
4
4
|
|
5
5
|
import pyautogui
|
6
6
|
|
7
|
-
from ctools import application
|
7
|
+
from ctools import application
|
8
|
+
from ctools import cid
|
8
9
|
|
9
10
|
"""
|
10
11
|
截屏工具类, 按回车截图
|
@@ -108,7 +109,7 @@ class ScreenshotTools:
|
|
108
109
|
time.sleep(0.3)
|
109
110
|
img = pyautogui.screenshot(region=[self.xstart, self.ystart, self.xend - self.xstart, self.yend - self.ystart])
|
110
111
|
self.screenshot_path = os.path.join(application.Server.screenshotPath,
|
111
|
-
"screenshot-%s.png" %
|
112
|
+
"screenshot-%s.png" % cid.get_snowflake_id())
|
112
113
|
img.save(self.screenshot_path)
|
113
114
|
except Exception:
|
114
115
|
pass
|
@@ -5,7 +5,10 @@ import pyautogui
|
|
5
5
|
import uiautomation as auto
|
6
6
|
from pynput import keyboard
|
7
7
|
|
8
|
-
from ctools import
|
8
|
+
from ctools import application
|
9
|
+
from ctools.auto import win_canvas
|
10
|
+
from ctools.pools import thread_pool
|
11
|
+
from ctools import cid
|
9
12
|
|
10
13
|
current_control = None
|
11
14
|
ctrl_pressed = False
|
@@ -55,7 +58,7 @@ def get_control_from_cursor():
|
|
55
58
|
|
56
59
|
img = pyautogui.screenshot(region=[control.BoundingRectangle.left, control.BoundingRectangle.top,
|
57
60
|
control.BoundingRectangle.width(), control.BoundingRectangle.height()])
|
58
|
-
screenshot_path = os.path.join(application.Server.screenshotPath, "screenshot-%s.png" %
|
61
|
+
screenshot_path = os.path.join(application.Server.screenshotPath, "screenshot-%s.png" % cid.get_snowflake_id())
|
59
62
|
img.save(screenshot_path)
|
60
63
|
# xx = auto.Control(**control_json)
|
61
64
|
# print(control_json)
|
ctools/cid.py
ADDED
@@ -0,0 +1,18 @@
|
|
1
|
+
from ctools.util.snow_id import SnowId
|
2
|
+
|
3
|
+
idWorker = SnowId(1, 2, 0)
|
4
|
+
|
5
|
+
def get_snowflake_id():
|
6
|
+
return idWorker.get_id()
|
7
|
+
|
8
|
+
def get_random_str(size: int = 10) -> str:
|
9
|
+
import random
|
10
|
+
return "".join(random.sample('abcdefghjklmnpqrstuvwxyz123456789', size))
|
11
|
+
|
12
|
+
def get_uuid() -> str:
|
13
|
+
import uuid
|
14
|
+
return str(uuid.uuid1()).replace("-", "")
|
15
|
+
|
16
|
+
|
17
|
+
|
18
|
+
|
ctools/{rsa.py → cipher/rsa.py}
RENAMED
@@ -5,7 +5,7 @@ from Crypto.Hash import SHA256
|
|
5
5
|
from Crypto.PublicKey import RSA
|
6
6
|
from Crypto.Signature import pkcs1_15
|
7
7
|
|
8
|
-
from ctools import
|
8
|
+
from ctools import cjson, path_info
|
9
9
|
|
10
10
|
ENCRYPT_CHUNK_SIZE = 245
|
11
11
|
decrypt_CHUNK_SIZE = 512
|
@@ -20,7 +20,7 @@ def generate_rsa_keypair(bits=2048):
|
|
20
20
|
f.write(public_key)
|
21
21
|
|
22
22
|
def loadLicenseInfo(auth_code):
|
23
|
-
with open(
|
23
|
+
with open(path_info.get_app_path() + '/keys/license.key', 'r') as pri:
|
24
24
|
decrypt_message = decrypt(auth_code.strip(), pri.read())
|
25
25
|
return cjson.loads(decrypt_message)
|
26
26
|
|
@@ -7,8 +7,9 @@ from sqlalchemy.ext.declarative import declarative_base
|
|
7
7
|
from sqlalchemy.orm import sessionmaker, Session
|
8
8
|
from sqlalchemy.sql import text
|
9
9
|
|
10
|
-
from ctools import call
|
11
|
-
from ctools.thread_pool import thread_local
|
10
|
+
from ctools import call
|
11
|
+
from ctools.pools.thread_pool import thread_local
|
12
|
+
from ctools import cid
|
12
13
|
|
13
14
|
"""
|
14
15
|
class XXXX(BaseMixin):
|
@@ -82,7 +83,7 @@ def _create_connection(db_url: str, pool_size: int=5, max_overflow: int=25, conn
|
|
82
83
|
return engine, sm
|
83
84
|
|
84
85
|
def generate_custom_id():
|
85
|
-
return str(
|
86
|
+
return str(cid.get_snowflake_id())
|
86
87
|
|
87
88
|
class BaseMixin(Base):
|
88
89
|
__abstract__ = True
|
ctools/geo/__init__.py
ADDED
ctools/metrics.py
CHANGED
@@ -4,7 +4,7 @@ from enum import Enum
|
|
4
4
|
|
5
5
|
from prometheus_client import Counter, Gauge, Summary, Histogram, start_http_server
|
6
6
|
|
7
|
-
from ctools import call, cjson, sys_log,
|
7
|
+
from ctools import call, cjson, sys_log, path_info
|
8
8
|
|
9
9
|
log = sys_log.flog
|
10
10
|
|
@@ -12,7 +12,7 @@ _metrics_port = 8889
|
|
12
12
|
_persistent_json = {}
|
13
13
|
_metrics_initial = {}
|
14
14
|
_lock = threading.Lock()
|
15
|
-
_metrics_persistent_path = os.path.join(
|
15
|
+
_metrics_persistent_path = os.path.join(path_info.get_user_work_path('metrics', True), 'persistent.json')
|
16
16
|
|
17
17
|
# 认证中间件
|
18
18
|
# @app.before_request
|
@@ -16,7 +16,7 @@ from xlsxtpl import writerx as xlsx_writerx
|
|
16
16
|
from xlutils.copy import copy
|
17
17
|
|
18
18
|
from ctools import cjson
|
19
|
-
from ctools.word_fill_entity import WordTable, WordCell, Style, Font, Alignment
|
19
|
+
from ctools.office.word_fill_entity import WordTable, WordCell, Style, Font, Alignment
|
20
20
|
|
21
21
|
EXCEL_WORD_ALIGNMENT = {"left": WD_TABLE_ALIGNMENT.LEFT,
|
22
22
|
"center": WD_TABLE_ALIGNMENT.CENTER,
|
ctools/pools/__init__.py
ADDED
ctools/similar.py
ADDED
@@ -0,0 +1,22 @@
|
|
1
|
+
from fuzzywuzzy import fuzz, process
|
2
|
+
|
3
|
+
def best_match(query: str, choices: list[str], score_cutoff: int = 70):
|
4
|
+
"""
|
5
|
+
获取最接近 query 的匹配项
|
6
|
+
:return: (匹配项, 相似度得分) 或 None
|
7
|
+
"""
|
8
|
+
return process.extractOne(query, choices, scorer=fuzz.ratio, score_cutoff=score_cutoff)
|
9
|
+
|
10
|
+
def all_matches(query: str, choices: list[str], limit: int = 5):
|
11
|
+
"""
|
12
|
+
获取多个相似匹配项
|
13
|
+
:return: [(匹配项, 相似度得分), ...]
|
14
|
+
"""
|
15
|
+
return process.extract(query, choices, scorer=fuzz.ratio, limit=limit)
|
16
|
+
|
17
|
+
def is_similar(s1: str, s2: str, threshold: int = 85):
|
18
|
+
"""
|
19
|
+
判断两个字符串是否相似
|
20
|
+
:return: True / False
|
21
|
+
"""
|
22
|
+
return fuzz.ratio(s1, s2) >= threshold
|
@@ -6,7 +6,8 @@ __date__ = '2025/2/14 11:09'
|
|
6
6
|
import redis
|
7
7
|
from redis import Redis
|
8
8
|
|
9
|
-
from ctools import
|
9
|
+
from ctools.pools import thread_pool
|
10
|
+
from ctools import cdate, cid
|
10
11
|
|
11
12
|
|
12
13
|
def init_pool(host: str = 'localhost', port: int = 6379, db: int = 0, password: str = None,
|
@@ -35,11 +36,11 @@ def init_pool(host: str = 'localhost', port: int = 6379, db: int = 0, password:
|
|
35
36
|
def add_lock(r: Redis, key: str, timeout: int = 30):
|
36
37
|
if r.exists(key):
|
37
38
|
expire_time = r.get(key)
|
38
|
-
if
|
39
|
+
if cdate.time_diff_in_seconds(expire_time, cdate.get_date_time()) > 0:
|
39
40
|
return True
|
40
41
|
else:
|
41
42
|
r.delete(key)
|
42
|
-
return r.set(key,
|
43
|
+
return r.set(key, cdate.opt_time(seconds=timeout), nx=True, ex=timeout) is not None
|
43
44
|
|
44
45
|
def remove_lock(r: Redis, key: str):
|
45
46
|
r.delete(key)
|
@@ -94,7 +95,7 @@ def stream_subscribe(r: Redis, stream_name, group_name, callback, from_id: str='
|
|
94
95
|
print(f"Consumer group '{group_name}' already exists.")
|
95
96
|
else:
|
96
97
|
print(f"Error creating consumer group '{group_name}': {e}")
|
97
|
-
consumer_name = 'consumer-{}'.format(
|
98
|
+
consumer_name = 'consumer-{}'.format(cid.get_uuid())
|
98
99
|
# 处理未确认的消息
|
99
100
|
_process_pending_messages(r, stream_name, group_name, consumer_name, callback)
|
100
101
|
while True:
|
@@ -5,8 +5,11 @@ from typing import Dict
|
|
5
5
|
from paho.mqtt import client as mqtt
|
6
6
|
from paho.mqtt.enums import CallbackAPIVersion
|
7
7
|
|
8
|
-
from ctools import sys_log, cjson,
|
8
|
+
from ctools import sys_log, cjson, sys_info
|
9
|
+
from ctools.cipher import sm_util
|
9
10
|
from ctools.dict_wrapper import DictWrapper as DictToObj
|
11
|
+
from ctools.pools import thread_pool
|
12
|
+
from ctools import cid, cdate
|
10
13
|
|
11
14
|
|
12
15
|
class MQTTEvent(Enum):
|
@@ -42,9 +45,9 @@ class MQTTRequest:
|
|
42
45
|
|
43
46
|
def __init__(self, **kwargs):
|
44
47
|
self.event: str = kwargs.get('event')
|
45
|
-
self.trace_id: str = kwargs.get('trace_id') if kwargs.get('trace_id') else
|
48
|
+
self.trace_id: str = kwargs.get('trace_id') if kwargs.get('trace_id') else cid.get_uuid()
|
46
49
|
self.client_id: str = kwargs.get('client_id')
|
47
|
-
self.time: str = kwargs.get('time') if kwargs.get('time') else
|
50
|
+
self.time: str = kwargs.get('time') if kwargs.get('time') else cdate.get_date_time()
|
48
51
|
self.body = kwargs.get('body')
|
49
52
|
|
50
53
|
def __str__(self):
|
@@ -60,7 +63,7 @@ class MQTTResponse:
|
|
60
63
|
self.event: str = kwargs.get('event')
|
61
64
|
self.trace_id: str = kwargs.get('trace_id')
|
62
65
|
self.status: int = kwargs.get('status')
|
63
|
-
self.time: str = kwargs.get('time') if kwargs.get('time') else
|
66
|
+
self.time: str = kwargs.get('time') if kwargs.get('time') else cdate.get_date_time()
|
64
67
|
self.msg: str = kwargs.get('msg')
|
65
68
|
self.body = kwargs.get('body')
|
66
69
|
|
@@ -94,8 +97,8 @@ class MQTTUtils:
|
|
94
97
|
will_msg = {
|
95
98
|
"event": "offline",
|
96
99
|
"client_id": self.client_id,
|
97
|
-
"trace_id":
|
98
|
-
"time":
|
100
|
+
"trace_id": cid.get_uuid(),
|
101
|
+
"time": cdate.get_date_time(),
|
99
102
|
"body": {"type": "will_msg"}
|
100
103
|
}
|
101
104
|
self.client.will_set(self.publish_topic, cjson.dumps(will_msg), 2, False)
|
@@ -150,16 +153,16 @@ class MQTTUtils:
|
|
150
153
|
def encrypt_body(self, body):
|
151
154
|
if self.broker_encrypt_key:
|
152
155
|
try:
|
153
|
-
return
|
156
|
+
return sm_util.encrypt_with_sm4(self.broker_encrypt_key, cjson.dumps(body))
|
154
157
|
except Exception:
|
155
|
-
return
|
158
|
+
return sm_util.encrypt_with_sm4(self.broker_encrypt_key, body)
|
156
159
|
|
157
160
|
def decrypt_body(self, body):
|
158
161
|
if self.broker_encrypt_key:
|
159
162
|
try:
|
160
|
-
return cjson.loads(
|
163
|
+
return cjson.loads(sm_util.decrypt_with_sm4(self.broker_encrypt_key, body))
|
161
164
|
except Exception:
|
162
|
-
|
165
|
+
sm_util.decrypt_with_sm4(self.broker_encrypt_key, body)
|
163
166
|
|
164
167
|
def connect(self, username=None, password=None, timeout=10):
|
165
168
|
if username and password:
|
ctools/sys_info.py
CHANGED
@@ -2,7 +2,8 @@ import hashlib
|
|
2
2
|
import os
|
3
3
|
import platform
|
4
4
|
|
5
|
-
from ctools import cjson,
|
5
|
+
from ctools import cjson, path_info
|
6
|
+
from ctools.cipher import sm_util
|
6
7
|
|
7
8
|
MACHINE_KEY = b'EnrGffoorbFyTYoS0902YyT1Fhehj4InpbezIDUuPOg='
|
8
9
|
|
@@ -15,7 +16,7 @@ def get_user():
|
|
15
16
|
|
16
17
|
def get_machine_code():
|
17
18
|
if MachineInfo.machine_code: return MachineInfo.machine_code
|
18
|
-
destPath = os.path.join(
|
19
|
+
destPath = os.path.join(path_info.get_user_work_path(), "AppData/Local/machine")
|
19
20
|
machine_file = os.path.join(destPath, 'machine_code.mc')
|
20
21
|
origin_machine_code = get_origin_machine_code()
|
21
22
|
if os.path.exists(machine_file):
|
@@ -23,7 +24,7 @@ def get_machine_code():
|
|
23
24
|
file_code = f.readline()
|
24
25
|
dec_code = ''
|
25
26
|
try:
|
26
|
-
dec_code = cjson.loads(
|
27
|
+
dec_code = cjson.loads(sm_util.decrypt_with_sm4(MACHINE_KEY, file_code))
|
27
28
|
origin_code = dec_code.get("origin_code")
|
28
29
|
if origin_code == origin_machine_code:
|
29
30
|
MachineInfo.machine_code = dec_code.get("hash_code")
|
@@ -33,7 +34,7 @@ def get_machine_code():
|
|
33
34
|
print('machine code file is error: {} {}'.format(file_code, dec_code))
|
34
35
|
hash_machine_code = get_hash_machine_code(origin_machine_code)
|
35
36
|
machine_code = {"origin_code": origin_machine_code, "hash_code": hash_machine_code}
|
36
|
-
enc_code =
|
37
|
+
enc_code = sm_util.encrypt_with_sm4(MACHINE_KEY, cjson.dumps(machine_code))
|
37
38
|
os.makedirs(destPath, exist_ok=True)
|
38
39
|
with open(machine_file, 'w') as f:
|
39
40
|
f.write(enc_code)
|