maimaiDX-Api/API_AuthLite.py

126 lines
4.2 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

# All.Net AuthLite 更新获取
from Crypto.Cipher import AES
from Crypto.Util.Padding import pad
import httpx
from loguru import logger
from urllib.parse import parse_qs
import configparser as ini
def enc(key, iv, data):
cipher = AES.new(key, AES.MODE_CBC, iv)
encrypted = cipher.encrypt(data)
return encrypted
def dec(key, iv ,data):
de_cipher = AES.new(key, AES.MODE_CBC, iv)
decrypted = de_cipher.decrypt(data)
return decrypted
def getRawDelivery():
key = bytes([47, 63, 106, 111, 43, 34, 76, 38, 92, 67, 114, 57, 40, 61, 107, 71])
iv = bytes.fromhex('00000000000000000000000000000000')
content = bytes([0] * 16) + b'title_id=SDGB&title_ver=1.40&client_id=A63E01C2805'
header = bytes.fromhex('00000000000000000000000000000000')
bytes_data = pad(header + content, 16)
encrypted = enc(key, iv, bytes_data)
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 = dec(key, resp_data[:16], resp_data)
decrypted_str = decrypted[16:].decode('UTF-8').strip()
# 过滤所有控制字符
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 = {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']
# 初始化消息列表
message = []
# 获取游戏描述并去除引号
game_desc = common['GAME_DESC'].strip('"')
# 根据前缀选择消息模板和图标
prefix_icons = {
'PATCH': ('💾 游戏程序更新 ', 'PATCH_'),
'OPTION': ('📚 游戏内容更新 ', 'OPTION_')
}
icon, prefix = prefix_icons.get(game_desc.split('_')[0], ('📦 游戏更新 ', ''))
# 构建消息标题
game_title = game_desc.replace(prefix, '', 1)
message.append(f"{icon}{game_title}")
# 添加主文件的下载链接
main_file = common['INSTALL1']
main_file_name = main_file.split('/')[-1]
message.append(f"下载: \n- [{main_file_name}]({main_file})")
# 添加可选文件的下载链接(如果有)
if 'OPTIONAL' in config:
message.append("其它文件:")
optional_files = [f"- [{url.split('/')[-1]}]({url})" for _, url in config.items('OPTIONAL')]
message.extend(optional_files)
# 添加发布时间信息
release_time = common['RELEASE_TIME'].replace('T', ' ')
message.append(f"将于 {release_time} 发布。\n")
# 构建最终的消息字符串
final_message = '\n'.join(message)
logger.info(f"消息构建完成,最终的消息为:\n{final_message}")
return final_message
if __name__ == '__main__':
urlList = parseRawDelivery(getRawDelivery())
for url in urlList:
iniText = getUpdateIniFromURL(url)
message = parseUpdateIni(iniText)