mirror of
https://github.com/Remik1r3n/maimaiDX-Api.git
synced 2025-05-20 04:17:28 +08:00
118 lines
3.3 KiB
Python
118 lines
3.3 KiB
Python
# 100% Standalone 的舞萌国服 AimeDB 通讯实现
|
||
# Ver.CN1.41
|
||
# Mainline 20250203
|
||
|
||
import hashlib
|
||
import time
|
||
import requests
|
||
import json
|
||
import re
|
||
|
||
# 常量
|
||
CHIP_ID = "A63E-01E68606624"
|
||
COMMON_KEY = "XcW5FW4cPArBXEk4vzKz3CIrMuA5EVVW"
|
||
API_URL = "http://ai.sys-allnet.cn/wc_aime/api/get_data"
|
||
|
||
# 计算 SHA256
|
||
def getSHA256(input_str):
|
||
"""SHA256计算"""
|
||
return hashlib.sha256(input_str.encode('utf-8')).hexdigest().upper()
|
||
|
||
# 生成时间戳
|
||
def generateSEGATimestamp():
|
||
"""SEGA格式的 YYMMDDHHMMSS 时间戳(sb玩意)"""
|
||
return time.strftime("%y%m%d%H%M%S", time.localtime())
|
||
|
||
# 计算认证 key
|
||
def calcSEGAAimeDBAuthKey(varString:str, timestamp:str, commonKey:str="XcW5FW4cPArBXEk4vzKz3CIrMuA5EVVW") -> str:
|
||
"""计算 SEGA AimeDB 的认证 key"""
|
||
return hashlib.sha256((varString + timestamp + commonKey).encode("utf-8")).hexdigest().upper()
|
||
|
||
def apiAimeDB(qrCode):
|
||
"""AimeDB 扫码 API 实现"""
|
||
# 生成一个时间戳
|
||
timestamp = generateSEGATimestamp()
|
||
|
||
# 使用时间戳计算 key
|
||
currentKey = calcSEGAAimeDBAuthKey(CHIP_ID, timestamp, COMMON_KEY)
|
||
|
||
# 构造请求数据
|
||
payload = {
|
||
"chipID": CHIP_ID,
|
||
"openGameID": "MAID",
|
||
"key": currentKey,
|
||
"qrCode": qrCode,
|
||
"timestamp": timestamp
|
||
}
|
||
|
||
# 输出准备好的请求数据
|
||
print("Payload:", json.dumps(payload, separators=(',', ':')))
|
||
|
||
# 发送 POST 请求
|
||
headers = {
|
||
"Connection": "Keep-Alive",
|
||
"Host": API_URL.split("//")[-1].split("/")[0],
|
||
"User-Agent": "WC_AIME_LIB",
|
||
"Content-Type": "application/json",
|
||
}
|
||
response = requests.post(API_URL, data=json.dumps(payload, separators=(',', ':')), headers=headers)
|
||
|
||
# 返回服务器的响应
|
||
return response
|
||
|
||
|
||
def isSGWCFormat(input_string: str) -> bool:
|
||
"""简单检查二维码字符串是否符合格式"""
|
||
if (
|
||
len(input_string) != 84 #长度
|
||
or not input_string.startswith("SGWCMAID") #识别字
|
||
or re.match("^[0-9A-F]+$", input_string[20:]) is None #有效字符
|
||
):
|
||
return False
|
||
else:
|
||
return True
|
||
|
||
|
||
def implAimeDB(qrCode:str, isAlreadyFinal:bool=False) -> str:
|
||
"""
|
||
Aime DB 的请求的参考实现。
|
||
提供完整 QRCode 内容,返回响应的字符串(Json格式)
|
||
"""
|
||
if isAlreadyFinal:
|
||
qr_code_final = qrCode
|
||
else:
|
||
# 提取有效部分(Hash)
|
||
qr_code_final = qrCode[20:]
|
||
|
||
# 发送请求
|
||
response = apiAimeDB(qr_code_final)
|
||
|
||
# 获得结果
|
||
print("implAimeDB: StatusCode is ", response.status_code)
|
||
print("implAimeDB: Response Body is:", response.text)
|
||
return response.text
|
||
|
||
|
||
def implGetUID(qr_content:str) -> dict:
|
||
"""
|
||
包装后的 UID 扫码器实现。
|
||
此函数会返回 AimeDB 传回的 Json 转成 Python 字典的结果。
|
||
主要特点是添加了几个新的错误码(6000x)用来应对程序的错误。
|
||
"""
|
||
# 检查格式
|
||
if not isSGWCFormat(qr_content):
|
||
return {'errorID': 60001} # 二维码内容明显无效
|
||
|
||
# 发送请求并处理响应
|
||
try:
|
||
result = json.loads(implAimeDB(qr_content))
|
||
except:
|
||
return {'errorID': 60002} # 无法解码 Response 的内容
|
||
|
||
# 返回结果
|
||
return result
|
||
|
||
if __name__ == "__main__":
|
||
userInputQR = input("QRCode: ")
|
||
print(implAimeDB(userInputQR))
|