#!/usr/bin/python3 import sqlite3 import json import sys import os import MAPPING """ Reads the API KEY, that must be passed as first command line argument. :returns: Recovered API KEY. :raises Exception: Th KEY couldn't be red. """ def readKey(): try: key = sys.argv[1] return key except Exception as e: print("Error parsing API KEY: " + str(e)) raise """ Reads the JSON data, that must be passed as second command line argument. :param: index 2 for start data, 3 for result data :returns: Recovered data, in JSON format. :raises Exception: The data couldn't be red or converted to JSON. """ def readData(index): try: data = json.loads(sys.argv[index]) return data except Exception as e: print("Error parsing data: " + str(e)) raise """ Verifies that the API key matches the player data and that it exists in th DB. :param db: Connection to the database. :returns: Connection to the database. :param data: Data in json format. :param key: API KEY. :returns: True if key and player match, False otherwise. :raises IntegrityError: The queryes couldn't bre executed. """ def verifyKey(db, data, key): print('Verifying KEY...') status = False try: uid = data["wizard_info"]["wizard_id"] cursor = db.cursor() cursor.execute('SELECT count(uid) AS c FROM player WHERE uid = ? AND api_key = ?;', (uid, key)) if cursor.fetchone()[0] == 1: status = True cursor.close() except sqlite3.IntegrityError as e: print("Error executing statement: " + str(e)) raise return status """ Opens the database file and deletes from the user tables :param name: The path to the sqlite database. :returns: Connection to the database. :raises IntegrityError: The queryes couldn't bre executed. :raises IOError: The sqlite file couldn't be created. """ def openDatabase(): kdb = os.path.dirname(os.path.realpath(sys.argv[0])) + '/../../../sw.sqlite' udb = os.path.dirname(os.path.realpath(sys.argv[0])) + '/../../../../data/sw.sqlite' print('Configuring database...') try: db = sqlite3.connect(kdb) cursor = db.cursor() cursor.execute('attach "' + udb + '" as data;') cursor.close() return db except sqlite3.IntegrityError as e: print("Error executing statement: " + str(e)) raise except IOError as e: print("I/O Error creating database " + name + ": " + str(e)) raise """ Inserts a row into the database. :param db: Connection to the database. :param table: Name of the table to insert into. :param values: List of values to insert. :raises IntegrityError: The insert query was unsuccesfull. """ def insert(db, table, values): cursor = db.cursor() placeholders = '' for x in range(0, len(values)): placeholders = placeholders + '?, ' placeholders = placeholders[:len(placeholders) - 2] query = 'INSERT INTO ' + table + ' VALUES (' + placeholders + ')' try: cursor.execute(query, values) except sqlite3.IntegrityError as e: print('Error Inserting into ' + table + ' with values (' + str(values) + '): ' + str(e)) raise cursor.close; """ Parses run data (tables run, run_party, run_drop_rune, run_drop_runecraft, run_drop_item, run_drop_unit, run_drop_sd, run_drop_unit_pieces, run_drop_shapeshifting). :param db: Sqlite database connection. :param data_start: JSON data of the run start. :param data_result: JSON data of the run result. """ def parseRun(db, data_request, data_response): print("Parsing run...") cursor = db.cursor() # Read basic data uid = data_request["wizard_id"] dtime = data_response["tvaluelocal"] # Check if run has already been inserted. cursor.execute("SELECT count(id) AS c FROM run WHERE uid = ? AND dtime = ?;", (uid, dtime)) if (cursor.fetchone()[0] > 0): print(" Run already in database. Stopping....") return 409; # We are inserting, get aditional info area_type = 2 # Cairos Dungeon area = data_request["dungeon_id"] stage = data_request["stage_id"] difficulty = None win = data_response["win_lose"] time = data_response["clear_time"]["current_time"] if ("mana" in data_response["reward"]): mana = data_response["reward"]["mana"] else: mana = 0 if ("energy" in data_response["reward"]): energy = mana = data_response["reward"]["energy"] else: energy = 0 if ("crystal" in data_response["reward"]): crystal = mana = data_response["reward"]["crystal"] else: crystal = 0 # TODO Read helper. Do a test with SWBD-debug helper = 0 # GEt the new ID and insert cursor.execute("SELECT max(id) + 1 AS id FROM run;") id = cursor.fetchone()[0] if id == None: id = 1 score = None rank = None insert(db, "run", (uid, id, dtime, area_type, area, stage, difficulty, win, time, mana, energy, crystal, helper, score, rank)) # Parse various types of reward crate = data_response["reward"]["crate"] if "costume_point" in crate and crate["costume_point"] > 0: insert(db, "run_drop_shapeshifting", (id, crate["costume_point"])) if "instance_info" in data_response: insert(db, "run_drop_sd", (id, data_response["instance_info"])) if "unit_info" in crate: insert(db, "run_drop_unit", (id, crate["unit_info"]["unit_master_id"])) if "summon_pieces" in crate: insert(db, "run_drop_unit_pieces", (id, crate["summon_pieces"]["item_master_id"], crate["summon_pieces"]["item_quantity"])) if "item" in crate: for item in crate["item"]: insert(db, "run_drop_item", (id, item["item_id"], item["item_quantity"])) # Parse rune reward if "rune" in crate: rune = crate["rune"] rune_id = rune["rune_id"] rune_type = rune["set_id"] slot = rune["slot_no"] stars = rune["class"] ancient = 0 quality = rune["rank"] value = rune["sell_value"] efficiency, max_efficiency = MAPPING.calculate_efficiency(rune) main_stat = rune["pri_eff"][0] main_stat_value = rune["pri_eff"][1] if "prefix_eff" in rune: innate_stat = rune["prefix_eff"][0] innate_stat_value = rune["prefix_eff"][1] else: innate_stat = 0 innate_stat_value = 0 substat_1 = 0 substat_1_value = 0 substat_2 = 0 substat_2_value = 0 substat_3 = 0 substat_3_value = 0 substat_4 = 0 substat_4_value = 0 if "0" in rune["sec_eff"]: substat_1 = rune["sec_eff"]["0"]["0"] substat_1_value = rune["sec_eff"]["0"]["1"] if "1" in rune["sec_eff"]: substat_1 = rune["sec_eff"]["1"]["0"] substat_1_value = rune["sec_eff"]["1"]["1"] if "2" in rune["sec_eff"]: substat_1 = rune["sec_eff"]["2"]["0"] substat_1_value = rune["sec_eff"]["2"]["1"] if "3" in rune["sec_eff"]: substat_1 = rune["sec_eff"]["3"]["0"] substat_1_value = rune["sec_eff"]["3"]["1"] insert(db, "run_drop_rune", (id, rune_id, rune_type, slot, stars, ancient, quality, value, efficiency, max_efficiency, main_stat, main_stat_value, innate_stat, innate_stat_value, substat_1, substat_1_value, substat_2, substat_2_value, substat_3, substat_3_value, substat_4, substat_4_value)) # Parse units #for attribute, value in data_request["unit_id_list"]: for unit in data_request["unit_id_list"]: unit_id = unit["unit_id"] unit_master_id = None for k_unit in data_response["unit_list"]: if k_unit["unit_id"] == unit["unit_id"]: unit_master_id = k_unit["unit_master_id"]; break; #unit_master_id = data_response["unit_list"][attribute]["unit_master_id"] leader = unit["is_leader"] front = 0 insert(db, "run_party", (id, unit_master_id, unit_id, leader, front)) db.commit() """ Begin script """ data_request = readData(2) data_response = readData(3) key = readKey() db = openDatabase() if verifyKey(db, data_response, key) == False: print("Invalid API KEY...") sys.exit(401) else: #try: parseRun(db, data_request, data_response) #except Exception as e: # print("Error parsing dungeon run: " + str(e)) # sys.exit(400) sys.exit(201)