mirror of
https://gitea.tendokyu.moe/AttackVector/AVNetwork.git
synced 2026-09-25 15:48:09 +03:00
1519 lines
68 KiB
Python
1519 lines
68 KiB
Python
import random
|
|
import re
|
|
from misc import repair_base64IIDX
|
|
from lz77 import lz77_decompress, lz77_compress
|
|
import xmltodict
|
|
import json
|
|
import hashlib
|
|
from urllib.parse import parse_qs
|
|
from base64 import b64decode
|
|
from flask import Blueprint, request # Import necessary functions
|
|
from kbinxml import KBinXML
|
|
from variables.protocols import IIDX_XML, IIDX_RESULT, EAC_XML, EAC_RESULT, IIDX_Protocol, Respond, EAC_PROTOCOL_1, EAC_PROTOCOL_2
|
|
from time import time, time_ns
|
|
from variables.strings.preLaunch import GenericOK
|
|
from variables.strings.common import heartbeat, genericError, standardIIDX
|
|
from variables.strings.iidx import takeover, musicList, serverClientPrivilege, ReservePoint, ReserveItem
|
|
from variables.strings.games.iidx import MusicGhost, MusicGhostRegex, clearList, clearListTemplate, clearListRegex, rivalClearListTemplate, champInfo, champInfo2, tokenRegex, MusicGhostTemplate, playdata, playerSave,PointList,PointsAdd, itemList
|
|
from database import (
|
|
getInfIDByToken,
|
|
getProfileByInfID,
|
|
add_user,
|
|
add_token,
|
|
getRivalDataFromInfID,
|
|
update_save_data,
|
|
randomizeGhost,
|
|
getGhostDataFromInfIDandCheckSum,
|
|
getAllUnlockDataFromInfID,
|
|
manage_ghost_data,
|
|
update_save_data_bits,
|
|
manage_music_data,
|
|
getInfIDMusicData,
|
|
update_save_data_consumables,
|
|
getItemsbyInfID,
|
|
update_unlock_status,
|
|
)
|
|
sha256 = hashlib.sha256()
|
|
bp = Blueprint(
|
|
"needAuth", __name__, url_prefix="/iidx/needAuth"
|
|
) # Create a Blueprint for this route section
|
|
|
|
|
|
# PreProcess
|
|
|
|
@bp.route("/Heartbeat", methods=["POST"])
|
|
def HeartbeatPulse():
|
|
if request.method == "POST":
|
|
# Access post data
|
|
post_data = request.get_data().decode("UTF-8")
|
|
|
|
variables = parse_qs(post_data)
|
|
|
|
if variables["protocol_version"][0] != "P2D:2015091800":
|
|
return "Version Not Supported.", 400
|
|
|
|
response = KBinXML(heartbeat.format(token=variables['p2d_token'][0],nextClock=int(round(time() * 1000) + 34526426473),timeRemain=int(time() + 1 * 10000)).encode("utf-8")
|
|
)
|
|
binary_data = response.to_binary()
|
|
if isinstance(binary_data, str):
|
|
binary_data = binary_data.encode("utf-8")
|
|
return Respond(binary_data,IIDX_Protocol)
|
|
|
|
return "Invalid request method", 400
|
|
|
|
@bp.route("/CheckTakeover", methods=["POST"])
|
|
def ProfileCheckTakeover():
|
|
if request.method == "POST":
|
|
# Access post data
|
|
post_data = request.get_data().decode("UTF-8")
|
|
|
|
variables = parse_qs(post_data)
|
|
|
|
if variables["protocol_version"][0] != "P2D:2015091800":
|
|
return "Version Not Supported.", 400
|
|
# Access headers
|
|
headers = request.headers
|
|
|
|
kbinxml_data = ""
|
|
# Example: Decoding and processing data
|
|
try:
|
|
|
|
decoded_data = b64decode(repair_base64IIDX(variables["request"][0]))
|
|
decompressed_data = lz77_decompress(decoded_data)
|
|
kbinxml_data = KBinXML(decompressed_data).to_text()
|
|
# Process kbinxml_data
|
|
except Exception as e:
|
|
print(f"Error processing data: {e}")
|
|
response = KBinXML(takeover)
|
|
binary_data = response.to_binary()
|
|
if isinstance(binary_data, str):
|
|
binary_data = binary_data.encode("utf-8")
|
|
return Respond(binary_data,IIDX_Protocol)
|
|
|
|
return "Invalid request method", 400
|
|
|
|
@bp.route("/GetCompeScoreData", methods=["POST"])
|
|
@bp.route("/SendLog", methods=["POST"])
|
|
@bp.route("/CheckGameStart", methods=["POST"])
|
|
def GetCompeScoreData():
|
|
if request.method == "POST":
|
|
# Access post data
|
|
post_data = request.get_data().decode("UTF-8")
|
|
|
|
variables = parse_qs(post_data)
|
|
|
|
if variables["protocol_version"][0] != "P2D:2015091800":
|
|
return "Version Not Supported.", 400
|
|
# Access headers
|
|
headers = request.headers
|
|
|
|
kbinxml_data = ""
|
|
# Example: Decoding and processing data
|
|
response = KBinXML(genericError.format(protocol=IIDX_XML,result=IIDX_RESULT))
|
|
binary_data = response.to_binary()
|
|
if isinstance(binary_data, str):
|
|
binary_data = binary_data.encode("utf-8")
|
|
return Respond(binary_data,IIDX_Protocol)
|
|
|
|
return "Invalid request method", 400
|
|
|
|
@bp.route("/GetPrivilegeServer", methods=["POST"])
|
|
@bp.route("/GetPrivilegeClient", methods=["POST"])
|
|
@bp.route("/CancelReserveChangePoint", methods=["POST"])
|
|
def GetPrivilegeServerClient():
|
|
if request.method == "POST":
|
|
# Access post data
|
|
post_data = request.get_data().decode("UTF-8")
|
|
|
|
variables = parse_qs(post_data)
|
|
|
|
if variables["protocol_version"][0] != "P2D:2015091800":
|
|
return "Version Not Supported.", 400
|
|
# Access headers
|
|
headers = request.headers
|
|
|
|
kbinxml_data = ""
|
|
# Example: Decoding and processing data
|
|
response = KBinXML(serverClientPrivilege)
|
|
binary_data = response.to_binary()
|
|
if isinstance(binary_data, str):
|
|
binary_data = binary_data.encode("utf-8")
|
|
return Respond(binary_data,IIDX_Protocol)
|
|
|
|
return "Invalid request method", 400
|
|
|
|
@bp.route("/ReserveConsumeItem", methods=["POST"])
|
|
@bp.route("/ReserveChangePoint", methods=["POST"])
|
|
def ReserveChangePoint():
|
|
if request.method == "POST":
|
|
# Access post data
|
|
post_data = request.get_data().decode("UTF-8")
|
|
|
|
variables = parse_qs(post_data)
|
|
|
|
if variables["protocol_version"][0] != "P2D:2015091800":
|
|
return "Version Not Supported.", 400
|
|
|
|
allow_bit_spend = False
|
|
bit_check = False
|
|
transaction_check = False
|
|
transaction_allow = False
|
|
validating = False
|
|
errord = False
|
|
|
|
profile = getProfileByInfID(variables["infinitas_id"][0])
|
|
if profile is None:
|
|
response = KBinXML(genericError.format(protocol=IIDX_Protocol,result=IIDX_RESULT).encode())
|
|
binary_data = response.to_binary()
|
|
if isinstance(binary_data, str):
|
|
binary_data = binary_data.encode("utf-8")
|
|
return Respond(binary_data,IIDX_Protocol)
|
|
|
|
bits = profile.bits
|
|
try:
|
|
|
|
decoded_data = b64decode(repair_base64IIDX(variables["request"][0]))
|
|
decompressed_data = lz77_decompress(decoded_data)
|
|
kbinxml_data = KBinXML(decompressed_data).to_text()
|
|
pdata = xmltodict.parse(kbinxml_data)
|
|
items = getItemsbyInfID(profile.infinitasID)
|
|
# Process kbinxml_data
|
|
if pdata["p2d"]["params"] is not None:
|
|
points = (
|
|
pdata["p2d"]
|
|
.get("params", None)
|
|
.get("point", None)
|
|
.get("point_num", None)
|
|
.get("#text", None)
|
|
or None
|
|
)
|
|
item_id = pdata["p2d"].get("params", None).get("item_id", None).get("#text", None) or None
|
|
print(points)
|
|
if points is not None:
|
|
bit_check = True
|
|
validating = True
|
|
if bits > int(
|
|
pdata["p2d"]
|
|
.get("params", None)
|
|
.get("point", None)
|
|
.get("point", None)
|
|
.get("#text", None)
|
|
):
|
|
allow_bit_spend = True
|
|
elif item_id is not None:
|
|
validating = True
|
|
transaction_check = True
|
|
if (
|
|
item_id == "I1000000"
|
|
and (((items.TicketsFree + items.TicketsPaid)) >= 1) == True
|
|
):
|
|
transaction_allow = True
|
|
elif item_id == "I1000001" and (items.lDiscs >= 1) == True:
|
|
transaction_allow = True
|
|
except Exception as e:
|
|
response = KBinXML(standardIIDX.format(status="0",error="0",response=ReserveItem).encode()
|
|
)
|
|
errord = True
|
|
print(f"Error processing data: {e}")
|
|
if allow_bit_spend == True and bit_check == True:
|
|
response = KBinXML(
|
|
standardIIDX.format(status="0",error="0",response=ReservePoint).encode()
|
|
)
|
|
elif transaction_allow == True and transaction_check == True:
|
|
response = KBinXML(
|
|
standardIIDX.format(status="0",error="0",response=ReserveItem).encode()
|
|
)
|
|
elif (
|
|
(bit_check == False or transaction_check == False)
|
|
and validating == True
|
|
and errord == False
|
|
):
|
|
response = KBinXML(
|
|
standardIIDX.format(status="0",error="0",response=ReserveItem).encode()
|
|
)
|
|
else:
|
|
response = KBinXML(
|
|
standardIIDX.format(status="0",error="0",response=ReserveItem).encode()
|
|
)
|
|
binary_data = response.to_binary()
|
|
if isinstance(binary_data, str):
|
|
binary_data = binary_data.encode("utf-8")
|
|
return Respond(binary_data,IIDX_Protocol)
|
|
|
|
return "Invalid request method", 400
|
|
|
|
# Player Data
|
|
|
|
@bp.route("/CheckPlayData", methods=["POST"])
|
|
def CheckPlayData():
|
|
if request.method == "POST":
|
|
# Access post data
|
|
post_data = request.get_data().decode("UTF-8")
|
|
|
|
variables = parse_qs(post_data)
|
|
|
|
if variables["protocol_version"][0] != "P2D:2015091800":
|
|
return "Version Not Supported.", 400
|
|
if len(variables["p2d_token"][0]) < 1:
|
|
return Respond(genericError.format(protocol=IIDX_Protocol,result=IIDX_RESULT).encode(),IIDX_Protocol)
|
|
|
|
# Access headers
|
|
headers = request.headers
|
|
|
|
# Initialize response variables
|
|
infinitasID = "INVALIDTOKEN00"
|
|
isExist = 0
|
|
|
|
try:
|
|
# Retrieve profile using token
|
|
profile = getInfIDByToken(variables["p2d_token"][0])
|
|
if profile is None:
|
|
# Generate new infinitasID if token does not exist
|
|
infinitasID = "C" + "".join(random.choices("0123456789", k=12))
|
|
isExist = 0 # Assuming isExist should indicate that the profile does not exist
|
|
else:
|
|
profileSave = getProfileByInfID(profile.infinitasID)
|
|
infinitasID = profile.infinitasID or "INVALIDTOKEN00"
|
|
if profileSave is not None:
|
|
isExist = 1 # Indicates that the profile exists
|
|
|
|
except Exception as e:
|
|
print(f"Error processing data: {e}")
|
|
finally:
|
|
if infinitasID == "INVALIDTOKEN00":
|
|
return Respond(genericError.format(protocol=IIDX_Protocol,result=IIDX_RESULT).encode(),IIDX_Protocol)
|
|
|
|
# Prepare response
|
|
response = KBinXML(
|
|
playdata.format(infinitasID=infinitasID,isExist=isExist).encode("utf-8")
|
|
)
|
|
binary_data = response.to_binary()
|
|
if isinstance(binary_data, str):
|
|
binary_data = binary_data.encode("utf-8")
|
|
return Respond(binary_data,IIDX_Protocol)
|
|
|
|
return "Invalid request method", 400
|
|
|
|
@bp.route("/GetPlayData", methods=["POST"])
|
|
def GetPlayData():
|
|
if request.method == "POST":
|
|
# Access post data
|
|
post_data = request.get_data().decode("UTF-8")
|
|
|
|
variables = parse_qs(post_data)
|
|
|
|
if variables["protocol_version"][0] != "P2D:2015091800":
|
|
return "Version Not Supported.", 400
|
|
if len(variables["p2d_token"][0]) < 1:
|
|
return Respond(genericError.format(protocol=IIDX_Protocol,result=IIDX_RESULT).encode(),IIDX_Protocol)
|
|
|
|
# Access headers
|
|
headers = request.headers
|
|
|
|
# Initialize response variables
|
|
saveData = b""
|
|
saveDataSize = -1
|
|
saveDataChecksum = ""
|
|
|
|
try:
|
|
# Retrieve profile using token
|
|
print(variables["infinitas_id"][0])
|
|
profile = getProfileByInfID(variables["infinitas_id"][0])
|
|
if profile is not None: # Check if the profile exists
|
|
saveData = profile.saveData
|
|
saveDataSize = profile.saveLength
|
|
saveDataChecksum = profile.saveCheck
|
|
totalPlays = profile.playSP + profile.playDP
|
|
totalClears = profile.totalClears
|
|
|
|
except Exception as e:
|
|
print(f"Error processing data: {e}")
|
|
|
|
finally:
|
|
if saveDataSize == -1:
|
|
print("saveData Load Failed")
|
|
return Respond(genericError.format(protocol=IIDX_Protocol,result=IIDX_RESULT).encode(),IIDX_Protocol)
|
|
|
|
saveDataDecrypt = xmltodict.parse(KBinXML(saveData).to_text())
|
|
if type(saveDataDecrypt["pdata"]["mission"]["mission_list"]) == dict:
|
|
print("Filling out Mission Data")
|
|
spStats = saveDataDecrypt["pdata"]["stats"]["sp"]
|
|
dpStats = saveDataDecrypt["pdata"]["stats"]["dp"]
|
|
spDan = saveDataDecrypt["pdata"]["dan"]["sp"]
|
|
dpDan = saveDataDecrypt["pdata"]["dan"]["dp"]
|
|
djPointTotal = int(spStats["djpoint_hist"][f"h{str(len(spStats['djpoint_hist'])-1).zfill(2)}"]["val"]["#text"]) + int(dpStats["djpoint_hist"][f"h{str(len(dpStats['djpoint_hist'])-1).zfill(2)}"]["val"]["#text"])
|
|
newMissionList = {}
|
|
total = 10
|
|
playMissionID = "M200000{id}"
|
|
DJPointMissionID = "M201000{id}"
|
|
clearMissionID = "M202000{id}"
|
|
danMissionID = "M205000{id}"
|
|
|
|
# Total Play & Clear Counts
|
|
for i in range(0, 78):
|
|
# i number should be padded by one digit to the left if it is less than 10
|
|
newMissionList[playMissionID.format(id=str(i).zfill(2))] = {"clear_count": {}, "progress": {}, "last_clear_date": {}}
|
|
newMissionList[clearMissionID.format(id=str(i).zfill(2))] = {"clear_count": {}, "progress": {}, "last_clear_date": {}}
|
|
|
|
if totalPlays > total:
|
|
newMissionList[playMissionID.format(id=str(i).zfill(2))]["clear_count"]["#text"] = "1"
|
|
newMissionList[playMissionID.format(id=str(i).zfill(2))]["progress"]["#text"] = str(total)
|
|
newMissionList[playMissionID.format(id=str(i).zfill(2))]["last_clear_date"]["#text"] = str(time_ns())
|
|
newMissionList[playMissionID.format(id=str(i).zfill(2))]["clear_count"]["@__type"] = "s32"
|
|
newMissionList[playMissionID.format(id=str(i).zfill(2))]["progress"]["@__type"] = "s32"
|
|
newMissionList[playMissionID.format(id=str(i).zfill(2))]["last_clear_date"]["@__type"] = "u64"
|
|
else:
|
|
newMissionList[playMissionID.format(id=str(i).zfill(2))]["clear_count"]["#text"] = "0"
|
|
newMissionList[playMissionID.format(id=str(i).zfill(2))]["progress"]["#text"] = str(totalPlays)
|
|
newMissionList[playMissionID.format(id=str(i).zfill(2))]["last_clear_date"]["#text"] = str(0)
|
|
newMissionList[playMissionID.format(id=str(i).zfill(2))]["clear_count"]["@__type"] = "s32"
|
|
newMissionList[playMissionID.format(id=str(i).zfill(2))]["progress"]["@__type"] = "s32"
|
|
newMissionList[playMissionID.format(id=str(i).zfill(2))]["last_clear_date"]["@__type"] = "u64"
|
|
if totalClears > total:
|
|
newMissionList[clearMissionID.format(id=str(i).zfill(2))]["clear_count"]["#text"] = "1"
|
|
newMissionList[clearMissionID.format(id=str(i).zfill(2))]["progress"]["#text"] = str(total)
|
|
newMissionList[clearMissionID.format(id=str(i).zfill(2))]["last_clear_date"]["#text"] = str(time_ns())
|
|
newMissionList[clearMissionID.format(id=str(i).zfill(2))]["clear_count"]["@__type"] = "s32"
|
|
newMissionList[clearMissionID.format(id=str(i).zfill(2))]["progress"]["@__type"] = "s32"
|
|
newMissionList[clearMissionID.format(id=str(i).zfill(2))]["last_clear_date"]["@__type"] = "u64"
|
|
else:
|
|
newMissionList[clearMissionID.format(id=str(i).zfill(2))]["clear_count"]["#text"] = "0"
|
|
newMissionList[clearMissionID.format(id=str(i).zfill(2))]["progress"]["#text"] = str(totalClears)
|
|
newMissionList[clearMissionID.format(id=str(i).zfill(2))]["last_clear_date"]["#text"] = str(0)
|
|
newMissionList[clearMissionID.format(id=str(i).zfill(2))]["clear_count"]["@__type"] = "s32"
|
|
newMissionList[clearMissionID.format(id=str(i).zfill(2))]["progress"]["@__type"] = "s32"
|
|
newMissionList[clearMissionID.format(id=str(i).zfill(2))]["last_clear_date"]["@__type"] = "u64"
|
|
|
|
if i <= 8:
|
|
total += 10
|
|
elif i <= 26:
|
|
total += 50
|
|
elif i <= 66:
|
|
total += 100
|
|
else: total += 500
|
|
|
|
# DJPoint Missions
|
|
for i in range(0, 59):
|
|
Threshold = 100 * (i+1)
|
|
newMissionList[DJPointMissionID.format(id=str(i).zfill(2))] = {"clear_count": {}, "progress": {}, "last_clear_date": {}}
|
|
if djPointTotal > Threshold:
|
|
newMissionList[DJPointMissionID.format(id=str(i).zfill(2))]["clear_count"]["#text"] = "1"
|
|
newMissionList[DJPointMissionID.format(id=str(i).zfill(2))]["progress"]["#text"] = str(Threshold)
|
|
newMissionList[DJPointMissionID.format(id=str(i).zfill(2))]["last_clear_date"]["#text"] = str(time_ns())
|
|
newMissionList[DJPointMissionID.format(id=str(i).zfill(2))]["clear_count"]["@__type"] = "s32"
|
|
newMissionList[DJPointMissionID.format(id=str(i).zfill(2))]["progress"]["@__type"] = "s32"
|
|
newMissionList[DJPointMissionID.format(id=str(i).zfill(2))]["last_clear_date"]["@__type"] = "u64"
|
|
else:
|
|
newMissionList[DJPointMissionID.format(id=str(i).zfill(2))]["clear_count"]["#text"] = "0"
|
|
newMissionList[DJPointMissionID.format(id=str(i).zfill(2))]["progress"]["#text"] = str(djPointTotal)
|
|
newMissionList[DJPointMissionID.format(id=str(i).zfill(2))]["last_clear_date"]["#text"] = str(0)
|
|
newMissionList[DJPointMissionID.format(id=str(i).zfill(2))]["clear_count"]["@__type"] = "s32"
|
|
newMissionList[DJPointMissionID.format(id=str(i).zfill(2))]["progress"]["@__type"] = "s32"
|
|
newMissionList[DJPointMissionID.format(id=str(i).zfill(2))]["last_clear_date"]["@__type"] = "u64"
|
|
saveDataDecrypt["pdata"]["mission"]["mission_list"] = newMissionList
|
|
saveData = KBinXML(xmltodict.unparse(saveDataDecrypt).encode()).to_binary()
|
|
|
|
# Dan Rank Missions
|
|
|
|
for item in spDan["kind"]:
|
|
# Check if the current item contains the "course" key
|
|
if "course" in item:
|
|
# Access the course data
|
|
courses = item["course"]
|
|
for course in courses:
|
|
# Print the course ID and other relevant information
|
|
course_id = int(course["@id"])
|
|
total_clear_count = int(course["total_clear_count"]["#text"])
|
|
|
|
newMissionList[DJPointMissionID.format(id=str(course_id).zfill(2))] = {"clear_count": {}, "progress": {}, "last_clear_date": {}}
|
|
if total_clear_count > 0:
|
|
newMissionList[DJPointMissionID.format(id=str(course_id).zfill(2))]["clear_count"]["#text"] = "1"
|
|
newMissionList[DJPointMissionID.format(id=str(course_id).zfill(2))]["progress"]["#text"] = "1"
|
|
newMissionList[DJPointMissionID.format(id=str(course_id).zfill(2))]["last_clear_date"]["#text"] = str(time_ns())
|
|
newMissionList[DJPointMissionID.format(id=str(course_id).zfill(2))]["clear_count"]["@__type"] = "s32"
|
|
newMissionList[DJPointMissionID.format(id=str(course_id).zfill(2))]["progress"]["@__type"] = "s32"
|
|
newMissionList[DJPointMissionID.format(id=str(course_id).zfill(2))]["last_clear_date"]["@__type"] = "u64"
|
|
else:
|
|
newMissionList[DJPointMissionID.format(id=str(course_id).zfill(2))]["clear_count"]["#text"] = "0"
|
|
newMissionList[DJPointMissionID.format(id=str(course_id).zfill(2))]["progress"]["#text"] = "0"
|
|
newMissionList[DJPointMissionID.format(id=str(course_id).zfill(2))]["last_clear_date"]["#text"] = str(0)
|
|
newMissionList[DJPointMissionID.format(id=str(course_id).zfill(2))]["clear_count"]["@__type"] = "s32"
|
|
newMissionList[DJPointMissionID.format(id=str(course_id).zfill(2))]["progress"]["@__type"] = "s32"
|
|
newMissionList[DJPointMissionID.format(id=str(course_id).zfill(2))]["last_clear_date"]["@__type"] = "u64"
|
|
|
|
for item in dpDan["kind"]:
|
|
# Check if the current item contains the "course" key
|
|
if "course" in item:
|
|
# Access the course data
|
|
courses = item["course"]
|
|
print(courses)
|
|
# Print the course ID and other relevant information
|
|
course_id = int(course["@id"])
|
|
total_clear_count = int(course["total_clear_count"]["#text"])
|
|
|
|
newMissionList[DJPointMissionID.format(id=str(course_id+20).zfill(2))] = {"clear_count": {}, "progress": {}, "last_clear_date": {}}
|
|
if total_clear_count > 0:
|
|
newMissionList[DJPointMissionID.format(id=str(course_id+20).zfill(2))]["clear_count"]["#text"] = "1"
|
|
newMissionList[DJPointMissionID.format(id=str(course_id+20).zfill(2))]["progress"]["#text"] = "1"
|
|
newMissionList[DJPointMissionID.format(id=str(course_id+20).zfill(2))]["last_clear_date"]["#text"] = str(time_ns())
|
|
newMissionList[DJPointMissionID.format(id=str(course_id+20).zfill(2))]["clear_count"]["@__type"] = "s32"
|
|
newMissionList[DJPointMissionID.format(id=str(course_id+20).zfill(2))]["progress"]["@__type"] = "s32"
|
|
newMissionList[DJPointMissionID.format(id=str(course_id+20).zfill(2))]["last_clear_date"]["@__type"] = "u64"
|
|
else:
|
|
newMissionList[DJPointMissionID.format(id=str(course_id+20).zfill(2))]["clear_count"]["#text"] = "0"
|
|
newMissionList[DJPointMissionID.format(id=str(course_id+20).zfill(2))]["progress"]["#text"] = "0"
|
|
newMissionList[DJPointMissionID.format(id=str(course_id+20).zfill(2))]["last_clear_date"]["#text"] = str(0)
|
|
newMissionList[DJPointMissionID.format(id=str(course_id+20).zfill(2))]["clear_count"]["@__type"] = "s32"
|
|
newMissionList[DJPointMissionID.format(id=str(course_id+20).zfill(2))]["progress"]["@__type"] = "s32"
|
|
newMissionList[DJPointMissionID.format(id=str(course_id+20).zfill(2))]["last_clear_date"]["@__type"] = "u64"
|
|
|
|
# Update the hash object with the encoded string
|
|
sha256.update(saveData)
|
|
saveDataChecksum = sha256.hexdigest()
|
|
saveDataSize = len(saveData)
|
|
|
|
# Prepare response
|
|
response = KBinXML(playerSave.format(saveDataSize=saveDataSize,saveDataChecksum=saveDataChecksum,saveData=saveData.hex()).encode()
|
|
)
|
|
binary_data = response.to_binary()
|
|
if isinstance(binary_data, str):
|
|
binary_data = binary_data.encode()
|
|
return Respond(binary_data,IIDX_Protocol)
|
|
|
|
return "Invalid request method", 400
|
|
|
|
@bp.route("/SavePlayData", methods=["POST"])
|
|
def savePlayData():
|
|
if request.method == "POST":
|
|
# Access post data
|
|
post_data = request.get_data().decode()
|
|
|
|
variables = parse_qs(post_data)
|
|
|
|
if variables["protocol_version"][0] != "P2D:2015091800":
|
|
return "Version Not Supported.", 400
|
|
# Access headers
|
|
headers = request.headers
|
|
|
|
kbinxml_data = ""
|
|
error = False
|
|
# Example: Decoding and processing data
|
|
try:
|
|
raw_request = repair_base64IIDX(variables["request"][0])
|
|
decoded_data = b64decode(raw_request)
|
|
decompressed_data = lz77_decompress(decoded_data)
|
|
kbinxml_data = KBinXML(decompressed_data).to_text()
|
|
data = xmltodict.parse(kbinxml_data) # Ensure to parse the XML correctly
|
|
save_data = xmltodict.parse(
|
|
KBinXML(
|
|
bytes.fromhex(data["p2d"]["params"]["pdata"]["#text"])
|
|
).to_text()
|
|
)
|
|
if type(save_data["pdata"]["mission"]["mission_list"]) == dict:
|
|
print("saving Data")
|
|
update_save_data(
|
|
variables["infinitas_id"][0],
|
|
data["p2d"]["params"]["pdata"]["#text"],
|
|
data["p2d"]["params"]["pdata_size"]["#text"],
|
|
data["p2d"]["params"]["check_sum"]["#text"],
|
|
)
|
|
# Process kbinxml_data
|
|
except Exception as e:
|
|
error = True
|
|
print(f"Error processing data: {e}")
|
|
if error == True:
|
|
response = KBinXML(genericError.format(protocol=IIDX_Protocol,result=IIDX_RESULT).encode())
|
|
else:
|
|
response = KBinXML(genericError.format(protocol=IIDX_XML,result=IIDX_RESULT))
|
|
binary_data = response.to_binary()
|
|
if isinstance(binary_data, str):
|
|
binary_data = binary_data.encode()
|
|
return Respond(binary_data,IIDX_Protocol)
|
|
|
|
return "Invalid request method", 400
|
|
|
|
|
|
@bp.route("/GetItemList", methods=["POST"])
|
|
def GetItemList():
|
|
if request.method == "POST":
|
|
# Access post data
|
|
post_data = request.get_data().decode("UTF-8")
|
|
|
|
variables = parse_qs(post_data)
|
|
|
|
if variables["protocol_version"][0] != "P2D:2015091800":
|
|
return "Version Not Supported.", 400
|
|
|
|
itemCount = 2
|
|
itemLists = ""
|
|
itemTemplate = '<item>\n <item_id __type="str">{itemID}</item_id>\n <not_free_count __type="s32">1</not_free_count>\n <free_count __type="s32">0</free_count>\n </item>'
|
|
defaultItems = '<item>\n <item_id __type="str">I1000000</item_id>\n <not_free_count __type="s32">{TicketsPaid}</not_free_count>\n <free_count __type="s32">{TicketsFree}</free_count>\n </item>\n <item>\n <item_id __type="str">I1000001</item_id>\n <not_free_count __type="s32">{lDiscs}</not_free_count>\n <free_count __type="s32">0</free_count>\n </item>'
|
|
# Example: Decoding and processing data
|
|
TicketsPaid = 0
|
|
TicketsFree = 0
|
|
lDiscs = 0
|
|
try:
|
|
# Process kbinxml_data
|
|
# variables["infinitas_id"][0]
|
|
items = getItemsbyInfID(variables["infinitas_id"][0]) or None
|
|
if items is not None:
|
|
TicketsPaid = items.TicketsPaid or "0"
|
|
TicketsFree = items.TicketsFree or "0"
|
|
lDiscs = items.lDiscs or "0"
|
|
defaultItems = defaultItems.format(
|
|
TicketsPaid=TicketsPaid, TicketsFree=TicketsFree, lDiscs=lDiscs
|
|
)
|
|
music_packs = json.loads(items.musicPacks or "[]")
|
|
for music_pack in music_packs:
|
|
itemCount = itemCount + 1
|
|
itemLists = itemLists + itemTemplate.format(itemID=str(music_pack))
|
|
except Exception as e:
|
|
print(f"Error processing data: {e}")
|
|
response = KBinXML(itemList.format(itemCount=itemCount,defaultItems=defaultItems,itemLists=itemLists).encode()
|
|
)
|
|
binary_data = response.to_binary()
|
|
if isinstance(binary_data, str):
|
|
binary_data = binary_data.encode("utf-8")
|
|
return Respond(binary_data,IIDX_Protocol)
|
|
|
|
return "Invalid request method", 400
|
|
|
|
|
|
@bp.route("/GetPointList", methods=["POST"])
|
|
def GetPointList():
|
|
if request.method == "POST":
|
|
# Access post data
|
|
post_data = request.get_data().decode("UTF-8")
|
|
|
|
variables = parse_qs(post_data)
|
|
|
|
if variables["protocol_version"][0] != "P2D:2015091800":
|
|
return "Version Not Supported.", 400
|
|
|
|
profile = getProfileByInfID(variables["infinitas_id"][0])
|
|
if profile:
|
|
bitCount = profile.bits
|
|
else:
|
|
bitCount = 0
|
|
response = KBinXML(
|
|
re.sub(
|
|
r'<point_num __type="u32">15000</point_num>',
|
|
f'<point_num __type="u32">{bitCount}</point_num>',
|
|
PointList,
|
|
).encode()
|
|
)
|
|
binary_data = response.to_binary()
|
|
if isinstance(binary_data, str):
|
|
binary_data = binary_data.encode("utf-8")
|
|
return Respond(binary_data,IIDX_Protocol)
|
|
|
|
return "Invalid request method", 400
|
|
|
|
|
|
@bp.route("/AddPoint", methods=["POST"])
|
|
def AddPoint():
|
|
if request.method == "POST":
|
|
# Access post data
|
|
post_data = request.get_data().decode("UTF-8")
|
|
|
|
variables = parse_qs(post_data)
|
|
|
|
if variables["protocol_version"][0] != "P2D:2015091800":
|
|
return "Version Not Supported.", 400
|
|
profile = getProfileByInfID(variables["infinitas_id"][0])
|
|
if profile is None:
|
|
response = KBinXML(genericError.format(protocol=IIDX_Protocol,result=IIDX_RESULT).encode())
|
|
binary_data = response.to_binary()
|
|
if isinstance(binary_data, str):
|
|
binary_data = binary_data.encode("utf-8")
|
|
return Respond(binary_data,IIDX_Protocol)
|
|
|
|
bitsEarned = profile.bits
|
|
try:
|
|
|
|
decoded_data = b64decode(repair_base64IIDX(variables["request"][0]))
|
|
decompressed_data = lz77_decompress(decoded_data)
|
|
kbinxml_data = KBinXML(decompressed_data).to_text()
|
|
pdata = xmltodict.parse(kbinxml_data)
|
|
# Process kbinxml_data
|
|
if isinstance(pdata["p2d"]["params"]["point"], list):
|
|
# Multiple ghost requests
|
|
for point in pdata["p2d"]["params"]["point"]:
|
|
bitsEarned = bitsEarned + int(point["point_num"]["#text"])
|
|
else:
|
|
# Single ghost request
|
|
point = pdata["p2d"]["params"]["point"]
|
|
bitsEarned = bitsEarned + int(point["point_num"]["#text"])
|
|
update_save_data_bits(profile.infinitasID, bitsEarned)
|
|
except Exception as e:
|
|
print(f"Error processing data: {e}")
|
|
|
|
response = KBinXML(PointsAdd.format(bits=bitsEarned).encode())
|
|
binary_data = response.to_binary()
|
|
if isinstance(binary_data, str):
|
|
binary_data = binary_data.encode("utf-8")
|
|
return Respond(binary_data,IIDX_Protocol)
|
|
|
|
return "Invalid request method", 400
|
|
|
|
|
|
@bp.route("/UsePoint", methods=["POST"])
|
|
def UsePoint():
|
|
if request.method == "POST":
|
|
# Access post data
|
|
post_data = request.get_data().decode("UTF-8")
|
|
|
|
variables = parse_qs(post_data)
|
|
|
|
if variables["protocol_version"][0] != "P2D:2015091800":
|
|
return "Version Not Supported.", 400
|
|
profile = getProfileByInfID(variables["infinitas_id"][0])
|
|
if profile is None:
|
|
response = KBinXML(genericError.format(protocol=IIDX_Protocol,result=IIDX_RESULT).encode())
|
|
binary_data = response.to_binary()
|
|
if isinstance(binary_data, str):
|
|
binary_data = binary_data.encode("utf-8")
|
|
return Respond(binary_data,IIDX_Protocol)
|
|
|
|
bits = profile.bits
|
|
bits_spent = False
|
|
try:
|
|
|
|
decoded_data = b64decode(repair_base64IIDX(variables["request"][0]))
|
|
decompressed_data = lz77_decompress(decoded_data)
|
|
kbinxml_data = KBinXML(decompressed_data).to_text()
|
|
pdata = xmltodict.parse(kbinxml_data)
|
|
# Process kbinxml_data
|
|
print(pdata["p2d"]["params"]["point"]["point_num"]["#text"])
|
|
if bits > int(pdata["p2d"]["params"]["point"]["point_num"]["#text"]):
|
|
bits = bits - int(pdata["p2d"]["params"]["point"]["point_num"]["#text"])
|
|
update_save_data_bits(profile.infinitasID, bits)
|
|
bits_spent = True
|
|
except Exception as e:
|
|
print(f"Error processing data: {e}")
|
|
if bits_spent == True:
|
|
response = KBinXML(standardIIDX.format(status="0",error="0",response='\n<point_count __type="s32">1</point_count>\n<point>\n<point_id __type="str">P0100000</point_id>\n<point_num __type="u32">{bits}</point_num>\n</point>\n').encode("utf-8")
|
|
)
|
|
else:
|
|
response = KBinXML(genericError.format(protocol=IIDX_Protocol,result=IIDX_RESULT).encode())
|
|
binary_data = response.to_binary()
|
|
if isinstance(binary_data, str):
|
|
binary_data = binary_data.encode("utf-8")
|
|
return Respond(binary_data,IIDX_Protocol)
|
|
|
|
return "Invalid request method", 400
|
|
|
|
@bp.route("/ConsumeItem", methods=["POST"])
|
|
def ConsumeItem():
|
|
if request.method == "POST":
|
|
# Access post data
|
|
post_data = request.get_data().decode("UTF-8")
|
|
|
|
variables = parse_qs(post_data)
|
|
|
|
if variables["protocol_version"][0] != "P2D:2015091800":
|
|
return "Version Not Supported.", 400
|
|
profile = getProfileByInfID(variables["infinitas_id"][0])
|
|
if profile is None:
|
|
response = KBinXML(genericError.format(protocol=IIDX_Protocol,result=IIDX_RESULT).encode())
|
|
binary_data = response.to_binary()
|
|
if isinstance(binary_data, str):
|
|
binary_data = binary_data.encode("utf-8")
|
|
return Respond(binary_data,IIDX_Protocol)
|
|
|
|
transaction_success = False
|
|
try:
|
|
|
|
decoded_data = b64decode(repair_base64IIDX(variables["request"][0]))
|
|
decompressed_data = lz77_decompress(decoded_data)
|
|
kbinxml_data = KBinXML(decompressed_data).to_text()
|
|
pdata = xmltodict.parse(kbinxml_data)
|
|
# Process kbinxml_data
|
|
goods_id = pdata["p2d"]["params"]["goods_id"]["#text"]
|
|
item_id = pdata["p2d"]["params"]["item_id"]["#text"]
|
|
consume_num = pdata["p2d"]["params"]["consume_num"]["#text"]
|
|
use_priority = pdata["p2d"]["params"]["use_priority"]["#text"]
|
|
|
|
if goods_id == "G1000001" or goods_id == "G2000002":
|
|
transaction_success = update_save_data_consumables(
|
|
variables["infinitas_id"][0], 1, 1
|
|
)
|
|
elif goods_id == "G3000000":
|
|
transaction_success = update_save_data_consumables(
|
|
variables["infinitas_id"][0], 3, 1
|
|
)
|
|
elif goods_id == "G3000001":
|
|
transaction_success = update_save_data_consumables(
|
|
variables["infinitas_id"][0], 2, 1
|
|
)
|
|
items = getItemsbyInfID(variables["infinitas_id"][0])
|
|
if items is not None:
|
|
TicketsPaid = items.TicketsPaid
|
|
TicketsFree = items.TicketsFree
|
|
lDiscs = items.lDiscs
|
|
if item_id == "I1000000":
|
|
itemTemplate = f'<not_free_count __type="s32">{TicketsPaid}</not_free_count>\n <free_count __type="s32">{TicketsFree}</free_count>\n'
|
|
else:
|
|
itemTemplate = f'<not_free_count __type="s32">{lDiscs}</not_free_count>\n <free_count __type="s32">0</free_count>\n'
|
|
|
|
except Exception as e:
|
|
print(f"Error processing data: {e}")
|
|
if transaction_success == True:
|
|
response = KBinXML(
|
|
standardIIDX.format(status="0",error="0",response=itemTemplate).encode()
|
|
)
|
|
else:
|
|
response = KBinXML(genericError.format(protocol=IIDX_Protocol,result=IIDX_RESULT).encode(),IIDX_Protocol)
|
|
binary_data = response.to_binary()
|
|
if isinstance(binary_data, str):
|
|
binary_data = binary_data.encode("utf-8")
|
|
return Respond(binary_data,IIDX_Protocol)
|
|
|
|
return "Invalid request method", 400
|
|
|
|
@bp.route("/GetItemNum", methods=["POST"])
|
|
def GetItemNum():
|
|
if request.method == "POST":
|
|
# Access post data
|
|
post_data = request.get_data().decode("UTF-8")
|
|
|
|
variables = parse_qs(post_data)
|
|
|
|
if variables["protocol_version"][0] != "P2D:2015091800":
|
|
return "Version Not Supported.", 400
|
|
|
|
itemCount = 2
|
|
itemLists = ""
|
|
# Example: Decoding and processing data
|
|
TicketsPaid = 0
|
|
TicketsFree = 0
|
|
lDiscs = 0
|
|
try:
|
|
|
|
decoded_data = b64decode(repair_base64IIDX(variables["request"][0]))
|
|
decompressed_data = lz77_decompress(decoded_data)
|
|
kbinxml_data = KBinXML(decompressed_data).to_text()
|
|
data = xmltodict.parse(kbinxml_data) # Ensure to parse the XML correctly
|
|
# Process kbinxml_data
|
|
# variables["infinitas_id"][0]
|
|
items = getItemsbyInfID(variables["infinitas_id"][0])
|
|
if items is not None:
|
|
TicketsPaid = items.TicketsPaid or 0
|
|
TicketsFree = items.TicketsFree or 0
|
|
lDiscs = items.lDiscs or 0
|
|
if data["p2d"]["params"]["item_id"]["#text"] == "I1000000":
|
|
itemTemplate = f'<not_free_count __type="s32">{TicketsPaid}</not_free_count>\n <free_count __type="s32">{TicketsFree}</free_count>\n'
|
|
else:
|
|
itemTemplate = f'<not_free_count __type="s32">{lDiscs}</not_free_count>\n <free_count __type="s32">0</free_count>\n'
|
|
|
|
except Exception as e:
|
|
print(f"Error processing data: {e}")
|
|
response = KBinXML(
|
|
standardIIDX.format(status="0",error="0",response=itemTemplate).encode()
|
|
)
|
|
binary_data = response.to_binary()
|
|
if isinstance(binary_data, str):
|
|
binary_data = binary_data.encode("utf-8")
|
|
return Respond(binary_data,IIDX_Protocol)
|
|
|
|
return "Invalid request method", 400
|
|
|
|
@bp.route("/RegistPlayer", methods=["POST"])
|
|
def registPlayer():
|
|
if request.method == "POST":
|
|
# Access post data
|
|
post_data = request.get_data().decode("UTF-8")
|
|
|
|
variables = parse_qs(post_data)
|
|
|
|
if variables["protocol_version"][0] != "P2D:2015091800":
|
|
return "Version Not Supported.", 400
|
|
# Access headers
|
|
headers = request.headers
|
|
|
|
# Do something with post_data and headers
|
|
kbinxml_data = ""
|
|
playStyle = -1
|
|
error = False
|
|
htmlrep = 200
|
|
# Example: Decoding and processing data
|
|
try:
|
|
decoded_data = b64decode(repair_base64IIDX(variables["request"][0]))
|
|
decompressed_data = lz77_decompress(decoded_data)
|
|
kbinxml_data = KBinXML(decompressed_data).to_text()
|
|
data = xmltodict.parse(kbinxml_data) # Ensure to parse the XML correctly
|
|
profile = xmltodict.parse(
|
|
KBinXML(
|
|
bytes.fromhex(data["p2d"]["params"]["pdata"]["#text"])
|
|
).to_text()
|
|
)
|
|
# Process kbinxml_data
|
|
add_user(
|
|
profile["pdata"]["player"]["infinitas_id"]["#text"],
|
|
profile["pdata"]["player"]["djname"]["#text"],
|
|
profile["pdata"]["version"]["#text"],
|
|
profile["pdata"]["player"]["pref_id"]["#text"],
|
|
0,
|
|
0,
|
|
0,
|
|
0,
|
|
-1,
|
|
-1,
|
|
)
|
|
add_token(
|
|
profile["pdata"]["player"]["infinitas_id"]["#text"],
|
|
variables["p2d_token"][0],
|
|
)
|
|
except Exception as e:
|
|
error = True
|
|
htmlrep = 500
|
|
print(f"Error processing data: {e}")
|
|
finally:
|
|
if error == True:
|
|
response = KBinXML(genericError.format(protocol=IIDX_XML,result=IIDX_RESULT))
|
|
else:
|
|
response = KBinXML(genericError.format(protocol=IIDX_XML,result=IIDX_RESULT))
|
|
binary_data = response.to_binary()
|
|
if isinstance(binary_data, str):
|
|
binary_data = binary_data.encode("utf-8")
|
|
return (
|
|
Respond(binary_data, IIDX_Protocol),
|
|
htmlrep,
|
|
)
|
|
|
|
return "Invalid request method", 400
|
|
|
|
@bp.route("/GetMusicData", methods=["POST"])
|
|
def getMusicData():
|
|
if request.method == "POST":
|
|
# Access post data
|
|
post_data = request.get_data().decode("UTF-8")
|
|
|
|
variables = parse_qs(post_data)
|
|
|
|
if variables["protocol_version"][0] != "P2D:2015091800":
|
|
return "Version Not Supported.", 400
|
|
# Access headers
|
|
headers = request.headers
|
|
|
|
# Do something with post_data and headers
|
|
kbinxml_data = ""
|
|
playStyle = -1
|
|
# Example: Decoding and processing data
|
|
|
|
profileMusicData = ""
|
|
|
|
try:
|
|
|
|
decoded_data = b64decode(repair_base64IIDX(variables["request"][0]))
|
|
decompressed_data = lz77_decompress(decoded_data)
|
|
kbinxml_data = KBinXML(decompressed_data).to_text()
|
|
data = xmltodict.parse(kbinxml_data) # Ensure to parse the XML correctly
|
|
playStyle = data["p2d"]["params"]["play_style"]["#text"]
|
|
# Process kbinxml_data
|
|
musicData = getInfIDMusicData(variables["infinitas_id"][0])
|
|
if musicData:
|
|
for music in musicData:
|
|
missCount = json.loads(music.missCount)
|
|
clearAmt = json.loads(music.clearAmount)
|
|
clearflg = json.loads(music.clearFlag)
|
|
playCount = json.loads(music.playCount)
|
|
score = json.loads(music.score)
|
|
if int(playStyle) == 0:
|
|
count = 5
|
|
# if everything field of a certain point in the array is empty, it will be replaced with a "-1"
|
|
for i in range(5):
|
|
if missCount[i] == 0 and clearAmt[i] == 0 and clearflg[i] == 0 and playCount[i] == 0 and score[i] == 0:
|
|
missCount[i] = -1
|
|
clearAmt[i] = -1
|
|
clearflg[i] = -1
|
|
playCount[i] = -1
|
|
score[i] = -1
|
|
|
|
misses = f"{missCount[0]} {missCount[1]} {missCount[2]} {missCount[3]} {missCount[4]}"
|
|
clears = f"{clearAmt[0]} {clearAmt[1]} {clearAmt[2]} {clearAmt[3]} {clearAmt[4]}"
|
|
flag = f"{clearflg[0]} {clearflg[1]} {clearflg[2]} {clearflg[3]} {clearflg[4]}"
|
|
counts = f"{playCount[0]} {playCount[1]} {playCount[2]} {playCount[3]} {playCount[4]}"
|
|
print(missCount[4])
|
|
scores = (
|
|
f"{score[0]} {score[1]} {score[2]} {score[3]} {score[4]}"
|
|
)
|
|
profileMusicData = profileMusicData + clearListTemplate.format(
|
|
count=count,
|
|
score=scores,
|
|
musicID=music.musicID,
|
|
missCnt=misses,
|
|
clearAmt=clears,
|
|
clearflg=flag,
|
|
playCount=counts,
|
|
)
|
|
else:
|
|
print(len(missCount))
|
|
print(len(clearAmt))
|
|
print(len(clearflg))
|
|
print(len(playCount))
|
|
print(len(score))
|
|
count = 4
|
|
for i in range(4):
|
|
if missCount[i+6] == 0 and clearAmt[i+6] == 0 and clearflg[i+6] == 0 and playCount[i+6] == 0 and score[i+6] == 0:
|
|
missCount[i+6] = -1
|
|
clearAmt[i+6] = -1
|
|
clearflg[i+6] = -1
|
|
playCount[i+6] = -1
|
|
score[i+6] = -1
|
|
misses = f"{missCount[6]} {missCount[7]} {missCount[8]} {missCount[9]}"
|
|
clears = f"{clearAmt[6]} {clearAmt[7]} {clearAmt[8]} {clearAmt[9]}"
|
|
flag = f"{clearflg[6]} {clearflg[7]} {clearflg[8]} {clearflg[9]}"
|
|
counts = f"{playCount[6]} {playCount[7]} {playCount[8]} {playCount[9]}"
|
|
scores = f"{score[6]} {score[7]} {score[8]} {score[9]}"
|
|
profileMusicData = profileMusicData + clearListTemplate.format(
|
|
count=count,
|
|
score=scores,
|
|
musicID=music.musicID,
|
|
missCnt=misses,
|
|
clearAmt=clears,
|
|
clearflg=flag,
|
|
playCount=counts,
|
|
)
|
|
except Exception as e:
|
|
print(f"Error processing data: {e}")
|
|
finally:
|
|
print(profileMusicData)
|
|
clearListReplace = f'<play_style __type="s32">{playStyle}</play_style>'
|
|
response = KBinXML(
|
|
re.sub(
|
|
r"<result />\n",
|
|
f"<result>\n{profileMusicData}\n</result>",
|
|
re.sub(
|
|
clearListRegex,
|
|
clearListReplace.format(playStyle=playStyle),
|
|
clearList,
|
|
),
|
|
).encode("utf-8")
|
|
)
|
|
# TODO: Grab Player Data from DB
|
|
binary_data = response.to_binary()
|
|
if isinstance(binary_data, str):
|
|
binary_data = binary_data.encode("utf-8")
|
|
return Respond(binary_data,IIDX_Protocol)
|
|
|
|
return "Invalid request method", 400
|
|
|
|
@bp.route("/UnlockMusic", methods=["POST"])
|
|
def unlockMusic():
|
|
if request.method == "POST":
|
|
# Access post data
|
|
post_data = request.get_data().decode("UTF-8")
|
|
|
|
variables = parse_qs(post_data)
|
|
|
|
if variables["protocol_version"][0] != "P2D:2015091800":
|
|
return "Version Not Supported.", 400
|
|
|
|
okToContinue = False
|
|
# Example: Decoding and processing data
|
|
try:
|
|
|
|
decoded_data = b64decode(repair_base64IIDX(variables["request"][0]))
|
|
decompressed_data = lz77_decompress(decoded_data)
|
|
kbinxml_data = KBinXML(decompressed_data).to_text()
|
|
pdata = xmltodict.parse(kbinxml_data)
|
|
musicUnlockCount = pdata["p2d"]["params"]["music_num"]["#text"]
|
|
unlock_request = pdata["p2d"]["params"]["music"]
|
|
# Process kbinxml_data
|
|
|
|
if (int(musicUnlockCount) > 1) or type(unlock_request) == list:
|
|
print("Processing Multiple Unlocks")
|
|
for music in unlock_request:
|
|
musicID = music["music_id"]["#text"]
|
|
kind = music["kind"]["#text"]
|
|
note_bit_type = music["note_bit"]["#text"]
|
|
print(f"MusicID is {musicID}")
|
|
print(f"kind is {kind}")
|
|
print(f"note_bit is {note_bit_type}")
|
|
update_unlock_status(
|
|
variables["infinitas_id"][0], musicID, kind, note_bit_type
|
|
)
|
|
else:
|
|
musicID = unlock_request["music_id"]["#text"]
|
|
kind = unlock_request["kind"]["#text"]
|
|
note_bit_type = unlock_request["note_bit"]["#text"]
|
|
print(f"MusicID is {musicID}")
|
|
print(f"kind is {kind}")
|
|
print(f"note_bit is {note_bit_type}")
|
|
update_unlock_status(
|
|
variables["infinitas_id"][0], musicID, kind, note_bit_type
|
|
)
|
|
except Exception as e:
|
|
print(f"Error processing data: {e}")
|
|
response = KBinXML(standardIIDX.format(status="0",error="0",response='<check_sum __type="str">dummy_check_sum</check_sum>').encode()
|
|
)
|
|
binary_data = response.to_binary()
|
|
if isinstance(binary_data, str):
|
|
binary_data = binary_data.encode("utf-8")
|
|
return Respond(binary_data,IIDX_Protocol)
|
|
|
|
return "Invalid request method", 400
|
|
|
|
@bp.route("/GetRivalInfo", methods=["POST"])
|
|
def GetRivalInfo():
|
|
if request.method == "POST":
|
|
# Access post data
|
|
post_data = request.get_data().decode("UTF-8")
|
|
|
|
variables = parse_qs(post_data)
|
|
|
|
if variables["protocol_version"][0] != "P2D:2015091800":
|
|
return "Version Not Supported.", 400
|
|
# Access headers
|
|
headers = request.headers
|
|
|
|
kbinxml_data = ""
|
|
# Example: Decoding and processing data
|
|
try:
|
|
infinitas_id = variables["infinitas_id"][0]
|
|
|
|
rivals = getRivalDataFromInfID(infinitas_id) or None
|
|
rivalSPNum = 0
|
|
rivalDPNum = 0
|
|
|
|
rivalTemplate = '<rival>\n <shop_name __type="str">Infinitas</shop_name>\n <pref_id __type="s32">{rivalPerfID}</pref_id>\n <music_data>{rivalSongData}</music_data>\n <infinitas_id __type="str">{rivalInfID}</infinitas_id>\n <grade_id_sp __type="s32">{rivalDanSP}</grade_id_sp>\n <grade_id_dp __type="s32">{rivalDanDP}</grade_id_dp>\n <dj_name __type="str">{rivalName}</dj_name>\n <comment>\n <status_comment __type="str"></status_comment>\n <rival_challenge_sweeping_victory __type="str"></rival_challenge_sweeping_victory>\n <rival_challenge_narrow_victory __type="str"></rival_challenge_narrow_victory>\n </comment>\n <challenges/>\n </rival>'
|
|
spRivalsData = ""
|
|
dpRivalsData = ""
|
|
|
|
if rivals is not None:
|
|
spRivals = json.loads(rivals.spRivals)
|
|
dpRivals = json.loads(rivals.dpRivals)
|
|
for rivalInfID in spRivals:
|
|
rivalProfile = getProfileByInfID(rivalInfID)
|
|
rivalGhosts = getInfIDMusicData(rivalInfID)
|
|
rivalName = rivalProfile.name
|
|
rivalDanSP = rivalProfile.danSP
|
|
rivalDanDP = rivalProfile.danDP
|
|
rivalPerfID = rivalProfile.prefID
|
|
rivalSongData = ""
|
|
for ghost in rivalGhosts:
|
|
clearLamps = ["-1", "-1", "-1", "-1", "-1"]
|
|
scores = ["-1", "-1", "-1", "-1", "-1"]
|
|
musicID = ghost.musicID
|
|
score = json.loads(ghost.score)
|
|
rivalClearLamps = json.loads(ghost.clearFlag)
|
|
for i in range(5):
|
|
if rivalClearLamps[i] == -1:
|
|
rivalClearLamps[i] = 0
|
|
if score[i] == -1:
|
|
score[i] = 0
|
|
clearLamps = f"{rivalClearLamps[0]} {rivalClearLamps[1]} {rivalClearLamps[2]} {rivalClearLamps[3]} {rivalClearLamps[4]}"
|
|
scores = (
|
|
f"{score[0]} {score[1]} {score[2]} {score[3]} {score[4]}"
|
|
)
|
|
rivalSongData = rivalSongData + rivalClearListTemplate.format(
|
|
count=5, score=scores, clearflg=clearLamps, musicID=musicID
|
|
)
|
|
spRivalsData = spRivalsData + rivalTemplate.format(
|
|
rivalPerfID=rivalPerfID,
|
|
rivalInfID=rivalInfID,
|
|
rivalDanSP=rivalDanSP,
|
|
rivalDanDP=rivalDanDP,
|
|
rivalName=rivalName,
|
|
rivalSongData=rivalSongData,
|
|
)
|
|
for rivalInfID in dpRivals:
|
|
rivalProfile = getProfileByInfID(rivalInfID)
|
|
rivalGhosts = getInfIDMusicData(rivalInfID)
|
|
rivalName = rivalProfile.name
|
|
rivalDanSP = rivalProfile.danSP
|
|
rivalDanDP = rivalProfile.danDP
|
|
rivalPerfID = rivalProfile.prefID
|
|
rivalSongData = ""
|
|
for ghost in rivalGhosts:
|
|
clearLamps = ["-1", "-1", "-1", "-1", "-1"]
|
|
scores = ["-1", "-1", "-1", "-1", "-1"]
|
|
musicID = ghost.musicID
|
|
score = json.loads(ghost.score)
|
|
rivalClearLamps = json.loads(ghost.clearFlag)
|
|
clearLamps = f"{rivalClearLamps[5]} {rivalClearLamps[6]} {rivalClearLamps[7]} {rivalClearLamps[8]} {rivalClearLamps[9]}"
|
|
scores = (
|
|
f"{score[5]} {score[6]} {score[7]} {score[8]} {score[9]}"
|
|
)
|
|
for i in range(len(clearLamps)):
|
|
if clearLamps[i] == -1:
|
|
clearLamps[i] = 0
|
|
for i in range(len(scores)):
|
|
if scores[i] == -1:
|
|
scores[i] = 0
|
|
rivalSongData = rivalSongData + rivalClearListTemplate.format(
|
|
count=5, score=scores, clearflg=clearLamps, musicID=musicID
|
|
)
|
|
dpRivalsData = dpRivalsData + rivalTemplate.format(
|
|
rivalPerfID=rivalPerfID,
|
|
rivalInfID=rivalInfID,
|
|
rivalDanSP=rivalDanSP,
|
|
rivalDanDP=rivalDanDP,
|
|
rivalName=rivalName,
|
|
rivalSongData=rivalSongData,
|
|
)
|
|
|
|
# Define the XML data
|
|
xml_data = f"<?xml version='1.0' encoding='UTF-8'?>\n<rival_info>\n <sp>\n <rival_num __type=\"s32\">{rivalSPNum}</rival_num>\n {spRivalsData}\n </sp>\n <dp>\n <rival_num __type=\"s32\">{rivalDPNum}</rival_num>\n {dpRivalsData}\n </dp>\n</rival_info>"
|
|
|
|
# Create the KBinXML object and convert it to binary
|
|
kbinxml_data = KBinXML(xml_data.encode()).to_binary()
|
|
|
|
# Convert the binary data to hexadecimal
|
|
hex_data = kbinxml_data.hex()
|
|
|
|
# Calculate the SHA-256 hash of the hexadecimal string
|
|
hash_value = sha256(kbinxml_data).hexdigest()
|
|
rivalInfoSize = len(kbinxml_data)
|
|
|
|
# Process kbinxml_data
|
|
except Exception as e:
|
|
print(f"Error processing data: {e}")
|
|
|
|
# Calculate the SHA-256 hash of the hexadecimal string
|
|
response = KBinXML(standardIIDX.format(status="0",error="0",response=f'<result><size __type="s32">{rivalInfoSize}</size><rival_data __type="bin" __size="{rivalInfoSize}">{hex_data}</rival_data><rest_size __type="s32">0</rest_size><check_sum __type="str">{str(hash_value)}</check_sum></result>').encode()
|
|
)
|
|
|
|
binary_data = response.to_binary()
|
|
if isinstance(binary_data, str):
|
|
binary_data = binary_data.encode("utf-8")
|
|
return Respond(binary_data,IIDX_Protocol)
|
|
|
|
return "Invalid request method", 400
|
|
|
|
@bp.route("/GetMusicGhost", methods=["POST"])
|
|
def GetMusicGhost():
|
|
if request.method == "POST":
|
|
# Access post data
|
|
post_data = request.get_data().decode("UTF-8")
|
|
|
|
variables = parse_qs(post_data)
|
|
|
|
if variables["protocol_version"][0] != "P2D:2015091800":
|
|
return "Version Not Supported.", 400
|
|
# Access headers
|
|
headers = request.headers
|
|
|
|
ghostData = ""
|
|
# Example: Decoding and processing data
|
|
try:
|
|
|
|
decoded_data = b64decode(repair_base64IIDX(variables["request"][0]))
|
|
decompressed_data = lz77_decompress(decoded_data)
|
|
kbinxml_data = KBinXML(decompressed_data).to_text()
|
|
pdata = xmltodict.parse(kbinxml_data)
|
|
# Process kbinxml_data
|
|
if isinstance(pdata["p2d"]["params"]["request_ghost"], list):
|
|
# Multiple ghost requests
|
|
for ghost in pdata["p2d"]["params"]["request_ghost"]:
|
|
searchParam = ghostReqProcess(ghost, pdata, variables)
|
|
if searchParam:
|
|
ghostData = ghostData + str(searchParam)
|
|
else:
|
|
# Single ghost request
|
|
ghost = pdata["p2d"]["params"]["request_ghost"]
|
|
# Process the single ghost
|
|
print("only one ghost request, sending to the process")
|
|
searchParam = ghostReqProcess(ghost, pdata, variables)
|
|
if searchParam:
|
|
ghostData = ghostData + str(searchParam)
|
|
print("updated ghostData")
|
|
print(ghostData)
|
|
except Exception as e:
|
|
print(f"Error processing data: {e}")
|
|
|
|
print(ghostData)
|
|
response = KBinXML(
|
|
re.sub(
|
|
MusicGhostRegex,
|
|
f'<music_id __type="s32">{pdata["p2d"]["params"]["music_id"]["#text"]}</music_id>\n <note_id __type="s32">{pdata["p2d"]["params"]["note_id"]["#text"]}</note_id>\n {ghostData}',
|
|
|
|
MusicGhost,
|
|
).encode()
|
|
)
|
|
binary_data = response.to_binary()
|
|
if isinstance(binary_data, str):
|
|
binary_data = binary_data.encode("utf-8")
|
|
return Respond(binary_data,IIDX_Protocol)
|
|
|
|
return "Invalid request method", 400
|
|
|
|
def ghostReqProcess(ghost, pdata, variables):
|
|
rivalType = int(ghost["kind"]["#text"])
|
|
prefecture = ghost["pref_id"]["#text"]
|
|
danRank = ghost["grade_id"]["#text"]
|
|
musicID = pdata["p2d"]["params"]["music_id"]["#text"]
|
|
noteID = pdata["p2d"]["params"]["note_id"]["#text"]
|
|
try:
|
|
infID = ghost["infinitas_id"]["#text"]
|
|
except (KeyError, TypeError):
|
|
infID = None
|
|
|
|
try:
|
|
checkSum = ghost["ghost_check_sum"]["#text"]
|
|
except (KeyError, TypeError):
|
|
checkSum = None
|
|
|
|
if rivalType == 2:
|
|
# Look for the ghost data that matches the ghostCheck and Infinitas ID Requirements.
|
|
print()
|
|
ghostData = getGhostDataFromInfIDandCheckSum(musicID, noteID, infID, checkSum)
|
|
if ghostData:
|
|
print("Recieved Ghost Data. Sending Back Now")
|
|
return MusicGhostTemplate.format(
|
|
kind=rivalType,
|
|
ghostDataSize=ghostData.ghostSize,
|
|
ghostData=ghostData.ghost.hex(),
|
|
exScore=ghostData.score,
|
|
dj_name=ghostData.name,
|
|
flip=ghostData.flip,
|
|
assist=ghostData.assist,
|
|
arrange1=ghostData.arrange1,
|
|
arrange0=ghostData.arrange0,
|
|
)
|
|
else:
|
|
return
|
|
elif rivalType == 1:
|
|
print("RivalType is 1, not sure why this is submitted but im skipping it.")
|
|
return # Doesn't seem to need anything, this can be safely skipped without issues.
|
|
else:
|
|
# in the future, we will handle other types of Pacemaker Requests, but for now, this will be a catchall that also happens to filter out anything that doesn't match grade & prefecture, if they are set.
|
|
ghostData = randomizeGhost(
|
|
musicID, noteID, variables["infinitas_id"][0], danRank, prefecture
|
|
)
|
|
if ghostData:
|
|
print("Recieved Ghost Data. Sending Back Now")
|
|
return MusicGhostTemplate.format(
|
|
kind=rivalType,
|
|
ghostDataSize=ghostData.ghostSize,
|
|
ghostData=ghostData.ghost.hex(),
|
|
exScore=ghostData.score,
|
|
dj_name=ghostData.name,
|
|
flip=ghostData.flip,
|
|
assist=ghostData.assist,
|
|
arrange1=ghostData.arrange1,
|
|
arrange0=ghostData.arrange0,
|
|
)
|
|
else:
|
|
return
|
|
|
|
# Server Resources
|
|
|
|
@bp.route("/GetMusicList", methods=["POST"])
|
|
def getMusicList():
|
|
if request.method == "POST":
|
|
# Access post data
|
|
post_data = request.get_data().decode("UTF-8")
|
|
|
|
variables = parse_qs(post_data)
|
|
|
|
if variables["protocol_version"][0] != "P2D:2015091800":
|
|
return "Version Not Supported.", 400
|
|
# Access headers
|
|
headers = request.headers
|
|
|
|
kbinxml_data = ""
|
|
# Example: Decoding and processing data
|
|
try:
|
|
|
|
decoded_data = b64decode(repair_base64IIDX(variables["request"][0]))
|
|
decompressed_data = lz77_decompress(decoded_data)
|
|
kbinxml_data = KBinXML(decompressed_data).to_text()
|
|
player_musicList = musicList
|
|
|
|
# TODO: Regex and replace any data in the MusicList to allow for unlocks.
|
|
|
|
# Unlock any Songs that happen to be Music Packs and show the folder for it.
|
|
items = getItemsbyInfID(variables["infinitas_id"][0])
|
|
if items is not None:
|
|
music_packs = json.loads(items.musicPacks)
|
|
|
|
# Decode player_musicList once before the loop
|
|
|
|
for music_pack in music_packs:
|
|
print(music_pack)
|
|
|
|
# Update the decoded music list with each music pack
|
|
player_musicList = re.sub(
|
|
rf'<note_bit __type="s32">0</note_bit>\n <music_pack_item_id __type="str">{music_pack}</music_pack_item_id>',
|
|
f'<note_bit __type="s32">462</note_bit>\n <music_pack_item_id __type="str">{music_pack}</music_pack_item_id>',
|
|
player_musicList.decode("utf-8"),
|
|
).encode("utf-8")
|
|
# For each in infinitasMusicList
|
|
music_unlocks = getAllUnlockDataFromInfID(variables["infinitas_id"][0])
|
|
if items is not None:
|
|
for music in music_unlocks:
|
|
print(music_pack)
|
|
|
|
# Update the decoded music list with each music pack
|
|
player_musicList = re.sub(
|
|
rf'<music_id __type="s32">{music.musicID}</music_id>\n <kind __type="s32">(.+)</kind>\n <note_bit __type="s32">0</note_bit>',
|
|
f'<music_id __type="s32">{music.musicID}</music_id>\n <kind __type="s32">\\1</kind>\n <note_bit __type="s32">{music.note_bit}</note_bit>',
|
|
player_musicList.decode("utf-8"),
|
|
).encode("utf-8")
|
|
except Exception as e:
|
|
print(f"Error processing data: {e}")
|
|
response = KBinXML(player_musicList)
|
|
binary_data = response.to_binary()
|
|
if isinstance(binary_data, str):
|
|
binary_data = binary_data.encode("utf-8")
|
|
return Respond(binary_data,IIDX_Protocol)
|
|
|
|
return "Invalid request method", 400
|
|
|
|
@bp.route("/GetCustomizeSetting", methods=["POST"])
|
|
def getCustomizeSetting():
|
|
if request.method == "POST":
|
|
# Access post data
|
|
post_data = request.get_data().decode("UTF-8")
|
|
|
|
variables = parse_qs(post_data)
|
|
|
|
if variables["protocol_version"][0] != "P2D:2015091800":
|
|
return "Version Not Supported.", 400
|
|
# Access headers
|
|
headers = request.headers
|
|
|
|
customize = ""
|
|
# Example: Decoding and processing data
|
|
try:
|
|
|
|
decoded_data = b64decode(repair_base64IIDX(variables["request"][0]))
|
|
decompressed_data = lz77_decompress(decoded_data)
|
|
kbinxml_data = KBinXML(decompressed_data).to_text()
|
|
# Process kbinxml_data
|
|
# variables["infinitas_id"][0]
|
|
|
|
userData = getItemsbyInfID(variables["infinitas_id"][0])
|
|
for i, itemID in enumerate(json.loads(userData.customizations)):
|
|
if itemID != "":
|
|
customize = (
|
|
customize
|
|
+ f'\n <customize>\n <item_id __type="str">{itemID}</item_id>\n <item_category __type="s32">{i+1}</item_category>\n </customize>'
|
|
)
|
|
for i, itemID in enumerate(
|
|
json.loads(userData.otherCustomizations)
|
|
): # This will skip empty strings.
|
|
customize += f'\n <other_customize>\n <item_id __type="str">{itemID}</item_id>\n <item_category __type="s32">{i+1}</item_category>\n </other_customize>'
|
|
|
|
except Exception as e:
|
|
print(f"Error processing data: {e}")
|
|
response = KBinXML(
|
|
standardIIDX.format(status="0",error="0",response=customize).encode()
|
|
)
|
|
# response = KBinXML(playerCustomizations) # TODO: IMPLEMENT Customization Options per Profile
|
|
binary_data = response.to_binary()
|
|
if isinstance(binary_data, str):
|
|
binary_data = binary_data.encode("utf-8")
|
|
return Respond(binary_data,IIDX_Protocol)
|
|
|
|
return "Invalid request method", 400
|
|
|
|
@bp.route("/ReportMusicResult", methods=["POST"])
|
|
def reportMusicResult():
|
|
if request.method == "POST":
|
|
# Access post data
|
|
post_data = request.get_data().decode("UTF-8")
|
|
|
|
variables = parse_qs(post_data)
|
|
|
|
if variables["protocol_version"][0] != "P2D:2015091800":
|
|
return "Version Not Supported.", 400
|
|
# Access headers
|
|
headers = request.headers
|
|
|
|
kbinxml_data = ""
|
|
# Example: Decoding and processing data
|
|
try:
|
|
decoded_data = b64decode(repair_base64IIDX(variables["request"][0]))
|
|
decompressed_data = lz77_decompress(decoded_data)
|
|
kbinxml_data = KBinXML(decompressed_data).to_text()
|
|
data = xmltodict.parse(kbinxml_data)
|
|
profile = getProfileByInfID(variables["infinitas_id"][0])
|
|
if int(data["p2d"]["params"]["note_id"]["#text"]) >= 6:
|
|
danRank = profile.danDP
|
|
else:
|
|
danRank = profile.danSP
|
|
|
|
if data["p2d"]["params"].get("ghost", {}):
|
|
scoreGhost = bytes.fromhex(data["p2d"]["params"]["ghost"]["#text"])
|
|
scoreGhostCheck = data["p2d"]["params"]["ghost_check_sum"]["#text"]
|
|
scoreGhostSize = data["p2d"]["params"]["ghost"]["@__size"]
|
|
manage_ghost_data(
|
|
variables["infinitas_id"][0],
|
|
profile.name,
|
|
data["p2d"]["params"]["score"]["#text"],
|
|
danRank,
|
|
profile.prefID,
|
|
data["p2d"]["params"]["music_id"]["#text"],
|
|
data["p2d"]["params"]["note_id"]["#text"],
|
|
scoreGhost,
|
|
scoreGhostCheck,
|
|
scoreGhostSize,
|
|
data["p2d"]["params"]["flip"]["#text"],
|
|
data["p2d"]["params"]["assist"]["#text"],
|
|
data["p2d"]["params"]["arrange_1"]["#text"],
|
|
data["p2d"]["params"]["arrange_0"]["#text"],
|
|
data["p2d"]["params"]["clear_flag"]["#text"],
|
|
)
|
|
# Process kbinxml_data
|
|
manage_music_data(
|
|
variables["infinitas_id"][0],
|
|
data["p2d"]["params"]["music_id"]["#text"],
|
|
data["p2d"]["params"]["note_id"]["#text"],
|
|
data["p2d"]["params"]["score"]["#text"],
|
|
data["p2d"]["params"]["miss_count"]["#text"],
|
|
data["p2d"]["params"]["clear_flag"]["#text"],
|
|
)
|
|
|
|
# TODO: IMPLEMENT Song Play Save
|
|
except Exception as e:
|
|
print(f"Error processing data: {e}")
|
|
response = KBinXML(genericError.format(protocol=IIDX_XML,result=IIDX_RESULT))
|
|
binary_data = response.to_binary()
|
|
if isinstance(binary_data, str):
|
|
binary_data = binary_data.encode("utf-8")
|
|
return Respond(binary_data,IIDX_Protocol)
|
|
|
|
return "Invalid request method", 400
|
|
|
|
@bp.route("/GameEnd", methods=["POST"])
|
|
def GameEnd():
|
|
if request.method == "POST":
|
|
# Access post data
|
|
post_data = request.get_data().decode("UTF-8")
|
|
|
|
variables = parse_qs(post_data)
|
|
|
|
if variables["protocol_version"][0] != "P2D:2015091800":
|
|
return "Version Not Supported.", 400
|
|
# Access headers
|
|
headers = request.headers
|
|
|
|
kbinxml_data = ""
|
|
# Example: Decoding and processing data
|
|
try:
|
|
|
|
decoded_data = b64decode(repair_base64IIDX(variables["request"][0]))
|
|
decompressed_data = lz77_decompress(decoded_data)
|
|
kbinxml_data = KBinXML(decompressed_data).to_text()
|
|
pdata = xmltodict.parse(kbinxml_data)
|
|
# Process kbinxml_data
|
|
sStartTime = pdata["p2d"]["params"]["start_clock"]["#text"]
|
|
sEndTime = pdata["p2d"]["params"]["end_clock"]["#text"]
|
|
print(
|
|
"SessionStart: {start}\nSessionEnd: {end}".format(
|
|
start=sStartTime, end=sEndTime
|
|
)
|
|
)
|
|
except Exception as e:
|
|
print(f"Error processing data: {e}")
|
|
response = KBinXML(genericError.format(protocol=IIDX_XML,result=IIDX_RESULT))
|
|
binary_data = response.to_binary()
|
|
if isinstance(binary_data, str):
|
|
binary_data = binary_data.encode("utf-8")
|
|
return Respond(binary_data,IIDX_Protocol)
|
|
|
|
return "Invalid request method", 400
|