Dev (#37)
* 滚木 * feat: 重构核心架构,增强类型安全与插件管理 本次提交对核心模块进行了深度重构,引入 Pydantic 增强配置管理的类型安全性,并全面优化了插件管理系统。 主要变更详情: 1. 核心架构与配置 - 重构配置加载模块:引入 Pydantic 模型 (`core/config_models.py`),提供严格的配置项类型检查、验证及默认值管理。 - 统一模块结构:规范化模块导入路径,移除冗余的 `__init__.py` 文件,提升项目结构的清晰度。 - 性能优化:集成 Redis 缓存支持 (`RedisManager`),有效降低高频 API 调用开销,提升响应速度。 2. 插件系统升级 - 实现热重载机制:新增插件文件变更监听功能,支持开发过程中自动重载插件,提升开发效率。 - 优化生命周期管理:改进插件加载与卸载逻辑,支持精确卸载指定插件及其关联的命令、事件处理器和定时任务。 3. 功能特性增强 - 新增媒体 API:引入 `MediaAPI` 模块,封装图片、语音等富媒体资源的获取与处理接口。 - 完善权限体系:重构权限管理系统,实现管理员与操作员的分级控制,支持更细粒度的命令权限校验。 4. 代码质量与稳定性 - 全面类型修复:解决 `mypy` 静态类型检查发现的大量类型错误(包括 `CommandManager`、`EventFactory` 及 `Bot` API 签名不匹配问题)。 - 增强错误处理:优化消息处理管道的异常捕获机制,完善关键路径的日志记录,提升系统运行稳定性。 * feat: 添加测试用例并优化代码结构 refactor(permission_manager): 调整初始化顺序和逻辑 fix(admin_manager): 修复初始化逻辑和目录创建问题 feat(ws): 优化Bot实例初始化条件 feat(message): 增强MessageSegment功能并添加测试 feat(events): 支持字符串格式的消息解析 test: 添加核心功能测试用例 refactor(plugin_manager): 改进插件路径处理 style: 清理无用导入和代码 chore: 更新依赖项 * refactor(handler): 移除TYPE_CHECKING并直接导入Bot类 简化类型注解,直接导入Bot类而非使用TYPE_CHECKING条件导入,提高代码可读性和维护性 * fix(command_manager): 修复插件卸载时元信息移除不精确的问题 修复 CommandManager 中 unload_plugin 方法移除插件元信息时使用 startswith 导致可能误删其他插件的问题,改为精确匹配 同时调整相关测试用例验证精确匹配行为 * refactor: 清理未使用的导入和更新文档结构 docs: 添加config_models.py到项目结构文档 docs: 调整数据目录位置到core/data下 docs: 更新权限管理器文档描述 * 文档更新 * 更新thpic插件 支持一次返回多张图 * feat: 添加测试覆盖率并修复相关问题 refactor(redis_manager): 移除冗余的ConnectionError处理 refactor(event_handler): 优化Bot类型注解 refactor(factory): 移除未使用的GroupCardNoticeEvent test: 添加全面的单元测试覆盖 - 添加test_import.py测试模块导入 - 添加test_debug.py测试插件加载调试 - 添加test_plugin_error.py测试错误处理 - 添加test_config_loader.py测试配置加载 - 添加test_redis_manager.py测试Redis管理 - 添加test_bot.py测试Bot功能 - 扩展test_models.py测试消息模型 - 添加test_plugin_manager_coverage.py测试插件管理 - 添加test_executor.py测试代码执行器 - 添加test_ws.py测试WebSocket - 添加test_api.py测试API接口 - 添加test_core_managers.py测试核心管理模块 fix(plugin_manager): 修复插件加载日志变量问题 覆盖率已到达86%(忽略插件) * 更新/help指令,现在会发送图片 * feat(help): 重构帮助系统为图片渲染模式 添加浏览器管理器和图片管理器,用于通过 Playwright 渲染帮助菜单为图片 重构命令管理器以支持图片缓存和同步功能 添加 HTML 模板用于帮助菜单渲染 * build: 更新依赖文件 requirements.txt * build: 更新依赖文件 * feat: 添加性能优化和架构文档,更新依赖和核心模块 refactor(browser_manager): 实现页面池机制以提升性能 refactor(image_manager): 添加模板缓存并集成页面池 refactor(bili_parser): 迁移到异步HTTP请求并实现会话复用 docs: 新增性能优化、架构设计和最佳实践文档 chore: 更新requirements.txt添加新依赖 * docs: 更新文档内容并优化语言风格 重构所有文档内容,使用更简洁直接的语言风格 更新架构、插件开发、部署等核心文档 优化代码示例和图表说明 统一术语和格式规范 * docs: 更新文档内容,简化语言并修正格式 - 简化插件开发指南中的描述,移除冗余内容 - 调整部署文档中的Python版本说明 - 优化最佳实践文档的措辞和格式 - 更新性能优化文档,删除不准确的数据 - 重构核心概念文档,使用更简洁的语言 - 修正README中的项目描述和技术栈说明 - 更新快速上手文档,简化安装步骤 - 调整事件流转文档的描述方式 - 简化架构文档内容 - 更新指令处理文档,添加参数注入示例 - 优化单例管理器文档的表述 * refactor(core): 优化权限管理和事件模型 - 重构 AdminManager 和 PermissionManager 以 Redis 为主要数据源 - 为所有事件模型添加 slots=True 提升性能 - 更新文档说明 Mypyc 编译注意事项 - 清理测试和调试文件 - 移动静态资源到 web_static 目录 --------- Co-authored-by: baby20162016 <2185823427@qq.com>
This commit is contained in:
288
web_static/html/404.html
Normal file
288
web_static/html/404.html
Normal file
@@ -0,0 +1,288 @@
|
||||
<!DOCTYPE html>
|
||||
<html><head><title></title><meta charset="UTF-8"><meta name="viewport" content="width=device-width, initial-scale=1.0"><title>404 - Signal Lost</title><script src="./tailwindcss.js"></script><script src="./iconify-icon.min.js"></script></head><body>
|
||||
<style id="style-404">
|
||||
/* 核心背景:动态噪点与 CRT 效果 */
|
||||
@keyframes noise {
|
||||
0%, 100% { transform: translate(0, 0); }
|
||||
10% { transform: translate(-5%, -5%); }
|
||||
20% { transform: translate(-10%, 5%); }
|
||||
30% { transform: translate(5%, -10%); }
|
||||
40% { transform: translate(-5%, 15%); }
|
||||
50% { transform: translate(-10%, 5%); }
|
||||
60% { transform: translate(15%, 0); }
|
||||
70% { transform: translate(0, 10%); }
|
||||
80% { transform: translate(-15%, 0); }
|
||||
90% { transform: translate(10%, 5%); }
|
||||
}
|
||||
|
||||
.bg-noise {
|
||||
position: fixed;
|
||||
top: -50%;
|
||||
left: -50%;
|
||||
right: -50%;
|
||||
bottom: -50%;
|
||||
width: 200%;
|
||||
height: 200vh;
|
||||
background: transparent url('http://assets.iceable.com/img/noise-transparent.png') repeat 0 0;
|
||||
background-repeat: repeat;
|
||||
animation: noise .2s infinite;
|
||||
opacity: .05;
|
||||
visibility: visible;
|
||||
pointer-events: none;
|
||||
z-index: 1;
|
||||
}
|
||||
|
||||
.crt-overlay {
|
||||
background: linear-gradient(rgba(18, 16, 16, 0) 50%, rgba(0, 0, 0, 0.25) 50%), linear-gradient(90deg, rgba(255, 0, 0, 0.06), rgba(0, 255, 0, 0.02), rgba(0, 0, 255, 0.06));
|
||||
background-size: 100% 2px, 3px 100%;
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
.vignette {
|
||||
background: radial-gradient(circle, rgba(0,0,0,0) 60%, rgba(0,0,0,1) 100%);
|
||||
pointer-events: none;
|
||||
}
|
||||
|
||||
/* 高级 Glitch 文本效果 */
|
||||
.cyber-glitch {
|
||||
position: relative;
|
||||
color: #fff;
|
||||
mix-blend-mode: lighten;
|
||||
}
|
||||
|
||||
.cyber-glitch::before,
|
||||
.cyber-glitch::after {
|
||||
content: attr(data-text);
|
||||
position: absolute;
|
||||
top: 0;
|
||||
width: 100%;
|
||||
background: #050505;
|
||||
clip: rect(0, 0, 0, 0);
|
||||
}
|
||||
|
||||
.cyber-glitch::before {
|
||||
left: -2px;
|
||||
text-shadow: 2px 0 #ff00c1;
|
||||
animation: glitch-anim-1 2s infinite linear alternate-reverse;
|
||||
}
|
||||
|
||||
.cyber-glitch::after {
|
||||
left: 2px;
|
||||
text-shadow: -2px 0 #00fff9;
|
||||
animation: glitch-anim-2 3s infinite linear alternate-reverse;
|
||||
}
|
||||
|
||||
@keyframes glitch-anim-1 {
|
||||
0% { clip: rect(20px, 9999px, 10px, 0); }
|
||||
20% { clip: rect(50px, 9999px, 80px, 0); }
|
||||
40% { clip: rect(10px, 9999px, 40px, 0); }
|
||||
60% { clip: rect(80px, 9999px, 20px, 0); }
|
||||
80% { clip: rect(30px, 9999px, 60px, 0); }
|
||||
100% { clip: rect(60px, 9999px, 30px, 0); }
|
||||
}
|
||||
@keyframes glitch-anim-2 {
|
||||
0% { clip: rect(60px, 9999px, 30px, 0); }
|
||||
20% { clip: rect(10px, 9999px, 50px, 0); }
|
||||
40% { clip: rect(70px, 9999px, 10px, 0); }
|
||||
60% { clip: rect(30px, 9999px, 90px, 0); }
|
||||
80% { clip: rect(90px, 9999px, 20px, 0); }
|
||||
100% { clip: rect(20px, 9999px, 60px, 0); }
|
||||
}
|
||||
|
||||
/* 装饰性扫描线 */
|
||||
.scanline-bar {
|
||||
width: 100%;
|
||||
height: 5px;
|
||||
background: rgba(0, 255, 249, 0.3);
|
||||
position: absolute;
|
||||
z-index: 10;
|
||||
animation: scan 3s linear infinite;
|
||||
opacity: 0.3;
|
||||
box-shadow: 0 0 10px rgba(0, 255, 249, 0.5);
|
||||
}
|
||||
|
||||
@keyframes scan {
|
||||
0% { top: -10%; }
|
||||
100% { top: 110%; }
|
||||
}
|
||||
|
||||
/* 终端光标闪烁 */
|
||||
.cursor-blink {
|
||||
animation: blink 1s step-end infinite;
|
||||
}
|
||||
@keyframes blink {
|
||||
0%, 100% { opacity: 1; }
|
||||
50% { opacity: 0; }
|
||||
}
|
||||
</style>
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
|
||||
<div id="content-404" class="relative min-h-screen bg-[#050505] flex flex-col items-center justify-center overflow-hidden font-mono text-gray-300 selection:bg-electric/30 selection:text-white">
|
||||
|
||||
<!-- Environmental Effects -->
|
||||
<div class="bg-noise"></div>
|
||||
<div class="crt-overlay absolute inset-0 z-50 pointer-events-none"></div>
|
||||
<div class="vignette absolute inset-0 z-40 pointer-events-none"></div>
|
||||
<div class="scanline-bar pointer-events-none"></div>
|
||||
|
||||
<!-- Background Grid -->
|
||||
<div class="absolute inset-0 bg-[linear-gradient(rgba(30,30,30,0.5)_1px,transparent_1px),linear-gradient(90deg,rgba(30,30,30,0.5)_1px,transparent_1px)] bg-[size:40px_40px] opacity-10 pointer-events-none z-0" style="perspective: 500px; transform: rotateX(20deg) scale(1.5);"></div>
|
||||
|
||||
<!-- Main Content -->
|
||||
<div class="relative z-30 flex flex-col items-center w-full max-w-4xl px-6">
|
||||
|
||||
<!-- Glitch Title -->
|
||||
<div class="relative mb-6 group cursor-default">
|
||||
<h1 class="cyber-glitch text-[120px] md:text-[180px] font-black leading-none tracking-tighter opacity-90 select-none" data-text="404">
|
||||
404
|
||||
</h1>
|
||||
<div class="absolute -bottom-4 left-0 w-full flex justify-between text-[10px] md:text-xs text-electric/40 uppercase tracking-[0.5em] font-bold">
|
||||
<span>Sys.Malfunction</span>
|
||||
<span>0x00_DEAD</span>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Terminal Window -->
|
||||
<div class="w-full max-w-2xl mt-8 mb-12 backdrop-blur-md bg-black/40 border border-white/5 rounded-sm shadow-[0_0_30px_rgba(0,0,0,0.8)] overflow-hidden">
|
||||
<!-- Terminal Header -->
|
||||
<div class="flex items-center justify-between px-4 py-2 bg-white/5 border-b border-white/5">
|
||||
<div class="flex gap-2">
|
||||
<div class="w-3 h-3 rounded-full bg-red-900/50 border border-red-500/30"></div>
|
||||
<div class="w-3 h-3 rounded-full bg-yellow-900/50 border border-yellow-500/30"></div>
|
||||
<div class="w-3 h-3 rounded-full bg-green-900/50 border border-green-500/30"></div>
|
||||
</div>
|
||||
<div class="text-[10px] text-gray-600 font-mono">root@neobot:~/system/logs</div>
|
||||
</div>
|
||||
|
||||
<!-- Terminal Body -->
|
||||
<div class="p-6 font-mono text-sm md:text-base leading-relaxed h-48 overflow-y-auto custom-scrollbar">
|
||||
<div id="terminal-content" class="space-y-1">
|
||||
<!-- Content will be injected by JS -->
|
||||
<div class="text-gray-500 transition-opacity duration-100">> initiating_handshake...</div><div class="text-gray-400 transition-opacity duration-100">> resolving_host: calglaubot.internal</div><div class="text-green-500/50 transition-opacity duration-100">> connection_established (port: 443)</div><div class="text-blue-400/60 transition-opacity duration-100">> GET /requested_resource HTTP/1.1</div><div class="text-gray-500 transition-opacity duration-100">> waiting_for_response...</div><div class="text-red-500 font-bold transition-opacity duration-100">> FATAL: endpoint_not_found</div><div class="text-gray-600 mt-2 transition-opacity duration-100">> stack_trace_dump:</div><div class="text-gray-600 pl-4 transition-opacity duration-100">> at Router.resolve (core.js:204)</div><div class="text-gray-600 pl-4 transition-opacity duration-100">> at Neobot.Handler (main.py:404)</div><div class="text-electric/80 mt-2 transition-opacity duration-100">> error: signal_lost_in_void</div></div>
|
||||
<div class="flex items-center mt-2 text-electric">
|
||||
<span class="mr-2">➜</span>
|
||||
<span class="cursor-blink w-2 h-4 bg-electric block"></span>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- Navigation -->
|
||||
<div class="flex flex-col md:flex-row gap-6 items-center">
|
||||
<a href="index.html" class="group relative px-8 py-3 bg-transparent overflow-hidden">
|
||||
<!-- Button Borders -->
|
||||
<div class="absolute top-0 left-0 w-2 h-2 border-t border-l border-electric/50 transition-all group-hover:w-full group-hover:h-full group-hover:border-electric"></div>
|
||||
<div class="absolute bottom-0 right-0 w-2 h-2 border-b border-r border-electric/50 transition-all group-hover:w-full group-hover:h-full group-hover:border-electric"></div>
|
||||
|
||||
<!-- Button Content -->
|
||||
<div class="relative flex items-center gap-3">
|
||||
<iconify-icon icon="mdi:console-network" class="text-xl text-electric/70 group-hover:text-electric transition-colors"></iconify-icon>
|
||||
<span class="font-bold tracking-widest text-sm text-gray-400 group-hover:text-white transition-colors">REBOOT_SYSTEM</span>
|
||||
</div>
|
||||
|
||||
<!-- Hover Background -->
|
||||
<div class="absolute inset-0 bg-electric/5 translate-y-full group-hover:translate-y-0 transition-transform duration-300"></div>
|
||||
</a>
|
||||
|
||||
<a href="#" class="text-xs text-gray-600 hover:text-electric/60 transition-colors uppercase tracking-widest border-b border-transparent hover:border-electric/30 pb-0.5">
|
||||
Report_Incident
|
||||
</a>
|
||||
</div>
|
||||
|
||||
</div>
|
||||
|
||||
<!-- Footer Stats -->
|
||||
<div class="absolute bottom-6 left-6 right-6 flex justify-between text-[10px] text-gray-700 font-mono uppercase z-30">
|
||||
<div>
|
||||
<span>CPU: <span class="text-gray-500">98%</span></span>
|
||||
<span class="mx-2">|</span>
|
||||
<span>MEM: <span class="text-red-900 animate-pulse">OVERFLOW</span></span>
|
||||
</div>
|
||||
<div>
|
||||
<span>NEOBOT FRAMEWORK</span>
|
||||
</div>
|
||||
</div>
|
||||
</div><script id="script-404">(function() {
|
||||
document.addEventListener('DOMContentLoaded', () => {
|
||||
const terminalContent = document.getElementById('terminal-content');
|
||||
const logs = [
|
||||
{ text: 'initiating_handshake...', delay: 100, class: 'text-gray-500' },
|
||||
{ text: 'resolving_host: calglaubot.internal', delay: 300, class: 'text-gray-400' },
|
||||
{ text: 'connection_established (port: 443)', delay: 600, class: 'text-green-500/50' },
|
||||
{ text: 'GET /requested_resource HTTP/1.1', delay: 900, class: 'text-blue-400/60' },
|
||||
{ text: 'waiting_for_response...', delay: 1200, class: 'text-gray-500' },
|
||||
{ text: 'FATAL: endpoint_not_found', delay: 2000, class: 'text-red-500 font-bold' },
|
||||
{ text: 'stack_trace_dump:', delay: 2200, class: 'text-gray-600 mt-2' },
|
||||
{ text: ' at Router.resolve (core.js:204)', delay: 2300, class: 'text-gray-600 pl-4' },
|
||||
{ text: ' at Neobot.Handler (main.py:404)', delay: 2400, class: 'text-gray-600 pl-4' },
|
||||
{ text: 'error: signal_lost_in_void', delay: 2800, class: 'text-electric/80 mt-2' }
|
||||
];
|
||||
|
||||
let currentLine = 0;
|
||||
|
||||
function typeWriter() {
|
||||
if (currentLine < logs.length) {
|
||||
const line = logs[currentLine];
|
||||
const p = document.createElement('div');
|
||||
p.className = `${line.class} opacity-0 transition-opacity duration-100`;
|
||||
p.textContent = `> ${line.text}`;
|
||||
terminalContent.appendChild(p);
|
||||
|
||||
// Trigger reflow
|
||||
void p.offsetWidth;
|
||||
p.classList.remove('opacity-0');
|
||||
|
||||
// Auto scroll to bottom
|
||||
const container = terminalContent.parentElement;
|
||||
container.scrollTop = container.scrollHeight;
|
||||
|
||||
currentLine++;
|
||||
setTimeout(typeWriter, Math.random() * 200 + 100); // Random typing speed variation
|
||||
}
|
||||
}
|
||||
|
||||
setTimeout(typeWriter, 500);
|
||||
});
|
||||
})();</script></body></html>
|
||||
387
web_static/html/index.html
Normal file
387
web_static/html/index.html
Normal file
@@ -0,0 +1,387 @@
|
||||
<!DOCTYPE html>
|
||||
<html lang="zh-CN" class="scroll-smooth">
|
||||
<head>
|
||||
<meta charset="UTF-8">
|
||||
<meta name="viewport" content="width=device-width, initial-scale=1.0">
|
||||
<title>NEOBOT | F.O.S FRAMEWORK</title>
|
||||
<script src="https://cdn.tailwindcss.com"></script>
|
||||
<link rel="preconnect" href="https://fonts.googleapis.com">
|
||||
<link href="https://fonts.googleapis.com/css2?family=JetBrains+Mono:wght@400;500;600&family=Inter:wght@300;400;600;800&display=swap" rel="stylesheet">
|
||||
<script src="https://code.iconify.design/iconify-icon/1.0.7/iconify-icon.min.js"></script>
|
||||
|
||||
<script>
|
||||
tailwind.config = {
|
||||
theme: {
|
||||
extend: {
|
||||
fontFamily: {
|
||||
sans: ['"Inter"', 'sans-serif'],
|
||||
mono: ['"JetBrains Mono"', 'monospace'],
|
||||
},
|
||||
colors: {
|
||||
brand: {
|
||||
dark: '#0B0C10',
|
||||
gray: '#1F2833',
|
||||
light: '#C5C6C7',
|
||||
accent: '#66FCF1', // 经典的青色高亮
|
||||
accentDim: '#45A29E',
|
||||
}
|
||||
},
|
||||
animation: {
|
||||
'float': 'float 6s ease-in-out infinite',
|
||||
'pulse-slow': 'pulse 4s cubic-bezier(0.4, 0, 0.6, 1) infinite',
|
||||
},
|
||||
keyframes: {
|
||||
float: {
|
||||
'0%, 100%': { transform: 'translateY(0)' },
|
||||
'50%': { transform: 'translateY(-10px)' },
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
</script>
|
||||
<style>
|
||||
body {
|
||||
background-color: #0B0C10;
|
||||
color: #C5C6C7;
|
||||
background-image:
|
||||
radial-gradient(circle at 15% 50%, rgba(69, 162, 158, 0.08) 0%, transparent 25%),
|
||||
radial-gradient(circle at 85% 30%, rgba(102, 252, 241, 0.05) 0%, transparent 25%);
|
||||
}
|
||||
|
||||
/* 现代卡片样式 */
|
||||
.modern-card {
|
||||
background: rgba(31, 40, 51, 0.6);
|
||||
backdrop-filter: blur(12px);
|
||||
border: 1px solid rgba(255, 255, 255, 0.05);
|
||||
border-radius: 12px;
|
||||
transition: all 0.3s ease;
|
||||
}
|
||||
.modern-card:hover {
|
||||
border-color: rgba(102, 252, 241, 0.3);
|
||||
transform: translateY(-4px);
|
||||
box-shadow: 0 10px 30px -10px rgba(102, 252, 241, 0.1);
|
||||
}
|
||||
|
||||
/* 代码块样式 */
|
||||
.code-window {
|
||||
background: #151515;
|
||||
border-radius: 8px;
|
||||
border: 1px solid #333;
|
||||
box-shadow: 0 20px 50px rgba(0,0,0,0.5);
|
||||
}
|
||||
|
||||
/* 自定义滚动条 */
|
||||
::-webkit-scrollbar { width: 6px; }
|
||||
::-webkit-scrollbar-track { background: #0B0C10; }
|
||||
::-webkit-scrollbar-thumb { background: #333; border-radius: 3px; }
|
||||
::-webkit-scrollbar-thumb:hover { background: #66FCF1; }
|
||||
|
||||
.text-glow {
|
||||
text-shadow: 0 0 20px rgba(102, 252, 241, 0.3);
|
||||
}
|
||||
</style>
|
||||
</head>
|
||||
<body class="antialiased selection:bg-brand-accent selection:text-brand-dark">
|
||||
|
||||
<!-- 顶部导航 -->
|
||||
<nav class="fixed top-0 w-full z-50 border-b border-white/5 bg-brand-dark/80 backdrop-blur-md">
|
||||
<div class="max-w-7xl mx-auto px-6 h-16 flex items-center justify-between">
|
||||
<div class="flex items-center gap-3">
|
||||
<div class="w-8 h-8 rounded-lg bg-brand-accent flex items-center justify-center text-brand-dark">
|
||||
<iconify-icon icon="mdi:robot" class="text-xl"></iconify-icon>
|
||||
</div>
|
||||
<span class="font-bold text-white tracking-wide text-lg">NEO<span class="text-brand-accent">BOT</span></span>
|
||||
</div>
|
||||
|
||||
<div class="hidden md:flex items-center gap-6 text-sm font-medium text-gray-400">
|
||||
<span class="flex items-center gap-2"><span class="w-2 h-2 rounded-full bg-green-500 animate-pulse"></span>OneBot 11</span>
|
||||
<span>v1.0.0</span>
|
||||
</div>
|
||||
|
||||
<a href="https://github.com/Fairy-Oracle-Sanctuary/NEO-Bot-Framework" target="_blank"
|
||||
class="flex items-center gap-2 px-4 py-2 bg-white/5 hover:bg-white/10 rounded-full transition-colors text-sm font-medium text-white border border-white/10">
|
||||
<iconify-icon icon="mdi:github" class="text-lg"></iconify-icon>
|
||||
GitHub
|
||||
</a>
|
||||
</div>
|
||||
</nav>
|
||||
|
||||
<main class="pt-32 pb-20 px-6">
|
||||
<div class="max-w-7xl mx-auto space-y-32">
|
||||
|
||||
<!-- Hero 区域 -->
|
||||
<section class="grid lg:grid-cols-2 gap-16 items-center">
|
||||
<div class="space-y-8 animate-float">
|
||||
<div class="inline-flex items-center gap-2 px-3 py-1 rounded-full bg-brand-accent/10 border border-brand-accent/20 text-brand-accent text-xs font-mono font-bold tracking-wider">
|
||||
🚀 HIGH PERFORMANCE ASYNC FRAMEWORK
|
||||
</div>
|
||||
|
||||
<h1 class="text-5xl md:text-7xl font-extrabold text-white leading-tight">
|
||||
为现代开发而生<br>
|
||||
<span class="text-transparent bg-clip-text bg-gradient-to-r from-brand-accent to-blue-500 text-glow">NEO 机器人框架</span>
|
||||
</h1>
|
||||
|
||||
<p class="text-lg text-gray-400 max-w-xl leading-relaxed">
|
||||
基于 Python 异步生态构建的 OneBot 11 解决方案。内置 Redis 缓存、插件热重载与类型安全检查。这是我的第一个 Python 作品,致力于极致的开发体验。
|
||||
</p>
|
||||
|
||||
<!-- 团队信息 (头像已更新) -->
|
||||
<div class="flex items-center gap-4 py-4 border-t border-white/10 border-b border-white/10">
|
||||
<div class="text-xs font-mono text-gray-500 uppercase tracking-widest">Core Team</div>
|
||||
<div class="flex -space-x-3 hover:space-x-1 transition-all duration-300">
|
||||
<!-- 镀铬酸钾 -->
|
||||
<img src="https://q1.qlogo.cn/g?b=qq&nk=2221577113&s=640" alt="镀铬酸钾" title="镀铬酸钾 (Lead Developer)"
|
||||
class="w-10 h-10 rounded-full border-2 border-brand-dark cursor-help hover:scale-110 transition-transform">
|
||||
<!-- baby2016 -->
|
||||
<img src="https://q1.qlogo.cn/g?b=qq&nk=2185823427&s=640" alt="baby2016" title="baby2016 (Co-Founder)"
|
||||
class="w-10 h-10 rounded-full border-2 border-brand-dark cursor-help hover:scale-110 transition-transform">
|
||||
</div>
|
||||
<span class="text-sm font-medium text-white pl-2">Fairy-Oracle-Sanctuary</span>
|
||||
</div>
|
||||
|
||||
<div class="flex flex-wrap gap-4">
|
||||
<button onclick="copyInstall()" class="group relative px-8 py-4 bg-brand-accent text-brand-dark font-bold rounded-xl transition-all hover:bg-white hover:scale-105 active:scale-95 flex items-center gap-2">
|
||||
<span>快速开始</span>
|
||||
<iconify-icon icon="mdi:arrow-right" class="group-hover:translate-x-1 transition-transform"></iconify-icon>
|
||||
</button>
|
||||
<div class="flex items-center gap-2 px-6 py-4 rounded-xl bg-brand-gray border border-white/5 text-gray-400 font-mono text-sm">
|
||||
<span class="text-brand-accent">$</span> git clone ...
|
||||
<button onclick="copyClone()" class="ml-2 hover:text-white transition-colors" title="复制指令">
|
||||
<iconify-icon icon="mdi:content-copy"></iconify-icon>
|
||||
</button>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
|
||||
<!-- 代码演示 (真实 main.py) -->
|
||||
<div class="relative group">
|
||||
<div class="absolute -inset-1 bg-gradient-to-r from-brand-accent to-blue-600 rounded-lg blur opacity-20 group-hover:opacity-40 transition duration-1000"></div>
|
||||
<div class="code-window relative overflow-hidden flex flex-col h-[500px]">
|
||||
<div class="flex items-center justify-between px-4 py-3 bg-[#1a1a1a] border-b border-white/5 shrink-0">
|
||||
<div class="flex gap-2">
|
||||
<div class="w-3 h-3 rounded-full bg-red-500"></div>
|
||||
<div class="w-3 h-3 rounded-full bg-yellow-500"></div>
|
||||
<div class="w-3 h-3 rounded-full bg-green-500"></div>
|
||||
</div>
|
||||
<span class="text-xs font-mono text-gray-500">main.py</span>
|
||||
</div>
|
||||
<div class="p-6 overflow-y-auto custom-scrollbar grow">
|
||||
<pre class="font-mono text-xs md:text-sm leading-6"><code><span class="text-gray-500">"""
|
||||
NEO Bot 主程序入口
|
||||
负责启动 WebSocket 连接,初始化插件系统,并提供热重载功能。
|
||||
"""</span>
|
||||
<span class="text-pink-400">import</span> asyncio
|
||||
<span class="text-pink-400">from</span> watchdog.observers <span class="text-pink-400">import</span> Observer
|
||||
<span class="text-pink-400">from</span> watchdog.events <span class="text-pink-400">import</span> FileSystemEventHandler
|
||||
|
||||
<span class="text-pink-400">from</span> core.logger <span class="text-pink-400">import</span> logger
|
||||
<span class="text-pink-400">from</span> core.ws <span class="text-pink-400">import</span> WS
|
||||
<span class="text-pink-400">from</span> core.plugin_manager <span class="text-pink-400">import</span> load_all_plugins
|
||||
|
||||
<span class="text-pink-400">class</span> <span class="text-yellow-300">PluginReloadHandler</span>(FileSystemEventHandler):
|
||||
<span class="text-gray-500">"""监听文件变更,触发热重载"""</span>
|
||||
<span class="text-pink-400">def</span> <span class="text-blue-400">on_any_event</span>(self, event):
|
||||
<span class="text-pink-400">if not</span> event.src_path.endswith(<span class="text-green-400">".py"</span>):
|
||||
<span class="text-pink-400">return</span>
|
||||
|
||||
logger.info(<span class="text-green-400">f"检测到文件变更: {event.src_path}"</span>)
|
||||
<span class="text-pink-400">try</span>:
|
||||
<span class="text-purple-400">run_in_thread_pool</span>(load_all_plugins)
|
||||
logger.success(<span class="text-green-400">"插件重载完成"</span>)
|
||||
<span class="text-pink-400">except</span> Exception <span class="text-pink-400">as</span> e:
|
||||
logger.exception(<span class="text-green-400">f"重载失败: {e}"</span>)
|
||||
|
||||
<span class="text-cyan-400">@logger.catch</span>
|
||||
<span class="text-pink-400">async def</span> <span class="text-yellow-300">main</span>():
|
||||
<span class="text-gray-500"># 1. 初始化核心组件</span>
|
||||
<span class="text-pink-400">await</span> run_in_thread_pool(load_all_plugins)
|
||||
<span class="text-pink-400">await</span> redis_manager.initialize()
|
||||
<span class="text-pink-400">await</span> admin_manager.initialize()
|
||||
|
||||
<span class="text-gray-500"># 2. 启动 Watchdog 热重载</span>
|
||||
observer = Observer()
|
||||
observer.schedule(PluginReloadHandler(), plugin_path, recursive=<span class="text-pink-400">True</span>)
|
||||
observer.start()
|
||||
|
||||
<span class="text-gray-500"># 3. 启动 WebSocket 客户端</span>
|
||||
<span class="text-pink-400">try</span>:
|
||||
bot = WS()
|
||||
<span class="text-pink-400">await</span> bot.connect()
|
||||
<span class="text-pink-400">finally</span>:
|
||||
observer.stop()
|
||||
|
||||
<span class="text-pink-400">if</span> __name__ == <span class="text-green-400">"__main__"</span>:
|
||||
asyncio.run(main())</code></pre>
|
||||
</div>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 特性介绍 -->
|
||||
<section>
|
||||
<div class="text-center mb-16 space-y-4">
|
||||
<h2 class="text-3xl md:text-4xl font-bold text-white">为什么选择 NEO?</h2>
|
||||
<p class="text-gray-400 max-w-2xl mx-auto">不仅仅是一个框架,更是一套完整的现代化开发解决方案。</p>
|
||||
</div>
|
||||
|
||||
<div class="grid md:grid-cols-2 lg:grid-cols-3 gap-6">
|
||||
<!-- Feature 1 -->
|
||||
<div class="modern-card p-8 group">
|
||||
<div class="w-12 h-12 rounded-xl bg-blue-500/10 flex items-center justify-center text-blue-400 mb-6 group-hover:scale-110 transition-transform">
|
||||
<iconify-icon icon="mdi:lightning-bolt" class="text-3xl"></iconify-icon>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-white mb-3">高性能异步 IO</h3>
|
||||
<p class="text-gray-400 text-sm leading-relaxed">
|
||||
基于 Python 原生 <code>asyncio</code> 和 <code>websockets</code> 构建。完全非阻塞设计,单进程即可轻松处理海量并发消息,拒绝卡顿。
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Feature 2 -->
|
||||
<div class="modern-card p-8 group">
|
||||
<div class="w-12 h-12 rounded-xl bg-green-500/10 flex items-center justify-center text-green-400 mb-6 group-hover:scale-110 transition-transform">
|
||||
<iconify-icon icon="mdi:refresh-auto" class="text-3xl"></iconify-icon>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-white mb-3">智能插件热重载</h3>
|
||||
<p class="text-gray-400 text-sm leading-relaxed">
|
||||
基于 <code>watchdog</code> 实现文件监控。修改代码后自动重载插件逻辑,无需重启机器人进程。让调试和开发效率提升 200%。
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Feature 3 -->
|
||||
<div class="modern-card p-8 group">
|
||||
<div class="w-12 h-12 rounded-xl bg-red-500/10 flex items-center justify-center text-red-400 mb-6 group-hover:scale-110 transition-transform">
|
||||
<iconify-icon icon="mdi:database" class="text-3xl"></iconify-icon>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-white mb-3">Redis 深度集成</h3>
|
||||
<p class="text-gray-400 text-sm leading-relaxed">
|
||||
内置 Redis 连接池。自动缓存群信息、好友列表等高频数据,减少 API 调用延迟,让响应速度快人一步。
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Feature 4 -->
|
||||
<div class="modern-card p-8 group">
|
||||
<div class="w-12 h-12 rounded-xl bg-yellow-500/10 flex items-center justify-center text-yellow-400 mb-6 group-hover:scale-110 transition-transform">
|
||||
<iconify-icon icon="mdi:shield-check" class="text-3xl"></iconify-icon>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-white mb-3">类型安全</h3>
|
||||
<p class="text-gray-400 text-sm leading-relaxed">
|
||||
全面采用 Pydantic 和 Dataclasses。为所有事件和数据模型提供完整的类型注解,IDE 智能补全,减少运行时错误。
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Feature 5 -->
|
||||
<div class="modern-card p-8 group">
|
||||
<div class="w-12 h-12 rounded-xl bg-purple-500/10 flex items-center justify-center text-purple-400 mb-6 group-hover:scale-110 transition-transform">
|
||||
<iconify-icon icon="mdi:account-key" class="text-3xl"></iconify-icon>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-white mb-3">精细权限管理</h3>
|
||||
<p class="text-gray-400 text-sm leading-relaxed">
|
||||
内置 Admin/Op/User 三级权限体系。支持动态添加管理员,通过装饰器即可轻松控制每个指令的访问权限。
|
||||
</p>
|
||||
</div>
|
||||
|
||||
<!-- Feature 6 -->
|
||||
<div class="modern-card p-8 group">
|
||||
<div class="w-12 h-12 rounded-xl bg-cyan-500/10 flex items-center justify-center text-cyan-400 mb-6 group-hover:scale-110 transition-transform">
|
||||
<iconify-icon icon="mdi:api" class="text-3xl"></iconify-icon>
|
||||
</div>
|
||||
<h3 class="text-xl font-bold text-white mb-3">标准 OneBot 11</h3>
|
||||
<p class="text-gray-400 text-sm leading-relaxed">
|
||||
完美兼容 OneBot v11 协议标准。支持 NapCatQQ、LLOneBot 等主流实现端,无缝对接,开箱即用。
|
||||
</p>
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 终端展示 -->
|
||||
<section class="max-w-4xl mx-auto">
|
||||
<div class="flex items-center gap-2 mb-4">
|
||||
<iconify-icon icon="mdi:console" class="text-brand-accent text-xl"></iconify-icon>
|
||||
<h3 class="font-mono text-sm text-gray-400">TERMINAL OUTPUT</h3>
|
||||
</div>
|
||||
<div class="bg-black rounded-lg border border-white/10 p-1 shadow-2xl">
|
||||
<div class="bg-[#0a0a0a] rounded p-6 h-64 overflow-y-auto font-mono text-sm leading-relaxed" id="terminal">
|
||||
<!-- JS 注入 -->
|
||||
</div>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
<!-- 性能建议 Banner -->
|
||||
<section class="rounded-2xl bg-gradient-to-r from-yellow-500/10 to-orange-500/10 border border-yellow-500/20 p-8 flex flex-col md:flex-row items-start md:items-center gap-6">
|
||||
<div class="w-12 h-12 rounded-full bg-yellow-500/20 flex items-center justify-center text-yellow-500 shrink-0">
|
||||
<iconify-icon icon="mdi:speedometer" class="text-2xl"></iconify-icon>
|
||||
</div>
|
||||
<div>
|
||||
<h3 class="text-lg font-bold text-white mb-1">性能建议:使用 PyPy</h3>
|
||||
<p class="text-gray-400 text-sm">
|
||||
为了获得最佳性能,我们强烈推荐使用 <span class="text-yellow-400">PyPy JIT 编译器</span> 来运行 NEO 框架。在处理高并发消息时,PyPy 相比标准 CPython 能提供显著的性能提升。
|
||||
</p>
|
||||
</div>
|
||||
</section>
|
||||
|
||||
</div>
|
||||
</main>
|
||||
|
||||
<footer class="border-t border-white/5 bg-brand-dark py-12">
|
||||
<div class="max-w-7xl mx-auto px-6 flex flex-col items-center justify-center gap-4 text-center">
|
||||
<div class="flex items-center gap-2 text-brand-light font-mono text-sm">
|
||||
<iconify-icon icon="mdi:code-tags"></iconify-icon>
|
||||
<span>Designed by 镀铬酸钾 & baby2016</span>
|
||||
</div>
|
||||
<p class="text-xs text-gray-600">
|
||||
© 2026 FAIRY-ORACLE-SANCTUARY. All Rights Reserved.
|
||||
</p>
|
||||
</div>
|
||||
</footer>
|
||||
|
||||
<script>
|
||||
// 终端打字机效果
|
||||
const terminalLines = [
|
||||
{ text: "$ git clone https://github.com/Fairy-Oracle-Sanctuary/NEO-Bot-Framework.git", color: "text-white" },
|
||||
{ text: "Cloning into 'NEO-Bot-Framework'...", color: "text-gray-500", delay: 300 },
|
||||
{ text: "Unpacking objects: 100% (402/402), done.", color: "text-gray-500", delay: 300 },
|
||||
{ text: "$ cd NEO-Bot-Framework", color: "text-white", delay: 100 },
|
||||
{ text: "$ pip install -r requirements.txt", color: "text-white", delay: 100 },
|
||||
{ text: "Successfully installed: watchdog loguru websockets redis pydantic", color: "text-green-400", delay: 500 },
|
||||
{ text: "$ python main.py", color: "text-white", delay: 200 },
|
||||
{ text: "[INFO] Initializing AdminManager...", color: "text-gray-400", delay: 200 },
|
||||
{ text: "[INFO] Redis Connection Pool Created (Size: 10)", color: "text-gray-400", delay: 200 },
|
||||
{ text: "[INFO] Watchdog Monitoring: /plugins (recursive=True)", color: "text-yellow-400", delay: 300 },
|
||||
{ text: "[SUCCESS] WebSocket Connected to ws://127.0.0.1:30004", color: "text-green-500", delay: 200 },
|
||||
{ text: "NEOBOT System is ready. Waiting for events...", color: "text-white animate-pulse" }
|
||||
];
|
||||
|
||||
const term = document.getElementById('terminal');
|
||||
let lineIndex = 0;
|
||||
|
||||
function runTerminal() {
|
||||
if (lineIndex >= terminalLines.length) return;
|
||||
|
||||
const line = terminalLines[lineIndex];
|
||||
const div = document.createElement('div');
|
||||
div.className = `mb-1 ${line.color}`;
|
||||
div.textContent = line.text;
|
||||
term.appendChild(div);
|
||||
term.scrollTop = term.scrollHeight;
|
||||
|
||||
lineIndex++;
|
||||
setTimeout(runTerminal, line.delay || 100);
|
||||
}
|
||||
|
||||
// 剪贴板功能
|
||||
function copyClone() {
|
||||
navigator.clipboard.writeText('git clone https://github.com/Fairy-Oracle-Sanctuary/NEO-Bot-Framework.git');
|
||||
alert('Git Clone 指令已复制到剪贴板');
|
||||
}
|
||||
|
||||
function copyInstall() {
|
||||
navigator.clipboard.writeText('pip install -r requirements.txt');
|
||||
alert('安装依赖指令已复制');
|
||||
}
|
||||
|
||||
// 启动
|
||||
window.onload = runTerminal;
|
||||
</script>
|
||||
</body>
|
||||
</html>
|
||||
Reference in New Issue
Block a user