Files
2026-01-26 18:48:28 -05:00

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