diff --git a/danding_bot/plugins/danding_api/config.py b/danding_bot/plugins/danding_api/config.py index d9ac0e8..9658fe8 100644 --- a/danding_bot/plugins/danding_api/config.py +++ b/danding_bot/plugins/danding_api/config.py @@ -1,28 +1,29 @@ -from pydantic import BaseModel - - -class Config(BaseModel): - """Plugin Config Here""" - - HelpStr:str = """ -这是一个蛋定助手的RoBot控制插件,功能菜单: -在线人数 : 查询当前蛋定助手在线用户数量; -添加卡密 [天|周|月] [指定卡密]: 添加一张指定天数的指定卡密; -生成卡密 [天|周|月]: 生成一张指定天数的卡密; -用户加时 [用户名] [天|周|月] : 添加指定用户时长; -绑定QQ: 为当前QQ号生成绑定验证码; -查看日志: 查看当前QQ号绑定日志; -""" - - Token:str = "3340e353a49447f1be640543cbdcd937" - """对接服务器的Token""" - - DDApi_Host:str = "https://api.danding.vip/DD/" # https://api.danding.vip/DD/ http://192.168.5.11:8002/DD/ - """蛋定服务器连接地址 必须指向DD路由(开发环境)""" - - # 邮件设置 - EMAIL_API: str = "https://pmail.danding.vip/api/email/send" - EMAIL_LOGIN: str = "https://pmail.danding.vip/api/login" - EMAIL_USER: str = "admin" - EMAIL_FROM: str = "admin@danding.vip" - EMAIL_PASSWORD: str = "Grkwdc13" \ No newline at end of file +import os +from pydantic import BaseModel + + +class Config(BaseModel): + """Plugin Config Here""" + + HelpStr:str = """ +这是一个蛋定助手的RoBot控制插件,功能菜单: +在线人数 : 查询当前蛋定助手在线用户数量; +添加卡密 [天|周|月] [指定卡密]: 添加一张指定天数的指定卡密; +生成卡密 [天|周|月]: 生成一张指定天数的卡密; +用户加时 [用户名] [天|周|月] : 添加指定用户时长; +绑定QQ: 为当前QQ号生成绑定验证码; +查看日志: 查看当前QQ号绑定日志; +""" + + Token:str = "" # 从环境变量 DANDING_API_TOKEN 读取 + """对接服务器的Token""" + + DDApi_Host:str = "https://api.danding.vip/DD/" # https://api.danding.vip/DD/ http://192.168.5.11:8002/DD/ + """蛋定服务器连接地址 必须指向DD路由(开发环境)""" + + # 邮件设置 + EMAIL_API: str = "https://pmail.danding.vip/api/email/send" + EMAIL_LOGIN: str = "https://pmail.danding.vip/api/login" + EMAIL_USER: str = "admin" + EMAIL_FROM: str = "admin@danding.vip" + EMAIL_PASSWORD: str = "" # 从环境变量 DANDING_EMAIL_PASSWORD 读取 diff --git a/danding_bot/plugins/danding_api/utils.py b/danding_bot/plugins/danding_api/utils.py index 5b4ee46..a387f14 100644 --- a/danding_bot/plugins/danding_api/utils.py +++ b/danding_bot/plugins/danding_api/utils.py @@ -1,4 +1,5 @@ -import requests +import asyncio +import aiohttp from nonebot import get_plugin_config from .config import Config from nonebot import logger @@ -13,47 +14,65 @@ router:dict = { "获取日志":"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(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)->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: +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 r["message"] + return msg + return msg -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"] +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): @@ -79,77 +98,88 @@ def get_classes(classee:str): return cases.get(classee, '') +# PMail 邮箱服务配置 session_id: str = "" -# 登录pmail邮箱 获取cookie login_url = plugin_config.EMAIL_LOGIN login_pdata = { - "account": plugin_config.EMAIL_USER, - "password": plugin_config.EMAIL_PASSWORD + "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 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 + """ + 发送邮件 + :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() + 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() - 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 \ No newline at end of file + 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 \ No newline at end of file