refactor(plugins): comprehensive code review - ~35 fixes across 14 plugins

Phase 1 - Plugin code review (14/14 plugins):
- Security: 3x token leak in print→logger.debug, Bearer prefix handling
- Bug: bare except→specific exceptions, HorseState type safety, sync→async
- Critical: response_model undefined, route dead code, sync blocking event loop
- Quality: 11x print()→logger, variable name shadowing, consistent logging

Phase 2 - Deep analysis:
- Fix: payout int truncation→max(1, round(amount*odds))
- Fix: room_store get_lock race condition→dict.setdefault()
- Verify: data_manager f-string SQL is safe (uses ? placeholders)

Infrastructure: review reports generated for all plugins.
This commit is contained in:
2026-05-09 23:22:28 +08:00
parent 9a8cb3ad6d
commit c01338f496
43 changed files with 4233 additions and 3645 deletions

View File

@@ -1,62 +1,58 @@
import asyncio
from typing import Optional, Dict, Any
from nonebot import get_driver, get_plugin_config, logger
from nonebot.adapters.onebot.v11 import Bot
from nonebot.plugin import PluginMetadata
from nonebot.exception import MockApiException
from nonebot.adapters import Bot
from nonebot.typing import T_State
from .config import Config
# 插件元信息
__plugin_meta__ = PluginMetadata(
name="auto_recall",
description="一个通用的消息撤回插件,监控所有发出的消息并在指定时间后撤回",
usage="无需手动调用,插件会自动监控并撤回消息",
config=Config,
)
# 获取插件配置
plugin_config = get_plugin_config(Config)
# 注册 API 调用后钩子
@Bot.on_called_api
async def handle_api_result(
bot: Bot, exception: Optional[Exception], api: str, data: Dict[str, Any], result: Any
):
"""拦截 send_msg 和 send_group_msg API 调用,监控发出的消息"""
if api not in ["send_msg", "send_group_msg"] or exception:
return
# 获取消息 ID
message_id = result.get("message_id")
if not message_id:
logger.warning("未找到 message_id无法撤回消息")
return
# 获取撤回延迟时间
recall_delay = plugin_config.recall_delay
# 检查是否为 danding_qqpush 发送的消息
# danding_qqpush 消息会在 data 中包含 __qqpush_source 标记
is_qqpush_message = data.get("__qqpush_source") == "danding_qqpush"
if is_qqpush_message:
# 使用 danding_qqpush 专用的撤回时间
recall_delay = plugin_config.qqpush_recall_delay
logger.info(f"danding_qqpush 消息将在 {recall_delay} 秒后撤回")
# 启动异步任务,延迟撤回消息
asyncio.create_task(recall_message_after_delay(bot, message_id, recall_delay))
async def recall_message_after_delay(bot: Bot, message_id: int, delay: int):
"""在指定时间后撤回消息"""
await asyncio.sleep(delay) # 等待指定时间
try:
await bot.delete_msg(message_id=message_id) # 撤回消息
except Exception as e:
if "success" in str(e).lower() or "timeout" in str(e).lower():
# 忽略成功和超时的错误
return
logger.error(f"撤回消息失败: {str(e)}")
import asyncio
from typing import Optional, Dict, Any, Set
from nonebot import get_plugin_config, logger
from nonebot.adapters.onebot.v11 import Bot
from nonebot.plugin import PluginMetadata
from .config import Config
# 插件元信息
__plugin_meta__ = PluginMetadata(
name="auto_recall",
description="一个通用的消息撤回插件,监控所有发出的消息并在指定时间后撤回",
usage="无需手动调用,插件会自动监控并撤回消息",
config=Config,
)
# 获取插件配置
plugin_config = get_plugin_config(Config)
# 撤回任务引用集合防止被GC回收
_recall_tasks: Set[asyncio.Task] = set()
def _track_task(task: asyncio.Task) -> None:
"""跟踪异步任务,完成后自动移除"""
_recall_tasks.add(task)
task.add_done_callback(_recall_tasks.discard)
# 注册 API 调用后钩子
@Bot.on_called_api
async def handle_api_result(
bot: Bot, exception: Optional[Exception], api: str, data: Dict[str, Any], result: Any
):
"""拦截发送消息API调用监控发出的消息"""
if api not in ("send_msg", "send_group_msg", "send_private_msg") or exception:
return
message_id = result.get("message_id")
if not message_id:
return
recall_delay = plugin_config.recall_delay
# 检查是否为 danding_qqpush 发送的消息
if data.get("__qqpush_source") == "danding_qqpush":
recall_delay = plugin_config.qqpush_recall_delay
logger.info(f"danding_qqpush 消息将在 {recall_delay}s 后撤回: msg_id={message_id}")
task = asyncio.create_task(recall_message_after_delay(bot, message_id, recall_delay))
_track_task(task)
async def recall_message_after_delay(bot: Bot, message_id: int, delay: int):
"""在指定时间后撤回消息"""
await asyncio.sleep(delay)
try:
await bot.delete_msg(message_id=message_id)
logger.debug(f"消息已撤回: msg_id={message_id}")
except Exception as e:
logger.error(f"撤回消息失败: msg_id={message_id} error={e}")

View File

@@ -1,5 +1,11 @@
from pydantic import BaseModel, Field
class Config(BaseModel):
recall_delay: int = Field(default=110, env="RECALL_DELAY") # 撤回延迟时间,默认 110 秒
qqpush_recall_delay: int = Field(default=3600, env="QQPUSH_RECALL_DELAY") # danding_qqpush 消息撤回延迟时间,默认 3600 秒1小时
from pydantic import BaseModel, Field, validator
class Config(BaseModel):
recall_delay: int = Field(default=110, ge=1, env="RECALL_DELAY")
qqpush_recall_delay: int = Field(default=3600, ge=1, env="QQPUSH_RECALL_DELAY")
@validator("recall_delay", "qqpush_recall_delay")
def delay_must_be_positive(cls, v: int) -> int:
if v < 1:
raise ValueError("撤回延迟必须大于0秒")
return v