feat: 改进配置加载逻辑并更新项目配置
当配置文件不存在时自动生成示例配置 添加pyproject.toml作为项目构建配置 更新.gitignore忽略更多文件类型 删除不再使用的反向WebSocket示例文件
This commit is contained in:
28
.gitignore
vendored
28
.gitignore
vendored
@@ -115,7 +115,7 @@ env/
|
||||
venv/
|
||||
ENV/
|
||||
env.bak/
|
||||
venv.bak/
|
||||
venv.bak()
|
||||
|
||||
# Spyder project settings
|
||||
.spyderproject
|
||||
@@ -138,6 +138,9 @@ dmypy.json
|
||||
# pytype static type analyzer
|
||||
.pytype/
|
||||
|
||||
# Cython
|
||||
*.c
|
||||
|
||||
# End of https://www.toptal.com/developers/gitignore/api/python
|
||||
|
||||
# Build artifacts
|
||||
@@ -146,4 +149,27 @@ build/
|
||||
# Scratch files
|
||||
scratch_files/
|
||||
|
||||
# Sensitive files (should never be committed)
|
||||
config.toml
|
||||
config.example.toml
|
||||
ca/*
|
||||
*.pem
|
||||
*.key
|
||||
|
||||
# Data directory (may contain sensitive data)
|
||||
/core/data/*
|
||||
|
||||
# IDE
|
||||
.vscode/
|
||||
.idea/
|
||||
*.swp
|
||||
*.swo
|
||||
*~
|
||||
|
||||
# OS
|
||||
.DS_Store
|
||||
Thumbs.db
|
||||
|
||||
# Logs
|
||||
logs/
|
||||
*.log
|
||||
|
||||
@@ -38,10 +38,10 @@ class Config:
|
||||
:raises ConfigError: 如果加载配置时发生其他错误
|
||||
"""
|
||||
if not self.path.exists():
|
||||
error = ConfigNotFoundError(message=f"配置文件 {self.path} 未找到!")
|
||||
self.logger.error(f"配置加载失败: {error.message}")
|
||||
self.logger.log_custom_exception(error)
|
||||
raise error
|
||||
self.logger.warning(f"配置文件 {self.path} 未找到,正在生成示例配置...")
|
||||
self._generate_example_config()
|
||||
self.logger.success(f"示例配置已生成: {self.path}")
|
||||
self.logger.info("请编辑配置文件后重新启动程序")
|
||||
|
||||
try:
|
||||
self.logger.info(f"正在从 {self.path} 加载配置...")
|
||||
@@ -86,6 +86,19 @@ class Config:
|
||||
self.logger.log_custom_exception(error)
|
||||
raise error
|
||||
|
||||
def _generate_example_config(self):
|
||||
"""
|
||||
生成示例配置文件
|
||||
"""
|
||||
example_path = Path("config.example.toml")
|
||||
|
||||
if not example_path.exists():
|
||||
self.logger.error(f"示例配置文件 {example_path} 不存在,无法生成配置")
|
||||
raise ConfigNotFoundError(message=f"示例配置文件 {example_path} 不存在")
|
||||
|
||||
content = example_path.read_text()
|
||||
self.path.write_text(content)
|
||||
|
||||
# 通过属性访问配置
|
||||
@property
|
||||
def napcat_ws(self) -> NapCatWSModel:
|
||||
|
||||
@@ -1,58 +0,0 @@
|
||||
"""
|
||||
反向 WebSocket 使用示例
|
||||
|
||||
该文件展示了如何使用反向 WebSocket 功能。
|
||||
"""
|
||||
|
||||
from core.managers import reverse_ws_manager
|
||||
|
||||
|
||||
async def example_usage():
|
||||
"""
|
||||
使用示例
|
||||
"""
|
||||
# 1. 启动反向 WebSocket 服务端
|
||||
await reverse_ws_manager.start(host="0.0.0.0", port=3002)
|
||||
|
||||
# 2. 等待客户端连接
|
||||
# 此时 OneBot 实现(如 NapCat)应该连接到 ws://your-server-ip:3002
|
||||
|
||||
# 3. 查看已连接的客户端
|
||||
connected_clients = reverse_ws_manager.get_connected_clients()
|
||||
print(f"已连接的客户端: {connected_clients}")
|
||||
|
||||
# 4. 查看健康的客户端
|
||||
healthy_clients = reverse_ws_manager.get_healthy_clients()
|
||||
print(f"健康的客户端: {healthy_clients}")
|
||||
|
||||
# 5. 调用 API(使用负载均衡)
|
||||
response = await reverse_ws_manager.call_api(
|
||||
action="get_login_info",
|
||||
params={},
|
||||
use_load_balance=True # 启用负载均衡
|
||||
)
|
||||
print(f"API 响应: {response}")
|
||||
|
||||
# 6. 调用 API(向特定客户端发送)
|
||||
if connected_clients:
|
||||
client_id = list(connected_clients.keys())[0]
|
||||
response = await reverse_ws_manager.call_api(
|
||||
action="get_login_info",
|
||||
params={},
|
||||
client_id=client_id,
|
||||
use_load_balance=False # 不使用负载均衡
|
||||
)
|
||||
print(f"特定客户端 API 响应: {response}")
|
||||
|
||||
# 7. 获取负载最低的客户端
|
||||
least_load_client = reverse_ws_manager.get_client_with_least_load()
|
||||
if least_load_client:
|
||||
print(f"负载最低的客户端: {least_load_client}")
|
||||
|
||||
# 8. 停止服务端
|
||||
await reverse_ws_manager.stop()
|
||||
|
||||
|
||||
if __name__ == "__main__":
|
||||
import asyncio
|
||||
asyncio.run(example_usage())
|
||||
91
pyproject.toml
Normal file
91
pyproject.toml
Normal file
@@ -0,0 +1,91 @@
|
||||
[build-system]
|
||||
requires = ["setuptools>=61.0", "wheel"]
|
||||
build-backend = "setuptools.build_meta"
|
||||
|
||||
[project]
|
||||
name = "neobot"
|
||||
version = "0.1.0"
|
||||
description = "NEO Bot Framework - A high-performance bot framework"
|
||||
readme = "README.md"
|
||||
requires-python = ">=3.14"
|
||||
license = {text = "MIT"}
|
||||
authors = [
|
||||
{name = "Neo", email = "neo@example.com"}
|
||||
]
|
||||
keywords = ["bot", "discord", "qq", "onebot"]
|
||||
classifiers = [
|
||||
"Development Status :: 4 - Beta",
|
||||
"Intended Audience :: Developers",
|
||||
"License :: OSI Approved :: MIT License",
|
||||
"Programming Language :: Python :: 3",
|
||||
"Programming Language :: Python :: 3.14",
|
||||
]
|
||||
|
||||
dependencies = [
|
||||
"aiohttp>=3.9.0",
|
||||
"websockets>=12.0",
|
||||
"playwright>=1.40.0",
|
||||
"redis>=5.0.0",
|
||||
"orjson>=3.9.0",
|
||||
"loguru>=0.7.0",
|
||||
"tomlkit>=0.12.0",
|
||||
"watchdog>=3.0.0",
|
||||
"discord.py>=2.0.0",
|
||||
"aiohappyeyeballs>=2.6.1",
|
||||
"aiomysql>=0.2.0",
|
||||
"beautifulsoup4>=4.12.0",
|
||||
"requests>=2.31.0",
|
||||
"cython>=3.0.0",
|
||||
]
|
||||
|
||||
[project.optional-dependencies]
|
||||
dev = [
|
||||
"pyinstrument>=4.5.0",
|
||||
"memory-profiler>=0.61.0",
|
||||
"psutil>=5.9.8",
|
||||
"pytest>=7.4.0",
|
||||
"pytest-asyncio>=0.21.0",
|
||||
"flake8>=7.0.0",
|
||||
"mypy>=1.5.0",
|
||||
]
|
||||
|
||||
[project.urls]
|
||||
Homepage = "https://github.com/yourusername/neobot"
|
||||
Documentation = "https://github.com/yourusername/neobot#readme"
|
||||
Repository = "https://github.com/yourusername/neobot"
|
||||
"Bug Tracker" = "https://github.com/yourusername/neobot/issues"
|
||||
|
||||
[tool.setuptools]
|
||||
packages = ["core", "models", "plugins", "adapters"]
|
||||
package-dir = {"" = "."}
|
||||
|
||||
[tool.setuptools.package-data]
|
||||
"core" = ["py.typed"]
|
||||
"plugins" = ["**/*.py"]
|
||||
"models" = ["**/*.py"]
|
||||
|
||||
[tool.setuptools.exclude-package-data]
|
||||
"*" = [
|
||||
"config.toml",
|
||||
"config.example.toml",
|
||||
"ca/*",
|
||||
"*.pem",
|
||||
"*.key",
|
||||
]
|
||||
|
||||
[tool.pytest.ini_options]
|
||||
testpaths = ["tests"]
|
||||
python_files = ["test_*.py"]
|
||||
asyncio_mode = "auto"
|
||||
|
||||
[tool.mypy]
|
||||
python_version = "3.14"
|
||||
warn_return_any = true
|
||||
warn_unused_configs = true
|
||||
disallow_untyped_defs = true
|
||||
check_untyped_defs = true
|
||||
no_implicit_optional = true
|
||||
warn_redundant_casts = true
|
||||
warn_subclassing = true
|
||||
strict_optional = true
|
||||
plugins = ["mypy.plugins.asyncio"]
|
||||
Reference in New Issue
Block a user