def subtract_balance(user_id, amount): storage.sql( """ UPDATE progress SET tokens_got = tokens_got - ?, tokens_used = tokens_used + ? WHERE user_id = ? """, (amount, amount, user_id))
def appApiUserData(environ, start_response): username = environ['PATH_INFO'].split('/')[-1].split('?')[0] user = storage.sql(''' SELECT * FROM users WHERE username=? ''', (username,)) if not user: start_response('200 OK', HEADERS_JSON + HEADERS_CORS) return [util.json_bytes({'error': 1, 'message': 'No such user.'})] storage.recalculate_player_achievements(user[0]['id']) data = storage.sql(''' SELECT username, points, achievements, users.id AS id FROM users LEFT OUTER JOIN leaderboard ON leaderboard.user_id = users.id WHERE username = ? ''', (username,)) if not data: start_response('200 OK', HEADERS_JSON + HEADERS_CORS) return [util.json_bytes({'error': 1, 'message': 'No such user.'})] data = data[0] data['achievements'] = json.loads(data['achievements']) start_response('200 OK', HEADERS_JSON + HEADERS_CORS) return [util.json_bytes({'error': 0, 'data': data})]
def appRequest(environ, start_response): #print("ASD") data_len = int(environ.get('CONTENT_LENGTH', 0)) data = urllib.parse.parse_qs(environ['wsgi.input'].read(data_len).decode('utf-8'), keep_blank_values=True) #print(data) user = storage.get_user_data(data['username'][0]) if user: start_response('200 OK', HEADERS_JSON + HEADERS_CORS) return [util.json_bytes({'error': 2, 'message': 'Username already exists.'})] if not re.match('^[A-Za-z0-9]{1,15}$', data['username'][0]): start_response('200 OK', HEADERS_JSON + HEADERS_CORS) return [util.json_bytes({'error': 4, 'message': 'Invalid username.'})] if len(data['password'][0]) < 7: start_response('200 OK', HEADERS_JSON + HEADERS_CORS) return [util.json_bytes({'error': 4, 'message': 'Password should be at least 7 characters long.'})] storage.sql(''' INSERT INTO users (username, password, mon) VALUES (?, ?, ?) ''', ( data['username'][0], util.password_hash(data['password'][0]), '{"species": "CHARMANDER", "mon_name": "Shadow", "moves": ["SCRATCH"], "name": "X", "items": [1,2,3,4,0,0,0,0]}' )) user = storage.get_user_data(data['username'][0]) key = util.new_session_key() storage.sql(''' UPDATE users SET sessid=? WHERE id=? ''', (key, user['id'])) print("New user!", user['username']) start_response('200 OK', HEADERS_JSON + HEADERS_CORS) return [util.json_bytes({'error': 0, 'message': 'OK'})]
def requestHandlerChangeFunValue(request, sessid): user = storage.get_user_by_sessid(sessid) if not user: raise RuntimeError("invalid session key") storage.sql('UPDATE users SET fun=? WHERE id=?', (random.randrange(0, 255), user['id'])) return [random.randrange(0, 255), random.randrange(0, 255)]
def queue_compilation(user_id, kingdom): logger.log(TAG, "queueing job (%i, %s)" % (user_id, kingdom)) storage.sql(""" INSERT INTO queue (user_id, kingdom) VALUES (?, ?) """, (user_id, kingdom)) poke_compiler_thread()
def store(user_id, value): i = augment_states[user_id].id logger.log(TAG, "user_id %i augmented `%s` to `%s`" % (user_id, i, value)) storage.sql( """ UPDATE augments SET content = ? WHERE augment = ? """, (value, i)) update_augment_map() augment_states[user_id] = {}
def appRequest(environ, start_response): start_response('200 OK', HEADERS_CORS, HEADERS_TEXT) credentials = util.get_raw_post(environ).split(b"|") username = base64.b64decode(credentials[0]).decode("utf-8") password = util.password_hash(base64.b64decode(credentials[1]).decode("utf-8")) q = storage.sql("select id from users where username=? and password=?", (username, password)) if q: sessid = util.new_session_key() storage.sql("update users set sessid=? where id=?", (sessid, q[0]["id"])) return [bytes(sessid, "ascii")] else: return [b"INVAL"]
def appApiChangeMessage(environ, start_response): data_len = int(environ.get('CONTENT_LENGTH', 0)) data = urllib.parse.parse_qs(environ['wsgi.input'].read(data_len).decode('utf-8'), keep_blank_values=True) if len(data['message'][0]) > 120: start_response('200 OK', HEADERS_JSON + HEADERS_CORS) return [util.json_bytes({'error': 2, 'message': 'Message too long.'})] storage.sql(''' UPDATE users SET message=? WHERE session=? ''', (data['message'][0], data['sessid'][0])) start_response('200 OK', HEADERS_JSON + HEADERS_CORS) return [util.json_bytes({'error': 0, 'message': 'OK'})]
def appRequest(environ, start_response): #print("LOGIN") start_response('200 OK', HEADERS_JSON + HEADERS_CORS) data_len = int(environ.get('CONTENT_LENGTH', 0)) data = urllib.parse.parse_qs(environ['wsgi.input'].read(data_len).decode('utf-8'), keep_blank_values=True) username = data['username'][0] password = data['password'][0] q = util.checkUserLogin(username, password) if q != None: sessid = util.new_session_key() storage.sql("update users set sessid=? where id=?", (sessid, q["id"])) return [util.json_bytes({'error': 0, 'sessid': sessid})] else: return [util.json_bytes({'error': 1, 'message': 'Invalid username and/or password.'})]
def battle_packet_handler(data, player_data): if data[0] == 1: q = storage.sql("select battle_data from last_battle where id=?", (player_data["id"], )) return bytearray(q[0]["battle_data"]) print(data) rnd_items_1 = [] rnd_items_2 = [] for i in range(0, 8): rnd_items_1.append(random.choice(list(items.ITEM_CLASSES.keys()))) for i in range(0, 8): rnd_items_2.append(random.choice(list(items.ITEM_CLASSES.keys()))) rnd_state = { "species": random.choice(list(resources.MON_DATA.keys())), "mon_name": "Shadow", "moves": ["SCRATCH"], "name": "X", "items": rnd_items_1 } attacking_player = json.loads(player_data["mon"]) defending_player = trainerloader.load_trainer(data[2] * 256 + data[1]) b = battle.battle(attacking_player, defending_player) r = bytearray( bytes(defending_player["items"]) + # attacker items bytes(attacking_player["items"]) + # defender items bytes([defending_player["class_id"]]) + # trainer class id bytes(util.bcd(defending_player["bp_reward"])) + # bp reward bytes(util.bcd(defending_player["credits_reward"])) + # credit reward bytes([ resources.MON_DATA[attacking_player["species"]]["mon_numeric_id"] ]) + # attacker species id bytes([ resources.MON_DATA[defending_player["species"]]["mon_numeric_id"] ]) + # defender species id bytes(util.parse_text(defending_player["name"], 21)) + # defender name b.log_bytes() # offset to stringbuf, battle data, stringbuf ) print(r) storage.sql( """ update last_battle set battle_data=? where id=? """, (r, player_data["id"])) return r
def appTravel(environ, start_response): data = util.get_json_post(environ) user = storage.get_user_by_sessid(data.sessid) if user is None: start_response('200 OK', HEADERS_JSON + HEADERS_CORS) return [util.err_json("You are not logged in.")] logger.bigbrother("/travel", user, environ) q = storage.sql( """ SELECT users.id AS id, leaderboard.achievements AS achievements, progress.visited_kingdoms AS kingdoms, progress.cur_kingdom AS cur_kingdom, progress.save_uid AS save_uid, progress.cur_visit_started AS cur_visit_started FROM users LEFT OUTER JOIN progress ON progress.user_id = users.id LEFT OUTER JOIN leaderboard ON leaderboard.user_id = users.id WHERE users.id = ? """, (user.id, ))[0] visit_delay = util.time_delta(q.cur_visit_started, config.RATELIMIT_VISIT_KINGDOM) if visit_delay and user.id != config.ADMIN_USER_ID: start_response('200 OK', HEADERS_JSON + HEADERS_CORS) return [ util.err_json( "You need to wait %i more seconds before visiting a new kingdom." % visit_delay) ] if q.cur_kingdom != 'none' or q.save_uid: start_response('200 OK', HEADERS_JSON + HEADERS_CORS) return [util.err_json("You are already visiting a kingdom.")] kingdoms = json.loads(q.kingdoms) achievements = json.loads(q.achievements) if not checks.is_kingdom_accessible(data.kingdom, kingdoms, achievements): start_response('200 OK', HEADERS_JSON + HEADERS_CORS) return [util.err_json("You can't access this kingdom yet.")] storage.sql( """ UPDATE progress SET cur_kingdom = ?, cur_visit_started = ?, save_uid = '' WHERE user_id = ? """, (data.kingdom, util.unix_time(), user.id)) compiler.queue_compilation(user.id, data.kingdom) start_response('200 OK', HEADERS_JSON + HEADERS_CORS) return [util.json_bytes({"success": True})]
def appAugmentInfo(environ, start_response): data = util.get_json_post(environ) user = storage.get_user_by_sessid(data.sessid) if user is None: start_response('200 OK', HEADERS_JSON + HEADERS_CORS) return [util.err_json("You are not logged in.")] logger.bigbrother("/augment/info", user, environ) captcha_needed = ratelimiter.get_suspicion_counter(user.id) >= 3 q = storage.sql( """ SELECT visited_kingdoms FROM progress WHERE user_id = ? """, (user.id, ))[0] result = { "success": True, "captcha": captcha_needed, "augmentables": [ x for x in json.loads(q.visited_kingdoms) if x in config.AUGMENTABLE_KINGDOMS ] } start_response('200 OK', HEADERS_JSON + HEADERS_CORS) return [util.json_bytes(result)]
def get_balance(user_id): return int( storage.sql( """ SELECT tokens_got FROM progress WHERE user_id = ? """, (user_id, ))[0].tokens_got)
def compiler_handle_jobs(): jobs = storage.sql(""" SELECT user_id, kingdom FROM queue WHERE save_uid IS NULL ORDER BY id """) for job in jobs: logger.log(TAG, "compiling job (%i, %s)" % (job.user_id, job.kingdom)) storage.sql(""" UPDATE queue SET save_uid = '_' WHERE user_id = ? """, (job.user_id,)) session = util.get_compiler_session(job.user_id) if os.path.exists(SAV_DIRECTORY + "/fools.sav"): os.remove(SAV_DIRECTORY + "/fools.sav") save_uid = "_" if compile_single_save(session): filename = util.new_save_file_name(job.user_id) shutil.copy( SAV_DIRECTORY + "/fools.sav", DATA_DIRECTORY + "/save/" + filename + ".sav" ) storage.sql(""" UPDATE progress SET save_uid = ? WHERE user_id = ? AND cur_kingdom = ? """, (filename, job.user_id, session['current_kingdom_undecorated'])) storage.sql(""" UPDATE queue SET save_uid = ? WHERE user_id = ? """, (filename, job.user_id)) logger.log(TAG, "job (%i, %s) completed" % (job.user_id, job.kingdom))
def token_grant_thread(): logger.log(TAG, "token granting thread started") while 1: for i in range(0, 15): time.sleep(60) logger.log(TAG, "granting 1 extra token for blessed users") storage.sql(""" UPDATE progress SET tokens_got = tokens_got + 1 WHERE laylah_blessing = 1 """) for i in range(0, 15): time.sleep(60) logger.log(TAG, "granting 1 extra token for everyone") storage.sql(""" UPDATE progress SET tokens_got = tokens_got + 1 """)
def appApiScoreboard(environ, start_response): leaderboard = storage.sql(''' SELECT username, points FROM leaderboard LEFT OUTER JOIN users ON leaderboard.user_id = users.id WHERE username <> 'TheZZAZZGlitch' ORDER BY points DESC ''') start_response('200 OK', HEADERS_JSON + HEADERS_CORS) return [util.json_bytes({'error': 0, 'data': leaderboard})]
def appUserProfile(environ, start_response): data = util.get_json_post(environ) user = storage.get_user_by_sessid(data.sessid) q = storage.sql( """ SELECT users.username AS username, users.message AS message, users.registered_ip AS ip, progress.tokens_used AS tokens_spent, progress.visited_kingdoms AS kingdoms, progress.save_blob AS save_data, progress.save_uid AS save_uid, progress.cur_kingdom AS cur_kingdom, leaderboard.score AS score, leaderboard.highest_rank AS highest_rank, leaderboard.achievements AS achievements FROM users LEFT OUTER JOIN leaderboard ON leaderboard.user_id = users.id LEFT OUTER JOIN progress ON progress.user_id = users.id WHERE username = ? """, (data.user, )) if not q: start_response('200 OK', HEADERS_JSON + HEADERS_CORS) return [util.err_json("This user does not exist.")] q = q[0] result = { "success": True, "username": q.username, "score": q.score, "tokens_spent": q.tokens_spent, "kingdoms_visited": len(json.loads(q.kingdoms)), "current_rank": q.current_rank, "highest_rank": q.highest_rank, "achievements": json.loads(q.achievements) } if user is not None and user.id == config.ADMIN_USER_ID: save_data = json.loads(q.save_data) html = "<b>Message:</b> %1<br>" html += "<b>Visited kingdoms:</b> %2<br>" html += "<b>Current kingdom:</b> %3<br>" html += "<b>Registered IP address:</b> %4<br>" html += "<br>Event flag status:<br><br><div style='overflow-y:scroll;width:100%;height:200px;border:1px solid #ccc;padding:8px'>" flags = [i for i in dir(event_flags) if i.startswith("EVENT_")] flags.sort(key=lambda x: eval("event_flags.%s" % x)) for flag in flags: if save_data["events"][eval("event_flags.%s" % flag)]: html += "<b style='color:green'>%s = True</b><br>" % flag else: html += "<span style='color:red'>%s = False</span><br>" % flag html += "</div><br><b>Save file name if exists:</b><br>`%s`" % q.save_uid result["admin"] = [html, q.message, q.kingdoms, q.cur_kingdom, q.ip] start_response('200 OK', HEADERS_JSON + HEADERS_CORS) return [util.json_bytes(result)]
def appApiLogin(environ, start_response): data_len = int(environ.get('CONTENT_LENGTH', 0)) data = urllib.parse.parse_qs(environ['wsgi.input'].read(data_len).decode('utf-8'), keep_blank_values=True) user = storage.sql(''' SELECT * FROM users WHERE username=? AND password=? ''', (data['username'][0], util.password_hash(data['password'][0]))) if not user: start_response('200 OK', HEADERS_JSON + HEADERS_CORS) return [util.json_bytes({'error': 1, 'message': 'Invalid username and/or password.'})] user = user[0] key = util.new_session_key() storage.sql(''' UPDATE users SET session=? WHERE id=? ''', (key, user['id'])) start_response('200 OK', HEADERS_JSON + HEADERS_CORS) return [util.json_bytes({'error': 0, 'sessid': key})]
def checkUserLogin(user, password): q = storage.sql("select * from users where username=?", (user, )) if q: q = q[0] pw = q["password"].split("$") h = password_hash(password, salt=pw[0]) if (h == q["password"]): print("Login confirmed for user", user) return q print("Login failed for user", user) return None
def update(user_id, session, save_data): q = storage.sql( """ SELECT achievements, score, highest_rank FROM leaderboard WHERE user_id = ? """, (user_id, ))[0] old_achievements = json.loads(q.achievements) new_achievements = copy.deepcopy(old_achievements) for k, v in ACHIEVEMENTS.items(): if v(save_data, session): new_achievements[k] = True rewards = calc_pending_rewards(old_achievements, new_achievements) monsters = generate_monsters(save_data) storage.sql( """ UPDATE progress SET tokens_got = tokens_got + ? WHERE user_id = ? """, (rewards[1], user_id)) if rewards[0]: storage.sql( """ UPDATE leaderboard SET last_update = ? WHERE user_id = ? """, (util.unix_time(), user_id)) storage.sql( """ UPDATE leaderboard SET score = score + ?, achievements = ?, monsters = ? WHERE user_id = ? """, (rewards[0], json.dumps(new_achievements), json.dumps(monsters), user_id)) storage.sql( """ UPDATE leaderboard SET highest_rank = MIN(highest_rank, ( SELECT COUNT(1) FROM leaderboard WHERE score >= (SELECT score FROM leaderboard WHERE user_id = ?) )) WHERE user_id = ? """, (user_id, user_id))
def appDoPing(environ, start_response): session_key = environ['PATH_INFO'].split('/')[-1] q = storage.sql( """ SELECT users.id AS id, users.username AS username, progress.tokens_got AS tokens, progress.cur_kingdom AS cur_kingdom, progress.cur_visit_started AS visit_started, progress.visited_kingdoms AS kingdoms, progress.save_uid AS save_uid, leaderboard.achievements AS achievements, leaderboard.score AS points FROM users LEFT OUTER JOIN progress ON progress.user_id = users.id LEFT OUTER JOIN leaderboard ON leaderboard.user_id = users.id WHERE sessid=? """, (session_key, )) response = {"success": True, "logged_in": False} if q: logger.bigbrother("/ping", { 'sessid': session_key, 'id': q[0].id }, environ) response = { "success": True, "username": q[0].username, "id": q[0].id, "tokens": q[0].tokens, "cur_kingdom": q[0].cur_kingdom, "visit_started": q[0].visit_started, "points": q[0].points, "save_uid": q[0].save_uid } achievements = json.loads(q[0].achievements) kingdoms = json.loads(q[0].kingdoms) response["pwnzord_i"] = checks.is_kingdom_accessible( "pwnage01", kingdoms, achievements) response["pwnzord_ii"] = checks.is_kingdom_accessible( "pwnage02", kingdoms, achievements) response["pwnzord_iii"] = checks.is_kingdom_accessible( "pwnage03", kingdoms, achievements) response["pwnzord_iv"] = checks.is_kingdom_accessible( "pwnage04", kingdoms, achievements) response["completionist"] = checks.is_kingdom_accessible( "last", kingdoms, achievements) response["central_unlocked"] = checks.is_kingdom_accessible( "final", kingdoms, achievements) response["kingdoms_visited"] = len(kingdoms) response["logged_in"] = True start_response('200 OK', HEADERS_JSON + HEADERS_CORS) return [util.json_bytes(response)]
def appQueueGiveUp(environ, start_response): data = util.get_json_post(environ) user = storage.get_user_by_sessid(data.sessid) if user is None: start_response('200 OK', HEADERS_JSON + HEADERS_CORS) return [util.err_json("You are not logged in.")] logger.bigbrother("/queue_give_up", user, environ) storage.sql( """ UPDATE queue SET save_uid = '_' WHERE user_id = ? """, (user.id, )) storage.sql( """ UPDATE progress SET cur_kingdom = 'none', save_uid = '' WHERE user_id = ? """, (user.id, )) start_response('200 OK', HEADERS_JSON + HEADERS_CORS) return [util.json_bytes({"success": True})]
def appLogin(environ, start_response): data = util.get_json_post(environ) username = data.username password = util.password_hash(data.password) q = storage.sql( """ SELECT id FROM users WHERE username = ? AND password = ? """, (username, password)) if not q: start_response('200 OK', HEADERS_JSON + HEADERS_CORS) return [util.err_json("Invalid username and/or password.")] uid = q[0].id sessid = util.new_session_key() logger.log( TAG, "uid %i logged in from ip %s" % (uid, util.get_real_ip(environ))) storage.sql( """ UPDATE users SET sessid = ? WHERE id = ? """, (sessid, uid)) start_response('200 OK', HEADERS_JSON + HEADERS_CORS) return [util.json_bytes({"success": True, "sessid": sessid})]
def appLeaveNoSave(environ, start_response): data = util.get_json_post(environ) user = storage.get_user_by_sessid(data.sessid) if user is None: start_response('200 OK', HEADERS_JSON + HEADERS_CORS) return [util.err_json("You are not logged in.")] logger.bigbrother("/leave_no_save", user, environ) q = storage.sql( """ SELECT cur_kingdom, save_uid FROM progress WHERE user_id = ? """, (user.id, ))[0] if q.cur_kingdom == 'none' or not q.save_uid: start_response('200 OK', HEADERS_JSON + HEADERS_CORS) return [util.err_json("You are not visiting a kingdom.")] storage.sql( """ UPDATE progress SET cur_kingdom = 'none', save_uid = '' WHERE user_id = ? """, (user.id, )) start_response('200 OK', HEADERS_JSON + HEADERS_CORS) return [util.json_bytes({"success": True})]
def init(): global wordnet_adjectives, wordnet_nouns, wordnet_verbs sects = augments.sections() logger.log(TAG, "init: populating %i augments" % len(sects)) for i in sects: try: storage.sql(""" INSERT INTO augments (augment, content) VALUES (?, ?) """, (i, augments[i]["Default"]), log_errors=False) except: pass update_augment_map() logger.log(TAG, "init: loading wordnet databases") wordnet_nouns = wordnet_load(WORDNET_DIRECTORY + "/index.noun") logger.log(TAG, "init: %i nouns loaded" % len(wordnet_nouns)) wordnet_adjectives = wordnet_load(WORDNET_DIRECTORY + "/index.adj") logger.log(TAG, "init: %i adjectives loaded" % len(wordnet_adjectives)) wordnet_verbs = wordnet_load(WORDNET_DIRECTORY + "/index.verb") logger.log(TAG, "init: %i verbs loaded" % len(wordnet_verbs)) logger.log(TAG, "init: finished")
def appSetRTC(environ, start_response): data = util.get_json_post(environ) user = storage.get_user_by_sessid(data.sessid) if user is None: start_response('200 OK', HEADERS_JSON + HEADERS_CORS) return [util.err_json("You are not logged in.")] logger.bigbrother("/set_rtc", user, environ) val = 1 if int(data.rtc) else 0 q = storage.sql( """ UPDATE users SET rtc = ? WHERE id = ? """, (val, user.id)) start_response('200 OK', HEADERS_JSON + HEADERS_CORS) return [util.json_bytes({"success": True})]
def appGetSettings(environ, start_response): data = util.get_json_post(environ) user = storage.get_user_by_sessid(data.sessid) if user is None: start_response('200 OK', HEADERS_JSON + HEADERS_CORS) return [util.err_json("You are not logged in.")] logger.bigbrother("/get_settings", user, environ) q = storage.sql( """ SELECT message, rtc FROM users WHERE id = ? """, (user.id, ))[0] result = {"success": True, "message": q.message, "rtc": q.rtc} start_response('200 OK', HEADERS_JSON + HEADERS_CORS) return [util.json_bytes(result)]
def appQueueGetSaveBytes(environ, start_response): session_key = environ['PATH_INFO'].split('/')[-1] user = storage.get_user_by_sessid(session_key) if user is None: start_response('200 OK', HEADERS_JSON + HEADERS_CORS) return [util.err_json("You are not logged in.")] logger.bigbrother("/save_bytes", user, environ) q = storage.sql( """ SELECT save_uid FROM progress WHERE user_id = ? """, (user.id, ))[0] with open(config.DATA_DIRECTORY + "/save/%s.sav" % q.save_uid, "rb") as f: save_data = f.read() start_response('200 OK', HEADERS_JSON + HEADERS_CORS) return [util.json_bytes({"success": True, "sav": list(save_data)})]
def appLeaderboardFull(environ, start_response): q = storage.sql(""" SELECT users.username AS username, score, achievements, monsters FROM leaderboard LEFT OUTER JOIN users ON users.id = leaderboard.user_id WHERE score >= 0 ORDER BY score DESC, last_update ASC """) resp = [] for i in q: resp.append({ "username": i.username, "score": i.score, "mons": json.loads(i.monsters) }) start_response('200 OK', HEADERS_JSON + HEADERS_CORS) return [util.json_bytes(resp)]
def appSetMessage(environ, start_response): data = util.get_json_post(environ) user = storage.get_user_by_sessid(data.sessid) if user is None: start_response('200 OK', HEADERS_JSON + HEADERS_CORS) return [util.err_json("You are not logged in.")] logger.bigbrother("/set_message", user, environ) if len(data.message) > 150: start_response('200 OK', HEADERS_JSON + HEADERS_CORS) return [util.err_json("Message is too long.")] q = storage.sql( """ UPDATE users SET message = ? WHERE id = ? """, (data.message, user.id)) start_response('200 OK', HEADERS_JSON + HEADERS_CORS) return [util.json_bytes({"success": True})]