Commit 8ad0c188 authored by 苍蓝's avatar 苍蓝

update

parent d23663b1
import os
import sys
import urllib.request
from datetime import datetime, timedelta
from typing import Dict, Optional
import urllib.error
from typing import Optional, List
from pathlib import Path
# 配置
......@@ -11,102 +11,203 @@ CONFIG = {
'formal_file': "to-formal.txt",
'pre_file': "to-pre.txt",
'url_formal': "https://code.moenext.com/coccvo/card-password-conversion/-/raw/master/to-formal.txt",
'url_pre': "https://code.moenext.com/coccvo/card-password-conversion/-/raw/master/to-pre.txt"
'url_pre': "https://code.moenext.com/coccvo/card-password-conversion/-/raw/master/to-pre.txt",
'max_retries': 3
}
def check_and_update_file(filename: str, url: str) -> bool:
"""检查并更新文件,如果成功返回True,失败返回False"""
def get_etag_path(filename: str) -> str:
"""获取存储 ETag 的隐藏文件路径"""
return f"{filename}.etag"
def load_local_etag(filename: str) -> Optional[str]:
"""从本地加载 ETag"""
etag_file = get_etag_path(filename)
if os.path.exists(etag_file):
try:
with open(etag_file, 'r', encoding='utf-8') as f:
return f.read().strip()
except Exception:
pass
return None
def save_local_etag(filename: str, etag: str):
"""保存 ETag 到本地"""
etag_file = get_etag_path(filename)
try:
if not os.path.exists(filename):
print(f"{filename} 不存在,开始下载...")
return download_file(url, filename)
file_mod_time = datetime.fromtimestamp(os.path.getmtime(filename))
current_time = datetime.now()
if (current_time - file_mod_time) > timedelta(days=1):
print(f"更新 {filename}...")
return download_file(url, filename)
return True
with open(etag_file, 'w', encoding='utf-8') as f:
f.write(etag)
except Exception as e:
print(f"Error: 检查文件更新失败 {e}")
return False
print(f"警告:无法保存 ETag 文件 {e}")
def check_and_update_file(filename: str, url: str) -> bool:
"""
检查并更新文件 (使用 ETag 机制,无随机延迟)
"""
local_etag = load_local_etag(filename)
def download_file(url: str, filename: str) -> bool:
try:
urllib.request.urlretrieve(url, filename)
return True
except Exception as e:
print(f"Error: 下载对照表失败 {e}")
return False
for attempt in range(CONFIG['max_retries']):
try:
req = urllib.request.Request(url)
req.add_header('User-Agent', 'YDK-Update-Tool/1.0')
# 核心:如果有本地 ETag,添加到请求头
if local_etag:
req.add_header('If-None-Match', local_etag)
try:
with urllib.request.urlopen(req, timeout=10) as response:
# 状态码 200: 文件有更新或首次下载
content = response.read()
new_etag = response.headers.get('ETag', '').strip()
# 保存文件内容
with open(filename, 'wb') as f:
f.write(content)
# 保存新的 ETag
if new_etag:
save_local_etag(filename, new_etag)
print(f"[下载] {filename} 已更新。")
return True
except urllib.error.HTTPError as e:
# 处理 304 Not Modified (文件未变化)
if e.code == 304:
return True
else:
# 其他 HTTP 错误
raise e
except Exception as e:
wait_time = (attempt + 1) * 2
print(f"[警告] 下载 {filename} 失败 (尝试 {attempt+1}/{CONFIG['max_retries']}): {e}")
if attempt < CONFIG['max_retries'] - 1:
print(f" 等待 {wait_time} 秒后重试...")
import time
time.sleep(wait_time)
else:
if os.path.exists(filename):
print(f"[提示] 无法连接服务器,继续使用本地旧版 {filename}。")
return True
else:
print(f"[错误] 无法下载初始文件 {filename}。")
return False
return False
def load_replacements(formal_file: str, pre_file: str) -> Optional[Dict[str, str]]:
def load_replacements(formal_file: str, pre_file: str) -> Optional[dict]:
replacements = {}
try:
replacements = {}
# 读取正式对照表
with open(formal_file, 'r', encoding='utf-8') as file:
for line in file:
if not os.path.exists(formal_file):
return None
with open(formal_file, 'r', encoding='utf-8') as f:
for line in f:
parts = line.strip().split('\t')
if len(parts) == 2:
replacements[parts[0]] = parts[1]
# 读取预发布对照表
with open(pre_file, 'r', encoding='utf-8') as file:
for line in file:
parts = line.strip().split('\t')
if len(parts) == 2:
replacements[parts[1]] = parts[0]
if os.path.exists(pre_file):
with open(pre_file, 'r', encoding='utf-8') as f:
for line in f:
parts = line.strip().split('\t')
if len(parts) == 2:
replacements[parts[1]] = parts[0]
return replacements
except Exception as e:
print(f"Error: 读取对照表失败 {e}")
print(f"[错误] 读取对照表出错:{e}")
return None
def main() -> int:
# 检查目录
def main():
# 1. 检查目录
if not os.path.exists(CONFIG['folder_path']):
print("Error: 请把此文件放到游戏目录中再运行")
print(f"[错误] 未找到 '{CONFIG['folder_path']}' 文件夹。")
print(" 请将此脚本放在游戏目录下运行。")
input("\n按回车键退出...")
return 1
# 更新对照表
for file_key, url_key in [('formal_file', 'url_formal'), ('pre_file', 'url_pre')]:
if not check_and_update_file(CONFIG[file_key], CONFIG[url_key]):
return 1
# 2. 更新对照表
files_config = [
('formal_file', 'url_formal'),
('pre_file', 'url_pre')
]
# 加载替换规则
critical_failure = False
for file_key, url_key in files_config:
f_name = CONFIG[file_key]
u_url = CONFIG[url_key]
if not os.path.exists(f_name):
if not check_and_update_file(f_name, u_url):
critical_failure = True
else:
check_and_update_file(f_name, u_url)
if critical_failure:
print("\n[错误] 缺少必要的对照表文件且无法下载。")
input("\n按回车键退出...")
return 1
# 3. 加载替换规则
replacements = load_replacements(CONFIG['formal_file'], CONFIG['pre_file'])
if not replacements:
return 1
print("[警告] 替换规则为空,跳过卡组处理。")
else:
deck_path = Path(CONFIG['folder_path'])
ydk_files = list(deck_path.rglob('*.ydk'))
if not ydk_files:
print(f"[提示] 在 '{CONFIG['folder_path']}' 目录下未找到 .ydk 文件。")
else:
updated_files: List[str] = []
for ydk in ydk_files:
try:
content = ydk.read_text(encoding='utf-8')
new_content = content
# 执行替换
for old, new in replacements.items():
if old in new_content:
new_content = new_content.replace(old, new)
# 如果内容发生变化,写入文件并记录
if new_content != content:
ydk.write_text(new_content, encoding='utf-8')
try:
relative_path = ydk.relative_to(deck_path)
updated_files.append(str(relative_path))
except ValueError:
updated_files.append(str(ydk.name))
except Exception as e:
print(f"[错误] 处理文件 {ydk.name} 时异常:{e}")
# 处理卡组文件
deck_path = Path(CONFIG['folder_path'])
for ydk_file in deck_path.rglob('*.ydk'):
try:
content = ydk_file.read_text(encoding='utf-8')
new_content = content
for old, new in replacements.items():
new_content = new_content.replace(old, new)
if new_content != content:
ydk_file.write_text(new_content, encoding='utf-8')
print(f"更新卡组: {ydk_file}")
# 4. 显示修改列表
print("\n" + "="*30)
if updated_files:
print(f"【更新完成】共修改 {len(updated_files)} 个卡组文件:")
for fname in updated_files:
print(f" - {fname}")
else:
print(f"卡组无需修改: {ydk_file}")
except Exception as e:
print(f"处理文件 {ydk_file} 时出错: {e}")
continue
print("【更新完成】所有卡组文件均为最新,无需修改。")
print("="*30)
print("卡组更新完成。")
print("\n按回车键退出...")
input()
return 0
if __name__ == "__main__":
try:
exit_code = main()
print("\n按回车键退出...")
input()
sys.exit(exit_code) # 使用 sys.exit() 替代 exit()
sys.exit(exit_code)
except KeyboardInterrupt:
print("\n[中断] 用户取消操作。")
sys.exit(130)
except Exception as e:
print(f"Error: {e}")
print("\n按回车键退出...")
input()
print(f"\n[严重错误] {e}")
input("\n按回车键退出...")
sys.exit(1)
#过期先行卡转换为正式卡
#项目地址:https://code.moenext.com/coccvo/card-password-conversion
100200277 40725446
100238201 32872239
100243001 20240828
......
#服务器未更新正式卡转换为先行卡
#项目地址:https://code.moenext.com/coccvo/card-password-conversion
100256001 88570003
100256002 14965712
100256003 41350417
......@@ -16,9 +17,7 @@
100256015 48171151
100256016 74665150
100256017 64865
100256018 37458564
100256019
100256020
100256018 37458564
100256021 32236916
100256022 68721020
100256023 5125629
......
Markdown is supported
0% or
You are about to add 0 people to the discussion. Proceed with caution.
Finish editing this message first!
Please register or to comment