Merge pull request #59 from Fairy-Oracle-Sanctuary/dev

Dev
This commit is contained in:
镀铬酸钾
2026-02-27 22:49:45 +08:00
committed by GitHub
8 changed files with 596 additions and 257 deletions

3
.gitignore vendored
View File

@@ -139,12 +139,11 @@ dmypy.json
.pytype/ .pytype/
# End of https://www.toptal.com/developers/gitignore/api/python # End of https://www.toptal.com/developers/gitignore/api/python
/ca
# Build artifacts # Build artifacts
build/ build/
# Scratch files # Scratch files
scratch_files/ scratch_files/
/config.toml
/core/data/* /core/data/*

33
ca/ca.pem Normal file
View File

@@ -0,0 +1,33 @@
-----BEGIN CERTIFICATE-----
MIIFqzCCA5OgAwIBAgIUUrxgE1Y97HIajlXcC8xPlbRzdOUwDQYJKoZIhvcNAQEL
BQAwZTELMAkGA1UEBhMCSEQxETAPBgNVBAgMCGRwZ3NvcGhhMSEwHwYDVQQKDBhJ
bnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxIDAeBgkqhkiG9w0BCQEWETIyMjE1Nzcx
MTNAcXEuY29tMB4XDTI2MDIyNzEwMjYzMVoXDTM2MDIyNTEwMjYzMVowZTELMAkG
A1UEBhMCSEQxETAPBgNVBAgMCGRwZ3NvcGhhMSEwHwYDVQQKDBhJbnRlcm5ldCBX
aWRnaXRzIFB0eSBMdGQxIDAeBgkqhkiG9w0BCQEWETIyMjE1NzcxMTNAcXEuY29t
MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEA26XkAzM03wTndIETVTSl
zZkGkzVjLHbkkZS+HZH9CSGwpxuIPY4l/vFA3ag11AJeN5huPiH3Ystjk1gugUM3
ZVjnZ48PeR8MwZ8PqW+tScfYUIzjcZTKQC+g8m+gdm0Tbr4JpxeZXdV4lK/N5m0G
PCC2WX+Xev8TAf9/1yWrtb3ruus4XSiJss9XN9hnidhNeuf4U6I+N2X8UPArNPtm
/YRJ6r2CKTCxohQ93fz+0SkuCHu3JDILa4zUM6J55BSLKtgB+c+nIHB8g2xXcWaZ
Xx7Evq3t/jC2swNxUpGtJrzKskkehdp+jRoPNtMbrMKYfTV6k2pXxDYUSuhkhWd8
6DRllwkFakm2fKOgEWjJx/kmX3RqkvpBNwAeBR1/YuJGDVKeEk/+D3dmVrzA+US1
ntsrajYwB4nY/T46OwUIDbgl374IBIFvhgO8BBPY5gpzjwrHLLQ9SzTPUxQlUfAU
qtbT9+wCrll1FR6ZqmtxkMkAm/pcOi73kfReRnLzY3Mqaa0xbzUzEThebtxLyGWQ
C2at4OyEaAdSa/STP+vlw+LDn3+oLpAkl12toosHi711BKVoP0lcsJL77VyeXYV8
lnJCK1OuQ7UKLRUuC9ydIsnH0jD9YbFtPAbFHAkXV1w5jZAKxTUvgJVOEN4bUCQG
neJrw5nl8iIWRWuLGlwLrmMCAwEAAaNTMFEwHQYDVR0OBBYEFJ+Ec/Dimw4sJ+h2
YQkoq3Plc3pmMB8GA1UdIwQYMBaAFJ+Ec/Dimw4sJ+h2YQkoq3Plc3pmMA8GA1Ud
EwEB/wQFMAMBAf8wDQYJKoZIhvcNAQELBQADggIBAAeswZuXpWE/QLlu3/ovR+Hi
f2N0ic1r0NDAapGtOk/XJgsmA4tMG8CG471v+hw+oHJZm/cL0g5fpvS6FhRtZa8l
Ca3vNqNGHkTRe98IIYY7tNluj4epFGHVhXKXD+ki52I/RmMjOy8VLEN7rLGZOKat
C0+uL6N5vl4QjbS5vvAQ5N6XvFfZ8wI1jWpeEhMYMj5EKGgbZ27VNLIV+pfI2uPH
SWy7cBMl1R+9S84z5rBoKqVgkp3FGaP39jUgnPQbUxfQGwTB9jDhnqYVbQzG9Ofw
2/ll7bHRNWcCNEGZmDp4bHBRlDSithXMk+u90Vup5z5ODuurH7M5sxKFCwp3KGcd
BurBosYUyFjf56JdFWUvILIbtihQOaXepLcnSxvpH+xE5HO+HNpEcIncM3m/Kqg4
f9/JHjxwOXX1JWkXuiNAxqHJcJtDKofSBrBap2uHE/U4dj8zBuG/0pe3Y46YF1ii
kvpmH2XafNQxhKJ84Is74Pu5SbO6Ut/f5BIiSNdW0XKmOdU9U3i+/uNTOPj4A2N9
eNvN3AjI9ghxUcOuSij9yQXvmtqxay6xPQuwjseJG7ucm0sUiAa1949afGodg6cf
dOhOZshS5ZdC1jRht5JEz17/6WsPn29vM4+V6wr32D8a+J10mBxj5cQGIoLDV62B
a3xpqwYOWwRV8tsn+4jj
-----END CERTIFICATE-----

31
ca/cert.pem Normal file
View File

@@ -0,0 +1,31 @@
-----BEGIN CERTIFICATE-----
MIIFWzCCA0OgAwIBAgIUQBN9Eaz8W62X3U/wS5gfYFiX/rwwDQYJKoZIhvcNAQEL
BQAwZTELMAkGA1UEBhMCSEQxETAPBgNVBAgMCGRwZ3NvcGhhMSEwHwYDVQQKDBhJ
bnRlcm5ldCBXaWRnaXRzIFB0eSBMdGQxIDAeBgkqhkiG9w0BCQEWETIyMjE1Nzcx
MTNAcXEuY29tMB4XDTI2MDIyNzEwMzAzMFoXDTM2MDIyNTEwMzAzMFowETEPMA0G
A1UEAwwGY2xpZW50MIICIjANBgkqhkiG9w0BAQEFAAOCAg8AMIICCgKCAgEAwB+5
jQh9kmBPhLStZaQvPhhp1TjLDKzKgPwgwC4ExV9h5gfXOJipTXYc1AEHzf75FtfI
HJ/3AXwGWtJ36s+2zPo/VV78ZtGTiGOJEMNdhcuf3sEyy3XK87teWIylYBPnN+BQ
zRudP/rurvXXw+AYaVCs8D/DvkRPUIsG1+MHM/gzWtmmK0vKQ15Ar/QUWq6xvuG9
vA+8dIjJUQ/4MKOAV5wN3oh7IY+HUNUbnl2lLy8Cr4TLxoUFzyY8CNrVoHb07thG
KWnAvyfWiK2fec0kiVZIqo19OLbNwNlkNwTGZ6jOFnG24vbCUZxfmbD5j1sG3xAB
qgfs6hFBbAX5AusjsDundIweU9nlkB3EEFy4InPzo1J3P4Is7G3pAPYTaP7UYdCr
DQxhV1FjOVVokFqnmB9g4hLOG4+SgxJZ4hk4845UnrkIlEgVP1pLl/tElHFkLr7j
I7VRh9jOHbvNOEtPeCIdM4NoqItaRxktCtQn71yY7gQbl6ZzYkUBqK+m/yYWckkP
su/iwS3rQhAX5c6p8fnfRMnWtUeXRsXW2wTbOjedxovkKvxAoR+FhS75ssgTzebZ
/hRaNFSWBCC6swdfzKbzHjs+VM7yPRAeCzkV8OGGeToI7HtxBYQv6QggaAIccwm/
vhA2r4EaDWnTbgqi+kxVq14afVPAk9Nt+/9+Xz8CAwEAAaNXMFUwEwYDVR0lBAww
CgYIKwYBBQUHAwIwHQYDVR0OBBYEFIAJAT7Vt/YIDEC0JwwZK8VD9u99MB8GA1Ud
IwQYMBaAFJ+Ec/Dimw4sJ+h2YQkoq3Plc3pmMA0GCSqGSIb3DQEBCwUAA4ICAQBG
i6Xyt85kdPHppHKGABHk+L8f4nPpF+qUhvIj2bm5cACEnFV8M2QCIctyNKdS/QUO
3D2TF7MrvZPaqeTqN0OgunVdt2LE5Jwb6zMO0fLWCp2xE23aQ4i/y3h5up+GQu9y
CDruuuOfWNBuI3h3hi5bw/WKzb3slcL1eKd9gaVzDKM77mf0Us8kEg7S9VP76mdo
BhBtCEBZRWKs+4mNk/IcKgyAXAPRUMhJ/mhH1Fw8qPhKy3oBaNzcFlq4zvY2MojL
Yupvv1RzY8PRTI+7WhxQj9vaK40gjzyHzZQkwMXYJZgEJWWbbKaLJWaW0QAzQPr4
IcJTBn/iwqwjD0oooVRyxDKhEqvYJ700MT6qKtbsjOWawsL9TeNTx0IBhZ5jBfHm
wEOD3j+saVGOZwamxNrlFf0TCHdHH79g/kqgWtwZWP3fHQinZWRFpI9XRTL5VssE
Ay+I8Y38v24Y0+XiNvw9qx3fPTS4ZkOpaPq2C/o8fYDN4XvK/ObRQXpWiV5vtkHB
PwvJM6PX7w1K9hywgWTvRvT/ZtKcXdbqlWiavjT3SE2XmvoFS7ug9KX6LiLQyUa4
awQYfidUAh/qiXVWAzWTyqO4+dJKnyxAk8hvuNpMkyOs/L7zqKumVdVsyMloENPF
gz3eWNdvGc8uL92Mp1+VXu3Gx6ymJYE+kT5XcON1LQ==
-----END CERTIFICATE-----

52
ca/key.pem Normal file
View File

@@ -0,0 +1,52 @@
-----BEGIN PRIVATE KEY-----
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
JrDhH32WMDQqFyoWMQd3EeyrH7tx8Q==
-----END PRIVATE KEY-----

49
config.toml Normal file
View File

@@ -0,0 +1,49 @@
# NeoBot 配置文件示例
# 复制此文件并重命名为 config.toml 以使用
# NapCat WebSocket 配置
[napcat_ws]
uri = "ws://114.66.61.199:3001"
# WebSocket 连接地址
token = "KoIAF.mcEHzxrPYF"
# 重连间隔(秒)
reconnect_interval = 5
# Bot 基础配置
[bot]
# 命令前缀列表
command = ["/"]
# 是否忽略自己的消息
ignore_self_message = true
# 权限不足时的消息
permission_denied_message = "权限不足,需要 {permission_name} 权限"
# Redis 配置
[redis]
# Redis 主机地址
host = "101.36.126.55"
# Redis 端口
port = 6379
# Redis 数据库编号
db = 0
# Redis 密码
password = "redis_5fCmnE"
# Docker 配置
[docker]
# Docker 基础 URL可选
base_url = "tcp://101.36.126.55:2376"
# 沙箱镜像名称
sandbox_image = "sanbox:latest"
# 超时时间(秒)
timeout = 10
# 并发限制
concurrency_limit = 5
# 是否验证 TLS
tls_verify = true
# CA 证书路径(可选)
ca_cert_path = "ca/ca.pem"
# 客户端证书路径(可选)
client_cert_path = "ca/cert.pem"
# 客户端密钥路径(可选)
client_key_path = "ca/key.pem"

View File

@@ -73,7 +73,7 @@ def get_jrcd(user_id: int) -> int:
@matcher.command("jrcd") @matcher.command("jrcd")
async def handle_jrcd(bot: Bot, event: MessageEvent, args: list[str]): async def handle_jrcd(bot: Bot, event: MessageEvent, args: list[str]):
if event.id == 831797331: if event.group_id == 831797331:
return None return None
""" """
处理 jrcd 指令,回复用户的“今日长度”。 处理 jrcd 指令,回复用户的“今日长度”。

221
plugins/mirror_avatar.py Normal file
View File

@@ -0,0 +1,221 @@
"""
镜像头像插件
提供 /镜像 指令,将@的用户头像或用户发送的图片处理成轴对称图形。
"""
from core.managers.command_manager import matcher
from core.bot import Bot
from models.events.message import MessageEvent
from core.permission import Permission
from PIL import Image
import io
import aiohttp
import base64
import asyncio
__plugin_meta__ = {
"name": "mirror_avatar",
"description": "将用户头像或图片处理成轴对称图形",
"usage": "/镜像 @人 - 将@的用户头像处理成轴对称图形\n/镜像 - 等待用户发送图片进行镜像处理",
}
# 存储等待图片的用户信息
waiting_for_image = {}
async def get_avatar(user_id: int) -> bytes:
"""
获取用户头像
:param user_id: 用户QQ号
:return: 头像图片字节
"""
# 构建QQ头像URL
url = f"https://q1.qlogo.cn/g?b=qq&nk={user_id}&s=640"
async with aiohttp.ClientSession() as session:
async with session.get(url) as response:
if response.status == 200:
return await response.read()
else:
raise Exception(f"获取头像失败: {response.status}")
async def get_image_from_url(url: str) -> bytes:
"""
从URL获取图片
:param url: 图片URL
:return: 图片字节
"""
async with aiohttp.ClientSession() as session:
async with session.get(url) as response:
if response.status == 200:
return await response.read()
else:
raise Exception(f"获取图片失败: {response.status}")
def process_avatar(image_bytes: bytes) -> bytes:
"""
处理头像为轴对称图形
:param image_bytes: 原始头像字节
:return: 处理后的头像字节
"""
# 打开图片
img = Image.open(io.BytesIO(image_bytes))
# 获取图片尺寸
width, height = img.size
# 计算对称轴位置(中间)
mid_x = width // 2
# 分割图片为左右两部分
left_half = img.crop((0, 0, mid_x, height))
right_half = img.crop((mid_x, 0, width, height))
# 翻转左侧部分到右侧
left_half_flipped = left_half.transpose(Image.FLIP_LEFT_RIGHT)
# 创建新图片
new_img = Image.new('RGB', (width, height))
# 粘贴左侧原始部分和右侧翻转部分
new_img.paste(left_half, (0, 0))
new_img.paste(left_half_flipped, (mid_x, 0))
# 保存处理后的图片
output = io.BytesIO()
new_img.save(output, format='JPEG')
output.seek(0)
return output.read()
async def wait_for_image(bot: Bot, event: MessageEvent):
"""
等待用户发送图片
:param bot: Bot实例
:param event: 消息事件对象
"""
user_id = event.user_id
chat_id = event.group_id if hasattr(event, 'group_id') else event.user_id
is_group = hasattr(event, 'group_id')
# 设置超时时间
timeout = 30
# 提示用户发送图片
await event.reply(f"请在{timeout}秒内发送要处理的图片")
# 记录等待状态
waiting_for_image[user_id] = True
try:
# 等待超时
await asyncio.sleep(timeout)
# 检查是否仍然在等待
if user_id in waiting_for_image:
del waiting_for_image[user_id]
await event.reply("等待超时,请重新发送指令")
except asyncio.CancelledError:
# 图片已收到,任务被取消
pass
@matcher.on_message()
async def handle_image_message(bot: Bot, event: MessageEvent):
"""
处理用户发送的图片消息
:param bot: Bot实例
:param event: 消息事件对象
"""
user_id = event.user_id
# 检查用户是否在等待图片
if user_id not in waiting_for_image:
return
# 查找消息中的图片
images = []
for segment in event.message:
if segment.type == "image" and segment.data.get("url"):
images.append(segment.data["url"])
if not images:
return
# 取消等待任务
del waiting_for_image[user_id]
try:
# 获取第一张图片
image_url = images[0]
# 下载图片
image_bytes = await get_image_from_url(image_url)
# 处理图片
processed_image = process_avatar(image_bytes)
# 检查是否可以发送图片
can_send = await bot.can_send_image()
if not can_send.get("yes"):
await event.reply("当前环境不支持发送图片")
return
# 发送处理后的图片
from models.message import MessageSegment
# 将字节数据转换为 Base64 编码
processed_image_base64 = base64.b64encode(processed_image).decode('utf-8')
# 使用 Base64 编码的字符串
await event.reply(MessageSegment.image(f"base64://{processed_image_base64}"))
except Exception as e:
await event.reply(f"处理图片失败: {str(e)}")
@matcher.command("镜像")
async def handle_mirror(bot: Bot, event: MessageEvent, args: list[str]):
"""
处理镜像指令,将@的用户头像或用户发送的图片处理成轴对称图形
:param bot: Bot实例
:param event: 消息事件对象
:param args: 指令参数列表
"""
# 检查消息中是否有@的用户
at_users = []
for segment in event.message:
if segment.type == "at" and segment.data.get("qq"):
at_users.append(int(segment.data["qq"]))
if at_users:
# 获取第一个@的用户
user_id = at_users[0]
try:
# 获取用户头像
avatar_bytes = await get_avatar(user_id)
# 处理头像
processed_avatar = process_avatar(avatar_bytes)
# 检查是否可以发送图片
can_send = await bot.can_send_image()
if not can_send.get("yes"):
await event.reply("当前环境不支持发送图片")
return
# 发送处理后的头像
from models.message import MessageSegment
# 将字节数据转换为 Base64 编码
processed_avatar_base64 = base64.b64encode(processed_avatar).decode('utf-8')
# 使用 Base64 编码的字符串
await event.reply(MessageSegment.image(f"base64://{processed_avatar_base64}"))
except Exception as e:
await event.reply(f"处理头像失败: {str(e)}")
else:
# 没有@用户,等待用户发送图片
# 启动等待任务
asyncio.create_task(wait_for_image(bot, event))

View File

@@ -3,10 +3,10 @@
<head> <head>
<meta charset="UTF-8"> <meta charset="UTF-8">
<meta name="viewport" content="width=device-width, initial-scale=1.0"> <meta name="viewport" content="width=device-width, initial-scale=1.0">
<title>NEOBOT | F.O.S FRAMEWORK</title> <title>NEOBOT | Private Digital Companion</title>
<script src="https://cdn.tailwindcss.com"></script> <script src="https://cdn.tailwindcss.com"></script>
<link rel="preconnect" href="https://fonts.googleapis.com"> <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"> <link href="https://fonts.googleapis.com/css2?family=Space+Grotesk:wght@300;500;700&family=Inter:wght@300;400;600&family=Noto+Serif+SC:wght@300;400;700&family=Cormorant+Garamond:ital,wght@0,400;1,400&display=swap" rel="stylesheet">
<script src="https://code.iconify.design/iconify-icon/1.0.7/iconify-icon.min.js"></script> <script src="https://code.iconify.design/iconify-icon/1.0.7/iconify-icon.min.js"></script>
<script> <script>
@@ -15,25 +15,27 @@
extend: { extend: {
fontFamily: { fontFamily: {
sans: ['"Inter"', 'sans-serif'], sans: ['"Inter"', 'sans-serif'],
mono: ['"JetBrains Mono"', 'monospace'], display: ['"Space Grotesk"', 'sans-serif'],
serif: ['"Noto Serif SC"', 'serif'],
lyric: ['"Cormorant Garamond"', 'serif'],
}, },
colors: { colors: {
brand: { brand: {
dark: '#0B0C10', bg: '#050505',
gray: '#1F2833', surface: '#121212',
light: '#C5C6C7', border: '#27272a',
accent: '#66FCF1', // 经典的青色高亮 text: '#e4e4e7',
accentDim: '#45A29E', muted: '#a1a1aa',
} }
}, },
animation: { animation: {
'float': 'float 6s ease-in-out infinite', 'fade-in-up': 'fadeInUp 1s cubic-bezier(0.16, 1, 0.3, 1) forwards',
'pulse-slow': 'pulse 4s cubic-bezier(0.4, 0, 0.6, 1) infinite', 'pulse-slow': 'pulse 4s cubic-bezier(0.4, 0, 0.6, 1) infinite',
}, },
keyframes: { keyframes: {
float: { fadeInUp: {
'0%, 100%': { transform: 'translateY(0)' }, '0%': { opacity: '0', transform: 'translateY(20px)' },
'50%': { transform: 'translateY(-10px)' }, '100%': { opacity: '1', transform: 'translateY(0)' },
} }
} }
} }
@@ -42,314 +44,279 @@
</script> </script>
<style> <style>
body { body {
background-color: #0B0C10; background-color: #050505;
color: #C5C6C7; color: #e4e4e7;
background-image: background-image: radial-gradient(circle at 50% 0%, #1a1a1a 0%, #050505 60%);
radial-gradient(circle at 15% 50%, rgba(69, 162, 158, 0.08) 0%, transparent 25%), background-attachment: fixed;
radial-gradient(circle at 85% 30%, rgba(102, 252, 241, 0.05) 0%, transparent 25%);
} }
/* 现代卡片样式 */ .feature-card {
.modern-card { background: rgba(18, 18, 18, 0.6);
background: rgba(31, 40, 51, 0.6);
backdrop-filter: blur(12px); backdrop-filter: blur(12px);
border: 1px solid rgba(255, 255, 255, 0.05); border: 1px solid rgba(255, 255, 255, 0.08);
border-radius: 12px; border-radius: 8px;
transition: all 0.3s ease; transition: all 0.3s ease;
} }
.modern-card:hover { .feature-card:hover {
border-color: rgba(102, 252, 241, 0.3); border-color: rgba(255, 255, 255, 0.2);
transform: translateY(-4px); background: rgba(30, 30, 30, 0.8);
box-shadow: 0 10px 30px -10px rgba(102, 252, 241, 0.1); transform: translateY(-2px);
} }
/* 代码块样式 */ .lyric-text {
.code-window { font-family: "Cormorant Garamond", serif;
background: #151515; font-style: italic;
border-radius: 8px;
border: 1px solid #333;
box-shadow: 0 20px 50px rgba(0,0,0,0.5);
} }
/* 自定义滚动条 */
::-webkit-scrollbar { width: 6px; } ::-webkit-scrollbar { width: 6px; }
::-webkit-scrollbar-track { background: #0B0C10; } ::-webkit-scrollbar-track { background: #050505; }
::-webkit-scrollbar-thumb { background: #333; border-radius: 3px; } ::-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> </style>
</head> </head>
<body class="antialiased selection:bg-brand-accent selection:text-brand-dark"> <body class="antialiased selection:bg-white/20 selection:text-white">
<!-- 顶部导航 --> <!-- 导航 -->
<nav class="fixed top-0 w-full z-50 border-b border-white/5 bg-brand-dark/80 backdrop-blur-md"> <nav class="fixed top-0 w-full z-50 border-b border-white/5 bg-black/80 backdrop-blur-md">
<div class="max-w-7xl mx-auto px-6 h-16 flex items-center justify-between"> <div class="max-w-6xl mx-auto px-6 h-20 flex items-center justify-between">
<div class="flex items-center gap-3"> <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"> <div class="w-2 h-2 bg-white rounded-full animate-pulse-slow"></div>
<iconify-icon icon="mdi:robot" class="text-xl"></iconify-icon> <span class="font-display font-bold text-sm tracking-widest text-white">NEO<span class="text-white/40 font-light">BOT</span></span>
</div>
<span class="font-bold text-white tracking-wide text-lg">NEO<span class="text-brand-accent">BOT</span></span>
</div> </div>
<div class="hidden md:flex items-center gap-6 text-sm font-medium text-gray-400"> <div class="flex items-center gap-4 text-[10px] font-mono text-gray-400 uppercase tracking-widest">
<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 class="px-2 py-1 rounded border border-white/10 bg-white/5">Private Project</span>
<span>v1.0.0</span> <span>v1.0.0</span>
</div> </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> </div>
</nav> </nav>
<main class="pt-32 pb-20 px-6"> <main class="pt-40 pb-32 px-6">
<div class="max-w-7xl mx-auto space-y-32"> <div class="max-w-5xl mx-auto space-y-32">
<!-- Hero 区域 --> <!-- Hero -->
<section class="grid lg:grid-cols-2 gap-16 items-center"> <section class="grid lg:grid-cols-2 gap-16 items-center animate-fade-in-up">
<div class="space-y-8 animate-float"> <div class="space-y-8">
<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"> <div class="space-y-2">
🚀 HIGH PERFORMANCE ASYNC FRAMEWORK <div class="font-mono text-xs text-gray-500 mb-2">SYSTEM STATUS: ONLINE</div>
</div> <h1 class="text-5xl md:text-7xl font-display font-bold text-white leading-tight">
My Digital<br>
<h1 class="text-5xl md:text-7xl font-extrabold text-white leading-tight"> <span class="text-white/30">Sanctuary</span>
为现代开发而生<br>
<span class="text-transparent bg-clip-text bg-gradient-to-r from-brand-accent to-blue-500 text-glow">NEO 机器人框架</span>
</h1> </h1>
</div>
<p class="text-lg text-gray-400 max-w-xl leading-relaxed"> <div class="space-y-6">
基于 Python 异步生态构建的 OneBot 11 解决方案。内置 Redis 缓存、插件热重载与类型安全检查。这是我的第一个 Python 作品,致力于极致的开发体验。 <p class="font-serif text-xl text-gray-300 leading-relaxed">
这不是一个为了改变世界而生的项目。<br>
它只是一个安静的角落,存放着我的一点点任性和想象。
</p>
<p class="font-serif text-sm text-gray-500 italic border-l-2 border-white/10 pl-4">
“我不觉得这个作品有多好,我很差劲,啥也做不好。<br>
但这可能是我留在这个世界的遗迹。”
</p> </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>
</div> </div>
<!-- 代码演示 (真实 main.py) --> <!-- 歌词展示 -->
<div class="relative group"> <div class="hidden lg:block text-right space-y-4 opacity-70">
<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="lyric-text text-2xl text-white/90 leading-loose">
<div class="code-window relative overflow-hidden flex flex-col h-[500px]"> <p>are smiling down on me because</p>
<div class="flex items-center justify-between px-4 py-3 bg-[#1a1a1a] border-b border-white/5 shrink-0"> <p class="text-base text-gray-500 not-italic font-serif">五亿颗星星 正对着我微笑</p>
<div class="flex gap-2"> <p class="mt-4">five hundred millions of stars</p>
<div class="w-3 h-3 rounded-full bg-red-500"></div> <p>are hiding you there?</p>
<div class="w-3 h-3 rounded-full bg-yellow-500"></div> <p class="text-base text-gray-500 not-italic font-serif">是否已经找到藏起来的内心?</p>
<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>
</div> </div>
</section> </section>
<!-- 特性介绍 --> <!-- 功能展示 -->
<section> <section>
<div class="text-center mb-16 space-y-4"> <div class="flex items-end justify-between mb-12 border-b border-white/10 pb-4">
<h2 class="text-3xl md:text-4xl font-bold text-white">为什么选择 NEO?</h2> <h2 class="font-display text-3xl text-white font-bold">My Toolbox</h2>
<p class="text-gray-400 max-w-2xl mx-auto">不仅仅是一个框架,更是一套完整的现代化开发解决方案。</p> <span class="font-mono text-xs text-gray-500">INSTALLED MODULES</span>
</div> </div>
<div class="grid md:grid-cols-2 lg:grid-cols-3 gap-6"> <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"> <div class="feature-card p-6 group">
<iconify-icon icon="mdi:lightning-bolt" class="text-3xl"></iconify-icon> <div class="flex justify-between items-start mb-4">
<iconify-icon icon="mdi:link-variant" class="text-2xl text-blue-400"></iconify-icon>
<span class="font-mono text-[10px] text-gray-600">WEB_PARSER</span>
</div> </div>
<h3 class="text-xl font-bold text-white mb-3">高性能异步 IO</h3> <h3 class="font-display text-lg text-white mb-2">万能解析</h3>
<p class="text-gray-400 text-sm leading-relaxed"> <p class="font-serif text-sm text-gray-400 leading-relaxed">
基于 Python 原生 <code>asyncio</code><code>websockets</code> 构建。完全非阻塞设计,单进程即可轻松处理海量并发消息,拒绝卡顿。 每次在群里发链接都要跳转半天,太麻烦了。所以我写了这个
</p> </p>
</div> </div>
<!-- Feature 2 --> <!-- 代码沙箱 -->
<div class="modern-card p-8 group"> <div class="feature-card p-6 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"> <div class="flex justify-between items-start mb-4">
<iconify-icon icon="mdi:refresh-auto" class="text-3xl"></iconify-icon> <iconify-icon icon="mdi:code-braces" class="text-2xl text-yellow-400"></iconify-icon>
<span class="font-mono text-[10px] text-gray-600">CODE_PY</span>
</div> </div>
<h3 class="text-xl font-bold text-white mb-3">智能插件热重载</h3> <h3 class="font-display text-lg text-white mb-2">Python 沙箱</h3>
<p class="text-gray-400 text-sm leading-relaxed"> <p class="font-serif text-sm text-gray-400 leading-relaxed">
基于 <code>watchdog</code> 实现文件监控。修改代码后自动重载插件逻辑,无需重启机器人进程。让调试和开发效率提升 200%。 sadbox
</p> </p>
</div> </div>
<!-- Feature 3 --> <!-- Furry 图库 -->
<div class="modern-card p-8 group"> <div class="feature-card p-6 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"> <div class="flex justify-between items-start mb-4">
<iconify-icon icon="mdi:database" class="text-3xl"></iconify-icon> <iconify-icon icon="mdi:paw" class="text-2xl text-orange-400"></iconify-icon>
<span class="font-mono text-[10px] text-gray-600">FURRY</span>
</div> </div>
<h3 class="text-xl font-bold text-white mb-3">Redis 深度集成</h3> <h3 class="font-display text-lg text-white mb-2">Furry 图库</h3>
<p class="text-gray-400 text-sm leading-relaxed"> <p class="font-serif text-sm text-gray-400 leading-relaxed">
内置 Redis 连接池。自动缓存群信息、好友列表等高频数据,减少 API 调用延迟,让响应速度快人一步 一点点个人爱好。在这个小小的空间里,我可以诚实地面对自己的喜好,不用在意别人的眼光
</p> </p>
</div> </div>
<!-- Feature 4 --> <!-- 天气查询 -->
<div class="modern-card p-8 group"> <div class="feature-card p-6 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"> <div class="flex justify-between items-start mb-4">
<iconify-icon icon="mdi:shield-check" class="text-3xl"></iconify-icon> <iconify-icon icon="mdi:weather-partly-cloudy" class="text-2xl text-cyan-400"></iconify-icon>
<span class="font-mono text-[10px] text-gray-600">WEATHER</span>
</div> </div>
<h3 class="text-xl font-bold text-white mb-3">类型安全</h3> <h3 class="font-display text-lg text-white mb-2">天气查询</h3>
<p class="text-gray-400 text-sm leading-relaxed"> <p class="font-serif text-sm text-gray-400 leading-relaxed">
全面采用 Pydantic 和 Dataclasses。为所有事件和数据模型提供完整的类型注解IDE 智能补全,减少运行时错误。 weather
</p> </p>
</div> </div>
<!-- Feature 5 --> <!-- 头像镜像 -->
<div class="modern-card p-8 group"> <div class="feature-card p-6 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"> <div class="flex justify-between items-start mb-4">
<iconify-icon icon="mdi:account-key" class="text-3xl"></iconify-icon> <iconify-icon icon="mdi:image-filter-center-focus" class="text-2xl text-purple-400"></iconify-icon>
<span class="font-mono text-[10px] text-gray-600">MIRROR_AVATAR</span>
</div> </div>
<h3 class="text-xl font-bold text-white mb-3">精细权限管理</h3> <h3 class="font-display text-lg text-white mb-2">头像镜像</h3>
<p class="text-gray-400 text-sm leading-relaxed"> <p class="font-serif text-sm text-gray-400 leading-relaxed">
内置 Admin/Op/User 三级权限体系。支持动态添加管理员,通过装饰器即可轻松控制每个指令的访问权限。 无聊时的恶搞
</p> </p>
</div> </div>
<!-- Feature 6 --> <!-- 今日人品 -->
<div class="modern-card p-8 group"> <div class="feature-card p-6 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"> <div class="flex justify-between items-start mb-4">
<iconify-icon icon="mdi:api" class="text-3xl"></iconify-icon> <iconify-icon icon="mdi:dice-5" class="text-2xl text-red-400"></iconify-icon>
<span class="font-mono text-[10px] text-gray-600">JRCD</span>
</div> </div>
<h3 class="text-xl font-bold text-white mb-3">标准 OneBot 11</h3> <h3 class="font-display text-lg text-white mb-2">今日人品</h3>
<p class="text-gray-400 text-sm leading-relaxed"> <p class="font-serif text-sm text-gray-400 leading-relaxed">
完美兼容 OneBot v11 协议标准。支持 NapCatQQ、LLOneBot 等主流实现端,无缝对接,开箱即用。 每天测测运气。虽然知道这只是 `random.randint(0, 100)`
</p>
</div>
</div>
</section>
<!-- 关于作者 -->
<section class="py-16 border-t border-white/5">
<div class="flex items-end justify-between mb-12">
<h2 class="font-display text-3xl text-white font-bold">Creators</h2>
<span class="font-mono text-xs text-gray-500">FAIRY-ORACLE-SANCTUARY</span>
</div>
<div class="grid md:grid-cols-2 gap-12">
<!-- 作者 1 -->
<div class="flex items-start gap-6 group">
<img src="https://q1.qlogo.cn/g?b=qq&nk=2221577113&s=640" alt="镀铬酸钾"
class="w-16 h-16 rounded-full border border-white/10 grayscale group-hover:grayscale-0 transition-all duration-500">
<div class="space-y-2">
<h3 class="font-display text-xl text-white">镀铬酸钾</h3>
<p class="font-mono text-xs text-gray-500 uppercase tracking-wider">Lead Developer</p>
<p class="font-serif text-sm text-gray-400 leading-relaxed pt-2">
“写代码是为了逃避现实”
</p> </p>
</div> </div>
</div> </div>
<!-- 作者 2 -->
<div class="flex items-start gap-6 group">
<img src="https://q1.qlogo.cn/g?b=qq&nk=2185823427&s=640" alt="baby2016"
class="w-16 h-16 rounded-full border border-white/10 grayscale group-hover:grayscale-0 transition-all duration-500">
<div class="space-y-2">
<h3 class="font-display text-xl text-white">baby2016</h3>
<p class="font-mono text-xs text-gray-500 uppercase tracking-wider">Co-Founder</p>
<p class="font-serif text-sm text-gray-400 leading-relaxed pt-2">
“在这个喧嚣的世界里,寻找一点点安静的秩序。”
</p>
</div>
</div>
</div>
</section>
<!-- 歌词过渡 -->
<section class="py-16 text-center space-y-6 opacity-80">
<div class="lyric-text text-3xl text-white/80">
"all of the stars have same faces<br>
no i can't find yours"
</div>
<p class="font-serif text-sm text-gray-500 tracking-widest uppercase">
所有的星星都是一个样 / 找不到你
</p>
</section> </section>
<!-- 终端展示 --> <!-- 终端展示 -->
<section class="max-w-4xl mx-auto"> <section class="max-w-3xl mx-auto">
<div class="flex items-center gap-2 mb-4"> <div class="flex items-center justify-between mb-2 px-1">
<iconify-icon icon="mdi:console" class="text-brand-accent text-xl"></iconify-icon> <span class="font-mono text-[10px] text-gray-500">SYSTEM LOG</span>
<h3 class="font-mono text-sm text-gray-400">TERMINAL OUTPUT</h3> <div class="flex gap-1.5">
<div class="w-2 h-2 rounded-full bg-red-500/20"></div>
<div class="w-2 h-2 rounded-full bg-yellow-500/20"></div>
<div class="w-2 h-2 rounded-full bg-green-500/20"></div>
</div> </div>
<div class="bg-black rounded-lg border border-white/10 p-1 shadow-2xl"> </div>
<div class="bg-[#0a0a0a] rounded p-6 h-64 overflow-y-auto font-mono text-sm leading-relaxed" id="terminal"> <div class="bg-[#0a0a0a] border border-white/10 p-6 font-mono text-xs h-56 overflow-hidden relative rounded-lg">
<div id="terminal" class="space-y-2 text-gray-400">
<!-- JS 注入 --> <!-- JS 注入 -->
</div> </div>
<div class="absolute bottom-0 left-0 w-full h-16 bg-gradient-to-t from-[#0a0a0a] to-transparent pointer-events-none"></div>
</div> </div>
</section> </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"> <section class="text-center py-16 space-y-8">
<div class="w-12 h-12 rounded-full bg-yellow-500/20 flex items-center justify-center text-yellow-500 shrink-0"> <div class="lyric-text text-4xl text-white leading-tight">
<iconify-icon icon="mdi:speedometer" class="text-2xl"></iconify-icon> "and all that i wished was to see one<br>
<span class="text-white/40">tiny little star</span>"
</div> </div>
<div> <div class="pt-8">
<h3 class="text-lg font-bold text-white mb-1">性能建议:使用 PyPy</h3> <p class="font-display font-bold text-xl text-white">NO GROWN-UPS UNDERSTAND</p>
<p class="text-gray-400 text-sm"> <p class="font-serif text-sm text-gray-500 mt-2">不要变成大人那样</p>
为了获得最佳性能,我们强烈推荐使用 <span class="text-yellow-400">PyPy JIT 编译器</span> 来运行 NEO 框架。在处理高并发消息时PyPy 相比标准 CPython 能提供显著的性能提升。
</p>
</div> </div>
</section> </section>
</div> </div>
</main> </main>
<footer class="border-t border-white/5 bg-brand-dark py-12"> <footer class="py-12 border-t border-white/5 bg-black/20">
<div class="max-w-7xl mx-auto px-6 flex flex-col items-center justify-center gap-4 text-center"> <div class="max-w-6xl mx-auto px-6 flex flex-col md:flex-row justify-between items-center gap-6">
<div class="flex items-center gap-2 text-brand-light font-mono text-sm"> <div class="text-center md:text-left">
<iconify-icon icon="mdi:code-tags"></iconify-icon> <div class="font-display font-bold text-white mb-1">NEOBOT</div>
<span>Designed by 镀铬酸钾 & baby2016</span> <p class="font-mono text-[10px] text-gray-600">
</div> PRIVATE PERSONAL PROJECT<br>
<p class="text-xs text-gray-600"> NOT FOR PUBLIC DISTRIBUTION
&copy; 2026 FAIRY-ORACLE-SANCTUARY. All Rights Reserved.
</p> </p>
</div> </div>
<div class="font-mono text-[10px] text-gray-600 text-center md:text-right">
TO ASTEROID B-612<br>
SASAKURE.UK
</div>
</div>
</footer> </footer>
<script> <script>
// 终端打字机效果
const terminalLines = [ const terminalLines = [
{ text: "$ git clone https://github.com/Fairy-Oracle-Sanctuary/NEO-Bot-Framework.git", color: "text-white" }, { text: "> SYSTEM_INIT...", color: "text-gray-500" },
{ text: "Cloning into 'NEO-Bot-Framework'...", color: "text-gray-500", delay: 300 }, { text: "> LOADING_MODULES: [weather, code_py, furry, web_parser]...", color: "text-gray-400", delay: 500 },
{ text: "Unpacking objects: 100% (402/402), done.", color: "text-gray-500", delay: 300 }, { text: "> CHECKING_ENVIRONMENT...", color: "text-gray-500", delay: 300 },
{ text: "$ cd NEO-Bot-Framework", color: "text-white", delay: 100 }, { text: "> STATUS: PRIVATE_MODE_ACTIVE", color: "text-blue-400", delay: 600 },
{ text: "$ pip install -r requirements.txt", color: "text-white", delay: 100 }, { text: "> CONNECTING_TO_ONEBOT...", color: "text-gray-500", delay: 800 },
{ text: "Successfully installed: watchdog loguru websockets redis pydantic", color: "text-green-400", delay: 500 }, { text: "> CONNECTION_ESTABLISHED", color: "text-green-500", delay: 1000 },
{ text: "$ python main.py", color: "text-white", delay: 200 }, { text: "> WAITING_FOR_COMMAND...", color: "text-white animate-pulse", delay: 2000 }
{ 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'); const term = document.getElementById('terminal');
@@ -360,28 +327,15 @@ NEO Bot 主程序入口
const line = terminalLines[lineIndex]; const line = terminalLines[lineIndex];
const div = document.createElement('div'); const div = document.createElement('div');
div.className = `mb-1 ${line.color}`; div.className = `${line.color}`;
div.textContent = line.text; div.textContent = line.text;
term.appendChild(div); term.appendChild(div);
term.scrollTop = term.scrollHeight;
lineIndex++; lineIndex++;
setTimeout(runTerminal, line.delay || 100); setTimeout(runTerminal, line.delay || 500);
} }
// 剪贴板功能 setTimeout(runTerminal, 1000);
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> </script>
</body> </body>
</html> </html>