重构:常量下沉到 api 模块 + 删无用脚本 + rating/grade 改为运行时推导

1) 删除 5 个无用的取数脚本(连同 __init__ 的导出):
   get_game_event / get_game_ng_music_id / get_game_ranking /
   get_game_tournament_info / get_game_weekly_data

2) config.py 常量下沉(config 只留「机台/店铺标识」和闸门/日志):
   - BASE_URL / AES_KEY / AES_IV / OBFUSCATE_PARAM -> api/maimai_net.py
   - AIMEDB_* / QR_* -> api/chime.py
   - TICKET_CREDIT_NUM / TICKET_NAMES / PAID_TICKET_IDS /
     TICKET_VALID_HOUR_OFFSET / TICKET_VALID_DAYS -> api/upsert_user_chargelog.py
   - PLAY_SPECIAL_NUM -> api/upsert_user_all.py
   - PLAY_CHARACTERS -> selftest.py(作为测试数据)
   下沉后的常量仍从 api 包统一导出,调用点无需改 import 路径。

3) PlayData 字段改造:
   - characters 默认空列表(真值由 derive_play_characters 从快照推)
   - local_play_count 恒为 2
   - after_grade_rank 恒为 1

4) rating / grade 改为运行时从服务器快照取:
   - 新增 derive_play_rating():
       before/afterRating      <- userData.playerRating
       before/afterDeluxRating <- userData.musicRating
     (真机实证 userRatingList[0].rating 是 0,不是这个值)
   - 新增 derive_play_grade() + find_music_detail():
       在 userMusicDetailList 里搜同 (musicId, level) 取 scoreRank
       DERIVE_GRADE_FROM_MUSIC_DETAIL=False 可切回严格复刻真机(一律 0)
     ⚠ 源码实证这三个字段其实是段位 Dan(VOExtensions.cs:1419-1421)

自检 238 项全绿。
This commit is contained in:
2026-10-07 00:17:08 +08:00
parent 8e3bd6fcaa
commit 652cf95faa
14 changed files with 390 additions and 427 deletions
+8 -83
View File
@@ -31,25 +31,7 @@ config.py —— 舞萌DX 纯网络脚本工程 · 运行时可配置项
# 一、网络与加密常量
# =============================================================================
# --- 游戏服务器(Maimai2Servlet)---
# 依据:source/Assembly-CSharp/Manager/OperationManager.cs:225,338
# _operationData.ServerUri = Auth.GameServerUri + MovieServerUri("mE2s3Jhd/")
# 实测:source/2026-10-05.log:1
BASE_URL = "https://maimai-gm.wahlap.com:42081/Maimai2Servlet/mE2s3Jhd/"
# --- AES 参数 ---
# 依据:source/Assembly-CSharp/Net/CipherAES.cs:11-12
# AesKey = "FKM2JX:VjZNK6hc:A0<JU:i5oR7LA]9W" (32 字节 -> AES-256)
# AesIV = "F>;24DjU9W6ZsRH[" (16 字节)
AES_KEY = b"FKM2JX:VjZNK6hc:A0<JU:i5oR7LA]9W"
AES_IV = b"F>;24DjU9W6ZsRH["
# --- API 名混淆盐 ---
# 依据:source/Assembly-CSharp/Net.Packet/Packet.cs:44 ObfuscateParam = "8bF76dE9"
# 用法:URL 尾段 = md5(逻辑接口名 + "MaimaiChn" + OBFUSCATE_PARAM) 小写 hex
# "MaimaiChn" 后缀来自 source/Assembly-CSharp/Net.VO/NetQuery.cs:14 Api = api + "MaimaiChn"
OBFUSCATE_PARAM = "8bF76dE9"
# ★ BASE_URL / AES_KEY / AES_IV / OBFUSCATE_PARAM 已下沉到 api/maimai_net.py
# --- 报文版本标识 ---
# 依据:source/Assembly-CSharp/Net/NetHttpClient.cs:69 DefaultHttpHeaderEncryption = "1.55"
# (请求头 Mai-Encoding 的值;1.56 ROM 实测仍发 1.55)
@@ -109,21 +91,7 @@ REGION_NAME = "" # ★★ 必填:区域名
# 依据:source/ChimeLib.NET/ChimeLib/NET/COMM/CCommGetUserData.cs
# + docs/舞萌DX_扫码登录协议技术规范.md
# aimedb 服务器
AIMEDB_HOST = "ai.sys-allnet.cn"
AIMEDB_PORT = 443
AIMEDB_PATH = "/wc_aime/api/get_data"
# 签名密钥(含前导 X,32 字符)
# 来源:chimelib_dll.dll .rdata UTF-16 @0x00B040,抓包验证一致
QR_SIGN_KEY = "XcW5FW4cPArBXEk4vzKz3CIrMuA5EVVW"
# 固定字段
QR_OPEN_GAME_ID = "MAID"
QR_TITLE_KEY = "SDGB"
QR_USER_AGENT = "WC_AIME_LIB"
# ★ aimedb / QR 常量已下沉到 api/chime.py
# =============================================================================
# 三之二、★ 功能票(Ticket)主数据
# =============================================================================
@@ -140,38 +108,12 @@ QR_USER_AGENT = "WC_AIME_LIB"
#
# ticketKind 含义(Ticket.xml 里的枚举):
# 1=Paid(付费,可在机台买) 2=Event 3=Free 4=Link 5=ShopWeekly 6=ShopChara
TICKET_CREDIT_NUM = {
0: 0,
2: 1, 3: 2, 4: 3, 5: 4, 6: 5, # 付费票:N 倍券的 creditNum = N-1
10005: 0, 10105: 0, 10205: 0, # 活动票
11001: 0, # 免费 1.5 倍券
30001: 0, 30002: 0, 30003: 0, # 连动 / 商店票
}
#: 票名(只用于日志好看,不影响协议)
TICKET_NAMES = {
0: "使用しない",
2: "2倍チケット", 3: "3倍チケット", 4: "4倍チケット", 5: "5倍チケット", 6: "6倍チケット",
10005: "イベント5倍チケット_1", 10105: "イベント5倍チケット_2",
10205: "イベント5倍チケット_3", 11001: "無料1.5倍チケット",
30001: "連動チケット", 30002: "每周区域前进2倍票", 30003: "旅行伙伴等级提升5倍票",
}
#: 付费票(ticketKind=1)—— 只有这些能在机台购买
PAID_TICKET_IDS = (2, 3, 4, 5, 6)
# ★ TICKET_CREDIT_NUM / TICKET_NAMES / PAID_TICKET_IDS /
# TICKET_VALID_HOUR_OFFSET / TICKET_VALID_DAYS
# 已下沉到 api/upsert_user_chargelog.py
#: 买票闸门(和 UpsertUserAll 一样,默认不放行)
UPSERT_CHARGELOG_CONFIRM = False
#: 票有效期算法参数
#: 依据 source/Assembly-CSharp/Manager/TicketManager.cs:564
#: DateTime.Now.AddHours(-4.0).AddDays(90.0).ToString("yyyy-MM-dd 04:00:00")
#: 真机验证:chargeId=5 的 purchaseDate=2026-10-04 18:22:10
#: -> 减 4 小时 = 10-04 14:22,加 90 天 = 2027-01-02 -> "2027-01-02 04:00:00" ✅
TICKET_VALID_HOUR_OFFSET = -4
TICKET_VALID_DAYS = 90
# =============================================================================
# 四、★ UpsertUserAll 即将上传的歌曲数据
# =============================================================================
@@ -225,14 +167,7 @@ PLAY_JUDGE_COUNTS = {
}
# --- 评级(本局前后)---
PLAY_BEFORE_RATING = 15000
PLAY_AFTER_RATING = 15000
PLAY_BEFORE_GRADE = 0
PLAY_AFTER_GRADE = 0
PLAY_AFTER_GRADE_RANK = 1
PLAY_BEFORE_DELUX_RATING = 15000
PLAY_AFTER_DELUX_RATING = 15000
# ★ PLAY_BEFORE/AFTER_RATING 等已改为运行时从服务器快照取(derive_play_rating)
# --- 曲种索引 ---
# ★ 必须与 userExtend.categoryIndex 一致(真机两处都是 2022)
PLAY_CATEGORY_INDEX = 2022
@@ -252,14 +187,6 @@ PLAY_EXTRA_FLAG = 1721 # userExtend.extraFlag
# 并覆盖本配置。只有拿不到快照(离线组包)时才回退到这里。
#
# 默认值 = 真机 charaSlot [395, 101, 400402, 400401, 200401] 的游玩前等级
PLAY_CHARACTERS = [
{"characterId": 395, "level": 3800, "awakening": 5},
{"characterId": 101, "level": 4455, "awakening": 5},
{"characterId": 400402, "level": 134, "awakening": 3},
{"characterId": 400401, "level": 134, "awakening": 3},
{"characterId": 200401, "level": 134, "awakening": 3},
]
# --- 本局消耗 ---
# ★ playCredit 语义(VOExtensions.cs:838-845):
# playCredit = Credit.GameCostEnoughPlay()(投币成本) + TicketManager.GetTicketCredit(useTicketId)
@@ -282,8 +209,7 @@ PLAY_IS_FREEDOM_MODE = False
# 所以既推不出来也不会被服务端纠正 —— 填错只是个统计数字不对。
# 取值 = 该机台当天/本轮的累计游玩局数(每打一局 +1)。
# 真机实测:19:21 那一局 = 9,22:31 那一局 = 10。
PLAY_LOCAL_PLAY_COUNT = 8
# ★ PLAY_LOCAL_PLAY_COUNT 恒为 2(已下沉到 api/upsert_user_all.py)
# --- ★ playSpecial 里的 "CalcSpecialNum"(机台硬件标志位)---
#
# 依据:source/Assembly-CSharp/Manager/GameManager.cs:332-378
@@ -312,8 +238,7 @@ PLAY_LOCAL_PLAY_COUNT = 8
# 余数恰好 1024,与抓到的 CalcSpecialNum 完全吻合。
#
# 改成 0 不会报错,但 playSpecial 的位模式就不是真机那种了。
PLAY_SPECIAL_NUM = 1024
# ★ PLAY_SPECIAL_NUM = 1024 已下沉到 api/upsert_user_all.py
# --- 用户总游玩次数增量 ---
#
# ★ 默认 0 = **userData.playCount / currentPlayCount 都不变**(本局不计入总次数)。