175 lines
6.6 KiB
Python
175 lines
6.6 KiB
Python
# -*- coding: UTF-8 -*-
|
||
import os,sys
|
||
import random
|
||
import string
|
||
import re
|
||
import time
|
||
import json
|
||
import shutil
|
||
import hashlib
|
||
import time
|
||
import argparse
|
||
#该脚本目前只针对Assets.xcassets目录下的文件进行副本、添加;
|
||
#即:在该脚本执行完毕之后,请将指定的--target 对应目录下的Assets.xcassets拷贝回工程项目替换原有的Assets.xcassets即可
|
||
#该脚本会修改原来的png图片的sha值,以及随机添加一些无效的且无法预览fake图片
|
||
script_path = os.path.split(os.path.realpath(sys.argv[0]))[0]
|
||
|
||
resource_path = ""
|
||
target_path = os.path.join(script_path, "target_resource")
|
||
|
||
#匹配规则,路径包含path_include且不包含path_exclude的才会创建对应类型的文件 os.path.sep:代表路径分隔符,即 /
|
||
match_rule = {
|
||
".png": {
|
||
# "path_include": os.path.sep + "res",
|
||
},
|
||
}
|
||
#确保添加的函数不重名
|
||
funcname_set = set()
|
||
|
||
#单词列表,用以随机名称
|
||
with open(os.path.join(script_path, "./ClassName_list.json"), "r") as fileObj:
|
||
word_name_list = json.load(fileObj)
|
||
|
||
#获取一个随机名称
|
||
def getOneName():
|
||
global word_name_list
|
||
return random.choice(word_name_list)
|
||
|
||
|
||
|
||
#获取png内容
|
||
def getPngText():
|
||
hexbyte = "0000000049454e44aecd6ab2"
|
||
text = str(random.randint(1, 100)) * random.randint(1024, 10240)
|
||
text = text + bytes.fromhex(hexbyte).hex()
|
||
text = text.encode('utf-8')
|
||
return text
|
||
|
||
#添加单个文件
|
||
def addSingleFile(file_path):
|
||
global target_path
|
||
print ("add file " + file_path.replace(target_path, ""))
|
||
_, file_type = os.path.splitext(file_path)
|
||
if file_type == ".png":
|
||
# print("发现png文件,准备在文件末尾追加hex文件操作...")
|
||
with open(file_path, "wb") as fileObj:
|
||
fileObj.write(getPngText())
|
||
fileObj.close()
|
||
|
||
def addFileTo(parent_folder, level, min_file_num=0):
|
||
global match_rule, target_path
|
||
create_folder_list = []
|
||
for parent, folders, files in os.walk(parent_folder):
|
||
target_file_type = ""
|
||
relative_path = parent.replace(target_path, "")
|
||
print("relative_path:"+relative_path)
|
||
for file_type, match_config in match_rule.items():
|
||
# print("file_type:" + file_type)
|
||
print("match_config:" + str(match_config))
|
||
|
||
if "path_exclude" in match_config and relative_path.find(match_config["path_exclude"]) != -1:
|
||
continue
|
||
if "path_include" not in match_config or relative_path.find(match_config["path_include"]) != -1:
|
||
target_file_type = file_type
|
||
# print("target_file_type:"+target_file_type)
|
||
break
|
||
if not target_file_type:
|
||
print("不在执行后续的addSingleFile步骤")
|
||
continue
|
||
|
||
# Create file count 创建 指定的最小文件数量 + 文件列表长度一半 到 文件列表长度 之间 的数量
|
||
new_file_num = random.randint(len(files) // 2, len(files)) + min_file_num
|
||
for i in range(new_file_num):
|
||
#根据随机的文件名 + 文件后缀类型 拼接为要创建的文件路径
|
||
file_path = os.path.join(parent, getOneName() + target_file_type)
|
||
addSingleFile(file_path)
|
||
print("已经执行addSingleFile步骤...")
|
||
# Prevent creating too many levels 如果该目录下已经被自动创建目录,则不再继续自动创建
|
||
if level > 2:
|
||
continue
|
||
|
||
# Create folder count
|
||
new_fold_num = random.randint(len(folders) // 2, len(folders))
|
||
for i in range(new_fold_num):
|
||
target_folder = os.path.join(parent, getOneName())
|
||
# Defer folder creation to avoid interrupting os.walk
|
||
create_folder_list.append(target_folder)
|
||
|
||
for folder_path in create_folder_list:
|
||
try:
|
||
print("create folder", folder_path.replace(target_path, ""))
|
||
os.makedirs(folder_path, exist_ok=True) # Handle existing folders
|
||
addFileTo(folder_path, level + 1, random.randint(2, 5))
|
||
except Exception as e:
|
||
print(e)
|
||
|
||
#----------------------------------------ended add file----------------------
|
||
def changeSingleFileMD5(file_path):
|
||
pre_hash_valaue = calculate_sha256_hash(file_path)
|
||
# print("pre_hash_value:\n" + pre_hash_valaue)
|
||
_, file_type = os.path.splitext(file_path)
|
||
with open(file_path, "ab") as fileObj:
|
||
if file_type == ".png":
|
||
text = "".join(random.sample(string.ascii_letters, 11))
|
||
elif file_type == ".jpg":
|
||
text = "".join(random.sample(string.ascii_letters, 20))
|
||
else:
|
||
text = " "*random.randint(1, 100)
|
||
fileObj.write(text.encode('utf-8'))
|
||
fileObj.close()
|
||
after_hash_valaue = calculate_sha256_hash(file_path)
|
||
# print("after_hash_valaue:\n" + after_hash_valaue)
|
||
|
||
#改变文件md5
|
||
def changeFolderMD5(target_path):
|
||
# type_filter = set([".png", ".jpg", ".json", ".plist", ".fnt"])
|
||
#暂时不处理json、pilist文件
|
||
type_filter = set([".png", ".jpg"])
|
||
for parent, folders, files in os.walk(target_path):
|
||
for file in files:
|
||
full_path = os.path.join(parent, file)
|
||
_, file_type = os.path.splitext(full_path)
|
||
if file_type in type_filter:
|
||
changeSingleFileMD5(full_path)
|
||
|
||
#返回文件的hash值
|
||
def calculate_sha256_hash(file_path):
|
||
with open(file_path, 'rb') as f:
|
||
data = f.read()
|
||
hasher = hashlib.sha256()
|
||
hasher.update(data)
|
||
return hasher.hexdigest()
|
||
#----------------------------------------------------main------------------------------------------------
|
||
|
||
def parse_args():
|
||
global res_path
|
||
parser = argparse.ArgumentParser(description='资源变异工具')
|
||
parser.add_argument('--res', dest='res_dir', type=str, required=True, help='资源目录')
|
||
parser.add_argument('--target', dest='target_dir', type=str, required=False, default=target_path, help='资源导出目录')
|
||
|
||
args = parser.parse_args()
|
||
return args
|
||
|
||
def main():
|
||
global resource_path, target_path
|
||
app_args = parse_args()
|
||
resource_path = app_args.res_dir
|
||
target_path = app_args.target_dir
|
||
|
||
if not os.path.exists(resource_path):
|
||
print ("res path not exists: " + resource_path)
|
||
exit(0)
|
||
if target_path != resource_path:
|
||
if os.path.exists(target_path):
|
||
shutil.rmtree(target_path)
|
||
shutil.copytree(resource_path, target_path)
|
||
#执行png文件的添加、目录的创建
|
||
addFileTo(target_path, 0)
|
||
|
||
print ("\n\nstart modify file md5")
|
||
changeFolderMD5(target_path)
|
||
print ("finish!")
|
||
|
||
if __name__ == "__main__":
|
||
main()
|