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,142 +1,145 @@
from nonebot import on_command, get_plugin_config,logger
from nonebot.permission import SUPERUSER
from nonebot.rule import to_me
from nonebot.adapters.onebot.v11 import PrivateMessageEvent, GroupMessageEvent, MessageSegment
from nonebot.params import Depends
from .config import Config
from .utils import post, get_classes, post_vcode, get_log
import random
import asyncio
import time
plugin_config = get_plugin_config(Config)
help = on_command("咸鸭蛋",rule=to_me(),aliases={"apihelp", "sudhelp"},permission=SUPERUSER, priority=0, block=True)
@help.handle()
async def _():
await asyncio.sleep(random.uniform(2, 3))
await help.finish(plugin_config.HelpStr)
ddonline = on_command("在线人数",rule=to_me(),aliases={"ddonline", "ddop"}, priority=0, block=True)
@ddonline.handle()
async def _(event:PrivateMessageEvent):
id:str = str(event.user_id)
msg:str = await post("在线人数",id)
await asyncio.sleep(random.uniform(2, 3))
await ddonline.finish(msg)
addkami = on_command("添加卡密",rule=to_me(),aliases={"addkami", "akm"},permission=SUPERUSER, priority=0, block=True)
@addkami.handle()
async def _(event:PrivateMessageEvent):
id:str = str(event.user_id)
msg:str = event.get_plaintext()
if len(msg.split(' ')) != 3:
await asyncio.sleep(random.uniform(2, 3))
await ddonline.finish("参数不正确!")
classes:str = msg.split(' ')[1]
classes = get_classes(classes)
if classes == '':
await ddonline.finish("卡密类型不正确!")
kami:str = msg.split(' ')[2]
msg:str = await post("添加卡密",id,{
"classes":classes,
"kami":kami
})
await asyncio.sleep(random.uniform(2, 3))
await ddonline.finish(msg)
createkami = on_command("生成卡密",rule=to_me(),aliases={"createkami", "ckm"},permission=SUPERUSER, priority=0, block=True)
@createkami.handle()
async def _(event:PrivateMessageEvent):
id:str = str(event.user_id)
msg:str = event.get_plaintext()
if len(msg.split(' ')) != 2:
await asyncio.sleep(random.uniform(2, 3))
await ddonline.finish("参数不正确!")
classes:str = msg.split(' ')[1]
classes = get_classes(classes)
if classes == '':
await ddonline.finish("卡密类型不正确!")
msg:str = await post("生成卡密",id,{
"classes":classes
})
await asyncio.sleep(random.uniform(2, 3))
await ddonline.finish(msg)
addviptime = on_command("用户加时",rule=to_me(),aliases={"addviptime", "avt"},permission=SUPERUSER, priority=0, block=True)
@addviptime.handle()
async def _(event:PrivateMessageEvent):
id:str = str(event.user_id)
msg:str = event.get_plaintext()
if len(msg.split(' ')) != 3:
await asyncio.sleep(random.uniform(2, 3))
await ddonline.finish("参数不正确!")
username:str = msg.split(' ')[1]
classes:str = msg.split(' ')[2]
classes = get_classes(classes)
if classes == '':
await ddonline.finish("卡密类型不正确!")
msg:str = await post("用户加时",id,{
"username":username,
"classes":classes
})
await asyncio.sleep(random.uniform(2, 3))
await ddonline.finish(msg)
generate_qq_vcode = on_command("绑定QQ",aliases={"bindqq", "绑定qq"}, priority=0, block=True)
# 添加用户使用时间记录字典
user_last_use_time = {}
@generate_qq_vcode.handle()
async def _(event: GroupMessageEvent): # GroupMessageEvent PrivateMessageEvent
# 检查是否来自指定群组
if event.group_id != 621016172:
return
# if event.user_id != 1424473282:
# return
id:str = str(event.user_id)
# 限流检查:检查用户上次使用时间
current_time = time.time()
if id in user_last_use_time:
time_diff = current_time - user_last_use_time[id]
if time_diff < 60: # 60秒内已使用过
await generate_qq_vcode.finish(f"请求过于频繁,请在{int(60 - time_diff)}秒后再试")
return
# 更新用户最后使用时间
user_last_use_time[id] = current_time
msg:str = await post_vcode(id)
await asyncio.sleep(random.uniform(2, 3))
# 在消息前添加@用户
at_user = MessageSegment.at(event.user_id)
await generate_qq_vcode.finish(at_user + " " + msg)
view_logs = on_command("查看日志",aliases={"logs", "查询日志"}, priority=0, block=True)
@view_logs.handle()
async def _(event:GroupMessageEvent): # GroupMessageEvent PrivateMessageEvent
# 检查是否来自指定群组
if event.group_id != 621016172:
return
# if event.user_id != 1424473282:
# return
id:str = str(event.user_id)
msg:str = await get_log(id)
await asyncio.sleep(random.uniform(2, 3))
# 在消息前添加@用户
at_user = MessageSegment.at(event.user_id)
from nonebot import on_command, get_plugin_config,logger
from nonebot.permission import SUPERUSER
from nonebot.rule import to_me
from nonebot.adapters.onebot.v11 import PrivateMessageEvent, GroupMessageEvent, MessageSegment
from nonebot.params import Depends
from .config import Config
from .utils import post, get_classes, post_vcode, get_log
import random
import asyncio
import time
plugin_config = get_plugin_config(Config)
help = on_command("咸鸭蛋",rule=to_me(),aliases={"apihelp", "sudhelp"},permission=SUPERUSER, priority=0, block=True)
@help.handle()
async def _():
await asyncio.sleep(random.uniform(2, 3))
await help.finish(plugin_config.HelpStr)
ddonline = on_command("在线人数",rule=to_me(),aliases={"ddonline", "ddop"}, priority=0, block=True)
@ddonline.handle()
async def _(event:PrivateMessageEvent):
id:str = str(event.user_id)
msg:str = await post("在线人数",id)
await asyncio.sleep(random.uniform(2, 3))
await ddonline.finish(msg)
addkami = on_command("添加卡密",rule=to_me(),aliases={"addkami", "akm"},permission=SUPERUSER, priority=0, block=True)
@addkami.handle()
async def handle_addkami(event: PrivateMessageEvent):
user_id = str(event.user_id)
msg = event.get_plaintext()
parts = msg.split(' ')
if len(parts) != 3:
await asyncio.sleep(random.uniform(2, 3))
await addkami.finish("参数不正确!格式: /添加卡密 <类型> <卡密>")
classes = get_classes(parts[1])
if not classes:
await addkami.finish("卡密类型不正确!支持: 天/周/月")
try:
result = await post("添加卡密", user_id, {"classes": classes, "kami": parts[2]})
except Exception as e:
logger.error(f"添加卡密失败: {e}")
await addkami.finish("添加卡密失败,请稍后再试")
await asyncio.sleep(random.uniform(2, 3))
await addkami.finish(result)
createkami = on_command("生成卡密",rule=to_me(),aliases={"createkami", "ckm"},permission=SUPERUSER, priority=0, block=True)
@createkami.handle()
async def handle_createkami(event: PrivateMessageEvent):
user_id = str(event.user_id)
msg = event.get_plaintext()
parts = msg.split(' ')
if len(parts) != 2:
await asyncio.sleep(random.uniform(2, 3))
await createkami.finish("参数不正确!格式: /生成卡密 <类型>")
classes = get_classes(parts[1])
if not classes:
await createkami.finish("卡密类型不正确!支持: 天/周/月")
try:
result = await post("生成卡密", user_id, {"classes": classes})
except Exception as e:
logger.error(f"生成卡密失败: {e}")
await createkami.finish("生成卡密失败,请稍后再试")
await asyncio.sleep(random.uniform(2, 3))
await createkami.finish(result)
addviptime = on_command("用户加时",rule=to_me(),aliases={"addviptime", "avt"},permission=SUPERUSER, priority=0, block=True)
@addviptime.handle()
async def handle_addviptime(event: PrivateMessageEvent):
user_id = str(event.user_id)
msg = event.get_plaintext()
parts = msg.split(' ')
if len(parts) != 3:
await asyncio.sleep(random.uniform(2, 3))
await addviptime.finish("参数不正确!格式: /用户加时 <用户名> <类型>")
username = parts[1]
classes = get_classes(parts[2])
if not classes:
await addviptime.finish("卡密类型不正确!支持: 天/周/月")
try:
result = await post("用户加时", user_id, {"username": username, "classes": classes})
except Exception as e:
logger.error(f"用户加时失败: {e}")
await addviptime.finish("用户加时失败,请稍后再试")
await asyncio.sleep(random.uniform(2, 3))
await addviptime.finish(result)
generate_qq_vcode = on_command("绑定QQ",aliases={"bindqq", "绑定qq"}, priority=0, block=True)
# 添加用户使用时间记录字典
user_last_use_time = {}
@generate_qq_vcode.handle()
async def _(event: GroupMessageEvent): # GroupMessageEvent PrivateMessageEvent
# 检查是否来自指定群组
if event.group_id != 621016172:
return
# if event.user_id != 1424473282:
# return
id:str = str(event.user_id)
# 限流检查:检查用户上次使用时间
current_time = time.time()
if id in user_last_use_time:
time_diff = current_time - user_last_use_time[id]
if time_diff < 60: # 60秒内已使用过
await generate_qq_vcode.finish(f"请求过于频繁,请在{int(60 - time_diff)}秒后再试")
return
# 更新用户最后使用时间
user_last_use_time[id] = current_time
msg:str = await post_vcode(id)
await asyncio.sleep(random.uniform(2, 3))
# 在消息前添加@用户
at_user = MessageSegment.at(event.user_id)
await generate_qq_vcode.finish(at_user + " " + msg)
view_logs = on_command("查看日志",aliases={"logs", "查询日志"}, priority=0, block=True)
@view_logs.handle()
async def _(event:GroupMessageEvent): # GroupMessageEvent PrivateMessageEvent
# 检查是否来自指定群组
if event.group_id != 621016172:
return
# if event.user_id != 1424473282:
# return
id:str = str(event.user_id)
msg:str = await get_log(id)
await asyncio.sleep(random.uniform(2, 3))
# 在消息前添加@用户
at_user = MessageSegment.at(event.user_id)
await view_logs.finish(at_user + " " + msg)

View File

@@ -1,155 +1,155 @@
import requests
from nonebot import get_plugin_config
from .config import Config
from nonebot import logger
plugin_config = get_plugin_config(Config)
router:dict = {
"在线人数":"bot_online_count",
"添加卡密":"bot_add_kami",
"生成卡密":"bot_create_kami",
"用户加时":"bot_add_user_viptime",
"生成QQ验证码":"bot_generate_vcode",
"获取日志":"bot_get_user_log"
}
async def post(router_name:str,user:str,data:dict={})->str:
_url:str = plugin_config.DDApi_Host + router[router_name]
data["user"]=user
data["token"]=plugin_config.Token
r = requests.post(url = _url,json=data)
logger.debug(r)
if r.status_code != 200:
return '出错啦!'
r=r.json()
logger.debug(r)
return r["message"]
async def post_vcode(user:str)->str:
_url:str = plugin_config.DDApi_Host + router["生成QQ验证码"]
data:dict={}
data["user"]="1424473282"
data["token"]=plugin_config.Token
data["qq"]=user
r = requests.post(url = _url,json=data)
logger.debug(r)
if r.status_code != 200:
return '出错啦!'
r=r.json()
logger.debug(r)
if "验证码生成成功" in r["message"]:
resp_data = await send_mail(f'{user}@qq.com',"验证码生成成功",r["message"],"DanDing-Admin")
if resp_data is None or resp_data.get("errorNo", -1) != 0:
return r["message"]
else:
return f"生成的绑定验证码已经发送到 {user}@qq.com 邮箱中,请查收!"
return r["message"]
async def get_log(user:str)->str:
_url:str = plugin_config.DDApi_Host + router["获取日志"]
r = requests.get(url = f"{_url}?user=1424473282&token={plugin_config.Token}&qq={user}")
logger.debug(r)
if r.status_code != 200:
return '出错啦!'
r=r.json()
logger.debug(r)
return r["message"]
def get_classes(classee:str):
"""
将口语类型转换为程序可识别的标准卡密类型
"""
cases = {
'day': 'Day',
'DAY': 'Day',
'': 'Day',
'天卡': 'Day',
'week': 'Week',
'WEEK': 'Week',
'': 'Week',
'周卡': 'Week',
'month': 'Month',
'MONTH': 'Month',
'': 'Month',
'月卡': 'Month',
}
return cases.get(classee, '')
session_id: str = ""
# 登录pmail邮箱 获取cookie
login_url = plugin_config.EMAIL_LOGIN
login_pdata = {
"account": plugin_config.EMAIL_USER,
"password": plugin_config.EMAIL_PASSWORD
}
session = requests.session() # 实例化session对象
def login_pmail():
global session_id
resp_data = None
error_msg: str = ""
retries = 3 # 设置重试次数
for attempt in range(retries):
try:
resp_data = session.post(login_url, json=login_pdata, headers={'Content-Type': 'application/json'})
if resp_data.status_code == 200 and resp_data.json().get('errorNo') == 0:
logger.info('PMail App 启动成功!')
session_id = resp_data.headers['Set-Cookie']
return
except ConnectionError:
error_msg = "服务器连接失败!"
except Exception as e:
error_msg = str(e)
logger.warning(f'PMail App 登录失败,正在重试... ({attempt + 1}/{retries})')
# 如果重试次数用尽仍然失败
logger.error(f'PMail App 登录失败!无法使用邮件功能!可能网络错误!{error_msg}')
async def send_mail(mail_to, subject, content, name):
"""
发送邮件
:param mail_to: 发送到
:param subject: 标题
:param content: 内容
:param name: 用户名
:return:
"""
url = plugin_config.EMAIL_API
pdata = {
'from':
{
"name": "DanDing-Admin",
"email": plugin_config.EMAIL_FROM
},
'to':
[
{
"name": name,
"email": mail_to
}
],
'subject': subject,
'html': content,
"text": "text"
}
if session_id is None or "":
logger.error("[error] 邮件发送失败没有session_id尝试重新登录邮箱服务")
login_pmail()
resp_data = session.post(url, json=pdata, headers={"cookie": f"{session_id}"}).json()
if resp_data is None or resp_data.get("errorNo", -1) != 0:
logger.error("[error] 邮件发送失败,未知的错误,尝试重新登录邮箱服务!")
# 重新登录pmail邮箱
login_pmail()
resp_data = session.post(url, json=pdata, headers={"cookie": f"{session_id}"}).json()
if resp_data is None or resp_data.get("errorNo", -1) != 0:
return {"errorNo": 0, "errorMsg": "", "data": ""}
import requests
from nonebot import get_plugin_config
from .config import Config
from nonebot import logger
plugin_config = get_plugin_config(Config)
router:dict = {
"在线人数":"bot_online_count",
"添加卡密":"bot_add_kami",
"生成卡密":"bot_create_kami",
"用户加时":"bot_add_user_viptime",
"生成QQ验证码":"bot_generate_vcode",
"获取日志":"bot_get_user_log"
}
async def post(router_name:str,user:str,data:dict={})->str:
_url:str = plugin_config.DDApi_Host + router[router_name]
data["user"]=user
data["token"]=plugin_config.Token
r = requests.post(url=_url, json=data, timeout=10)
logger.debug(r)
if r.status_code != 200:
return '出错啦!'
r=r.json()
logger.debug(r)
return r["message"]
async def post_vcode(user:str)->str:
_url:str = plugin_config.DDApi_Host + router["生成QQ验证码"]
data:dict={}
data["user"]="1424473282"
data["token"]=plugin_config.Token
data["qq"]=user
r = requests.post(url=_url, json=data, timeout=10)
logger.debug(r)
if r.status_code != 200:
return '出错啦!'
r=r.json()
logger.debug(r)
if "验证码生成成功" in r["message"]:
resp_data = await send_mail(f'{user}@qq.com',"验证码生成成功",r["message"],"DanDing-Admin")
if resp_data is None or resp_data.get("errorNo", -1) != 0:
return r["message"]
else:
return f"生成的绑定验证码已经发送到 {user}@qq.com 邮箱中,请查收!"
return r["message"]
async def get_log(user:str)->str:
_url:str = plugin_config.DDApi_Host + router["获取日志"]
r = requests.get(url=f"{_url}?user=1424473282&token={plugin_config.Token}&qq={user}", timeout=10)
logger.debug(r)
if r.status_code != 200:
return '出错啦!'
r=r.json()
logger.debug(r)
return r["message"]
def get_classes(classee:str):
"""
将口语类型转换为程序可识别的标准卡密类型
"""
cases = {
'day': 'Day',
'DAY': 'Day',
'': 'Day',
'天卡': 'Day',
'week': 'Week',
'WEEK': 'Week',
'': 'Week',
'周卡': 'Week',
'month': 'Month',
'MONTH': 'Month',
'': 'Month',
'月卡': 'Month',
}
return cases.get(classee, '')
session_id: str = ""
# 登录pmail邮箱 获取cookie
login_url = plugin_config.EMAIL_LOGIN
login_pdata = {
"account": plugin_config.EMAIL_USER,
"password": plugin_config.EMAIL_PASSWORD
}
session = requests.session() # 实例化session对象
def login_pmail():
global session_id
resp_data = None
error_msg: str = ""
retries = 3 # 设置重试次数
for attempt in range(retries):
try:
resp_data = session.post(login_url, json=login_pdata, headers={'Content-Type': 'application/json'})
if resp_data.status_code == 200 and resp_data.json().get('errorNo') == 0:
logger.info('PMail App 启动成功!')
session_id = resp_data.headers['Set-Cookie']
return
except ConnectionError:
error_msg = "服务器连接失败!"
except Exception as e:
error_msg = str(e)
logger.warning(f'PMail App 登录失败,正在重试... ({attempt + 1}/{retries})')
# 如果重试次数用尽仍然失败
logger.error(f'PMail App 登录失败!无法使用邮件功能!可能网络错误!{error_msg}')
async def send_mail(mail_to, subject, content, name):
"""
发送邮件
:param mail_to: 发送到
:param subject: 标题
:param content: 内容
:param name: 用户名
:return:
"""
url = plugin_config.EMAIL_API
pdata = {
'from':
{
"name": "DanDing-Admin",
"email": plugin_config.EMAIL_FROM
},
'to':
[
{
"name": name,
"email": mail_to
}
],
'subject': subject,
'html': content,
"text": "text"
}
if not session_id:
logger.error("[error] 邮件发送失败没有session_id尝试重新登录邮箱服务")
login_pmail()
resp_data = session.post(url, json=pdata, headers={"cookie": f"{session_id}"}).json()
if resp_data is None or resp_data.get("errorNo", -1) != 0:
logger.error("[error] 邮件发送失败,未知的错误,尝试重新登录邮箱服务!")
# 重新登录pmail邮箱
login_pmail()
resp_data = session.post(url, json=pdata, headers={"cookie": f"{session_id}"}).json()
if resp_data is None or resp_data.get("errorNo", -1) != 0:
return {"errorNo": 0, "errorMsg": "", "data": ""}
return resp_data