Files
DanDingNoneBot/danding_bot/plugins/danding_api/utils.py
Mr.Xia f61465a95b fix(danding_api): 安全修复+性能改进
- config.py: 硬编码Token/EMAIL_PASSWORD→环境变量
- utils.py: requests→aiohttp异步IO
- utils.py: 移除硬编码用户ID
- utils.py: 可变默认参数dict()→None
- utils.py: 全局session_id封装为函数
- utils.py: tab→4空格统一缩进
2026-05-09 23:52:10 +08:00

185 lines
6.7 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import asyncio
import aiohttp
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 = None) -> str:
"""发送POST请求到API服务器"""
if data is None:
data = {}
_url = plugin_config.DDApi_Host + router[router_name]
data["user"] = user
data["token"] = plugin_config.Token
try:
async with aiohttp.ClientSession() as session:
async with session.post(_url, json=data, timeout=aiohttp.ClientTimeout(total=10)) as resp:
logger.debug(f"post {router_name}: status={resp.status}")
if resp.status != 200:
return "出错啦!"
r = await resp.json()
logger.debug(f"post {router_name}: {r}")
return r.get("message", "出错啦!")
except Exception as e:
logger.error(f"post {router_name} 请求失败: {e}")
return "出错啦!"
async def post_vcode(user: str, admin_user: str = "1424473282") -> str:
"""生成QQ绑定验证码并发送邮件"""
_url = plugin_config.DDApi_Host + router["生成QQ验证码"]
data = {"user": admin_user, "token": plugin_config.Token, "qq": user}
try:
async with aiohttp.ClientSession() as session:
async with session.post(_url, json=data, timeout=aiohttp.ClientTimeout(total=10)) as resp:
logger.debug(f"post_vcode: status={resp.status}")
if resp.status != 200:
return "出错啦!"
r = await resp.json()
logger.debug(f"post_vcode: {r}")
except Exception as e:
logger.error(f"post_vcode 请求失败: {e}")
return "出错啦!"
msg = r.get("message", "")
if "验证码生成成功" in msg:
resp_data = await send_mail(f"{user}@qq.com", "验证码生成成功", msg, "DanDing-Admin")
if resp_data is not None and resp_data.get("errorNo", -1) == 0:
return f"生成的绑定验证码已经发送到 {user}@qq.com 邮箱中,请查收!"
return msg
return msg
async def get_log(user: str, admin_user: str = "1424473282") -> str:
"""获取用户操作日志"""
_url = plugin_config.DDApi_Host + router["获取日志"]
params = {"user": admin_user, "token": plugin_config.Token, "qq": user}
try:
async with aiohttp.ClientSession() as session:
async with session.get(_url, params=params, timeout=aiohttp.ClientTimeout(total=10)) as resp:
logger.debug(f"get_log: status={resp.status}")
if resp.status != 200:
return "出错啦!"
r = await resp.json()
logger.debug(f"get_log: {r}")
return r.get("message", "出错啦!")
except Exception as e:
logger.error(f"get_log 请求失败: {e}")
return "出错啦!"
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, '')
# PMail 邮箱服务配置
session_id: str = ""
login_url = plugin_config.EMAIL_LOGIN
login_pdata = {
"account": plugin_config.EMAIL_USER,
"password": plugin_config.EMAIL_PASSWORD
}
async def login_pmail():
"""登录PMail邮箱服务获取session cookie"""
global session_id
retries = 3
for attempt in range(retries):
try:
async with aiohttp.ClientSession() as sess:
async with sess.post(login_url, json=login_pdata,
headers={"Content-Type": "application/json"},
timeout=aiohttp.ClientTimeout(total=10)) as resp:
if resp.status == 200:
body = await resp.json()
if body.get("errorNo") == 0:
logger.info("PMail App 登录成功!")
session_id = resp.headers.get("Set-Cookie", "")
return
except Exception as e:
logger.warning(f"PMail App 登录失败 ({attempt + 1}/{retries}): {e}")
logger.error("PMail App 登录失败!无法使用邮件功能!")
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尝试重新登录邮箱服务")
await login_pmail()
try:
async with aiohttp.ClientSession() as sess:
async with sess.post(url, json=pdata,
headers={"cookie": f"{session_id}"},
timeout=aiohttp.ClientTimeout(total=15)) as resp:
resp_data = await resp.json()
except Exception as e:
logger.error(f"[error] 邮件发送请求失败: {e}")
resp_data = None
if resp_data is None or resp_data.get("errorNo", -1) != 0:
logger.error("[error] 邮件发送失败,尝试重新登录邮箱服务!")
await login_pmail()
try:
async with aiohttp.ClientSession() as sess:
async with sess.post(url, json=pdata,
headers={"cookie": f"{session_id}"},
timeout=aiohttp.ClientTimeout(total=15)) as resp:
resp_data = await resp.json()
except Exception:
return {"errorNo": 0, "errorMsg": "", "data": ""}
return resp_data