mirror of
https://github.com/ClovertaTheTrilobita/SanYeCao-Nonebot.git
synced 2026-04-01 22:04:51 +00:00
feat(jm_download): 添加二维码下载 优化错误处理
This commit is contained in:
parent
1830d49d88
commit
9297f9cab7
7 changed files with 169 additions and 22 deletions
6
.gitignore
vendored
6
.gitignore
vendored
|
|
@ -28,3 +28,9 @@ src/clover_lightnovel/wenku8.cookie
|
||||||
src/clover_lightnovel/output1.html
|
src/clover_lightnovel/output1.html
|
||||||
*.pyc
|
*.pyc
|
||||||
/src/resources/image/jm/*
|
/src/resources/image/jm/*
|
||||||
|
|
||||||
|
|
||||||
|
Elysia
|
||||||
|
runtime
|
||||||
|
/src/configs/tts
|
||||||
|
bot.pid
|
||||||
|
|
@ -4,7 +4,9 @@ import zipfile
|
||||||
from pathlib import Path
|
from pathlib import Path
|
||||||
from PIL import Image
|
from PIL import Image
|
||||||
from natsort import natsorted
|
from natsort import natsorted
|
||||||
|
from nonebot import logger
|
||||||
|
|
||||||
|
__name__ = "cliver_jm | disguise_pdf"
|
||||||
|
|
||||||
async def webp_to_pdf(input_folder, output_pdf):
|
async def webp_to_pdf(input_folder, output_pdf):
|
||||||
"""
|
"""
|
||||||
|
|
@ -17,7 +19,8 @@ async def webp_to_pdf(input_folder, output_pdf):
|
||||||
)
|
)
|
||||||
|
|
||||||
if not webp_files:
|
if not webp_files:
|
||||||
print("未找到WebP图片")
|
logger.error("未找到WebP图片")
|
||||||
|
return False
|
||||||
|
|
||||||
images = []
|
images = []
|
||||||
for webp_file in webp_files:
|
for webp_file in webp_files:
|
||||||
|
|
@ -31,10 +34,10 @@ async def webp_to_pdf(input_folder, output_pdf):
|
||||||
else:
|
else:
|
||||||
images.append(img.convert('RGB'))
|
images.append(img.convert('RGB'))
|
||||||
except Exception as e:
|
except Exception as e:
|
||||||
print(f"处理失败 {webp_file}: {e}")
|
logger.error(f"处理失败 {webp_file}: {e}")
|
||||||
|
|
||||||
if not images:
|
if not images:
|
||||||
print("无有效图片")
|
logger.error("无有效图片")
|
||||||
|
|
||||||
images[0].save(
|
images[0].save(
|
||||||
output_pdf,
|
output_pdf,
|
||||||
|
|
@ -43,6 +46,7 @@ async def webp_to_pdf(input_folder, output_pdf):
|
||||||
optimize=True,
|
optimize=True,
|
||||||
quality=80
|
quality=80
|
||||||
)
|
)
|
||||||
|
return True
|
||||||
|
|
||||||
async def batch_convert_subfolders(base_dir,output_dir):
|
async def batch_convert_subfolders(base_dir,output_dir):
|
||||||
"""
|
"""
|
||||||
|
|
|
||||||
|
|
@ -1,16 +1,23 @@
|
||||||
import yaml
|
import yaml
|
||||||
|
import uuid
|
||||||
import jmcomic
|
import jmcomic
|
||||||
|
from nonebot import logger
|
||||||
|
from datetime import datetime
|
||||||
|
from src.configs.api_config import qrserver_url,qrserver_size
|
||||||
from src.clover_jm.disguise_pdf import *
|
from src.clover_jm.disguise_pdf import *
|
||||||
from concurrent.futures import ThreadPoolExecutor
|
from concurrent.futures import ThreadPoolExecutor
|
||||||
from src.configs.path_config import jm_path,jm_config_path
|
from src.configs.path_config import jm_path,jm_config_path
|
||||||
|
from src.providers.cloud_file_api import anonfile
|
||||||
from src.clover_image.delete_file import delete_folder,delete_file
|
from src.clover_image.delete_file import delete_folder,delete_file
|
||||||
from src.clover_email.send_email import send_email_by_google,send_email_by_qq
|
from src.clover_email.send_email import send_email_by_google,send_email_by_qq
|
||||||
|
|
||||||
|
__name__ = "clover | jm_comic"
|
||||||
|
|
||||||
# 创建线程池
|
# 创建线程池
|
||||||
jm_executor = ThreadPoolExecutor(max_workers=5)
|
jm_executor = ThreadPoolExecutor(max_workers=5)
|
||||||
jm_executor.submit(lambda: None).result()
|
jm_executor.submit(lambda: None).result()
|
||||||
|
|
||||||
async def download_jm(album_id: str| None,receiver_email: str| None):
|
async def download_jm_Pemail(album_id: str| None,receiver_email: str| None):
|
||||||
# 修改配置文件的下载路径
|
# 修改配置文件的下载路径
|
||||||
source_path = await get_jm_config(receiver_email)
|
source_path = await get_jm_config(receiver_email)
|
||||||
option = jmcomic.JmOption.from_file(jm_config_path)
|
option = jmcomic.JmOption.from_file(jm_config_path)
|
||||||
|
|
@ -40,13 +47,54 @@ async def download_jm(album_id: str| None,receiver_email: str| None):
|
||||||
await delete_file(zip_path)
|
await delete_file(zip_path)
|
||||||
return "发送邮件失败,请重试!"
|
return "发送邮件失败,请重试!"
|
||||||
|
|
||||||
|
async def download_jm_qr(album_id: str| None):
|
||||||
|
# 修改配置文件的下载路径
|
||||||
|
file_name = f"JM-{album_id}-{datetime.now().date()}@{uuid.uuid4().hex}"
|
||||||
|
source_path = await get_jm_config(file_name)
|
||||||
|
option = jmcomic.JmOption.from_file(jm_config_path)
|
||||||
|
# 还原配置文件
|
||||||
|
await recover_jm_config(source_path)
|
||||||
|
#调用JM下载api
|
||||||
|
album_detail,downloader = await asyncio.get_event_loop().run_in_executor(jm_executor,jmcomic.download_album,album_id,option)
|
||||||
|
logger.debug(f"JM下载api调用成功,返回————>{album_detail}")
|
||||||
|
if album_detail.title is None:
|
||||||
|
return {
|
||||||
|
"msg":"下载失败,请检查JM ID 是否正确"
|
||||||
|
}
|
||||||
|
# 创建变量
|
||||||
|
folder_path = f"{jm_path}{album_detail.title}"
|
||||||
|
pdf_path = f"{jm_path}{file_name}.pdf"
|
||||||
|
# 转为pdf
|
||||||
|
pdf_status = await webp_to_pdf(folder_path,pdf_path)
|
||||||
|
if not pdf_status:
|
||||||
|
await delete_folder(folder_path)
|
||||||
|
return {
|
||||||
|
"msg":"PDF转换失败"
|
||||||
|
}
|
||||||
|
# 发送文件
|
||||||
|
send_status = await anonfile.upload_file(pdf_path)
|
||||||
|
if send_status["success"]== "true":
|
||||||
|
file_code=send_status["code"]
|
||||||
|
# 删除文件
|
||||||
|
await delete_folder(pdf_path)
|
||||||
|
await delete_folder(folder_path)
|
||||||
|
return {
|
||||||
|
"msg":"获取成功~!码上下载!~",
|
||||||
|
"qr_code": f"{qrserver_url}?size={qrserver_size}&data={file_code}"
|
||||||
|
}
|
||||||
|
else:
|
||||||
|
await delete_folder(pdf_path)
|
||||||
|
await delete_folder(folder_path)
|
||||||
|
return {
|
||||||
|
"msg":"发送失败,请重试!"
|
||||||
|
}
|
||||||
|
|
||||||
async def get_jm_config(receiver_email: str):
|
async def get_jm_config(file_name: str):
|
||||||
|
|
||||||
with open(jm_config_path, 'r', encoding='utf-8') as f:
|
with open(jm_config_path, 'r', encoding='utf-8') as f:
|
||||||
config = yaml.safe_load(f)
|
config = yaml.safe_load(f)
|
||||||
source_path = config['dir_rule']['base_dir']
|
source_path = config['dir_rule']['base_dir']
|
||||||
new_base_dir = str(Path(source_path) / receiver_email)
|
new_base_dir = str(Path(source_path) / file_name)
|
||||||
config['dir_rule']['base_dir'] = new_base_dir
|
config['dir_rule']['base_dir'] = new_base_dir
|
||||||
with open(jm_config_path, 'w', encoding='utf-8') as f:
|
with open(jm_config_path, 'w', encoding='utf-8') as f:
|
||||||
yaml.dump(config, f, sort_keys=False, allow_unicode=True)
|
yaml.dump(config, f, sort_keys=False, allow_unicode=True)
|
||||||
|
|
|
||||||
|
|
@ -53,3 +53,14 @@ wenku8_password = "<passwd>"
|
||||||
多米HTTP代理api
|
多米HTTP代理api
|
||||||
"""
|
"""
|
||||||
proxy_api = "<KEY>"
|
proxy_api = "<KEY>"
|
||||||
|
|
||||||
|
"""
|
||||||
|
二维码生成 API 参数
|
||||||
|
"""
|
||||||
|
qrserver_url = "https://api.qrserver.com/v1/create-qr-code/"
|
||||||
|
qrserver_size= "200x200"
|
||||||
|
|
||||||
|
"""
|
||||||
|
anonfile API 参数
|
||||||
|
"""
|
||||||
|
anonfile_download_url = "https://anonfile.io/api/download/"
|
||||||
|
|
@ -7,6 +7,6 @@ download:
|
||||||
cache: true # 如果要下载的文件在磁盘上已存在,不用再下一遍了吧?默认为true
|
cache: true # 如果要下载的文件在磁盘上已存在,不用再下一遍了吧?默认为true
|
||||||
image:
|
image:
|
||||||
decode: true # JM的原图是混淆过的,要不要还原?默认为true
|
decode: true # JM的原图是混淆过的,要不要还原?默认为true
|
||||||
suffix: .jpg # 把图片都转为.jpg格式,默认为null,表示不转换。
|
suffix: null # 把图片都转为.jpg格式,默认为null,表示不转换。
|
||||||
threading:
|
threading:
|
||||||
photo: 5
|
photo: 5
|
||||||
|
|
|
||||||
|
|
@ -1,24 +1,54 @@
|
||||||
import re
|
import re
|
||||||
|
from nonebot import logger
|
||||||
from nonebot.rule import to_me
|
from nonebot.rule import to_me
|
||||||
from nonebot.plugin import on_command
|
from nonebot.plugin import on_command
|
||||||
from nonebot.adapters.qq import MessageEvent
|
from nonebot.adapters.qq import MessageEvent, MessageSegment,Message
|
||||||
from src.clover_jm.jm_comic import download_jm
|
from src.clover_jm.jm_comic import download_jm_qr, download_jm_Pemail
|
||||||
|
from nonebot.exception import FinishedException
|
||||||
|
|
||||||
|
__name__ = "JM_Download"
|
||||||
|
|
||||||
jm = on_command("jm", rule=to_me(), priority=10, block=False)
|
jm = on_command("jm", rule=to_me(), priority=10, block=False)
|
||||||
|
|
||||||
|
async def handle_email_download(album_id: str, email: str):
|
||||||
|
"""处理邮箱发送逻辑"""
|
||||||
|
logger.debug(f"开始发送文件到邮箱,ID: {album_id}, 邮箱: {email}")
|
||||||
|
if not validate_email(email):
|
||||||
|
await jm.finish("邮箱格式不正确!")
|
||||||
|
await jm.send("正在发送中,请稍等~")
|
||||||
|
msg = await download_jm_Pemail(album_id=album_id, receiver_email=email)
|
||||||
|
await jm.finish(msg)
|
||||||
|
|
||||||
|
async def handle_qrcode_download(album_id: str):
|
||||||
|
"""处理二维码发送载逻辑"""
|
||||||
|
logger.debug(f"开始二维码逻辑,ID: {album_id}")
|
||||||
|
await jm.send("正在下载中,请稍等~")
|
||||||
|
msgs = await download_jm_qr(album_id=album_id)
|
||||||
|
if "qr_code" not in msgs:
|
||||||
|
await jm.finish(msgs["msg"])
|
||||||
|
msg = Message([
|
||||||
|
MessageSegment.text(msgs["msg"]),
|
||||||
|
MessageSegment.image(msgs["qr_code"])
|
||||||
|
])
|
||||||
|
await jm.finish(msg)
|
||||||
|
|
||||||
@jm.handle()
|
@jm.handle()
|
||||||
async def handle_function(message: MessageEvent):
|
async def handle_function(message: MessageEvent):
|
||||||
|
|
||||||
values = message.get_plaintext().replace("/jm", "").split(" ")
|
values = message.get_plaintext().replace("/jm", "").split(" ")
|
||||||
|
|
||||||
if 3 > len(values) > 4:
|
try:
|
||||||
await jm.finish("请输入正确的格式 /jm+id 或 /jm+id+邮箱号")
|
if len(values) == 2:
|
||||||
|
await handle_qrcode_download(values[1])
|
||||||
|
elif len(values) == 3:
|
||||||
|
await handle_email_download(values[1], values[2])
|
||||||
else:
|
else:
|
||||||
if not validate_email(values[2]):
|
logger.debug("输入格式不正确")
|
||||||
await jm.finish("邮箱格式不正确!")
|
await jm.finish("请输入正确的格式 /jm+id 或 /jm+id+邮箱号")
|
||||||
|
except Exception as e:
|
||||||
await jm.send("正在发送中,请稍等~")
|
if isinstance(e, FinishedException):
|
||||||
msg = await download_jm(album_id = values[1],receiver_email = values[2])
|
return
|
||||||
await jm.finish(msg)
|
logger.error(f"处理请求时发生错误: {e}")
|
||||||
|
await jm.finish("处理请求时发生错误,请稍后重试")
|
||||||
|
|
||||||
def validate_email(email: str) -> bool:
|
def validate_email(email: str) -> bool:
|
||||||
"""验证邮箱格式是否合法"""
|
"""验证邮箱格式是否合法"""
|
||||||
|
|
|
||||||
48
src/providers/cloud_file_api/anonfile.py
Normal file
48
src/providers/cloud_file_api/anonfile.py
Normal file
|
|
@ -0,0 +1,48 @@
|
||||||
|
import requests
|
||||||
|
from nonebot import logger
|
||||||
|
|
||||||
|
__name__ = 'Anonfile Api'
|
||||||
|
|
||||||
|
async def upload_file(file_path):
|
||||||
|
"""
|
||||||
|
### 上传文件到anonfile并返回 \n
|
||||||
|
:param file_path: 上传文件路径
|
||||||
|
:return: {\n
|
||||||
|
"success": true,\n
|
||||||
|
"code": "文件码",\n
|
||||||
|
"message": "File uploaded successfully",\n
|
||||||
|
"isProtected": fales\n
|
||||||
|
}
|
||||||
|
### GET获取文件信息:
|
||||||
|
https://anonfile.io/f/{ 文件码 }
|
||||||
|
|
||||||
|
### GET下载文件:
|
||||||
|
https://anonfile.io/api/download/{ 文件码 }
|
||||||
|
"""
|
||||||
|
try:
|
||||||
|
# 创建Data对象并添加文件
|
||||||
|
files = {'file': open(file_path, 'rb')}
|
||||||
|
|
||||||
|
upload_settings = {
|
||||||
|
'password': '', # 密码
|
||||||
|
'expiryDays': 7, # 过期天数 7、30
|
||||||
|
}
|
||||||
|
|
||||||
|
# 如果设置了密码和过期天数,则添加到Data中
|
||||||
|
data = {}
|
||||||
|
if upload_settings['password']:
|
||||||
|
data['password'] = upload_settings['password']
|
||||||
|
data['expiryDays'] = str(upload_settings['expiryDays'])
|
||||||
|
|
||||||
|
# 发送上传请求
|
||||||
|
response = requests.post('https://anonfile.io/api/upload', files=files, data=data)
|
||||||
|
|
||||||
|
# 检查响应状态码
|
||||||
|
if response.status_code == 200:
|
||||||
|
return response.json()
|
||||||
|
else:
|
||||||
|
logger.error('Upload failed:', response.status_code, response.text)
|
||||||
|
|
||||||
|
except Exception as error:
|
||||||
|
# 捕获并处理上传过程中的错误
|
||||||
|
logger.error('Upload error:', error)
|
||||||
Loading…
Reference in a new issue