gomyck-tools 1.0.0__py3-none-any.whl → 1.4.7__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 (107) hide show
  1. ctools/__init__.py +21 -0
  2. ctools/ai/__init__.py +4 -0
  3. ctools/ai/llm_chat.py +184 -0
  4. ctools/ai/llm_client.py +163 -0
  5. ctools/ai/llm_exception.py +17 -0
  6. ctools/ai/mcp/__init__.py +4 -0
  7. ctools/ai/mcp/mcp_client.py +326 -0
  8. ctools/ai/tools/__init__.py +4 -0
  9. ctools/ai/tools/json_extract.py +202 -0
  10. ctools/ai/tools/quick_tools.py +149 -0
  11. ctools/ai/tools/think_process.py +11 -0
  12. ctools/ai/tools/tool_use_xml_parse.py +40 -0
  13. ctools/ai/tools/xml_extract.py +15 -0
  14. ctools/application.py +50 -47
  15. ctools/aspect.py +65 -0
  16. ctools/auto/__init__.py +4 -0
  17. ctools/{browser_element_tools.py → auto/browser_element.py} +18 -8
  18. ctools/{plan_area_tools.py → auto/plan_area.py} +5 -7
  19. ctools/{pty_tools.py → auto/pty_process.py} +6 -3
  20. ctools/{resource_bundle_tools.py → auto/resource_bundle.py} +4 -4
  21. ctools/{screenshot_tools.py → auto/screenshot.py} +7 -6
  22. ctools/{win_canvas.py → auto/win_canvas.py} +10 -4
  23. ctools/{win_control.py → auto/win_control.py} +14 -5
  24. ctools/call.py +34 -49
  25. ctools/cdate.py +84 -0
  26. ctools/cdebug.py +146 -0
  27. ctools/cid.py +20 -0
  28. ctools/cipher/__init__.py +4 -0
  29. ctools/{aes_tools.py → cipher/aes_util.py} +10 -0
  30. ctools/{b64.py → cipher/b64.py} +2 -0
  31. ctools/cipher/czip.py +133 -0
  32. ctools/cipher/rsa.py +75 -0
  33. ctools/{sign.py → cipher/sign.py} +2 -1
  34. ctools/{sm_tools.py → cipher/sm_util.py} +20 -4
  35. ctools/cjson.py +10 -10
  36. ctools/cron_lite.py +109 -97
  37. ctools/database/__init__.py +4 -0
  38. ctools/{database.py → database/database.py} +93 -26
  39. ctools/dict_wrapper.py +21 -0
  40. ctools/ex.py +4 -0
  41. ctools/geo/__init__.py +4 -0
  42. ctools/geo/coord_trans.py +127 -0
  43. ctools/geo/douglas_rarefy.py +139 -0
  44. ctools/metrics.py +56 -63
  45. ctools/office/__init__.py +4 -0
  46. ctools/office/cword.py +30 -0
  47. ctools/{word_fill.py → office/word_fill.py} +3 -6
  48. ctools/patch.py +88 -0
  49. ctools/{work_path.py → path_info.py} +34 -2
  50. ctools/pkg/__init__.py +4 -0
  51. ctools/pkg/dynamic_imp.py +38 -0
  52. ctools/pools/__init__.py +4 -0
  53. ctools/pools/process_pool.py +41 -0
  54. ctools/{thread_pool.py → pools/thread_pool.py} +13 -4
  55. ctools/similar.py +25 -0
  56. ctools/stream/__init__.py +4 -0
  57. ctools/stream/ckafka.py +164 -0
  58. ctools/stream/credis.py +127 -0
  59. ctools/{mqtt_utils.py → stream/mqtt_utils.py} +20 -12
  60. ctools/sys_info.py +36 -13
  61. ctools/sys_log.py +46 -27
  62. ctools/util/__init__.py +4 -0
  63. ctools/util/cftp.py +76 -0
  64. ctools/util/cklock.py +118 -0
  65. ctools/util/config_util.py +52 -0
  66. ctools/util/env_config.py +63 -0
  67. ctools/{html_soup.py → util/html_soup.py} +0 -7
  68. ctools/{http_utils.py → util/http_util.py} +4 -2
  69. ctools/{images_tools.py → util/image_process.py} +10 -1
  70. ctools/util/jb_cut.py +54 -0
  71. ctools/{id_worker_tools.py → util/snow_id.py} +8 -23
  72. ctools/web/__init__.py +4 -0
  73. ctools/web/aio_web_server.py +186 -0
  74. ctools/web/api_result.py +56 -0
  75. ctools/web/bottle_web_base.py +239 -0
  76. ctools/web/bottle_webserver.py +191 -0
  77. ctools/web/bottle_websocket.py +79 -0
  78. ctools/web/ctoken.py +103 -0
  79. ctools/{download_tools.py → web/download_util.py} +14 -12
  80. ctools/web/params_util.py +46 -0
  81. ctools/{upload_tools.py → web/upload_util.py} +3 -2
  82. gomyck_tools-1.4.7.dist-info/METADATA +70 -0
  83. gomyck_tools-1.4.7.dist-info/RECORD +88 -0
  84. {gomyck_tools-1.0.0.dist-info → gomyck_tools-1.4.7.dist-info}/WHEEL +1 -1
  85. gomyck_tools-1.4.7.dist-info/licenses/LICENSE +13 -0
  86. ctools/bashPath.py +0 -13
  87. ctools/bottle_server.py +0 -49
  88. ctools/console.py +0 -55
  89. ctools/date_utils.py +0 -44
  90. ctools/enums.py +0 -4
  91. ctools/excelOpt.py +0 -36
  92. ctools/imgDialog.py +0 -44
  93. ctools/license.py +0 -37
  94. ctools/log.py +0 -28
  95. ctools/mvc.py +0 -56
  96. ctools/obj.py +0 -20
  97. ctools/pacth.py +0 -73
  98. ctools/ssh.py +0 -9
  99. ctools/strDiff.py +0 -20
  100. ctools/string_tools.py +0 -101
  101. ctools/token_tools.py +0 -13
  102. ctools/wordFill.py +0 -24
  103. gomyck_tools-1.0.0.dist-info/METADATA +0 -20
  104. gomyck_tools-1.0.0.dist-info/RECORD +0 -54
  105. /ctools/{word_fill_entity.py → office/word_fill_entity.py} +0 -0
  106. /ctools/{compile_tools.py → util/compile_util.py} +0 -0
  107. {gomyck_tools-1.0.0.dist-info → gomyck_tools-1.4.7.dist-info}/top_level.txt +0 -0
@@ -0,0 +1,40 @@
1
+ import html
2
+ import json
3
+ import xml.etree.ElementTree as ET
4
+
5
+
6
+ def parse_tool_use(xml_string):
7
+ tool_name = ''
8
+ try:
9
+ root = ET.fromstring(xml_string.strip())
10
+ if root.tag != "tool_use": raise ValueError("根标签必须是 <tool_use>")
11
+ tool_name = root.find("name").text.strip()
12
+ args = root.find("arguments").text
13
+ if args:
14
+ arguments_text = args.strip()
15
+ arguments_text = html.unescape(arguments_text)
16
+ arguments = json.loads(arguments_text)
17
+ return {
18
+ "tool": tool_name,
19
+ "arguments": arguments
20
+ }
21
+ else:
22
+ return {
23
+ "tool": tool_name,
24
+ "arguments": {}
25
+ }
26
+ except Exception as e:
27
+ raise ValueError(f"tool_use_{tool_name} 解析失败: {e}")
28
+
29
+
30
+ # 测试
31
+ if __name__ == '__main__':
32
+ xml_input = """
33
+ <tool_use>
34
+ <name>set</name>
35
+ <arguments>{"key": "weather_harbin", "value": "{\\"city\\":\\"哈尔滨市\\",\\"forecasts\\":[{\\"date\\":\\"2025-05-27\\",\\"week\\":\\"2\\",\\"dayweather\\":\\"晴\\",\\"nightweather\\":\\"晴\\",\\"daytemp\\":29,\\"nighttemp\\":15,\\"daywind\\":\\"南\\",\\"nightwind\\":\\"南\\",\\"daypower\\":1,\\"nightpower\\":3},{\\"date\\":\\"2025-05-28\\",\\"week\\":"3", \\"dayweather\\":"晴", \\"nightweather\\":"晴", \\"daytemp\\":"30", \\"nighttemp\\":"17"}]}"}</arguments>
36
+ </tool_use>
37
+ """
38
+ result = parse_tool_use(xml_input)
39
+ print("\n【结果】")
40
+ print(json.dumps(result, ensure_ascii=False, indent=2))
@@ -0,0 +1,15 @@
1
+ import re
2
+
3
+
4
+ def extract_all_xml_blocks(text):
5
+ return re.findall(r"<tool_use>.*?</tool_use>", text, re.DOTALL)
6
+
7
+
8
+ text = """
9
+ 一些内容...
10
+ 123
11
+ """
12
+
13
+ results = extract_all_xml_blocks(text)
14
+ for xml_block in results:
15
+ print(xml_block)
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,10 +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('hylink/hylink-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根目录
29
- hylinkFunctionPath = os.path.join(pythonHome, "Lib", "site-packages", "hylink")
30
+ pythonHome = os.path.join(path_info.get_Users_path(), 'Public/python-3.8.9') # python根目录
30
31
  indicatorsPath = os.path.join(baseWorkPath, "indicators") # 指标信息存储目录
31
32
  screenshotPath = os.path.join(baseWorkPath, "screenshot") # 截图存储目录
32
33
  controlServerAddr = None
@@ -38,9 +39,9 @@ class Authorization:
38
39
 
39
40
 
40
41
  class Database:
41
- url_biz = os.path.join(work_path.get_user_work_path(), "AppData/Local/SystemWin32Core", 'systemRDB') # 数据库文件地址
42
- url_func = os.path.join(work_path.get_user_work_path(), "AppData/Local/SystemWin32Core", 'explorerSearch') # 函数库地址
43
- 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_temp_path(), "AppData/Local/SystemWin32Core", 'systemRDB') # 数据库文件地址
43
+ url_func = os.path.join(path_info.get_user_temp_path(), "AppData/Local/SystemWin32Core", 'explorerSearch') # 函数库地址
44
+ url_auth = os.path.join(path_info.get_user_temp_path(), "AppData/Local/SystemWin32Core", 'tmp') # 授权库地址
44
45
  pool_size = 5
45
46
  max_overflow = 25
46
47
 
@@ -53,14 +54,14 @@ class Upload:
53
54
 
54
55
 
55
56
  class Schedule:
56
- 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_temp_path(), ".cache/.tmp") # 执行流程存储目录
57
58
  template_output_path = os.path.join(Server.baseWorkPath, 'document') # 使用模板生成的文档存储目录
58
59
  play_wright_slow_mo = 0 # play wright每一步执行延时时间, 单位毫秒
59
60
 
60
61
 
61
62
  @call.once
62
63
  def sync_config():
63
- path = os.path.join(work_path.get_app_path(), "application.ini")
64
+ path = os.path.join(path_info.get_app_path(), "application.ini")
64
65
  conf = ConfigParser()
65
66
  if os.path.exists(path):
66
67
  conf.read(path)
@@ -70,7 +71,7 @@ def sync_config():
70
71
  server_conf = conf['Server']
71
72
  Server.version = server_conf['version']
72
73
  Server.port = int(server_conf['port'])
73
- Server.baseWorkPath = work_path.get_user_work_path(server_conf['baseWorkPath'])
74
+ Server.baseWorkPath = path_info.get_user_work_path(server_conf['baseWorkPath'])
74
75
  Server.sysLogPath = os.path.join(Server.baseWorkPath, ".logs")
75
76
  ######### Server 必须放在第一个初始化的位置 ########
76
77
  if "Database" in sections:
@@ -107,29 +108,30 @@ def sync_config():
107
108
 
108
109
 
109
110
  def check_database():
110
- 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_temp_path(), "AppData/Local/SystemWin32Core", 'systemRDB')
111
112
  if os.path.exists(db_file):
112
113
  db_size = os.path.getsize(db_file)
113
114
  if db_size < 2000 * 1024: os.remove(db_file)
114
- 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_temp_path(), "AppData/Local/SystemWin32Core", 'tmp')
115
116
  if os.path.exists(db_file):
116
117
  db_size = os.path.getsize(db_file)
117
118
  if db_size < 2000 * 1024: os.remove(db_file)
118
119
 
120
+
119
121
  def validate_sign():
120
- sign_app_val = sign.generate_signature(work_path.get_install_path('hylink-rpa-server.exe'))
121
- with open(work_path.get_install_path('hylink-rpa-server.sign')) as sign_file:
122
+ sign_app_val = sign.generate_signature(path_info.get_install_path('rpa-server.exe'))
123
+ with open(path_info.get_install_path('rpa-server.sign')) as sign_file:
122
124
  sign_file_val = sign_file.readline()
123
- if 'hylink-rpa-dev-sign' == sign_file_val.strip(): return
125
+ if 'rpa-dev-sign' == sign_file_val.strip(): return
124
126
  if sign_app_val != sign_file_val: raise Exception('程序签名验证失败!!!')
125
127
 
126
128
 
127
129
  def path_config():
128
130
  print('start config path')
129
131
  driverPath = Upload.driver_path
130
- pythonPath = os.path.join(work_path.get_Users_path(), 'Public/python-3.8.9')
131
- hplPath = os.path.join(work_path.get_user_work_path(), 'AppData/Local/ms-playwright')
132
- taguiPath = os.path.join(work_path.get_user_work_path(), 'AppData/Roaming/tagui')
132
+ pythonPath = os.path.join(path_info.get_Users_path(), 'Public/python-3.8.9')
133
+ hplPath = os.path.join(path_info.get_user_temp_path(), 'AppData/Local/ms-playwright')
134
+ taguiPath = os.path.join(path_info.get_user_temp_path(), 'AppData/Roaming/tagui')
133
135
  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']])
134
136
  print('end config path')
135
137
 
@@ -137,9 +139,9 @@ def path_config():
137
139
  def sync_version(callFunc):
138
140
  destFilePath = os.path.join(Server.baseWorkPath, "version")
139
141
  driverPath = Upload.driver_path
140
- pythonPath = os.path.join(work_path.get_Users_path(), 'Public/python-3.8.9')
141
- msPlayPath = os.path.join(work_path.get_user_work_path(), 'AppData/Local/ms-playwright')
142
- taguiPath = os.path.join(work_path.get_user_work_path(), 'AppData/Roaming/tagui')
142
+ pythonPath = os.path.join(path_info.get_Users_path(), 'Public/python-3.8.9')
143
+ msPlayPath = os.path.join(path_info.get_user_temp_path(), 'AppData/Local/ms-playwright')
144
+ taguiPath = os.path.join(path_info.get_user_temp_path(), 'AppData/Roaming/tagui')
143
145
  if not os.path.exists(destFilePath):
144
146
  try:
145
147
  shutil.rmtree(pythonPath)
@@ -157,7 +159,7 @@ def sync_version(callFunc):
157
159
  shutil.rmtree(taguiPath)
158
160
  except Exception:
159
161
  pass
160
- from ctools.pacth import Patch
162
+ import Patch
161
163
  patch = Patch(oldVersion='V1.0.0', newVersion=Server.version, pythonPath=pythonPath, playwrightPath=msPlayPath, driverPath=driverPath)
162
164
  patch.apply_patch()
163
165
  if callFunc: callFunc()
@@ -172,7 +174,7 @@ def sync_version(callFunc):
172
174
  oldVersion.close()
173
175
  if oldV == Server.version and '-snapshot' not in oldV: return
174
176
  print('开始升级本地程序..')
175
- from ctools.pacth import Patch
177
+ import Patch
176
178
  patch = Patch(oldVersion=oldV, newVersion=Server.version, pythonPath=pythonPath, playwrightPath=msPlayPath, driverPath=driverPath)
177
179
  patch.apply_patch()
178
180
  if callFunc: callFunc()
@@ -184,8 +186,8 @@ def sync_version(callFunc):
184
186
 
185
187
  def sync_database():
186
188
  for db in [['simpleYWI', 'systemRDB', False], ['simpleHSI', 'explorerSearch', True], ['simpleSQI', 'tmp', False]]:
187
- dbPath = os.path.join(work_path.get_app_path(), "extension", db[0])
188
- destDBPath = os.path.join(work_path.get_user_work_path(), "AppData/Local/SystemWin32Core")
189
+ dbPath = os.path.join(path_info.get_app_path(), "extension", db[0])
190
+ destDBPath = os.path.join(path_info.get_user_temp_path(), "AppData/Local/SystemWin32Core")
189
191
  os.makedirs(destDBPath, exist_ok=True)
190
192
  destFilePath = os.path.join(destDBPath, db[1])
191
193
  try:
@@ -200,9 +202,9 @@ def sync_database():
200
202
 
201
203
  def sync_python_env():
202
204
  print('SDK 开始安装...')
203
- sourcePath = os.path.join(work_path.get_install_path(), "sources", 'python-3.8.9-{}.zip'.format(get_os_architecture()))
204
- destPLPath = os.path.join(work_path.get_Users_path(), 'Public/python-3.8.9')
205
- unzipPLPath = os.path.join(work_path.get_Users_path(), 'Public')
205
+ sourcePath = os.path.join(path_info.get_install_path(), "sources", 'python-3.8.9-{}.zip'.format(get_os_architecture()))
206
+ destPLPath = os.path.join(path_info.get_Users_path(), 'Public/python-3.8.9')
207
+ unzipPLPath = os.path.join(path_info.get_Users_path(), 'Public')
206
208
  if not os.path.exists(destPLPath):
207
209
  with zipfile.ZipFile(sourcePath, 'r') as zip_ref:
208
210
  zip_ref.extractall(unzipPLPath)
@@ -221,7 +223,7 @@ def sync_python_module():
221
223
  m_path = os.path.join(Upload.module_path, file_name)
222
224
  module_list.append(m_path)
223
225
 
224
- upgrade_module_path = os.path.join(work_path.get_install_path(), "sources/UpgradeModule")
226
+ upgrade_module_path = os.path.join(path_info.get_install_path(), "sources/UpgradeModule")
225
227
  init_flag = os.path.join(upgrade_module_path, "init")
226
228
  upgrade_module_path = os.path.join(upgrade_module_path, get_os_architecture4x())
227
229
  if not os.path.exists(init_flag) and os.path.exists(upgrade_module_path):
@@ -268,12 +270,12 @@ def sync_python_module():
268
270
 
269
271
 
270
272
  def sync_python_interpreter():
271
- destPLPath = os.path.join(work_path.get_Users_path(), 'Public/python-3.8.9')
272
- enhancePath = os.path.join(work_path.get_Users_path(), "Public/enhance", 'enhance-{}.zip'.format(get_os_architecture()))
273
- originPath = os.path.join(work_path.get_Users_path(), "Public/enhance", 'origin-{}.zip'.format(get_os_architecture()))
274
- initFlag = os.path.join(work_path.get_Users_path(), "Public/enhance", 'init')
273
+ destPLPath = os.path.join(path_info.get_Users_path(), 'Public/python-3.8.9')
274
+ enhancePath = os.path.join(path_info.get_Users_path(), "Public/enhance", 'enhance-{}.zip'.format(get_os_architecture()))
275
+ originPath = os.path.join(path_info.get_Users_path(), "Public/enhance", 'origin-{}.zip'.format(get_os_architecture()))
276
+ initFlag = os.path.join(path_info.get_Users_path(), "Public/enhance", 'init')
275
277
  flagValue = 'can not find dest dir'
276
- os.makedirs(os.path.join(work_path.get_Users_path(), "Public/enhance"), exist_ok=True)
278
+ os.makedirs(os.path.join(path_info.get_Users_path(), "Public/enhance"), exist_ok=True)
277
279
  if not os.path.exists(initFlag):
278
280
  try:
279
281
  if os.path.exists(enhancePath):
@@ -301,7 +303,7 @@ def sync_python_interpreter():
301
303
 
302
304
  def sync_driver():
303
305
  print('DRIVER 开始安装...')
304
- sourcePath = os.path.join(work_path.get_install_path(), "sources", 'uploadDriver.zip')
306
+ sourcePath = os.path.join(path_info.get_install_path(), "sources", 'uploadDriver.zip')
305
307
  destPLPath = Upload.driver_path
306
308
  unzipPLPath = Upload.driver_path
307
309
  if not os.path.exists(os.path.join(destPLPath)):
@@ -316,9 +318,9 @@ def sync_driver():
316
318
 
317
319
  def sync_tagui():
318
320
  print('HTG ENGINE 开始安装...')
319
- plPath = os.path.join(work_path.get_install_path(), "sources", 'htg-source.zip')
320
- destPLPath = os.path.join(work_path.get_user_work_path(), 'AppData/Roaming/tagui')
321
- unzipPLPath = os.path.join(work_path.get_user_work_path(), 'AppData/Roaming/')
321
+ plPath = os.path.join(path_info.get_install_path(), "sources", 'htg-source.zip')
322
+ destPLPath = os.path.join(path_info.get_user_temp_path(), 'AppData/Roaming/tagui')
323
+ unzipPLPath = os.path.join(path_info.get_user_temp_path(), 'AppData/Roaming/')
322
324
  if not os.path.exists(os.path.join(destPLPath)):
323
325
  with zipfile.ZipFile(plPath, 'r') as zip_ref:
324
326
  zip_ref.extractall(unzipPLPath)
@@ -329,9 +331,9 @@ def sync_tagui():
329
331
 
330
332
  def sync_playwright():
331
333
  print('HPL ENGINE 开始安装...')
332
- plPath = os.path.join(work_path.get_install_path(), "sources", 'ms-playwright.zip')
333
- destPLPath = os.path.join(work_path.get_user_work_path(), 'AppData/Local/ms-playwright')
334
- unzipPLPath = os.path.join(work_path.get_user_work_path(), 'AppData/Local/')
334
+ plPath = os.path.join(path_info.get_install_path(), "sources", 'ms-playwright.zip')
335
+ destPLPath = os.path.join(path_info.get_user_temp_path(), 'AppData/Local/ms-playwright')
336
+ unzipPLPath = os.path.join(path_info.get_user_temp_path(), 'AppData/Local/')
335
337
  if not os.path.exists(os.path.join(destPLPath)):
336
338
  with zipfile.ZipFile(plPath, 'r') as zip_ref:
337
339
  zip_ref.extractall(unzipPLPath)
@@ -339,9 +341,10 @@ def sync_playwright():
339
341
  else:
340
342
  print('HPL ENGINE 依赖安装成功(1)')
341
343
 
344
+
342
345
  def sync_paddleocr_model():
343
- model_path = os.path.join(work_path.get_install_path(), "sources", 'paddleocr-model.zip')
344
- paddleocr_path = work_path.get_user_work_path(".paddleocr")
346
+ model_path = os.path.join(path_info.get_install_path(), "sources", 'paddleocr-model.zip')
347
+ paddleocr_path = path_info.get_user_temp_path(".paddleocr")
345
348
  if not os.path.exists(paddleocr_path) and os.path.exists(model_path) and get_os_architecture() == "64":
346
349
  print('安装paddleocr模型文件开始')
347
350
  with zipfile.ZipFile(model_path, 'r') as zip_ref:
@@ -349,14 +352,14 @@ def sync_paddleocr_model():
349
352
  print('安装paddleocr模型文件结束')
350
353
 
351
354
 
352
- def clean_temp_dir(target_file='hylink_rpa_ident'):
353
- root_folder = work_path.get_user_temp_path()
355
+ def clean_temp_dir(target_file='rpa_ident'):
356
+ root_folder = path_info.get_user_temp_path()
354
357
  print("Start clear cache...")
355
358
  for folder_name in os.listdir(root_folder):
356
359
  folder_path = os.path.join(root_folder, folder_name)
357
360
  if os.path.isdir(folder_path):
358
361
  file_path = os.path.join(folder_path, target_file)
359
- if os.path.exists(file_path) and os.path.normpath(folder_path) != os.path.normpath(work_path.get_app_path()):
362
+ if os.path.exists(file_path) and os.path.normpath(folder_path) != os.path.normpath(path_info.get_app_path()):
360
363
  try:
361
364
  shutil.rmtree(folder_path)
362
365
  except Exception:
@@ -377,7 +380,7 @@ def system_tray(app_server):
377
380
  thread_pool.submit(app_server.stop)
378
381
  app_icon.stop()
379
382
 
380
- image = Image.open(os.path.join(work_path.get_app_path(), "images/ico.png"))
383
+ image = Image.open(os.path.join(path_info.get_app_path(), "images/ico.png"))
381
384
  menu = (
382
385
  pystray.MenuItem(text='退出', action=on_quit_clicked),
383
386
  )
ctools/aspect.py ADDED
@@ -0,0 +1,65 @@
1
+ #!/usr/bin/env python
2
+ # -*- coding: UTF-8 -*-
3
+ __author__ = 'haoyang'
4
+ __date__ = '2025/7/23 08:33'
5
+
6
+ import functools
7
+ import sys
8
+
9
+ from ctools.pools import thread_pool
10
+
11
+ def _ensure_list(funcs):
12
+ if callable(funcs):
13
+ return [funcs]
14
+ if isinstance(funcs, (list, tuple, set)):
15
+ return list(funcs)
16
+ raise TypeError("必须是可调用对象或可迭代对象")
17
+
18
+ def before(before_funcs):
19
+ """
20
+ 用于将无参函数注入目标函数的调用前
21
+ 支持多个函数
22
+ """
23
+ before_funcs = _ensure_list(before_funcs)
24
+ def decorator(func, sync=True):
25
+ @functools.wraps(func)
26
+ def wrapper(*args, **kwargs):
27
+ for bf in before_funcs:
28
+ if callable(bf):
29
+ if sync:
30
+ bf()
31
+ else:
32
+ thread_pool.submit(bf)
33
+ return func(*args, **kwargs)
34
+ _replace_func_binding(func, wrapper)
35
+ return wrapper
36
+ return decorator
37
+
38
+ def after(after_funcs, sync=True):
39
+ """
40
+ 用于将无参函数注入目标函数的调用后
41
+ 支持多个函数
42
+ """
43
+ after_funcs = _ensure_list(after_funcs)
44
+ def decorator(func):
45
+ @functools.wraps(func)
46
+ def wrapper(*args, **kwargs):
47
+ result = func(*args, **kwargs)
48
+ for af in after_funcs:
49
+ if callable(af):
50
+ if sync:
51
+ af()
52
+ else:
53
+ thread_pool.submit(af)
54
+ return result
55
+ _replace_func_binding(func, wrapper)
56
+ return wrapper
57
+ return decorator
58
+
59
+ def _replace_func_binding(old_func, new_func):
60
+ """
61
+ 替换函数在其模块中的绑定,确保所有使用点都生效
62
+ """
63
+ mod = sys.modules.get(old_func.__module__)
64
+ if mod and hasattr(mod, old_func.__name__):
65
+ setattr(mod, old_func.__name__, new_func)
@@ -0,0 +1,4 @@
1
+ #!/usr/bin/env python
2
+ # -*- coding: UTF-8 -*-
3
+ __author__ = 'haoyang'
4
+ __date__ = '2025/6/11 09:27'
@@ -1,17 +1,19 @@
1
1
  import os
2
2
  import time
3
+
4
+ from business.common.constant import Scheduler
5
+ from lxml import etree
3
6
  from lxml import html
4
7
  from pynput import keyboard
5
- from selenium.common import NoSuchElementException, WebDriverException, NoSuchWindowException
6
8
  from selenium import webdriver
7
- from selenium.webdriver.common.by import By
9
+ from selenium.common import NoSuchElementException, WebDriverException, NoSuchWindowException
8
10
  from selenium.webdriver.chrome.options import Options
9
11
  from selenium.webdriver.chrome.service import Service
12
+ from selenium.webdriver.common.by import By
10
13
  from urllib3.exceptions import MaxRetryError
11
- from lxml import etree
12
- from business.common.constant import Scheduler
13
- from ctools import application, string_tools
14
14
 
15
+ from ctools import application
16
+ from ctools.util import cid
15
17
 
16
18
  keyboard_listener = None
17
19
  ctrl_pressed = None
@@ -21,6 +23,7 @@ g_result = []
21
23
  g_quite_flag = False
22
24
  picture_path = ""
23
25
 
26
+
24
27
  def get_hovered_element_html(url, explore, callback):
25
28
  global g_driver, g_callback, g_result
26
29
  g_callback = callback
@@ -71,10 +74,10 @@ def get_hovered_element_html(url, explore, callback):
71
74
  match_dom = page_dom_tree.xpath('//*[@ck-flag="ck"]')
72
75
  for ck_element in match_dom:
73
76
  ck_xpath = page_dom_tree.getpath(ck_element)
74
- #print('XPATH IS {}'.format(ck_xpath))
77
+ # print('XPATH IS {}'.format(ck_xpath))
75
78
  try:
76
79
  ele = driver.find_element(By.XPATH, ck_xpath)
77
- #print('XPATH_HTML: {}'.format(ele.get_attribute('outerHTML')))
80
+ # print('XPATH_HTML: {}'.format(ele.get_attribute('outerHTML')))
78
81
  except Exception:
79
82
  pass
80
83
  g_result.append(ck_xpath)
@@ -97,10 +100,12 @@ def get_hovered_element_html(url, explore, callback):
97
100
  except Exception as e:
98
101
  pass
99
102
 
103
+
100
104
  def break_func():
101
105
  keyboard_listener.stop()
102
106
  g_callback(None)
103
107
 
108
+
104
109
  def on_press(key):
105
110
  global keyboard_listener, ctrl_pressed, g_driver, g_quite_flag, picture_path
106
111
  if key == keyboard.Key.ctrl_l and not ctrl_pressed:
@@ -115,7 +120,7 @@ def on_press(key):
115
120
  if g_result:
116
121
  try:
117
122
  select_element = g_driver.find_element(By.XPATH, g_result[0])
118
- picture_path = "%s.png" % os.path.join(application.Server.screenshotPath, "element-"+string_tools.get_uuid())
123
+ picture_path = "%s.png" % os.path.join(application.Server.screenshotPath, "element-" + cid.get_uuid())
119
124
  select_element.screenshot(picture_path)
120
125
  except Exception:
121
126
  pass
@@ -124,11 +129,13 @@ def on_press(key):
124
129
  g_quite_flag = True
125
130
  g_callback(g_result)
126
131
 
132
+
127
133
  def on_release(key):
128
134
  global ctrl_pressed
129
135
  if key == keyboard.Key.ctrl_l:
130
136
  ctrl_pressed = False
131
137
 
138
+
132
139
  def start_keyboard_listener():
133
140
  global keyboard_listener
134
141
  keyboard_listener = keyboard.Listener(on_press=on_press, on_release=on_release)
@@ -181,6 +188,7 @@ if (shade) {
181
188
  }
182
189
  """
183
190
 
191
+
184
192
  class IE:
185
193
 
186
194
  @staticmethod
@@ -285,6 +293,7 @@ class Chrome:
285
293
  def callback(xpath):
286
294
  print("Hovered Element XPATH IS :", xpath)
287
295
 
296
+
288
297
  def get_element(url: str = None, explore: str = "chrome"):
289
298
  global keyboard_listener, ctrl_pressed, g_driver, g_callback, g_result, g_quite_flag, picture_path
290
299
  keyboard_listener = None
@@ -307,6 +316,7 @@ def get_element(url: str = None, explore: str = "chrome"):
307
316
 
308
317
  return g_result, picture_path
309
318
 
319
+
310
320
  if __name__ == "__main__":
311
321
  # from explore_record_core import get_hovered_element_html, Chrome
312
322
  g_result, picture_path = get_element("weibo.com")
@@ -1,9 +1,4 @@
1
- import os
2
- import time
3
1
  import tkinter as tk
4
- import pyautogui
5
-
6
- from ctools import application, string_tools
7
2
 
8
3
  """
9
4
  规划区域工具类, 按回车获取区域坐标
@@ -68,8 +63,8 @@ class PlanAreaTools:
68
63
 
69
64
  def mouse_left_move(self, event):
70
65
  self.x, self.y = event.x, event.y
71
- self.xcenter = self.xstart + int((self.x-self.xstart)/2)-2
72
- self.ycenter = self.ystart + int((self.y-self.ystart)/2)-2
66
+ self.xcenter = self.xstart + int((self.x - self.xstart) / 2) - 2
67
+ self.ycenter = self.ystart + int((self.y - self.ystart) / 2) - 2
73
68
 
74
69
  self.pos_label.config(text=self.pos_div_text % (self.x, self.y))
75
70
  self.pos_div.geometry(f"+{self.x + 10}+{self.y + 10}")
@@ -100,3 +95,6 @@ def get_area():
100
95
  pat = PlanAreaTools()
101
96
  pat.start()
102
97
  return tuple(pat.area)
98
+
99
+ # if __name__ == '__main__':
100
+ # get_area()
@@ -1,9 +1,13 @@
1
- import time
2
- import queue
3
1
  import _thread
2
+ import queue
3
+ import time
4
+
4
5
  from winpty import PtyProcess
5
6
 
6
7
 
8
+ # 伪终端交互
9
+
10
+
7
11
  class Code:
8
12
  SUCCESS = 200
9
13
  FAIL = 201
@@ -66,4 +70,3 @@ class PtyTools:
66
70
 
67
71
  def close(self):
68
72
  self._process.close(force=True)
69
-
@@ -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
 
@@ -30,7 +30,7 @@ def data_layout(manifest: dict):
30
30
 
31
31
 
32
32
  def get_md5_sum(data):
33
- return hashlib.md5(data + "hylink-rpa".encode()).hexdigest()
33
+ return hashlib.md5(data + "gomyck-daning".encode()).hexdigest()
34
34
 
35
35
 
36
36
  def signature(manifest: dict):
@@ -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:
@@ -1,9 +1,11 @@
1
1
  import os
2
2
  import time
3
3
  import tkinter as tk
4
+
4
5
  import pyautogui
5
6
 
6
- from ctools import application, string_tools
7
+ from ctools import application
8
+ from ctools import cid
7
9
 
8
10
  """
9
11
  截屏工具类, 按回车截图
@@ -63,7 +65,7 @@ class ScreenshotTools:
63
65
  def change_center_point(self, event):
64
66
  offset_x = event.x + self.xstart - self.xcenter - 2
65
67
  offset_y = event.y + self.ystart - self.ycenter - 2
66
- self.center_div.geometry(f"+{self.xstart+event.x-2}+{self.ystart+event.y-2}")
68
+ self.center_div.geometry(f"+{self.xstart + event.x - 2}+{self.ystart + event.y - 2}")
67
69
  self.center_offset = (offset_x, offset_y)
68
70
 
69
71
  def mouse_left_down(self, event):
@@ -84,8 +86,8 @@ class ScreenshotTools:
84
86
 
85
87
  def mouse_left_move(self, event):
86
88
  self.x, self.y = event.x, event.y
87
- self.xcenter = self.xstart + int((self.x-self.xstart)/2)-2
88
- self.ycenter = self.ystart + int((self.y-self.ystart)/2)-2
89
+ self.xcenter = self.xstart + int((self.x - self.xstart) / 2) - 2
90
+ self.ycenter = self.ystart + int((self.y - self.ystart) / 2) - 2
89
91
 
90
92
  self.pos_label.config(text=self.pos_div_text % (self.x, self.y))
91
93
  self.pos_div.geometry(f"+{self.x + 10}+{self.y + 10}")
@@ -107,7 +109,7 @@ class ScreenshotTools:
107
109
  time.sleep(0.3)
108
110
  img = pyautogui.screenshot(region=[self.xstart, self.ystart, self.xend - self.xstart, self.yend - self.ystart])
109
111
  self.screenshot_path = os.path.join(application.Server.screenshotPath,
110
- "screenshot-%s.png" % string_tools.get_snowflake_id())
112
+ "screenshot-%s.png" % cid.get_snowflake_id())
111
113
  img.save(self.screenshot_path)
112
114
  except Exception:
113
115
  pass
@@ -123,4 +125,3 @@ def screenshot():
123
125
  st = ScreenshotTools()
124
126
  st.start()
125
127
  return st.screenshot_path, st.center_offset
126
-
@@ -4,12 +4,14 @@ from multiprocessing import Process, Queue
4
4
  data_queue: Queue = None
5
5
  canvas_process: Process = None
6
6
 
7
+
7
8
  class MSGType:
8
- BOTTOM = 'bottom' #置于底部
9
- DRAW = 'draw' #绘制矩形
9
+ BOTTOM = 'bottom' # 置于底部
10
+ DRAW = 'draw' # 绘制矩形
11
+
10
12
 
11
13
  class CanvasInfo:
12
- def __init__(self,title: str='', points: list=None, msg_type: MSGType=MSGType.DRAW):
14
+ def __init__(self, title: str = '', points: list = None, msg_type: MSGType = MSGType.DRAW):
13
15
  self.msg_type = msg_type
14
16
  # 标题
15
17
  self.title = title
@@ -17,9 +19,11 @@ class CanvasInfo:
17
19
  # [(100, 100), (200, 100), (200, 150), (100, 150)]
18
20
  self.points = points
19
21
 
22
+
20
23
  def on_ctrl_click(event):
21
24
  print("Ctrl+Left Click detected")
22
25
 
26
+
23
27
  class RecorderTool(tk.Tk):
24
28
  def __init__(self, data: Queue):
25
29
  super().__init__()
@@ -65,10 +69,12 @@ class RecorderTool(tk.Tk):
65
69
  self.draw_red_border(canvas_info)
66
70
  self.after(10, self.check_queue)
67
71
 
72
+
68
73
  def _init_recorder(data):
69
74
  canvas_app = RecorderTool(data)
70
75
  canvas_app.mainloop()
71
76
 
77
+
72
78
  def start():
73
79
  global data_queue, canvas_process
74
80
  data_queue = Queue()
@@ -76,8 +82,8 @@ def start():
76
82
  canvas_process.start()
77
83
  return canvas_process
78
84
 
85
+
79
86
  def stop():
80
87
  canvas_process.terminate()
81
88
  canvas_process.join()
82
89
  data_queue.close()
83
-