# 100% Standalone 的舞萌国服 AimeDB 通讯实现
# Ver.CN1.41
# Mainline 20250203

import hashlib
import time
import requests
import json
import re
from loguru import logger
# 常量
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))
        logger.info(f"QRScan Got Response {result}")
    except:
        return {'errorID': 60002} # 无法解码 Response 的内容
    
    # 返回结果
    return result

if __name__ == "__main__":
    userInputQR = input("QRCode: ")
    print(implAimeDB(userInputQR))