133 lines
4.0 KiB
Python
133 lines
4.0 KiB
Python
import rapidjson as json
|
||
from loguru import logger
|
||
|
||
from API_TitleServer import (
|
||
SDGBRequestError,
|
||
SDGBApiError,
|
||
apiSDGB,
|
||
calcPlaySpecial,
|
||
)
|
||
from HelperGetUserThing import implGetUser_
|
||
from HelperUploadUserPlayLog import apiUploadUserPlaylog
|
||
from HelperUserAll import generateFullUserAll
|
||
|
||
|
||
def generateMusicData():
|
||
"""生成一份占位的音乐数据"""
|
||
return {
|
||
"musicId": 834, # PANDORA PARADOXXX
|
||
"level": 4,
|
||
"playCount": 1,
|
||
"achievement": 0,
|
||
"comboStatus": 0,
|
||
"syncStatus": 0,
|
||
"deluxscoreMax": 0,
|
||
"scoreRank": 0,
|
||
"extNum1": 0,
|
||
}
|
||
|
||
|
||
def applyUserAllPatches(userAll, patches):
|
||
"""
|
||
递归地将给定的补丁应用到用户数据的各个层次。
|
||
|
||
:param userAll: 原始用户数据
|
||
:param patches: 包含所有patch的字典
|
||
"""
|
||
for key, value in patches.items():
|
||
if (
|
||
isinstance(value, dict)
|
||
and key in userAll
|
||
and isinstance(userAll[key], dict)
|
||
):
|
||
# 如果patch的值是字典,并且userAll中对应的key也是字典,递归处理
|
||
applyUserAllPatches(userAll[key], value)
|
||
elif (
|
||
isinstance(value, list)
|
||
and key in userAll
|
||
and isinstance(userAll[key], list)
|
||
):
|
||
# 如果值是列表,进行详细的更新处理
|
||
for i, patch_item in enumerate(value):
|
||
if (
|
||
i < len(userAll[key])
|
||
and isinstance(patch_item, dict)
|
||
and isinstance(userAll[key][i], dict)
|
||
):
|
||
# 如果列表项是字典,更新字典中的字段
|
||
applyUserAllPatches(userAll[key][i], patch_item)
|
||
elif i >= len(userAll[key]):
|
||
# 如果patch的列表比userAll的列表长,追加新的元素
|
||
userAll[key].append(patch_item)
|
||
else:
|
||
# 否则直接更新或添加key
|
||
userAll[key] = value
|
||
|
||
|
||
def implFullPlayAction(
|
||
userId: int,
|
||
currentLoginTimestamp: int,
|
||
currentLoginResult,
|
||
musicData,
|
||
userAllPatches,
|
||
debugMode=False,
|
||
):
|
||
"""
|
||
一份完整的上机实现,可以打 patch 来实现各种功能
|
||
需要在外部先登录并传入登录结果
|
||
"""
|
||
|
||
# 取得 UserData
|
||
currentUserData = implGetUser_("Data", userId)
|
||
currentUserData2 = currentUserData["userData"]
|
||
|
||
# 构建并上传一个游玩记录
|
||
currentUploadUserPlaylogApiResult = apiUploadUserPlaylog(
|
||
userId, musicData, currentUserData2, currentLoginResult["loginId"]
|
||
)
|
||
logger.debug(f"上传 UserPlayLog 结果: {currentUploadUserPlaylogApiResult}")
|
||
|
||
# 构建并上传 UserAll
|
||
retries = 0
|
||
while retries < 3:
|
||
# 计算一个特殊数
|
||
currentPlaySpecial = calcPlaySpecial()
|
||
# 生成出 UserAll
|
||
currentUserAll = generateFullUserAll(
|
||
userId,
|
||
currentLoginResult,
|
||
currentLoginTimestamp,
|
||
currentUserData2,
|
||
currentPlaySpecial,
|
||
)
|
||
# 应用参数里的补丁
|
||
applyUserAllPatches(currentUserAll, userAllPatches)
|
||
|
||
# 调试模式下直接输出数据
|
||
if debugMode:
|
||
logger.debug(
|
||
"调试模式:构建出的 UserAll 数据:"
|
||
+ json.dumps(currentUserAll, indent=4)
|
||
)
|
||
logger.info("Bye!")
|
||
return
|
||
|
||
# 建构 Json 数据
|
||
data = json.dumps(currentUserAll)
|
||
# 开始上传 UserAll
|
||
try:
|
||
currentUserAllResult = json.loads(apiSDGB(data, "UpsertUserAllApi", userId))
|
||
except SDGBRequestError:
|
||
logger.warning("上传 UserAll 出现 500. 重建数据.")
|
||
retries += 1
|
||
continue
|
||
except Exception:
|
||
raise SDGBApiError("邪门错误")
|
||
# 成功上传后退出循环
|
||
break
|
||
else: # 重试次数超过3次
|
||
raise SDGBRequestError
|
||
|
||
logger.info("上机:结果:" + str(currentUserAllResult))
|
||
return currentUserAllResult
|