├── 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 | ![image](https://github.com/user-attachments/assets/0998f74e-0489-4d64-b5c6-52c25813efa7) 11 | ![image](https://github.com/user-attachments/assets/d9694840-e264-4f70-9cce-d0ad401ecaab) 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 | ![image](https://github.com/user-attachments/assets/3f3dabc2-a8fb-4de5-9c36-979cf0399480) 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 | ![image](https://github.com/user-attachments/assets/4b4ad3b0-0f3b-4165-a8b4-c8d7a1721188) 45 | ![image](https://github.com/user-attachments/assets/d701ceb7-0878-49f3-8f08-1bbd6f70f718) 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 | ![image](https://github.com/user-attachments/assets/37d669c2-8e1c-4817-b97e-7f6ccf9c0537) 60 | ![image](https://github.com/user-attachments/assets/794fe439-8c16-4db0-800c-a07b82a1530e) 61 | ![image](https://github.com/user-attachments/assets/ecba6fe9-7c37-444c-9d4c-45cce258308a) 62 | 63 | ## link-tools工具箱 64 | 65 | link-tools为一款Windows GUI界面的渗透测试工具箱(仿rolan启动器),支持拖拉新增工具(脚本、文件夹),支持自定义运行参数和备注,支持bat批量运行脚本,支持RapidScanner端口扫描结果服务指纹联动工具,可协助安全运维人员快速运行工具(脚本、文件夹),提高安全检测效率。 66 | ![image](https://github.com/user-attachments/assets/5f12f86c-4527-4b7a-af30-bf3e12f08665) 67 | ## 使用方法: 68 | 69 | ### 1. 工具添加: 70 | 71 | **右键新建分组,拖拉新增工具** 72 | 73 | #### 1.1 分组栏支持: 74 | 75 | - 拖拉排序、刷新、新增、重命名、删除 76 | 77 | #### 1.2 工具栏支持: 78 | 79 | - 拖拉新增工具(文件夹)、拖拉排序、双击打开、右键打开、打开目录、刷新、新增、重命名、删除、配置文件、移动分组 80 | 81 | ![image](https://github.com/user-attachments/assets/5e365e08-804e-4e50-be83-58c2281509a7) 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 | ![image](https://github.com/user-attachments/assets/83bdd62d-f456-4f24-bbe6-765c1e009f98) 110 | 111 | ### 3. 工具启动 112 | 113 | 图形化工具:支持双击运行、右键打开运行 114 | 115 | 脚本工具(带参数):选择要运行的命令,使用【启动/运行】按钮运行 116 | ![image](https://github.com/user-attachments/assets/0f216f9c-a552-4bea-bc42-57caf34f6fde) 117 | 118 | ### 4. RapidScanner工具联动 119 | 120 | 支持导入处理RapidScanner扫描结果scan_result.txt数据,并输出处理结果到文件夹 121 | 122 | #### 4.1 扫描数据 123 | ![image](https://github.com/user-attachments/assets/a789dd9a-9f76-4070-88ef-17a7f5097360) 124 | 125 | 126 | #### 4.2 导入数据 127 | ![image](https://github.com/user-attachments/assets/6bb0895f-9035-4ea6-930b-4f4291f805c5) 128 | 129 | **处理后的端口数据保存到result目录下,二次导入数据可使用文件夹方式导入** 130 | 131 | ![image](https://github.com/user-attachments/assets/39a791b8-cf64-4dc0-9f8e-5abb98ab372f) 132 | #### 4.3 展示数据 133 | ![image](https://github.com/user-attachments/assets/588129e6-0479-4024-996c-82ca968cf2b0) 134 | 135 | 136 | #### 4.4 工具联动 137 | 常用工具提前配置**服务类型**,选中数据时**展示工具快捷入口**,点击工具可**快速加载工具启动参数**数据。 138 | ![image](https://github.com/user-attachments/assets/63dbe486-ef37-4c0e-8a88-7a2763de8ecc) 139 | 140 | ### 5. 使用示例 141 | 142 | 可快速联动各种工具,一键运行,提高效率。 143 | ![image](https://github.com/user-attachments/assets/c0ed33cd-adbe-4d88-aa11-42f5328f4a53) 144 | 145 | ### 6. 正则小工具 146 | 147 | 支持快速生成和匹配简单正则表达式,处理数据。支持自定义常用表达式,配置文件config/正则.txt 148 | ![image](https://github.com/user-attachments/assets/2edf0b44-c516-4b03-a3bd-0c92b477e57b) 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 --------------------------------------------------------------------------------