import random
import os
import zipfile
import pyzipper
from jmcomic import *
# Plugin: EncryptedZipPlugin (参考了zip插件)
class EncryptedZipPlugin(JmOptionPlugin):
plugin_key = 'encryptzip'
# noinspection PyAttributeOutsideInit
def invoke(self,
downloader,
album: JmAlbumDetail = None,
photo: JmPhotoDetail = None,
delete_original_file=False,
level='photo',
filename_rule='Ptitle',
suffix='zip',
zip_dir='./'
) -> None:
downloader: JmDownloader
self.downloader = downloader
self.level = level
self.delete_original_file = delete_original_file
# 确保压缩文件所在文件夹存在
zip_dir = JmcomicText.parse_to_abspath(zip_dir)
mkdir_if_not_exists(zip_dir)
path_to_delete = []
photo_dict = self.get_downloaded_photo(downloader, album, photo)
if level == 'album':
zip_path = self.get_zip_path(album, None, filename_rule, suffix, zip_dir)
self.zip_album(album, photo_dict, zip_path, path_to_delete)
elif level == 'photo':
for photo, image_list in photo_dict.items():
zip_path = self.get_zip_path(None, photo, filename_rule, suffix, zip_dir)
self.zip_photo(photo, image_list, zip_path, path_to_delete)
else:
ExceptionTool.raises(f'Not Implemented Zip Level: {level}')
self.after_zip(path_to_delete)
def generate_random_str(self,randomlength=32):
"""
自动生成随机字符密码,长度由randomlength指定
"""
random_str = ''
base_str = r'ABCDEFGHIJKLMNOPQRSTUVWXYZabcdefghijklmnopqrstuvwxyz0123456789+/='
length = len(base_str) - 1
for i in range(randomlength):
random_str += base_str[random.randint(0, length)]
return random_str
def get_downloaded_photo(self, downloader, album, photo):
return (
downloader.download_success_dict[album]
if album is not None # after_album
else downloader.download_success_dict[photo.from_album] # after_photo
)
def zip_photo(self, photo, image_list: list, zip_path: str, path_to_delete):
"""
压缩photo文件夹
"""
photo_dir = self.option.decide_image_save_dir(photo) \
if len(image_list) == 0 \
else os.path.dirname(image_list[0][0])
#from common import backup_dir_to_zip
#backup_dir_to_zip(photo_dir, zip_path)
#generate random password
crypt=self.generate_random_str(48)
zip_file=pyzipper.AESZipFile(zip_path, "w",pyzipper.ZIP_DEFLATED)
#attach to the comment of the zip file
zip_file.comment=str.encode(crypt)
zip_file.setpassword(str.encode(crypt))
zip_file.setencryption(pyzipper.WZ_AES, nbits=128)
for file in files_of_dir(photo_dir):
abspath = os.path.join(photo_dir, file)
relpath = os.path.relpath(abspath, photo_dir)
zip_file.write(abspath, relpath)
self.log(f'加密压缩章节[{photo.photo_id}]成功 → {zip_path}', 'finish')
path_to_delete.append(self.unified_path(photo_dir))
@staticmethod
def unified_path(f):
return fix_filepath(f, os.path.isdir(f))
def zip_album(self, album, photo_dict: dict, zip_path, path_to_delete):
"""
压缩album文件夹
"""
album_dir = self.option.dir_rule.decide_album_root_dir(album)
with pyzipper.AESZipFile(zip_path, 'w', pyzipper.ZIP_DEFLATED) as f:
#generate random password
crypt=self.generate_random_str(48)
#attach to the comment of the zip file
f.comment=str.encode(crypt)
f.setpassword(str.encode(crypt))
f.setencryption(pyzipper.WZ_AES, nbits=128)
for photo in photo_dict.keys():
# 定位到章节所在文件夹
photo_dir = self.unified_path(self.option.decide_image_save_dir(photo))
# 章节文件夹标记为删除
path_to_delete.append(photo_dir)
for file in files_of_dir(photo_dir):
abspath = os.path.join(photo_dir, file)
relpath = os.path.relpath(abspath, album_dir)
f.write(abspath, relpath)
self.log(f'加密压缩本子[{album.album_id}]成功 → {zip_path}', 'finish')
def after_zip(self, path_to_delete: List[str]):
# 删除所有原文件
dirs = sorted(path_to_delete, reverse=True)
image_paths = [
path
for photo_dict in self.downloader.download_success_dict.values()
for image_list in photo_dict.values()
for path, image in image_list
]
#print(image_paths)
self.execute_deletion(image_paths)
self.execute_deletion(dirs)
# noinspection PyMethodMayBeStatic
def get_zip_path(self, album, photo, filename_rule, suffix, zip_dir):
"""
计算zip文件的路径
"""
filename = DirRule.apply_rule_directly(album, photo, filename_rule)
from os.path import join
return join(
zip_dir,
filename + fix_suffix(suffix),
)
新功能请求
有的时候,分享未加密的zip压缩包很可能会被制裁,在这种情况下就诞生了生成加密的zip文件的需求
根据这个需求,可以制作一个含加密功能的zip插件(encryptzip)
可以使用pyzipper实现该插件,这库使用方法和zipfile差不多,支持AES加密
密码可以自动生成,可以保存到文件,或者附着在压缩包注释中
我仿照着你的zip插件,试着写了一个,你看看可不可以。