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.
Files changed (78) hide show
  1. ctools/ai/env_config.py +2 -0
  2. ctools/ai/llm_chat.py +27 -26
  3. ctools/ai/llm_client.py +87 -66
  4. ctools/ai/llm_exception.py +17 -0
  5. ctools/ai/mcp/mcp_client.py +5 -1
  6. ctools/ai/tools/quick_tools.py +99 -0
  7. ctools/ai/tools/xml_extract.py +0 -1
  8. ctools/application.py +46 -44
  9. ctools/auto/__init__.py +4 -0
  10. ctools/{browser_element_tools.py → auto/browser_element.py} +3 -2
  11. ctools/{plan_area_tools.py → auto/plan_area.py} +3 -0
  12. ctools/{resource_bundle_tools.py → auto/resource_bundle.py} +3 -3
  13. ctools/{screenshot_tools.py → auto/screenshot.py} +3 -2
  14. ctools/{win_control.py → auto/win_control.py} +5 -2
  15. ctools/cid.py +18 -0
  16. ctools/cipher/__init__.py +4 -0
  17. ctools/{rsa.py → cipher/rsa.py} +2 -2
  18. ctools/database/__init__.py +4 -0
  19. ctools/{database.py → database/database.py} +4 -3
  20. ctools/geo/__init__.py +4 -0
  21. ctools/metrics.py +2 -2
  22. ctools/office/__init__.py +4 -0
  23. ctools/{word_fill.py → office/word_fill.py} +1 -1
  24. ctools/pools/__init__.py +4 -0
  25. ctools/similar.py +22 -0
  26. ctools/stream/__init__.py +4 -0
  27. ctools/{credis.py → stream/credis.py} +5 -4
  28. ctools/{mqtt_utils.py → stream/mqtt_utils.py} +13 -10
  29. ctools/sys_info.py +5 -4
  30. ctools/sys_log.py +32 -31
  31. ctools/util/__init__.py +4 -0
  32. ctools/{http_utils.py → util/http_util.py} +0 -1
  33. ctools/{snow_id.py → util/snow_id.py} +2 -2
  34. ctools/web/__init__.py +4 -0
  35. ctools/{aio_web_server.py → web/aio_web_server.py} +23 -4
  36. ctools/{bottle_web_base.py → web/bottle_web_base.py} +2 -2
  37. ctools/{download_tools.py → web/download_util.py} +3 -2
  38. ctools/web/params_util.py +42 -0
  39. ctools/{upload_tools.py → web/upload_util.py} +3 -2
  40. {gomyck_tools-1.3.7.dist-info → gomyck_tools-1.3.9.dist-info}/METADATA +1 -1
  41. gomyck_tools-1.3.9.dist-info/RECORD +82 -0
  42. ctools/bashPath.py +0 -13
  43. ctools/console.py +0 -55
  44. ctools/enums.py +0 -4
  45. ctools/excelOpt.py +0 -36
  46. ctools/imgDialog.py +0 -45
  47. ctools/obj.py +0 -20
  48. ctools/str_diff.py +0 -20
  49. ctools/string_tools.py +0 -85
  50. gomyck_tools-1.3.7.dist-info/RECORD +0 -76
  51. /ctools/{pacth.py → auto/pacth.py} +0 -0
  52. /ctools/{pty_tools.py → auto/pty_process.py} +0 -0
  53. /ctools/{win_canvas.py → auto/win_canvas.py} +0 -0
  54. /ctools/{date_utils.py → cdate.py} +0 -0
  55. /ctools/{aes_tools.py → cipher/aes_util.py} +0 -0
  56. /ctools/{b64.py → cipher/b64.py} +0 -0
  57. /ctools/{czip.py → cipher/czip.py} +0 -0
  58. /ctools/{sign.py → cipher/sign.py} +0 -0
  59. /ctools/{sm_tools.py → cipher/sm_util.py} +0 -0
  60. /ctools/{coord_trans.py → geo/coord_trans.py} +0 -0
  61. /ctools/{douglas_rarefy.py → geo/douglas_rarefy.py} +0 -0
  62. /ctools/{cword.py → office/cword.py} +0 -0
  63. /ctools/{word_fill_entity.py → office/word_fill_entity.py} +0 -0
  64. /ctools/{work_path.py → path_info.py} +0 -0
  65. /ctools/{process_pool.py → pools/process_pool.py} +0 -0
  66. /ctools/{thread_pool.py → pools/thread_pool.py} +0 -0
  67. /ctools/{ckafka.py → stream/ckafka.py} +0 -0
  68. /ctools/{cftp.py → util/cftp.py} +0 -0
  69. /ctools/{compile_tools.py → util/compile_util.py} +0 -0
  70. /ctools/{html_soup.py → util/html_soup.py} +0 -0
  71. /ctools/{images_tools.py → util/image_process.py} +0 -0
  72. /ctools/{api_result.py → web/api_result.py} +0 -0
  73. /ctools/{bottle_webserver.py → web/bottle_webserver.py} +0 -0
  74. /ctools/{bottle_websocket.py → web/bottle_websocket.py} +0 -0
  75. /ctools/{ctoken.py → web/ctoken.py} +0 -0
  76. {gomyck_tools-1.3.7.dist-info → gomyck_tools-1.3.9.dist-info}/WHEEL +0 -0
  77. {gomyck_tools-1.3.7.dist-info → gomyck_tools-1.3.9.dist-info}/licenses/LICENSE +0 -0
  78. {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 work_path, call, sign, thread_pool
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 = work_path.get_user_work_path('rpa') # 基础的工作目录
28
+ baseWorkPath = path_info.get_user_path_info('rpa') # 基础的工作目录
27
29
  sysLogPath = os.path.join(baseWorkPath, ".logs") # 系统日志存储目录
28
- pythonHome = os.path.join(work_path.get_Users_path(), 'Public/python-3.8.9') # python根目录
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(work_path.get_user_work_path(), "AppData/Local/SystemWin32Core", 'systemRDB') # 数据库文件地址
41
- url_func = os.path.join(work_path.get_user_work_path(), "AppData/Local/SystemWin32Core", 'explorerSearch') # 函数库地址
42
- url_auth = os.path.join(work_path.get_user_work_path(), "AppData/Local/SystemWin32Core", 'tmp') # 授权库地址
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(work_path.get_user_work_path(), ".cache/.tmp") # 执行流程存储目录
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(work_path.get_app_path(), "application.ini")
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 = work_path.get_user_work_path(server_conf['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(work_path.get_user_work_path(), "AppData/Local/SystemWin32Core", 'systemRDB')
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(work_path.get_user_work_path(), "AppData/Local/SystemWin32Core", 'tmp')
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(work_path.get_install_path('rpa-server.exe'))
120
- with open(work_path.get_install_path('rpa-server.sign')) as sign_file:
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(work_path.get_Users_path(), 'Public/python-3.8.9')
130
- hplPath = os.path.join(work_path.get_user_work_path(), 'AppData/Local/ms-playwright')
131
- taguiPath = os.path.join(work_path.get_user_work_path(), 'AppData/Roaming/tagui')
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(work_path.get_Users_path(), 'Public/python-3.8.9')
140
- msPlayPath = os.path.join(work_path.get_user_work_path(), 'AppData/Local/ms-playwright')
141
- taguiPath = os.path.join(work_path.get_user_work_path(), 'AppData/Roaming/tagui')
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(work_path.get_app_path(), "extension", db[0])
187
- destDBPath = os.path.join(work_path.get_user_work_path(), "AppData/Local/SystemWin32Core")
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(work_path.get_install_path(), "sources", 'python-3.8.9-{}.zip'.format(get_os_architecture()))
203
- destPLPath = os.path.join(work_path.get_Users_path(), 'Public/python-3.8.9')
204
- unzipPLPath = os.path.join(work_path.get_Users_path(), 'Public')
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(work_path.get_install_path(), "sources/UpgradeModule")
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(work_path.get_Users_path(), 'Public/python-3.8.9')
271
- enhancePath = os.path.join(work_path.get_Users_path(), "Public/enhance", 'enhance-{}.zip'.format(get_os_architecture()))
272
- originPath = os.path.join(work_path.get_Users_path(), "Public/enhance", 'origin-{}.zip'.format(get_os_architecture()))
273
- initFlag = os.path.join(work_path.get_Users_path(), "Public/enhance", 'init')
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(work_path.get_Users_path(), "Public/enhance"), exist_ok=True)
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(work_path.get_install_path(), "sources", 'uploadDriver.zip')
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(work_path.get_install_path(), "sources", 'htg-source.zip')
319
- destPLPath = os.path.join(work_path.get_user_work_path(), 'AppData/Roaming/tagui')
320
- unzipPLPath = os.path.join(work_path.get_user_work_path(), 'AppData/Roaming/')
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(work_path.get_install_path(), "sources", 'ms-playwright.zip')
332
- destPLPath = os.path.join(work_path.get_user_work_path(), 'AppData/Local/ms-playwright')
333
- unzipPLPath = os.path.join(work_path.get_user_work_path(), 'AppData/Local/')
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(work_path.get_install_path(), "sources", 'paddleocr-model.zip')
343
- paddleocr_path = work_path.get_user_work_path(".paddleocr")
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 = work_path.get_user_temp_path()
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(work_path.get_app_path()):
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(work_path.get_app_path(), "images/ico.png"))
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
  )
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env python
2
+ # -*- coding: UTF-8 -*-
3
+ __author__ = 'haoyang'
4
+ __date__ = '2025/6/11 09:27'
@@ -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, string_tools
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-"+string_tools.get_uuid())
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
@@ -95,3 +95,6 @@ def get_area():
95
95
  pat = PlanAreaTools()
96
96
  pat.start()
97
97
  return tuple(pat.area)
98
+
99
+ # if __name__ == '__main__':
100
+ # get_area()
@@ -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, work_path, application
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(work_path.get_app_path() + '/keys/resource_private_key.pem', 'r') as pri:
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(work_path.get_app_path() + '/keys/resource_public_key.pem', 'r') as pub:
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, string_tools
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" % string_tools.get_snowflake_id())
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 thread_pool, win_canvas, application, string_tools
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" % string_tools.get_snowflake_id())
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
+
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env python
2
+ # -*- coding: UTF-8 -*-
3
+ __author__ = 'haoyang'
4
+ __date__ = '2025/6/11 09:20'
@@ -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 work_path, cjson
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(work_path.get_app_path() + '/keys/license.key', 'r') as pri:
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
 
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env python
2
+ # -*- coding: UTF-8 -*-
3
+ __author__ = 'haoyang'
4
+ __date__ = '2025/6/11 09:22'
@@ -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, string_tools
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(string_tools.get_snowflake_id())
86
+ return str(cid.get_snowflake_id())
86
87
 
87
88
  class BaseMixin(Base):
88
89
  __abstract__ = True
ctools/geo/__init__.py ADDED
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env python
2
+ # -*- coding: UTF-8 -*-
3
+ __author__ = 'haoyang'
4
+ __date__ = '2025/6/11 09:20'
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, work_path
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(work_path.get_user_work_path('metrics', True), 'persistent.json')
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
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env python
2
+ # -*- coding: UTF-8 -*-
3
+ __author__ = 'haoyang'
4
+ __date__ = '2025/6/11 09:37'
@@ -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,
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env python
2
+ # -*- coding: UTF-8 -*-
3
+ __author__ = 'haoyang'
4
+ __date__ = '2025/6/11 09:18'
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
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env python
2
+ # -*- coding: UTF-8 -*-
3
+ __author__ = 'haoyang'
4
+ __date__ = '2025/6/11 09:21'
@@ -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 date_utils, thread_pool, string_tools
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 date_utils.time_diff_in_seconds(expire_time, date_utils.get_date_time()) > 0:
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, date_utils.opt_time(seconds=timeout), nx=True, ex=timeout) is not None
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(string_tools.get_uuid())
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, string_tools, sys_info, date_utils, sm_tools, thread_pool
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 string_tools.get_uuid()
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 date_utils.get_date_time()
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 date_utils.get_date_time()
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": string_tools.get_uuid(),
98
- "time": date_utils.get_date_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 sm_tools.encrypt_with_sm4(self.broker_encrypt_key, cjson.dumps(body))
156
+ return sm_util.encrypt_with_sm4(self.broker_encrypt_key, cjson.dumps(body))
154
157
  except Exception:
155
- return sm_tools.encrypt_with_sm4(self.broker_encrypt_key, body)
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(sm_tools.decrypt_with_sm4(self.broker_encrypt_key, body))
163
+ return cjson.loads(sm_util.decrypt_with_sm4(self.broker_encrypt_key, body))
161
164
  except Exception:
162
- sm_tools.decrypt_with_sm4(self.broker_encrypt_key, body)
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, sm_tools, work_path
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(work_path.get_user_work_path(), "AppData/Local/machine")
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(sm_tools.decrypt_with_sm4(MACHINE_KEY, file_code))
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 = sm_tools.encrypt_with_sm4(MACHINE_KEY, cjson.dumps(machine_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)