mirror of
https://github.com/N1ngYu/SaltBot.git
synced 2025-09-28 08:42:40 +08:00
Add: Separate Plugin
This commit is contained in:
499
nonebot_plugin_maimai_helper/helper/simai.py
Normal file
499
nonebot_plugin_maimai_helper/helper/simai.py
Normal file
@@ -0,0 +1,499 @@
|
||||
import hashlib
|
||||
import random
|
||||
import re
|
||||
|
||||
import time
|
||||
import nonebot
|
||||
from datetime import datetime, timedelta
|
||||
from nonebot.log import logger
|
||||
|
||||
import requests
|
||||
|
||||
from nonebot_plugin_maimai_helper.util.net.HTTPRequest import HTTPRequest
|
||||
from nonebot_plugin_maimai_helper.data import ticket_define, region_map
|
||||
from nonebot_plugin_maimai_helper.util.utils import find_chara_levels, find_chara_awakening
|
||||
from nonebot_plugin_maimai_helper.manager.game_data import GameDataManager
|
||||
|
||||
chara_manager = GameDataManager("chara")
|
||||
title_manager = GameDataManager("title")
|
||||
frame_manager = GameDataManager("frame")
|
||||
plate_manager = GameDataManager("plate")
|
||||
partner_manager = GameDataManager("partner")
|
||||
icon_manager = GameDataManager("icon")
|
||||
|
||||
|
||||
config = nonebot.get_driver().config
|
||||
dateTime_constant = getattr(config, 'dateTime_constant', 114514)
|
||||
region_id = getattr(config, 'region_id', 114514)
|
||||
placeId = getattr(config, 'place_id', 114514)
|
||||
clientId = getattr(config, 'client_id', 'ABCDEFG')
|
||||
chimeSalt = getattr(config, 'chime_salt', 'PArBXE')
|
||||
chimeHost = getattr(config, 'chime_host', 'localhost')
|
||||
aimeHost = getattr(config, 'aime_host', 'http://localhost')
|
||||
|
||||
|
||||
def get_user_music_details(uid: int):
|
||||
req = HTTPRequest(uid)
|
||||
data = req.Request("GetUserMusicApiMaimaiChn", {"userId": uid, "nextIndex": 0, "maxCount": 2147483647})
|
||||
return [detail for music in data["userMusicList"] for detail in music["userMusicDetailList"]]
|
||||
|
||||
|
||||
def get_preview(uid):
|
||||
result = {"is_success": False, "is_error": False, "user_id": uid, "data": {}, "msg_body": "",
|
||||
"is_in_whitelist": False}
|
||||
login_dict = {
|
||||
"userId": uid,
|
||||
"accessCode": "",
|
||||
"regionId": region_id,
|
||||
"placeId": placeId,
|
||||
"clientId": clientId,
|
||||
"dateTime": dateTime_constant,
|
||||
"isContinue": False,
|
||||
"genericFlag": 0
|
||||
}
|
||||
request = HTTPRequest(uid=uid)
|
||||
logger.debug("开始获取用户数据")
|
||||
preview = request.Request("GetUserPreviewApiMaimaiChn", login_dict)
|
||||
preview["iconName"] = icon_manager.get_resource(preview["iconId"])
|
||||
result["data"] = preview
|
||||
result["is_success"] = True
|
||||
result["is_error"] = False
|
||||
result["msg_body"] = "成功"
|
||||
return result
|
||||
|
||||
|
||||
def get_preview_detailed(uid):
|
||||
result = {"is_success": False, "is_error": False, "user_id": uid, "data": {}, "msg_body": "",
|
||||
"is_in_whitelist": False, "is_got_qr_code": False}
|
||||
login_dict = {
|
||||
"userId": uid,
|
||||
"accessCode": "",
|
||||
"regionId": region_id,
|
||||
"placeId": placeId,
|
||||
"clientId": clientId,
|
||||
"dateTime": dateTime_constant,
|
||||
"isContinue": False,
|
||||
"genericFlag": 0,
|
||||
"nextIndex": 0,
|
||||
"maxCount": 20
|
||||
}
|
||||
request = HTTPRequest(uid=uid)
|
||||
logger.debug("开始获取用户数据")
|
||||
preview = request.Request("GetUserPreviewApiMaimaiChn", login_dict)
|
||||
if not preview["isLogin"]:
|
||||
logger.debug("开始登入用户账号")
|
||||
login = request.Request("UserLoginApiMaimaiChn", login_dict)
|
||||
if login["returnCode"] != 1:
|
||||
result["is_got_qr_code"] = False
|
||||
result["msg_body"] = "请在微信「舞萌 | 中二」公众号上点击一次「玩家二维码」按钮后再试一遍吧~"
|
||||
logger.error("登入失败,请在微信「舞萌 | 中二」公众号上点击一次「玩家二维码」按钮后再试一遍吧~")
|
||||
return result
|
||||
logger.success("登入成功")
|
||||
result["is_got_qr_code"] = True
|
||||
else:
|
||||
result["is_got_qr_code"] = True
|
||||
result["is_already_login"] = True
|
||||
logger.debug("开始获取用户详细信息")
|
||||
user_data = request.Request("GetUserDataApiMaimaiChn", login_dict)
|
||||
logger.debug("开始获取用户旅行伙伴信息")
|
||||
character_list = request.Request("GetUserCharacterApiMaimaiChn", login_dict)["userCharacterList"]
|
||||
|
||||
player_info = user_data["userData"]
|
||||
player_info["charaLevel"] = find_chara_levels(character_list, user_data["userData"]["charaSlot"])
|
||||
player_info["charaAwakening"] = find_chara_awakening(character_list, user_data["userData"]["charaSlot"])
|
||||
player_info["charaName"] = [chara_manager.get_resource(title_id) for title_id in user_data["userData"]["charaSlot"]]
|
||||
player_info["frameName"] = frame_manager.get_resource(user_data["userData"]["frameId"])
|
||||
player_info["plateName"] = plate_manager.get_resource(user_data["userData"]["plateId"])
|
||||
player_info["iconName"] = icon_manager.get_resource(user_data["userData"]["iconId"])
|
||||
player_info["partnerName"] = partner_manager.get_resource(user_data["userData"]["partnerId"])
|
||||
player_info["titleName"] = title_manager.get_resource(user_data["userData"]["titleId"])["title"]
|
||||
player_info["titleRare"] = title_manager.get_resource(user_data["userData"]["titleId"])["rareType"]
|
||||
player_info["classRank"] = user_data["userData"]["classRank"]
|
||||
player_info["courseRank"] = user_data["userData"]["courseRank"]
|
||||
player_info["banState"] = user_data["banState"]
|
||||
player_info["loginState"] = preview["isLogin"]
|
||||
player_info["frameId"] = user_data["userData"]["frameId"]
|
||||
player_info["plateId"] = user_data["userData"]["plateId"]
|
||||
player_info["iconId"] = user_data["userData"]["iconId"]
|
||||
player_info["charaId"] = [(title_id)for title_id in user_data["userData"]["charaSlot"]]
|
||||
# result["userData"]
|
||||
result["data"] = player_info
|
||||
|
||||
if not preview["isLogin"]:
|
||||
logger.debug("开始登出用户账号")
|
||||
returnCode = request.Request("UserLogoutApiMaimaiChn", login_dict)['returnCode']
|
||||
retry = 1
|
||||
while returnCode != 1 and retry <= 5:
|
||||
returnCode = request.Request("UserLogoutApiMaimaiChn", login_dict)['returnCode']
|
||||
retry += 1
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def send_ticket(uid, ticket_id):
|
||||
result = {"is_success": False, "is_got_qr_code": True, "is_already_login": False, "is_already_had_ticket": False,
|
||||
"is_error": False, "user_id": uid, "data": {}, "msg_body": ""}
|
||||
login_dict = {
|
||||
"userId": uid,
|
||||
"accessCode": "",
|
||||
"regionId": region_id,
|
||||
"placeId": placeId,
|
||||
"clientId": clientId,
|
||||
"dateTime": dateTime_constant,
|
||||
"isContinue": False,
|
||||
"genericFlag": 0
|
||||
}
|
||||
|
||||
request = HTTPRequest(uid=uid)
|
||||
logger.debug("开始获取用户信息")
|
||||
preview = request.Request("GetUserPreviewApiMaimaiChn", login_dict)
|
||||
if preview["isLogin"]:
|
||||
result["is_already_login"] = True
|
||||
result["msg_body"] = "当前用户已上机,请先下机然后再试一遍"
|
||||
return result
|
||||
else:
|
||||
logger.debug("开始登入用户账户")
|
||||
login = request.Request("UserLoginApiMaimaiChn", login_dict)
|
||||
if login["returnCode"] != 1:
|
||||
result["is_got_qr_code"] = False
|
||||
result["msg_body"] = "请在微信「舞萌 | 中二」公众号上点击一次「玩家二维码」按钮后再试一遍吧~"
|
||||
return result
|
||||
user_data = request.Request("GetUserDataApiMaimaiChn", login_dict)
|
||||
charges = request.Request("GetUserChargeApiMaimaiChn", login_dict)
|
||||
|
||||
had_ticket = False
|
||||
if charges["userChargeList"]:
|
||||
for charge in charges["userChargeList"]:
|
||||
if charge["stock"] > 0 and charge["chargeId"] == int(ticket_id):
|
||||
had_ticket = True
|
||||
result["is_already_had_ticket"] = True
|
||||
result["msg_body"] = "无法重复发放跑图票"
|
||||
break
|
||||
|
||||
if not had_ticket:
|
||||
date_time = datetime.now()
|
||||
timestamp_str = date_time.strftime('%Y-%m-%d %H:%M:%S.0')
|
||||
expire_timestamp = (date_time + timedelta(days=90)).strftime('%Y-%m-%d 04:00:00')
|
||||
ticket_dict = {
|
||||
"userId": uid,
|
||||
"userChargelog": {
|
||||
"chargeId": ticket_id,
|
||||
"price": ticket_define[ticket_id]["cost"],
|
||||
"purchaseDate": timestamp_str,
|
||||
"playCount": int(user_data["userData"]["playCount"]),
|
||||
"playerRating": int(user_data["userData"]["playerRating"]),
|
||||
"placeId": placeId,
|
||||
"regionId": region_id,
|
||||
"clientId": clientId,
|
||||
},
|
||||
"userCharge": {
|
||||
"chargeId": ticket_id,
|
||||
"stock": 1,
|
||||
"purchaseDate": timestamp_str,
|
||||
"validDate": expire_timestamp
|
||||
}
|
||||
}
|
||||
|
||||
try:
|
||||
logger.debug("开始充值功能票")
|
||||
result["data"] = request.Request("UpsertUserChargelogApiMaimaiChn", ticket_dict)
|
||||
result["is_success"] = True
|
||||
result["msg_body"] = "成功"
|
||||
except Exception as e:
|
||||
print(e.with_traceback(None))
|
||||
result["is_error"] = True
|
||||
result["msg_body"] = f"未知错误:{e.with_traceback(None)}"
|
||||
|
||||
if not preview["isLogin"]:
|
||||
logger.debug("开始登出用户账户")
|
||||
returnCode = request.Request("UserLogoutApiMaimaiChn", login_dict)['returnCode']
|
||||
retry = 1
|
||||
while returnCode != 1 and retry <= 5:
|
||||
returnCode = request.Request("UserLogoutApiMaimaiChn", login_dict)['returnCode']
|
||||
retry += 1
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def logout(uid, timestamp=dateTime_constant):
|
||||
result = {"is_success": False, "is_error": False, "user_id": uid, "data":{}, "msg_body": ""}
|
||||
login_dict = {
|
||||
"userId": uid,
|
||||
"accessCode": "",
|
||||
"placeId": placeId,
|
||||
"regionId": region_id,
|
||||
"clientId": clientId,
|
||||
"dateTime": timestamp,
|
||||
"isContinue": False,
|
||||
"type": 5
|
||||
}
|
||||
try:
|
||||
request = HTTPRequest(uid=uid)
|
||||
logger.debug("开始登出用户账户")
|
||||
result["data"] = request.Request("UserLogoutApiMaimaiChn", login_dict)
|
||||
result["is_success"] = True
|
||||
result["msg_body"] = "成功"
|
||||
except Exception as e:
|
||||
e.with_traceback(None)
|
||||
result["data"] = None
|
||||
result["is_error"] = True
|
||||
result["msg_body"] = f"未知错误:{e.with_traceback(None)}"
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def login(uid, timestamp=dateTime_constant):
|
||||
result = {"is_success": False, "is_error": False, "user_id": uid, "data": {}, "msg_body": ""}
|
||||
login_dict = {
|
||||
"userId": uid,
|
||||
"accessCode": "",
|
||||
"regionId": region_id,
|
||||
"placeId": placeId,
|
||||
"clientId": clientId,
|
||||
"dateTime": timestamp,
|
||||
"isContinue": False,
|
||||
"genericFlag": 0
|
||||
}
|
||||
|
||||
request = HTTPRequest(uid=uid)
|
||||
logger.debug("开始获取用户信息")
|
||||
preview = request.Request("GetUserPreviewApiMaimaiChn", login_dict)
|
||||
if preview["isLogin"]:
|
||||
result["data"] = None
|
||||
result["is_already_login"] = True
|
||||
result["msg_body"] = "当前用户已上机,请先下机然后再试一遍"
|
||||
return result
|
||||
else:
|
||||
logger.debug("开始登入用户账户")
|
||||
login = request.Request("UserLoginApiMaimaiChn", login_dict)
|
||||
if login["returnCode"] != 1:
|
||||
result["data"] = login
|
||||
result["is_got_qr_code"] = False
|
||||
result["msg_body"] = "请在微信「舞萌 | 中二」公众号上点击一次「玩家二维码」按钮后再试一遍吧~"
|
||||
return result
|
||||
else:
|
||||
result["data"] = login
|
||||
result["is_success"] = True
|
||||
result["msg_body"] = "成功"
|
||||
return result
|
||||
|
||||
|
||||
def dump_user_all(uid):
|
||||
result = {"is_success": False, "is_got_qr_code": True, "is_error": False, "user_id": uid, "data": {},
|
||||
"msg_body": ""}
|
||||
|
||||
available_attrs = ["UserData", "UserExtend", "UserOption", "UserCharacter", "UserMap", "UserLoginBonus",
|
||||
"UserRating", "UserItem", "UserMusic", "UserCourse", "UserCharge"]
|
||||
data = {}
|
||||
|
||||
login_dict = {
|
||||
"userId": uid,
|
||||
"accessCode": "",
|
||||
"regionId": region_id,
|
||||
"placeId": placeId,
|
||||
"clientId": clientId,
|
||||
"dateTime": dateTime_constant,
|
||||
"isContinue": False,
|
||||
"genericFlag": 0
|
||||
}
|
||||
|
||||
request = HTTPRequest(uid=uid)
|
||||
logger.debug("开始获取用户信息")
|
||||
preview = request.Request("GetUserPreviewApiMaimaiChn", login_dict)
|
||||
if not preview["isLogin"]:
|
||||
logger.debug("开始登入用户")
|
||||
login = request.Request("UserLoginApiMaimaiChn", login_dict)
|
||||
if login["returnCode"] != 1:
|
||||
result["is_got_qr_code"] = False
|
||||
result["msg_body"] = "请在微信「舞萌 | 中二」公众号上点击一次「玩家二维码」按钮后再试一遍吧~"
|
||||
return result
|
||||
else:
|
||||
result["is_already_login"] = True
|
||||
|
||||
for ava_attr in available_attrs:
|
||||
for i in range(0, 1):
|
||||
try:
|
||||
api = f"Get{ava_attr}Api"
|
||||
final_attr = ava_attr[0].lower() + ava_attr[1:]
|
||||
|
||||
query = {"userId": uid, "nextIndex": 10000000000 if final_attr == "userItem" else 0,
|
||||
"maxCount": 2147483647}
|
||||
resp = request.Request(api, datas=query)
|
||||
if final_attr in resp:
|
||||
match final_attr:
|
||||
case "userActivity":
|
||||
data["userActList"] = resp["userActivity"]["playList"] + resp["userActivity"]["musicList"]
|
||||
case _:
|
||||
data[final_attr] = resp[final_attr]
|
||||
else:
|
||||
match final_attr:
|
||||
case "userMusic":
|
||||
data["userMusicDetailList"] = []
|
||||
for music in resp["userMusicList"]:
|
||||
data["userMusicDetailList"] += music["userMusicDetailList"]
|
||||
case _:
|
||||
data[final_attr + "List"] = resp[final_attr + "List"]
|
||||
break
|
||||
except Exception as e:
|
||||
continue
|
||||
|
||||
if not preview["isLogin"]:
|
||||
logger.debug("开始登出账户")
|
||||
returnCode = request.Request("UserLogoutApiMaimaiChn", login_dict)['returnCode']
|
||||
retry = 1
|
||||
while returnCode != 1 and retry <= 5:
|
||||
returnCode = request.Request("UserLogoutApiMaimaiChn", login_dict)['returnCode']
|
||||
retry += 1
|
||||
result["is_success"] = True
|
||||
result["msg_body"] = "成功"
|
||||
result["data"] = data
|
||||
return result
|
||||
|
||||
|
||||
def query_ticket(uid):
|
||||
result = {"is_success": False, "is_error": False, "user_id": uid, "data": {}, "msg_body": ""}
|
||||
request = HTTPRequest(uid=uid)
|
||||
logger.debug("开始获取用户功能票信息")
|
||||
ticket = request.Request("GetUserChargeApiMaimaiChn", {"userId": uid})
|
||||
if not ticket["userChargeList"]:
|
||||
ticket["userChargeList"] = []
|
||||
result["data"] = ticket
|
||||
result["is_success"] = True
|
||||
result["is_error"] = False
|
||||
result["msg_body"] = "成功"
|
||||
return result
|
||||
|
||||
|
||||
def get_user_region(uid):
|
||||
result = {"is_success": False, "is_error": False, "user_id": uid, "data": {}, "msg_body": ""}
|
||||
request = HTTPRequest(uid=uid)
|
||||
logger.debug("开始获取用户登入信息")
|
||||
resp = request.Request("GetUserRegionApiMaimaiChn", {"userId": uid})
|
||||
|
||||
for i in range(len(resp["userRegionList"])):
|
||||
region_name = region_map[int(resp["userRegionList"][i]["regionId"]) - 1]
|
||||
resp["userRegionList"][i]["regionName"] = region_name
|
||||
|
||||
result["data"] = resp
|
||||
result["is_success"] = True
|
||||
result["is_error"] = False
|
||||
result["msg_body"] = "成功"
|
||||
return result
|
||||
|
||||
|
||||
def get_user_id_by_qr(qr_code):
|
||||
if not (qr_code.startswith("SGWCMAID") and len(qr_code) == 84 and bool(re.match(r'^[0-9A-F]+$', qr_code[20:]))):
|
||||
return {
|
||||
"userID": 0,
|
||||
"errorID": 99,
|
||||
"timestamp": datetime.now().strftime("%Y%m%d%H%M%S")[2:],
|
||||
"key": ""
|
||||
}
|
||||
return get_user_id(qr_code[20:])
|
||||
|
||||
|
||||
def get_user_id(qr_code):
|
||||
GAME_ID = "MAID"
|
||||
AIME_SALT = chimeSalt
|
||||
AIME_HOST = aimeHost
|
||||
|
||||
timestamp = datetime.now().strftime("%Y%m%d%H%M%S")[2:]
|
||||
chip_id = "A63E-01E{0:08}".format(random.randint(0, 99999999))
|
||||
key = hashlib.sha256(f"{chip_id}{timestamp}{AIME_SALT}".encode()).hexdigest().upper()
|
||||
data_json = f"{{\"chipID\":\"{chip_id}\",\"openGameID\":\"{GAME_ID}\",\"key\":\"{key}\",\"qrCode\":\"{qr_code}\",\"timestamp\":\"{timestamp}\"}}"
|
||||
|
||||
logger.debug("开始获取用户USER_ID")
|
||||
resp = requests.post(f"{AIME_HOST}/wc_aime/api/get_data", data_json, headers={
|
||||
"User-Agent": "WC_AIME_LIB",
|
||||
})
|
||||
return resp.json()
|
||||
|
||||
|
||||
def get_user_music(uid):
|
||||
result = {"is_success": False, "is_error": False, "user_id": uid, "data": {}, "msg_body": "",
|
||||
"is_in_whitelist": False}
|
||||
data = {}
|
||||
dump_dict = {"userId": uid, "nextIndex": 0,
|
||||
"maxCount": 2147483647}
|
||||
request = HTTPRequest(uid=uid)
|
||||
logger.debug("开始获取用户音乐数据")
|
||||
preview = request.Request("GetUserMusicApiMaimaiChn", dump_dict)
|
||||
data["userMusicDetailList"] = []
|
||||
for music in preview["userMusicList"]:
|
||||
data["userMusicDetailList"] += music["userMusicDetailList"]
|
||||
result["data"] = data
|
||||
result["is_success"] = True
|
||||
result["is_error"] = False
|
||||
result["msg_body"] = "成功"
|
||||
return result
|
||||
|
||||
def title_ping():
|
||||
result = {"is_success": False, "is_error": False, "data": {}, "msg_body": ""}
|
||||
login_dict = {}
|
||||
try:
|
||||
request = HTTPRequest(uid=-1)
|
||||
resp = request.Request("PingMaimaiChn", login_dict)
|
||||
result["is_success"] = True
|
||||
result["msg_body"] = "成功"
|
||||
result['data'] = resp
|
||||
print(resp)
|
||||
|
||||
except Exception as e:
|
||||
e.with_traceback(None)
|
||||
result["is_error"] = True
|
||||
result["msg_body"] = f"未知错误:{e.with_traceback(None)}"
|
||||
|
||||
return result
|
||||
|
||||
|
||||
def chime_ping():
|
||||
result = {"is_success": False, "is_error": False, "data": {}, "msg_body": ""}
|
||||
headers = {
|
||||
'Connection': 'Close',
|
||||
'Host': 'at.sys-allnet.cn',
|
||||
'User-Agent': 'SDGB',
|
||||
'Content-Length': '0',
|
||||
'Content-Type': 'application/x-www-form-urlencoded',
|
||||
}
|
||||
data = {}
|
||||
url = "http://at.sys-allnet.cn/report-api/Report"
|
||||
try:
|
||||
request = requests.post(url, headers=headers, data=data)
|
||||
if request.status_code == 200:
|
||||
result['is_success'] = True
|
||||
result['data'] = request.text
|
||||
result['msg_body'] = '成功'
|
||||
else:
|
||||
result['is_error'] = True
|
||||
result['msg_body'] = request.status_code
|
||||
return result
|
||||
except Exception as e:
|
||||
result['is_error'] = True
|
||||
result['msg_body'] = e
|
||||
return result
|
||||
|
||||
|
||||
def all_net_ping():
|
||||
result = {"is_success": False, "is_error": False, "data": {}, "msg_body": ""}
|
||||
url = "http://ai.sys-allnet.cn/wc_aime/api/alive_check"
|
||||
headers = {
|
||||
'Connection': 'Keep-Alive',
|
||||
'Host': 'ai.sys-allnet.cn',
|
||||
'User-Agent': 'WC_AIME_LIB',
|
||||
'Content-Length': '0'
|
||||
}
|
||||
data = {}
|
||||
try:
|
||||
request = requests.post(url, headers=headers, data=data)
|
||||
if request.text == 'alive':
|
||||
result['is_success'] = True
|
||||
result['data'] = request.text
|
||||
result['msg_body'] = '成功'
|
||||
else:
|
||||
result['is_error'] = True
|
||||
result['msg_body'] = request.status_code
|
||||
return result
|
||||
except Exception as e:
|
||||
result['is_error'] = True
|
||||
result['msg_body'] = e
|
||||
return result
|
||||
Reference in New Issue
Block a user