Skip to content
Projects
Groups
Snippets
Help
Loading...
Help
Support
Keyboard shortcuts
?
Submit feedback
Sign in / Register
Toggle navigation
C
Card password conversion
Project overview
Project overview
Details
Activity
Releases
Repository
Repository
Files
Commits
Branches
Tags
Contributors
Graph
Compare
Locked Files
Issues
0
Issues
0
List
Boards
Labels
Service Desk
Milestones
Merge Requests
0
Merge Requests
0
CI / CD
CI / CD
Pipelines
Jobs
Schedules
Security & Compliance
Security & Compliance
Dependency List
License Compliance
Packages
Packages
List
Container Registry
Analytics
Analytics
CI / CD
Code Review
Insights
Issues
Repository
Value Stream
Wiki
Wiki
Snippets
Snippets
Members
Members
Collapse sidebar
Close sidebar
Activity
Graph
Create a new issue
Jobs
Commits
Issue Boards
Open sidebar
苍蓝
Card password conversion
Commits
8ad0c188
Commit
8ad0c188
authored
Feb 26, 2026
by
苍蓝
Browse files
Options
Browse Files
Download
Email Patches
Plain Diff
update
parent
d23663b1
Changes
3
Show whitespace changes
Inline
Side-by-side
Showing
3 changed files
with
173 additions
and
72 deletions
+173
-72
deckcode.py
deckcode.py
+170
-69
to-formal.txt
to-formal.txt
+1
-0
to-pre.txt
to-pre.txt
+2
-3
No files found.
deckcode.py
View file @
8ad0c188
import
os
import
os
import
sys
import
sys
import
urllib.request
import
urllib.request
from
datetime
import
datetime
,
timedelta
import
urllib.error
from
typing
import
Dict
,
Optional
from
typing
import
Optional
,
List
from
pathlib
import
Path
from
pathlib
import
Path
# 配置
# 配置
...
@@ -11,102 +11,203 @@ CONFIG = {
...
@@ -11,102 +11,203 @@ CONFIG = {
'formal_file'
:
"to-formal.txt"
,
'formal_file'
:
"to-formal.txt"
,
'pre_file'
:
"to-pre.txt"
,
'pre_file'
:
"to-pre.txt"
,
'url_formal'
:
"https://code.moenext.com/coccvo/card-password-conversion/-/raw/master/to-formal.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
:
def
get_etag_path
(
filename
:
str
)
->
str
:
"""检查并更新文件,如果成功返回True,失败返回False"""
"""获取存储 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
:
try
:
if
not
os
.
path
.
exists
(
filename
):
with
open
(
etag_file
,
'r'
,
encoding
=
'utf-8'
)
as
f
:
print
(
f
"{filename} 不存在,开始下载..."
)
return
f
.
read
()
.
strip
()
return
download_file
(
url
,
filename
)
except
Exception
:
pass
file_mod_time
=
datetime
.
fromtimestamp
(
os
.
path
.
getmtime
(
filename
))
return
None
current_time
=
datetime
.
now
()
if
(
current_time
-
file_mod_time
)
>
timedelta
(
days
=
1
):
def
save_local_etag
(
filename
:
str
,
etag
:
str
):
print
(
f
"更新 {filename}..."
)
"""保存 ETag 到本地"""
return
download_file
(
url
,
filename
)
etag_file
=
get_etag_path
(
filename
)
return
True
try
:
with
open
(
etag_file
,
'w'
,
encoding
=
'utf-8'
)
as
f
:
f
.
write
(
etag
)
except
Exception
as
e
:
except
Exception
as
e
:
print
(
f
"Error: 检查文件更新失败 {e}"
)
print
(
f
"警告:无法保存 ETag 文件 {e}"
)
return
False
def
check_and_update_file
(
filename
:
str
,
url
:
str
)
->
bool
:
"""
检查并更新文件 (使用 ETag 机制,无随机延迟)
"""
local_etag
=
load_local_etag
(
filename
)
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
)
def
download_file
(
url
:
str
,
filename
:
str
)
->
bool
:
try
:
try
:
urllib
.
request
.
urlretrieve
(
url
,
filename
)
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
return
True
else
:
# 其他 HTTP 错误
raise
e
except
Exception
as
e
:
except
Exception
as
e
:
print
(
f
"Error: 下载对照表失败 {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
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
]:
try
:
replacements
=
{}
replacements
=
{}
# 读取正式对照表
try
:
with
open
(
formal_file
,
'r'
,
encoding
=
'utf-8'
)
as
file
:
if
not
os
.
path
.
exists
(
formal_file
):
for
line
in
file
:
return
None
with
open
(
formal_file
,
'r'
,
encoding
=
'utf-8'
)
as
f
:
for
line
in
f
:
parts
=
line
.
strip
()
.
split
(
'
\t
'
)
parts
=
line
.
strip
()
.
split
(
'
\t
'
)
if
len
(
parts
)
==
2
:
if
len
(
parts
)
==
2
:
replacements
[
parts
[
0
]]
=
parts
[
1
]
replacements
[
parts
[
0
]]
=
parts
[
1
]
# 读取预发布对照表
if
os
.
path
.
exists
(
pre_file
):
with
open
(
pre_file
,
'r'
,
encoding
=
'utf-8'
)
as
file
:
with
open
(
pre_file
,
'r'
,
encoding
=
'utf-8'
)
as
f
:
for
line
in
file
:
for
line
in
f
:
parts
=
line
.
strip
()
.
split
(
'
\t
'
)
parts
=
line
.
strip
()
.
split
(
'
\t
'
)
if
len
(
parts
)
==
2
:
if
len
(
parts
)
==
2
:
replacements
[
parts
[
1
]]
=
parts
[
0
]
replacements
[
parts
[
1
]]
=
parts
[
0
]
return
replacements
return
replacements
except
Exception
as
e
:
except
Exception
as
e
:
print
(
f
"
Error: 读取对照表失败
{e}"
)
print
(
f
"
[错误] 读取对照表出错:
{e}"
)
return
None
return
None
def
main
()
->
int
:
def
main
():
# 检查目录
#
1.
检查目录
if
not
os
.
path
.
exists
(
CONFIG
[
'folder_path'
]):
if
not
os
.
path
.
exists
(
CONFIG
[
'folder_path'
]):
print
(
"Error: 请把此文件放到游戏目录中再运行"
)
print
(
f
"[错误] 未找到 '{CONFIG['folder_path']}' 文件夹。"
)
print
(
" 请将此脚本放在游戏目录下运行。"
)
input
(
"
\n
按回车键退出..."
)
return
1
return
1
# 更新对照表
# 2. 更新对照表
for
file_key
,
url_key
in
[(
'formal_file'
,
'url_formal'
),
(
'pre_file'
,
'url_pre'
)]:
files_config
=
[
if
not
check_and_update_file
(
CONFIG
[
file_key
],
CONFIG
[
url_key
]):
(
'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
return
1
# 加载替换规则
#
3.
加载替换规则
replacements
=
load_replacements
(
CONFIG
[
'formal_file'
],
CONFIG
[
'pre_file'
])
replacements
=
load_replacements
(
CONFIG
[
'formal_file'
],
CONFIG
[
'pre_file'
])
if
not
replacements
:
return
1
# 处理卡组文件
if
not
replacements
:
print
(
"[警告] 替换规则为空,跳过卡组处理。"
)
else
:
deck_path
=
Path
(
CONFIG
[
'folder_path'
])
deck_path
=
Path
(
CONFIG
[
'folder_path'
])
for
ydk_file
in
deck_path
.
rglob
(
'*.ydk'
):
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
:
try
:
content
=
ydk_file
.
read_text
(
encoding
=
'utf-8'
)
content
=
ydk
.
read_text
(
encoding
=
'utf-8'
)
new_content
=
content
new_content
=
content
# 执行替换
for
old
,
new
in
replacements
.
items
():
for
old
,
new
in
replacements
.
items
():
if
old
in
new_content
:
new_content
=
new_content
.
replace
(
old
,
new
)
new_content
=
new_content
.
replace
(
old
,
new
)
# 如果内容发生变化,写入文件并记录
if
new_content
!=
content
:
if
new_content
!=
content
:
ydk_file
.
write_text
(
new_content
,
encoding
=
'utf-8'
)
ydk
.
write_text
(
new_content
,
encoding
=
'utf-8'
)
print
(
f
"更新卡组: {ydk_file}"
)
try
:
else
:
relative_path
=
ydk
.
relative_to
(
deck_path
)
print
(
f
"卡组无需修改: {ydk_file}"
)
updated_files
.
append
(
str
(
relative_path
))
except
ValueError
:
updated_files
.
append
(
str
(
ydk
.
name
))
except
Exception
as
e
:
except
Exception
as
e
:
print
(
f
"处理文件 {ydk_file} 时出错: {e}"
)
print
(
f
"[错误] 处理文件 {ydk.name} 时异常:{e}"
)
continue
# 4. 显示修改列表
print
(
"
\n
"
+
"="
*
30
)
if
updated_files
:
print
(
f
"【更新完成】共修改 {len(updated_files)} 个卡组文件:"
)
for
fname
in
updated_files
:
print
(
f
" - {fname}"
)
else
:
print
(
"【更新完成】所有卡组文件均为最新,无需修改。"
)
print
(
"="
*
30
)
print
(
"卡组更新完成。"
)
print
(
"
\n
按回车键退出..."
)
input
()
return
0
return
0
if
__name__
==
"__main__"
:
if
__name__
==
"__main__"
:
try
:
try
:
exit_code
=
main
()
exit_code
=
main
()
print
(
"
\n
按回车键退出..."
)
sys
.
exit
(
exit_code
)
input
()
except
KeyboardInterrupt
:
sys
.
exit
(
exit_code
)
# 使用 sys.exit() 替代 exit()
print
(
"
\n
[中断] 用户取消操作。"
)
sys
.
exit
(
130
)
except
Exception
as
e
:
except
Exception
as
e
:
print
(
f
"Error: {e}"
)
print
(
f
"
\n
[严重错误] {e}"
)
print
(
"
\n
按回车键退出..."
)
input
(
"
\n
按回车键退出..."
)
input
()
sys
.
exit
(
1
)
sys
.
exit
(
1
)
to-formal.txt
View file @
8ad0c188
#过期先行卡转换为正式卡
#过期先行卡转换为正式卡
#项目地址:https://code.moenext.com/coccvo/card-password-conversion
100200277 40725446
100200277 40725446
100238201 32872239
100238201 32872239
100243001 20240828
100243001 20240828
...
...
to-pre.txt
View file @
8ad0c188
#服务器未更新正式卡转换为先行卡
#服务器未更新正式卡转换为先行卡
#项目地址:https://code.moenext.com/coccvo/card-password-conversion
100256001 88570003
100256001 88570003
100256002 14965712
100256002 14965712
100256003 41350417
100256003 41350417
...
@@ -17,8 +18,6 @@
...
@@ -17,8 +18,6 @@
100256016 74665150
100256016 74665150
100256017 64865
100256017 64865
100256018 37458564
100256018 37458564
100256019
100256020
100256021 32236916
100256021 32236916
100256022 68721020
100256022 68721020
100256023 5125629
100256023 5125629
...
...
Write
Preview
Markdown
is supported
0%
Try again
or
attach a new file
Attach a file
Cancel
You are about to add
0
people
to the discussion. Proceed with caution.
Finish editing this message first!
Cancel
Please
register
or
sign in
to comment