def test_load_modify_save(self, test_app_context, fixture_colony_a): ad = fixture_colony_a.to_dict() connection = get_redis_db_from_context() # It should be near the end of the list. index = connection.lrange(consts.KEY_COLONY_INDEX_BY_ID, -5, -1) assert fixture_colony_a.Hash in index # Reload it as a new object b = Colony.get_from_database(ad, db.get_redis_db_from_context()) assert b.Hash == fixture_colony_a.Hash for k, v in b.to_dict().items(): assert ad[k] == v b.LastAction = 2 b.save_to_database(connection) c = Colony.get_from_database(ad, db.get_redis_db_from_context()) assert c.LastAction == b.LastAction
def test_save_and_load_steam(self, test_app_context, fixture_colony_steam): connection = get_redis_db_from_context() self.setup_data_in_db(fixture_colony_steam, connection) # It should be near the end of the list. index = connection.lrange(consts.KEY_COLONY_INDEX_BY_ID, -5, -1) steam_index = connection.lrange( consts.KEY_COLONY_INDEX_BY_STEAM_ID.format( fixture_colony_steam.OwnerID), -5, -1) assert fixture_colony_steam.Hash in index assert fixture_colony_steam.Hash in steam_index # Reload it as a new object o_loaded = Colony.get_from_database(fixture_colony_steam.to_dict(), db.get_redis_db_from_context()) assert o_loaded.FromDatabase assert o_loaded.Hash == fixture_colony_steam.Hash od = fixture_colony_steam.to_dict() for k, v in o_loaded.to_dict().items(): assert od[k] == v
def test_one_doesnt_exist(self, test_app_context, fixture_colony_a, fixture_colony_b): connection = get_redis_db_from_context() a = fixture_colony_a b = fixture_colony_b self.setup_data_in_db(a, connection) self.setup_data_in_db(b, connection) c = Colony.from_dict( { 'BaseName': 'TestColonyC', 'FactionName': 'TestFactionC', 'Planet': 'TestPlanetC', 'Hash': 'EFGH', 'OwnerType': 'Normal', 'OwnerID': 1 }, connection=db.get_redis_db_from_context()) colony_data = [a.to_dict(), b.to_dict(), c.to_dict()] result = list( Colony.get_many_from_database( colony_data, db.get_redis_db_from_context()).values()) assert len(result) == 3 assert result[0].BaseName == a.BaseName and result[0].FromDatabase assert result[1].BaseName == b.BaseName and result[1].FromDatabase assert result[2].BaseName == c.BaseName and not result[2].FromDatabase
def test_get_colony_by_hash(self, test_app_context, fixture_colony_steam): connection = get_redis_db_from_context() self.setup_data_in_db(fixture_colony_steam, connection) result = Colony.get_from_database_by_hash( fixture_colony_steam.Hash, db.get_redis_db_from_context()) assert result.FromDatabase
def test_all_exist(self, test_app_context, a, b, c): connection = db.get_redis_db_from_context() thing_data = [a, b, c] self.setup_data_in_db(Thing.from_dict(a), get_redis_db_from_context()) self.setup_data_in_db(Thing.from_dict(b), get_redis_db_from_context()) self.setup_data_in_db(Thing.from_dict(c), get_redis_db_from_context()) result = Thing.get_many_from_database(thing_data, connection).values() s = zip(thing_data, result) for a, b in s: assert a['Name'] == b.Name and b.FromDatabase
def subscription_update(colony_hash): db_connection = db.get_redis_db_from_context() colony = Colony.get_from_database_by_hash(colony_hash, db.get_redis_db_from_context()) if not colony: current_app.logger.warning('{} colony not found in database'.format(colony.Hash)) return Response(consts.ERROR_NOT_FOUND, status=consts.HTTP_NOT_FOUND) sub_data = request.json # Validate token if 'Token' not in sub_data: current_app.logger.error('{} Subscription token was not in payload.'.format(colony.Hash)) return Response(consts.ERROR_INVALID, status=consts.HTTP_INVALID) # Fetch our token from DB token_in_db = db_connection.get(consts.KEY_PRIME_TOKEN_DATA.format(colony.Hash)) # Has it expired or ever existed? if token_in_db is None: current_app.logger.warning('{} Subscription token was not in database or has expired.'.format(colony.Hash)) return Response(consts.ERROR_INVALID, status=consts.HTTP_INVALID) # They should match if token_in_db != sub_data['Token']: current_app.logger.error( '{} Subscription tokens did not match {} != {}.'.format(colony.Hash, sub_data['Token'], token_in_db)) return Response(consts.ERROR_INVALID, status=consts.HTTP_INVALID) expiryTick = DaysPerQuadrum * TicksPerDay + colony.LastGameTick pipe = db_connection.pipeline() # Update subscription tick for Colony. pipe.set(consts.KEY_PRIME_SUBSCRIPTION_DATA.format(colony.Hash), int(expiryTick)) # Remove the token to prevent reuse. pipe.delete(consts.KEY_PRIME_TOKEN_DATA.format(colony_hash)) # Subscriptions expire after 42 days in real life. pipe.expireat(consts.KEY_PRIME_SUBSCRIPTION_DATA.format(colony.Hash), date_utils.add_days_to_current_time(30)) # Update Silver acquired. thing = Thing("Silver") subscriptionCost = int(db_connection.get(consts.KEY_CONFIGURATION_PRIME_COST)) pipe.hincrby(consts.KEY_THING_META.format(thing.Hash), 'Quantity', subscriptionCost) pipe.execute() current_app.logger.debug('{} Subscription successful.'.format(colony.Hash)) return Response("OK", status=consts.HTTP_OK)
def test_one_doesnt_exist(self, test_app_context, a, c): connection = db.get_redis_db_from_context() b = {'Name': 'Nonexistent', 'StuffType': 'WoodenLog'} thing_data = [a, b, c] self.setup_data_in_db(Thing.from_dict(a), get_redis_db_from_context()) self.setup_data_in_db(Thing.from_dict(c), get_redis_db_from_context()) result = list( Thing.get_many_from_database(thing_data, connection).values()) assert len(result) == 3 assert result[0].Name == a['Name'] and result[0].FromDatabase assert result[1].Name == b['Name'] and not result[1].FromDatabase assert result[2].Name == c['Name'] and result[2].FromDatabase
def test_save_and_load(self, test_app_context): connection = db.get_redis_db_from_context() d = { 'Name': 'TestSaveAndLoad', 'Quality': 'Good', 'StuffType': 'Silver', 'UseServerPrice': True, 'CurrentBuyPrice': 19.99, 'CurrentSellPrice': 13.99, 'BaseMarketValue': 15.99, 'Quantity': 100 } o_save = Thing.from_dict(d) od = o_save.to_dict() # Remove the key from the index if it already exists connection.srem(consts.KEY_THING_INDEX, o_save.Hash) # Write the Thing to the database. o_save.save_to_database(connection) # It should be near the end of the list. is_member = connection.sismember(consts.KEY_THING_INDEX, o_save.Hash) assert is_member # Reload it as a new object o_loaded = Thing.get_from_database(o_save.to_dict(), connection) assert o_loaded.FromDatabase assert o_loaded.Hash == o_save.Hash for k, v in o_loaded.to_dict().items(): assert od[k] == v
def test_class_init_from_dict_hash(self, test_app_context, fixture_colony_a): o = Colony.from_dict(fixture_colony_a.to_dict(), db.get_redis_db_from_context()) assert "87a41f64617b379cb80c7123351b35db356c97c8" == o.Hash
def test_update_stats_for_colony_action(self, test_app_context, fixture_colony_a, fixture_colony_b): connection = get_redis_db_from_context() self.setup_data_in_db(fixture_colony_a, connection) self.setup_data_in_db(fixture_colony_b, connection) date = date_utils.get_today_date_string() hour = date_utils.get_current_hour() with connection.pipeline() as pipe: pipe.delete(consts.KEY_BUCKET_COLONIES_ACTIVE) pipe.delete( consts.KEY_COUNTERS_HOURLY_COLONIES_ACTIVE.format(hour)) pipe.execute() fixture_colony_a.ping() fixture_colony_b.ping() colony_set = connection.smembers( consts.KEY_TRENDS_HISTORICAL_COLONIES_ACTIVE_BY_DATE.format(date)) assert fixture_colony_a.Hash in colony_set assert fixture_colony_b.Hash in colony_set colony_set = connection.zrange(consts.KEY_BUCKET_COLONIES_ACTIVE, 0, -1) assert fixture_colony_a.Hash in colony_set assert fixture_colony_b.Hash in colony_set colony_count = connection.get( consts.KEY_COUNTERS_HOURLY_COLONIES_ACTIVE.format(hour)) assert colony_count >= 2
def order_a(cls, fixture_colony_a, thing_a_bought, thing_a_sold) -> Order: colony = fixture_colony_a order: Order = Order.from_order_data_dict( { 'OwnerID': colony.Hash, 'OrderedTick': 1000, 'ThingsBoughtFromGwp': json.dumps([ OrderThing.from_dict(thing_a_bought).to_dict( keep_quantity=True) ]), 'ThingsSoldToGwp': json.dumps([ OrderThing.from_dict(thing_a_sold).to_dict( keep_quantity=True) ]), 'DeliveryTick': 10000 }, connection=db.get_redis_db_from_context()) return order
def test_name_withquality_and_stuff(self, test_app_context, a): connection = db.get_redis_db_from_context() thing_data = a a = Thing.from_dict(thing_data) self.setup_data_in_db(a, connection) b = Thing.get_from_database(thing_data, connection) assert b.Hash == '4f57967468deccdb718432a13fdd55eef9f8bd4f'
def test_one_not_exists(self, test_app_context): connection = get_redis_db_from_context() thing_data = {'Name': 'Non-existent thing'} result = OrderThing.from_dict_and_check_exists(thing_data, connection) assert thing_data['Name'] == result.Name assert not result.ThingExists
def test_one_exists(self, test_app_context, a): connection = get_redis_db_from_context() self.setup_data_in_db(Thing.from_dict(a), connection) result = OrderThing.from_dict_and_check_exists(a, connection) assert a['Name'] == result.Name assert result.ThingExists
def test_class_init_from_dict_to_dict(self, test_app_context, fixture_colony_a): a_dict = fixture_colony_a.to_dict() b = Colony.from_dict(a_dict, db.get_redis_db_from_context()).to_dict() for k, v in b.items(): assert a_dict[k] == v
def test_all_none(self, test_app_context): """ Test that none of these entries exist in the DB, Assert that all results have FromDatabase == False :param test_app_context: :return: """ a = Colony.from_dict( { 'BaseName': 'TestColonyA', 'FactionName': 'TestFactionA', 'Planet': 'TestPlanetA', 'Hash': '1234', 'OwnerType': 'Normal', 'OwnerID': 1 }, connection=db.get_redis_db_from_context()) b = Colony.from_dict( { 'BaseName': 'TestColonyB', 'FactionName': 'TestFactionB', 'Planet': 'TestPlanetB', 'Hash': '5678', 'OwnerType': 'Normal', 'OwnerID': 1 }, connection=db.get_redis_db_from_context()) c = Colony.from_dict( { 'BaseName': 'TestColonyC', 'FactionName': 'TestFactionC', 'Planet': 'TestPlanetC', 'Hash': 'EFGH', 'OwnerType': 'Normal', 'OwnerID': 1 }, connection=db.get_redis_db_from_context()) colony_data = [a.to_dict(), b.to_dict(), c.to_dict()] result = Colony.get_many_from_database(colony_data, db.get_redis_db_from_context()) s = list(zip(colony_data, result.values())) assert len(s) == 3 for a, b in s: assert not b.FromDatabase
def server_maintenance_window(): db_connection = db.get_redis_db_from_context() # Returns tuple, {Start: epoch, Stop: epoch} window = db_connection.hgetall(KEY_API_MAINTENANCE_WINDOW) print("Maintenance Window is {}".format(json.dumps(window))) return Response(json.dumps(window), status=200, mimetype='application/json')
def colony_set_supported_things(colony_hash: str): print("Received Supported things list from colony") colony = Colony.get_from_database_by_hash(colony_hash, db.get_redis_db_from_context()) if not colony: return Response(consts.ERROR_NOT_FOUND, status=consts.HTTP_NOT_FOUND) try: gz_post_data = request.files['things'] # Decompress payload thing_file = gzip.GzipFile(fileobj=gz_post_data, mode='r') # Deserialize JSON back in to {'Locale': str, 'Things': List[Dict[str, str]]} payload = json.loads(thing_file.read().decode('UTF8')) # Set locale locale = payload['Locale'].lower() # This is a List[Dict[str, str]] supported_things_json = payload['Things'] print("Supported things parsed") except json.JSONDecodeError: print("Error in things list found") return Response(consts.ERROR_INVALID, status=consts.HTTP_INVALID) # Need to construct things then add Localized name to index pipe = db.get_redis_db_from_context().pipeline() pipe.sadd(consts.KEY_THING_LOCALE_KNOWN_LANGUAGES, locale) for thing_json in supported_things_json: thing = Thing.from_dict(thing_json) pipe.zincrby(KEY_THING_LOCALE_THING_NAMES.format(locale, thing.Hash), 1, thing.LocalizedName) pipe.execute() # This is immediately saved. colony.SupportedThings = supported_things_json print("Supported things saved") return Response('OK', status=200, mimetype='application/json')
def test_is_from_database(self, test_app_context, order_a): connection = get_redis_db_from_context() self.setup_order_data_in_db(order_a, connection) order_hash = order_a.Hash order_a = Order.get_from_database_by_hash(order_hash, connection) assert order_a.FromDatabase
def colony_get_data(colony_hash): print("Getting colony data") colony = Colony.get_from_database_by_hash(colony_hash, db.get_redis_db_from_context()) if not colony: return Response(consts.ERROR_NOT_FOUND, status=consts.HTTP_NOT_FOUND) print("Sending colony data") return Response(json.dumps(colony.to_dict()), status=200, mimetype='application/json')
def test_is_from_database_many(self, test_app_context, order_a): connection = get_redis_db_from_context() self.setup_order_data_in_db(order_a, connection) order_hash = [order_a.Hash] orders = Order.get_many_from_database(order_hash, connection) result = list(orders.values())[0] assert result.Hash == order_a.Hash
def fixture_colony_a() -> Colony: a: Colony = Colony.from_dict( { 'BaseName': 'TestColonyA', 'FactionName': 'TestFactionA', 'Planet': 'TestPlanetA', 'DateCreated': 1, 'OwnerType': 'Normal', 'OwnerID': 1 }, connection=db.get_redis_db_from_context()) return a
def user_generate_id(): db_connection = db.get_redis_db_from_context() # Generate a hash for the user. ts = datetime.utcnow().timestamp() user_hash = hashlib.sha1(str(ts).encode('UTF8')).hexdigest() db_connection.hset(consts.KEY_USER_NORMAL.format(user_hash), 'DateCreated', ts) # Add to index db_connection.sadd(consts.KEY_USER_INDEX_BY_NORMAL_ID, user_hash) return Response(json.dumps({'Hash': user_hash}), status=200, mimetype='application/json')
def fixture_colony_steam() -> Colony: s: Colony = Colony.from_dict( { 'BaseName': 'TestColonyS', 'FactionName': 'TestFactionS', 'Planet': 'TestPlanetS', 'DateCreated': 100, 'OwnerType': 'Steam', 'OwnerID': '76561198275909496' }, connection=db.get_redis_db_from_context()) return s
def fixture_colony_b() -> Colony: b: Colony = Colony.from_dict( { 'BaseName': 'TestColonyB', 'FactionName': 'TestFactionB', 'Planet': 'TestPlanetB', 'Hash': 'ABCD', 'OwnerType': 'Normal', 'OwnerID': 1 }, connection=db.get_redis_db_from_context()) return b
def set_database_connection(): """ This function setups up a database connection depending on the version of the API being requested. And is called before each request. :return: """ try: groups = request.path.split('/') if groups is None or len(groups) < 1: return Response(consts.ERROR_NOT_FOUND, status=consts.HTTP_NOT_FOUND) version = groups[1] # Check if it's a new style URL if version.startswith('v'): if len(groups) > 2: version = groups[2] # New versions: m1, m2, m3 etc. if version in API_DB_CONFIG: db_number = API_DB_CONFIG[version] else: return Response('Unknown API Version', status=consts.HTTP_NOT_FOUND) else: return Response('Unknown API Version', status=consts.HTTP_NOT_FOUND) else: return Response('Unknown API Version', status=consts.HTTP_NOT_FOUND) g.gwp_market = version get_redis_db_from_context(db_number) except Exception as e: return Response(consts.ERROR_NOT_FOUND, status=consts.HTTP_NOT_FOUND)
def api_version_get(): db_connection = db.get_redis_db_from_context() version = db_connection.get(KEY_API_VERSION) versionSupported = db_connection.get(KEY_API_VERSION_SUPPORTED) print("Main Version is {} Supported Version is {}".format( version, versionSupported)) version_data = {'Version': version, 'Supported': versionSupported} return Response(json.dumps(version_data), status=200, mimetype='application/json')
def market_get_items(colony_hash): print("Sending Market items to Colony") connection = db.get_redis_db_from_context() colony = Colony.get_from_database_by_hash(colony_hash, db.get_redis_db_from_context()) if not colony: return Response(consts.ERROR_NOT_FOUND, status=consts.HTTP_NOT_FOUND) things = Thing.get_many_from_database(colony.SupportedThings, connection) #thing_data = [thing.to_dict() for thing in things.values()] thing_data = [ thing.to_dict() for thing in things.values() if thing.Quantity > 0 ] print("Market items sent") content = gzip.compress(json.dumps(thing_data).encode('utf8'), 5) response = make_response(content, 200) response.headers['Content-length'] = len(content) response.headers['Content-Encoding'] = 'gzip' response.headers['Content-Type'] = "application/json" return response
def test_all_exist(self, test_app_context, fixture_colony_a, fixture_colony_b, fixture_colony_steam): connection = get_redis_db_from_context() a = fixture_colony_a b = fixture_colony_b c = fixture_colony_steam self.setup_data_in_db(a, connection) self.setup_data_in_db(b, connection) self.setup_data_in_db(c, connection) colony_data = [a.to_dict(), b.to_dict(), c.to_dict()] result = Colony.get_many_from_database(colony_data, db.get_redis_db_from_context()) s = zip(colony_data, result.values()) for a, b in s: assert a['BaseName'] == b.BaseName and b.FromDatabase
def server_status(): db_connection = db.get_redis_db_from_context() mode = db_connection.get(KEY_API_MAINTENANCE_MODE) print("Maintenance Mode is {}".format(mode)) # True if in Maintenance mode. if mode: return Response(json.dumps("Gone"), status=410, mimetype='application/json') else: return Response(json.dumps("OK"), status=200, mimetype='application/json')