feat(jm): 添加JM漫画下载功能及相关模块

新增jm_download插件、jm_comic核心下载逻辑、disguise_pdf文件处理工具
扩展delete_file功能,添加批量删除和文件夹删除方法
更新路径配置和菜单选项
This commit is contained in:
SlyAimer 2025-03-31 17:59:30 +08:00
parent 53a6cb2822
commit 7a58497e5f
8 changed files with 141 additions and 3 deletions

View file

@ -26,6 +26,9 @@ nonebot-plugin-htmlrender
tenacity
paramiko
commonX
jmcomic
natsort
requests
pillow

View file

@ -1,4 +1,6 @@
import os
import asyncio
import shutil
async def delete_file(file_path):
@ -8,3 +10,25 @@ async def delete_file(file_path):
print(f"文件 {file_path} 不存在。")
except Exception as e:
print(f"删除文件时发生错误: {e}")
async def delete_file_batch(file_paths):
"""
批量删除文件的异步函数并行版本
:param file_paths: 需要删除的文件路径列表
"""
tasks = [delete_file(path) for path in file_paths]
results = await asyncio.gather(*tasks, return_exceptions=True)
for path, result in zip(file_paths, results):
if isinstance(result, Exception):
print(f"删除 {path} 失败: {result}")
async def delete_folder(folder_path):
try:
shutil.rmtree(folder_path)
except FileNotFoundError:
print(f"文件夹 {folder_path} 不存在。")
except Exception as e:
print(f"删除文件夹时发生错误: {e}")

View file

@ -0,0 +1,65 @@
import os
import zipfile
from PIL import Image
from natsort import natsorted
async def webp_to_pdf(input_folder, output_pdf):
"""
WebP转PDF
"""
webp_files = natsorted(
[os.path.join(input_folder, f) for f in os.listdir(input_folder)
if f.lower().endswith('.webp')],
key=lambda x: os.path.basename(x)
)
if not webp_files:
print("未找到WebP图片")
# raise ValueError("未找到WebP图片")
images = []
for webp_file in webp_files:
try:
img = Image.open(webp_file)
# 处理透明背景
if img.mode in ('RGBA', 'LA'):
white_bg = Image.new('RGB', img.size, (255, 255, 255))
white_bg.paste(img, mask=img.split()[-1])
images.append(white_bg)
else:
images.append(img.convert('RGB'))
except Exception as e:
print(f"处理失败 {webp_file}: {e}")
if not images:
print("无有效图片")
# raise ValueError("无有效图片")
images[0].save(
output_pdf,
save_all=True,
append_images=images[1:],
optimize=True,
quality=85
)
return output_pdf
async def zip_pdf(pdf_path, zip_path):
try:
with zipfile.ZipFile(zip_path, 'w', zipfile.ZIP_DEFLATED) as zipf:
arcname = os.path.basename(pdf_path)
zipf.write(pdf_path, arcname=arcname)
except Exception as e:
print(f"压缩PDF时出错: {e}")
async def merge_files(jpg_path, zip_path, output_path):
try:
with open(jpg_path, 'rb') as jpg_file, open(zip_path, 'rb') as zip_file, open(output_path,'wb') as output_file:
output_file.write(jpg_file.read())
output_file.write(zip_file.read())
except Exception as e:
print(f"合并文件时出错: {e}")

28
src/clover_jm/jm_comic.py Normal file
View file

@ -0,0 +1,28 @@
import jmcomic
from src.clover_jm.disguise_pdf import *
from src.configs.path_config import jm_path
from src.clover_image.delete_file import delete_file_batch,delete_folder
async def download_jm(album_id: str| None):
album_detail,downloader = jmcomic.download_album(album_id)
original_path = os.getcwd()+f"/{album_detail.title}"
# 将图片转换为PDF
await webp_to_pdf(original_path,jm_path +f"{album_id}.pdf")
pdf_file = jm_path + f"{album_id}.pdf"
jpg_file = jm_path + 'temp.jpg'
zip_file = jm_path + "resume.zip"
output_file = jm_path +"merged.jpg"
if os.path.exists(pdf_file) and os.path.exists(jpg_file):
await zip_pdf(pdf_file, zip_file)
await merge_files(jpg_file, zip_file, output_file)
await delete_file_batch([zip_file, pdf_file])
await delete_folder(original_path)
else:
print("PDF文件或JPG文件不存在请检查文件路径。")
return output_file

View file

@ -31,6 +31,9 @@ os.makedirs(font_path, exist_ok=True)
# 临时数据路径
temp_path = path + '/temp/'
os.makedirs(temp_path, exist_ok=True)
# JM发送 图片模板
jm_path = path + '/image/jm/'
os.makedirs(jm_path, exist_ok=True)
# 日志路径
log_path = path+'/log/'
os.makedirs(log_path, exist_ok=True)

View file

@ -10,11 +10,11 @@ from src.clover_sqlite.models.user import UserList
menu = ["/重启","/今日运势","/今日塔罗","/图","/随机图","/搜番","/日报","/点歌","/摸摸头","/群老婆","/今日老婆", "/开启ai","/关闭ai","/角色列表","/添加人设", "/更新人设", "/删除人设", "/切换人设", "/管理员注册",
"/待办", "/test","/天气","我喜欢你", "", "/待办查询", "/新建待办", "/删除待办" ,"/cf","/B站搜索", "/BV搜索", "/喜报", "/悲报", "/luxun","/鲁迅说",
"/奶龙", "/repo", "/info", "/menu", "/轻小说","/本季新番","/下季新番","/新番观察","/绝对色感"]
"/奶龙", "/repo", "/info", "/menu", "/轻小说","/本季新番","/下季新番","/新番观察","/绝对色感" ,"/jm"]
send_menu = ["/menu","/今日运势","/今日塔罗","/图","/随机图","搜番","/日报","/点歌","/摸摸头","/群老婆","/待办","/天气",
"/待办查询", "/新建待办", "/删除待办" ,"/cf","/B站搜索", "/BV搜索", "/喜报", "/悲报","/鲁迅说",
"/轻小说","/本季新番","/新番观察","/下季新番","/绝对色感"]
"/轻小说","/本季新番","/新番观察","/下季新番","/绝对色感","/jm"]
async def check_value_in_menu(message: MessageEvent) -> bool:
value = message.get_plaintext().strip().split(" ")

View file

@ -0,0 +1,15 @@
from pathlib import Path
from nonebot.rule import to_me
from nonebot.plugin import on_command
from nonebot.adapters.qq import MessageSegment,MessageEvent
from src.clover_jm.jm_comic import download_jm
from src.clover_image.delete_file import delete_file
jm = on_command("jm", rule=to_me(), priority=10,block=False)
@jm.handle()
async def handle_function(message: MessageEvent):
key = message.get_plaintext().replace("/jm", "").strip(" ")
output_file = await download_jm(key)
await jm.send(MessageSegment.file_image(Path(output_file)))
await delete_file(output_file)

Binary file not shown.

After

Width:  |  Height:  |  Size: 2.7 KiB