-
Notifications
You must be signed in to change notification settings - Fork 9.8k
Closed
Labels
enhancementNew feature or requestNew feature or requestgood first issueGood for newcomersGood for newcomers
Description
新功能请求
有的时候,分享未加密的zip压缩包很可能会被制裁,在这种情况下就诞生了生成加密的zip文件的需求
根据这个需求,可以制作一个含加密功能的zip插件(encryptzip)
可以使用pyzipper实现该插件,这库使用方法和zipfile差不多,支持AES加密
密码可以自动生成,可以保存到文件,或者附着在压缩包注释中
我仿照着你的zip插件,试着写了一个,你看看可不可以。
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),
)
Metadata
Metadata
Assignees
Labels
enhancementNew feature or requestNew feature or requestgood first issueGood for newcomersGood for newcomers