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 = '\n {itemID}\n 1\n 0\n ' defaultItems = '\n I1000000\n {TicketsPaid}\n {TicketsFree}\n \n \n I1000001\n {lDiscs}\n 0\n ' # 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'15000', f'{bitCount}', 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='\n1\n\nP0100000\n{bits}\n\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'{TicketsPaid}\n {TicketsFree}\n' else: itemTemplate = f'{lDiscs}\n 0\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'{TicketsPaid}\n {TicketsFree}\n' else: itemTemplate = f'{lDiscs}\n 0\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'{playStyle}' response = KBinXML( re.sub( r"\n", f"\n{profileMusicData}\n", 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='dummy_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 = '\n Infinitas\n {rivalPerfID}\n {rivalSongData}\n {rivalInfID}\n {rivalDanSP}\n {rivalDanDP}\n {rivalName}\n \n \n \n \n \n \n ' 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"\n\n \n {rivalSPNum}\n {spRivalsData}\n \n \n {rivalDPNum}\n {dpRivalsData}\n \n" # 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'{rivalInfoSize}{hex_data}0{str(hash_value)}').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'{pdata["p2d"]["params"]["music_id"]["#text"]}\n {pdata["p2d"]["params"]["note_id"]["#text"]}\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'0\n {music_pack}', f'462\n {music_pack}', 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.musicID}\n (.+)\n 0', f'{music.musicID}\n \\1\n {music.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 \n {itemID}\n {i+1}\n ' ) for i, itemID in enumerate( json.loads(userData.otherCustomizations) ): # This will skip empty strings. customize += f'\n \n {itemID}\n {i+1}\n ' 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