Files
Astral/api/__init__.py
T
Txiaochen 8e3bd6fcaa 重构:Get* 命名统一 + 用户数据落盘 + use_ticket / reincarnate
1) 命名统一(服务端 API 名带 Get 的,脚本名与函数名一律带 get/Get)
   - 26 个 api 脚本改名:userdata.py -> get_user_data.py 等
   - 7 个 game_*.py -> get_game_*.py
   - 38 个函数改名:UserData -> GetUserData 等
   - upsert_snapshot.py -> get_need_user_data.py,
     fetch_upsert_snapshot -> GetNeedUserData
   - user_getter_common.fetch_all_pages -> get_all_pages

2) GetNeedUserData 抓到的数据自动落盘
   - <工程根>/data/<userId>.json,新数据总是覆盖老数据
   - 新增 save_user_data / load_user_data / user_data_path /
     list_saved_user_ids / DATA_DIR / PROJECT_ROOT
   - data/ 已加入 .gitignore

3) use_ticket.py(新)
   - 读取账号当前持有的功能票,用 UpsertUserAll 消耗掉
   - 依据:GetUserChargeApi 与 UpsertUserAllApi 的 userChargeList 格式相同;
     真机实证 userChargeList.stock -1 + useTicketId + playCredit
   - playCredit = 投币数 + 票的 creditNum(VOExtensions.cs:838-845)

4) reincarnate.py(新)
   - 账号数据迁移(转生):A 的数据克隆到 B
   - 每包最多 4 首(真机一局上限),包间用续关登录换新 loginId
     续关依据:ContinueProcess.cs:403 -> PacketUserLogin(isContinue: true)
   - playlog 从曲目记录反推合成(没有对应的 Get 接口)

自检 238 项全绿。
2026-10-06 23:32:09 +08:00

515 lines
19 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
# -*- coding: utf-8 -*-
"""
api 包 —— 统一导出
================================================================================
主脚本只需要 from api import ... 就能拿到全部功能。
★ 本文件在导入时就给下面 _API_FUNCS 里列出的每个函数套上「日志外壳」,
所以主脚本拿到的已经是带日志的版本 —— 调用时会自动产出:
=== ParseQRCode 开始运行 ===
[接口说明] 解析二维码并换取 userId 与 token。
[位置参数] 'SGWCMAID2610022219463A297AF4CA...'
[运行结果] 成功 tuple(2 项)(耗时 412 ms)
=== ParseQRCode 运行结束 ===
主脚本**不需要**写装饰器,也不需要自己埋点。
--------------------------------------------------------------------------------
目录结构(一个 api 一个脚本)
--------------------------------------------------------------------------------
基础设施
log_setup.py 统一日志(INFO / DEBUG 双模式)
maimai_net.py 网络核心(AES / deflate / URL 混淆 / Cookie)
user_getter_common.py 取数脚本公共底座(请求 VO / _get / 翻页)
会话链路
chime.py 扫码登录 -> userId + token
get_game_settings.py GetGameSettingApi(游戏设置)
ping.py 心跳探活
get_user_preview.py GetUserPreviewApi(用户预览)
userlogin.py UserLoginApi(正式登录 -> loginId + loginDateTime)
userlogout.py UserLogoutApi(登出)
上传 / 结算(有副作用的接口)
upsert_user_all.py ★ UpsertUserAllApi(上传成绩)
upsert_user_chargelog.py UpsertUserChargelogApi(购买功能票)
get_need_user_data.py ★ 结算快照编排(统一调用下面的取数脚本),
并把结果落盘到 <工程根>/data/<userId>.json
★ 命名约定:服务端 API 名里带 Get 的,**脚本名与函数名一律带 get / Get**
(不要模棱两可)。所以下面这些文件全是 get_ 开头。
取数 —— GetUser*(一个接口一个脚本)
get_user_data.py GetUserDataApi
get_user_extend.py GetUserExtendApi
get_user_option.py GetUserOptionApi
get_user_character.py GetUserCharacterApi
get_user_ghost.py GetUserGhostApi
get_user_map.py GetUserMapApi
get_user_login_bonus.py GetUserLoginBonusApi
get_user_rating.py GetUserRatingApi
get_user_item.py GetUserItemApi
get_user_music.py GetUserMusicApi
get_user_course.py GetUserCourseApi
get_user_charge.py GetUserChargeApi
get_user_favorite.py GetUserFavoriteApi
get_user_activity.py GetUserActivityApi
get_user_mission.py GetUserMissionDataApi
get_user_intimate.py GetUserIntimateApi
get_user_shop_stock.py GetUserShopStockApi
get_user_favorite_item.py GetUserFavoriteItemApi
get_user_rival.py GetUserRivalDataApi / GetUserRivalMusicApi
get_user_friend_bonus.py GetUserFriendBonusApi
get_user_kaleidx_scope.py GetUserKaleidxScopeApi / GetGameKaleidxScopeApi
get_user_region.py GetUserRegionApi
get_user_recommend_music.py GetUserRecommendRateMusicApi / GetUserRecommendSelectMusicApi
get_user_new_item.py GetUserNewItemListApi
取数 —— GetGame*
get_game_settings.py GetGameSettingApi
get_game_ranking.py GetGameRankingApi
get_game_event.py GetGameEventApi
get_game_charge.py GetGameChargeApi
get_game_weekly_data.py GetGameWeeklyDataApi
get_game_tournament_info.py GetGameTournamentInfoApi
get_game_ng_music_id.py GetGameNgMusicIdApi
"""
from .log_setup import (
# 会话
setup_logging,
teardown_logging,
# 自动跟踪
autowrap,
get_called_apis,
# 模式
get_level,
set_level,
is_debug,
LEVEL_INFO,
LEVEL_DEBUG,
# 装饰器 / 兼容
api_log,
get_logger,
# 流程日志(INFO 可见)
log_info,
log_step,
log_result,
log_warning,
log_error,
log_section,
log_field,
log_debug,
# 收发数据日志(DEBUG 专属)
log_request,
log_response,
log_payload,
)
# ---------------------------------------------------------------------------
# 1) 网络核心
# ---------------------------------------------------------------------------
from .maimai_net import (
MaimaiNetClient,
MaimaiNetError,
get_default_client,
close_default_client,
request,
request_dict,
request_vo,
obfuscate_api_name,
build_api_url,
build_user_agent,
adler32,
aes_encrypt,
aes_decrypt,
deflate_compress,
deflate_decompress,
vo_to_json,
vo_from_json,
local_utc_offset_seconds,
login_date_time_now,
EmptyRequestVO,
UserIdRequestVO,
ReturnCodeVO,
)
# ---------------------------------------------------------------------------
# 2) 会话链路
# ---------------------------------------------------------------------------
from .chime import ParseQRCode
from .get_game_settings import (
GetGameSettings,
GameSetting,
GameSettingRequestVO,
GameSettingResponseVO,
is_maintenance,
is_ping_disabled,
)
from .ping import Ping
from .get_user_preview import (
GetUserPreview,
UserPreviewRequestVO,
UserPreviewResponseVO,
)
from .userlogin import (
UserLogin,
UserLoginRequestVO,
UserLoginResponseVO,
)
from .userlogout import (
UserLogout,
LogoutType,
DelayLog,
RequestAPI,
UserLogoutRequestVO,
UserLogoutRequest2VO,
UserLogoutResponseVO,
create_empty_delay_log,
create_delay_log_from_stats,
DELAY_LOG_SLOTS,
)
# ---------------------------------------------------------------------------
# 3) 上传成绩
# ---------------------------------------------------------------------------
from .upsert_user_all import (
UpsertUserAll,
PlayData,
build_play_from_config,
derive_play_characters,
UserAllRequestVO,
UpsertResponseVO,
UpsertUserAllError,
ConfirmRequiredError,
PatchError,
# 节点结构
NODE_TYPES,
NODE_ORDER,
BITS_TO_ARRAY,
ARRAY_TO_BITS,
DIFF_PRIMARY_KEYS,
MAY_BE_EMPTY_NODES,
DEFAULT_EMPTY_NODES,
# 组包辅助
empty_node,
empty_user_all,
coerce_node_value,
sync_bits_to_arrays,
build_delta,
build_favorite_delta,
build_user_all,
build_user_playlog,
build_user_game_playlog,
build_post_play_user_data,
validate_user_playlog,
validate_before_send,
apply_play_effects,
# ★ 额外 JSON 合并 / 落库回查
load_extra_data,
merge_extra_data,
verify_upsert_landing,
default_user_weekly_data,
default_user_2p_playlog,
calc_play_special,
normalize_snapshot,
wait_send_cooldown,
# 字段表
PLAYLOG_FIELDS,
PLAYLOG_BOOL_FIELDS,
PLAYLOG_STRING_FIELDS,
JUDGE_TYPES,
JUDGE_BOXES,
USER_DATA_DROP_KEYS,
USER_OPTION_DROP_KEYS,
USER_CHARACTER_KEEP_KEYS,
USER_MUSIC_DETAIL_DROP_KEYS,
USER_CHARGE_DROP_KEYS,
USER_MISSION_DROP_KEYS,
)
from .get_need_user_data import (
GetNeedUserData,
save_snapshot,
load_snapshot,
summarize_snapshot,
DEFAULT_SNAPSHOT_NODES,
# ★ 用户数据落盘(<工程根>/data/<userId>.json)
PROJECT_ROOT,
DATA_DIR,
user_data_path,
save_user_data,
load_user_data,
list_saved_user_ids,
)
from .upsert_user_chargelog import (
UpsertUserChargelog,
ChargelogConfirmError,
ChargelogGuardError,
UserChargeVO,
UserChargelogVO,
UserChargelogRequestVO,
ticket_name,
ticket_price,
calc_valid_date,
parse_wall_time,
now_cst,
)
# ---------------------------------------------------------------------------
# 4) 取数公共底座
# ---------------------------------------------------------------------------
from .user_getter_common import (
EmptyRequestVO as GetterEmptyRequestVO,
UserIdRequestVO as GetterUserIdRequestVO,
UserIdPageRequestVO,
UserLoginBonusRequestVO,
UserItemRequestVO,
UserMusicRequestVO,
UserCourseRequestVO,
UserFavoriteRequestVO,
UserFavoriteItemRequestVO,
UserShopStockRequestVO,
UserRivalRequestVO,
UserRivalMusicRequestVO,
get_all_pages,
ITEM_KINDS,
ITEM_NEXT_INDEX_FACTOR,
FAVORITE_ITEM_KINDS,
RIVAL_MUSIC_LEVELS,
)
# ---------------------------------------------------------------------------
# 5) 取数脚本(一个接口一个脚本)
# ---------------------------------------------------------------------------
from .get_user_data import GetUserData
from .get_user_extend import GetUserExtend
from .get_user_option import GetUserOption
from .get_user_character import GetUserCharacter
from .get_user_ghost import GetUserGhost
from .get_user_map import GetUserMap, GetUserMapAll
from .get_user_login_bonus import GetUserLoginBonus, GetUserLoginBonusAll
from .get_user_rating import GetUserRating
from .get_user_item import GetUserItem, GetUserItemAll
from .get_user_music import GetUserMusicDetail, GetUserMusicDetailAll
from .get_user_course import GetUserCourse, GetUserCourseAll
from .get_user_charge import GetUserCharge
from .get_user_favorite import GetUserFavorite, GetUserFavoriteAll
from .get_user_activity import GetUserActivity
from .get_user_mission import GetUserMissionData
from .get_user_intimate import GetUserIntimate
from .get_user_shop_stock import GetUserShopStock
from .get_user_favorite_item import (
GetUserFavoriteItem,
GetUserFavoriteItemAll,
FAVORITE_ITEM_KIND_MUSIC,
FAVORITE_ITEM_KIND_RIVAL,
)
from .get_user_rival import GetUserRivalData, GetUserRivalMusic, GetUserRivalMusicAll
from .get_user_friend_bonus import GetUserFriendBonus, extract_gift_points
from .get_user_kaleidx_scope import GetUserKaleidxScope, GetGameKaleidxScope
from .get_user_region import GetUserRegion
from .get_user_recommend_music import GetUserRecommendRateMusic, GetUserRecommendSelectMusic
from .get_user_new_item import GetUserNewItemList, UserNewItemListRequestVO
from .get_game_ranking import GetGameRanking, GameRankingRequestVO
from .get_game_event import GetGameEvent, GameEventRequestVO
from .get_game_charge import GetGameCharge, GameChargeRequestVO
from .get_game_weekly_data import GetGameWeeklyData
from .get_game_tournament_info import GetGameTournamentInfo
from .get_game_ng_music_id import GetGameNgMusicId
# ---------------------------------------------------------------------------
# 6) 需要日志跟踪的 api 函数(新增 api 时把函数名加到这里)
# ---------------------------------------------------------------------------
_API_FUNCS = (
# --- 会话链路 ---
"ParseQRCode",
"GetGameSettings",
"Ping",
"GetUserPreview",
"UserLogin",
"UserLogout",
# --- 上传成绩 ---
"UpsertUserAll",
"build_play_from_config",
"derive_play_characters",
"merge_extra_data",
"verify_upsert_landing",
"build_user_all",
# --- 购买功能票 ---
"UpsertUserChargelog",
"ticket_name",
"ticket_price",
"calc_valid_date",
"build_user_playlog",
"build_user_game_playlog",
"validate_user_playlog",
"validate_before_send",
"apply_play_effects",
"build_post_play_user_data",
"build_delta",
"build_favorite_delta",
"normalize_snapshot",
"GetNeedUserData",
"summarize_snapshot",
"GetUserNewItemList",
# --- 取数:单接口 ---
"GetUserData", # GetUserDataApi
"GetUserExtend", # GetUserExtendApi
"GetUserOption", # GetUserOptionApi
"GetUserCharacter", # GetUserCharacterApi
"GetUserGhost", # GetUserGhostApi
"GetUserMap", # GetUserMapApi(单页)
"GetUserMapAll", # GetUserMapApi(全量)
"GetUserLoginBonus", # GetUserLoginBonusApi(单页)
"GetUserLoginBonusAll", # GetUserLoginBonusApi(全量)
"GetUserRating", # GetUserRatingApi
"GetUserItem", # GetUserItemApi(单类)
"GetUserItemAll", # GetUserItemApi(全量)
"GetUserMusicDetail", # GetUserMusicApi(单页)
"GetUserMusicDetailAll", # GetUserMusicApi(全量)
"GetUserCourse", # GetUserCourseApi(单页)
"GetUserCourseAll", # GetUserCourseApi(全量)
"GetUserCharge", # GetUserChargeApi
"GetUserFavorite", # GetUserFavoriteApi(单类)
"GetUserFavoriteAll", # GetUserFavoriteApi(全量)
"GetUserActivity", # GetUserActivityApi
"GetUserMissionData", # GetUserMissionDataApi
"GetUserIntimate", # GetUserIntimateApi
"GetUserShopStock", # GetUserShopStockApi
"GetUserFavoriteItem", # GetUserFavoriteItemApi(单页)
"GetUserFavoriteItemAll", # GetUserFavoriteItemApi(全量)
"GetUserRivalData", # GetUserRivalDataApi
"GetUserRivalMusic", # GetUserRivalMusicApi(单页)
"GetUserRivalMusicAll", # GetUserRivalMusicApi(全量)
"GetUserFriendBonus", # GetUserFriendBonusApi
"GetUserKaleidxScope", # GetUserKaleidxScopeApi
"GetGameKaleidxScope", # GetGameKaleidxScopeApi
"GetUserRegion", # GetUserRegionApi
"GetUserRecommendRateMusic", # GetUserRecommendRateMusicApi
"GetUserRecommendSelectMusic", # GetUserRecommendSelectMusicApi
"GetUserNewItemList", # GetUserNewItemListApi
# --- 取数:游戏侧 ---
"GetGameRanking", # GetGameRankingApi
"GetGameEvent", # GetGameEventApi
"GetGameCharge", # GetGameChargeApi
"GetGameWeeklyData", # GetGameWeeklyDataApi
"GetGameTournamentInfo", # GetGameTournamentInfoApi
"GetGameNgMusicId", # GetGameNgMusicIdApi
)
# ---------------------------------------------------------------------------
# 7) 导入即包装:保证 from api import X 拿到的是带日志的版本
# ---------------------------------------------------------------------------
autowrap(globals(), _API_FUNCS)
# ---------------------------------------------------------------------------
# 8) 统一导出
# ---------------------------------------------------------------------------
__all__ = [
# ---- 日志:会话 ----
"setup_logging", "teardown_logging",
# ---- 日志:自动跟踪 ----
"autowrap", "get_called_apis",
# ---- 日志:模式 ----
"get_level", "set_level", "is_debug", "LEVEL_INFO", "LEVEL_DEBUG",
# ---- 日志:装饰器 / 兼容 ----
"api_log", "get_logger",
# ---- 日志:流程 ----
"log_info", "log_step", "log_result", "log_warning", "log_error",
"log_section", "log_field",
# ---- 日志:收发数据 ----
"log_debug", "log_request", "log_response", "log_payload",
# ---- 网络核心 ----
"MaimaiNetClient", "MaimaiNetError", "get_default_client", "close_default_client",
"request", "request_dict", "request_vo",
"obfuscate_api_name", "build_api_url", "build_user_agent", "adler32",
"aes_encrypt", "aes_decrypt", "deflate_compress", "deflate_decompress",
"vo_to_json", "vo_from_json",
"local_utc_offset_seconds", "login_date_time_now",
"EmptyRequestVO", "UserIdRequestVO", "ReturnCodeVO",
# ---- 会话链路 ----
"ParseQRCode",
"GetGameSettings", "GameSetting", "GameSettingRequestVO", "GameSettingResponseVO",
"is_maintenance", "is_ping_disabled",
"Ping",
"GetUserPreview", "UserPreviewRequestVO", "UserPreviewResponseVO",
"UserLogin", "UserLoginRequestVO", "UserLoginResponseVO",
"UserLogout", "LogoutType", "DelayLog", "RequestAPI",
"UserLogoutRequestVO", "UserLogoutRequest2VO", "UserLogoutResponseVO",
"create_empty_delay_log", "create_delay_log_from_stats", "DELAY_LOG_SLOTS",
# ---- 上传成绩 ----
"UpsertUserAll", "PlayData", "build_play_from_config", "derive_play_characters",
"load_extra_data", "merge_extra_data", "verify_upsert_landing",
# ---- 购买功能票 ----
"UpsertUserChargelog", "ChargelogConfirmError", "ChargelogGuardError",
"UserChargeVO", "UserChargelogVO", "UserChargelogRequestVO",
"ticket_name", "ticket_price", "calc_valid_date", "parse_wall_time", "now_cst",
"UserAllRequestVO", "UpsertResponseVO",
"UpsertUserAllError", "ConfirmRequiredError", "PatchError",
"NODE_TYPES", "NODE_ORDER", "BITS_TO_ARRAY", "ARRAY_TO_BITS",
"DIFF_PRIMARY_KEYS", "MAY_BE_EMPTY_NODES", "DEFAULT_EMPTY_NODES",
"empty_node", "empty_user_all", "coerce_node_value", "sync_bits_to_arrays",
"build_delta", "build_favorite_delta", "build_user_all",
"build_user_playlog", "build_user_game_playlog", "build_post_play_user_data",
"validate_user_playlog", "validate_before_send", "apply_play_effects",
"default_user_weekly_data", "default_user_2p_playlog", "calc_play_special",
"normalize_snapshot", "wait_send_cooldown",
"PLAYLOG_FIELDS", "PLAYLOG_BOOL_FIELDS", "PLAYLOG_STRING_FIELDS",
"JUDGE_TYPES", "JUDGE_BOXES",
"USER_DATA_DROP_KEYS", "USER_OPTION_DROP_KEYS", "USER_CHARACTER_KEEP_KEYS",
"USER_MUSIC_DETAIL_DROP_KEYS", "USER_CHARGE_DROP_KEYS", "USER_MISSION_DROP_KEYS",
# ---- 快照编排 ----
"GetNeedUserData", "save_snapshot", "load_snapshot",
"summarize_snapshot", "DEFAULT_SNAPSHOT_NODES",
"PROJECT_ROOT", "DATA_DIR", "user_data_path",
"save_user_data", "load_user_data", "list_saved_user_ids",
# ---- 取数公共底座 ----
"GetterEmptyRequestVO", "GetterUserIdRequestVO", "UserIdPageRequestVO",
"UserLoginBonusRequestVO", "UserItemRequestVO", "UserMusicRequestVO",
"UserCourseRequestVO", "UserFavoriteRequestVO", "UserFavoriteItemRequestVO",
"UserShopStockRequestVO", "UserRivalRequestVO", "UserRivalMusicRequestVO",
"get_all_pages",
"ITEM_KINDS", "ITEM_NEXT_INDEX_FACTOR", "FAVORITE_ITEM_KINDS", "RIVAL_MUSIC_LEVELS",
# ---- 取数脚本 ----
"GetUserData", "GetUserExtend", "GetUserOption", "GetUserCharacter", "GetUserGhost",
"GetUserMap", "GetUserMapAll",
"GetUserLoginBonus", "GetUserLoginBonusAll",
"GetUserRating",
"GetUserItem", "GetUserItemAll",
"GetUserMusicDetail", "GetUserMusicDetailAll",
"GetUserCourse", "GetUserCourseAll",
"GetUserCharge",
"GetUserFavorite", "GetUserFavoriteAll",
"GetUserActivity", "GetUserMissionData", "GetUserIntimate", "GetUserShopStock",
"GetUserFavoriteItem", "GetUserFavoriteItemAll",
"FAVORITE_ITEM_KIND_MUSIC", "FAVORITE_ITEM_KIND_RIVAL",
"GetUserRivalData", "GetUserRivalMusic", "GetUserRivalMusicAll",
"GetUserFriendBonus", "extract_gift_points",
"GetUserKaleidxScope", "GetGameKaleidxScope",
"GetUserRegion",
"GetUserRecommendRateMusic", "GetUserRecommendSelectMusic",
"GetUserNewItemList", "UserNewItemListRequestVO",
"GetGameRanking", "GameRankingRequestVO",
"GetGameEvent", "GameEventRequestVO",
"GetGameCharge", "GameChargeRequestVO",
"GetGameWeeklyData", "GetGameTournamentInfo", "GetGameNgMusicId",
]