diff --git a/DatabaseModels.py b/DatabaseModels.py index 25d8567..fc04ade 100644 --- a/DatabaseModels.py +++ b/DatabaseModels.py @@ -30,11 +30,11 @@ class GeoffreyDatabase: self.add_object(shop) return shop - def add_item(self, player_name, shop_name, item_name, price): + def add_item(self, player_name, shop_name, item_name, price, amount): try: shop = self.find_shop_by_name_and_owner(player_name, shop_name) - item = ItemListing(item_name, price, shop[0]) + item = ItemListing(item_name, price, amount, shop[0]) self.add_object(item) except IndexError: raise LocationLookUpError @@ -65,11 +65,11 @@ class GeoffreyDatabase: self.session.commit() def find_location_by_name(self, name): - expr = Location.name.like('%{}%'.format(name)) + expr = Location.name.ilike('%{}%'.format(name)) return self.query_by_filter(Location, expr) def find_shop_by_name(self, name): - expr = Location.name.like('%{}%'.format(name)) + expr = Location.name.ilike('%{}%'.format(name)) return self.query_by_filter(Shop, expr) def find_location_by_owner(self, owner_name): @@ -79,22 +79,23 @@ class GeoffreyDatabase: def find_shop_by_name_and_owner(self, owner_name, name): player = self.find_player(owner_name) - expr = (Shop.owner == player) & (Shop.name == name) + expr = (Shop.owner == player) & (Shop.name.ilike(name)) return self.query_by_filter(Shop, expr) def find_location_by_name_and_owner(self, owner_name, name): player = self.find_player(owner_name) - expr = (Location.owner == player) & (Location.name == name) + expr = (Location.owner == player) & (Location.name.ilike(name)) return self.query_by_filter(Location, expr) def find_location_around(self, x_pos, z_pos, radius): + radius = radius + 1 #gets a the correct area expr = (Location.x < x_pos + radius) & (Location.x > x_pos - radius) & (Location.z < z_pos + radius) & \ (Location.z > z_pos - radius) return self.query_by_filter(Location, expr) def find_item(self, item_name): - expr = ItemListing.name.like(item_name) + expr = ItemListing.name.ilike('{}'.format(item_name)) return self.query_by_filter(ItemListing, expr) def find_shop_selling_item(self, item_name): @@ -103,6 +104,7 @@ class GeoffreyDatabase: shops = [] for listing in listings: shops.append(listing.shop) + shops.append(listing.__str__()) return shops @@ -183,6 +185,38 @@ class TunnelDirection(enum.Enum): raise ValueError +class TunnelSide(enum.Enum): + right = 'right' + left = 'left' + + def str_to_tunnel_side(arg): + arg = arg.lower() + if arg == TunnelSide.right.value: + return TunnelSide.right + elif arg == TunnelSide.left.value: + return TunnelSide.left + else: + raise ValueError + + +class Dimension(enum.Enum): + overworld = 'overworld' + nether = 'nether' + end = 'end' + + def str_to_dimension(arg): + arg = arg.lower() + if arg == Dimension.overworld.value: + return Dimension.overworld + elif arg == Dimension.nether.value: + return Dimension.nether + elif arg == Dimension.end.value: + return Dimension.end + else: + raise ValueError + + + class Player(SQL_Base): __tablename__ = 'Players' @@ -205,6 +239,9 @@ class Location(SQL_Base): z = Column(Integer) tunnelNumber = Column(Integer) direction = Column(Enum(TunnelDirection)) + tunnel_side = Column(Enum(TunnelSide)) + dimension = Column(Enum(Dimension)) + owner_id = Column(Integer, ForeignKey('Players.id')) owner = relationship("Player", back_populates="locations") type = Column(String) @@ -225,15 +262,21 @@ class Location(SQL_Base): if len(args) > 0: self.direction = TunnelDirection.str_to_tunnel_dir(args[0]) self.tunnelNumber = int(args[1]) + self.tunnel_side = TunnelSide.str_to_tunnel_side(args[2]) + + if len(args) > 3: + self.dimension = Dimension.str_to_dimension(args[3]) + else: + self.dimension = Dimension.str_to_dimension("overworld") except (ValueError, IndexError): raise LocationInitError def pos_to_str(self): - return '(x= {}, y= {}, z= {})'.format(self.x, self.y, self.z) + return '(x= {}, y= {}, z= {}) in the {}'.format(self.x, self.y, self.z, self.dimension.value.title()) def nether_tunnel_addr_to_str(self): - return '{} {}'.format(self.direction.value.title(), self.tunnelNumber) + return '{} {} {}'.format(self.direction.value.title(), self.tunnelNumber, self.tunnel_side.value.title()) def __str__(self): if self.direction is not None: @@ -262,14 +305,16 @@ class ItemListing(SQL_Base): id = Column(Integer, primary_key=True, autoincrement=True) name = Column(String) price = Column(Integer) + amount = Column(Integer) shop_id = Column(Integer, ForeignKey('Shops.shop_id')) shop = relationship("Shop", back_populates="inventory") - def __init__(self, name, price, shop): + def __init__(self, name, price, amount, shop): self.name = name self.price = price + self.amount = amount self.shop = shop def __str__(self): - return "Item: {}, Price: {}D".format(self.name, self.price) + return "Item: {}, Price: {} for {}D".format(self.name, self.amount, self.price) diff --git a/Geoffrey.py b/Geoffrey.py index f88d494..a38d4a7 100644 --- a/Geoffrey.py +++ b/Geoffrey.py @@ -3,6 +3,7 @@ from DatabaseModels import * from BotErrors import * from MinecraftAccountInfoGrabber import * import configparser +import sqlite3 #from WebInterface import * TOKEN = '' @@ -38,6 +39,12 @@ async def on_command_error(error, ctx): .format(ctx.invoked_with, ctx.invoked_with) elif isinstance(error.original, UsernameLookupFailed): error_str = error.original.__doc__ + elif isinstance(error.original, OverflowError): + error_str = 'Wow buddy, that\'s a big number. Please don\'t do that.' + database.session.rollback() + elif isinstance(error.original, sqlite3.IntegrityError): + error_str = 'Off, the fuck did you do? Try the command again but be less of a ding dong with it.' + database.session.rollback() else: error_str = bad_error_message.format(ctx.invoked_with, error) @@ -57,7 +64,8 @@ async def addbase(ctx, name: str, x_pos: int, y_pos: int, z_pos: int, * args): ''' Add your base to the database. The tunnel address is optional. - ?addbase [Base Name] [X Coordinate] [Y Coordinate] [Z Coordinate] [Tunnel Color] [Tunnel Position] + The default dimension is the overworld. Valid options: overworld, nether, end + ?addbase [Base Name] [X Coordinate] [Y Coordinate] [Z Coordinate] [Tunnel Color] [Tunnel Position] [Side] [Dimension] ''' player_name = get_nickname(ctx.message.author) @@ -75,7 +83,8 @@ async def addshop(ctx, name: str, x_pos: int, y_pos: int, z_pos: int, * args): ''' Adds a shop to the database. The tunnel address is optional. - ?addbase [Shop name] [X Coordinate] [Y Coordinate] [Z Coordinate] [Tunnel Color] [Tunnel Position] + The default dimension is the overworld. Valid options: overworld, nether, end + ?addbase [Base Name] [X Coordinate] [Y Coordinate] [Z Coordinate] [Tunnel Color] [Tunnel Position] [Side] {Dimension] ''' player_name = get_nickname(ctx.message.author) @@ -100,7 +109,7 @@ async def find(ctx, name: str): loc_list = database.find_location_by_owner(name) loc_string = loc_list_to_string(loc_list, '{} \n{}') - await bot.say('{}, **{}** has **{}** base(s): \n {}'.format(ctx.message.author.mention, name, len(loc_list), + await bot.say('{}, **{}** has **{}** locations(s): \n {}'.format(ctx.message.author.mention, name, len(loc_list), loc_string)) except PlayerNotFound: await bot.say('{}, the player **{}** is not in the database'.format(ctx.message.author.mention, name)) @@ -123,7 +132,7 @@ async def delete(ctx, name: str): @bot.command(pass_context=True) async def findaround(ctx, x_pos: int, z_pos: int, * args): ''' - Finds all the bases/shops around a certain point that are registered in the database + Finds all the locations around a certain point that are registered in the database The Radius argument defaults to 200 blocks if no value is given ?findbasearound [X Coordinate] [Z Coordinate] [Radius] ''' @@ -140,23 +149,23 @@ async def findaround(ctx, x_pos: int, z_pos: int, * args): if len(base_list) != 0: base_string = loc_list_to_string(base_list, '{} \n{}') - await bot.say('{}, there are {} base(s) within {} blocks of that point: \n {}'.format( + await bot.say('{}, there are {} locations(s) within {} blocks of that point: \n {}'.format( ctx.message.author.mention, len(base_list), radius, base_string)) else: - await bot.say('{}, there are no bases within {} blocks of that point' + await bot.say('{}, there are no locations within {} blocks of that point' .format(ctx.message.author.mention, radius)) @bot.command(pass_context=True) -async def additem(ctx, shop_name: str, item_name: str, diamond_price: int): +async def additem(ctx, shop_name: str, item_name: str, amount: int, diamond_price: int): ''' - Adds an item to a shop's inventory - ?additem [Shop name] [Item Name] [Price] + Adds an item to a shop's inventory. Amount for diamond price. + ?additem [Shop name] [Item Name] [Amount] [Price] ''' try: player_name = get_nickname(ctx.message.author) - database.add_item(player_name, shop_name, item_name, diamond_price) + database.add_item(player_name, shop_name, item_name, diamond_price, amount) await bot.say('{}, **{}** has been added to the inventory of **{}**.'.format(ctx.message.author.mention, item_name, shop_name)) diff --git a/test_geoffreyDatabase.py b/test_geoffreyDatabase.py index 56870cf..b40fbfc 100644 --- a/test_geoffreyDatabase.py +++ b/test_geoffreyDatabase.py @@ -8,7 +8,7 @@ class TestGeoffreyDatabase(TestCase): def setUp(self): self.database = GeoffreyDatabase('sqlite:///:memory:') self.owner = Player('ZeroHD') - self.loc = Location('test', 1, 2, 3, self.owner, ['Green', 0]) + self.loc = Location('test', 1, 2, 3, self.owner, ['Green', 0, 'Right']) def test_add_object(self): self.database.add_object(self.loc) @@ -43,41 +43,41 @@ class TestGeoffreyDatabase(TestCase): self.assertRaises(DeleteEntryError, self.database.delete_entry, Location, expr) def test_add_shop(self): - shop = self.database.add_shop('ZeroHD', 'test', 1, 2, 3, ['Green', 0]) + shop = self.database.add_shop('ZeroHD', 'test', 1, 2, 3, ['Green', 0, 'Right']) self.assertEqual(type(shop), Shop) def test_add_two_shops(self): - shop1 = self.database.add_shop('ZeroHD', 'test', 1, 2, 3, ['Green', 0]) - shop2 = self.database.add_shop('ZeroHD', 'no u', 1, 2, 3, ['Green', 0]) + shop1 = self.database.add_shop('ZeroHD', 'test', 1, 2, 3, ['Green', 0, 'Right']) + shop2 = self.database.add_shop('ZeroHD', 'no u', 1, 2, 3, ['Green', 0, 'Right']) loc_list = self.database.find_location_by_owner('ZeroHD') self.assertEqual(loc_list[1].id, shop2.id) def test_add_item(self): - self.database.add_shop('ZeroHD', 'test', 1, 2, 3, ['Green', 0]) - self.database.add_item('ZeroHD', 'test', 'dirt', 1) + self.database.add_shop('ZeroHD', 'test', 1, 2, 3, ['Green', 0, "Right"]) + self.database.add_item('ZeroHD', 'test', 'dirt', 1, 15) shops = self.database.find_shop_selling_item('dirt') self.assertEqual(shops[0].name, 'test') def test_find_location_by_owner(self): - shop = self.database.add_shop('ZeroHD', 'test', 1, 2, 3, ['Green', 0]) + shop = self.database.add_shop('ZeroHD', 'test', 1, 2, 3, ['Green', 0, "Right"]) loc_list = self.database.find_location_by_owner('ZeroHD') self.assertEqual(loc_list[0].id, shop.id) def test_find_location_by_name_and_owner(self): - shop = self.database.add_shop('ZeroHD', 'test', 1, 2, 3, ['Green', 0]) + shop = self.database.add_shop('ZeroHD', 'test', 1, 2, 3, ['Green', 0, "Right"]) loc_list = self.database.find_location_by_name_and_owner('ZeroHD','test') self.assertEqual(loc_list[0].id, shop.id) def test_delete_base(self): - self.database.add_location('ZeroHD', 'test', 1, 2, 3, ['Green', 0]) + self.database.add_location('ZeroHD', 'test', 1, 2, 3, ['Green', 0, "Right"]) self.database.delete_base('ZeroHD', 'test') @@ -86,35 +86,35 @@ class TestGeoffreyDatabase(TestCase): self.assertEqual(len(loc_list), 0) def test_find_location_around(self): - loc = self.database.add_location('ZeroHD', 'test', 0, 0, 0, ['Green', 0]) + loc = self.database.add_location('ZeroHD', 'test', 0, 0, 0, ['Green', 0, "Right"]) - loc_list = self.database.find_location_around(100, 100, 200) + loc_list = self.database.find_location_around(100, 100, 100) self.assertEqual(loc_list[0].name, loc.name) - loc_list = self.database.find_location_around(200, 200, 200) + loc_list = self.database.find_location_around(200, 200, 100) self.assertEqual(len(loc_list), 0) def test_find_location_by_name(self): - loc = self.database.add_location('ZeroHD', 'test', 0, 0, 0, ['Green', 0]) + loc = self.database.add_location('ZeroHD', 'test', 0, 0, 0, ['Green', 0, "Right"]) loc_list = self.database.find_location_by_name('test') self.assertEqual(loc_list[0].name, loc.name) def test_wrong_case(self): - loc = self.database.add_location('ZeroHD', 'test', 0, 0, 0, ['Green', 0]) + loc = self.database.add_location('ZeroHD', 'test', 0, 0, 0, ['Green', 0, "right"]) loc_list = self.database.find_location_by_owner('zerohd') self.assertEqual(loc_list[0].id, loc.id) - self.database.add_shop('ZeroHD', 'testshop', 1, 2, 3, ['Green', 0]) + self.database.add_shop('ZeroHD', 'testshop', 1, 2, 3, ['Green', 0, "lEft", "neThEr"]) - self.database.add_item('ZeroHD', 'testshop', 'dirt', 1) + self.database.add_item('ZeroHD', 'testshop', 'dirt', 1, 15) - shops = self.database.find_shop_selling_item('Dirt') + shops = self.database.find_shop_selling_item('Dirts') self.assertEqual(shops[0].name, 'testshop') @@ -122,6 +122,13 @@ class TestGeoffreyDatabase(TestCase): self.assertEqual(loc_list[0].name, 'test') + def test_big_input(self): + loc = self.database.add_location('ZeroHD', + 'TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT', 0, 0, 0, ['Green', 0, "Right"]) + + loc_list = self.database.find_location_by_owner('zerohd') + + self.assertEqual(loc_list[0].id, loc.id)