# -*- coding: utf-8 -*- """ api 包 —— 统一导出 ================================================================================ 主脚本只需要 from api import ... 就能拿到全部功能。 ★ 本文件在导入时就给下面 _API_FUNCS 里列出的每个函数套上「日志外壳」, 所以主脚本拿到的已经是带日志的版本 —— 调用时会自动产出: === ParseQRCode 开始运行 === [接口说明] 解析二维码并换取 userId 与 token。 [位置参数] 'SGWCMAID2610022219463A297AF4CA...' [运行结果] 成功 tuple(2 项)(耗时 412 ms) === ParseQRCode 运行结束 === 主脚本**不需要**写装饰器,也不需要自己埋点。 -------------------------------------------------------------------------------- 目录结构(一个 api 一个脚本) -------------------------------------------------------------------------------- 基础设施 LogSetup.py 统一日志(INFO / DEBUG 双模式) MaimaiNet.py 网络核心(AES / deflate / URL 混淆 / Cookie) UserGetterCommon.py 取数脚本公共底座(请求 VO / _get / 翻页) ChargeGuard.py ★ 买票前置闸门:买票前必须先跑过 GetUserCharge 会话链路 Chime.py 扫码登录 -> userId + token GetGameSettings.py GetGameSettingApi(游戏设置) Ping.py 心跳探活 GetUserPreview.py GetUserPreviewApi(用户预览) UserLogin.py UserLoginApi(正式登录 -> loginId + loginDateTime) UserLogout.py UserLogoutApi(登出) 上传 / 结算(有副作用的接口) UpsertUserAll.py ★ UpsertUserAllApi(上传成绩 + 解锁歌曲/解禁难度) UpsertUserChargelog.py UpsertUserChargelogApi(购买功能票) GetNeedUserData.py ★ 结算快照编排(统一调用下面的取数脚本), 并把结果落盘到 <工程根>/data/.json ★ 命名约定:服务端 API 名里带 Get 的,**脚本名与函数名一律带 get / Get** (不要模棱两可)。所以下面这些文件全是 get_ 开头。 取数 —— GetUser*(一个接口一个脚本) GetUserData.py GetUserDataApi GetUserExtend.py GetUserExtendApi GetUserOption.py GetUserOptionApi GetUserCharacter.py GetUserCharacterApi GetUserGhost.py GetUserGhostApi GetUserMap.py GetUserMapApi GetUserLoginBonus.py GetUserLoginBonusApi GetUserRating.py GetUserRatingApi GetUserItem.py GetUserItemApi GetUserMusic.py GetUserMusicApi GetUserCourse.py GetUserCourseApi GetUserCharge.py GetUserChargeApi GetUserFavorite.py GetUserFavoriteApi GetUserActivity.py GetUserActivityApi GetUserMission.py GetUserMissionDataApi GetUserIntimate.py GetUserIntimateApi GetUserShopStock.py GetUserShopStockApi GetUserFavoriteItem.py GetUserFavoriteItemApi GetUserRival.py GetUserRivalDataApi / GetUserRivalMusicApi GetUserFriendBonus.py GetUserFriendBonusApi GetUserKaleidxScope.py GetUserKaleidxScopeApi / GetGameKaleidxScopeApi GetUserRegion.py GetUserRegionApi GetUserRecommendMusic.py GetUserRecommendRateMusicApi / GetUserRecommendSelectMusicApi GetUserNewItem.py GetUserNewItemListApi 取数 —— GetGame* GetGameSettings.py GetGameSettingApi GetGameCharge.py GetGameChargeApi """ from .LogSetup 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 .MaimaiNet import ( # 协议常量(原在 config.py,已下沉到 MaimaiNet.py) BASE_URL, AES_KEY, AES_IV, OBFUSCATE_PARAM, 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, # aimedb / QR 常量(原在 config.py,已下沉到 Chime.py) AIMEDB_HOST, AIMEDB_PORT, AIMEDB_PATH, QR_SIGN_KEY, QR_OPEN_GAME_ID, QR_TITLE_KEY, QR_USER_AGENT, ) from .GetGameSettings import ( GetGameSettings, GameSetting, GameSettingRequestVO, GameSettingResponseVO, is_maintenance, is_ping_disabled, ) from .Ping import Ping from .GetUserPreview 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 .UpsertUserAll import ( UpsertUserAll, PlayData, build_play_from_config, derive_play_characters, derive_play_rating, derive_play_grade, find_music_detail, PLAY_SPECIAL_NUM, PLAY_LOCAL_PLAY_COUNT, PLAY_AFTER_GRADE_RANK, DERIVE_GRADE_FROM_MUSIC_DETAIL, 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, # ★ 歌曲解锁(解禁):写进 userItemList 的 itemKind 5/6/7 build_unlock_items, ITEM_KIND_MUSIC_UNLOCK, ITEM_KIND_MUSIC_UNLOCK_MASTER, ITEM_KIND_MUSIC_UNLOCK_REMASTER, ITEM_KIND_MUSIC_UNLOCK_STRONG, UNLOCK_MASTER_MIN_MUSIC_ID, 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 .GetNeedUserData import ( GetNeedUserData, save_snapshot, load_snapshot, summarize_snapshot, DEFAULT_SNAPSHOT_NODES, # ★ 用户数据落盘(<工程根>/data/.json) PROJECT_ROOT, DATA_DIR, user_data_path, save_user_data, load_user_data, list_saved_user_ids, ) # --------------------------------------------------------------------------- # ★ 买票前置闸门:GetUserCharge 必须先跑过(见 api/ChargeGuard.py) # --------------------------------------------------------------------------- from .ChargeGuard import ( CHARGE_READ_FRESH_SEC, has_fresh_read, held_charges, last_charge_list, last_read_age, note_charge_purchase, note_user_charge_read, purchased_charge_ids, reset as reset_charge_guard, ) from .UpsertUserChargelog import ( # 票券主数据(原在 config.py,已下沉到 UpsertUserChargelog.py) TICKET_CREDIT_NUM, TICKET_NAMES, PAID_TICKET_IDS, TICKET_VALID_HOUR_OFFSET, TICKET_VALID_DAYS, UpsertUserChargelog, ChargelogConfirmError, ChargelogGuardError, UserChargeVO, UserChargelogVO, UserChargelogRequestVO, ticket_name, ticket_price, calc_valid_date, parse_wall_time, now_cst, ) # --------------------------------------------------------------------------- # 4) 取数公共底座 # --------------------------------------------------------------------------- from .UserGetterCommon 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 .GetUserData import GetUserData from .GetUserExtend import GetUserExtend from .GetUserOption import GetUserOption from .GetUserCharacter import GetUserCharacter from .GetUserGhost import GetUserGhost from .GetUserMap import GetUserMap, GetUserMapAll from .GetUserLoginBonus import GetUserLoginBonus, GetUserLoginBonusAll from .GetUserRating import GetUserRating from .GetUserItem import GetUserItem, GetUserItemAll from .GetUserMusic import GetUserMusicDetail, GetUserMusicDetailAll from .GetUserCourse import GetUserCourse, GetUserCourseAll from .GetUserCharge import GetUserCharge from .GetUserFavorite import GetUserFavorite, GetUserFavoriteAll from .GetUserActivity import GetUserActivity from .GetUserMission import GetUserMissionData from .GetUserIntimate import GetUserIntimate from .GetUserShopStock import GetUserShopStock from .GetUserFavoriteItem import ( GetUserFavoriteItem, GetUserFavoriteItemAll, FAVORITE_ITEM_KIND_MUSIC, FAVORITE_ITEM_KIND_RIVAL, ) from .GetUserRival import GetUserRivalData, GetUserRivalMusic, GetUserRivalMusicAll from .GetUserFriendBonus import GetUserFriendBonus, extract_gift_points from .GetUserKaleidxScope import GetUserKaleidxScope, GetGameKaleidxScope from .GetUserRegion import GetUserRegion from .GetUserRecommendMusic import GetUserRecommendRateMusic, GetUserRecommendSelectMusic from .GetUserNewItem import GetUserNewItemList, UserNewItemListRequestVO from .GetGameCharge import GetGameCharge, GameChargeRequestVO # --------------------------------------------------------------------------- # 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", "build_unlock_items", # --- 购买功能票 --- "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 # --- 取数:游戏侧 --- "GetGameCharge", # GetGameChargeApi ) # --------------------------------------------------------------------------- # 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", # ---- 歌曲解锁(解禁)---- "build_unlock_items", "UNLOCK_MASTER_MIN_MUSIC_ID", "ITEM_KIND_MUSIC_UNLOCK", "ITEM_KIND_MUSIC_UNLOCK_MASTER", "ITEM_KIND_MUSIC_UNLOCK_REMASTER", "ITEM_KIND_MUSIC_UNLOCK_STRONG", # ---- 购买功能票 ---- "UpsertUserChargelog", "ChargelogConfirmError", "ChargelogGuardError", # ---- 买票前置闸门(GetUserCharge 必须先跑过)---- "CHARGE_READ_FRESH_SEC", "has_fresh_read", "held_charges", "last_charge_list", "last_read_age", "note_charge_purchase", "note_user_charge_read", "purchased_charge_ids", "reset_charge_guard", "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", "GetGameCharge", "GameChargeRequestVO", # --- 协议常量(原在 config.py,已下沉到各 api 模块)--- "BASE_URL", "AES_KEY", "AES_IV", "OBFUSCATE_PARAM", "AIMEDB_HOST", "AIMEDB_PORT", "AIMEDB_PATH", "QR_SIGN_KEY", "QR_OPEN_GAME_ID", "QR_TITLE_KEY", "QR_USER_AGENT", "TICKET_CREDIT_NUM", "TICKET_NAMES", "PAID_TICKET_IDS", "TICKET_VALID_HOUR_OFFSET", "TICKET_VALID_DAYS", ]