- panel.py 调开放平台 2026-08 新增的 /v2/panels 接口,把 点歌/歌词/帮助 三条指令同步到输入框 / 菜单:READY 时幂等同步(没有则创建、内容有变 则更新、一致则跳过,重连自愈),target_type=all 对全部群生效;失败 只记日志不影响运行;COMMAND_PANEL=off 可关闭 - 斜杠指令与 @机器人 消息归一解析:_normalize 剥开头 / 与 @ 前缀, 与裸文本命令共用 handle_command(/点歌 稻香、@bot 点歌 稻香、 点歌 稻香 三种写法等价) - 只敲命令不带参数(斜杠指令参数可为空)时回复用法提示 - 帮助消息带 [🎤 点歌][📝 歌词] 指令按钮(action type=2,点击把 /点歌 填进输入框),键盘无权限自动回退纯文本;帮助文案改以 / 指令呈现
65 lines
2.5 KiB
Python
65 lines
2.5 KiB
Python
"""Bot 全局配置:启动时从环境变量一次性读齐。"""
|
||
|
||
import os
|
||
from dataclasses import dataclass
|
||
from pathlib import Path
|
||
|
||
# 内嵌键盘上限 5 行 × 每行 5 个;歌曲占行 + 1 行翻页 → 每页最多 20 首
|
||
_MAX_MENU_PAGE_SIZE = 20
|
||
|
||
_LOG_LEVELS = ("TRACE", "DEBUG", "INFO", "SUCCESS", "WARNING", "ERROR", "CRITICAL")
|
||
|
||
|
||
def _flag(name: str, default: bool) -> bool:
|
||
"""读布尔环境变量:on/true/1/yes 为真,off/false/0/no 为假。"""
|
||
raw = os.getenv(name, "").strip().lower()
|
||
if not raw:
|
||
return default
|
||
return raw in ("1", "true", "on", "yes")
|
||
|
||
|
||
def _send_mode() -> str:
|
||
"""SEND_MODE:下载发送方式。
|
||
|
||
file 先上传群文件、失败回退直链;link 直接发直链(跳过上传,可避开
|
||
"仅群主和管理员上传文件" 的 40093005)。非法值按默认 link 处理。
|
||
"""
|
||
raw = os.getenv("SEND_MODE", "").strip().lower()
|
||
return raw if raw in ("file", "link") else "link"
|
||
|
||
|
||
@dataclass(frozen=True, slots=True)
|
||
class BotConfig:
|
||
music_server_url: str
|
||
music_quality: str
|
||
music_source: str
|
||
menu_page_size: int = 10 # 选歌菜单每页候选数(1~20)
|
||
withdraw: bool = True # 自动撤回旧菜单/卡片是否开启
|
||
send_mode: str = "link" # 下载发送方式:"file" 先传文件 / "link" 直接发直链
|
||
command_panel: bool = True # 启动/重连时自动注册指令面板(输入框 / 菜单)
|
||
log_level: str = "INFO" # 控制台与文件日志级别
|
||
log_dir: Path = Path("logs") # 日志目录;写不进去时自动退化为仅控制台
|
||
reload: bool = False # 热重载(开发用;--reload 亦可开启)
|
||
|
||
@classmethod
|
||
def load(cls) -> "BotConfig":
|
||
page_size = int(os.getenv("MENU_PAGE_SIZE", "10"))
|
||
return cls(
|
||
music_server_url=os.getenv("MUSIC_SERVER_URL", "http://127.0.0.1:16688"),
|
||
music_quality=os.getenv("MUSIC_QUALITY", "128k"),
|
||
music_source=os.getenv("MUSIC_SOURCE", "tx"),
|
||
menu_page_size=min(max(1, page_size), _MAX_MENU_PAGE_SIZE),
|
||
withdraw=_flag("WITHDRAW", True),
|
||
send_mode=_send_mode(),
|
||
command_panel=_flag("COMMAND_PANEL", True),
|
||
log_level=_log_level(),
|
||
log_dir=Path(os.getenv("LOG_DIR", "logs")),
|
||
reload=_flag("RELOAD", False),
|
||
)
|
||
|
||
|
||
def _log_level() -> str:
|
||
"""LOG_LEVEL:日志级别,非法值按 INFO。"""
|
||
raw = os.getenv("LOG_LEVEL", "").strip().upper()
|
||
return raw if raw in _LOG_LEVELS else "INFO"
|