- 文件代理(PUBLIC_URL):上传与直链文本的 URL 换成 bot 公开地址,请求 到来现场重解析直链再转发字节,绕开 QQ 抓风控直链失败(40093007)与 qs 本地流外网不可达;PROXY_PORT 指定监听端口 - 群消息去重补第二把钥匙:全量模式下 @消息同时命中两事件且 msg_id 不同, 只按 msg_id 拦不住,再加「群+发送人+文本」10 秒短窗(修双发) - 「<平台>下载 <歌名>」改出该平台的选歌菜单(与 /点歌 同款交互、spage 翻页锁定平台),不再直接下第一首 - 猫耳/懒人/蜻蜓节目级条目点编号先出选集菜单(/album):猫耳选集接口 忽略翻页参数,一次拉 50 集本地切片;懒人/蜻蜓走服务端翻页;空选集 (已下线/需登录)给明确提示 - 指令面板条目按 /sources 现算、按宽度裁剪(修 30013 超限);装配入口 改用 Bot 门面;qqbotsdk 依赖更名 qqbotsdk-py(撤 GitHub archive 源)
This commit is contained in:
1 parent
324fe86962
commit
c364506925
10 files changed
+1883
-254
No files matched your search
@@ -3,10 +3,14 @@
|
||||
import os
|
||||
from dataclasses import dataclass
|
||||
from pathlib import Path
|
||||
from urllib.parse import urlsplit
|
||||
|
||||
# 内嵌键盘上限 5 行 × 每行 5 个;歌曲占行 + 1 行翻页 → 每页最多 20 首
|
||||
_MAX_MENU_PAGE_SIZE = 20
|
||||
|
||||
# PUBLIC_URL 不带端口时文件代理的监听端口(MusicServer 默认在 16688)
|
||||
_DEFAULT_PROXY_PORT = 16689
|
||||
|
||||
_LOG_LEVELS = ("TRACE", "DEBUG", "INFO", "SUCCESS", "WARNING", "ERROR", "CRITICAL")
|
||||
|
||||
|
||||
@@ -28,6 +32,20 @@ def _send_mode() -> str:
|
||||
return raw if raw in ("file", "link") else "link"
|
||||
|
||||
|
||||
def _proxy_port(public_url: str) -> int:
|
||||
"""PROXY_PORT:文件代理的监听端口。
|
||||
|
||||
缺省跟随 PUBLIC_URL 里的显式端口(如 http://1.2.3.4:16689 → 16689),
|
||||
没写端口用默认(https 域名走反向代理时必须显式配置,bot 本身不收 TLS)。"""
|
||||
raw = os.getenv("PROXY_PORT", "").strip()
|
||||
if raw.isdigit():
|
||||
return int(raw)
|
||||
try:
|
||||
return urlsplit(public_url).port or _DEFAULT_PROXY_PORT
|
||||
except ValueError: # URL 端口段写坏了
|
||||
return _DEFAULT_PROXY_PORT
|
||||
|
||||
|
||||
@dataclass(frozen=True, slots=True)
|
||||
class BotConfig:
|
||||
music_server_url: str
|
||||
@@ -36,6 +54,9 @@ class BotConfig:
|
||||
menu_page_size: int = 10 # 选歌菜单每页候选数(1~20)
|
||||
withdraw: bool = True # 自动撤回旧菜单/卡片是否开启
|
||||
send_mode: str = "link" # 下载发送方式:"file" 先传文件 / "link" 直接发直链
|
||||
file_proxy: bool = False # 文件代理开关(FILE_PROXY=on 且配了 PUBLIC_URL 才开)
|
||||
public_url: str = "" # 文件代理对外基址(PUBLIC_URL,如 http://1.2.3.4:16689)
|
||||
proxy_port: int = _DEFAULT_PROXY_PORT # 文件代理监听端口(缺省跟 PUBLIC_URL)
|
||||
command_panel: bool = True # 启动/重连时自动注册指令面板(输入框 / 菜单)
|
||||
log_level: str = "INFO" # 控制台与文件日志级别
|
||||
log_dir: Path = Path("logs") # 日志目录;写不进去时自动退化为仅控制台
|
||||
@@ -44,6 +65,7 @@ class BotConfig:
|
||||
@classmethod
|
||||
def load(cls) -> "BotConfig":
|
||||
page_size = int(os.getenv("MENU_PAGE_SIZE", "10"))
|
||||
public_url = os.getenv("PUBLIC_URL", "").strip().rstrip("/")
|
||||
return cls(
|
||||
music_server_url=os.getenv("MUSIC_SERVER_URL", "http://127.0.0.1:16688"),
|
||||
music_quality=os.getenv("MUSIC_QUALITY", "128k"),
|
||||
@@ -51,6 +73,9 @@ class BotConfig:
|
||||
menu_page_size=min(max(1, page_size), _MAX_MENU_PAGE_SIZE),
|
||||
withdraw=_flag("WITHDRAW", True),
|
||||
send_mode=_send_mode(),
|
||||
file_proxy=_flag("FILE_PROXY", True) and bool(public_url),
|
||||
public_url=public_url,
|
||||
proxy_port=_proxy_port(public_url),
|
||||
command_panel=_flag("COMMAND_PANEL", True),
|
||||
log_level=_log_level(),
|
||||
log_dir=Path(os.getenv("LOG_DIR", "logs")),
|
||||
|
||||
Reference in new issue
Block a user