diff --git a/requirements.txt b/requirements.txt index b358581..ba0c4ee 100644 --- a/requirements.txt +++ b/requirements.txt @@ -26,6 +26,9 @@ nonebot-plugin-htmlrender tenacity paramiko +commonX +jmcomic +natsort requests pillow diff --git a/src/clover_image/delete_file.py b/src/clover_image/delete_file.py index 9260815..b39e5cd 100644 --- a/src/clover_image/delete_file.py +++ b/src/clover_image/delete_file.py @@ -1,4 +1,6 @@ import os +import asyncio +import shutil async def delete_file(file_path): @@ -7,4 +9,26 @@ async def delete_file(file_path): except FileNotFoundError: print(f"文件 {file_path} 不存在。") except Exception as e: - print(f"删除文件时发生错误: {e}") \ No newline at end of file + 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}") \ No newline at end of file diff --git a/src/clover_jm/disguise_pdf.py b/src/clover_jm/disguise_pdf.py new file mode 100644 index 0000000..20d9de6 --- /dev/null +++ b/src/clover_jm/disguise_pdf.py @@ -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}") diff --git a/src/clover_jm/jm_comic.py b/src/clover_jm/jm_comic.py new file mode 100644 index 0000000..3859ce7 --- /dev/null +++ b/src/clover_jm/jm_comic.py @@ -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 + diff --git a/src/configs/path_config.py b/src/configs/path_config.py index 99f0865..4cd5648 100644 --- a/src/configs/path_config.py +++ b/src/configs/path_config.py @@ -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) diff --git a/src/plugins/check.py b/src/plugins/check.py index 179ef33..27e54b1 100644 --- a/src/plugins/check.py +++ b/src/plugins/check.py @@ -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(" ") diff --git a/src/plugins/jm_download.py b/src/plugins/jm_download.py new file mode 100644 index 0000000..2ffa860 --- /dev/null +++ b/src/plugins/jm_download.py @@ -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) diff --git a/src/resources/image/jm/temp.jpg b/src/resources/image/jm/temp.jpg new file mode 100644 index 0000000..6c2cd9b Binary files /dev/null and b/src/resources/image/jm/temp.jpg differ