Initial commit: Add maimaiDX API web application with AimeDB scanning and logging features

This commit is contained in:
kejiz
2025-09-18 10:19:08 +08:00
commit 4e83f159f0
84 changed files with 14012 additions and 0 deletions

View File

@@ -0,0 +1,113 @@
# All.Net AuthLite 更新获取
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad, unpad
import httpx
from loguru import logger
from urllib.parse import parse_qs
import configparser as ini
LITE_AUTH_KEY = bytes(
[47, 63, 106, 111, 43, 34, 76, 38, 92, 67, 114, 57, 40, 61, 107, 71]
)
LITE_AUTH_IV = bytes.fromhex("00000000000000000000000000000000")
def auth_lite_encrypt(plaintext: str) -> bytes:
# 构造数据16字节头 + 16字节0前缀 + 明文
content = bytes(32) + plaintext.encode("utf-8")
data = content
# 填充并加密
padded_data = pad(data, AES.block_size)
cipher = AES.new(LITE_AUTH_KEY, AES.MODE_CBC, LITE_AUTH_IV)
return cipher.encrypt(padded_data)
def auth_lite_decrypt(ciphertext: bytes) -> str:
# 解密并去除填充
cipher = AES.new(LITE_AUTH_KEY, AES.MODE_CBC, LITE_AUTH_IV)
decrypted_data = unpad(cipher.decrypt(ciphertext), AES.block_size)
# 提取内容并解码
content = decrypted_data[16:] # 去除头部的16字节
return content.decode("utf-8").strip()
def getRawDelivery(title_ver: str = "1.51"):
encrypted = auth_lite_encrypt(
f"title_id=SDGB&title_ver={title_ver}&client_id=A63E01C2805"
)
r = httpx.post(
"http://at.sys-allnet.cn/net/delivery/instruction",
data=encrypted,
headers={"User-Agent": "SDGB;Windows/Lite", "Pragma": "DFI"},
)
resp_data = r.content
decrypted_str = auth_lite_decrypt(resp_data)
# 过滤所有控制字符
decrypted_str = "".join([i for i in decrypted_str if 31 < ord(i) < 127])
logger.info(f"RAW Response: {decrypted_str}")
return decrypted_str
def parseRawDelivery(deliveryStr):
"""解析 RAW 的 Delivery 字符串,返回其中的有效的 instruction URL 的列表"""
parsedResponseDict: dict[str, str] = {
key: value[0] for key, value in parse_qs(deliveryStr).items()
}
urlList = parsedResponseDict["uri"].split("|")
# 过滤掉空字符串和内容为 null 的情况
urlList = [url for url in urlList if url and url != "null"]
logger.info(f"Parsed URL List: {urlList}")
validURLs = []
for url in urlList:
# 检查是否是 HTTPS 的 URL以及是否是 txt 文件,否则忽略
if not url.startswith("https://") or not url.endswith(".txt"):
logger.warning(f"Invalid URL will be ignored: {url}")
continue
validURLs.append(url)
logger.info(f"Verified Valid URLs: {validURLs}")
return validURLs
def getUpdateIniFromURL(url):
# 发送请求
response = httpx.get(
url, headers={"User-Agent": "SDGB;Windows/Lite", "Pragma": "DFI"}
)
logger.info(f"成功自 {url} 获取更新信息")
return response.text
def parseUpdateIni(iniText):
# 解析配置
config = ini.ConfigParser(allow_no_value=True)
config.read_string(iniText)
logger.info(f"成功解析配置文件,包含的节有:{config.sections()}")
# 获取 COMMON 节的配置
common = config["COMMON"]
game_desc = common.get("GAME_DESC", "").strip('"')
release_time = common.get("RELEASE_TIME", "").replace("T", " ")
main_file = common.get("INSTALL1", "")
optional_files = []
if "OPTIONAL" in config:
for key, url in config.items("OPTIONAL"):
optional_files.append(f"{url.split('/')[-1]} {url}")
return {
"game_desc": game_desc,
"release_time": release_time,
"main_file": main_file,
"optional_files": optional_files,
}
if __name__ == "__main__":
raw = getRawDelivery("1.51")
urlList = parseRawDelivery(raw)
for url in urlList:
iniText = getUpdateIniFromURL(url)
message = parseUpdateIni(iniText)