Skip to content

Instantly share code, notes, and snippets.

@the-eric-kwok
Created May 1, 2023 18:05
Show Gist options
  • Save the-eric-kwok/6619cde86c6ae4b5dd38ae5f5b6e83e8 to your computer and use it in GitHub Desktop.
Save the-eric-kwok/6619cde86c6ae4b5dd38ae5f5b6e83e8 to your computer and use it in GitHub Desktop.
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