This commit is contained in:
Remik1r3n 2025-06-11 09:52:45 +08:00
parent 472844474f
commit 31361541fd

View File

@ -11,6 +11,7 @@ from ctypes import c_int32
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
from Config import *
from typing import Optional
import certifi
# 舞萌DX 2024
@ -70,62 +71,53 @@ def getSDGBApiHash(api):
# 有空做一下 Hash 的彩虹表?
return hashlib.md5((api+"MaimaiChn"+ObfuscateParam).encode()).hexdigest()
def apiSDGB(data:str, targetApi:str, userAgentExtraData:str, noLog:bool=False, timeout:int=5):
def apiSDGB(
data: str,
targetApi: str,
userAgentExtraData: str,
noLog: bool = False,
timeout: int = 5,
useProxy: bool = False,
proxyUrl: Optional[str] = None
) -> str:
"""
舞萌DX 2024 API 通讯用函数
舞萌DX API 通讯用函数增强版
:param data: 请求数据
:param targetApi: 使用的 API
:param userAgentExtraData: UA 附加信息机台相关则为狗号如A63E01E9564用户相关则为 UID
:param noLog: 是否不记录日志
:param timeout: 请求超时时间
:param useProxy: 是否使用代理
:param proxyUrl: 代理地址如果使用代理
:return: 解码后的响应数据
"""
maxRetries = 3
agentExtra = str(userAgentExtraData)
aes = aes_pkcs7(AesKey,AesIV)
data = bytes(data, encoding="utf-8")
data_def = zlib.compress(data)
data_enc = aes.encrypt(data_def)
aes = aes_pkcs7(AesKey, AesIV) # Assuming aes_pkcs7, AesKey, AesIV are defined elsewhere
endpoint = "https://maimai-gm.wahlap.com:42081/Maimai2Servlet/"
r = httpx.post(
endpoint + getSDGBApiHash(targetApi),
headers = {
"User-Agent": f"{getSDGBApiHash(targetApi)}#{agentExtra}",
"Content-Type": "application/json",
"Mai-Encoding": "1.50",
"Accept-Encoding": "",
"Charset": "UTF-8",
"Content-Encoding": "deflate",
"Expect": "100-continue"
},
data = data_enc
)
resp_enc = r.content
try:
resp_def = aes.decrypt(resp_enc)
except:
resp_def = resp_enc
return zlib.decompress(resp_def).decode('utf-8')
# Begin Build
# Prepare request data
requestDataFinal = aes.encrypt(zlib.compress(data.encode('utf-8')))
# End Build
endpoint = "https://maimai-gm.wahlap.com:42081/Maimai2Servlet/"
if not noLog:
logger.debug(f"开始请求 {targetApi},以 {data}")
retries = 0
while retries < maxRetries:
try:
if useProxy:
# 使用代理
logger.debug("使用代理")
# Configure HTTP client
if useProxy and proxyUrl:
if not noLog:
logger.debug("使用代理")
httpClient = httpx.Client(proxy=proxyUrl, verify=False)
else:
# 不使用代理
logger.debug("不使用代理")
if not noLog:
logger.debug("不使用代理")
httpClient = httpx.Client(verify=False)
responseDataRaw = httpClient.post(
url=endpoint + getSDGBApiHash(targetApi),
# Send request
response = httpClient.post(
url=endpoint + getSDGBApiHash(targetApi), # Assuming getSDGBApiHash is defined
headers={
"User-Agent": f"{getSDGBApiHash(targetApi)}#{agentExtra}",
"Content-Type": "application/json",
@ -136,57 +128,69 @@ def apiSDGB(data:str, targetApi:str, userAgentExtraData:str, noLog:bool=False, t
"Expect": "100-continue"
},
content=requestDataFinal,
# 经测试,加 Verify 之后速度慢好多,因此建议选择性开
#verify=certifi.where(),
#verify=False,
timeout=timeout
)
if not noLog:
logger.info(f"{targetApi} 请求结果: {responseDataRaw.status_code}")
logger.info(f"{targetApi} 请求结果: {response.status_code}")
if responseDataRaw.status_code == 200:
logger.debug("200 OK!")
else:
errorMessage = f"请求失败: {responseDataRaw.status_code}"
if response.status_code != 200:
errorMessage = f"请求失败: {response.status_code}"
logger.error(errorMessage)
raise SDGBRequestError(errorMessage)
responseContentRaw = responseDataRaw.content
# Process response
responseContentRaw = response.content
try:
responseContentDecrypted = aes.decrypt(responseContentRaw)
logger.debug(f"成功解密响应!")
except:
logger.warning(f"解密失败,得到的原始响应: {responseContentRaw}")
if not noLog:
logger.debug("成功解密响应!")
except Exception as e:
logger.warning(f"解密失败,原始响应: {responseContentRaw}, 错误: {e}")
raise SDGBResponseError("解密失败")
try:
zlib.decompress(responseContentDecrypted).decode('utf-8')
logger.debug("成功解压响应!")
except:
logger.warning(f"无法解压,解密的原始响应: {responseContentDecrypted}")
# 检查 ResponseContentDecrypted 是否为 zlib 压缩格式
if not responseContentDecrypted.startswith(b'\x78\x9c'):
logger.warning("Not Zlib. Not decompressed.")
raise Exception(f"响应内容不是 zlib 压缩格式, 内容: {responseContentDecrypted}")
responseContentFinal = zlib.decompress(responseContentDecrypted).decode('utf-8')
if not noLog:
logger.debug("成功解压响应!")
logger.debug(f"响应: {responseContentFinal}")
return responseContentFinal
except zlib.error as e:
logger.warning(f"解压失败,原始响应: {responseContentDecrypted}, 错误: {e}")
raise SDGBResponseError("解压失败")
# If decompression fails after attempts, trigger a retry of the entire request
retries += 1
if retries < maxRetries:
logger.warning(f"解压失败,将重试请求 (第 {retries + 1}/{maxRetries} 次)")
time.sleep(2)
continue
raise SDGBResponseError("多次尝试后仍无法解压响应")
if not noLog:
logger.debug(f"响应: {responseContentDecrypted}")
return responseContentDecrypted.decode('utf-8')
# 异常处理
except SDGBRequestError as e:
# 请求格式错误,不需要重试
raise SDGBRequestError("请求格式错误")
# Request format error, no retry
logger.error(f"请求格式错误: {e}")
raise
except SDGBResponseError as e:
# 响应解析错误,这种有一定可能是我们的问题,所以只重试一次
logger.warning(f"将重试一次 Resp Err: {e}")
retries += 2
time.sleep(2)
except Exception as e:
# 其他错误,重试多次
logger.warning(f"将开始重试请求. {e}")
# Response parsing error, retry once more
logger.warning(f"响应错误,将重试: {e}")
retries += 1
time.sleep(2)
except Exception as e:
# Other errors, retry
logger.warning(f"请求失败,将重试: {e}")
retries += 1
time.sleep(2)
finally:
if 'httpClient' in locals():
httpClient.close()
raise SDGBApiError("重试多次仍然无法成功请求服务器")