├── README.md
├── config
├── Data+.txt
├── finger
│ ├── finger.ini
│ ├── finger_diy.ini
│ └── finger_port.ini
├── ico
│ ├── java.ico
│ ├── link.ico
│ └── python.ico
├── 提示词.md
└── 正则.txt
├── link-tools-v1.3.py
├── requirements.txt
├── tabs
├── tab_ai.py
├── tab_rolan.py
├── tab_zz.py
└── ui_main.py
└── tools
└── RapidScanner.exe
/README.md:
--------------------------------------------------------------------------------
1 | ## link-tools v1.3工具箱更新:
2 |
3 | 1、使用OpenAI库,会话更流畅稳定,支持更多厂商(如DeepSeek、腾讯云、阿里云、硅基流动等,其他自测)
4 |
5 | 2、支持自定义添加API模型,KEY置空为Ollama模式,如需快速配置可修改配置文件config/config_ai.ini后刷新导入
6 |
7 | 3、优化临时中断对话代码,阻断流式输出,修复短时间中断和执行导致的会话受限问题
8 |
9 | 4、增加输入内容实时tokens显示,合理控制输入内容长度
10 | 
11 | 
12 |
13 | 其他说明:
14 |
15 | 1、由于使用了OpenAi库,程序打包后大小暴增,本次更新提供EXE版本并公开源码
16 |
17 | ```
18 | python源码由python3.7编写:
19 | 安装库:
20 | pip install -r requirements.txt -i https://mirrors.aliyun.com/pypi/simple/
21 | 启动工具箱
22 | python link-tools-v1.3.py
23 | ```
24 |
25 | 2、工具箱尝试采用模块化设计,包含正则、Rolan+、AI+三个模块,代码写得随意,师傅们请见谅
26 |
27 | 3、感谢师傅们的星星,如果有BUG、有建议,交流学习欢迎师傅们滴滴
28 |
29 | 
30 |
31 |
32 | ## link-tools v1.2工具箱更新:
33 |
34 | 1、Deepseek官方API接口更新,同步新增自定义模型(原deepseek-chat为V3模型,deepseek-reasoner为R1模型)
35 |
36 | 2、新增工具箱配置,允许自定义修改工具箱首页模块。
37 |
38 | 3、其他说明:
39 |
40 | -- 由于流式输出,超时功能可能会失效,可自行中止。
41 |
42 | -- 经测试可支持腾讯云API,对应修改key、api、model即可,其他厂商API自行测试。
43 |
44 | 
45 | 
46 |
47 |
48 | ## link-tools v1.1工具箱更新:
49 | 1、新增AI+模块,支持3种模型连接方式(Deepseek Api、Siliconflow Api和Ollama本地部署接入),目前R1模型的Api不稳定,可以使用V3模型,效果也不错。
50 |
51 | 2、支持提示词自定义增删查改,可随时中止AI进行修改和完善提示词。
52 |
53 | 3、内置多条提示词(来自ChinaRan404师傅的DeepSeekSelfTool项目,超强)。
54 |
55 | 4、AI+模块代码由Deepseek R1生成。
56 |
57 | 5、Rolan+模块修复已知BUG,去除工具灰色标记代码。
58 |
59 | 
60 | 
61 | 
62 |
63 | ## link-tools工具箱
64 |
65 | link-tools为一款Windows GUI界面的渗透测试工具箱(仿rolan启动器),支持拖拉新增工具(脚本、文件夹),支持自定义运行参数和备注,支持bat批量运行脚本,支持RapidScanner端口扫描结果服务指纹联动工具,可协助安全运维人员快速运行工具(脚本、文件夹),提高安全检测效率。
66 | 
67 | ## 使用方法:
68 |
69 | ### 1. 工具添加:
70 |
71 | **右键新建分组,拖拉新增工具**
72 |
73 | #### 1.1 分组栏支持:
74 |
75 | - 拖拉排序、刷新、新增、重命名、删除
76 |
77 | #### 1.2 工具栏支持:
78 |
79 | - 拖拉新增工具(文件夹)、拖拉排序、双击打开、右键打开、打开目录、刷新、新增、重命名、删除、配置文件、移动分组
80 |
81 | 
82 |
83 | ### 2. 参数配置:
84 |
85 | **点击工具(脚本)激活参数栏,填写工具(脚本)启动参数,保存参数。**
86 |
87 | #### 2.1 示例:
88 |
89 | python3 tool.py -f [file] -o [log]
90 |
91 | python2 tool.py -i [ip] -p [port]
92 |
93 | tool.exe -l [target]
94 |
95 | #### 2.2 数据参数说明:
96 |
97 | [file]: -f [file] ,数据写入一个临时文件,由工具运行
98 |
99 | [ip] [port]: -ip [ip] -p [port] ,数据按':'进行分割,并逐行(批量)运行
100 |
101 | [target]: -u [target] ,数据无处理,并逐行(批量)运行
102 |
103 | [log]: -o [log] ,统一格式和位置:[logpath]/log-[tool_name]-[date].txt(当使用[log]时[输出/日志]按钮打开统一位置,否则为工具所在目录)
104 |
105 | [date]:当前时间
106 |
107 | [logpath]:统一位置
108 |
109 | 
110 |
111 | ### 3. 工具启动
112 |
113 | 图形化工具:支持双击运行、右键打开运行
114 |
115 | 脚本工具(带参数):选择要运行的命令,使用【启动/运行】按钮运行
116 | 
117 |
118 | ### 4. RapidScanner工具联动
119 |
120 | 支持导入处理RapidScanner扫描结果scan_result.txt数据,并输出处理结果到文件夹
121 |
122 | #### 4.1 扫描数据
123 | 
124 |
125 |
126 | #### 4.2 导入数据
127 | 
128 |
129 | **处理后的端口数据保存到result目录下,二次导入数据可使用文件夹方式导入**
130 |
131 | 
132 | #### 4.3 展示数据
133 | 
134 |
135 |
136 | #### 4.4 工具联动
137 | 常用工具提前配置**服务类型**,选中数据时**展示工具快捷入口**,点击工具可**快速加载工具启动参数**数据。
138 | 
139 |
140 | ### 5. 使用示例
141 |
142 | 可快速联动各种工具,一键运行,提高效率。
143 | 
144 |
145 | ### 6. 正则小工具
146 |
147 | 支持快速生成和匹配简单正则表达式,处理数据。支持自定义常用表达式,配置文件config/正则.txt
148 | 
149 |
150 | ## 其他说明:
151 |
152 | 1、工具名称灰色问题:出于工具箱迁移考虑,非link-tools工具箱目录下的工具标记灰色。
153 |
154 | 2、工具编写:基于python3.7+pyqt5,启动器通过生成bat方式运行(可脱离工具箱运行),个人编写的小工具,欢迎提出建议。
155 |
--------------------------------------------------------------------------------
/config/Data+.txt:
--------------------------------------------------------------------------------
1 | {"\u793a\u4f8b\u5206\u7ec4": {"\u53c2\u6570\u6f14\u793a": {"Path": "[toolpath]\\config\\Data+.txt","config_1": "echo python3 tool.py -f [file] -o [log]","config_2": "echo python2 tool.py -i [ip] -p [port]","config_3": "echo tool.exe -l [target]","tool_key": "first","tool_tip": "\u4f7f\u7528echo\u6f14\u793abat\u542f\u52a8\u6548\u679c\uff08\u66f4\u591a\u53c2\u6570\u70b9\u51fb\u8bf4\u660e\u6309\u94ae\u67e5\u770b\uff09","tool_service": "\u670d\u52a1\u7c7b\u578b"},"RapidScanner": {"Path": "[toolpath]\\tools\\RapidScanner.exe","config_1": "1\u3001\u5de5\u5177\u652f\u6301\u62d6\u62c9\u65b0\u589e\u6216\u8005\u53f3\u952e\u65b0\u589e","config_2": "2\u3001\u652f\u6301\u4e09\u6761\u81ea\u5b9a\u4e49\u542f\u52a8\u547d\u4ee4","config_3": "3\u3001\u901a\u8fc7\u8fd0\u884cbat\u65b9\u5f0f\u6267\u884c\u542f\u52a8\u547d\u4ee4","tool_key": "first","tool_tip": "\u652f\u6301\u76f4\u63a5\u53cc\u51fb\u6253\u5f00\uff0c\u53f3\u952e\u6253\u5f00,\u6309\u94ae\u6253\u5f00\uff08\u9700\u547d\u4ee4\u7f6e\u7a7a\uff09","tool_service": "\u670d\u52a1\u7c7b\u578b"}}}
2 |
--------------------------------------------------------------------------------
/config/finger/finger.ini:
--------------------------------------------------------------------------------
1 | {"JavaRMI":"JavaRMI"}
2 | {"Microsoft Windows RPC":"msrcp"}
3 | {"ajp13":"ajp13"}
4 | {"bgp":"bgp"}
5 | {"dns":"dns"}
6 | {"dtspcd":"dtspcd"}
7 | {"elasticsearch":"elasticsearch"}
8 | {"ftp":"ftp"}
9 | {"http":"http"}
10 | {"ibm-db2":"ibm-db2"}
11 | {"imap":"imap"}
12 | {"intersys-cache":"intersys-cache"}
13 | {"jabber":"jabber"}
14 | {"jdwp":"jdwp"}
15 | {"ldap":"ldap"}
16 | {"ldp":"ldp"}
17 | {"lotusnotes":"lotusnotes"}
18 | {"lpd":"lpd"}
19 | {"memcached":"memcached"}
20 | {"microsoft-ds":"smb"}
21 | {"mongodb":"mongodb"}
22 | {"ms-sql-s":"mssql"}
23 | {"msrcp":"msrcp"}
24 | {"mssql":"mssql"}
25 | {"mysql":"mysql"}
26 | {"netbios-ssn":"netbios"}
27 | {"nfs":"nfs"}
28 | {"nullpacket":"nullpacket"}
29 | {"oracle":"oracle"}
30 | {"pcanywhere":"pcanywhere"}
31 | {"pop":"pop"}
32 | {"postgresql":"postgresql"}
33 | {"radmin":"radmin"}
34 | {"rdp":"rdp"}
35 | {"redis":"redis"}
36 | {"rpcbind":"msrcp"}
37 | {"rsync":"rsync"}
38 | {"rtsp":"rtsp"}
39 | {"sip":"sip"}
40 | {"smtp":"smtp"}
41 | {"sqlserver":"mssql"}
42 | {"ssh":"ssh"}
43 | {"ssl":"http"}
44 | {"ssl/tls":"http"}
45 | {"svn":"svn"}
46 | {"svrloc":"svrloc"}
47 | {"teamviewer":"teamviewer"}
48 | {"telnet":"telnet"}
49 | {"vmware-auth":"vmware"}
50 | {"vnc":"vnc"}
51 | {"vpn-pptp":"vpn-pptp"}
52 | {"xmpp":"xmpp"}
53 | {"FULLSCANTOOL":"ip_all"}
--------------------------------------------------------------------------------
/config/finger/finger_diy.ini:
--------------------------------------------------------------------------------
1 | {"whitelist":"zookeeper"}
2 | {"Zookeeper":"zookeeper"}
3 | {"WebLogic":"http-weblogic"}
4 | {"weblogic":"http-weblogic"}
5 | {"IIS":"http-iis"}
6 | {"Verification failure":"http-sunlogin"}
7 | {"C-Lodop":"http-c-lodop"}
8 | {"dhvideowhmode":"http-dahua"}
9 | {"tomcat":"http-tomcat"}
--------------------------------------------------------------------------------
/config/finger/finger_port.ini:
--------------------------------------------------------------------------------
1 | {":80":"http"}
2 | {":443":"http"}
3 | {":8080":"http"}
4 | {":22":"ssh"}
5 | {":3389":"rdp"}
6 | {":445":"smb"}
7 | {":139":"smb"}
8 | {":3306":"mysql"}
9 | {":1433":"sqlserver"}
10 | {":1521":"oracle"}
11 | {":21":"ftp"}
12 | {":27017":"mongodb"}
13 | {":27018":"mongodb"}
14 | {":11211":"memcached"}
15 | {":5432":"postgresql"}
16 | {":23":"telnet"}
17 | {":6379":"redis"}
18 | {":25":"smtp"}
19 | {":110":"pop"}
20 | {":135":"msrcp"}
21 | {":53":"dns"}
22 | {":4899":"radmin"}
23 | {":143":"imap"}
24 | {":161":"snmp"}
--------------------------------------------------------------------------------
/config/ico/java.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lintx0/link-tools/8b146616106348ee16da0541204468deac94d662/config/ico/java.ico
--------------------------------------------------------------------------------
/config/ico/link.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lintx0/link-tools/8b146616106348ee16da0541204468deac94d662/config/ico/link.ico
--------------------------------------------------------------------------------
/config/ico/python.ico:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lintx0/link-tools/8b146616106348ee16da0541204468deac94d662/config/ico/python.ico
--------------------------------------------------------------------------------
/config/提示词.md:
--------------------------------------------------------------------------------
1 | ### AI对话
2 | ```
3 | [输入1]
4 | ```
5 |
6 | ### AI代码审计1
7 |
8 | ```
9 | 你是一个代码审计专家用来辅助我判断代码有没有安全漏洞,你的职责是判断我给你的漏洞有没有可控点,我只会给你代码你只需要回答,存在漏洞,不存在漏洞,以及无法判断,不需要解释!!!,不需要你给出修复 防止 等等建议只需要回答,存在漏洞,不存在漏洞,以及无法判断这几个选择。
10 | 需判断代码如下:
11 | [输入1]
12 | ```
13 |
14 | ### AI代码审计2
15 |
16 | ```
17 | 【强制指令】你是一个专业的安全审计AI,请按以下要求分析代码:
18 |
19 | 1. 漏洞分析流程:
20 | 1.1 识别潜在风险点(SQL操作、文件操作、用户输入点、文件上传漏洞、CSRF、SSRF、XSS、RCE、OWASP top10等漏洞)
21 | 1.2 验证漏洞可利用性
22 | 1.3 按CVSS评分标准评估风险等级
23 |
24 | 2. 输出规则:
25 | - 仅输出确认存在的高危/中危漏洞
26 | - 使用严格格式:[风险等级] 类型 - 代码类型:位置行号 - 50字内描述
27 | - 禁止解释漏洞原理
28 | - 禁止给出修复建议
29 | - 每文件最多报告3个最严重问题
30 |
31 | 3. 输出示例(除此外不要有任何输出):
32 | [高危] SQL注入 - .php:32 - 未过滤的$_GET参数直接拼接SQL查询
33 | [中危] XSS - .jsp:15 - 未转义的userInput输出到HTML
34 |
35 | 4. 当前代码(仅限分析):
36 | [输入1]
37 | ```
38 |
39 | ### WEBSHELL检测1
40 |
41 | ```
42 | 【Webshell检测指令】请严格按以下步骤分析代码:
43 |
44 | 1. 检测要求:
45 | 请分析以下文件内容是否为WebShell或内存马。要求:
46 | 1. 检查PHP/JSP/ASP等WebShell特征(如加密函数、执行系统命令、文件操作)
47 | 2. 识别内存马特征(如无文件落地、进程注入、异常网络连接)
48 | 3. 分析代码中的可疑功能(如命令执行、文件上传、信息收集)
49 | 4. 检查混淆编码、加密手段等规避技术
50 |
51 | 2. 判断规则:
52 | - 仅当确认恶意性时报告
53 | - 输出格式:🔴 [高危] Webshell - 代码类型:位置行号 - 检测到[特征1+特征2+...]
54 |
55 | 3. 输出示例(严格按照此格式输出,不要有任何的补充,如果未检测到危险,则不输出,除此之外,不要有任何输出):
56 | 🔴 [高危] Webshell - .php:8 - 检测到[system执行+base64解码+错误抑制]
57 |
58 | 4. 待分析代码:
59 | [输入1]
60 | ```
61 |
62 | ### WEBSHELL检测2
63 |
64 | ```
65 | 请分析以下文件内容是否为WebShell或内存马。要求:
66 | 1. 检查PHP/JSP/ASP等WebShell特征(如加密函数、执行系统命令、文件操作)
67 | 2. 识别内存马特征(如无文件落地、进程注入、异常网络连接)
68 | 3. 分析代码中的可疑功能(如命令执行、文件上传、信息收集)
69 | 4. 检查混淆编码、加密手段等规避技术
70 | 5. 最终结论:是否为恶意软件(是/否)
71 |
72 | 请用中文按以下格式响应:
73 | 【分析结果】是/否
74 | 【恶意类型】WebShell/内存马/其他
75 | 【技术特征】列出检测到的技术指标
76 | 【风险等级】高/中/低
77 |
78 | 文件内容:
79 | [输入1]
80 | ```
81 |
82 | ### HTTP流量分析
83 |
84 | ```
85 | 请进行网络安全分析。请严格按照以下步骤执行:
86 | 1. 分析以下HTTP请求的各个组成部分
87 | 2. 识别是否存在SQL注入、XSS、CSRF、反序列化、文件上传、路径遍历、OWASPTop10、等常见攻击特征
88 | 3. 检查User-Agent等头部信息是否可疑
89 | 4. 最终结论:是否为攻击流量(是/否)
90 |
91 | 请用中文按以下格式响应:
92 | 【分析结果】是/否
93 | 【依据】简明扼要列出技术依据
94 |
95 | HTTP请求数据:
96 | [输入1]
97 | ```
98 |
99 | ### 编码分析
100 |
101 | ```
102 | 请完整分析并解码以下字符串,要求:
103 | 1. 识别所有可能的编码方式(包括嵌套编码)
104 | 2. 通过自己重新编码,确认自己解码正确
105 | 3. 展示完整的解码过程
106 | 4. 输出最终解码结果
107 |
108 | 原始字符串:[输入1]
109 |
110 | 请用中文按以下格式响应:
111 | 【编码分析】列出检测到的编码类型及层级
112 | 【解码过程】逐步展示解码步骤
113 | 【最终结果】解码后的明文内容
114 | ```
115 |
116 | ### 进程分析
117 |
118 | ```
119 | 你是一个Windows/Linux进程分析工程师,要求:
120 | 1. 用户将输出tasklist或者ps aux的结果
121 | 2. 帮助用户分析输出你所有认识的进程信息
122 | 3. 识别可能的恶意进程
123 | 4. 识别杀毒软件进程
124 | 5. 识别其他软件进程
125 |
126 | tasklist或者ps aux的结果:[输入1]
127 |
128 | 按优先级列出需要关注的进程
129 | 【可疑进程】
130 | 【杀软进程】
131 | 【第三方软件进程】
132 | 给出具体操作建议:
133 | • 安全进程的可终止性评估
134 | ```
135 |
136 | ### JavaScript分析
137 |
138 | ```
139 | 请对以下JavaScript代码进行完整的安全审计,要求:
140 | 1. 识别XSS、CSRF、不安全的DOM操作、敏感信息泄露、eval使用等安全问题
141 | 2. 检查第三方库的安全性和版本漏洞
142 | 3. 分析代码逻辑漏洞
143 | 4. 提供修复建议
144 |
145 | 请用中文按以下格式响应:
146 | 【高危漏洞】列出高危安全问题及位置
147 | 【中低危问题】列出中低风险问题
148 | 【修复建议】提供具体修复方案
149 |
150 | JavaScript代码:
151 | [输入1]
152 | ```
153 |
154 | ### HTTP转Python
155 |
156 | ```
157 | 你是一个专业Python开发助手,请将以下HTTP请求转换为规范的Python代码(使用requests库)。按以下步骤处理:
158 | 要求:
159 | 1.用户输入:完整请求头(包含Content-Type和Authorization)
160 | 2.用户输入:完整的请求题(包含请求方法、URL和参数)
161 | 3.用户输入:请求体的内容(如果有)
162 | 4.默认不进行SSL验证
163 | 5.输出:完整的Python代码,包含请求头、请求体和请求方法
164 |
165 | 请用中文按以下格式响应:
166 | 【Python代码】输出转换后的Python代码,不使用markdown格式,不要有其他多余的输出
167 |
168 | 这是用户输入的内容:
169 | [输入1]
170 | ```
171 |
172 | ### 文本格式转换
173 |
174 | ```
175 | 写python代码,请根据提供的样本格式,将源文本转换为与样本相同的格式。要求:
176 | 1. 分析样本文本的结构和格式特征
177 | 2. 保持源文本的核心内容不变
178 | 3. 按照样本的格式要求重新组织内容
179 | 4. 确保转换后的文本与样本格式完全一致
180 | 5.最后输出转换两文本的python代码脚本,不要有其他多余的输出。
181 |
182 | 样本文本:
183 | [输入1]
184 |
185 | 源文本:
186 | [输入2]
187 |
188 | 请直接输出python脚本,不要包含任何解释或说明。不使用markdown格式
189 | ```
190 |
191 | ### 正则表达式生成
192 |
193 | ```
194 | 请根据提供的样本格式,通过源文本生成正则表达式为与样本相同的内容。要求:
195 | 1. 分析样本文本的结构和格式特征
196 | 2. 保持源文本的核心内容不变
197 | 3. 生成多个正则表达式
198 | 4. 保证可以通过正则表达式匹配到样本文件中的内容
199 |
200 | 样本文本:
201 | [输入1]
202 |
203 | 源文本:
204 | [输入2]
205 |
206 | 请直接输出生成的多个正则表达式,不要包含任何解释或说明,不要使用markdown格式输出
207 | ```
208 |
209 | ### 语言翻译
210 |
211 | ```
212 | 请将以下待翻译文本专业地翻译成中文。要求:
213 | 1. 保持技术术语准确性(特别是网络安全相关词汇)
214 | 2. 保留代码格式和变量名
215 | 3. 正确处理专业缩写(如XSS、SQLi等)
216 | 4. 输出仅需翻译结果,无需额外说明
217 |
218 | 待翻译文本:
219 | [输入1]
220 | ```
221 |
222 |
--------------------------------------------------------------------------------
/config/正则.txt:
--------------------------------------------------------------------------------
1 | PWD1<--->(?<="password":")(.+?)(?=")
2 | IP1<--->\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}
3 | IP2<--->['"]\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}['"]
4 | IP_PORT1<--->\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d+
5 | IP_PORT2<--->['"]\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d+['"]
6 | SFZ1<--->\d{14}[0-9a-zA-Z]{4}
7 | SFZ2<--->['"]\d{14}[0-9a-zA-Z]{4}['"]
8 | MOBILE1<--->[1][3,4,5,6,7,8,9][0-9]{9}
9 | MOBILE2<--->['"][1][3,4,5,6,7,8,9][0-9]{9}['"]
10 | WEB日志去杂<--->.*\.js .*|.*\.svg .*|.*\.css .*|.*\.png .*|.*\.jpg .*|.*\.jpeg .*|.*\.woff .*|.*\.woff2 .*|.*\.gif .*|.*getVerifyCode .*|.*\.ico .*
11 | JS文件提取参数<--->\w+(?=:\w+\.\w+)|(?<=params:\{)(.+?)(?=\})
12 | 换行→逗号<--->\n<--->,
13 | 逗号→换行<--->,<--->\n
14 | 换行→顿号<--->\n<--->、
15 | 顿号→换行<--->、<--->\n
16 | 换行→实体<--->\n<--->\\n
17 | 实体→换行<--->\\n<--->\n
--------------------------------------------------------------------------------
/link-tools-v1.3.py:
--------------------------------------------------------------------------------
1 | #-- coding:UTF-8 --
2 | # Author:lintx
3 | # Date:2025/02/10
4 | import sys,os
5 | from PyQt5.QtCore import Qt,QSettings
6 | from PyQt5.QtWidgets import QApplication, QMainWindow,QMessageBox
7 | from tabs.ui_main import Ui_Form
8 | from tabs import tab_zz,tab_rolan,tab_ai
9 |
10 |
11 | class MyMainForm(QMainWindow, Ui_Form):
12 | def __init__(self, parent=None):
13 | super(MyMainForm, self).__init__(parent)
14 | self.setupUi(self)
15 | # -------------------------------------------功能加载-------------------------------------------------
16 | #正则
17 | self.tab_zz = tab_zz.tab_zz(self)
18 | # Rolan
19 | self.tab_rolan = tab_rolan.tab_rolan(self)
20 | # Ai
21 | self.tab_ai = tab_ai.tab_ai(self)
22 |
23 | #tab数据加载
24 | self.tabs_button.clicked.connect(self.tabs_save)
25 | tabs_names = [self.tabWidget.tabText(i) for i in range(self.tabWidget.count())]
26 | self.tabs_combox.addItems(tabs_names)
27 | tabs_settings = QSettings("link_tools", "AI")
28 | tabs_cname = tabs_settings.value("tabs_cname", "Rolan+")
29 | self.tabs_combox.setCurrentText(tabs_cname)
30 | self.tabWidget.setCurrentIndex(self.tabs_combox.currentIndex())
31 | try:
32 | self.tabread()
33 | self.tabWidget.currentChanged.connect(self.tabread)
34 | except Exception as e:
35 | QMessageBox.about(self, "错误", f"配置文件缺失,请检查config目录{e}")
36 | exit()
37 |
38 | #self.rolan_list_4.setVisible(False)
39 |
40 | # -------------------------------------------数据读取-------------------------------------------------
41 | def tabread(self):
42 | os.chdir(pwd)
43 | tabs_text=self.tabWidget.tabText(self.tabWidget.currentIndex())
44 | if tabs_text=='正则':
45 | self.tab_zz.zhengze_list()
46 | elif tabs_text == 'Rolan+':
47 | if self.tab_rolan.ui.rolan_list_1.count() ==0:
48 | self.tab_rolan.read_data('')
49 | def tabs_save(self):
50 | tabs_settings = QSettings("link_tools", "AI")
51 | tabs_cname = self.tabs_combox.currentText()
52 | tabs_settings.setValue("tabs_cname",tabs_cname)
53 | QMessageBox.information(self, "提示", "配置保存成功!")
54 |
55 | if __name__ == "__main__":
56 | QApplication.setAttribute(Qt.AA_EnableHighDpiScaling)
57 | QApplication.setAttribute(Qt.AA_UseHighDpiPixmaps)
58 | app = QApplication(sys.argv)
59 | pwd = os.getcwd()
60 | myWin = MyMainForm()
61 | myWin.show()
62 | sys.exit(app.exec_())
--------------------------------------------------------------------------------
/requirements.txt:
--------------------------------------------------------------------------------
1 | PyQt5
2 | openai
3 | xlsxwriter
4 | requests
--------------------------------------------------------------------------------
/tabs/tab_ai.py:
--------------------------------------------------------------------------------
1 | #-- coding:UTF-8 --
2 | # Author:lintx
3 | # Date:2025/02/20
4 | import re,json,time,requests
5 | from PyQt5.QtCore import QThread, pyqtSignal, QTimer, QSettings
6 | from PyQt5.QtWidgets import QMessageBox, QInputDialog
7 | from PyQt5.QtGui import QTextCursor
8 | from openai import OpenAI
9 |
10 | class Worker(QThread):
11 | # AI调用模块,实现会话功能
12 | response_received = pyqtSignal(str, bool)
13 | error_occurred = pyqtSignal(str)
14 |
15 | def __init__(self, config, prompt, user_input,user_input_1):
16 | super().__init__()
17 | self.config = config
18 | self.prompt = prompt.replace("[输入1]", user_input).replace("[输入2]", user_input_1)
19 | self._is_running = True
20 |
21 | def run(self):
22 | try:
23 | if self.config.get('api_key'):
24 | self.call_openai_api()
25 | else:
26 | self.call_ollama()
27 | except Exception as e:
28 | self.error_occurred.emit(str(e))
29 |
30 | def stop(self):
31 | self._is_running = False
32 | self.terminate()
33 |
34 | def call_openai_api(self):
35 | try:
36 | client = OpenAI(
37 | api_key=self.config["api_key"],
38 | base_url=self.config["api_base"],
39 | timeout=my_timeout
40 | )
41 | stream = client.chat.completions.create(
42 | model=self.config["model"],
43 | messages=[{"role": "user", "content": self.prompt}],
44 | stream=True
45 | )
46 | for chunk in stream:
47 | if not self._is_running:
48 | break
49 | content = chunk.choices[0].delta.content or ""
50 | self.response_received.emit(content, False)
51 |
52 | self.response_received.emit('\n\n', True)
53 | except Exception as e:
54 | self.error_occurred.emit(f"API请求失败: {str(e)}")
55 |
56 | def call_ollama(self):
57 | data = {
58 | "model": self.config["model"],
59 | "prompt": self.prompt,
60 | "stream": True
61 | }
62 |
63 | try:
64 | with requests.post(
65 | self.config["api_base"],
66 | json=data,
67 | stream=True,
68 | timeout=my_timeout
69 | ) as response:
70 | response.raise_for_status()
71 | if response.status_code == 200:
72 | for line in response.iter_lines():
73 | if not self._is_running:
74 | break
75 | if line:
76 | try:
77 | chunk = json.loads(line)
78 | delta = chunk.get("response", "")
79 | self.response_received.emit(delta, False)
80 | except Exception as e:
81 | print(e)
82 | continue
83 |
84 | self.response_received.emit('', True)
85 |
86 | except Exception as e:
87 | self.error_occurred.emit(f"Ollama连接失败: {str(e)}")
88 |
89 | class tab_ai():
90 | def __init__(self, ui):
91 | super().__init__()
92 | self.ui = ui
93 | self.prompts = {}
94 | self.thinking_start = None
95 | self.configs = {}
96 | self.init_ui()
97 | self.load_prompts()
98 | self.load_configs()
99 |
100 | def init_ui(self):
101 | self.is_running = False
102 | self.ui.send_btn.clicked.connect(self.toggle_ai_process)
103 | self.ui.prompt_combo.currentTextChanged.connect(self.update_prompt)
104 | self.ui.prompt_combo_1.currentTextChanged.connect(self.update_prompt_1)
105 | self.ui.refresh_btn.clicked.connect(self.load_prompts)
106 | self.ui.new_btn.clicked.connect(self.new_prompt)
107 | self.ui.delete_btn.clicked.connect(self.delete_prompt)
108 | self.ui.save_prompt_btn.clicked.connect(self.save_prompt)
109 | self.ui.prompt_edit.textChanged.connect(self.hide_input)
110 | self.ui.input_edit.textChanged.connect(self.input_size)
111 | self.ui.input_edit_1.textChanged.connect(self.input_size_1)
112 | self.ui.config_combo.currentTextChanged.connect(self.update_config)
113 | self.ui.config_combo_1.currentTextChanged.connect(self.update_config_1)
114 | self.ui.new_config_btn.clicked.connect(self.new_config)
115 | self.ui.save_config_btn.clicked.connect(self.save_config)
116 | self.ui.del_config_btn.clicked.connect(self.del_config)
117 | self.ui.refresh_btn_2.clicked.connect(self.refresh_config)
118 | self.ui.config_combo.currentIndexChanged.connect(self.load_config)
119 | self.timer = QTimer()
120 | self.timer.timeout.connect(self.update_time)
121 |
122 | # 交互功能实现
123 | def input_size(self):
124 | size=len(self.ui.input_edit.toPlainText())
125 | self.ui.label_input1.setText(f'[输入1] {size} tokens')
126 | def input_size_1(self):
127 | size=len(self.ui.input_edit_1.toPlainText())
128 | self.ui.label_input2.setText(f'[输入2] {size} tokens')
129 |
130 | def toggle_ai_process(self):
131 | if self.is_running:
132 | self.handle_interrupt()
133 | else:
134 | self.on_send()
135 |
136 | def hide_input(self):
137 | text = self.ui.prompt_edit.toPlainText()
138 | if '[输入1]' in text:
139 | self.ui.input_edit.setEnabled(True)
140 | else:
141 | self.ui.input_edit.setEnabled(False)
142 | if '[输入2]' in text:
143 | self.ui.input_edit_1.setEnabled(True)
144 | else:
145 | self.ui.input_edit_1.setEnabled(False)
146 |
147 | def handle_interrupt(self):
148 | if hasattr(self, 'worker'):
149 | self.worker.stop()
150 | self.cleanup_after_interrupt()
151 | self.ui.output_area.append("=== 用户中止 ===")
152 |
153 | def cleanup_after_interrupt(self):
154 | self.timer.stop()
155 | self.ui.send_btn.setText("AI分析和处理")
156 | self.ui.send_btn.setStyleSheet("")
157 | self.is_running = False
158 | self.thinking_start = None
159 |
160 | def update_time(self):
161 | if self.thinking_start:
162 | elapsed = time.time() - self.thinking_start
163 | self.ui.send_btn.setText(f"中止({elapsed:.2f}s)")
164 |
165 | def handle_error(self, error_msg):
166 | self.timer.stop()
167 | self.ui.output_area.append(f"\n[错误] {error_msg}")
168 | self.ui.send_btn.setEnabled(True)
169 | self.thinking_start = None
170 | self.ui.send_btn.setText("AI分析和处理")
171 | self.ui.send_btn.setStyleSheet("")
172 | self.is_running = False
173 |
174 | def update_response(self, delta, finished):
175 | try:
176 | if not self.is_running:
177 | return
178 | processed = delta.replace('', '[思考]').replace('', '[/思考]')
179 | self.ui.output_area.moveCursor(QTextCursor.End)
180 | self.ui.output_area.insertPlainText(processed)
181 |
182 | if finished:
183 | self.cleanup_after_interrupt()
184 | self.ui.output_area.append("=== 回答结束 ===")
185 | self.ui.output_area.moveCursor(QTextCursor.End)
186 | except Exception as e:
187 | print(e)
188 |
189 | def on_send(self):
190 | global my_timeout
191 | my_timeout = int(self.ui.timeout_input.text())
192 |
193 | if self.ui.input_edit.toPlainText() == '' and self.ui.input_edit.isEnabled() == True:
194 | QMessageBox.critical(self.ui, "错误", f"输入框1,未输入数据")
195 | return
196 | if self.ui.input_edit_1.toPlainText() == '' and self.ui.input_edit_1.isEnabled() == True:
197 | QMessageBox.critical(self.ui, "错误", f"输入框2,未输入数据")
198 | return
199 | if self.is_running: # 如果正在运行则执行中止
200 | self.handle_interrupt()
201 | return
202 |
203 | self.is_running = True
204 | self.ui.send_btn.setText("中止(0.00s)")
205 | self.ui.send_btn.setStyleSheet("background-color: grey;")
206 | prompt = self.ui.prompt_edit.toPlainText()
207 | size_emit = int(self.ui.size_emit.text())
208 | user_input = self.ui.input_edit.toPlainText().strip()[:size_emit]
209 | user_input_1 = self.ui.input_edit_1.toPlainText().strip()[:size_emit]
210 | if not prompt or not user_input:
211 | return
212 |
213 | self.ui.output_area.clear()
214 | self.thinking_start = time.time()
215 | self.timer.start(100)
216 |
217 | self.config = {
218 | "name": self.ui.config_combo.currentText(),
219 | "api_base": self.ui.conf_api_base.text(),
220 | "api_key": self.ui.conf_api_key.text(),
221 | "model": self.ui.conf_model.text()
222 | }
223 |
224 | self.worker = Worker(self.config, prompt, user_input,user_input_1)
225 | self.worker.response_received.connect(self.update_response)
226 | self.worker.error_occurred.connect(self.handle_error)
227 | self.worker.start()
228 |
229 | prompt_combo = self.ui.prompt_combo_1.currentText()
230 | model_combo = self.ui.config_combo.currentText()
231 | self.ui.output_area.append(f"[运行参数] Timeout:{my_timeout} | Size:{size_emit} | Prompt:{prompt_combo} | Model:{model_combo}\n")
232 |
233 | # 提示词功能实现
234 | def load_prompts(self):
235 | try:
236 | with open("config/提示词.md", "r", encoding="utf-8") as f:
237 | content = f.read()
238 | pattern = r"### (.*?)```(.*?)```"
239 | matches = re.findall(pattern, content, re.DOTALL)
240 | self.prompts = {title.strip(): prompt.strip() for title, prompt in matches}
241 | self.ui.prompt_combo.clear()
242 | self.ui.prompt_combo.addItems(self.prompts.keys())
243 | if self.prompts:
244 | self.ui.prompt_combo.setCurrentIndex(0)
245 | self.ui.prompt_combo_1.clear()
246 | self.ui.prompt_combo_1.addItems(self.prompts.keys())
247 | if self.prompts:
248 | self.ui.prompt_combo_1.setCurrentIndex(0)
249 | except Exception as e:
250 | print(e)
251 | QMessageBox.critical(self.ui, "错误", f"加载提示词失败: {str(e)}")
252 |
253 | def update_prompt(self):
254 | title = self.ui.prompt_combo.currentText()
255 | self.ui.prompt_edit.setPlainText(self.prompts.get(title, ""))
256 | self.ui.prompt_combo_1.setCurrentText(title)
257 |
258 | def update_prompt_1(self):
259 | title = self.ui.prompt_combo_1.currentText()
260 | self.ui.prompt_edit.setPlainText(self.prompts.get(title, ""))
261 | self.ui.prompt_combo.setCurrentText(title)
262 |
263 | def update_config(self):
264 | title = self.ui.config_combo.currentText()
265 | self.ui.config_combo_1.setCurrentText(title)
266 |
267 | def update_config_1(self):
268 | title = self.ui.config_combo_1.currentText()
269 | self.ui.config_combo.setCurrentText(title)
270 |
271 | def new_prompt(self):
272 | title, ok = QInputDialog.getText(self.ui, "新增提示词", "请输入提示词标题:")
273 | if ok and title:
274 | content, ok = QInputDialog.getMultiLineText(self.ui, "新增提示词", "请输入提示词内容:")
275 | if ok and content:
276 | self.prompts[title] = content
277 | self.save_prompts_to_file()
278 | self.load_prompts()
279 | self.ui.prompt_combo.setCurrentText(title)
280 |
281 | def delete_prompt(self):
282 | current_title = self.ui.prompt_combo.currentText()
283 | if not current_title:
284 | return
285 | confirm = QMessageBox.question(
286 | self.ui,
287 | "确认删除",
288 | f"确定要删除提示词【{current_title}】吗?",
289 | QMessageBox.Yes | QMessageBox.No
290 | )
291 | if confirm == QMessageBox.Yes:
292 | del self.prompts[current_title]
293 | self.save_prompts_to_file()
294 | self.load_prompts()
295 |
296 | def save_prompt(self):
297 | current_title = self.ui.prompt_combo.currentText()
298 | new_content = self.ui.prompt_edit.toPlainText()
299 | if current_title and new_content:
300 | self.prompts[current_title] = new_content
301 | self.save_prompts_to_file()
302 | QMessageBox.information(self.ui, "提示", "提示词保存成功!")
303 |
304 | def save_prompts_to_file(self):
305 | try:
306 | content = ""
307 | for title, prompt in self.prompts.items():
308 | content += f"### {title}\n```\n{prompt}\n```\n\n"
309 | with open("config/提示词.md", "w", encoding="utf-8") as f:
310 | f.write(content)
311 | except Exception as e:
312 | print(e)
313 | QMessageBox.critical(self.ui, "错误", f"保存提示词失败: {str(e)}")
314 |
315 | #AI配置功能实现
316 | def load_configs(self, preserve_selection=None):
317 | settings = QSettings("config/config_ai.ini", QSettings.IniFormat)
318 | self.configs = {}
319 |
320 | sections = settings.childGroups()
321 | for section in sections:
322 | settings.beginGroup(section)
323 | self.configs[section] = {
324 | "api_base": settings.value("api_base", ""),
325 | "api_key": settings.value("api_key", ""),
326 | "model": settings.value("model", "")
327 | }
328 | settings.endGroup()
329 |
330 | if not self.configs:
331 | self.ui.config_combo.clear()
332 | self.ui.config_combo_1.clear()
333 | return
334 |
335 | current_index = self.ui.config_combo.currentIndex()
336 | self.ui.config_combo.clear()
337 | self.ui.config_combo.addItems(self.configs.keys())
338 | self.ui.config_combo_1.clear()
339 | self.ui.config_combo_1.addItems(self.configs.keys())
340 | if preserve_selection:
341 | new_index = self.ui.config_combo.findText(preserve_selection)
342 | self.ui.config_combo.setCurrentIndex(new_index if new_index != -1 else 0)
343 | elif current_index >= 0:
344 | self.ui.config_combo.setCurrentIndex(min(current_index, self.ui.config_combo.count() - 1))
345 |
346 | def save_configs(self):
347 | settings = QSettings("config/config_ai.ini", QSettings.IniFormat)
348 | # 清空旧配置
349 | settings.clear()
350 | for name, config in self.configs.items():
351 | settings.beginGroup(name)
352 | settings.setValue("api_base", config["api_base"])
353 | settings.setValue("api_key", config["api_key"])
354 | settings.setValue("model", config["model"])
355 | settings.endGroup()
356 |
357 | def new_config(self):
358 | name, ok = QInputDialog.getText(self.ui, "新建配置", "配置名称:")
359 | if ok and name:
360 | self.configs[name] = {
361 | "api_base": "http://localhost:11434/api/generate",
362 | "api_key": "",
363 | "model": "deepseek-r1:1.5b"
364 | }
365 | self.save_configs()
366 | self.load_configs()
367 | self.ui.config_combo.setCurrentText(name)
368 |
369 | def save_config(self):
370 | name = self.ui.config_combo.currentText() # 改为从下拉框获取名称
371 | if name:
372 | # 保存前记录当前选中项
373 | current_name = self.ui.config_combo.currentText()
374 |
375 | self.configs[name] = {
376 | "api_base": self.ui.conf_api_base.text(),
377 | "api_key": self.ui.conf_api_key.text(),
378 | "model": self.ui.conf_model.text()
379 | }
380 | self.save_configs()
381 |
382 | # 重新加载时保持选中状态
383 | self.load_configs(preserve_selection=current_name)
384 | QMessageBox.information(self.ui, "成功", "配置保存成功!")
385 |
386 | def del_config(self):
387 | name = self.ui.config_combo.currentText()
388 | if name in self.configs:
389 | # 确认对话框
390 | reply = QMessageBox.question(
391 | self.ui,
392 | "确认删除",
393 | f"确定要删除配置 【{name}】 吗?",
394 | QMessageBox.Yes | QMessageBox.No
395 | )
396 | if reply == QMessageBox.Yes:
397 | del self.configs[name]
398 | self.save_configs()
399 | self.refresh_config()
400 |
401 | def refresh_config(self):
402 | self.ui.config_combo.setCurrentIndex(0)
403 | self.ui.config_combo_1.setCurrentIndex(0)
404 | self.ui.conf_api_base.setText('')
405 | self.ui.conf_api_key.setText('')
406 | self.ui.conf_model.setText('')
407 | self.load_configs()
408 |
409 | def load_config(self):
410 | name = self.ui.config_combo.currentText()
411 | if name in self.configs:
412 | config = self.configs[name]
413 | self.ui.conf_api_base.setText(config["api_base"])
414 | self.ui.conf_api_key.setText(config["api_key"])
415 | self.ui.conf_model.setText(config["model"])
--------------------------------------------------------------------------------
/tabs/tab_rolan.py:
--------------------------------------------------------------------------------
1 | #-- coding:UTF-8 --
2 | # Author:lintx
3 | # Date:2025/01/21
4 | # set http_proxy=http://127.0.0.1:4780 & set https_proxy=http://127.0.0.1:4780
5 | from PyQt5.QtWidgets import QFileIconProvider,QListWidgetItem,QMenu,QMessageBox,QFileDialog,QInputDialog
6 | from PyQt5.QtCore import Qt, QFileInfo
7 | from PyQt5.QtGui import QIcon,QColor
8 | import json,os,datetime,re,xlsxwriter,traceback
9 |
10 | class tab_rolan():
11 | def __init__(self, ui):
12 | self.ui=ui
13 | #rolan功能点
14 | self.ui.rolan_list_1.itemClicked.connect(self.read_tool) #分组单击读取工具
15 | self.ui.rolan_list_1.itemChanged.connect(self.change_type) #分组重命名
16 | self.ui.rolan_list_2.itemChanged.connect(self.change_tool) #工具重命名
17 | self.ui.rolan_list_2.itemClicked.connect(self.the_tool0) #工具单击读取config
18 | self.ui.rolan_list_2.itemDoubleClicked.connect(self.the_tool) #工具双击启动
19 |
20 | self.ui.rolan_list_1.setContextMenuPolicy(Qt.CustomContextMenu) #分组右键菜单
21 | self.ui.rolan_list_1.customContextMenuRequested.connect(self.list_1_menu)
22 | self.ui.rolan_list_2.setContextMenuPolicy(Qt.CustomContextMenu) #工具右键菜单
23 | self.ui.rolan_list_2.customContextMenuRequested.connect(self.list_2_menu)
24 | self.ui.dragEnterEvent = self.dragEnterEvent #工具拖拉启动
25 | self.ui.dropEvent = self.dropEvent
26 | self.list_1_drop = self.ui.rolan_list_1.dropEvent
27 | self.list_2_drop = self.ui.rolan_list_2.dropEvent
28 | self.ui.rolan_list_1.dropEvent = self.list_1_move #分组移动保存
29 | self.ui.rolan_list_2.dropEvent = self.list_2_move #工具移动保存
30 |
31 |
32 | #rapid功能点
33 | self.ui.rolan_Button_6.clicked.connect(self.read_file) #导入Rapid+数据
34 | self.ui.rolan_list_3.itemClicked.connect(self.rapid_data_read) #单击加载数据
35 | self.ui.rolan_list_4.setVisible(False)
36 | self.ui.rolan_list_4.itemClicked.connect(self.rapid_link_tool)
37 | #启动器功能点
38 | self.ui.rolan_textBrowser_2.textChanged.connect(self.target_list) #数据框统计
39 | self.ui.rolan_Button_1.clicked.connect(self.text_add1) #数据左增加
40 | self.ui.rolan_Button_2.clicked.connect(self.text_add2) #数据右增加
41 | self.ui.rolan_Button_3.clicked.connect(self.text_del) #数据删除
42 | self.ui.rolan_Button_7.clicked.connect(self.data_clear) # 数据框清空
43 | self.ui.rolan_Button_4.clicked.connect(self.tools_run_config) #启动工具
44 | self.ui.rolan_Button_5.clicked.connect(self.tool_config) #config保存
45 | self.ui.rolan_Button_8.clicked.connect(self.log_open)
46 | self.ui.rolan_Button_9.clicked.connect(self.tips)
47 |
48 | ####################################################Rolan功能实现####################################################
49 | #Tips
50 | def tips(self):
51 | QMessageBox.about(self.ui, "数据参数说明", "[file]: -f [file] ,数据写入一个临时文件,由工具运行\n"
52 | "[ip][port]: -ip [ip] -p [port] ,数据按':'进行分割,并逐行(批量)运行\n"
53 | "[target]: -u [target] ,数据无处理,并逐行(批量)运行\n"
54 | "[log]: -o [log] ,统一格式和位置:[logpath]/log-[tool_name]-[date].txt\n\t当使用[log]时[输出/日志]按钮打开统一位置,否则为工具所在目录\n"
55 | "[date]:当前时间\n"
56 | "[logpath]:统一位置")
57 | #打开配置文件
58 | def open_config(self):
59 | os.system('start "" "config/Data+.txt"')
60 | #数据框清空
61 | def data_clear(self):
62 | self.ui.rolan_textBrowser_2.clear()
63 | self.ui.rolan_list_4.setVisible(False)
64 | def read_file(self):
65 | try:
66 | msg_box = QMessageBox()
67 | msg_box.setWindowTitle("提示")
68 | msg_box.setText("导入Rapid数据类型")
69 | msg_box.setIcon(QMessageBox.Question)
70 | yes_button = msg_box.addButton("dir", QMessageBox.AcceptRole)
71 | no_button = msg_box.addButton("file", QMessageBox.NoRole)
72 | close_button = msg_box.addButton("close", QMessageBox.RejectRole)
73 | msg_box.exec_()
74 | try:
75 | filepath=''
76 | if msg_box.clickedButton() == yes_button:
77 | filepath = QFileDialog.getExistingDirectory(self.ui, "选择文件夹")
78 | elif msg_box.clickedButton() == no_button:
79 | file = QFileDialog.getOpenFileName(self.ui, "选择文件")[0]
80 | if file != '':
81 | self.ui.rolan_list_3.clear()
82 | filepath=self.rapid_data(file)
83 | if filepath =='':
84 | QMessageBox.about(self.ui, "提示", "请重新选择数据1")
85 | if filepath != '':
86 | self.ui.rolan_list_3.clear()
87 | self.ui.rolan_line_7.setText(filepath)
88 | for root, dirs, filenames in os.walk(filepath + '/server'):
89 | for filename in filenames:
90 | filename = filename.replace('.txt', '')
91 | self.ui.rolan_list_3.addItem(filename)
92 | self.ui.rolan_list_3.setEnabled(True)
93 | for root, dirs, filenames in os.walk(filepath + '/source'):
94 | for filename in filenames:
95 | filename = filename.replace('.txt', '')
96 | self.ui.rolan_list_3.addItem(filename)
97 | self.ui.rolan_list_3.setEnabled(True)
98 | if self.ui.rolan_list_3.count() == 0:
99 | QMessageBox.about(self.ui, "提示", "请重新选择数据2")
100 | except Exception as e:
101 | print(e)
102 | traceback.print_exc()
103 | pass
104 | except:
105 | QMessageBox.about(self.ui, "错误", "请重新选择数据3")
106 | def rapid_data(self,file):
107 | def load_finger(file_name, data_dict): # 读取指纹数据
108 | with open(file_name, "r") as f:
109 | for i in f.readlines():
110 | data = json.loads(i)
111 | for i in data:
112 | data_dict[i] = data[i]
113 |
114 | def match_finger(ip_port, finger_data): # 指纹分类
115 | types = 'unknown'
116 | for i in finger: # 关键字
117 | if types not in finger:
118 | if i in finger_data:
119 | types = finger[i]
120 | else:
121 | break
122 | for i in finger_diy: # 自定义
123 | if types not in finger_diy:
124 | if i in finger_data:
125 | types = finger_diy[i]
126 | else:
127 | break
128 | if types == 'unknown': # 端口默认服务
129 | for i in finger_port:
130 | if types not in finger_port:
131 | port = re.findall(r'\b' + i + r'\b', ip_port)
132 | if port:
133 | types = finger_port[i]
134 | else:
135 | break
136 | if 'http-' in types:
137 | save_finger('http', ip_port, finger_data)
138 | save_finger(types, ip_port, finger_data)
139 |
140 | def save_finger(types, ip_port, data): # 结果保存
141 | # 根据服务保存
142 | with open(filedir + '/server/' + types + '.txt', 'a', encoding='utf-8') as f:
143 | if types == 'other':
144 | f.write(data)
145 | else:
146 | f.write(ip_port + '\t' + data)
147 | if ip_port.split(":")[0] not in ip_all:
148 | ip_all.append(ip_port.split(":")[0])
149 | if ip_port not in ips_all:
150 | ips_all.append(ip_port)
151 | # 根据端口保存
152 | if 'http' in types or types == 'msrcp' or types == 'none' or types == 'unknown' or types == 'jdwp' or types == 'JavaRMI' or types == 'nullpacket': # 服务端口杂多,不输出
153 | pass
154 | else:
155 | with open(filedir + '/port/' + types + '-' + ip_port.split(":")[1] + '.txt', 'a',
156 | encoding='utf-8') as f:
157 | f.write(ip_port.split(":")[0] + '\n')
158 |
159 |
160 | def save_all():
161 | # 保存源数据
162 | os.popen('copy ' + file.replace('/', '\\') + ' ' + filedir.replace('/', '\\') + '\source\scan_result.txt')
163 | # 保存ip_all和ips_all
164 | with open(filedir + '/source/ip_all.txt', 'a', encoding='utf-8') as f:
165 | for i in ip_all:
166 | f.write(i + '\n')
167 | with open(filedir + '/source/ips_all.txt', 'a', encoding='utf-8') as f:
168 | for i in ips_all:
169 | f.write(i + '\n')
170 | # 保存成excel
171 | f = xlsxwriter.Workbook(filedir + '/server.xls')
172 | for root, dirs, filenames in os.walk(filedir + '/server/'):
173 | for i in filenames:
174 | sheetname = i.replace('.txt', '')
175 | worksheet = f.add_worksheet(sheetname)
176 | row = 2
177 | title = ['IP-PORT', 'SERVER', 'FINGER']
178 | worksheet.write_row('A1', title)
179 | with open(filedir + '/server/' + i, 'r', encoding='utf-8') as g:
180 | codes = g.readlines()
181 | for code in codes:
182 | worksheet.set_column(0, 0, 22)
183 | worksheet.set_column(1, 1, 15)
184 | worksheet.set_column(2, 2, 100)
185 | ip_port = re.findall(r'^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d+', code)
186 | if ip_port:
187 | fingers = re.sub(r'\s+', ' ', code.replace(ip_port[0], '').replace('\t', ' '))
188 | worksheet.write('A' + str(row), ip_port[0])
189 | worksheet.write('B' + str(row), sheetname)
190 | worksheet.write('C' + str(row), fingers)
191 | else:
192 | worksheet.write('A' + str(row), code)
193 |
194 | row += 1
195 | with open(filedir + '/server/' + i, 'r', encoding='utf-8') as h:
196 | ser = re.sub('\t.*', '', h.read())
197 | with open(filedir + '/server/' + i, 'w', encoding='utf-8') as i:
198 | i.write(ser)
199 | f.close()
200 |
201 | def run_finger(datas): # 主程序运行
202 | counts = 0
203 | ip_port_all = re.findall(r'^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d+', ''.join(datas))
204 | if ip_port_all:
205 | for i in datas:
206 | data = i
207 | counts += 1
208 | current_time = datetime.datetime.now()
209 | print('\r[*] [{}] [Rapid] 数据处理进度:{}/{}'.format(current_time,counts, len(datas)), end='', flush=True)
210 | ip_port = re.findall(r'^\d{1,3}\.\d{1,3}\.\d{1,3}\.\d{1,3}\:\d+', data)
211 | if ip_port: # RapidScanner
212 | finger_data = data.replace(ip_port[0], '')
213 | match_finger(ip_port[0], finger_data)
214 | return 1
215 | else:
216 | return 0
217 | current_time = datetime.datetime.now()
218 | with open(file, 'r', encoding='utf-8') as f:
219 | try:
220 | datas = f.readlines()
221 | except:
222 | print('\n[-] [{}] [Rapid] {}编码出错,请将数据另存为UTF-8编码'.format(current_time,file))
223 | exit()
224 |
225 | now = datetime.datetime.now()
226 | filedir = f'result/{now.strftime("%Y%m%d")}/rapid_result_{str(int(now.timestamp()))[-6:]}'
227 | os.makedirs(filedir + '/port')
228 | os.makedirs(filedir + '/server')
229 | os.makedirs(filedir + '/source')
230 |
231 |
232 | finger = {}
233 | finger_diy = {}
234 | finger_port = {}
235 | load_finger("config/finger/finger.ini", finger)
236 | load_finger("config/finger/finger_diy.ini", finger_diy)
237 | load_finger("config/finger/finger_port.ini", finger_port)
238 |
239 | ip_all = []
240 | ips_all = []
241 | if run_finger(datas) == 1:
242 | current_time = datetime.datetime.now()
243 | print('\n[+] [{}] [Rapid] 数据处理完毕,数据来源:{}'.format(current_time,file))
244 | print('[+] [{}] [Rapid] 数据结果保存至目录:{}'.format(current_time, filedir))
245 | save_all()
246 | else:
247 | filedir=filedir.replace('/', '\\')
248 | os.popen(f"rmdir {filedir} /S/Q")
249 | filedir=''
250 | return filedir
251 |
252 | def rapid_data_read(self):
253 | current_data = self.ui.rolan_list_3.selectedItems()[0].text()
254 | try:
255 | with open(self.ui.rolan_line_7.text()+'/server/'+current_data+'.txt','r',encoding='utf-8') as f:
256 | self.ui.rolan_textBrowser_2.setText(f.read().strip())
257 | except:
258 | try:
259 | with open(self.ui.rolan_line_7.text()+'/source/'+current_data+'.txt','r',encoding='utf-8') as f:
260 | self.ui.rolan_textBrowser_2.setText(f.read().strip())
261 | except:
262 | QMessageBox.about(self.ui, "提示", "读取数据错误")
263 | if current_data in Service_type:
264 | self.ui.rolan_list_4.clear()
265 | for i in Service_type[current_data]:
266 | self.ui.rolan_list_4.addItem(i)
267 | self.ui.rolan_list_4.setVisible(True)
268 | else:
269 | self.ui.rolan_list_4.clear()
270 | self.ui.rolan_list_4.setVisible(False)
271 | def rapid_link_tool(self):
272 | try:
273 | current_service = self.ui.rolan_list_3.selectedItems()[0].text()
274 | current_tool = self.ui.rolan_list_4.selectedItems()[0].text()
275 | for i in range(self.ui.rolan_list_1.count()):
276 | item = self.ui.rolan_list_1.item(i)
277 | if item.text() == Service_type[current_service][current_tool]:
278 | self.ui.rolan_list_1.setCurrentItem(item)
279 | self.ui.rolan_list_1.itemClicked.emit(item)
280 | for i in range(self.ui.rolan_list_2.count()):
281 | item = self.ui.rolan_list_2.item(i)
282 | if item.text() == current_tool:
283 | self.ui.rolan_list_2.setCurrentItem(item)
284 | self.ui.rolan_list_2.itemClicked.emit(item)
285 | except:
286 | pass
287 |
288 | #读取data
289 | def read_data(self,clearstate):
290 | if not clearstate:
291 | self.ui.setAcceptDrops(True)
292 | self.ui.rolan_frame_1.setEnabled(False)
293 | self.ui.rolan_list_1.clear()
294 | self.ui.rolan_list_2.clear()
295 | self.ui.rolan_line_1.clear()
296 | self.ui.rolan_line_2.clear()
297 | self.ui.rolan_line_3.clear()
298 | self.ui.rolan_line_4.clear()
299 | self.ui.rolan_radio_1.setChecked(True)
300 | if not os.path.exists('config/Data+.txt'):
301 | os.system('echo {"\\u793a\\u4f8b\\u5206\\u7ec4": {"\\u53c2\\u6570\\u6f14\\u793a": {"Path": "[toolpath]\\\\config\\\\Data+.txt","config_1": "echo python3 tool.py -f [file] -o [log]","config_2": "echo python2 tool.py -i [ip] -p [port]","config_3": "echo tool.exe -l [target]","tool_key": "first","tool_tip": "\\u4f7f\\u7528echo\\u6f14\\u793abat\\u542f\\u52a8\\u6548\\u679c\\uff08\\u66f4\\u591a\\u53c2\\u6570\\u70b9\\u51fb\\u8bf4\\u660e\\u6309\\u94ae\\u67e5\\u770b\\uff09","tool_service": "\\u670d\\u52a1\\u7c7b\\u578b"},"RapidScanner": {"Path": "[toolpath]\\\\tools\\\\RapidScanner.exe","config_1": "1\\u3001\\u5de5\\u5177\\u652f\\u6301\\u62d6\\u62c9\\u65b0\\u589e\\u6216\\u8005\\u53f3\\u952e\\u65b0\\u589e","config_2": "2\\u3001\\u652f\\u6301\\u4e09\\u6761\\u81ea\\u5b9a\\u4e49\\u542f\\u52a8\\u547d\\u4ee4","config_3": "3\\u3001\\u901a\\u8fc7\\u8fd0\\u884cbat\\u65b9\\u5f0f\\u6267\\u884c\\u542f\\u52a8\\u547d\\u4ee4","tool_key": "first","tool_tip": "\\u652f\\u6301\\u76f4\\u63a5\\u53cc\\u51fb\\u6253\\u5f00\\uff0c\\u53f3\\u952e\\u6253\\u5f00,\\u6309\\u94ae\\u6253\\u5f00\\uff08\\u9700\\u547d\\u4ee4\\u7f6e\\u7a7a\\uff09","tool_service": "\\u670d\\u52a1\\u7c7b\\u578b"}}}>config/Data+.txt')
302 | with open('config/Data+.txt','r',encoding='utf-8')as f:
303 | global Tools_type,Service_type
304 | Tools_type={}
305 | Service_type={}
306 | try:
307 | Tools_type=json.loads(f.read())
308 | except:
309 | pass
310 |
311 | for i in Tools_type:
312 | theItem = QListWidgetItem(i)
313 | theItem.setFlags(theItem.flags() | Qt.ItemIsEditable)
314 | if not clearstate:
315 | self.ui.rolan_list_1.addItem(theItem)
316 | for b in Tools_type[i]:
317 | try:
318 | servicetext=Tools_type[i][b]['tool_service']
319 | if servicetext not in Service_type:
320 | Service_type[servicetext]= {b:i}
321 | else:
322 | Service_type[servicetext][b]=i
323 | except:
324 | pass
325 | if not clearstate:
326 | self.read_service('')
327 |
328 | def read_service(self,tool_service):
329 | self.ui.comboBox_3.clear()
330 | if tool_service:
331 | self.ui.comboBox_3.addItem(tool_service)
332 | self.ui.comboBox_3.addItem('服务类型')
333 | else:
334 | self.ui.comboBox_3.addItem('服务类型')
335 | list = []
336 | with open('config/finger/finger.ini', 'r', encoding='utf-8') as f:
337 | for i in f.readlines():
338 | jsontext = json.loads(i)
339 | for b in jsontext:
340 | servicetext = jsontext[b]
341 | if servicetext not in list:
342 | list.append(jsontext[b])
343 | with open('config/finger/finger_diy.ini', 'r', encoding='utf-8') as f:
344 | for i in f.readlines():
345 | jsontext = json.loads(i)
346 | for b in jsontext:
347 | servicetext = jsontext[b]
348 | if servicetext not in list:
349 | list.append(jsontext[b])
350 | list.sort()
351 | self.ui.comboBox_3.addItems(list)
352 |
353 | #加载工具列表
354 | def read_tool(self):
355 | try:
356 | self.ui.rolan_frame_1.setEnabled(False)
357 | self.ui.rolan_list_2.verticalScrollBar().setValue(0)
358 | self.ui.rolan_list_2.clear()
359 | item=self.ui.rolan_list_1.selectedItems()[0].text()
360 | try:
361 | tools = Tools_type[item]
362 | except:
363 | pass
364 | for tool in tools:
365 | pwd=os.getcwd()
366 | tool_path=tools[tool]['Path'].replace('[toolpath]', pwd)
367 | file_Info = QFileInfo(tool_path)
368 | try:
369 | if '.jar' in tool_path:
370 | java_path = 'config/ico/java.ico'
371 | file_Info = QFileInfo(java_path)
372 | if '.py' in tool_path:
373 | java_path = 'config/ico/python.ico'
374 | file_Info = QFileInfo(java_path)
375 | except:
376 | pass
377 | iconProvider = QFileIconProvider()
378 | if os.path.exists(file_Info):
379 | icon = iconProvider.icon(file_Info)
380 | theItem = QListWidgetItem(QIcon(icon), tool)
381 | else:
382 | theItem =QListWidgetItem(tool)
383 | theItem.setFlags(theItem.flags() | Qt.ItemIsEditable)
384 | # if pwd not in tool_path:
385 | # theItem.setForeground(QColor('gray'))
386 | self.ui.rolan_list_2.addItem(theItem)
387 | except:
388 | pass
389 |
390 |
391 | #打开工具
392 | def the_tool(self):
393 | self.tools_run('start')
394 | self.read_config()
395 | # 选中工具
396 | def the_tool0(self):
397 | self.read_config()
398 | self.ui.rolan_frame_1.setEnabled(True)
399 |
400 | #拖放文件
401 | def dragEnterEvent(self, event):
402 | self.ui.rolan_frame_1.setEnabled(False)
403 | tabs_text = self.ui.tabWidget.tabText(self.ui.tabWidget.currentIndex())
404 | if tabs_text == 'Rolan+' and self.ui.rolan_list_1.selectedItems():
405 | if event.mimeData().hasUrls():
406 | event.acceptProposedAction()
407 |
408 | def dropEvent(self, event):
409 | self.ui.rolan_frame_1.setEnabled(False)
410 | tabs_text = self.ui.tabWidget.tabText(self.ui.tabWidget.currentIndex())
411 | if tabs_text == 'Rolan+' and self.ui.rolan_list_1.selectedItems():
412 | if event.mimeData().hasUrls():
413 | for url in event.mimeData().urls():
414 | path = url.toLocalFile()
415 | self.tools_add(path)
416 | event.acceptProposedAction()
417 |
418 | #tools_add
419 | def tools_add(self,path):
420 | current_type = self.ui.rolan_list_1.selectedItems()[0].text()
421 | fileInfo = QFileInfo(path)
422 | if fileInfo.isSymLink():
423 | fileInfo = QFileInfo(fileInfo.symLinkTarget())
424 | filename = os.path.splitext(fileInfo.fileName())[0]
425 | while filename in [i for i in Tools_type[current_type]]:
426 | filename += '_new'
427 | # 数据处理
428 | file_path = fileInfo.filePath().replace('/', '\\')
429 | if os.getcwd() in os.path.dirname(file_path):
430 | file_path = file_path.replace(os.getcwd(),'[toolpath]')
431 | Tools_type[current_type][filename] = {"Path": file_path}
432 | # 列表增加
433 | iconProvider = QFileIconProvider()
434 | icon = iconProvider.icon(fileInfo)
435 | theItem = QListWidgetItem(QIcon(icon), filename)
436 | theItem.setFlags(theItem.flags() | Qt.ItemIsEditable)
437 | # if '[toolpath]' not in file_path:
438 | # theItem.setForeground(QColor('gray'))
439 | self.ui.rolan_list_2.addItem(theItem)
440 | self.ui.rolan_frame_1.setEnabled(False)
441 | self.save_config()
442 |
443 | #target_list
444 | def target_list(self):
445 | if self.ui.rolan_textBrowser_2.toPlainText() == '':
446 | self.ui.rolan_line_6.setText('Count:0')
447 | else:
448 | self.ui.rolan_line_6.setText('Count:' + str(len(self.ui.rolan_textBrowser_2.toPlainText().split('\n'))))
449 |
450 | # list_1_menu
451 | def list_1_menu(self, post):
452 | menu = QMenu()
453 | item1 = menu.addAction("刷新")
454 | item2 = menu.addAction("新增")
455 | item3 = menu.addAction("重命名")
456 | item4 = menu.addAction("删除")
457 | action = menu.exec_(self.ui.rolan_list_1.mapToGlobal(post))
458 | if action == item1:
459 | self.read_data('')
460 | if action == item2:
461 | try:
462 | dir,ok = QInputDialog.getText(None, "提示", "新增分组:")
463 | if dir:
464 | while dir in Tools_type:
465 | dir+='_new'
466 | Tools_type[dir] = {}
467 | theItem = QListWidgetItem(dir)
468 | theItem.setFlags(theItem.flags() | Qt.ItemIsEditable)
469 | self.ui.rolan_list_1.addItem(theItem)
470 | self.ui.rolan_frame_1.setEnabled(False)
471 | self.save_config()
472 | else:
473 | QMessageBox.about(self.ui, "提示", "分组不能为空")
474 | except:
475 | pass
476 | if action == item3:
477 | try:
478 | self.ui.rolan_list_1.editItem(self.ui.rolan_list_1.selectedItems()[0])
479 | except:
480 | pass
481 | if action == item4:
482 | try:
483 | current_type=self.ui.rolan_list_1.selectedItems()[0].text()
484 | checkif = QMessageBox.question(self.ui, "提示", f"确定删除[{current_type}]分组?", QMessageBox.No | QMessageBox.Yes,QMessageBox.No)
485 | if checkif == QMessageBox.Yes:
486 | del Tools_type[current_type]
487 | current_row = self.ui.rolan_list_1.currentRow()
488 | self.ui.rolan_list_1.takeItem(current_row)
489 | self.save_config()
490 | self.read_data('')
491 | except:
492 | pass
493 |
494 | # list_2_menu
495 | def list_2_menu(self,post):
496 | global Tools_type
497 | menu = QMenu()
498 | item2 = menu.addAction("打开")
499 | item3 = menu.addAction("打开目录")
500 | item1 = menu.addAction("刷新")
501 | item4 = menu.addAction("新增")
502 | item5 = menu.addAction("重命名")
503 | item6 = menu.addAction("删除")
504 | item7 = menu.addAction("Config")
505 | item8 = menu.addMenu("移动分组")
506 | action_dirs=[]
507 | for i in Tools_type:
508 | action_dirs.append(item8.addAction(i))
509 | action =menu.exec_(self.ui.rolan_list_2.mapToGlobal(post))
510 | if action in action_dirs:
511 | try:
512 | current_type = self.ui.rolan_list_1.selectedItems()[0].text()
513 | current_tool = self.ui.rolan_list_2.selectedItems()[0].text()
514 | moveto_dir = action.text()
515 | checkif0 = ''
516 | checkif = QMessageBox.question(self.ui, "提示", f"确定移动 [{current_tool}] 到分组 [{moveto_dir}] ?",
517 | QMessageBox.No | QMessageBox.Yes, QMessageBox.No)
518 | if checkif == QMessageBox.Yes:
519 | if current_tool in [i for i in Tools_type[moveto_dir]]:
520 | checkif0=QMessageBox.question(self.ui, "提示", f"分组 [{moveto_dir}] 已存在 [{current_tool}] ,是否移动?",
521 | QMessageBox.No | QMessageBox.Yes, QMessageBox.No)
522 | if checkif0 == QMessageBox.Yes:
523 | current_tool0 = current_tool+'_new'
524 | else:
525 | return
526 | if checkif0:
527 | Tools_type[moveto_dir][current_tool0] = Tools_type[current_type][current_tool]
528 | else:
529 | Tools_type[moveto_dir][current_tool]=Tools_type[current_type][current_tool]
530 | if moveto_dir != current_type:
531 | del Tools_type[current_type][current_tool]
532 | self.save_config()
533 | self.read_tool()
534 | except:
535 | pass
536 | if action == item1:
537 | self.read_tool()
538 | if action == item2:
539 | self.tools_run('start')
540 | self.read_config()
541 | if action == item3:
542 | self.tools_run('dir')
543 | self.read_config()
544 | if action == item4:
545 | try:
546 | self.ui.rolan_list_1.selectedItems()[0].text()
547 | msg_box = QMessageBox()
548 | msg_box.setWindowTitle("提示")
549 | msg_box.setText("选择要新增的类型?")
550 | msg_box.setIcon(QMessageBox.Question)
551 | yes_button = msg_box.addButton("dir",QMessageBox.AcceptRole)
552 | no_button = msg_box.addButton("file", QMessageBox.NoRole)
553 | close_button = msg_box.addButton("close", QMessageBox.RejectRole)
554 | msg_box.exec_()
555 | try:
556 | if msg_box.clickedButton() == yes_button:
557 | filepath = QFileDialog.getExistingDirectory(self.ui, "选择要添加的目录")
558 | elif msg_box.clickedButton() == no_button:
559 | filepath = QFileDialog.getOpenFileName(self.ui, "选择要添加的工具")[0]
560 | if filepath:
561 | self.tools_add(filepath)
562 | except:
563 | pass
564 | except:
565 | QMessageBox.about(self.ui, "错误", "请先选择分组")
566 | if action == item5:
567 | try:
568 | self.ui.rolan_list_2.editItem(self.ui.rolan_list_2.selectedItems()[0])
569 | except:
570 | pass
571 | if action == item6:
572 | try:
573 | current_type = self.ui.rolan_list_1.selectedItems()[0].text()
574 | current_tool = self.ui.rolan_list_2.selectedItems()[0].text()
575 | checkif = QMessageBox.question(self.ui, "提示", f"确定删除[{current_tool}]?",
576 | QMessageBox.No | QMessageBox.Yes, QMessageBox.No)
577 | if checkif == QMessageBox.Yes:
578 | del Tools_type[current_type][current_tool]
579 | current_row = self.ui.rolan_list_2.currentRow()
580 | self.ui.rolan_list_2.takeItem(current_row)
581 | self.ui.rolan_frame_1.setEnabled(False)
582 | self.save_config()
583 | except:
584 | pass
585 | if action == item7:
586 | self.open_config()
587 |
588 | # 顺序移动保存
589 | def list_1_move(self, event):
590 | self.ui.rolan_frame_1.setEnabled(False)
591 | self.list_1_drop(event)
592 | global Tools_type
593 | item_names = [self.ui.rolan_list_1.item(i).text() for i in range(self.ui.rolan_list_1.count())]
594 | Tools_type_0 = {}
595 | for b,i in enumerate(item_names):
596 | try:
597 | Tools_type_0[i] = Tools_type[i]
598 | except:
599 | pass
600 | if len(Tools_type) == len(Tools_type_0):
601 | Tools_type = Tools_type_0
602 | self.ui.rolan_list_2.clear()
603 | self.save_config()
604 |
605 | def list_2_move(self, event):
606 | self.ui.rolan_frame_1.setEnabled(False)
607 | self.list_2_drop(event)
608 | global Tools_type
609 | item_names = [self.ui.rolan_list_2.item(i).text() for i in range(self.ui.rolan_list_2.count())]
610 | Tools_type_0 = {}
611 | for b,i in enumerate(item_names):
612 | try:
613 | global type
614 | type = self.ui.rolan_list_1.selectedItems()[0].text()
615 | Tools_type_0[i] = Tools_type[type][i]
616 | except:
617 | pass
618 | if len(Tools_type[type]) == len(Tools_type_0):
619 | Tools_type[type] = Tools_type_0
620 | self.save_config()
621 |
622 | #change_type
623 | def change_type(self):
624 | current_type = self.ui.rolan_list_1.selectedItems()[0].text()
625 | current_row = self.ui.rolan_list_1.currentRow()
626 | global Tools_type
627 | histry_type = [i for i in Tools_type][current_row]
628 | item_names = [self.ui.rolan_list_1.item(i).text() for i in range(self.ui.rolan_list_1.count())]
629 | Tools_type_0 = {}
630 | if current_type != histry_type:
631 | checkif = QMessageBox.question(self.ui, "提示", f"确定修改为[{current_type}]分组?",
632 | QMessageBox.No | QMessageBox.Yes, QMessageBox.No)
633 | if checkif == QMessageBox.Yes:
634 | while current_type in [i for i in Tools_type]:
635 | QMessageBox.about(self.ui, "错误", "分组名称重复,请重新修改")
636 | self.read_data('')
637 | return
638 | for i in item_names:
639 | if i == current_type:
640 | Tools_type_0[i] = Tools_type[histry_type]
641 | else:
642 | Tools_type_0[i] = Tools_type[i]
643 | if len(Tools_type) == len(Tools_type_0):
644 | Tools_type = Tools_type_0
645 | self.save_config()
646 | self.read_data('')
647 |
648 | #change_tool
649 | def change_tool(self):
650 | current_type = self.ui.rolan_list_1.selectedItems()[0].text()
651 | current_tool = self.ui.rolan_list_2.selectedItems()[0].text()
652 | current_row = self.ui.rolan_list_2.currentRow()
653 | global Tools_type
654 | histry_tool = [i for i in Tools_type[current_type]][current_row]
655 | item_names = [self.ui.rolan_list_2.item(i).text() for i in range(self.ui.rolan_list_2.count())]
656 | Tools_type_0 = {}
657 | if current_tool != histry_tool:
658 | checkif = QMessageBox.question(self.ui, "提示", f"确定修改为[{current_tool}]?",
659 | QMessageBox.No | QMessageBox.Yes, QMessageBox.No)
660 | if checkif == QMessageBox.Yes:
661 | while current_tool in [i for i in Tools_type[current_type]]:
662 | QMessageBox.about(self.ui, "错误", "工具名称重复,请重新修改")
663 | self.read_tool()
664 | return
665 | for i in item_names:
666 | if i == current_tool:
667 | Tools_type_0[i] = Tools_type[current_type][histry_tool]
668 | else:
669 | Tools_type_0[i] = Tools_type[current_type][i]
670 | if len(Tools_type[current_type]) == len(Tools_type_0):
671 | Tools_type[current_type] = Tools_type_0
672 | self.save_config()
673 | self.read_tool()
674 |
675 |
676 | #save_config
677 | def save_config(self):
678 | with open('config/Data+.txt','w',encoding='utf-8')as f:
679 | f.write(json.dumps(Tools_type,indent=4))
680 |
681 | ####################################################启动功能实现####################################################
682 | #tool_config
683 | def tool_config(self):
684 | try:
685 | tool_tip=self.ui.rolan_line_1.text()
686 | config_1=self.ui.rolan_line_2.text()
687 | config_2=self.ui.rolan_line_3.text()
688 | config_3=self.ui.rolan_line_4.text()
689 | if self.ui.rolan_radio_1.isChecked() == True:
690 | tool_key='first'
691 | elif self.ui.rolan_radio_2.isChecked() == True:
692 | tool_key = 'second'
693 | elif self.ui.rolan_radio_3.isChecked() == True:
694 | tool_key = 'third'
695 | current_type = self.ui.rolan_list_1.selectedItems()[0].text()
696 | current_tool = self.ui.rolan_list_2.selectedItems()[0].text()
697 | Tools_type[current_type][current_tool]['config_1'] = config_1
698 | Tools_type[current_type][current_tool]['config_2'] = config_2
699 | Tools_type[current_type][current_tool]['config_3'] = config_3
700 | Tools_type[current_type][current_tool]['tool_key'] = tool_key
701 | Tools_type[current_type][current_tool]['tool_tip'] = tool_tip
702 | current_service = self.ui.comboBox_3.currentText()
703 | if current_service != '服务类型':
704 | Tools_type[current_type][current_tool]['tool_service'] = current_service
705 | else:
706 | Tools_type[current_type][current_tool]['tool_service'] = '服务类型'
707 | self.save_config()
708 | QMessageBox.about(self.ui, "提示", "已保存")
709 | self.read_data('change')
710 | except Exception as e:
711 | QMessageBox.about(self.ui, "错误", f"保存配置异常:{e}")
712 | #read_config
713 | def read_config(self):
714 | self.ui.rolan_line_1.clear()
715 | self.ui.rolan_line_2.clear()
716 | self.ui.rolan_line_3.clear()
717 | self.ui.rolan_line_4.clear()
718 | self.ui.rolan_radio_1.setChecked(True)
719 | self.read_service('')
720 | current_type = self.ui.rolan_list_1.selectedItems()[0].text()
721 | current_tool = self.ui.rolan_list_2.selectedItems()[0].text()
722 | try:
723 | config_1 = Tools_type[current_type][current_tool]['config_1']
724 | config_2 = Tools_type[current_type][current_tool]['config_2']
725 | config_3 = Tools_type[current_type][current_tool]['config_3']
726 | tool_key = Tools_type[current_type][current_tool]['tool_key']
727 | try:
728 | tool_tip = Tools_type[current_type][current_tool]['tool_tip']
729 | self.ui.rolan_line_1.setText(tool_tip)
730 | self.ui.rolan_line_1.setToolTip(tool_tip)
731 | except:
732 | pass
733 | try:
734 | tool_service = Tools_type[current_type][current_tool]['tool_service']
735 | self.read_service(tool_service)
736 | try:
737 | if self.ui.rolan_list_4.selectedItems()[0].text() != current_tool:
738 | self.ui.rolan_list_4.setVisible(False)
739 | except:
740 | self.ui.rolan_list_4.setVisible(False)
741 | pass
742 | except:
743 | self.ui.rolan_list_4.setVisible(False)
744 | self.read_service('')
745 | pass
746 | self.ui.rolan_line_2.setText(config_1)
747 | self.ui.rolan_line_3.setText(config_2)
748 | self.ui.rolan_line_4.setText(config_3)
749 | self.ui.rolan_line_2.setToolTip(config_1)
750 | self.ui.rolan_line_3.setToolTip(config_2)
751 | self.ui.rolan_line_4.setToolTip(config_3)
752 | self.ui.rolan_line_1.setCursorPosition(0)
753 | self.ui.rolan_line_2.setCursorPosition(0)
754 | self.ui.rolan_line_3.setCursorPosition(0)
755 | self.ui.rolan_line_4.setCursorPosition(0)
756 | if tool_key == 'first':
757 | self.ui.rolan_radio_1.setChecked(True)
758 | elif tool_key == 'second':
759 | self.ui.rolan_radio_2.setChecked(True)
760 | elif tool_key == 'third':
761 | self.ui.rolan_radio_3.setChecked(True)
762 | except:
763 | self.ui.rolan_list_4.setVisible(False)
764 | pass
765 | def text_add1(self):
766 | text=self.ui.rolan_textBrowser_2.toPlainText()
767 | text=text.split('\n')
768 | self.ui.rolan_textBrowser_2.setText("")
769 | text0 = []
770 | for i in text:
771 | text0.append(self.ui.rolan_line_5.text()+i)
772 | self.ui.rolan_textBrowser_2.setPlainText('\n'.join(text0))
773 | def text_add2(self):
774 | text=self.ui.rolan_textBrowser_2.toPlainText()
775 | text=text.split('\n')
776 | self.ui.rolan_textBrowser_2.setText("")
777 | text0 = []
778 | for i in text:
779 | text0.append(i+self.ui.rolan_line_5.text())
780 | self.ui.rolan_textBrowser_2.setPlainText('\n'.join(text0))
781 | def text_del(self):
782 | text = self.ui.rolan_textBrowser_2.toPlainText()
783 | text = text.split('\n')
784 | self.ui.rolan_textBrowser_2.setText("")
785 | text0 = []
786 | for i in text:
787 | text0.append(i.replace(self.ui.rolan_line_5.text(),''))
788 | self.ui.rolan_textBrowser_2.setPlainText('\n'.join(text0))
789 | #tools_run_config
790 | def tools_run_config(self):
791 | try:
792 | tool_name = self.ui.rolan_list_2.selectedItems()[0].text()
793 | type = self.ui.rolan_list_1.selectedItems()[0].text()
794 | item = self.ui.rolan_list_2.selectedItems()[0].text()
795 | cmds = Tools_type[type][item]['Path']
796 | pwd = os.getcwd()
797 | cmds = cmds.replace('[toolpath]',pwd)
798 | current_time = datetime.datetime.now()
799 | current_date = current_time.strftime("%Y%m%d")
800 | current_dates = current_time.strftime("%Y%m%d%S")
801 | temp_data = f"{os.getcwd()}\\config\\temp_run.data"
802 | logpath = f'{pwd}\\result\\{current_date}'
803 | if not os.path.exists(logpath):
804 | os.makedirs(logpath)
805 |
806 | if self.ui.rolan_radio_1.isChecked() == True:
807 | tool_config=self.ui.rolan_line_2.text()
808 | elif self.ui.rolan_radio_2.isChecked() == True:
809 | tool_config=self.ui.rolan_line_3.text()
810 | elif self.ui.rolan_radio_3.isChecked() == True:
811 | tool_config=self.ui.rolan_line_4.text()
812 |
813 | logs=f'[*] [{current_time}] [{tool_name}] {tool_config}'
814 | print(logs)
815 | with open(f'{logpath}\\logs-run-{current_date}.txt', 'a', encoding='utf-8') as tool_log:
816 | print(logs,file=tool_log)
817 |
818 | try:
819 | with open('config/env.ini', "r") as f:
820 | env = json.loads(f.read())
821 | current_env = tool_config.split(' ')[0]
822 | if current_env in env:
823 | if env[current_env]:
824 | tool_config = tool_config.replace(current_env+' ',pwd+'/'+env[current_env]+' ')
825 | except:
826 | pass
827 |
828 | tool_config = tool_config.replace('[tool]',cmds)
829 | tool_config = tool_config.replace('[date]',current_dates)
830 | tool_config = tool_config.replace('[log]', f'{logpath}\\log-{tool_name}-{current_dates}.txt')
831 | tool_config = tool_config.replace('[logpath]', logpath)
832 | if tool_config:
833 | with open(temp_data, 'w', encoding='utf-8') as f:
834 | f.write(self.ui.rolan_textBrowser_2.toPlainText())
835 | if '[file]' in tool_config or '%TARGETS%' in tool_config:
836 | tool_config = tool_config.replace('[file]', temp_data).replace('%TARGETS%', temp_data)
837 | elif '[ip]' in tool_config or '!IP!' in tool_config:
838 | if ':' in self.ui.rolan_textBrowser_2.toPlainText():
839 | tool_config = tool_config.replace('[ip]','%%a').replace('[port]','%%b').replace('!IP!','%%a').replace('!PORT!','%%b')
840 | tool_config = f"for /f \"tokens=1,2 delims=:\" %%a in ({temp_data}) do {tool_config}"
841 | else:
842 | QMessageBox.about(self.ui, "错误", f"启动异常:当前数据非[ip]:[port]格式")
843 | return
844 | elif '[target]' in tool_config or '!TARGET!' in tool_config:
845 | tool_config = tool_config.replace('[target]','%%a').replace('!TARGET!','%%a')
846 | tool_config = f"for /f %%a in ({temp_data}) do {tool_config}"
847 | os.chdir(os.path.dirname(cmds))
848 | with open(f'{item}_run.bat', 'w', encoding='utf-8') as f:
849 | #f.write('chcp 65001\n'+tool_config)
850 | f.write(tool_config)
851 | os.chdir(pwd)
852 | self.tools_run('run')
853 | else:
854 | QMessageBox.about(self.ui, "提示", "未配置数据,直接启动")
855 | self.tools_run('start')
856 | except Exception as e:
857 | os.chdir(pwd)
858 | QMessageBox.about(self.ui, "错误", f"启动异常:请先选中工具")
859 | print('[-] [{}] [{}] [错误] '.format(current_time,item),e)
860 |
861 | #tools_run
862 | def tools_run(self,key=''):
863 | try:
864 | type=self.ui.rolan_list_1.selectedItems()[0].text()
865 | item=self.ui.rolan_list_2.selectedItems()[0].text()
866 | cmds=Tools_type[type][item]['Path']
867 | pwd = os.getcwd()
868 | cmds = cmds.replace('[toolpath]', pwd)
869 | os.chdir(os.path.dirname(cmds))
870 | if key == 'dir':
871 | cmds = f'start "" "{os.path.dirname(cmds)}"'
872 | elif key == 'run':
873 | cmds = f'start "" "{item}_run.bat"'
874 | elif key == 'start':
875 | cmds = f'start "" "{cmds}"'
876 | if '.jar' in cmds:
877 | current_time = datetime.datetime.now()
878 | print("[*] [{}] [提示] Java程序打开或双击无反应,可使用启动按钮打开".format(current_time))
879 | else:
880 | try:
881 | if Tools_type[type][item]['config_1']:
882 | cmds = 'REM'
883 | else:
884 | cmds = f'start "" "{cmds}"'
885 | except:
886 | cmds = f'start "" "{cmds}"'
887 | os.system(cmds)
888 | os.chdir(pwd)
889 | except:
890 | pass
891 |
892 | #log_open
893 | def log_open(self):
894 | pwd = os.getcwd()
895 | current_time = datetime.datetime.now()
896 | current_date = current_time.strftime("%Y%m%d")
897 | logpath = f'{pwd}\\result\\{current_date}'
898 | logpath0 = f'{pwd}\\result'
899 | if self.ui.rolan_radio_1.isChecked() == True:
900 | tool_config = self.ui.rolan_line_2.text()
901 | elif self.ui.rolan_radio_2.isChecked() == True:
902 | tool_config = self.ui.rolan_line_3.text()
903 | elif self.ui.rolan_radio_3.isChecked() == True:
904 | tool_config = self.ui.rolan_line_4.text()
905 | if '[log]' in tool_config or '[logpath]' in tool_config:
906 | if os.path.exists(logpath):
907 | cmds = f'start "" "{logpath}"'
908 | else:
909 | cmds = f'start "" "{logpath0}"'
910 | os.system(cmds)
911 | else:
912 | self.tools_run('dir')
--------------------------------------------------------------------------------
/tabs/tab_zz.py:
--------------------------------------------------------------------------------
1 | #-- coding:UTF-8 --
2 | # Author:lintx
3 | # Date:2025/01/07 11:00
4 | import re
5 | from PyQt5.QtWidgets import QApplication,QMessageBox
6 |
7 | class tab_zz():
8 | def __init__(self, ui):
9 | self.__dict__.update(ui.__dict__)
10 | self.ui=ui
11 | self.pushButton.clicked.connect(self.display)
12 | self.pushButton1.clicked.connect(self.pipei)
13 | self.pushButton2.clicked.connect(self.copy)
14 | self.pushButton3.clicked.connect(self.copy1)
15 | self.pushButton3_2.clicked.connect(self.add1)
16 | self.pushButton3_3.clicked.connect(self.add2)
17 | self.pushButton3_4.clicked.connect(self.minus)
18 | self.pushButton3_5.clicked.connect(self.tihuan)
19 | self.pushButton3_6.clicked.connect(self.quchong)
20 | self.comboBox.currentIndexChanged.connect(self.zhengze0)
21 | self.comboBox_2.currentIndexChanged.connect(self.zhengze0)
22 | # ---------------------------------------------正则---------------------------------------------------
23 | def copy(self):
24 | try:
25 | clipboard = QApplication.clipboard()
26 | clipboard.setText(self.textBrowser.toPlainText())
27 | QMessageBox.about(self.ui, "提示", "复制表达式成功")
28 | except Exception as e:
29 | print(e)
30 | def copy1(self):
31 | try:
32 | clipboard = QApplication.clipboard()
33 | clipboard.setText(self.textBrowser1.toPlainText())
34 | QMessageBox.about(self.ui, "提示", "复制结果成功")
35 | except Exception as e:
36 | print(e)
37 | def display(self):
38 | begin = self.lineEdit1.text()
39 | end = self.lineEdit2.text()
40 | #转义
41 | begins = []
42 | ends=[]
43 | for i in begin:
44 | if i in "[-\/^$*+?.()|[\]{}]":
45 | begins.append("\\")
46 | begins.append(i)
47 | begin = "".join(begins)
48 | for b in end:
49 | if b in "[-\/^$*+?.()|[\]{}]":
50 | ends.append("\\")
51 | ends.append(b)
52 | end = "".join(ends)
53 | #数据处理
54 | if begin=='' or end=='':
55 | self.textBrowser.setText("请输入开始和结束关键字")
56 | elif self.checkBox1.isChecked()and self.checkBox2.isChecked()and self.checkBox3.isChecked()and self.checkBox4.isChecked():
57 | self.textBrowser.setPlainText(begin + "(.+?)"+end)
58 | elif self.checkBox1.isChecked()and self.checkBox2.isChecked()and self.checkBox3.isChecked():
59 | self.textBrowser.setText(begin + "(.+?)(?="+end+")")
60 | elif self.checkBox1.isChecked()and self.checkBox3.isChecked()and self.checkBox4.isChecked():
61 | self.textBrowser.setText("(?<="+begin+")(.+?)"+end)
62 | elif self.checkBox1.isChecked()and self.checkBox3.isChecked():
63 | self.textBrowser.setText("(?<="+begin+")(.+?)(?="+end+")")
64 | else:
65 | self.textBrowser.setText("自动生成报错,请重新勾选")
66 | def pipei(self):
67 | try:
68 | self.textBrowser1.setText("")
69 | text = self.textEdit.toPlainText()
70 | test = self.textBrowser.toPlainText()
71 | result=re.finditer(test,text)
72 | result0 = []
73 | for i in result:
74 | result0.append(i[0])
75 | self.textBrowser1.setPlainText('\n'.join(result0))
76 | except:
77 | self.textBrowser1.setText("匹配失败,请重试")
78 | if self.textBrowser1.toPlainText()=='':
79 | self.textBrowser1.setText("未匹配到语句,请重试")
80 | def zhengze0(self):
81 | item = self.comboBox.currentText()
82 | item1=self.comboBox_2.currentText()
83 | with open('config/正则.txt','r',encoding='utf-8')as f:
84 | for i in f.readlines():
85 | if i.count('<--->')==1:
86 | if item == i.split('<--->')[0]:
87 | self.textBrowser.setText(i.split('<--->')[1].strip())
88 | elif i.count('<--->')==2:
89 | if item1 == i.split('<--->')[0]:
90 | self.lineEdit2_3.setText(i.split('<--->')[1].strip())
91 | self.lineEdit2_4.setText(i.split('<--->')[2].strip())
92 | def zhengze_list(self):
93 | self.ui.comboBox.clear()
94 | self.ui.comboBox.addItem('常用表达式')
95 | self.ui.comboBox_2.clear()
96 | self.ui.comboBox_2.addItem('常用替换模板')
97 | with open('config/正则.txt','r',encoding='utf-8')as f:
98 | list=[]
99 | list1=[]
100 | for i in f.readlines():
101 | if i.count('<--->') == 1:
102 | list.append(i.split('<--->')[0])
103 | elif i.count('<--->')==2:
104 | list1.append(i.split('<--->')[0])
105 | self.ui.comboBox.addItems(list)
106 | self.ui.comboBox_2.addItems(list1)
107 | def add1(self):
108 | text=self.textBrowser1.toPlainText()
109 | text=text.split('\n')
110 | self.textBrowser1.setText("")
111 | text0=[]
112 | for i in text:
113 | text0.append(self.lineEdit2_2.text()+i)
114 | self.textBrowser1.setPlainText('\n'.join(text0))
115 | def add2(self):
116 | text=self.textBrowser1.toPlainText()
117 | text=text.split('\n')
118 | self.textBrowser1.setText("")
119 | text0 = []
120 | for i in text:
121 | text0.append(i+self.lineEdit2_2.text())
122 | self.textBrowser1.setPlainText('\n'.join(text0))
123 | def minus(self):
124 | text = self.textBrowser1.toPlainText()
125 | text = text.split('\n')
126 | self.textBrowser1.setText("")
127 | text0 = []
128 | for i in text:
129 | text0.append(i.replace(self.lineEdit2_2.text(),''))
130 | self.textBrowser1.setPlainText('\n'.join(text0))
131 | def tihuan(self):
132 | text0=self.textBrowser1.toPlainText()
133 | try:
134 | text = re.sub(self.lineEdit2_3.text(), self.lineEdit2_4.text(),text0)
135 | self.textBrowser1.setPlainText(text)
136 | except:
137 | QMessageBox.about(self.ui, "错误", "正则匹配失败")
138 | self.textBrowser1.setPlainText(text0)
139 | def quchong(self):
140 | newtext = set()
141 | for text in self.textBrowser1.toPlainText().splitlines():
142 | newtext.add(text.strip())
143 | self.textBrowser1.setPlainText('\n'.join(newtext))
144 |
--------------------------------------------------------------------------------
/tabs/ui_main.py:
--------------------------------------------------------------------------------
1 | # -*- coding: utf-8 -*-
2 |
3 | # Form implementation generated from reading ui file 'ui_main.ui'
4 | #
5 | # Created by: PyQt5 UI code generator 5.15.10
6 | #
7 | # WARNING: Any manual changes made to this file will be lost when pyuic5 is
8 | # run again. Do not edit this file unless you know what you are doing.
9 |
10 |
11 | from PyQt5 import QtCore, QtGui, QtWidgets
12 |
13 |
14 | class Ui_Form(object):
15 | def setupUi(self, Form):
16 | Form.setObjectName("Form")
17 | Form.setEnabled(True)
18 | Form.resize(890, 510)
19 | Form.setMinimumSize(QtCore.QSize(890, 510))
20 | Form.setMaximumSize(QtCore.QSize(890, 510))
21 | icon = QtGui.QIcon("config/ico/link.ico")
22 | Form.setWindowIcon(icon)
23 | self.tabWidget = QtWidgets.QTabWidget(Form)
24 | self.tabWidget.setEnabled(True)
25 | self.tabWidget.setGeometry(QtCore.QRect(20, 10, 850, 475))
26 | self.tabWidget.setMouseTracking(True)
27 | self.tabWidget.setAcceptDrops(False)
28 | self.tabWidget.setObjectName("tabWidget")
29 | self.tab = QtWidgets.QWidget()
30 | self.tab.setObjectName("tab")
31 | self.pushButton3 = QtWidgets.QPushButton(self.tab)
32 | self.pushButton3.setGeometry(QtCore.QRect(530, 365, 131, 31))
33 | self.pushButton3.setObjectName("pushButton3")
34 | self.label = QtWidgets.QLabel(self.tab)
35 | self.label.setGeometry(QtCore.QRect(20, 10, 91, 16))
36 | self.label.setObjectName("label")
37 | self.label_4 = QtWidgets.QLabel(self.tab)
38 | self.label_4.setGeometry(QtCore.QRect(530, 10, 91, 16))
39 | self.label_4.setObjectName("label_4")
40 | self.checkBox3 = QtWidgets.QCheckBox(self.tab)
41 | self.checkBox3.setEnabled(False)
42 | self.checkBox3.setGeometry(QtCore.QRect(530, 70, 61, 16))
43 | self.checkBox3.setChecked(True)
44 | self.checkBox3.setObjectName("checkBox3")
45 | self.checkBox4 = QtWidgets.QCheckBox(self.tab)
46 | self.checkBox4.setGeometry(QtCore.QRect(590, 70, 81, 16))
47 | self.checkBox4.setObjectName("checkBox4")
48 | self.pushButton1 = QtWidgets.QPushButton(self.tab)
49 | self.pushButton1.setGeometry(QtCore.QRect(530, 215, 281, 31))
50 | self.pushButton1.setObjectName("pushButton1")
51 | self.textBrowser1 = QtWidgets.QTextBrowser(self.tab)
52 | self.textBrowser1.setGeometry(QtCore.QRect(20, 290, 491, 141))
53 | self.textBrowser1.setUndoRedoEnabled(True)
54 | self.textBrowser1.setReadOnly(False)
55 | self.textBrowser1.setAcceptRichText(False)
56 | self.textBrowser1.setObjectName("textBrowser1")
57 | self.label_2 = QtWidgets.QLabel(self.tab)
58 | self.label_2.setGeometry(QtCore.QRect(20, 260, 81, 16))
59 | self.label_2.setObjectName("label_2")
60 | self.pushButton2 = QtWidgets.QPushButton(self.tab)
61 | self.pushButton2.setGeometry(QtCore.QRect(670, 365, 141, 31))
62 | self.pushButton2.setFocusPolicy(QtCore.Qt.StrongFocus)
63 | self.pushButton2.setContextMenuPolicy(QtCore.Qt.DefaultContextMenu)
64 | self.pushButton2.setObjectName("pushButton2")
65 | self.lineEdit2 = QtWidgets.QLineEdit(self.tab)
66 | self.lineEdit2.setGeometry(QtCore.QRect(680, 70, 131, 21))
67 | self.lineEdit2.setText("")
68 | self.lineEdit2.setObjectName("lineEdit2")
69 | self.pushButton = QtWidgets.QPushButton(self.tab)
70 | self.pushButton.setGeometry(QtCore.QRect(530, 100, 281, 31))
71 | self.pushButton.setObjectName("pushButton")
72 | self.label_3 = QtWidgets.QLabel(self.tab)
73 | self.label_3.setGeometry(QtCore.QRect(530, 140, 81, 21))
74 | self.label_3.setObjectName("label_3")
75 | self.textBrowser = QtWidgets.QTextBrowser(self.tab)
76 | self.textBrowser.setGeometry(QtCore.QRect(530, 170, 281, 41))
77 | self.textBrowser.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
78 | self.textBrowser.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
79 | self.textBrowser.setUndoRedoEnabled(True)
80 | self.textBrowser.setReadOnly(False)
81 | self.textBrowser.setAcceptRichText(False)
82 | self.textBrowser.setObjectName("textBrowser")
83 | self.checkBox1 = QtWidgets.QCheckBox(self.tab)
84 | self.checkBox1.setEnabled(False)
85 | self.checkBox1.setGeometry(QtCore.QRect(530, 40, 61, 16))
86 | self.checkBox1.setAcceptDrops(False)
87 | self.checkBox1.setChecked(True)
88 | self.checkBox1.setObjectName("checkBox1")
89 | self.textEdit = QtWidgets.QTextEdit(self.tab)
90 | self.textEdit.setGeometry(QtCore.QRect(20, 40, 491, 206))
91 | self.textEdit.setUndoRedoEnabled(True)
92 | self.textEdit.setAcceptRichText(False)
93 | self.textEdit.setObjectName("textEdit")
94 | self.checkBox2 = QtWidgets.QCheckBox(self.tab)
95 | self.checkBox2.setGeometry(QtCore.QRect(590, 40, 81, 16))
96 | self.checkBox2.setObjectName("checkBox2")
97 | self.lineEdit1 = QtWidgets.QLineEdit(self.tab)
98 | self.lineEdit1.setGeometry(QtCore.QRect(680, 40, 131, 21))
99 | self.lineEdit1.setText("")
100 | self.lineEdit1.setObjectName("lineEdit1")
101 | self.comboBox = QtWidgets.QComboBox(self.tab)
102 | self.comboBox.setGeometry(QtCore.QRect(630, 140, 181, 25))
103 | self.comboBox.setObjectName("comboBox")
104 | self.comboBox.addItem("")
105 | self.lineEdit2_2 = QtWidgets.QLineEdit(self.tab)
106 | self.lineEdit2_2.setGeometry(QtCore.QRect(530, 327, 131, 31))
107 | self.lineEdit2_2.setText("")
108 | self.lineEdit2_2.setObjectName("lineEdit2_2")
109 | self.pushButton3_2 = QtWidgets.QPushButton(self.tab)
110 | self.pushButton3_2.setGeometry(QtCore.QRect(670, 327, 45, 31))
111 | self.pushButton3_2.setObjectName("pushButton3_2")
112 | self.pushButton3_3 = QtWidgets.QPushButton(self.tab)
113 | self.pushButton3_3.setGeometry(QtCore.QRect(718, 327, 45, 31))
114 | self.pushButton3_3.setObjectName("pushButton3_3")
115 | self.pushButton3_4 = QtWidgets.QPushButton(self.tab)
116 | self.pushButton3_4.setGeometry(QtCore.QRect(766, 327, 45, 31))
117 | self.pushButton3_4.setObjectName("pushButton3_4")
118 | self.lineEdit2_3 = QtWidgets.QLineEdit(self.tab)
119 | self.lineEdit2_3.setGeometry(QtCore.QRect(530, 290, 71, 31))
120 | self.lineEdit2_3.setText("")
121 | self.lineEdit2_3.setObjectName("lineEdit2_3")
122 | self.lineEdit2_4 = QtWidgets.QLineEdit(self.tab)
123 | self.lineEdit2_4.setGeometry(QtCore.QRect(610, 290, 51, 31))
124 | self.lineEdit2_4.setText("")
125 | self.lineEdit2_4.setObjectName("lineEdit2_4")
126 | self.pushButton3_5 = QtWidgets.QPushButton(self.tab)
127 | self.pushButton3_5.setGeometry(QtCore.QRect(670, 290, 141, 31))
128 | self.pushButton3_5.setObjectName("pushButton3_5")
129 | self.comboBox_2 = QtWidgets.QComboBox(self.tab)
130 | self.comboBox_2.setGeometry(QtCore.QRect(630, 260, 181, 25))
131 | self.comboBox_2.setObjectName("comboBox_2")
132 | self.comboBox_2.addItem("")
133 | self.label_10 = QtWidgets.QLabel(self.tab)
134 | self.label_10.setGeometry(QtCore.QRect(530, 260, 81, 21))
135 | self.label_10.setObjectName("label_10")
136 | self.pushButton3_6 = QtWidgets.QPushButton(self.tab)
137 | self.pushButton3_6.setGeometry(QtCore.QRect(530, 400, 281, 31))
138 | self.pushButton3_6.setObjectName("pushButton3_6")
139 | self.label.raise_()
140 | self.label_4.raise_()
141 | self.checkBox3.raise_()
142 | self.checkBox4.raise_()
143 | self.pushButton1.raise_()
144 | self.textBrowser1.raise_()
145 | self.label_2.raise_()
146 | self.lineEdit2.raise_()
147 | self.pushButton.raise_()
148 | self.label_3.raise_()
149 | self.textBrowser.raise_()
150 | self.checkBox1.raise_()
151 | self.textEdit.raise_()
152 | self.checkBox2.raise_()
153 | self.lineEdit1.raise_()
154 | self.pushButton3.raise_()
155 | self.pushButton2.raise_()
156 | self.comboBox.raise_()
157 | self.lineEdit2_2.raise_()
158 | self.pushButton3_2.raise_()
159 | self.pushButton3_3.raise_()
160 | self.pushButton3_4.raise_()
161 | self.lineEdit2_3.raise_()
162 | self.lineEdit2_4.raise_()
163 | self.pushButton3_5.raise_()
164 | self.comboBox_2.raise_()
165 | self.label_10.raise_()
166 | self.pushButton3_6.raise_()
167 | self.tabWidget.addTab(self.tab, "")
168 | self.tab_8 = QtWidgets.QWidget()
169 | self.tab_8.setEnabled(True)
170 | self.tab_8.setAcceptDrops(True)
171 | self.tab_8.setObjectName("tab_8")
172 | self.rolan_list_1 = QtWidgets.QListWidget(self.tab_8)
173 | self.rolan_list_1.setEnabled(True)
174 | self.rolan_list_1.setGeometry(QtCore.QRect(20, 20, 111, 411))
175 | self.rolan_list_1.setAcceptDrops(True)
176 | self.rolan_list_1.setStyleSheet("background-color: rgb(240,240,240);")
177 | self.rolan_list_1.setFrameShape(QtWidgets.QFrame.StyledPanel)
178 | self.rolan_list_1.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
179 | self.rolan_list_1.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
180 | self.rolan_list_1.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
181 | self.rolan_list_1.setProperty("showDropIndicator", True)
182 | self.rolan_list_1.setDragEnabled(True)
183 | self.rolan_list_1.setDragDropMode(QtWidgets.QAbstractItemView.InternalMove)
184 | self.rolan_list_1.setDefaultDropAction(QtCore.Qt.MoveAction)
185 | self.rolan_list_1.setObjectName("rolan_list_1")
186 | self.rolan_list_2 = QtWidgets.QListWidget(self.tab_8)
187 | self.rolan_list_2.setGeometry(QtCore.QRect(140, 20, 191, 411))
188 | self.rolan_list_2.setAcceptDrops(True)
189 | self.rolan_list_2.setFrameShape(QtWidgets.QFrame.Box)
190 | self.rolan_list_2.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded)
191 | self.rolan_list_2.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
192 | self.rolan_list_2.setSizeAdjustPolicy(QtWidgets.QAbstractScrollArea.AdjustIgnored)
193 | self.rolan_list_2.setEditTriggers(QtWidgets.QAbstractItemView.NoEditTriggers)
194 | self.rolan_list_2.setDragEnabled(True)
195 | self.rolan_list_2.setDragDropMode(QtWidgets.QAbstractItemView.InternalMove)
196 | self.rolan_list_2.setDefaultDropAction(QtCore.Qt.MoveAction)
197 | self.rolan_list_2.setObjectName("rolan_list_2")
198 | self.rolan_frame_1 = QtWidgets.QFrame(self.tab_8)
199 | self.rolan_frame_1.setEnabled(False)
200 | self.rolan_frame_1.setGeometry(QtCore.QRect(340, 250, 481, 181))
201 | self.rolan_frame_1.setFrameShape(QtWidgets.QFrame.StyledPanel)
202 | self.rolan_frame_1.setFrameShadow(QtWidgets.QFrame.Sunken)
203 | self.rolan_frame_1.setObjectName("rolan_frame_1")
204 | self.rolan_line_2 = QtWidgets.QLineEdit(self.rolan_frame_1)
205 | self.rolan_line_2.setGeometry(QtCore.QRect(30, 40, 441, 25))
206 | self.rolan_line_2.setText("")
207 | self.rolan_line_2.setPlaceholderText("")
208 | self.rolan_line_2.setObjectName("rolan_line_2")
209 | self.rolan_line_3 = QtWidgets.QLineEdit(self.rolan_frame_1)
210 | self.rolan_line_3.setGeometry(QtCore.QRect(30, 70, 441, 25))
211 | self.rolan_line_3.setText("")
212 | self.rolan_line_3.setPlaceholderText("")
213 | self.rolan_line_3.setObjectName("rolan_line_3")
214 | self.rolan_line_4 = QtWidgets.QLineEdit(self.rolan_frame_1)
215 | self.rolan_line_4.setGeometry(QtCore.QRect(30, 100, 441, 25))
216 | self.rolan_line_4.setText("")
217 | self.rolan_line_4.setPlaceholderText("")
218 | self.rolan_line_4.setObjectName("rolan_line_4")
219 | self.rolan_radio_1 = QtWidgets.QRadioButton(self.rolan_frame_1)
220 | self.rolan_radio_1.setGeometry(QtCore.QRect(10, 40, 20, 25))
221 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Minimum, QtWidgets.QSizePolicy.Minimum)
222 | sizePolicy.setHorizontalStretch(0)
223 | sizePolicy.setVerticalStretch(0)
224 | sizePolicy.setHeightForWidth(self.rolan_radio_1.sizePolicy().hasHeightForWidth())
225 | self.rolan_radio_1.setSizePolicy(sizePolicy)
226 | self.rolan_radio_1.setText("")
227 | self.rolan_radio_1.setChecked(True)
228 | self.rolan_radio_1.setObjectName("rolan_radio_1")
229 | self.rolan_radio_2 = QtWidgets.QRadioButton(self.rolan_frame_1)
230 | self.rolan_radio_2.setGeometry(QtCore.QRect(10, 70, 20, 25))
231 | self.rolan_radio_2.setText("")
232 | self.rolan_radio_2.setObjectName("rolan_radio_2")
233 | self.rolan_radio_3 = QtWidgets.QRadioButton(self.rolan_frame_1)
234 | self.rolan_radio_3.setGeometry(QtCore.QRect(10, 100, 20, 25))
235 | self.rolan_radio_3.setText("")
236 | self.rolan_radio_3.setObjectName("rolan_radio_3")
237 | self.rolan_Button_4 = QtWidgets.QPushButton(self.rolan_frame_1)
238 | self.rolan_Button_4.setGeometry(QtCore.QRect(10, 130, 221, 41))
239 | self.rolan_Button_4.setObjectName("rolan_Button_4")
240 | self.rolan_Button_5 = QtWidgets.QPushButton(self.rolan_frame_1)
241 | self.rolan_Button_5.setGeometry(QtCore.QRect(330, 130, 91, 41))
242 | self.rolan_Button_5.setObjectName("rolan_Button_5")
243 | self.rolan_Button_8 = QtWidgets.QPushButton(self.rolan_frame_1)
244 | self.rolan_Button_8.setGeometry(QtCore.QRect(230, 130, 101, 41))
245 | self.rolan_Button_8.setObjectName("rolan_Button_8")
246 | self.rolan_line_1 = QtWidgets.QLineEdit(self.rolan_frame_1)
247 | self.rolan_line_1.setGeometry(QtCore.QRect(50, 8, 301, 25))
248 | self.rolan_line_1.setText("")
249 | self.rolan_line_1.setPlaceholderText("")
250 | self.rolan_line_1.setObjectName("rolan_line_1")
251 | self.label_5 = QtWidgets.QLabel(self.rolan_frame_1)
252 | self.label_5.setGeometry(QtCore.QRect(10, 10, 41, 20))
253 | self.label_5.setObjectName("label_5")
254 | self.rolan_Button_9 = QtWidgets.QPushButton(self.rolan_frame_1)
255 | self.rolan_Button_9.setGeometry(QtCore.QRect(420, 130, 51, 41))
256 | self.rolan_Button_9.setObjectName("rolan_Button_9")
257 | self.comboBox_3 = QtWidgets.QComboBox(self.rolan_frame_1)
258 | self.comboBox_3.setGeometry(QtCore.QRect(360, 8, 111, 25))
259 | self.comboBox_3.setObjectName("comboBox_3")
260 | self.comboBox_3.addItem("")
261 | self.rolan_textBrowser_2 = QtWidgets.QTextBrowser(self.tab_8)
262 | self.rolan_textBrowser_2.setEnabled(True)
263 | self.rolan_textBrowser_2.setGeometry(QtCore.QRect(340, 20, 351, 181))
264 | self.rolan_textBrowser_2.setAcceptDrops(True)
265 | self.rolan_textBrowser_2.setFrameShape(QtWidgets.QFrame.Box)
266 | self.rolan_textBrowser_2.setFrameShadow(QtWidgets.QFrame.Sunken)
267 | self.rolan_textBrowser_2.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
268 | self.rolan_textBrowser_2.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded)
269 | self.rolan_textBrowser_2.setUndoRedoEnabled(True)
270 | self.rolan_textBrowser_2.setLineWrapMode(QtWidgets.QTextEdit.NoWrap)
271 | self.rolan_textBrowser_2.setReadOnly(False)
272 | self.rolan_textBrowser_2.setHtml("\n"
273 | "
\n"
276 | "
")
277 | self.rolan_textBrowser_2.setOverwriteMode(False)
278 | self.rolan_textBrowser_2.setTabStopWidth(80)
279 | self.rolan_textBrowser_2.setAcceptRichText(False)
280 | self.rolan_textBrowser_2.setCursorWidth(1)
281 | self.rolan_textBrowser_2.setOpenExternalLinks(False)
282 | self.rolan_textBrowser_2.setOpenLinks(False)
283 | self.rolan_textBrowser_2.setObjectName("rolan_textBrowser_2")
284 | self.rolan_line_7 = QtWidgets.QLineEdit(self.tab_8)
285 | self.rolan_line_7.setEnabled(False)
286 | self.rolan_line_7.setGeometry(QtCore.QRect(0, 0, 0, 0))
287 | self.rolan_line_7.setObjectName("rolan_line_7")
288 | self.rolan_Button_6 = QtWidgets.QPushButton(self.tab_8)
289 | self.rolan_Button_6.setGeometry(QtCore.QRect(700, 210, 121, 31))
290 | self.rolan_Button_6.setObjectName("rolan_Button_6")
291 | self.rolan_list_3 = QtWidgets.QListWidget(self.tab_8)
292 | self.rolan_list_3.setEnabled(False)
293 | self.rolan_list_3.setGeometry(QtCore.QRect(700, 20, 121, 181))
294 | self.rolan_list_3.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded)
295 | self.rolan_list_3.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
296 | self.rolan_list_3.setSelectionMode(QtWidgets.QAbstractItemView.SingleSelection)
297 | self.rolan_list_3.setObjectName("rolan_list_3")
298 | self.rolan_line_6 = QtWidgets.QLineEdit(self.tab_8)
299 | self.rolan_line_6.setEnabled(True)
300 | self.rolan_line_6.setGeometry(QtCore.QRect(340, 210, 71, 31))
301 | self.rolan_line_6.setStyleSheet("")
302 | self.rolan_line_6.setText("")
303 | self.rolan_line_6.setEchoMode(QtWidgets.QLineEdit.Normal)
304 | self.rolan_line_6.setReadOnly(True)
305 | self.rolan_line_6.setObjectName("rolan_line_6")
306 | self.rolan_Button_7 = QtWidgets.QPushButton(self.tab_8)
307 | self.rolan_Button_7.setGeometry(QtCore.QRect(640, 210, 51, 31))
308 | self.rolan_Button_7.setObjectName("rolan_Button_7")
309 | self.rolan_line_5 = QtWidgets.QLineEdit(self.tab_8)
310 | self.rolan_line_5.setGeometry(QtCore.QRect(420, 210, 91, 31))
311 | self.rolan_line_5.setEchoMode(QtWidgets.QLineEdit.Normal)
312 | self.rolan_line_5.setObjectName("rolan_line_5")
313 | self.rolan_Button_2 = QtWidgets.QPushButton(self.tab_8)
314 | self.rolan_Button_2.setGeometry(QtCore.QRect(560, 210, 41, 31))
315 | self.rolan_Button_2.setObjectName("rolan_Button_2")
316 | self.rolan_Button_1 = QtWidgets.QPushButton(self.tab_8)
317 | self.rolan_Button_1.setGeometry(QtCore.QRect(520, 210, 41, 31))
318 | self.rolan_Button_1.setObjectName("rolan_Button_1")
319 | self.rolan_Button_3 = QtWidgets.QPushButton(self.tab_8)
320 | self.rolan_Button_3.setGeometry(QtCore.QRect(600, 210, 41, 31))
321 | self.rolan_Button_3.setObjectName("rolan_Button_3")
322 | self.rolan_list_4 = QtWidgets.QListWidget(self.tab_8)
323 | self.rolan_list_4.setEnabled(True)
324 | self.rolan_list_4.setGeometry(QtCore.QRect(565, 25, 121, 171))
325 | self.rolan_list_4.setFrameShape(QtWidgets.QFrame.StyledPanel)
326 | self.rolan_list_4.setFrameShadow(QtWidgets.QFrame.Plain)
327 | self.rolan_list_4.setVerticalScrollBarPolicy(QtCore.Qt.ScrollBarAsNeeded)
328 | self.rolan_list_4.setHorizontalScrollBarPolicy(QtCore.Qt.ScrollBarAlwaysOff)
329 | self.rolan_list_4.setSelectionMode(QtWidgets.QAbstractItemView.SingleSelection)
330 | self.rolan_list_4.setFlow(QtWidgets.QListView.TopToBottom)
331 | self.rolan_list_4.setObjectName("rolan_list_4")
332 | self.rolan_frame_1.raise_()
333 | self.rolan_textBrowser_2.raise_()
334 | self.rolan_line_7.raise_()
335 | self.rolan_Button_6.raise_()
336 | self.rolan_list_3.raise_()
337 | self.rolan_line_6.raise_()
338 | self.rolan_Button_7.raise_()
339 | self.rolan_line_5.raise_()
340 | self.rolan_Button_2.raise_()
341 | self.rolan_Button_1.raise_()
342 | self.rolan_Button_3.raise_()
343 | self.rolan_list_1.raise_()
344 | self.rolan_list_2.raise_()
345 | self.rolan_list_4.raise_()
346 | self.tabWidget.addTab(self.tab_8, "")
347 | self.tab_2 = QtWidgets.QWidget()
348 | self.tab_2.setObjectName("tab_2")
349 | self.tabWidget_2 = QtWidgets.QTabWidget(self.tab_2)
350 | self.tabWidget_2.setGeometry(QtCore.QRect(10, 10, 821, 431))
351 | self.tabWidget_2.setObjectName("tabWidget_2")
352 | self.tab_9 = QtWidgets.QWidget()
353 | self.tab_9.setObjectName("tab_9")
354 | self.input_edit = QtWidgets.QTextEdit(self.tab_9)
355 | self.input_edit.setGeometry(QtCore.QRect(10, 30, 391, 101))
356 | self.input_edit.setFrameShape(QtWidgets.QFrame.Box)
357 | self.input_edit.setFrameShadow(QtWidgets.QFrame.Sunken)
358 | self.input_edit.setUndoRedoEnabled(True)
359 | self.input_edit.setAcceptRichText(False)
360 | self.input_edit.setObjectName("input_edit")
361 | self.label_input1 = QtWidgets.QLabel(self.tab_9)
362 | self.label_input1.setGeometry(QtCore.QRect(10, 10, 391, 16))
363 | self.label_input1.setObjectName("label_input1")
364 | self.input_edit_1 = QtWidgets.QTextEdit(self.tab_9)
365 | self.input_edit_1.setGeometry(QtCore.QRect(410, 30, 391, 101))
366 | self.input_edit_1.setFrameShape(QtWidgets.QFrame.Box)
367 | self.input_edit_1.setUndoRedoEnabled(True)
368 | self.input_edit_1.setAcceptRichText(False)
369 | self.input_edit_1.setObjectName("input_edit_1")
370 | self.label_input2 = QtWidgets.QLabel(self.tab_9)
371 | self.label_input2.setGeometry(QtCore.QRect(410, 10, 391, 16))
372 | self.label_input2.setObjectName("label_input2")
373 | self.send_btn = QtWidgets.QPushButton(self.tab_9)
374 | self.send_btn.setGeometry(QtCore.QRect(600, 140, 201, 31))
375 | self.send_btn.setObjectName("send_btn")
376 | self.output_area = QtWidgets.QTextEdit(self.tab_9)
377 | self.output_area.setGeometry(QtCore.QRect(10, 180, 791, 221))
378 | self.output_area.setFrameShape(QtWidgets.QFrame.Box)
379 | self.output_area.setUndoRedoEnabled(True)
380 | self.output_area.setAcceptRichText(True)
381 | self.output_area.setObjectName("output_area")
382 | self.config_combo_1 = QtWidgets.QComboBox(self.tab_9)
383 | self.config_combo_1.setGeometry(QtCore.QRect(450, 140, 141, 31))
384 | font = QtGui.QFont()
385 | font.setPointSize(9)
386 | font.setKerning(False)
387 | self.config_combo_1.setFont(font)
388 | self.config_combo_1.setObjectName("config_combo_1")
389 | self.timeout_input = QtWidgets.QLineEdit(self.tab_9)
390 | self.timeout_input.setEnabled(True)
391 | self.timeout_input.setGeometry(QtCore.QRect(50, 140, 31, 31))
392 | self.timeout_input.setStyleSheet("")
393 | self.timeout_input.setEchoMode(QtWidgets.QLineEdit.Normal)
394 | self.timeout_input.setReadOnly(False)
395 | self.timeout_input.setObjectName("timeout_input")
396 | self.label_8 = QtWidgets.QLabel(self.tab_9)
397 | self.label_8.setGeometry(QtCore.QRect(410, 150, 30, 12))
398 | self.label_8.setObjectName("label_8")
399 | self.label_9 = QtWidgets.QLabel(self.tab_9)
400 | self.label_9.setGeometry(QtCore.QRect(10, 150, 30, 12))
401 | self.label_9.setObjectName("label_9")
402 | self.prompt_combo_1 = QtWidgets.QComboBox(self.tab_9)
403 | self.prompt_combo_1.setGeometry(QtCore.QRect(230, 140, 171, 31))
404 | font = QtGui.QFont()
405 | font.setPointSize(9)
406 | font.setKerning(False)
407 | self.prompt_combo_1.setFont(font)
408 | self.prompt_combo_1.setObjectName("prompt_combo_1")
409 | self.label_11 = QtWidgets.QLabel(self.tab_9)
410 | self.label_11.setGeometry(QtCore.QRect(180, 150, 40, 12))
411 | self.label_11.setObjectName("label_11")
412 | self.size_emit = QtWidgets.QLineEdit(self.tab_9)
413 | self.size_emit.setEnabled(True)
414 | self.size_emit.setGeometry(QtCore.QRect(130, 140, 41, 31))
415 | self.size_emit.setStyleSheet("")
416 | self.size_emit.setEchoMode(QtWidgets.QLineEdit.Normal)
417 | self.size_emit.setReadOnly(False)
418 | self.size_emit.setObjectName("size_emit")
419 | self.label_19 = QtWidgets.QLabel(self.tab_9)
420 | self.label_19.setGeometry(QtCore.QRect(90, 150, 30, 12))
421 | self.label_19.setObjectName("label_19")
422 | self.tabWidget_2.addTab(self.tab_9, "")
423 | self.tab_6 = QtWidgets.QWidget()
424 | self.tab_6.setObjectName("tab_6")
425 | self.prompt_edit = QtWidgets.QTextEdit(self.tab_6)
426 | self.prompt_edit.setGeometry(QtCore.QRect(10, 10, 381, 391))
427 | self.prompt_edit.setFrameShape(QtWidgets.QFrame.Box)
428 | self.prompt_edit.setUndoRedoEnabled(True)
429 | self.prompt_edit.setAcceptRichText(False)
430 | self.prompt_edit.setObjectName("prompt_edit")
431 | self.groupBox_2 = QtWidgets.QGroupBox(self.tab_6)
432 | self.groupBox_2.setGeometry(QtCore.QRect(410, 10, 381, 91))
433 | self.groupBox_2.setObjectName("groupBox_2")
434 | self.prompt_combo = QtWidgets.QComboBox(self.groupBox_2)
435 | self.prompt_combo.setGeometry(QtCore.QRect(10, 20, 361, 25))
436 | font = QtGui.QFont()
437 | font.setPointSize(9)
438 | font.setKerning(False)
439 | self.prompt_combo.setFont(font)
440 | self.prompt_combo.setObjectName("prompt_combo")
441 | self.delete_btn = QtWidgets.QPushButton(self.groupBox_2)
442 | self.delete_btn.setGeometry(QtCore.QRect(280, 50, 91, 31))
443 | self.delete_btn.setObjectName("delete_btn")
444 | self.save_prompt_btn = QtWidgets.QPushButton(self.groupBox_2)
445 | self.save_prompt_btn.setGeometry(QtCore.QRect(190, 50, 91, 31))
446 | self.save_prompt_btn.setObjectName("save_prompt_btn")
447 | self.new_btn = QtWidgets.QPushButton(self.groupBox_2)
448 | self.new_btn.setGeometry(QtCore.QRect(100, 50, 91, 31))
449 | self.new_btn.setObjectName("new_btn")
450 | self.refresh_btn = QtWidgets.QPushButton(self.groupBox_2)
451 | self.refresh_btn.setGeometry(QtCore.QRect(10, 50, 91, 31))
452 | self.refresh_btn.setObjectName("refresh_btn")
453 | self.groupBox = QtWidgets.QGroupBox(self.tab_6)
454 | self.groupBox.setGeometry(QtCore.QRect(410, 110, 381, 181))
455 | self.groupBox.setObjectName("groupBox")
456 | self.config_combo = QtWidgets.QComboBox(self.groupBox)
457 | self.config_combo.setGeometry(QtCore.QRect(10, 20, 361, 25))
458 | font = QtGui.QFont()
459 | font.setPointSize(9)
460 | font.setKerning(False)
461 | self.config_combo.setFont(font)
462 | self.config_combo.setObjectName("config_combo")
463 | self.conf_api_key = QtWidgets.QLineEdit(self.groupBox)
464 | self.conf_api_key.setEnabled(True)
465 | self.conf_api_key.setGeometry(QtCore.QRect(50, 50, 321, 25))
466 | sizePolicy = QtWidgets.QSizePolicy(QtWidgets.QSizePolicy.Expanding, QtWidgets.QSizePolicy.Fixed)
467 | sizePolicy.setHorizontalStretch(0)
468 | sizePolicy.setVerticalStretch(0)
469 | sizePolicy.setHeightForWidth(self.conf_api_key.sizePolicy().hasHeightForWidth())
470 | self.conf_api_key.setSizePolicy(sizePolicy)
471 | self.conf_api_key.setStyleSheet("")
472 | self.conf_api_key.setText("")
473 | self.conf_api_key.setEchoMode(QtWidgets.QLineEdit.Password)
474 | self.conf_api_key.setReadOnly(False)
475 | self.conf_api_key.setObjectName("conf_api_key")
476 | self.label_12 = QtWidgets.QLabel(self.groupBox)
477 | self.label_12.setGeometry(QtCore.QRect(10, 50, 41, 25))
478 | self.label_12.setObjectName("label_12")
479 | self.label_13 = QtWidgets.QLabel(self.groupBox)
480 | self.label_13.setGeometry(QtCore.QRect(10, 80, 41, 25))
481 | self.label_13.setObjectName("label_13")
482 | self.label_20 = QtWidgets.QLabel(self.groupBox)
483 | self.label_20.setGeometry(QtCore.QRect(10, 110, 41, 25))
484 | self.label_20.setObjectName("label_20")
485 | self.conf_model = QtWidgets.QLineEdit(self.groupBox)
486 | self.conf_model.setEnabled(True)
487 | self.conf_model.setGeometry(QtCore.QRect(50, 110, 321, 25))
488 | self.conf_model.setMouseTracking(True)
489 | self.conf_model.setAcceptDrops(True)
490 | self.conf_model.setStyleSheet("")
491 | self.conf_model.setText("")
492 | self.conf_model.setEchoMode(QtWidgets.QLineEdit.Normal)
493 | self.conf_model.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter)
494 | self.conf_model.setDragEnabled(False)
495 | self.conf_model.setReadOnly(False)
496 | self.conf_model.setCursorMoveStyle(QtCore.Qt.LogicalMoveStyle)
497 | self.conf_model.setClearButtonEnabled(False)
498 | self.conf_model.setObjectName("conf_model")
499 | self.conf_api_base = QtWidgets.QLineEdit(self.groupBox)
500 | self.conf_api_base.setEnabled(True)
501 | self.conf_api_base.setGeometry(QtCore.QRect(50, 80, 321, 25))
502 | self.conf_api_base.setMouseTracking(True)
503 | self.conf_api_base.setAcceptDrops(True)
504 | self.conf_api_base.setStyleSheet("")
505 | self.conf_api_base.setText("")
506 | self.conf_api_base.setEchoMode(QtWidgets.QLineEdit.Normal)
507 | self.conf_api_base.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignVCenter)
508 | self.conf_api_base.setDragEnabled(False)
509 | self.conf_api_base.setReadOnly(False)
510 | self.conf_api_base.setCursorMoveStyle(QtCore.Qt.LogicalMoveStyle)
511 | self.conf_api_base.setClearButtonEnabled(False)
512 | self.conf_api_base.setObjectName("conf_api_base")
513 | self.refresh_btn_2 = QtWidgets.QPushButton(self.groupBox)
514 | self.refresh_btn_2.setGeometry(QtCore.QRect(10, 140, 91, 31))
515 | self.refresh_btn_2.setObjectName("refresh_btn_2")
516 | self.new_config_btn = QtWidgets.QPushButton(self.groupBox)
517 | self.new_config_btn.setGeometry(QtCore.QRect(100, 140, 91, 31))
518 | self.new_config_btn.setObjectName("new_config_btn")
519 | self.save_config_btn = QtWidgets.QPushButton(self.groupBox)
520 | self.save_config_btn.setGeometry(QtCore.QRect(190, 140, 91, 31))
521 | self.save_config_btn.setObjectName("save_config_btn")
522 | self.del_config_btn = QtWidgets.QPushButton(self.groupBox)
523 | self.del_config_btn.setGeometry(QtCore.QRect(280, 140, 91, 31))
524 | self.del_config_btn.setObjectName("del_config_btn")
525 | self.groupBox_3 = QtWidgets.QGroupBox(self.tab_6)
526 | self.groupBox_3.setGeometry(QtCore.QRect(410, 310, 381, 91))
527 | self.groupBox_3.setObjectName("groupBox_3")
528 | self.label_6 = QtWidgets.QLabel(self.groupBox_3)
529 | self.label_6.setGeometry(QtCore.QRect(10, 20, 361, 61))
530 | self.label_6.setFrameShadow(QtWidgets.QFrame.Plain)
531 | self.label_6.setLineWidth(0)
532 | self.label_6.setTextFormat(QtCore.Qt.AutoText)
533 | self.label_6.setAlignment(QtCore.Qt.AlignLeading|QtCore.Qt.AlignLeft|QtCore.Qt.AlignTop)
534 | self.label_6.setWordWrap(True)
535 | self.label_6.setObjectName("label_6")
536 | self.groupBox_2.raise_()
537 | self.prompt_edit.raise_()
538 | self.groupBox.raise_()
539 | self.groupBox_3.raise_()
540 | self.tabWidget_2.addTab(self.tab_6, "")
541 | self.tabWidget.addTab(self.tab_2, "")
542 | self.tab_3 = QtWidgets.QWidget()
543 | self.tab_3.setObjectName("tab_3")
544 | self.tabs_button = QtWidgets.QPushButton(self.tab_3)
545 | self.tabs_button.setGeometry(QtCore.QRect(470, 180, 75, 25))
546 | self.tabs_button.setObjectName("tabs_button")
547 | self.tabs_combox = QtWidgets.QComboBox(self.tab_3)
548 | self.tabs_combox.setGeometry(QtCore.QRect(350, 180, 111, 25))
549 | self.tabs_combox.setObjectName("tabs_combox")
550 | self.label_21 = QtWidgets.QLabel(self.tab_3)
551 | self.label_21.setGeometry(QtCore.QRect(280, 180, 61, 21))
552 | self.label_21.setObjectName("label_21")
553 | self.tabWidget.addTab(self.tab_3, "")
554 |
555 | self.retranslateUi(Form)
556 | self.tabWidget.setCurrentIndex(0)
557 | self.tabWidget_2.setCurrentIndex(0)
558 | QtCore.QMetaObject.connectSlotsByName(Form)
559 |
560 | def retranslateUi(self, Form):
561 | _translate = QtCore.QCoreApplication.translate
562 | Form.setWindowTitle(_translate("Form", "link-tools v1.3 By:Github/lintx0"))
563 | self.pushButton3.setText(_translate("Form", "复制结果"))
564 | self.label.setText(_translate("Form", "测试文本:"))
565 | self.label_4.setText(_translate("Form", "自动生成:"))
566 | self.checkBox3.setText(_translate("Form", "结束"))
567 | self.checkBox4.setText(_translate("Form", "包含结束"))
568 | self.pushButton1.setText(_translate("Form", "匹配测试"))
569 | self.label_2.setText(_translate("Form", "匹配结果:"))
570 | self.pushButton2.setText(_translate("Form", "复制表达式"))
571 | self.pushButton.setText(_translate("Form", "自动生成"))
572 | self.label_3.setText(_translate("Form", "正则表达式:"))
573 | self.textBrowser.setHtml(_translate("Form", "\n"
574 | "\n"
577 | "
"))
578 | self.checkBox1.setText(_translate("Form", "开始"))
579 | self.checkBox2.setText(_translate("Form", "包含开始"))
580 | self.comboBox.setItemText(0, _translate("Form", "常用表达式"))
581 | self.pushButton3_2.setText(_translate("Form", "←"))
582 | self.pushButton3_3.setText(_translate("Form", "→"))
583 | self.pushButton3_4.setText(_translate("Form", "-"))
584 | self.pushButton3_5.setText(_translate("Form", "正则替换"))
585 | self.comboBox_2.setItemText(0, _translate("Form", "常用替换模板"))
586 | self.label_10.setText(_translate("Form", "结果处理:"))
587 | self.pushButton3_6.setText(_translate("Form", "数据去重"))
588 | self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab), _translate("Form", "正则"))
589 | self.rolan_Button_4.setText(_translate("Form", "启动/运行"))
590 | self.rolan_Button_5.setText(_translate("Form", "保存"))
591 | self.rolan_Button_8.setText(_translate("Form", "输出/日志"))
592 | self.label_5.setText(_translate("Form", "备注:"))
593 | self.rolan_Button_9.setText(_translate("Form", "说明"))
594 | self.comboBox_3.setItemText(0, _translate("Form", "服务类型"))
595 | self.rolan_line_7.setPlaceholderText(_translate("Form", "数据路径"))
596 | self.rolan_Button_6.setText(_translate("Form", "导入Raid+数据"))
597 | self.rolan_Button_7.setText(_translate("Form", "清空"))
598 | self.rolan_line_5.setText(_translate("Form", "http://"))
599 | self.rolan_Button_2.setText(_translate("Form", "→"))
600 | self.rolan_Button_1.setText(_translate("Form", "←"))
601 | self.rolan_Button_3.setText(_translate("Form", "-"))
602 | self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_8), _translate("Form", "Rolan+"))
603 | self.label_input1.setText(_translate("Form", "[输入1]"))
604 | self.label_input2.setText(_translate("Form", "[输入2]"))
605 | self.send_btn.setText(_translate("Form", "AI分析和处理"))
606 | self.timeout_input.setText(_translate("Form", "10"))
607 | self.label_8.setText(_translate("Form", "模型:"))
608 | self.label_9.setText(_translate("Form", "超时:"))
609 | self.label_11.setText(_translate("Form", "提示词:"))
610 | self.size_emit.setText(_translate("Form", "3000"))
611 | self.label_19.setText(_translate("Form", "字符:"))
612 | self.tabWidget_2.setTabText(self.tabWidget_2.indexOf(self.tab_9), _translate("Form", "AI+"))
613 | self.prompt_edit.setHtml(_translate("Form", "\n"
614 | "\n"
617 | "
"))
618 | self.groupBox_2.setTitle(_translate("Form", "提示词:"))
619 | self.delete_btn.setText(_translate("Form", "删除"))
620 | self.save_prompt_btn.setText(_translate("Form", "修改"))
621 | self.new_btn.setText(_translate("Form", "新增"))
622 | self.refresh_btn.setText(_translate("Form", "刷新"))
623 | self.groupBox.setTitle(_translate("Form", "AI模型:"))
624 | self.conf_api_key.setPlaceholderText(_translate("Form", "KEY置空为Ollama模式"))
625 | self.label_12.setText(_translate("Form", "KEY:"))
626 | self.label_13.setText(_translate("Form", "接口:"))
627 | self.label_20.setText(_translate("Form", "模型:"))
628 | self.refresh_btn_2.setText(_translate("Form", "刷新"))
629 | self.new_config_btn.setText(_translate("Form", "新增"))
630 | self.save_config_btn.setText(_translate("Form", "修改"))
631 | self.del_config_btn.setText(_translate("Form", "删除"))
632 | self.groupBox_3.setTitle(_translate("Form", "使用说明:"))
633 | self.label_6.setText(_translate("Form", "1、支持OpenAI库API接入\n"
634 | "(如DeepSeek、腾讯云、阿里云、硅基流动等,其他自测)\n"
635 | "2、支持Ollama本地部署接入\n"
636 | "3、支持自定义提示词,输入标识:[输入1][输入2]"))
637 | self.tabWidget_2.setTabText(self.tabWidget_2.indexOf(self.tab_6), _translate("Form", "配置"))
638 | self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_2), _translate("Form", "AI+"))
639 | self.tabs_button.setText(_translate("Form", "保存"))
640 | self.label_21.setText(_translate("Form", "首页模块:"))
641 | self.tabWidget.setTabText(self.tabWidget.indexOf(self.tab_3), _translate("Form", "配置"))
642 |
--------------------------------------------------------------------------------
/tools/RapidScanner.exe:
--------------------------------------------------------------------------------
https://raw.githubusercontent.com/lintx0/link-tools/8b146616106348ee16da0541204468deac94d662/tools/RapidScanner.exe
--------------------------------------------------------------------------------