├── requirements.txt ├── Tools ├── requirements.txt ├── TTranslation.py ├── TUtilLog.py ├── MasInstaller.py ├── TLogo.py ├── MASToolKit.py └── TUtil.py ├── QA.md ├── .gitignore ├── .vscode └── settings.json ├── test.py ├── .github └── workflows │ └── build.yml ├── extra_file.json ├── MasInstaller.spec ├── tldump.py └── create_data.py /requirements.txt: -------------------------------------------------------------------------------- 1 | Requests==2.31.0 2 | tqdm==4.65.0 3 | -------------------------------------------------------------------------------- /Tools/requirements.txt: -------------------------------------------------------------------------------- 1 | Requests==2.31.0 2 | tqdm==4.65.0 3 | -------------------------------------------------------------------------------- /QA.md: -------------------------------------------------------------------------------- 1 | # 常见问题 2 | 3 | 1. **ValueError: check_hostname requires server_hostname** 4 | 5 | 关掉你的梯子 6 | -------------------------------------------------------------------------------- /.gitignore: -------------------------------------------------------------------------------- 1 | *.log 2 | Tools/game/masrun 3 | __pycache__ 4 | build 5 | build/* 6 | dist 7 | MASToolKit.log 8 | cache 9 | MASToolKit常见问题QA.txt -------------------------------------------------------------------------------- /.vscode/settings.json: -------------------------------------------------------------------------------- 1 | { 2 | "files.exclude": { 3 | "**/*.rpyc": true, 4 | "**/*.rpa": true, 5 | "**/*.rpymc": true, 6 | "**/cache/": true 7 | } 8 | } -------------------------------------------------------------------------------- /test.py: -------------------------------------------------------------------------------- 1 | import os, sys 2 | import requests 3 | 4 | 5 | print(sys.path[0]) 6 | 7 | requests.get("https://github.com/Mon1-innovation/MAS-Simplified-Chinese-Patch/releases/download/0.12.11.4/chs.rpa") -------------------------------------------------------------------------------- /Tools/TTranslation.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #-*- coding: utf-8 -*- 3 | 4 | import TUtilLog 5 | 6 | def get_tl(str): 7 | try: 8 | return TARGET_LANG[str] 9 | except KeyError: 10 | TUtilLog.warning("缺失翻译:{}".format(str)) 11 | return str 12 | en = { 13 | "选择语言/Select Language": "", 14 | "1 - 简体中文 (Default)": "", 15 | "MAS 已经安装": "", 16 | "未安装 MAS": "" 17 | } 18 | 19 | zhCN = {} 20 | 21 | TARGET_LANG = None -------------------------------------------------------------------------------- /.github/workflows/build.yml: -------------------------------------------------------------------------------- 1 | name: Package Application with Pyinstaller 2 | 3 | on: push 4 | 5 | jobs: 6 | pyinstaller-build: 7 | runs-on: windows-latest 8 | steps: 9 | - name: Create Executable 10 | uses: theSanguss/pyinstaller-action@patch-1 11 | with: 12 | python_ver: '3.9' 13 | spec: 'Tools/MasInstaller.py' 14 | requirements: 'requirements.txt' 15 | upload_exe_with_name: 'MasInstaller' 16 | options: --onefile, --name "MasInstaller", -------------------------------------------------------------------------------- /extra_file.json: -------------------------------------------------------------------------------- 1 | {"base_files": [["ddlc.zip", "https://disk.edgemonix.top:28991/api/v3/slave/source/4194304/dXBsb2Fkcy8xL-WbvuW6ii8xX0hKN0pJUlFuX2RkbGMtd2luLnppcA/ddlc-win.zip?sign=BD-hzhfvNvGYSgqP8IOh57dRRTjCS6jyHHF1j0ATWzE%3D%3A0"], ["ddlc.zip", "https://link.jscdn.cn/1drv/aHR0cHM6Ly8xZHJ2Lm1zL3UvcyFBdXhYOTVIVGRJNkxtVXp5aVQ1R3ZnS2VDQkpNP2U9SGRsNUFV.zip"]], "extra_files": [["\u6c49\u5316\u8bf4\u660e.txt", "https://raw.githubusercontent.com/Mon1-innovation/MAS-Simplified-Chinese-Patch/main/%E6%B1%89%E5%8C%96%E8%AF%B4%E6%98%8E.txt", "./", null], ["\u5982\u4f55\u66f4\u65b0.txt", "https://raw.githubusercontent.com/Mon1-innovation/MAS-Simplified-Chinese-Patch/main/%E5%A6%82%E4%BD%95%E6%9B%B4%E6%96%B0.txt", "./", null], ["sp_zhcn.zip", "https://raw.githubusercontent.com/Mon1-innovation/MAS-Simplified-Chinese-Patch/main/%E7%B2%BE%E7%81%B5%E5%8C%85%E6%B1%89%E5%8C%96.zip", "./cache", "EXTRACT_EXTRA"], ["chinese_patch.zip", "http://sp2.0721play.icu/d/MAS/MAS-PC/ChinesePatch.zip", "./cache", "EXTRACT_EXTRA"]]} -------------------------------------------------------------------------------- /MasInstaller.spec: -------------------------------------------------------------------------------- 1 | # -*- mode: python ; coding: utf-8 -*- 2 | 3 | 4 | block_cipher = None 5 | 6 | 7 | a = Analysis( 8 | ['Tools\\MasInstaller.py'], 9 | pathex=[], 10 | binaries=[], 11 | datas=[], 12 | hiddenimports=[], 13 | hookspath=[], 14 | hooksconfig={}, 15 | runtime_hooks=[], 16 | excludes=[], 17 | win_no_prefer_redirects=False, 18 | win_private_assemblies=False, 19 | cipher=block_cipher, 20 | noarchive=False, 21 | ) 22 | pyz = PYZ(a.pure, a.zipped_data, cipher=block_cipher) 23 | 24 | exe = EXE( 25 | pyz, 26 | a.scripts, 27 | a.binaries, 28 | a.zipfiles, 29 | a.datas, 30 | [], 31 | name='MasInstaller', 32 | debug=False, 33 | bootloader_ignore_signals=False, 34 | strip=False, 35 | upx=True, 36 | upx_exclude=[], 37 | runtime_tmpdir=None, 38 | console=True, 39 | disable_windowed_traceback=False, 40 | argv_emulation=False, 41 | target_arch=None, 42 | codesign_identity=None, 43 | entitlements_file=None, 44 | ) 45 | -------------------------------------------------------------------------------- /Tools/TUtilLog.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #-*- coding: utf-8 -*- 3 | 4 | import platform 5 | import logging 6 | import time 7 | import traceback, TLogo 8 | logging.basicConfig(level=logging.NOTSET #设置日志输出格式 9 | ,filename="./MASToolKit.log" #log日志输出的文件位置和文件名 10 | ,filemode="w" #文件的写入格式,w为重新写入文件,默认是追加 11 | ,format="%(asctime)s | %(levelname)s | %(message)s" #日志输出的格式 12 | # -8表示占位符,让输出左对齐,输出长度都为8位 13 | ,datefmt="%Y-%m-%d %H:%M:%S" #时间输出的格式 14 | ,encoding='utf-8' 15 | ) 16 | logging.info( 17 | """OS: {0} - {1} - {2}""".format( 18 | platform.system(), 19 | platform.release(), 20 | platform.version() 21 | ) 22 | ) 23 | logging.info("MASToolKit Version: " + TLogo.VER) 24 | 25 | def debug(str): 26 | logging.debug("{}".format(str), ) 27 | def info(str): 28 | logging.info("{}".format(str)) 29 | def warning(str): 30 | logging.warning("{}".format(str)) 31 | def error(str): 32 | logging.error("{}".format(str)) 33 | def exception(): 34 | #traceback.print_exc() 35 | logging.exception("\n" + traceback.format_exc()) -------------------------------------------------------------------------------- /Tools/MasInstaller.py: -------------------------------------------------------------------------------- 1 | import TUtilLog, TUtil, time 2 | import argparse 3 | import sys 4 | 5 | def main(silent=False): 6 | try: 7 | # 导入MASToolKit时传入silent参数 8 | import MASToolKit 9 | MASToolKit.SILENT_MODE = silent 10 | MASToolKit.main() 11 | if not silent: 12 | print("--按下回车后退出--") 13 | input() 14 | 15 | TUtil.tool_clear() 16 | 17 | except Exception as e: 18 | TUtil.print_info("=========================================") 19 | TUtil.print_info('发生异常,MASTookKit即将退出...') 20 | TUtil.print_info('查看MASToolKit.log获取详细信息...') 21 | TUtil.print_info("=========================================") 22 | TUtil.print_info("异常原因:{}".format(e)) 23 | TUtilLog.exception() 24 | 25 | if not silent: 26 | print("--按下回车后退出--") 27 | input() 28 | 29 | TUtil.tool_clear(True) 30 | 31 | if __name__ == '__main__': 32 | # 添加命令行参数解析 33 | parser = argparse.ArgumentParser(description='MAS Tool Installer') 34 | parser.add_argument('--silent', action='store_true', help='运行时不需要用户输入') 35 | 36 | # 解析参数 37 | args = parser.parse_args() 38 | 39 | # 调用主函数,传入silent标志 40 | main(silent=args.silent) 41 | 42 | #pyinstaller -F .\Tools\MasInstaller.py -------------------------------------------------------------------------------- /tldump.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #-*- coding: utf-8 -*- 3 | 4 | # 输出所有包括中文的行 5 | 6 | import re, os 7 | pattern = r'[\u4e00-\u9fa5]' 8 | pattern2 = re.compile(r'\"(.*?)\"') 9 | INPUT_FILE = "Tools/".replace('\\', '/') 10 | filelist = ['MASToolKit.py']#os.listdir(INPUT_FILE) 11 | 12 | 13 | def find_exist(str, list): 14 | for i in list: 15 | if str == i: 16 | return True 17 | return False 18 | def main(file): 19 | with open(INPUT_FILE + "/" + files, 'r', encoding='utf-8') as file: 20 | news = [] 21 | lines = file.readlines() 22 | for pos, line in enumerate(lines): 23 | if re.search(pattern, line) is not None: 24 | result = pattern2.findall(line) 25 | for i in result: 26 | if re.search(pattern, i) is None: 27 | continue 28 | if find_exist(i, news): 29 | continue 30 | 31 | outbase.writelines('"{}":"{}",\n'.format(i, i)) 32 | news.append(i) 33 | 34 | for files in filelist: 35 | outbase = open('{}'.format(files), 'w', encoding='utf-8') 36 | outbase.writelines('# file: {}\n'.format(INPUT_FILE + "/" + files)) 37 | try: 38 | main(files) 39 | except Exception as e: 40 | print(e) 41 | outbase.close() -------------------------------------------------------------------------------- /create_data.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #-*- coding: utf-8 -*- 3 | 4 | import json 5 | data = {} 6 | # 基础文件 7 | data['base_files'] = [] 8 | data['base_files'].append( 9 | ( 10 | "ddlc.zip", 11 | "https://disk.edgemonix.top:28991/api/v3/slave/source/4194304/dXBsb2Fkcy8xL-WbvuW6ii8xX0hKN0pJUlFuX2RkbGMtd2luLnppcA/ddlc-win.zip?sign=BD-hzhfvNvGYSgqP8IOh57dRRTjCS6jyHHF1j0ATWzE%3D%3A0" 12 | ) 13 | ) 14 | data['base_files'].append( 15 | ( 16 | "ddlc.zip", 17 | "https://link.jscdn.cn/1drv/aHR0cHM6Ly8xZHJ2Lm1zL3UvcyFBdXhYOTVIVGRJNkxtVXp5aVQ1R3ZnS2VDQkpNP2U9SGRsNUFV.zip" 18 | ) 19 | ) 20 | 21 | data['extra_files'] = [] 22 | # 名称, 下载链接, 下载到相对路径, 额外操作 23 | # 额外操作: 24 | # 0. None - 不指定额外操作 25 | # 1. ASK_DOWNLOAD - 下载前进行询问,在旧版中会直接下载 26 | # 2. EXTRACT_EXTRA - 解压,并以扩展内容安装 27 | # 只在安装时下载 28 | data['extra_files'].append( 29 | ( 30 | "汉化说明.txt", 31 | r"https://raw.githubusercontent.com/Mon1-innovation/MAS-Simplified-Chinese-Patch/main/%E6%B1%89%E5%8C%96%E8%AF%B4%E6%98%8E.txt", 32 | "./", 33 | None 34 | ) 35 | ) 36 | data['extra_files'].append( 37 | ( 38 | "如何更新.txt", 39 | r"https://raw.githubusercontent.com/Mon1-innovation/MAS-Simplified-Chinese-Patch/main/%E5%A6%82%E4%BD%95%E6%9B%B4%E6%96%B0.txt", 40 | "./", 41 | None 42 | ) 43 | ) 44 | data['extra_files'].append( 45 | ( 46 | "sp_zhcn.zip", 47 | r"https://raw.githubusercontent.com/Mon1-innovation/MAS-Simplified-Chinese-Patch/main/%E7%B2%BE%E7%81%B5%E5%8C%85%E6%B1%89%E5%8C%96.zip", 48 | "./cache", 49 | "EXTRACT_EXTRA" 50 | ) 51 | ) 52 | 53 | data['extra_files'].append( 54 | ( 55 | "chinese_patch.zip", 56 | r"http://sp2.0721play.icu/d/MAS/MAS-PC/ChinesePatch.zip", 57 | "./cache", 58 | "EXTRACT_EXTRA" 59 | ) 60 | ) 61 | 62 | 63 | with open('extra_file.json', 'w', encoding = 'utf-8') as files: 64 | files.write(json.dumps(data)) 65 | -------------------------------------------------------------------------------- /Tools/TLogo.py: -------------------------------------------------------------------------------- 1 | import TUtil, os 2 | VER = "0.0.14" 3 | MOYU = R""" 4 | 5 | _____ _______ _____ _____ 6 | /\ \ /::\ \ |\ \ /\ \ 7 | /::\____\ /::::\ \ |:\____\ /::\____\ 8 | /::::| | /::::::\ \ |::| | /:::/ / 9 | /:::::| | /::::::::\ \ |::| | /:::/ / 10 | /::::::| | /:::/~~\:::\ \ |::| | /:::/ / 11 | /:::/|::| | /:::/ \:::\ \ |::| | /:::/ / 12 | /:::/ |::| | /:::/ / \:::\ \ |::| | /:::/ / 13 | /:::/ |::|___|______ /:::/____/ \:::\____\ |::|___|______ /:::/ / _____ 14 | /:::/ |::::::::\ \ |:::| | |:::| | /::::::::\ \ /:::/____/ /\ \ 15 | /:::/ |:::::::::\____\|:::|____| |:::| | /::::::::::\____\|:::| / /::\____\ 16 | \::/ / ~~~~~/:::/ / \:::\ \ /:::/ / /:::/~~~~/~~ |:::|____\ /:::/ / 17 | \/____/ /:::/ / \:::\ \ /:::/ / /:::/ / \:::\ \ /:::/ / 18 | /:::/ / \:::\ /:::/ / /:::/ / \:::\ \ /:::/ / 19 | /:::/ / \:::\__/:::/ / /:::/ / \:::\ /:::/ / 20 | /:::/ / \::::::::/ / \::/ / \:::\__/:::/ / 21 | /:::/ / \::::::/ / \/____/ \::::::::/ / 22 | /:::/ / \::::/ / \::::::/ / 23 | /:::/ / \::/____/ \::::/ / 24 | \::/ / ~~ \::/____/ 25 | \/____/ ~~ 26 | 27 | 28 | ---------------------------------------------------------------------------------------- 29 | 欢迎使用 MASToolKit by Sir.P v{} 30 | 当提示选项时,输入对应的选项,然后按下回车键确定选项。 31 | 如果程序卡住,可以尝试点一下回车来继续。(通常这种情况发生时,标题栏会出现“选择”二字) 32 | 本程序一般不需要加速器,开启加速器可能会导致异常 33 | ---------------------------------------------------------------------------------------- 34 | Monika After Story本次安装的目标位置由本可执行文件所在的位置决定。 35 | 目标位置:{} 36 | """.format(VER, os.path.abspath('.')) 37 | 38 | QA = """ 39 | 1. 异常 "ValueError: check_hostname requires server_hostname" 40 | 41 | A: 关闭梯子 42 | 43 | 44 | 2. 异常中出现关键词 "[SSL: CERTIFICATE_VERIFY_FAILED]" "requests.exceptions.SSLError" 45 | 完整:requests.exceptions.SSLError: HTTPSConnectionPool(host='api.github.com', port=443): Max retries exceeded with url: /repos/Mon1-innovation/MASToolScript/releases/latest (Caused by SSLError(SSLCertVerificationError(1, '[SSL: CERTIFICATE_VERIFY_FAILED] certificate verify failed: unable to get local issuer certificate (_ssl.c:1129)'))) 46 | 47 | A: 关闭Steam++ / Watt Toolkit / 梯子 48 | 49 | 50 | 3. 出现意义不明的异常 51 | 52 | A: 发送MASToolKit.log到Discord/QQ/Github issue等地寻求帮助 53 | Github issue:https://github.com/Mon1-innovation/MASToolScript/issues 54 | 55 | """ 56 | 57 | def moyu(): 58 | print(MOYU) 59 | out_files() 60 | a = self_checkupdate() 61 | try: 62 | if a: 63 | print("MASToolKit有更新 -> {}".format(VER)) 64 | print("====================================") 65 | print(TUtil.get_latest_release_info("Mon1-innovation", "MASToolScript")) 66 | print("你可以在 https://github.com/Mon1-innovation/MASToolScript/releases/latest 更新 MASToolKit") 67 | except: 68 | pass 69 | 70 | 71 | def self_checkupdate(): 72 | try: 73 | return TUtil.check_update(VER.split('.'), "Mon1-innovation", "MASToolScript") 74 | except: 75 | pass 76 | 77 | 78 | def out_files(): 79 | a = open("MASToolKit常见问题QA.txt", 'w', encoding='utf-8') 80 | a.write(QA) 81 | -------------------------------------------------------------------------------- /Tools/MASToolKit.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | #-*- coding: utf-8 -*- 3 | 4 | from pickle import TRUE 5 | import sys, time 6 | from tkinter import N 7 | import traceback, requests, tqdm 8 | import TUtil 9 | import TUtilLog 10 | from TUtilLog import info, debug, warning, error 11 | import TTranslation 12 | import TLogo 13 | DOWNLOAD_DDLC_URL = None 14 | PATH = '.'#sys.path[0] 15 | CACHE_PATH = PATH + "/cache" 16 | GAME_PATH = PATH + "/game" 17 | MAS_OWN = "Mon1-innovation"#"Monika-After-Story" 18 | MAS_REP = "MonikaModDev-zhCN" 19 | 20 | MON1_REP = "MAS-Simplified-Chinese-Patch" 21 | MON1_OWN = "Mon1-innovation" 22 | 23 | debug('文件路径: {}'.format(PATH)) 24 | TLogo.moyu() 25 | def print_info(str): 26 | print(str) 27 | TUtilLog.info(str) 28 | 29 | TUtil.mkdir('./CACHE') 30 | 31 | mas_installed = False#TUtil.is_exists(PATH + "/game/masrun") 32 | FileData = None 33 | #print("选择语言/Select Language") 34 | #print("") 35 | #print("1 - 简体中文 (Default)") 36 | #print("2 - English") 37 | # 38 | import requests 39 | 40 | def check_link_access(link): 41 | try: 42 | response = requests.head(link) 43 | if response.status_code in [200, 301, 302]: 44 | return True 45 | else: 46 | return False 47 | except Exception as e: 48 | error(traceback.format_exc()) 49 | return False 50 | def get_base_file(): 51 | global DOWNLOAD_DDLC_URL 52 | global FileData 53 | # 获取基础文件信息 54 | print_info("获取基础文件信息") 55 | try: 56 | FileData = requests.get("http://releases.0721play.top/" if TUtil.ENABLE_SPEED else "" + 'https://raw.githubusercontent.com/Mon1-innovation/MAS-Simplified-Chinese-Patch/main/extra_file.json', verify=False) 57 | except Exception as e: 58 | error(traceback.format_exc()) 59 | FileData = requests.get('http://sp2.0721play.icu/d/MAS/MAS-PC/extra_file.json', verify=False) 60 | FileData = FileData.json() 61 | for file in tqdm.tqdm(FileData["base_files"], desc="基础文件"): 62 | if DOWNLOAD_DDLC_URL != None: 63 | continue 64 | if file[0] == "ddlc.zip": 65 | if (check_link_access(file[1])): 66 | DOWNLOAD_DDLC_URL = file[1] 67 | print_info("设置DDLC链接为:{}".format(file[1])) 68 | continue 69 | else: 70 | print_info("访问失败, 正在尝试更换备用链接") 71 | if DOWNLOAD_DDLC_URL == None: 72 | raise Exception("所有DDLC链接全部尝试失败, 无法进行安装!") 73 | # 添加全局silent模式标志 74 | SILENT_MODE = False 75 | 76 | print_info("是否启用github release加速") 77 | print_info("cloudflare workers加速被墙了, 所以应该是用不了的.") 78 | print_info("Y/N(默认)") 79 | 80 | ## 根据silent模式设置默认值 81 | #if not SILENT_MODE: 82 | # a = input() 83 | # if a.lower() == 'y': 84 | # TUtil.ENABLE_SPEED = True 85 | # else: 86 | # TUtil.ENABLE_SPEED = False 87 | #else: 88 | # # 静默模式下默认不启用加速 89 | # TUtil.ENABLE_SPEED = False 90 | # 91 | #if TUtil.ENABLE_SPEED: 92 | # print_info("启用基于Cloudflare Workers的github开源项目hunshcn/gh-proxy进行加速") 93 | 94 | def tool_box(): 95 | def cn_update(): 96 | print_info('准备下载汉化补丁') 97 | print_info("汉化补丁当前版本:{}".format(TUtil.get_latest_release_tag(MON1_OWN, MON1_REP))) 98 | print_info('==========================================') 99 | print_info('更新说明:\n\n' + TUtil.get_latest_release_info(MON1_OWN, MON1_REP)) 100 | print_info('==========================================') 101 | time.sleep(2) 102 | url = TUtil.get_latest_release_dl(MON1_OWN, MON1_REP) 103 | 104 | debug(url) 105 | for name, dl in url: 106 | if name == "chs.rpa": 107 | print_info('准备下载chs.rpa...') 108 | try: 109 | if TUtil.ENABLE_SPEED: 110 | dl = "http://releases.0721play.top/"+dl 111 | TUtil.download(dl, GAME_PATH, 'chs.rpa') 112 | except Exception as e: 113 | error("下载失败:\n{}".format(traceback.format_exc())) 114 | print("下载失败,准备重试...") 115 | print("从github下载可能需要加速器...") 116 | try: 117 | if TUtil.ENABLE_SPEED: 118 | dl = "http://releases.0721play.top/"+dl 119 | TUtil.download(dl, GAME_PATH, 'chs.rpa') 120 | except Exception as e: 121 | print("下载失败,查看MASToolKit.log获取更多信息") 122 | raise e 123 | if name == 'chs_gui.rpa': 124 | print_info('准备下载chs_gui.rpa...') 125 | try: 126 | if TUtil.ENABLE_SPEED: 127 | dl = "http://releases.0721play.top/"+dl 128 | TUtil.download(dl, GAME_PATH, 'chs_gui.rpa') 129 | except Exception as e: 130 | error("下载失败:\n{}".format(traceback.format_exc())) 131 | print("下载失败,准备重试...") 132 | print("从github下载可能需要加速器...") 133 | try: 134 | if TUtil.ENABLE_SPEED: 135 | dl = "http://releases.0721play.top/"+dl 136 | TUtil.download(dl, GAME_PATH, 'chs_gui.rpa') 137 | except Exception as e: 138 | print("下载失败,查看MASToolKit.log获取更多信息") 139 | raise 140 | print("===============================") 141 | if not SILENT_MODE: 142 | print_info("请选择功能") 143 | print_info("1. 重装最新版汉化") 144 | print_info("2. 安装扩展内容(未实现)") 145 | print_info("3. 退出(默认)") 146 | a = input() 147 | if a == '1': 148 | cn_update() 149 | elif a == '2': 150 | pass 151 | else: 152 | pass 153 | else: 154 | # 静默模式下自动执行重装最新版汉化 155 | print_info("静默模式:自动重装最新版汉化") 156 | cn_update() 157 | 158 | 159 | def main(): 160 | language = None#input() 161 | if language != '2': 162 | TTranslation.TARGET_LANG = TTranslation.zhCN 163 | else: 164 | TTranslation.TARGET_LANG = TTranslation.en 165 | _ = TTranslation.get_tl 166 | 167 | if mas_installed: 168 | info(_("MAS 已经安装")) 169 | print(_("MAS 已经安装")) 170 | #print("删除masrun文件即可让本程序覆盖重装") 171 | tool_box() 172 | else: 173 | try: 174 | TUtil.get_github_rate_limit() 175 | except: 176 | pass 177 | info(_("未安装 MAS")) 178 | print(_("未安装 MAS")) 179 | print(_("准备安装MAS...")) 180 | print("获取DDLC下载链接...") 181 | get_base_file() 182 | info("开始下载DDLC: {}".format(CACHE_PATH)) 183 | TUtil.download(DOWNLOAD_DDLC_URL, CACHE_PATH, 'ddlc.zip') 184 | print('开始下载MAS最新版本') 185 | info("开始下载MAS最新版本") 186 | masver1 = TUtil.get_latest_release_tag(MAS_OWN, MAS_REP) 187 | print_info("MAS最新版本为:" + masver1) 188 | print_info('==========================================') 189 | print_info('Monika After Story '+ masver1 +' 更新内容:\n\n') 190 | print_info('\n'+TUtil.get_latest_release_info(MAS_OWN, MAS_REP)) 191 | print_info('\n\n') 192 | print_info('==========================================') 193 | print_info('更新内容已经保存至log文件中') 194 | print_info('获取下载链接...') 195 | url = TUtil.get_latest_release_dl(MAS_OWN, MAS_REP) 196 | debug(url) 197 | for name, dl in url: 198 | if TUtil.ENABLE_SPEED: 199 | dl = "http://releases.0721play.top/"+dl 200 | 201 | if name == "Monika_After_Story-{}-Mod.zip".format(masver1[1:]): 202 | print_info('准备下载MAS...') 203 | try: 204 | TUtil.download(dl, CACHE_PATH, 'mas.zip') 205 | except Exception as e: 206 | error("下载失败:\n{}".format(traceback.format_exc())) 207 | print("下载失败,准备重试...") 208 | print("从github下载可能需要加速器...") 209 | try: 210 | TUtil.download(dl, CACHE_PATH, 'mas.zip') 211 | except Exception as e: 212 | print("下载失败,查看MASToolKit.log获取更多信息") 213 | error("下载失败:\n{}".format(traceback.format_exc())) 214 | raise 215 | if name == 'spritepacks.zip': 216 | if not SILENT_MODE: 217 | print('是否下载官方精灵包?(未汉化)') 218 | print('不下载则需要手动安装精灵包') 219 | print("Y(默认)/N") 220 | spdl = input() 221 | if spdl.lower() == 'n': 222 | print_info('跳过精灵包下载') 223 | spdl = False 224 | continue 225 | else: 226 | # 静默模式下默认不下载精灵包 227 | print_info('静默模式:精灵包下载') 228 | spdl = True 229 | continue 230 | try: 231 | if spdl: 232 | print_info('准备下载精灵包') 233 | 234 | TUtil.download(dl, CACHE_PATH, 'spritepacks.zip') 235 | except Exception as e: 236 | error("下载失败:\n{}".format(traceback.format_exc())) 237 | print("下载失败,准备重试...") 238 | print("从github下载可能需要加速器...") 239 | try: 240 | TUtil.download(dl, CACHE_PATH, 'spritepacks.zip') 241 | except Exception as e: 242 | print("下载失败,查看MASToolKit.log获取更多信息") 243 | error("下载失败:\n{}".format(traceback.format_exc())) 244 | TUtilLog.warning("{}".format(traceback.format_exc())) 245 | print_info('跳过精灵包下载') 246 | break 247 | #print_info('准备下载汉化补丁') 248 | print_info("汉化补丁当前版本:{}".format(TUtil.get_latest_release_tag(MON1_OWN, MON1_REP))) 249 | print_info('==========================================') 250 | print_info('更新说明:\n\n' + TUtil.get_latest_release_info(MON1_OWN, MON1_REP)) 251 | print_info('==========================================') 252 | time.sleep(2) 253 | url = TUtil.get_latest_release_dl(MON1_OWN, MON1_REP) 254 | debug(url) 255 | for name, dl in url: 256 | if TUtil.ENABLE_SPEED: 257 | dl = "http://releases.0721play.top/"+dl 258 | 259 | if name == "chs.rpa": 260 | print_info('准备下载chs.rpa...') 261 | 262 | try: 263 | TUtil.download(dl, CACHE_PATH, 'chs.rpa') 264 | except Exception as e: 265 | error("下载失败:\n{}".format(traceback.format_exc())) 266 | print("下载失败,准备重试...") 267 | print("从github下载可能需要加速器...") 268 | try: 269 | TUtil.download(dl, CACHE_PATH, 'chs.rpa') 270 | except Exception as e: 271 | TUtilLog.error("{}".format(traceback.format_exc(e))) 272 | print("下载失败,查看MASToolKit.log获取更多信息") 273 | raise e 274 | if name == 'chs_gui.rpa': 275 | 276 | print_info('准备下载chs_gui.rpa...') 277 | try: 278 | TUtil.download(dl, CACHE_PATH, 'chs_gui.rpa') 279 | except Exception as e: 280 | error("下载失败:\n{}".format(traceback.format_exc())) 281 | print("下载失败,准备重试...") 282 | print("从github下载可能需要加速器...") 283 | try: 284 | TUtil.download(dl, CACHE_PATH, 'chs_gui.rpa') 285 | except Exception as e: 286 | TUtilLog.warning("{}".format(traceback.format_exc(e))) 287 | print("下载失败,查看MASToolKit.log获取更多信息") 288 | raise 289 | 290 | print_info('开始解压文件') 291 | print_info('解压ddlc') 292 | if TUtil.is_exists(CACHE_PATH + '/ddlc.zip'): 293 | TUtil.un_zip(CACHE_PATH + '/ddlc.zip') 294 | print_info('解压MAS') 295 | if TUtil.is_exists(CACHE_PATH + '/mas.zip'): 296 | TUtil.un_zip(CACHE_PATH + '/mas.zip') 297 | 298 | 299 | print_info('安装MAS...') 300 | #TUtil.copy_dir(CACHE_PATH + '/mas.zip_files', CACHE_PATH + '/ddlc.zip_files/DDLC-1.1.1-pc') 301 | TUtil.dir_check(CACHE_PATH + '/mas.zip', CACHE_PATH + '/ddlc.zip_files/DDLC-1.1.1-pc') 302 | #print_info('安装MAS汉化补丁...') 303 | if TUtil.is_exists(CACHE_PATH + '/chs.rpa'): 304 | print_info('安装汉化补丁...') 305 | TUtil.copy(CACHE_PATH + '/chs.rpa', CACHE_PATH + '/ddlc.zip_files/DDLC-1.1.1-pc/game') 306 | if TUtil.is_exists(CACHE_PATH + '/chs_gui.rpa'): 307 | print_info('安装字体...') 308 | TUtil.copy(CACHE_PATH + '/chs_gui.rpa', CACHE_PATH + '/ddlc.zip_files/DDLC-1.1.1-pc/game') 309 | if TUtil.is_exists(CACHE_PATH + '/spritepacks.zip'): 310 | TUtil.un_zip(CACHE_PATH + '/spritepacks.zip') 311 | print_info('安装精灵包...') 312 | TUtil.dir_check(CACHE_PATH + '/spritepacks.zip', CACHE_PATH + '/ddlc.zip_files/DDLC-1.1.1-pc') 313 | try: 314 | TUtil.get_extra_file(FileData) 315 | except Exception as e: 316 | print_info("安装额外内容失败, 跳过") 317 | TUtilLog.warning("{}".format(traceback.format_exc(e))) 318 | print_info('移出缓存文件夹...') 319 | TUtil.copy_dir(CACHE_PATH + '/ddlc.zip_files/DDLC-1.1.1-pc', PATH) 320 | print_info('MAS安装完成~') 321 | print_info('ENJOY 你的莫妮卡~') 322 | print("======================================") -------------------------------------------------------------------------------- /Tools/TUtil.py: -------------------------------------------------------------------------------- 1 | #!/usr/bin/env python 2 | # -*- coding: utf-8 -*- 3 | 4 | 5 | import os 6 | import shutil 7 | import TUtilLog 8 | import requests 9 | import urllib3 10 | urllib3.disable_warnings(urllib3.exceptions.InsecureRequestWarning) 11 | import time 12 | import traceback 13 | import zipfile 14 | from tqdm import tqdm 15 | import threading 16 | 17 | 18 | 19 | _install_completed = None 20 | ENABLE_SPEED = False 21 | 22 | def set_proxy(port): 23 | os.environ["http_proxy"] = "http://127.0.0.1:{}".format(port) 24 | os.environ["https_proxy"] = "https://127.0.0.1:{}".format(port) 25 | print_info("代理地址设置为: '{}'".format("127.0.0.1:{}".format(port))) 26 | def un_zip(file_name): 27 | """ 28 | 解压文件 29 | """ 30 | import zipfile 31 | TUtilLog.info("解压文件:'{}'".format(file_name)) 32 | try: 33 | zip_file = zipfile.ZipFile(file_name) 34 | except Exception as e: 35 | TUtilLog.error("解压文件失败:'{}'".format(e)) 36 | return False 37 | try: 38 | if os.path.isdir(file_name + "_files"): 39 | pass 40 | else: 41 | os.mkdir(file_name + "_files") 42 | for names in tqdm(zip_file.namelist(), "解压文件"): 43 | zip_file.extract(names, file_name + "_files/") 44 | zip_file.close() 45 | return True 46 | except Exception as e: 47 | TUtilLog.error("解压文件失败:'{}'".format(e)) 48 | zip_file.close() 49 | return False 50 | 51 | 52 | def get_github_rate_limit(): 53 | a = requests.get('https://api.github.com/rate_limit', verify=False) 54 | a = a.json() 55 | try: 56 | if a['resources']['core']['limit'] - a['resources']['core']['used'] < 1: 57 | print("您已经到达Github请求上限,请等待一段时间后重试。") 58 | TUtilLog.warning('您已经到达Github请求上限,请等待一段时间后重试。') 59 | return False 60 | elif a['resources']['core']['limit'] - a['resources']['core']['used'] < 5: 61 | print("!!您即将到达Github请求上限,本次安装可能会失败。!!") 62 | TUtilLog.warning('您即将到达Github请求上限,本次安装可能会失败。') 63 | 64 | return False 65 | except KeyError as e: 66 | TUtilLog.error("{}".format(traceback.format_exc(e))) 67 | 68 | 69 | def get_latest_release_tag(own, rep): 70 | """ 71 | 获取仓库最新release的tag 72 | IN: 73 | own - 拥有者 74 | rep - 存储库名称 75 | filename - 下载的文件名称 76 | Return: 77 | tag 类似于"v0.12.1" 78 | """ 79 | url = requests.get( 80 | "https://api.github.com/repos/{}/{}/releases".format(own, rep), verify=False) 81 | url = url.json() 82 | try: 83 | return url[0]['tag_name'] 84 | except Exception as e: 85 | print('遇到致命错误,请查看log获取详细信息') 86 | TUtilLog.error(e) 87 | return('版本号获取失败') 88 | 89 | def check_update(oldver, own, rep): 90 | """ 91 | 从github检查是否有更新 92 | 93 | IN: 94 | oldver - 当前版本号['0', '12', '11'] 95 | own - 拥有者 96 | rep - 存储库 97 | 98 | RETURNS: 99 | False - 无更新 100 | 新版本号 - 返回版本号 v0.12.11.3 101 | """ 102 | def comp_version(old, new): 103 | length = len(old) 104 | if length > len(new): 105 | length = len(new) 106 | for i in range(length): 107 | if old[i] < new[i]: 108 | return True 109 | 110 | url = requests.get( 111 | "https://api.github.com/repos/{}/{}/releases".format(own, rep), verify=False) 112 | try: 113 | ver = url.json()[0]['tag_name'] 114 | versp = ver[1:].split('.') 115 | if comp_version(oldver, versp): 116 | return ver 117 | return False 118 | except Exception as e: 119 | TUtilLog.error("检查更新时发生异常: {}".format(e)) 120 | return False 121 | 122 | def get_latest_release_info(own, rep): 123 | """ 124 | 获取仓库最新release的更新信息 125 | IN: 126 | own - 拥有者 127 | rep - 存储库名称 128 | filename - 下载的文件名称 129 | Return: 130 | md 源文件 131 | """ 132 | url = requests.get( 133 | "https://api.github.com/repos/{}/{}/releases".format(own, rep), verify=False) 134 | url = url.json() 135 | try: 136 | return url[0]['body'] 137 | except Exception as e: 138 | TUtilLog.error(e) 139 | return "更新信息获取失败" 140 | 141 | 142 | def get_latest_release_dl(own, rep): 143 | """ 144 | 获取仓库的最新release 145 | 146 | IN: 147 | own - 拥有者 148 | rep - 存储库名称 149 | filename - 下载的文件名称 150 | Return: 151 | (文件名, 下载链接) 152 | """ 153 | url = requests.get( 154 | "https://api.github.com/repos/{}/{}/releases".format(own, rep), verify=False) 155 | url = url.json() 156 | assets = url[0]['assets'] 157 | result = [] 158 | for items in assets: 159 | result.append((items['name'], items['browser_download_url'])) 160 | return result 161 | 162 | 163 | def is_exists(path): 164 | try: 165 | return os.path.exists(path) 166 | except Exception as e: 167 | TUtilLog.error("{}".format(traceback.format_exc(e))) 168 | return False 169 | 170 | 171 | def mkdir(str): 172 | os.makedirs(str, exist_ok=True) 173 | 174 | # https://blog.csdn.net/weixin_43347550/article/details/105248223 175 | 176 | import os 177 | import requests 178 | import traceback 179 | from tqdm import tqdm 180 | from concurrent.futures import ThreadPoolExecutor, as_completed 181 | 182 | def single_thread_download(final_url, file_path, name, chunk_size=1024*1024): 183 | print("开始单线程普通下载...") 184 | with requests.get(final_url, stream=True, verify=False, allow_redirects=True) as response: 185 | if 'Content-Length' in response.headers: 186 | data_size = int(response.headers['Content-Length']) / 1024 / 1024 187 | else: 188 | data_size = None 189 | with open(file_path, 'wb') as f: 190 | for data in tqdm( 191 | iterable=response.iter_content(chunk_size), 192 | total=int(data_size + 1) if data_size else None, 193 | desc=name, 194 | unit='MB' 195 | ): 196 | f.write(data) 197 | print(f"单线程下载完成,文件已保存至: {file_path}") 198 | 199 | def download(url, path, name, chunk_size=1024*1024, thread_count=8): 200 | if ENABLE_SPEED: 201 | if ("github.com" in url or "raw.githubusercontent.com" in url) and "0721play.top" not in url: 202 | url = "http://releases.0721play.top/" + url 203 | TUtilLog.debug("请求下载链接: '{}'".format(url)) 204 | 205 | if not os.path.exists(path): 206 | os.makedirs(path) 207 | 208 | file_path = os.path.join(path, name) 209 | failtime = 5 210 | 211 | while True: 212 | try: 213 | head_resp = requests.head(url, verify=False, allow_redirects=True) 214 | file_size = int(head_resp.headers.get('Content-Length', 0)) 215 | accept_ranges = head_resp.headers.get('Accept-Ranges', '').lower() 216 | final_url = head_resp.url 217 | TUtilLog.debug(f"HEAD 响应头: {head_resp.headers}") 218 | TUtilLog.debug(f"最终跳转后的下载链接: {final_url}") 219 | 220 | if accept_ranges == 'bytes' and file_size > 0: 221 | print(f"服务器支持断点续传,尝试多线程下载({thread_count}线程)") 222 | 223 | def download_chunk(start, end, idx): 224 | headers = {'Range': f'bytes={start}-{end}'} 225 | part_file = f"{file_path}.part{idx}" 226 | with requests.get(final_url, headers=headers, stream=True, verify=False, timeout=30) as r: 227 | if r.status_code != 206: 228 | raise Exception(f"服务器未正确返回分段内容,状态码: {r.status_code}") 229 | if 'Content-Range' not in r.headers: 230 | raise Exception("服务器未返回 Content-Range,可能不支持分段下载") 231 | with open(part_file, 'wb') as f: 232 | for chunk in r.iter_content(chunk_size=chunk_size): 233 | if chunk: 234 | f.write(chunk) 235 | 236 | try: 237 | # 大小<1MB 直接单线程下载 238 | if file_size < chunk_size: 239 | print("文件小于最小分块大小,使用单线程下载...") 240 | single_thread_download(final_url, file_path, name, chunk_size) 241 | return 242 | part_size = file_size // thread_count 243 | ranges = [ 244 | (i * part_size, (i + 1) * part_size - 1 if i < thread_count - 1 else file_size - 1, i) 245 | for i in range(thread_count) 246 | ] 247 | 248 | with ThreadPoolExecutor(max_workers=thread_count) as executor: 249 | futures = {executor.submit(download_chunk, start, end, idx): idx for start, end, idx in ranges} 250 | 251 | pbar = tqdm(total=file_size, unit='B', unit_scale=True, desc=name) 252 | try: 253 | while True: 254 | downloaded = sum( 255 | os.path.getsize(f"{file_path}.part{i}") if os.path.exists(f"{file_path}.part{i}") else 0 256 | for i in range(thread_count) 257 | ) 258 | pbar.n = downloaded 259 | pbar.refresh() 260 | if all(f.done() for f in futures): 261 | break 262 | finally: 263 | pbar.close() 264 | 265 | for future in futures: 266 | if future.exception(): 267 | raise future.exception() 268 | 269 | # 合并 270 | print("所有分段下载完成,开始合并文件...") 271 | with open(file_path, 'wb') as outfile: 272 | for i in range(thread_count): 273 | part_file = f"{file_path}.part{i}" 274 | with open(part_file, 'rb') as infile: 275 | outfile.write(infile.read()) 276 | os.remove(part_file) 277 | print(f"下载完成,文件已保存至: {file_path}") 278 | 279 | except Exception as e: 280 | print(f"多线程下载失败: {e}\n自动切换到单线程普通下载...") 281 | single_thread_download(final_url, file_path, name, chunk_size) 282 | 283 | else: 284 | # 直接单线程 285 | single_thread_download(final_url, file_path, name, chunk_size) 286 | 287 | break 288 | except Exception as e: 289 | print('出现异常! 自动重试中...') 290 | TUtilLog.warning("{}".format(traceback.format_exc())) 291 | failtime -= 1 292 | if failtime < 0: 293 | raise Exception("资源获取失败!请稍后再试!") 294 | def tool_clear(ask = False): 295 | import shutil 296 | clear = False 297 | if ask: 298 | print("清除缓存?(Y/N,默认N)") 299 | a = input().lower() 300 | if a != 'y': 301 | clear = True 302 | 303 | try: 304 | if (ask and clear) or not ask: 305 | print("清除缓存...") 306 | TUtilLog.info("清除缓存...") 307 | shutil.rmtree('./cache') 308 | except: 309 | TUtilLog.exception() 310 | finally: 311 | import os 312 | os._exit(0) 313 | 314 | def print_info(message): 315 | print(message) 316 | TUtilLog.info(message) 317 | 318 | def check_zip(path="./", targetdir = './'): 319 | dirs = os.listdir(path) 320 | 321 | for _file in tqdm(dirs, desc="安装内容"): 322 | if _file.find('.zip'): 323 | if un_zip(_file): 324 | pass 325 | else: 326 | print_info("精灵包文件处理失败") 327 | os.remove(path + _file) 328 | TUtilLog.error("\n处理出错的文件: '{}'\n".format(_file)) 329 | continue 330 | dir_check(path + _file, targetdir) 331 | 332 | 333 | def dir_check(filedir, path): 334 | """ 335 | 精灵包文件检查流程 336 | IN: 337 | filedir - 检查的扩展包压缩包名(先调用解压函数完成后) 338 | path - MAS所在的文件夹,类似于renpy.config.basedir 339 | """ 340 | path=path.replace('//', '/') 341 | subfile = os.listdir(filedir+"_files") 342 | for i in tqdm(subfile, desc="复制文件"): 343 | ifull = filedir + "_files" + "/" + i 344 | if copy_dir_m(i, ifull, path): 345 | # 处理成功 346 | continue 347 | else: 348 | # 处理名字不正常的文件 349 | # 进入文件夹后再遍历文件进行处理 350 | TUtilLog.info("进入文件夹 '{}' 处理内部文件".format(ifull)) 351 | if not os.path.isdir(ifull): 352 | TUtilLog.info("不是文件夹 '{}' ".format(ifull)) 353 | continue 354 | subi = os.listdir(ifull) 355 | for subifile in subi: 356 | subifile_full = ifull + "/" + subifile 357 | if copy_dir_m(subifile, subifile_full, path ): 358 | continue 359 | else: 360 | TUtilLog.info( 361 | "2 - 进入文件夹 '{}' 处理内部文件".format(subifile_full)) 362 | if not os.path.isdir(subifile_full): 363 | TUtilLog.info( 364 | "不是文件夹 '{}' ".format(subifile_full)) 365 | continue 366 | subi2 = os.listdir(subifile_full) 367 | for subifile in subi2: 368 | subifile_full2 = subifile_full + "/" + subifile 369 | if copy_dir_m(subifile, subifile_full2, path): 370 | continue 371 | else: 372 | TUtilLog.info( 373 | "3 - 进入文件夹 '{}' 处理内部文件".format(subifile_full2)) 374 | if not os.path.isdir(subifile_full2): 375 | TUtilLog.info( 376 | "不是文件夹 '{}' ".format(subifile_full2)) 377 | continue 378 | subi3 = os.listdir(subifile_full2) 379 | for subifile in subi3: 380 | subifile_full3 = subifile_full2 + "/" + subifile 381 | if copy_dir_m(subifile, subifile_full3, path): 382 | continue 383 | else: 384 | TUtilLog.info( 385 | "4 - 进入文件夹 '{}' 处理内部文件".format(subifile_full3)) 386 | if not os.path.isdir(subifile_full3): 387 | TUtilLog.info( 388 | "不是文件夹 '{}' ".format(subifile_full3)) 389 | continue 390 | subi4 = os.listdir( 391 | subifile_full3) 392 | for subifile in subi4: 393 | subifile_full4 = subifile_full3 + "/" + subifile 394 | if copy_dir_m(subifile, subifile_full4, path): 395 | continue 396 | else: 397 | TUtilLog.info( 398 | "5 - 进入文件夹 '{}' 处理内部文件".format(subifile_full4)) 399 | if not os.path.isdir(subifile_full4): 400 | TUtilLog.info( 401 | "不是文件夹 '{}' ".format(subifile_full4)) 402 | continue 403 | subi5 = os.listdir( 404 | subifile_full4) 405 | for subifile in subi5: 406 | subifile_full5 = subifile_full4 + "/" + subifile 407 | if copy_dir_m(subifile, subifile_full5, path): 408 | continue 409 | else: 410 | TUtilLog.info( 411 | "6 - 进入文件夹 '{}' 处理内部文件".format(subifile_full5)) 412 | if not os.path.isdir(subifile_full5): 413 | TUtilLog.info( 414 | "不是文件夹 '{}' ".format(subifile_full5)) 415 | continue 416 | subi6 = os.listdir( 417 | subifile_full5) 418 | for subifile in subi6: 419 | subifile_full6 = subifile_full5 + "/" + subifile 420 | if copy_dir_m(subifile, subifile_full6, path): 421 | continue 422 | else: 423 | TUtilLog.warning( 424 | "达到最深深度6,不再继续处理") 425 | continue 426 | 427 | def copy(src, tgp): 428 | shutil.copy(src, tgp) 429 | 430 | 431 | def copy_dir(src_path, target_path): 432 | """ 433 | 复制文件 网上找的代码:)))))) 434 | """ 435 | global _install_completed 436 | if os.path.isdir(src_path) and os.path.isdir(target_path): 437 | filelist_src = os.listdir(src_path) 438 | for file in filelist_src: 439 | path = os.path.join(os.path.abspath(src_path), file) 440 | if os.path.isdir(path): 441 | path1 = os.path.join(os.path.abspath(target_path), file) 442 | if not os.path.exists(path1): 443 | os.mkdir(path1) 444 | copy_dir(path, path1) 445 | else: 446 | with open(path, 'rb') as read_stream: 447 | contents = read_stream.read() 448 | path1 = os.path.join(target_path, file) 449 | with open(path1, 'wb') as write_stream: 450 | write_stream.write(contents) 451 | _install_completed = True 452 | return True 453 | else: 454 | return False 455 | 456 | 457 | def copy_dir_m(dirs, file_name, path): 458 | """ 459 | 处理文件夹 460 | in: 461 | dirs - 文件夹,短名 462 | file_name - 文件夹绝对路径 463 | path - 根目录 464 | """ 465 | TUtilLog.info("准备复制文件:'{}'".format(dirs)) 466 | # bak_file_name = 467 | # if inseconddir == False: 468 | # files = os.listdir(file_name) 469 | # for dirs in files: 470 | if dirs == 'game': 471 | check_json(file_name + "/mod_assets", path) 472 | copy_dir(file_name, path + "/game") 473 | return True 474 | elif dirs == 'lib': 475 | copy_dir(file_name, path + "/lib") 476 | return True 477 | elif dirs == 'log': 478 | copy_dir(file_name, path + "/log") 479 | return True 480 | elif dirs == 'piano_songs': 481 | copy_dir(file_name, path + "/piano_songs") 482 | return True 483 | elif dirs == 'custom_bgm': 484 | copy_dir(file_name, path + "/custom_bgm") 485 | return True 486 | elif dirs == 'characters': 487 | TUtilLog.info("忽略该文件夹: '{}'".format(dirs)) 488 | return True # 什么都不做, 我不希望做一个一键解锁精灵包的东西--至少要手动移动文件. 489 | elif dirs == 'gift': 490 | TUtilLog.info("忽略该文件夹: '{}'".format(dirs)) 491 | return True # 什么都不做, 我不希望做一个一键解锁精灵包的东西--至少要手动移动文件. 492 | elif dirs == 'gifts': 493 | TUtilLog.info("忽略该文件夹: '{}'".format(dirs)) 494 | return True # 什么都不做, 我不希望做一个一键解锁精灵包的东西--至少要手动移动文件. 495 | # game下文件夹 496 | elif dirs == 'Submods': 497 | copy_dir(file_name, path + "/game/Submods") 498 | return True 499 | elif dirs == 'mod_assets': 500 | check_json(file_name, path) 501 | copy_dir(file_name, path + "/game/mod_assets") 502 | return True 503 | elif dirs == 'python-packages': 504 | copy_dir(file_name, path + "/game/python-packages") 505 | return True 506 | elif dirs == 'gui': 507 | copy_dir(file_name, path + "/game/gui") 508 | return True 509 | else: 510 | if os.path.isfile(file_name): 511 | if file_name in ['CustomIconMac.icns', 'CustomIconWindows.ico', 'README.html']: 512 | shutil.move(file_name, os.path.join( 513 | path + "/")) 514 | return True 515 | if file_name.find('rpy') != -1: # 如果是rpy文件 516 | if not os.path.exists(path + "/game/Submods/UnGroupScripts"): 517 | os.mkdir(path + "/game/Submods/UnGroupScripts") 518 | shutil.move(file_name, os.path.join( 519 | path + "/game/Submods/UnGroupScripts")) 520 | TUtilLog.warning( 521 | "这是个脚本文件,复制到 'Submods/UnGroupScripts':{}".format(file_name)) 522 | return True 523 | TUtilLog.info("不符合任何常规子模组应有的文件夹: '{}'".format(file_name)) 524 | return False 525 | 526 | 527 | def check_json(filename, path, movedir=None): 528 | import json 529 | """ 530 | 用于检查json并生成gift文件 531 | vars: 532 | filename - mod_assets文件夹 533 | movedir - 失败后删除的文件夹 534 | path - 根目录 535 | """ 536 | TUtilLog.info("检测精灵包json文件:'{}'".format(filename)) 537 | if not os.path.exists(filename + "/monika/j"): 538 | TUtilLog.info("未找到的json文件夹,跳过检测礼物:'{}'".format(filename)) 539 | return 540 | filename = filename + "/monika/j" 541 | files = os.listdir(filename) 542 | for jsonfile in files: 543 | if jsonfile.find('json') != -1: 544 | try: 545 | json_file = filename + "/" + jsonfile 546 | json_data = open(json_file).read() 547 | output_json = json.loads(json_data) 548 | except: 549 | # move_files(movedir,False) 550 | 551 | TUtilLog.error("在尝试读取 '{}' 出现异常,跳过".format(json_file)) 552 | continue 553 | try: 554 | giftname = output_json['giftname'] 555 | try: 556 | gtype = "/" + output_json['select_info']['group'] + "/" 557 | except: 558 | TUtilLog.warning( 559 | "在尝试获取的礼物分组时出现异常,使用空分组: '{}' ".format(json_file)) 560 | gtype = "/" 561 | try: 562 | if not os.path.exists(path + '/AvailableGift'): 563 | os.mkdir(path + '/AvailableGift') 564 | if not os.path.exists(path + '/AvailableGift' + gtype): 565 | os.mkdir(path + '/AvailableGift' + gtype) 566 | giftfile = open(path + '/AvailableGift' + 567 | gtype + giftname + '.gift', 'w') 568 | giftfile.close() 569 | TUtilLog.info("生成了礼物文件:'{}'".format( 570 | 'AvailableGift' + gtype + giftname + '.gift')) 571 | except Exception as e: 572 | TUtilLog.error('生成礼物文件出现异常!{}'.format(e)) 573 | except: 574 | TUtilLog.warning( 575 | "在尝试获取礼物文件名时出现异常,可能未设置giftname,跳过该文件:'{}'".format(json_file)) 576 | continue 577 | 578 | def get_extra_file(data = None): 579 | # 下载额外内容仅在第一次安装时进行 580 | print_info("下载额外内容") 581 | if not data: 582 | try: 583 | a = requests.get("http://releases.0721play.top/" + 'https://raw.githubusercontent.com/Mon1-innovation/MAS-Simplified-Chinese-Patch/main/extra_file.json', verify=False) 584 | except: 585 | a = requests.get('http://sp2.0721play.icu/d/MAS/MAS-PC/extra_file.json', verify=False) 586 | a = a.json() 587 | else: 588 | a = data 589 | for file in tqdm(a["extra_files"], desc="额外内容"): 590 | if file[3] == "EXTRACT_EXTRA": 591 | download(file[1], file[2], file[0]) 592 | un_zip(file[2] + "/" + file[0]) 593 | dir_check(file[2] + "/" + file[0], path = "./CACHE" + '/ddlc.zip_files/DDLC-1.1.1-pc') 594 | elif file[3] == "ASK_DOWNLOAD": 595 | print_info("是否下载{}, 默认为N".format(file[1])) 596 | print_info(file[5]) 597 | a = input().lower() 598 | if a != 'y': 599 | print_info("取消下载") 600 | else: 601 | download(file[1], file[2], file[0]) 602 | else: 603 | download(file[1], file[2], file[0]) 604 | 605 | --------------------------------------------------------------------------------