275 lines
7.9 KiB
Python
275 lines
7.9 KiB
Python
from django.db.models import Q, F
|
|
from GeoffreyApp.models import *
|
|
from GeoffreyApp.errors import *
|
|
from GeoffreyApp.minecraft_api import *
|
|
import inspect
|
|
|
|
command_dict = {"GET": {}, "POST": {}, "DELETE": {}}
|
|
|
|
|
|
def getRequiredArgs(func):
|
|
args = inspect.getfullargspec(func)
|
|
|
|
return args.args + args.kwonlyargs
|
|
|
|
|
|
def command(type):
|
|
def command_dec(func):
|
|
def add_command():
|
|
command_dict[type][func.__name__] = {"func": func, "params": getRequiredArgs(func)}
|
|
|
|
return add_command()
|
|
|
|
return command_dec
|
|
|
|
|
|
def get_player(discord_uuid=None, mc_uuid=None):
|
|
if discord_uuid is not None:
|
|
player = Player.objects.get(discord_uuid=discord_uuid)
|
|
elif mc_uuid is not None:
|
|
player = Player.objects.get(mc_uuid=discord_uuid)
|
|
else:
|
|
raise AttributeError
|
|
|
|
return player
|
|
|
|
|
|
def get_location(owner, name=None, loc_type=Location):
|
|
if name is None:
|
|
if loc_type == Location:
|
|
loc_list = Location.objects.all().filter(owner=owner)
|
|
else:
|
|
loc_list = Location.objects.all().select_related(loc_type.__name__.lower()).filter(owner=owner)
|
|
if len(loc_list) == 1:
|
|
loc = loc_list[0]
|
|
elif len(loc_list) == 0:
|
|
raise NoLocationsInDatabase
|
|
else:
|
|
raise EntryNameNotUniqueError
|
|
else:
|
|
if loc_type == Location:
|
|
loc_list = Location.objects.all().filter(owner=owner)
|
|
else:
|
|
loc_list = Location.objects.all().select_related(loc_type.__name__.lower()).filter(owner=owner)
|
|
if len(loc_list) == 1:
|
|
loc = loc_list[0]
|
|
else:
|
|
raise LocationLookUpError
|
|
|
|
return loc
|
|
|
|
|
|
@command("POST")
|
|
def register(player_name, discord_uuid):
|
|
mc_uuid = grab_UUID(player_name)
|
|
player = Player.objects.create(name=player_name, mc_uuid=mc_uuid, discord_uuid=discord_uuid)
|
|
|
|
return player.json
|
|
|
|
|
|
@command("POST")
|
|
def add_base(x_pos, z_pos, name=None, discord_uuid=None, mc_uuid=None):
|
|
return add_location(x_pos, z_pos, name=name, discord_uuid=discord_uuid, mc_uuid=mc_uuid, loc_type=Base)
|
|
|
|
|
|
@command("POST")
|
|
def add_shop(x_pos, z_pos, name=None, discord_uuid=None, mc_uuid=None):
|
|
return add_location(x_pos, z_pos, name=name, discord_uuid=discord_uuid, mc_uuid=mc_uuid, loc_type=Shop)
|
|
|
|
|
|
def add_location(x_pos, z_pos, name=None, discord_uuid=None, mc_uuid=None, loc_type=Location):
|
|
player = get_player(discord_uuid, mc_uuid)
|
|
try:
|
|
get_location(player, name, loc_type=loc_type)
|
|
raise EntryNameNotUniqueError
|
|
except Location.DoesNotExist:
|
|
if name is None:
|
|
name = "{}'s {}".format(player.name, loc_type.__name__)
|
|
|
|
if loc_type == Base:
|
|
location = Base.objects.create(owner=player, name=name, x_coord=x_pos, z_coord=z_pos)
|
|
elif loc_type == Shop:
|
|
location = Shop.objects.create(owner=player, name=name, x_coord=x_pos, z_coord=z_pos)
|
|
else:
|
|
raise DataBaseError
|
|
|
|
return location
|
|
|
|
|
|
@command("POST")
|
|
def add_tunnel(tunnel_direction, tunnel_number, location_name=None, discord_uuid=None, mc_uuid=None):
|
|
player = get_player(discord_uuid, mc_uuid)
|
|
if location_name is None:
|
|
loc = get_location(player, name=location_name)
|
|
location_name = loc.name
|
|
|
|
tunnel = Tunnel.objects.create(tunnel_direction=tunnel_direction, tunnel_number=tunnel_number,
|
|
location=get_location(player, location_name))
|
|
|
|
return tunnel
|
|
|
|
|
|
@command("GET")
|
|
def find_location(search):
|
|
limit = 25
|
|
|
|
locations_obj = Location.objects.filter(Q(name__icontains=search) | Q(owner__name__icontains=search)).all()[:limit]
|
|
|
|
if len(locations_obj) == 0:
|
|
raise LocationLookUpError
|
|
|
|
locations_json = []
|
|
for location in locations_obj:
|
|
locations_json.append(location.json)
|
|
|
|
return locations_json
|
|
|
|
|
|
@command("DELETE")
|
|
def delete(name, discord_uuid=None, mc_uuid=None):
|
|
owner = get_player(discord_uuid, mc_uuid)
|
|
Location.objects.get(name__iexact=name, owner=owner).delete()
|
|
|
|
|
|
@command("GET")
|
|
def find_around(x_pos, z_pos, radius=200):
|
|
locations = Location.objects.get(x_coord__range=(x_pos - radius, x_pos + radius),
|
|
z_coord__range=(z_pos - radius, z_pos + radius), dimension='O')
|
|
|
|
return locations
|
|
|
|
|
|
@command("POST")
|
|
def add_item(item_name, quantity, diamond_price, shop_name=None, discord_uuid=None, mc_uuid=None):
|
|
player = get_player(discord_uuid, mc_uuid)
|
|
|
|
shop = get_location(player, shop_name, Shop).shop
|
|
|
|
item_listing = ItemListing.objects.create(shop=shop, amount=quantity, price=diamond_price, item_name=item_name)
|
|
|
|
return item_listing
|
|
|
|
|
|
# TODO Re-implement selling shop search
|
|
@command("GET")
|
|
def selling(item_name):
|
|
items = []
|
|
if len(item_name) == 0:
|
|
raise EmptryString
|
|
|
|
shops = ItemListing.objects.annotate(normalized_price=F('price') / F('amount'))\
|
|
.filter(item_name__icontains=item_name).order_by('normalized_price').values('shop_id').distinct()
|
|
|
|
if len(shops) == 0:
|
|
raise ItemNotFound
|
|
|
|
for shop_id in shops:
|
|
shop = Shop.objects.get(pk=shop_id['shop_id']).json
|
|
|
|
item_query = ItemListing.objects.annotate(normalized_price=F('price') / F('amount')) \
|
|
.filter(item_name__icontains=item_name, shop_id=shop_id) \
|
|
.order_by('normalized_price') \
|
|
.values("item_name", "amount", "price")
|
|
|
|
item_list = []
|
|
for item in item_query:
|
|
item_list.append(item)
|
|
|
|
shop["items"] = item_list
|
|
items.append(shop)
|
|
|
|
return items
|
|
|
|
|
|
@command("GET")
|
|
def info(location_name):
|
|
location = Location.objects.get(name__iexact=location_name)
|
|
|
|
if location is None:
|
|
location = Location.objects.get(name__iregex="*{}*".format(location_name))
|
|
|
|
if location is not None:
|
|
return location.json
|
|
else:
|
|
raise LocationLookUpError
|
|
|
|
|
|
@command("GET")
|
|
def tunnel(player_name):
|
|
tunnels_obj = Tunnel.objects.filter(location__owner__name__icontains=player_name).all()
|
|
|
|
if len(tunnels_obj) == 0:
|
|
raise LocationLookUpError
|
|
|
|
tunnels_json = []
|
|
|
|
for t in tunnels_obj:
|
|
tunnels_json.append(t.json)
|
|
|
|
return tunnels_json
|
|
|
|
|
|
@command("POST")
|
|
def edit_pos(x, z, loc_name, discord_uuid=None, mc_uuid=None):
|
|
|
|
player = get_player(discord_uuid=discord_uuid, mc_uuid=mc_uuid)
|
|
location = get_location(player, loc_name)
|
|
|
|
location.x_coord = x
|
|
location.z_coord = z
|
|
location.save()
|
|
|
|
return location
|
|
|
|
|
|
@command("POST")
|
|
def edit_tunnel(tunnel_direction, tunnel_number, loc_name, discord_uuid=None, mc_uuid=None):
|
|
player = get_player(discord_uuid=discord_uuid, mc_uuid=mc_uuid)
|
|
location = get_location(player, loc_name)
|
|
|
|
if location.tunnel is not None:
|
|
location.tunnel.tunnel_direction = tunnel_direction
|
|
location.tunnel.tunnel_number = tunnel_number
|
|
else:
|
|
Tunnel.objects.create(tunnel_direction=tunnel_direction, tunnel_number=tunnel_number, location=location)
|
|
|
|
return location
|
|
|
|
|
|
@command("POST")
|
|
def edit_name(new_name, loc_name, discord_uuid=None, mc_uuid=None):
|
|
player = get_player(discord_uuid=discord_uuid, mc_uuid=mc_uuid)
|
|
location = get_location(player, loc_name)
|
|
|
|
location.name = new_name
|
|
location.save()
|
|
|
|
return location
|
|
|
|
|
|
@command("DELETE")
|
|
def delete_item(item, shop_name, discord_uuid=None, mc_uuid=None):
|
|
player = get_player(discord_uuid=discord_uuid, mc_uuid=mc_uuid)
|
|
|
|
shop = get_location(player, shop_name, Shop)
|
|
|
|
ItemListing.objects.filter(item_name__iexact=item, shop=shop).delete()
|
|
|
|
return shop
|
|
|
|
|
|
@command("GET")
|
|
def me(discord_uuid=None, mc_uuid=None):
|
|
player = get_player(discord_uuid=discord_uuid, mc_uuid=mc_uuid)
|
|
|
|
locations_obj = Location.objects.filter(owner=player).all()
|
|
|
|
if len(locations_obj) == 0:
|
|
raise PlayerNotFound
|
|
|
|
locations_json = []
|
|
for location in locations_obj:
|
|
locations_json.append(location.json)
|
|
|
|
return locations_json
|