Created
May 1, 2023 18:05
-
-
Save the-eric-kwok/6619cde86c6ae4b5dd38ae5f5b6e83e8 to your computer and use it in GitHub Desktop.
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
import os | |
import re | |
import json | |
class Store: | |
config_file_path = os.path.join(os.getcwd(), "installer.json") | |
patched_files: list[str] = [] | |
patched_dirs: list[str] = [] | |
@staticmethod | |
def toJson() -> str: | |
return json.dumps( | |
{ | |
"patched_files": Store.patched_files, | |
"patched_dirs": Store.patched_dirs, | |
}, | |
indent=2) | |
@staticmethod | |
def load(): | |
if not os.path.isfile(Store.config_file_path): | |
Store.save() | |
return | |
with open(Store.config_file_path, 'r') as f: | |
_dict = json.load(f) | |
Store.patched_files = _dict[ | |
"patched_files"] if "patched_files" in _dict else [] | |
Store.patched_dirs = _dict[ | |
"patched_dirs"] if "patched_dirs" in _dict else [] | |
@staticmethod | |
def save(): | |
with open(Store.config_file_path, 'w') as f: | |
f.write(Store.toJson()) | |
def cls(): | |
os.system('cls') | |
def return_menu(prompt: str = "按下回车继续..."): | |
print(prompt) | |
input() | |
cls() | |
def prompt_input(prompt: str, *options: list[str]) -> str: | |
print(prompt) | |
for option in options: | |
print(option) | |
print("输入后请按下回车...") | |
user_input = input().lower() | |
return user_input | |
def install(): | |
print("请将补丁包文件夹拖入此窗口,并回车") | |
print("输入Q并回车可以返回主菜单") | |
patch_dir = input() | |
if patch_dir.lower() == 'q': | |
cls() | |
return | |
print() | |
if '"' in patch_dir or "'" in patch_dir: | |
re_patch = re.search(r"['\"]([a-zA-Z]:\\.*)['\"]", patch_dir) | |
patch_dir = re_patch[re_patch.lastindex] | |
patch_files = [ | |
os.path.relpath(os.path.join(root, file), patch_dir) | |
for (root, dirs, files) in os.walk(patch_dir) for file in files | |
] | |
patch_dirs = [ | |
os.path.relpath(os.path.join(root, dir_), patch_dir) | |
for (root, dirs, files) in os.walk(patch_dir) for dir_ in dirs | |
] | |
cwd = os.getcwd() | |
# 检查是否已存在备份文件,若存在则意味着冲突,将停止安装 | |
from functools import reduce | |
neither_exist = reduce( | |
lambda x, y: x and not os.path.isfile(y), | |
[os.path.join(cwd, file) + '.bak' for file in patch_files], True) | |
if not neither_exist: | |
return_menu("该补丁包与已安装的某个补丁包存在冲突,无法安装,请按下回车返回主菜单") | |
return | |
# 预览操作 | |
for file in patch_files: | |
patch = os.path.join(patch_dir, file) | |
target = os.path.join(cwd, file) | |
if os.path.isfile(target): | |
print(f"重命名文件:{file} -> {file}.bak") | |
print(f"复制文件:{patch} -> {file}") | |
for dir_ in patch_dirs: | |
if not os.path.exists(dir_): | |
print(f"创建文件夹:{dir_}") | |
print() | |
user_input = prompt_input("要执行操作吗?", "Y - 确认执行", "N - 放弃执行并返回主菜单") | |
if user_input == 'y': | |
import shutil | |
Store.patched_files += [ | |
os.path.join(cwd, file) for file in patch_files | |
] | |
Store.patched_dirs += [os.path.join(cwd, dir_) for dir_ in patch_dirs] | |
Store.save() | |
# 再次检查补丁文件完整性 | |
all_exist = reduce( | |
lambda x, y: x and os.path.isfile(y), | |
map(lambda x: os.path.join(patch_dir, x), patch_files), True) | |
if not all_exist: | |
return_menu("补丁包中文件发生改变,中止操作,请按下回车返回主菜单") | |
# 执行操作 | |
for file in patch_files: | |
patch = os.path.join(patch_dir, file) | |
target = os.path.join(cwd, file) | |
if os.path.isfile(target): | |
os.rename(target, target + ".bak") | |
if not os.path.exists(os.path.dirname(target)): | |
os.makedirs(os.path.dirname(target)) | |
shutil.copyfile(patch, target) | |
for dir_ in patch_dirs: | |
dir_ = os.path.join(cwd, dir_) | |
if not os.path.exists(dir_): | |
os.makedirs(dir_) | |
return_menu("执行完成,按下回车返回主菜单") | |
elif user_input == 'n': | |
cls() | |
return | |
else: | |
cls() | |
return_menu("输入有误,请按回车返回主菜单") | |
def remove_all(): | |
patched_files = list( | |
filter(lambda x: x.endswith('.bak'), [ | |
os.path.join(root, file) | |
for (root, dirs, files) in os.walk(os.getcwd()) for file in files | |
])) | |
installed_files = list( | |
filter( | |
lambda x: x not in | |
[file.replace(".bak", "") for file in patched_files], | |
Store.patched_files)) | |
patched_dirs = Store.patched_dirs | |
if len(patched_files) == 0 and len(installed_files) == 0: | |
return_menu("当前已经是纯净游戏,按下回车返回主菜单") | |
return | |
# 预览操作 | |
for backup_file in patched_files: | |
patch_file = backup_file.replace(".bak", "") | |
if os.path.isfile(patch_file): | |
print(f"删除文件:{os.path.relpath(patch_file)}") | |
print( | |
f"重命名文件:{os.path.relpath(backup_file)} -> {os.path.relpath(patch_file)}" | |
) | |
for file in installed_files: | |
print(f"删除文件:{os.path.relpath(file)}") | |
for dir_ in patched_dirs: | |
if os.path.exists(dir_): | |
if (len(os.listdir(dir_)) <= 0): | |
print(f"删除空文件夹:{dir_}") | |
print() | |
user_input = prompt_input("要执行操作吗?", "Y - 确认执行", "N - 放弃执行并返回主菜单") | |
if user_input == 'y': | |
# 执行操作 | |
for backup_file in patched_files: | |
patch_file = backup_file.replace(".bak", "") | |
if os.path.isfile(patch_file): | |
os.remove(patch_file) | |
os.rename(backup_file, patch_file) | |
for file in installed_files: | |
if os.path.isfile(file): | |
os.remove(file) | |
for dir_ in patched_dirs: | |
if os.path.exists(dir_): | |
if (len(os.listdir(dir_)) <= 0): | |
os.rmdir(dir_) | |
Store.patched_files.clear() | |
Store.save() | |
return_menu("执行完成,按下回车返回主菜单") | |
elif user_input == 'n': | |
cls() | |
return | |
else: | |
cls() | |
return_menu("输入有误,请按回车返回主菜单") | |
import sys | |
if sys.platform != 'win32': | |
print("该脚本不支持此操作系统") | |
exit(1) | |
if __name__ == "__main__": | |
cls() | |
Store.load() | |
while True: | |
user_input = prompt_input("请选择您要执行的操作:", "I - 安装", "U - 卸载", | |
"R - 恢复纯净游戏", "Q - 退出") | |
if user_input == 'i': | |
cls() | |
install() | |
elif user_input == 'u': | |
cls() | |
return_menu("该功能还在开发中,按回车键返回") | |
elif user_input == 'r': | |
cls() | |
remove_all() | |
elif user_input == 'q': | |
exit(0) | |
else: | |
cls() | |
return_menu("输入有误,请按回车重试") |
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment