Added flag support for commands that had optional params

doc_update
Joey Hines 2018-07-15 13:27:11 -05:00
parent eccfba5bec
commit 6622b98830
3 changed files with 153 additions and 85 deletions

View File

@ -7,22 +7,30 @@ from sqlalchemy.orm import sessionmaker, relationship
from sqlalchemy.exc import IntegrityError
import sqlalchemy
from MinecraftAccountInfoGrabber import *
from difflib import SequenceMatcher
SQL_Base = declarative_base()
def check_similarity(a, b):
ratio = SequenceMatcher(None, a, b).ratio()
if (ratio > 0.6) or (a[0] == b[0]):
return True
else:
return False
class DatabaseInterface:
def __init__(self, db_engine_arg):
self.database = GeoffreyDatabase(db_engine_arg)
def add_location(self, owner, name, x_pos, y_pos, z_pos, args):
location = Location(name, x_pos, y_pos, z_pos, owner, args)
def add_location(self, owner, name, x_pos, y_pos, z_pos, tunnel=None, dimension=None):
location = Location(name, x_pos, y_pos, z_pos, owner, tunnel, dimension)
self.database.add_object(location)
return location
def add_shop(self, owner, name, x_pos, y_pos, z_pos, args):
shop = Shop(name, x_pos, y_pos, z_pos, owner, args)
def add_shop(self, owner, name, x_pos, y_pos, z_pos, tunnel=None, dimension=None):
shop = Shop(name, x_pos, y_pos, z_pos, owner, tunnel, dimension)
self.database.add_object(shop)
return shop
@ -79,8 +87,9 @@ class DatabaseInterface:
return self.database.query_by_filter(Location, expr)
def find_location_around(self, x_pos, z_pos, radius, dimension):
dimension_obj = Dimension.str_to_dimension(dimension)
expr = (Location.x < x_pos + radius + 1) & (Location.x > x_pos - radius - 1) & (Location.z < z_pos + radius + 1) \
& (Location.z > z_pos - radius - 1) & (Location.dimension == dimension)
& (Location.z > z_pos - radius - 1) & (Location.dimension == dimension_obj)
return self.database.query_by_filter(Location, expr)
@ -140,13 +149,13 @@ class DatabaseInterface:
class DiscordDatabaseInterface(DatabaseInterface):
def add_location(self, owner_uuid, name, x_pos, y_pos, z_pos, args):
def add_location(self, owner_uuid, name, x_pos, y_pos, z_pos, tunnel=None, dimension=None):
owner = DatabaseInterface.find_player_by_discord_uuid(self, owner_uuid)
return DatabaseInterface.add_location(self, owner, name, x_pos, y_pos, z_pos, args)
return DatabaseInterface.add_location(self, owner, name, x_pos, y_pos, z_pos, tunnel, dimension)
def add_shop(self, owner_uuid, name, x_pos, y_pos, z_pos, args):
def add_shop(self, owner_uuid, name, x_pos, y_pos, z_pos, tunnel=None, dimension=None):
owner = DatabaseInterface.find_player_by_discord_uuid(self, owner_uuid)
return DatabaseInterface.add_shop(self, owner, name, x_pos, y_pos, z_pos, args)
return DatabaseInterface.add_shop(self, owner, name, x_pos, y_pos, z_pos, tunnel, dimension)
def add_item(self, owner_uuid, shop_name, item_name, price, amount):
owner = DatabaseInterface.find_player_by_discord_uuid(self, owner_uuid)
@ -236,13 +245,14 @@ class TunnelDirection(enum.Enum):
def str_to_tunnel_dir(arg):
arg = arg.lower()
if arg in TunnelDirection.North.value:
if check_similarity(TunnelDirection.North.value, arg):
return TunnelDirection.North
elif arg in TunnelDirection.East.value:
elif check_similarity(TunnelDirection.East.value, arg):
return TunnelDirection.East
elif arg in TunnelDirection.South.value:
elif check_similarity(TunnelDirection.South.value, arg):
return TunnelDirection.South
elif arg in TunnelDirection.West.value:
elif check_similarity(TunnelDirection.West.value, arg):
return TunnelDirection.West
else:
raise ValueError
@ -254,9 +264,9 @@ class TunnelSide(enum.Enum):
def str_to_tunnel_side(arg):
arg = arg.lower()
if arg in TunnelSide.right.value:
if check_similarity(TunnelSide.right.value, arg):
return TunnelSide.right
elif arg in TunnelSide.left.value:
elif check_similarity(TunnelSide.left.value, arg):
return TunnelSide.left
else:
raise ValueError
@ -269,11 +279,11 @@ class Dimension(enum.Enum):
def str_to_dimension(arg):
arg = arg.lower()
if arg in Dimension.overworld.value:
if check_similarity(Dimension.overworld.value, arg):
return Dimension.overworld
elif arg in Dimension.nether.value:
elif check_similarity(Dimension.nether.value, arg):
return Dimension.nether
elif arg in Dimension.end.value:
elif check_similarity(Dimension.end.value, arg):
return Dimension.end
else:
raise ValueError
@ -301,8 +311,8 @@ class Location(SQL_Base):
x = Column(Integer)
y = Column(Integer)
z = Column(Integer)
tunnelNumber = Column(Integer)
direction = Column(Enum(TunnelDirection))
tunnel_number = Column(Integer)
tunnel_direction = Column(Enum(TunnelDirection))
tunnel_side = Column(Enum(TunnelSide))
dimension = Column(Enum(Dimension))
@ -315,7 +325,7 @@ class Location(SQL_Base):
'polymorphic_identity': 'Location'
}
def __init__(self, name, x, y, z, owner, args):
def __init__(self, name, x, y, z, owner, tunnel, dimension):
try:
self.name = name
self.x = x
@ -323,15 +333,15 @@ class Location(SQL_Base):
self.z = z
self.owner = owner
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 tunnel is not None:
tunnel_info_list = tunnel.split(',')
self.tunnel_direction = TunnelDirection.str_to_tunnel_dir(tunnel_info_list[0])
self.tunnel_number = int(tunnel_info_list[1])
self.tunnel_side = TunnelSide.str_to_tunnel_side(tunnel_info_list[2])
if len(args) > 3:
self.dimension = Dimension.str_to_dimension(args[3])
if self.dimension is None:
if self.dimension is not None:
self.dimension = self.dimension = Dimension.str_to_dimension(dimension)
else:
self.dimension = Dimension.overworld
except (ValueError, IndexError):
@ -341,10 +351,10 @@ class Location(SQL_Base):
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, self.tunnel_side.value.title())
return '{} {} {}'.format(self.tunnel_direction.value.title(), self.tunnel_number, self.tunnel_side.value.title())
def __str__(self):
if self.direction is not None:
if self.tunnel_direction is not None:
return "Name: {}, Position: {}, Tunnel: {}".format(self.name, self.pos_to_str(),
self.nether_tunnel_addr_to_str())
else:
@ -360,8 +370,8 @@ class Shop(Location):
'polymorphic_identity': 'Shop',
}
def __init__(self, name, x, y, z, owner, args):
Location.__init__(self, name, x, y, z, owner, args)
def __init__(self, name, x, y, z, owner, tunnel, dimension):
Location.__init__(self, name, x, y, z, owner, tunnel, dimension)
class ItemListing(SQL_Base):

View File

@ -2,6 +2,7 @@ from discord.ext import commands
from DatabaseModels import *
from BotErrors import *
from MinecraftAccountInfoGrabber import *
from itertools import zip_longest
import configparser
import shlex
#from WebInterface import *
@ -67,7 +68,7 @@ async def test():
@bot.command(pass_context=True)
async def register(ctx):
'''
Registers your discord and minecraft account with the the database. You must do this before adding entries to
Registers your Discord and Minecraft account with the the database. You must do this before adding entries to
the database.
'''
@ -87,14 +88,29 @@ 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.
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]
?addbase [Base Name] [X Coordinate] [Y Coordinate] [Z Coordinate] [Tunnel Color] [Optional Flags]
Optional Flags:
-t [Tunnel Color],[Tunnel Position],[Side]
-d [dimension]
'''
player_name = get_nickname(ctx.message.author)
flags = get_args_dict(args)
tunnel = None
dimension = None
if len(flags) > 0:
if '-t' in flags:
tunnel = flags['-t']
if '-d' in flags:
dimension = flags['-d']
await bot.say('Test ' + tunnel)
try:
base = database_interface.add_location(ctx.message.author.id, name, x_pos, y_pos, z_pos, args)
shop = database_interface.add_shop(ctx.message.author.id, name, x_pos, y_pos, z_pos, tunnel, dimension)
except LocationInitError:
raise commands.UserInputError
@ -102,19 +118,32 @@ async def addbase(ctx, name: str, x_pos: int, y_pos: int, z_pos: int, * args):
' to the database.'.format(ctx.message.author.mention, base.name, base.pos_to_str()))
@bot.command(pass_context=True)
async def addshop(ctx, name: str, x_pos: int, y_pos: int, z_pos: int, * args):
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.
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]
?addbase [Shop Name] [X Coordinate] [Y Coordinate] [Z Coordinate] [Optional Flags]
Optional Flags:
-t [Tunnel Color],[Tunnel Position],[Side]
-d [dimension]
'''
player_name = get_nickname(ctx.message.author)
flags = get_args_dict(args)
tunnel = None
dimension = None
if len(flags) > 0:
if '-t' in flags:
tunnel = flags['-t']
if '-d' in flags:
dimension = flags['-d']
try:
shop = database_interface.add_shop(ctx.message.author.id, name, x_pos, y_pos, z_pos, args)
shop = database_interface.add_shop(ctx.message.author.id, name, x_pos, y_pos, z_pos, tunnel, dimension)
except LocationInitError:
raise commands.UserInputError
@ -157,19 +186,29 @@ async def delete(ctx, name: str):
async def findaround(ctx, x_pos: int, z_pos: int, * args):
'''
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]
The radius defaults to 200 blocks if no value is given
Default dimension is overworld
?findaround [X Coordinate] [Z Coordinate] [Optional Flags]
Optional Flags:
-r [radius]
-d [dimension]
'''
radius = 200
dimension = 'Overworld'
if len(args) > 0:
try:
radius = int(args[0])
except ValueError:
raise commands.UserInputError
flags = get_args_dict(args)
base_list = database_interface.find_location_around(x_pos, z_pos, radius)
if len(flags) > 0:
if '-r' in flags:
radius = int(flags['-r'])
if '-d' in flags:
dimension = flags['-d']
base_list = database_interface.find_location_around(x_pos, z_pos, radius, dimension)
if len(base_list) != 0:
base_string = loc_list_to_string(base_list, '{} \n{}')
@ -185,6 +224,7 @@ async def findaround(ctx, x_pos: int, z_pos: int, * args):
async def additem(ctx, shop_name: str, item_name: str, amount: int, diamond_price: int):
'''
Adds an item to a shop's inventory. Amount for diamond price.
?additem [Shop name] [Item Name] [Amount] [Price]
'''
@ -205,6 +245,7 @@ async def additem(ctx, shop_name: str, item_name: str, amount: int, diamond_pric
async def selling(ctx, item_name: str):
'''
Lists all the shops selling an item
?selling [item]
'''
shop_list = database_interface.find_shop_selling_item(item_name)
@ -217,6 +258,7 @@ async def selling(ctx, item_name: str):
async def shopinfo(ctx, shop_name: str):
'''
Lists the information and inventory of a shop
?shopinfo [Shop Name]
'''
shop = database_interface.find_shop_by_name(shop_name)[0]
@ -251,6 +293,13 @@ def loc_list_to_string(loc_list, str_format='{}\n{}'):
return loc_string
def get_args_dict(args):
if len(args) != 0:
return dict(zip_longest(*[iter(args)] * 2, fillvalue=""))
else:
return {}
def create_config():
config['Discord'] = {'Token': ''}
config['SQL'] = {'Dialect+Driver': 'test', 'username': '', 'password':'', 'host': '', 'port': '', 'database':''}

View File

@ -7,7 +7,7 @@ class TestGeoffreyDatabase(TestCase):
def setUp(self):
self.interface = DiscordDatabaseInterface('sqlite:///:memory:')
self.owner = Player('ZeroHD', '143072699567177728')
self.loc = Location('test', 1, 2, 3, self.owner, ['Green', 0, 'Right', 'Nether'])
self.loc = Location('test', 1, 2, 3, self.owner, 'Green,105,Right', 'Nether')
def test_add_object(self):
self.interface.database.add_object(self.loc)
@ -43,8 +43,8 @@ class TestGeoffreyDatabase(TestCase):
self.assertRaises(DeleteEntryError, self.interface.database.delete_entry, Location, expr)
def test_add_shop(self):
owner = self.interface.add_player('ZeroHD', '143072699567177728')
shop = self.interface.add_shop('143072699567177728', 'test', 1, 2, 3, ['Green', 0, 'Right', 'Nether'])
owner = self.add_player()
shop = self.add_shop()
self.assertEqual(type(shop), Shop)
@ -52,42 +52,51 @@ class TestGeoffreyDatabase(TestCase):
self.assertEqual(shop_list[0].dimension, shop.dimension)
self.assertEqual(shop_list[0].tunnel_side, shop.tunnel_side)
def add_shop(self):
return self.interface.add_shop('143072699567177728', 'test', 1, 2, 3, 'Green,105,Right', 'Nether')
def add_player(self):
return self.interface.add_player('ZeroHD', '143072699567177728')
def add_loc(self):
return self.interface.add_location('143072699567177728', 'test', 0, 0, 0, 'Green,105,Right', 'Nether')
def test_add_two_shops(self):
owner = self.interface.add_player('ZeroHD', '143072699567177728')
shop1 = self.interface.add_shop('143072699567177728', 'test', 1, 2, 3, ['Green', 0, 'Right', 'Nether'])
shop2 = self.interface.add_shop('143072699567177728', 'no u', 1, 2, 3, ['Green', 0, 'Right', 'Nether'])
owner = self.add_player()
shop1 = self.add_shop()
shop2 = self.interface.add_shop('143072699567177728', 'no u', 1, 2, 3, 'Green,0,Right', 'Nether')
loc_list = self.interface.find_location_by_owner_uuid('143072699567177728')
self.assertEqual(loc_list[1].id, shop2.id)
def test_add_item(self):
owner = self.interface.add_player('ZeroHD', '143072699567177728')
self.interface.add_shop('143072699567177728', 'test', 1, 2, 3, ['Green', 0, "Right"])
owner = self.add_player()
self.add_shop()
self.interface.add_item('143072699567177728', 'test', 'dirt', 1, 15)
shops = self.interface.find_shop_selling_item('dirt')
self.assertEqual(shops[0].name, 'test')
def test_find_location_by_owner(self):
owner = self.interface.add_player('ZeroHD', '143072699567177728')
shop = self.interface.add_shop('143072699567177728', 'test', 1, 2, 3, ['Green', 0, "Right"])
owner = self.add_player()
shop = self.add_shop()
loc_list = self.interface.find_location_by_owner(owner)
self.assertEqual(loc_list[0].id, shop.id)
def test_find_location_by_name_and_owner(self):
owner = self.interface.add_player('ZeroHD', '143072699567177728')
shop = self.interface.add_shop('143072699567177728', 'test', 1, 2, 3, ['Green', 0, "Right"])
owner = self.add_player()
shop = self.add_shop()
loc_list = self.interface.find_location_by_name_and_owner_uuid('143072699567177728', 'test')
self.assertEqual(loc_list[0].id, shop.id)
def test_delete_base(self):
owner = self.interface.add_player('ZeroHD', '143072699567177728')
self.interface.add_location('143072699567177728', 'test', 1, 2, 3, ['Green', 0, "Right"])
owner = self.add_player()
self.add_loc()
self.interface.delete_location('143072699567177728', 'test')
@ -96,10 +105,10 @@ class TestGeoffreyDatabase(TestCase):
self.assertEqual(len(loc_list), 0)
def test_find_location_around(self):
owner = self.interface.add_player('ZeroHD', '143072699567177728')
loc = self.interface.add_location('143072699567177728', 'test', 0, 0, 0, ['Green', 0, "Right"])
owner = self.add_player()
loc = self.add_loc()
dim = Dimension.str_to_dimension("O")
dim = "o"
loc_list = self.interface.find_location_around(100, 100, 100, dim)
@ -126,22 +135,22 @@ class TestGeoffreyDatabase(TestCase):
self.assertEqual(loc_list[0].name, loc.name)
def test_find_location_by_name(self):
owner = self.interface.add_player('ZeroHD', '143072699567177728')
loc = self.interface.add_location('143072699567177728', 'test', 0, 0, 0, ['Green', 0, "Right"])
owner = self.add_player()
loc = self.add_loc()
loc_list = self.interface.find_location_by_name('test')
self.assertEqual(loc_list[0].name, loc.name)
def test_wrong_case(self):
owner = self.interface.add_player('ZeroHD', '143072699567177728')
loc = self.interface.add_location('143072699567177728', 'test', 0, 0, 0, ['Green', 0, "right"])
owner = self.add_player()
loc = self.add_loc()
loc_list = self.interface.find_location_by_owner_name('zerohd')
self.assertEqual(loc_list[0].id, loc.id)
self.interface.add_shop('143072699567177728', 'testshop', 1, 2, 3, ['Green', 0, "lEft", "neThEr"])
self.interface.add_shop('143072699567177728', 'testshop', 1, 2, 3, 'Green,0,lEft', 'neThEr')
self.interface.add_item('143072699567177728', 'testshop', 'dirts', 1, 15)
@ -158,20 +167,20 @@ class TestGeoffreyDatabase(TestCase):
self.assertEqual(loc_list[0].name, 'test')
def test_big_input(self):
owner = self.interface.add_player('ZeroHD', '143072699567177728')
owner = self.add_player()
loc = self.interface.add_location('143072699567177728',
'TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT', 0, 0, 0, ['Green', 0, "Right"])
'TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT', 0, 0, 0)
loc_list = self.interface.find_location_by_owner(owner)
self.assertEqual(loc_list[0].id, loc.id)
def test_duplicate_name(self):
self.interface.add_player('ZeroHD', '143072699567177728')
self.interface.add_location('143072699567177728', 'test', 0, 0, 0, ['Green', 0, "right"])
self.add_player()
self.add_loc()
self.assertRaises(LocationNameNotUniqueError, self.interface.add_location,
'143072699567177728', 'test', 0, 0, 0, ['Green', 0, "right"])
'143072699567177728', 'test', 0, 0, 0)