refactor(config): 简化EULA验证并统一环境变量配置管理
- 重构EULA验证机制,从复杂的文件哈希验证改为简单的环境变量验证 - 统一host和port配置,优先从环境变量读取而非配置文件 - 移除ServerConfig配置类,简化配置结构 - 添加.env文件自动创建和管理功能 - 更新相关模板和文档注释
This commit is contained in:
131
bot.py
131
bot.py
@@ -1,6 +1,5 @@
|
||||
# import asyncio
|
||||
import asyncio
|
||||
import hashlib
|
||||
import os
|
||||
import sys
|
||||
import time
|
||||
@@ -9,6 +8,7 @@ import traceback
|
||||
from pathlib import Path
|
||||
from rich.traceback import install
|
||||
from colorama import init, Fore
|
||||
from dotenv import load_dotenv # 处理.env文件
|
||||
|
||||
# maim_message imports for console input
|
||||
|
||||
@@ -34,6 +34,28 @@ script_dir = os.path.dirname(os.path.abspath(__file__))
|
||||
os.chdir(script_dir)
|
||||
logger.info(f"已设置工作目录为: {script_dir}")
|
||||
|
||||
# 检查并创建.env文件
|
||||
def ensure_env_file():
|
||||
"""确保.env文件存在,如果不存在则从模板创建"""
|
||||
env_file = Path(".env")
|
||||
template_env = Path("template/template.env")
|
||||
|
||||
if not env_file.exists():
|
||||
if template_env.exists():
|
||||
logger.info("未找到.env文件,正在从模板创建...")
|
||||
import shutil
|
||||
shutil.copy(template_env, env_file)
|
||||
logger.info("已从template/template.env创建.env文件")
|
||||
logger.warning("请编辑.env文件,将EULA_CONFIRMED设置为true并配置其他必要参数")
|
||||
else:
|
||||
logger.error("未找到.env文件和template.env模板文件")
|
||||
sys.exit(1)
|
||||
|
||||
# 确保环境文件存在
|
||||
ensure_env_file()
|
||||
|
||||
# 加载环境变量
|
||||
load_dotenv()
|
||||
|
||||
confirm_logger = get_logger("confirm")
|
||||
# 获取没有加载env时的环境变量
|
||||
@@ -105,82 +127,41 @@ async def graceful_shutdown():
|
||||
logger.error(f"麦麦关闭失败: {e}", exc_info=True)
|
||||
|
||||
|
||||
def _calculate_file_hash(file_path: Path, file_type: str) -> str:
|
||||
"""计算文件的MD5哈希值"""
|
||||
if not file_path.exists():
|
||||
logger.error(f"{file_type} 文件不存在")
|
||||
raise FileNotFoundError(f"{file_type} 文件不存在")
|
||||
|
||||
with open(file_path, "r", encoding="utf-8") as f:
|
||||
content = f.read()
|
||||
return hashlib.md5(content.encode("utf-8")).hexdigest()
|
||||
|
||||
|
||||
def _check_agreement_status(file_hash: str, confirm_file: Path, env_var: str) -> tuple[bool, bool]:
|
||||
"""检查协议确认状态
|
||||
|
||||
Returns:
|
||||
tuple[bool, bool]: (已确认, 未更新)
|
||||
"""
|
||||
# 检查环境变量确认
|
||||
if file_hash == os.getenv(env_var):
|
||||
return True, False
|
||||
|
||||
# 检查确认文件
|
||||
if confirm_file.exists():
|
||||
with open(confirm_file, "r", encoding="utf-8") as f:
|
||||
confirmed_content = f.read()
|
||||
if file_hash == confirmed_content:
|
||||
return True, False
|
||||
|
||||
return False, True
|
||||
|
||||
|
||||
def _prompt_user_confirmation(eula_hash: str, privacy_hash: str) -> None:
|
||||
"""提示用户确认协议"""
|
||||
confirm_logger.critical("EULA或隐私条款内容已更新,请在阅读后重新确认,继续运行视为同意更新后的以上两款协议")
|
||||
confirm_logger.critical(
|
||||
f'输入"同意"或"confirmed"或设置环境变量"EULA_AGREE={eula_hash}"和"PRIVACY_AGREE={privacy_hash}"继续运行'
|
||||
)
|
||||
|
||||
while True:
|
||||
user_input = input().strip().lower()
|
||||
if user_input in ["同意", "confirmed"]:
|
||||
return
|
||||
confirm_logger.critical('请输入"同意"或"confirmed"以继续运行')
|
||||
|
||||
|
||||
def _save_confirmations(eula_updated: bool, privacy_updated: bool, eula_hash: str, privacy_hash: str) -> None:
|
||||
"""保存用户确认结果"""
|
||||
if eula_updated:
|
||||
logger.info(f"更新EULA确认文件{eula_hash}")
|
||||
Path("eula.confirmed").write_text(eula_hash, encoding="utf-8")
|
||||
|
||||
if privacy_updated:
|
||||
logger.info(f"更新隐私条款确认文件{privacy_hash}")
|
||||
Path("privacy.confirmed").write_text(privacy_hash, encoding="utf-8")
|
||||
|
||||
|
||||
def check_eula():
|
||||
"""检查EULA和隐私条款确认状态"""
|
||||
# 计算文件哈希值
|
||||
eula_hash = _calculate_file_hash(Path("EULA.md"), "EULA.md")
|
||||
privacy_hash = _calculate_file_hash(Path("PRIVACY.md"), "PRIVACY.md")
|
||||
|
||||
# 检查确认状态
|
||||
eula_confirmed, eula_updated = _check_agreement_status(eula_hash, Path("eula.confirmed"), "EULA_AGREE")
|
||||
privacy_confirmed, privacy_updated = _check_agreement_status(
|
||||
privacy_hash, Path("privacy.confirmed"), "PRIVACY_AGREE"
|
||||
)
|
||||
|
||||
# 早期返回:如果都已确认且未更新
|
||||
if eula_confirmed and privacy_confirmed:
|
||||
"""检查EULA和隐私条款确认状态 - 环境变量版(类似Minecraft)"""
|
||||
# 检查环境变量中的EULA确认
|
||||
eula_confirmed = os.getenv('EULA_CONFIRMED', '').lower()
|
||||
|
||||
if eula_confirmed == 'true':
|
||||
logger.info("EULA已通过环境变量确认")
|
||||
return
|
||||
|
||||
# 如果有更新,需要重新确认
|
||||
if eula_updated or privacy_updated:
|
||||
_prompt_user_confirmation(eula_hash, privacy_hash)
|
||||
_save_confirmations(eula_updated, privacy_updated, eula_hash, privacy_hash)
|
||||
|
||||
# 如果没有确认,提示用户
|
||||
confirm_logger.critical("您需要同意EULA和隐私条款才能使用MoFox_Bot")
|
||||
confirm_logger.critical("请阅读以下文件:")
|
||||
confirm_logger.critical(" - EULA.md (用户许可协议)")
|
||||
confirm_logger.critical(" - PRIVACY.md (隐私条款)")
|
||||
confirm_logger.critical("然后编辑 .env 文件,将 'EULA_CONFIRMED=false' 改为 'EULA_CONFIRMED=true'")
|
||||
|
||||
# 等待用户确认
|
||||
while True:
|
||||
try:
|
||||
load_dotenv(override=True) # 重新加载.env文件
|
||||
|
||||
eula_confirmed = os.getenv('EULA_CONFIRMED', '').lower()
|
||||
if eula_confirmed == 'true':
|
||||
confirm_logger.info("EULA确认成功,感谢您的同意")
|
||||
return
|
||||
|
||||
confirm_logger.critical("请修改 .env 文件中的 EULA_CONFIRMED=true 后重新启动程序")
|
||||
input("按Enter键检查.env文件状态...")
|
||||
|
||||
except KeyboardInterrupt:
|
||||
confirm_logger.info("用户取消,程序退出")
|
||||
sys.exit(0)
|
||||
except Exception as e:
|
||||
confirm_logger.error(f"检查EULA状态失败: {e}")
|
||||
sys.exit(1)
|
||||
|
||||
|
||||
class MaiBotMain(BaseMain):
|
||||
|
||||
@@ -3,6 +3,7 @@ import importlib.metadata
|
||||
from maim_message import MessageServer
|
||||
from src.common.logger import get_logger
|
||||
from src.config.config import global_config
|
||||
import os
|
||||
|
||||
global_api = None
|
||||
|
||||
@@ -22,9 +23,18 @@ def get_global_api() -> MessageServer: # sourcery skip: extract-method
|
||||
maim_message_config = global_config.maim_message
|
||||
|
||||
# 设置基本参数
|
||||
|
||||
host = os.getenv("HOST", "127.0.0.1")
|
||||
port_str = os.getenv("PORT", "8000")
|
||||
|
||||
try:
|
||||
port = int(port_str)
|
||||
except ValueError:
|
||||
port = 8000
|
||||
|
||||
kwargs = {
|
||||
"host": global_config.server.host,
|
||||
"port": int(global_config.server.port),
|
||||
"host": host,
|
||||
"port": port,
|
||||
"app": get_global_server().get_app(),
|
||||
}
|
||||
|
||||
|
||||
@@ -4,6 +4,7 @@ from typing import Optional
|
||||
from uvicorn import Config, Server as UvicornServer
|
||||
from src.config.config import global_config
|
||||
from rich.traceback import install
|
||||
import os
|
||||
|
||||
install(extra_lines=3)
|
||||
|
||||
@@ -98,5 +99,14 @@ def get_global_server() -> Server:
|
||||
"""获取全局服务器实例"""
|
||||
global global_server
|
||||
if global_server is None:
|
||||
global_server = Server(host=global_config.server.host,port=int(global_config.server.port),)
|
||||
|
||||
host = os.getenv("HOST", "127.0.0.1")
|
||||
port_str = os.getenv("PORT", "8000")
|
||||
|
||||
try:
|
||||
port = int(port_str)
|
||||
except ValueError:
|
||||
port = 8000
|
||||
|
||||
global_server = Server(host=host, port=port)
|
||||
return global_server
|
||||
|
||||
@@ -43,8 +43,7 @@ from src.config.official_configs import (
|
||||
CrossContextConfig,
|
||||
PermissionConfig,
|
||||
CommandConfig,
|
||||
PlanningSystemConfig,
|
||||
ServerConfig,
|
||||
PlanningSystemConfig
|
||||
)
|
||||
|
||||
from .api_ada_configs import (
|
||||
@@ -399,7 +398,6 @@ class Config(ValidatedConfigBase):
|
||||
cross_context: CrossContextConfig = Field(
|
||||
default_factory=lambda: CrossContextConfig(), description="跨群聊上下文共享配置"
|
||||
)
|
||||
server: ServerConfig = Field(default_factory=lambda: ServerConfig(), description="主服务器配置")
|
||||
|
||||
|
||||
class APIAdapterConfig(ValidatedConfigBase):
|
||||
|
||||
@@ -477,12 +477,6 @@ class ExperimentalConfig(ValidatedConfigBase):
|
||||
pfc_chatting: bool = Field(default=False, description="启用PFC聊天")
|
||||
|
||||
|
||||
class ServerConfig(ValidatedConfigBase):
|
||||
"""主服务器配置类"""
|
||||
|
||||
host: str = Field(default="127.0.0.1", description="主服务器监听地址")
|
||||
port: int = Field(default=8080, description="主服务器监听端口")
|
||||
|
||||
|
||||
class MaimMessageConfig(ValidatedConfigBase):
|
||||
"""maim_message配置类"""
|
||||
|
||||
@@ -1,2 +1,3 @@
|
||||
HOST=127.0.0.1
|
||||
PORT=8000
|
||||
PORT=8000
|
||||
EULA_CONFIRMED=false
|
||||
Reference in New Issue
Block a user