Initial Commit for v2
Began migration of project to Django Created Django models for all current SQLAlchemy modelsdoc_update
parent
2557e75a2f
commit
7748ab4010
|
@ -0,0 +1,2 @@
|
|||
*.pyc
|
||||
__pycache__/*
|
|
@ -0,0 +1,9 @@
|
|||
from django.contrib import admin
|
||||
from .models import *
|
||||
|
||||
# Register your models here.
|
||||
admin.site.register(Player)
|
||||
admin.site.register(Base)
|
||||
admin.site.register(Shop)
|
||||
admin.site.register(Tunnel)
|
||||
admin.site.register(ItemListing)
|
|
@ -0,0 +1,5 @@
|
|||
from django.apps import AppConfig
|
||||
|
||||
|
||||
class GeoffreyConfig(AppConfig):
|
||||
name = 'geoffrey'
|
|
@ -1,85 +0,0 @@
|
|||
import codecs
|
||||
import configparser
|
||||
|
||||
|
||||
def create_config(config, path):
|
||||
config['Discord'] = {'Token': '',
|
||||
'Status': '',
|
||||
'Prefix': '?',
|
||||
'Bot_Mod': '',
|
||||
'Error_Users': ''
|
||||
}
|
||||
config['SQL'] = {'Dialect+Driver': 'mysql+pymysql',
|
||||
'Username': '',
|
||||
'Password': '',
|
||||
'Host': '',
|
||||
'Port': '',
|
||||
'Database': ''
|
||||
}
|
||||
config['Minecraft'] = {'Dynmap_Url': '',
|
||||
'World_Name': '',
|
||||
}
|
||||
config['Logging'] = {'Log_Path': '',
|
||||
'Count': '7',
|
||||
'Rotation_Duration': '1'
|
||||
}
|
||||
config['Special Names'] = {}
|
||||
|
||||
with open(path, 'w') as configfile:
|
||||
config.write(configfile)
|
||||
|
||||
|
||||
def read_config(path):
|
||||
config = configparser.ConfigParser()
|
||||
try:
|
||||
file = codecs.open(path, "r", "utf8")
|
||||
config.read_file(file)
|
||||
file.close()
|
||||
except FileNotFoundError:
|
||||
create_config(config, path)
|
||||
print("Config generated.")
|
||||
quit(0)
|
||||
|
||||
return config
|
||||
|
||||
|
||||
class Config:
|
||||
|
||||
def __init__(self, path):
|
||||
try:
|
||||
self.config = read_config(path)
|
||||
self.engine_args = self.read_engine_arg()
|
||||
|
||||
self.token = self.config['Discord']['Token']
|
||||
self.status = self.config['Discord']['Status']
|
||||
self.prefix = self.config['Discord']['Prefix']
|
||||
self.bot_mod = self.config['Discord']['Bot_Mod'].split(',')
|
||||
self.error_users = self.config['Discord']['Error_Users'].split(',')
|
||||
|
||||
self.world_name = self.config['Minecraft']['World_Name']
|
||||
self.dynmap_url = self.config['Minecraft']['Dynmap_Url']
|
||||
|
||||
self.log_path = self.config['Logging']['log_path']
|
||||
self.count = int(self.config['Logging']['Count'])
|
||||
self.rotation_duration = int(self.config['Logging']['Rotation_Duration'])
|
||||
|
||||
self.special_name_list = dict(self.config.items('Special Names'))
|
||||
except Exception as e:
|
||||
print("Invalid config file, missing {}.".format(e))
|
||||
quit(1)
|
||||
|
||||
def read_engine_arg(self):
|
||||
driver = self.config['SQL']['Dialect+Driver']
|
||||
username = self.config['SQL']['Username']
|
||||
password = self.config['SQL']['Password']
|
||||
host = self.config['SQL']['Host']
|
||||
port = self.config['SQL']['Port']
|
||||
database_name = self.config['SQL']['Database']
|
||||
|
||||
engine_args = '{}://{}:{}@{}:{}/{}?charset=utf8mb4&use_unicode=1'
|
||||
|
||||
return engine_args.format(driver, username, password, host, port, database_name)
|
||||
|
||||
|
||||
def get_config(config_path):
|
||||
return Config(config_path)
|
|
@ -1,82 +0,0 @@
|
|||
class DataBaseError(Exception):
|
||||
"""Base class for exceptions in this module."""
|
||||
pass
|
||||
|
||||
|
||||
class LocationInitError(DataBaseError):
|
||||
"""Error in initializing Location"""
|
||||
|
||||
|
||||
class TunnelInitError(DataBaseError):
|
||||
"""Error in initializing Tunnel"""
|
||||
|
||||
|
||||
class NoMatchFoundError(DataBaseError):
|
||||
"""No matches were found in the database"""
|
||||
|
||||
|
||||
class LocationLookUpError(DataBaseError):
|
||||
"""Error in finding location in database"""
|
||||
|
||||
|
||||
class DeleteEntryError(DataBaseError):
|
||||
"""Error in deleting entry"""
|
||||
|
||||
|
||||
class UsernameLookupFailed(Exception):
|
||||
"""Error in username lookup, is the player's nickname set correctly? *stares at aeskdar*"""
|
||||
|
||||
|
||||
class PlayerNotFound(DataBaseError):
|
||||
"""Player not found in database."""
|
||||
|
||||
|
||||
class EntryNameNotUniqueError(DataBaseError):
|
||||
"""A location by that name is already in the database."""
|
||||
|
||||
|
||||
class StringTooLong(DataBaseError):
|
||||
"""Given string is too long."""
|
||||
|
||||
|
||||
class DatabaseValueError(DataBaseError):
|
||||
"""'String too long or number too large"""
|
||||
|
||||
|
||||
class ItemNotFound(DataBaseError):
|
||||
"""No item matches found in database"""
|
||||
|
||||
|
||||
class InvalidDimError(DataBaseError):
|
||||
"""Invalid dimension name"""
|
||||
|
||||
|
||||
class InvalidTunnelError(DataBaseError):
|
||||
"""Invalid tunnel name"""
|
||||
|
||||
|
||||
class PlayerInDBError(DataBaseError):
|
||||
"""Player already registered in database"""
|
||||
|
||||
|
||||
class LocationHasTunnelError(DataBaseError):
|
||||
"""That location already has a tunnel"""
|
||||
|
||||
|
||||
class NoPermissionError(DataBaseError):
|
||||
"""You have no permission to run this command"""
|
||||
|
||||
|
||||
class NotOnServerError(DataBaseError):
|
||||
"""You need to run this command on 24CC"""
|
||||
|
||||
|
||||
class NoLocationsInDatabase(DataBaseError):
|
||||
"""This player has no locations in the database"""
|
||||
|
||||
|
||||
class FuckyWucky:
|
||||
"""You made one."""
|
||||
|
||||
class EmptryString(DataBaseError):
|
||||
"""Empty string provided"""
|
|
@ -1,428 +0,0 @@
|
|||
from geoffrey.DatabaseInterface import *
|
||||
|
||||
|
||||
def list_to_string(loc_list, str_format='{}\n{}'):
|
||||
loc_string = ''
|
||||
|
||||
for loc in loc_list:
|
||||
loc_string = str_format.format(loc_string, loc)
|
||||
|
||||
return loc_string
|
||||
|
||||
|
||||
def checkIfEmpty(str):
|
||||
if len(str) == 0:
|
||||
raise EmptryString
|
||||
|
||||
|
||||
class Commands:
|
||||
def __init__(self, bot_config, debug=False):
|
||||
self.bot_config = bot_config
|
||||
self.interface = DatabaseInterface(bot_config, debug)
|
||||
|
||||
def get_player(self, session, discord_uuid=None, mc_uuid=None):
|
||||
if discord_uuid is not None:
|
||||
player = self.interface.find_player_by_discord_uuid(session, discord_uuid)
|
||||
elif mc_uuid is not None:
|
||||
player = self.interface.find_player_by_mc_uuid(session, mc_uuid)
|
||||
else:
|
||||
raise AttributeError
|
||||
|
||||
return player
|
||||
|
||||
def get_location(self, session, owner, name=None, loc_type=Location):
|
||||
if name is None:
|
||||
loc_list = self.interface.find_location_by_owner(session, owner, loc_type)
|
||||
if len(loc_list) == 1:
|
||||
loc = loc_list[0]
|
||||
elif len(loc_list) == 0:
|
||||
raise NoLocationsInDatabase
|
||||
else:
|
||||
raise EntryNameNotUniqueError
|
||||
else:
|
||||
loc_list = self.interface.find_location_by_name_and_owner(session, owner, name, loc_type)
|
||||
if len(loc_list) == 1:
|
||||
loc = loc_list[0]
|
||||
else:
|
||||
raise LocationLookUpError
|
||||
|
||||
return loc
|
||||
|
||||
def register(self, player_name, discord_uuid):
|
||||
|
||||
session = self.interface.database.Session()
|
||||
|
||||
try:
|
||||
player = self.interface.add_player(session, player_name, discord_uuid)
|
||||
player_name = player.name
|
||||
|
||||
finally:
|
||||
session.close()
|
||||
|
||||
return player_name
|
||||
|
||||
def add_base(self, x_pos, z_pos, base_name=None, discord_uuid=None, mc_uuid=None):
|
||||
|
||||
session = self.interface.database.Session()
|
||||
|
||||
try:
|
||||
player = self.get_player(session, discord_uuid, mc_uuid)
|
||||
|
||||
if len(self.interface.find_location_by_owner(session, player, loc_type=Base)) == 0:
|
||||
if base_name is None:
|
||||
base_name = "{}'s Base".format(player.name)
|
||||
elif base_name is None:
|
||||
raise EntryNameNotUniqueError
|
||||
|
||||
checkIfEmpty(base_name)
|
||||
|
||||
base = self.interface.add_loc(session, player, base_name, x_pos, z_pos, loc_type=Base)
|
||||
|
||||
base_str = base.__str__()
|
||||
finally:
|
||||
session.close()
|
||||
|
||||
return base_str
|
||||
|
||||
def add_shop(self, x_pos, z_pos, shop_name=None, discord_uuid=None, mc_uuid=None):
|
||||
session = self.interface.database.Session()
|
||||
|
||||
try:
|
||||
player = self.get_player(session, discord_uuid, mc_uuid)
|
||||
|
||||
if len(self.interface.find_location_by_owner(session, player, loc_type=Shop)) == 0:
|
||||
if shop_name is None:
|
||||
shop_name = "{}'s Shop".format(player.name)
|
||||
elif shop_name is None:
|
||||
raise EntryNameNotUniqueError
|
||||
|
||||
checkIfEmpty(shop_name)
|
||||
shop = self.interface.add_loc(session, player, shop_name, x_pos, z_pos, loc_type=Shop)
|
||||
|
||||
shop_name = shop.__str__()
|
||||
finally:
|
||||
session.close()
|
||||
|
||||
return shop_name
|
||||
|
||||
def add_tunnel(self, tunnel_direction, tunnel_number, location_name=None, discord_uuid=None, mc_uuid=None):
|
||||
|
||||
session = self.interface.database.Session()
|
||||
try:
|
||||
|
||||
player = self.get_player(session, discord_uuid, mc_uuid)
|
||||
if location_name is None:
|
||||
loc = self.get_location(session, player, name=location_name)
|
||||
location_name = loc.name
|
||||
|
||||
checkIfEmpty(location_name)
|
||||
tunnel = self.interface.add_tunnel(session, player, tunnel_direction, tunnel_number, location_name)
|
||||
tunnel_info = tunnel.__str__()
|
||||
|
||||
finally:
|
||||
session.close()
|
||||
|
||||
return tunnel_info
|
||||
|
||||
def find(self, search):
|
||||
limit = 25
|
||||
session = self.interface.database.Session()
|
||||
checkIfEmpty(search)
|
||||
try:
|
||||
locations = self.interface.search_all_fields(session, search, limit)
|
||||
locations_string = ''
|
||||
|
||||
if len(locations) > 0:
|
||||
|
||||
for loc in locations:
|
||||
locations_string = "{}\n{}".format(locations_string, loc)
|
||||
|
||||
if len(locations) == limit:
|
||||
locations_string = locations_string + '\n**. . .**'
|
||||
else:
|
||||
raise LocationLookUpError
|
||||
finally:
|
||||
session.close()
|
||||
|
||||
return locations_string
|
||||
|
||||
def delete(self, name, discord_uuid=None, mc_uuid=None):
|
||||
session = self.interface.database.Session()
|
||||
checkIfEmpty(name)
|
||||
try:
|
||||
player = self.get_player(session, discord_uuid, mc_uuid)
|
||||
self.interface.delete_location(session, player, name)
|
||||
finally:
|
||||
session.close()
|
||||
|
||||
def find_around(self, x_pos, z_pos, radius=200, dimension='Overworld'):
|
||||
|
||||
session = self.interface.database.Session()
|
||||
|
||||
try:
|
||||
loc_list = self.interface.find_location_around(session, x_pos, z_pos, radius, dimension)
|
||||
|
||||
loc_list_str = list_to_string(loc_list)
|
||||
finally:
|
||||
session.close()
|
||||
|
||||
return loc_list_str
|
||||
|
||||
def add_item(self, item_name, quantity, diamond_price, shop_name=None, discord_uuid=None, mc_uuid=None):
|
||||
session = self.interface.database.Session()
|
||||
checkIfEmpty(item_name)
|
||||
try:
|
||||
player = self.get_player(session, discord_uuid, mc_uuid)
|
||||
|
||||
shop = self.get_location(session, player, shop_name, Shop)
|
||||
|
||||
item_listing = self.interface.add_item(session, player, shop.name, item_name, diamond_price, quantity)
|
||||
item_listing_str = item_listing.__str__()
|
||||
finally:
|
||||
session.close()
|
||||
|
||||
return item_listing_str
|
||||
|
||||
def selling(self, item_name: str):
|
||||
session = self.interface.database.Session()
|
||||
|
||||
try:
|
||||
|
||||
if len(item_name) == 0:
|
||||
raise EmptryString
|
||||
|
||||
shop_list = self.interface.find_top_shops_selling_item(session, item_name)
|
||||
|
||||
if len(shop_list) == 0:
|
||||
raise ItemNotFound
|
||||
|
||||
shop_list_str = "\n"
|
||||
for shop in shop_list:
|
||||
matches = self.interface.get_inventory_matches(session, shop[0], item_name)
|
||||
shop_list_str = shop_list_str + shop[0].selling_str() + list_to_string(matches)
|
||||
|
||||
if len(matches) == 5:
|
||||
shop_list_str = shop_list_str + '\n**...**'
|
||||
|
||||
shop_list_str = shop_list_str + '\n\n'
|
||||
|
||||
finally:
|
||||
session.close()
|
||||
|
||||
return shop_list_str
|
||||
|
||||
def info(self, location_name):
|
||||
session = self.interface.database.Session()
|
||||
try:
|
||||
if len(location_name) == 0:
|
||||
raise EmptryString
|
||||
loc = self.interface.find_location_by_name_closest_match(session,
|
||||
location_name).full_str(self.bot_config)
|
||||
finally:
|
||||
session.close()
|
||||
|
||||
return loc
|
||||
|
||||
def tunnel(self, player_name):
|
||||
session = self.interface.database.Session()
|
||||
|
||||
try:
|
||||
tunnel_list = self.interface.find_tunnel_by_owner_name(session, player_name)
|
||||
|
||||
if len(tunnel_list) == 0:
|
||||
raise LocationLookUpError
|
||||
|
||||
tunnel_str = ''
|
||||
|
||||
for tunnel in tunnel_list:
|
||||
tunnel_str = '{}\n{}'.format(tunnel_str, tunnel.full_str())
|
||||
|
||||
finally:
|
||||
session.close()
|
||||
|
||||
return tunnel_str
|
||||
|
||||
def edit_pos(self, x, z, loc_name, discord_uuid=None, mc_uuid=None):
|
||||
session = self.interface.database.Session()
|
||||
|
||||
try:
|
||||
player = self.get_player(session, discord_uuid=discord_uuid, mc_uuid=mc_uuid)
|
||||
location = self.get_location(session, player, loc_name)
|
||||
|
||||
location.x = x
|
||||
location.z = z
|
||||
|
||||
session.commit()
|
||||
|
||||
loc_str = location.__str__()
|
||||
except DataError:
|
||||
session.rollback()
|
||||
raise DatabaseValueError
|
||||
finally:
|
||||
session.close()
|
||||
|
||||
return loc_str
|
||||
|
||||
def edit_tunnel(self, tunnel_direction, tunnel_number, loc_name, discord_uuid=None, mc_uuid=None):
|
||||
session = self.interface.database.Session()
|
||||
|
||||
try:
|
||||
player = self.get_player(session, discord_uuid=discord_uuid, mc_uuid=mc_uuid)
|
||||
location = self.get_location(session, player, loc_name)
|
||||
|
||||
if location.tunnel is not None:
|
||||
location.tunnel.tunnel_direction = TunnelDirection.str_to_tunnel_dir(tunnel_direction)
|
||||
location.tunnel.tunnel_number = tunnel_number
|
||||
else:
|
||||
self.interface.add_tunnel(session, player, tunnel_direction, tunnel_number, loc_name)
|
||||
|
||||
loc_str = location.__str__()
|
||||
|
||||
session.commit()
|
||||
except IntegrityError:
|
||||
session.rollback()
|
||||
raise EntryNameNotUniqueError
|
||||
except DataError:
|
||||
session.rollback()
|
||||
raise DatabaseValueError
|
||||
except IndexError:
|
||||
raise LocationLookUpError
|
||||
finally:
|
||||
session.close()
|
||||
|
||||
return loc_str
|
||||
|
||||
def edit_name(self, new_name, loc_name, discord_uuid=None, mc_uuid=None):
|
||||
session = self.interface.database.Session()
|
||||
|
||||
try:
|
||||
player = self.get_player(session, discord_uuid=discord_uuid, mc_uuid=mc_uuid)
|
||||
location = self.get_location(session, player, loc_name)
|
||||
|
||||
location.name = new_name
|
||||
loc_str = location.__str__()
|
||||
session.commit()
|
||||
|
||||
except IntegrityError:
|
||||
session.rollback()
|
||||
raise EntryNameNotUniqueError
|
||||
except DataError:
|
||||
session.rollback()
|
||||
raise DatabaseValueError
|
||||
except IndexError:
|
||||
raise LocationLookUpError
|
||||
finally:
|
||||
session.close()
|
||||
|
||||
return loc_str
|
||||
|
||||
def delete_item(self, item, shop_name, discord_uuid=None, mc_uuid=None):
|
||||
session = self.interface.database.Session()
|
||||
|
||||
try:
|
||||
player = self.get_player(session, discord_uuid=discord_uuid, mc_uuid=mc_uuid)
|
||||
|
||||
shop = self.get_location(session, player, shop_name, Shop)
|
||||
|
||||
self.interface.delete_item(session, shop, item)
|
||||
|
||||
shop_str = shop.name
|
||||
finally:
|
||||
session.close()
|
||||
|
||||
return shop_str
|
||||
|
||||
def me(self, discord_uuid=None, mc_uuid=None):
|
||||
session = self.interface.database.Session()
|
||||
|
||||
try:
|
||||
player = self.get_player(session, discord_uuid=discord_uuid, mc_uuid=mc_uuid)
|
||||
|
||||
loc_list = self.interface.find_location_by_owner(session, player)
|
||||
|
||||
if len(loc_list) == 0:
|
||||
raise PlayerNotFound
|
||||
|
||||
loc_str = list_to_string(loc_list)
|
||||
finally:
|
||||
session.close()
|
||||
|
||||
return loc_str
|
||||
|
||||
def update_mc_uuid(self, discord_uuid, mc_uuid):
|
||||
session = self.interface.database.Session()
|
||||
|
||||
try:
|
||||
player = self.interface.find_player_by_discord_uuid(session, discord_uuid)
|
||||
|
||||
player.mc_uuid = mc_uuid
|
||||
|
||||
session.commit()
|
||||
except Exception as e:
|
||||
session.rollback()
|
||||
raise e
|
||||
finally:
|
||||
session.close()
|
||||
|
||||
def update_discord_uuid(self, old_discord_uuid, new_discord_uuid):
|
||||
session = self.interface.database.Session()
|
||||
|
||||
try:
|
||||
player = self.interface.find_player_by_discord_uuid(session, old_discord_uuid)
|
||||
|
||||
player.discord_uuid = new_discord_uuid
|
||||
|
||||
session.commit()
|
||||
except Exception as e:
|
||||
session.rollback()
|
||||
raise e
|
||||
finally:
|
||||
session.close()
|
||||
|
||||
def update_mc_name(self, discord_uuid):
|
||||
session = self.interface.database.Session()
|
||||
|
||||
try:
|
||||
player = self.interface.find_player_by_discord_uuid(session, discord_uuid)
|
||||
|
||||
player.name = grab_playername(player.mc_uuid)
|
||||
|
||||
session.commit()
|
||||
except Exception as e:
|
||||
session.rollback()
|
||||
raise e
|
||||
finally:
|
||||
session.close()
|
||||
|
||||
def add_player(self, discord_uuid, mc_name):
|
||||
session = self.interface.database.Session()
|
||||
|
||||
try:
|
||||
self.interface.find_player_by_discord_uuid(session, discord_uuid)
|
||||
raise PlayerInDBError
|
||||
except PlayerNotFound:
|
||||
player = Player(mc_name, discord_id=discord_uuid)
|
||||
self.interface.database.add_object(session, player)
|
||||
|
||||
player = self.interface.find_player_by_discord_uuid(session, discord_uuid)
|
||||
id = player.id
|
||||
|
||||
finally:
|
||||
session.close()
|
||||
|
||||
return id
|
||||
|
||||
def find_player(self, discord_uuid):
|
||||
session = self.interface.database.Session()
|
||||
|
||||
try:
|
||||
player = self.interface.find_player_by_discord_uuid(session, discord_uuid)
|
||||
id = player.id
|
||||
username = player.name
|
||||
discord_uuid = player.discord_uuid
|
||||
minecraft_uuid = player.mc_uuid
|
||||
|
||||
finally:
|
||||
session.close()
|
||||
|
||||
return id, username, discord_uuid, minecraft_uuid
|
|
@ -1,194 +0,0 @@
|
|||
from sqlalchemy import func
|
||||
from geoffrey.DatabaseModels import *
|
||||
|
||||
|
||||
class DatabaseInterface:
|
||||
|
||||
def __init__(self, bot_config, debug=False):
|
||||
self.database = GeoffreyDatabase(bot_config, debug)
|
||||
|
||||
def add_loc(self, session, owner, name, x_pos, z_pos, dimension=None, loc_type=Location):
|
||||
if loc_type == Base:
|
||||
loc = Base(name, x_pos, z_pos, owner, dimension)
|
||||
elif loc_type == Shop:
|
||||
loc = Shop(name, x_pos, z_pos, owner, dimension)
|
||||
else:
|
||||
loc = Location(name, x_pos, z_pos, owner, dimension)
|
||||
|
||||
self.database.add_object(session, loc)
|
||||
return loc
|
||||
|
||||
def add_tunnel(self, session, owner, direction, number, location_name):
|
||||
tunnels = self.find_tunnel_by_owner(session, owner)
|
||||
if location_name is None:
|
||||
if len(tunnels):
|
||||
raise EntryNameNotUniqueError
|
||||
else:
|
||||
location = None
|
||||
else:
|
||||
try:
|
||||
location = self.find_location_by_name_and_owner(session, owner, location_name)[0]
|
||||
|
||||
if location.tunnel is not None:
|
||||
raise LocationHasTunnelError
|
||||
|
||||
except IndexError:
|
||||
raise LocationLookUpError
|
||||
|
||||
tunnel = Tunnel(owner, direction, number, location)
|
||||
self.database.add_object(session, tunnel)
|
||||
|
||||
return tunnel
|
||||
|
||||
def add_item(self, session, owner, shop_name, item_name, price, amount):
|
||||
try:
|
||||
shop = self.find_location_by_name_and_owner(session, owner, shop_name, loc_type=Shop)
|
||||
|
||||
item = ItemListing(item_name, price, amount, shop[0])
|
||||
self.database.add_object(session, item)
|
||||
except IndexError:
|
||||
raise LocationLookUpError
|
||||
|
||||
return item
|
||||
|
||||
def add_player(self, session, player_name, discord_uuid=None):
|
||||
try:
|
||||
player = self.find_player(session, player_name)
|
||||
|
||||
if (discord_uuid is not None) and (discord_uuid == player.discord_uuid):
|
||||
raise PlayerInDBError
|
||||
else:
|
||||
raise PlayerNotFound
|
||||
|
||||
except PlayerNotFound:
|
||||
mc_uuid = grab_UUID(player_name)
|
||||
try:
|
||||
self.find_player_by_mc_uuid(session, mc_uuid)
|
||||
raise PlayerInDBError
|
||||
except PlayerNotFound:
|
||||
player = Player(player_name, discord_uuid)
|
||||
self.database.add_object(session, player)
|
||||
|
||||
return player
|
||||
|
||||
def find_location_by_name(self, session, name, loc_type=Location):
|
||||
expr = loc_type.name.ilike('%{}%'.format(name))
|
||||
return self.database.query_by_filter(session, loc_type, expr)
|
||||
|
||||
def find_location_by_name_closest_match(self, session, name, loc_type=Location):
|
||||
expr = loc_type.name.ilike('%{}%'.format(name))
|
||||
loc_list = self.database.query_by_filter(session, loc_type, expr)
|
||||
|
||||
if len(loc_list) == 1:
|
||||
loc = loc_list[0]
|
||||
else:
|
||||
expr = loc_type.name.ilike(name)
|
||||
loc_list = self.database.query_by_filter(session, loc_type, expr)
|
||||
|
||||
if len(loc_list) > 1:
|
||||
raise EntryNameNotUniqueError
|
||||
elif len(loc_list) == 0:
|
||||
raise LocationLookUpError
|
||||
else:
|
||||
loc = loc_list[0]
|
||||
|
||||
return loc
|
||||
|
||||
def find_location_by_owner(self, session, owner, loc_type=Location):
|
||||
expr = loc_type.owner == owner
|
||||
return self.database.query_by_filter(session, loc_type, expr)
|
||||
|
||||
def find_location_by_owner_name(self, session, owner_name, loc_type=Location):
|
||||
expr = loc_type.owner.has(Player.name.ilike(owner_name))
|
||||
return self.database.query_by_filter(session, loc_type, expr)
|
||||
|
||||
def find_location_by_name_and_owner(self, session, owner, name, loc_type=Location):
|
||||
expr = (loc_type.owner == owner) & (loc_type.name.ilike(name))
|
||||
return self.database.query_by_filter(session, loc_type, expr)
|
||||
|
||||
def find_location_around(self, session, x_pos, z_pos, radius, dimension, loc_type=Location):
|
||||
dimension_obj = Dimension.str_to_dimension(dimension)
|
||||
expr = (loc_type.x < x_pos + radius + 1) & (loc_type.x > x_pos - radius - 1) & \
|
||||
(loc_type.z < z_pos + radius + 1) \
|
||||
& (loc_type.z > z_pos - radius - 1) & (loc_type.dimension == dimension_obj)
|
||||
|
||||
return self.database.query_by_filter(session, Location, expr)
|
||||
|
||||
def find_tunnel_by_owner(self, session, owner):
|
||||
expr = Tunnel.owner == owner
|
||||
|
||||
return self.database.query_by_filter(session, Tunnel, expr)
|
||||
|
||||
def find_tunnel_by_owner_name(self, session, owner_name):
|
||||
expr = Tunnel.owner.has(Player.name.ilike('%{}%'.format(owner_name)))
|
||||
return self.database.query_by_filter(session, Tunnel, expr)
|
||||
|
||||
def find_item(self, session, item_name, limit=25):
|
||||
expr = ItemListing.name.ilike('%{}%'.format(item_name))
|
||||
return self.database.query_by_filter(session, ItemListing, expr, limit=limit,
|
||||
sort=ItemListing.normalized_price)
|
||||
|
||||
def find_shop_selling_item(self, session, item_name):
|
||||
return self.find_item(session, item_name)
|
||||
|
||||
def find_top_shops_selling_item(self, session, item_name):
|
||||
expr = ItemListing.name.ilike('%{}%'.format(item_name))
|
||||
result = session.query(func.min(ItemListing.normalized_price), ItemListing.shop_id).group_by(
|
||||
ItemListing.shop_id).filter(expr).order_by(func.min(ItemListing.normalized_price)).limit(5).all()
|
||||
|
||||
shop_list = []
|
||||
|
||||
for item in result:
|
||||
expr = Shop.shop_id == item[1]
|
||||
shop = self.database.query_by_filter(session, Shop, expr, limit=10)
|
||||
shop_list.append(shop)
|
||||
|
||||
return shop_list
|
||||
|
||||
def get_inventory_matches(self, session, shop, item_name):
|
||||
expr = (ItemListing.shop_id == shop.id) & (ItemListing.name.ilike('%{}%'.format(item_name)))
|
||||
return self.database.query_by_filter(session, ItemListing, expr, limit=5, sort=ItemListing.normalized_price)
|
||||
|
||||
def find_player(self, session, player_name):
|
||||
expr = func.lower(Player.name) == func.lower(player_name)
|
||||
|
||||
try:
|
||||
player = self.database.query_by_filter(session, Player, expr)[0]
|
||||
except IndexError:
|
||||
raise PlayerNotFound
|
||||
|
||||
return player
|
||||
|
||||
def find_player_by_mc_uuid(self, session, uuid):
|
||||
expr = Player.mc_uuid == uuid
|
||||
|
||||
try:
|
||||
player = self.database.query_by_filter(session, Player, expr)[0]
|
||||
except IndexError:
|
||||
raise PlayerNotFound
|
||||
|
||||
return player
|
||||
|
||||
def find_player_by_discord_uuid(self, session, uuid):
|
||||
expr = Player.discord_uuid == uuid
|
||||
|
||||
try:
|
||||
player = self.database.query_by_filter(session, Player, expr)[0]
|
||||
|
||||
except IndexError:
|
||||
raise PlayerNotFound
|
||||
return player
|
||||
|
||||
def search_all_fields(self, session, search, limit=25):
|
||||
expr = Location.owner.has(Player.name.ilike('%{}%'.format(search))) | Location.name.ilike('%{}%'.format(search))
|
||||
locations = self.database.query_by_filter(session, Location, expr, limit=limit)
|
||||
|
||||
return locations
|
||||
|
||||
def delete_location(self, session, owner, name):
|
||||
expr = (Location.owner == owner) & (Location.name == name)
|
||||
self.database.delete_entry(session, Location, expr)
|
||||
|
||||
def delete_item(self, session, shop, item_name):
|
||||
expr = (ItemListing.name == item_name) & (ItemListing.shop == shop)
|
||||
self.database.delete_entry(session, ItemListing, expr)
|
|
@ -1,311 +0,0 @@
|
|||
import enum
|
||||
from difflib import SequenceMatcher
|
||||
from sys import maxsize
|
||||
|
||||
from sqlalchemy import Column, Integer, String, ForeignKey, Enum, create_engine, exists
|
||||
from sqlalchemy.exc import IntegrityError, DataError
|
||||
from sqlalchemy.ext.declarative import declarative_base
|
||||
from sqlalchemy.orm import relationship, column_property, sessionmaker
|
||||
from sqlalchemy.sql import expression, case
|
||||
from sqlalchemy.ext.hybrid import hybrid_property
|
||||
|
||||
from geoffrey.BotErrors import *
|
||||
from geoffrey.MinecraftAccountInfoGrabber import *
|
||||
|
||||
SQL_Base = declarative_base()
|
||||
|
||||
|
||||
def check_similarity(a, b):
|
||||
ratio = SequenceMatcher(None, a, b).ratio()
|
||||
|
||||
if (ratio > 0.80) or (a[0] == b[0]):
|
||||
return True
|
||||
else:
|
||||
return False
|
||||
|
||||
|
||||
class GeoffreyDatabase:
|
||||
|
||||
def __init__(self, bot_config, debug):
|
||||
if not debug:
|
||||
self.engine = create_engine(bot_config.engine_args, pool_recycle=3600)
|
||||
else:
|
||||
self.engine = create_engine(bot_config.config['SQL']['test_args'], pool_recycle=3600)
|
||||
self.Session = sessionmaker(bind=self.engine)
|
||||
SQL_Base.metadata.create_all(self.engine)
|
||||
|
||||
def clear_all(self, session):
|
||||
session.query(Tunnel).delete()
|
||||
session.query(ItemListing).delete()
|
||||
session.query(Shop).delete()
|
||||
session.query(Location).delete()
|
||||
session.query(Player).delete()
|
||||
session.commit()
|
||||
|
||||
def add_object(self, session, obj):
|
||||
try:
|
||||
ret = session.query(exists().where(type(obj).id == obj.id))
|
||||
if ret:
|
||||
session.add(obj)
|
||||
session.commit()
|
||||
except IntegrityError:
|
||||
session.rollback()
|
||||
raise EntryNameNotUniqueError
|
||||
except DataError:
|
||||
session.rollback()
|
||||
raise DatabaseValueError
|
||||
except:
|
||||
session.rollback()
|
||||
raise Exception
|
||||
|
||||
def query_by_filter(self, session, obj_type, *args, sort=None, limit=10):
|
||||
filter_value = self.combine_filter(args)
|
||||
return session.query(obj_type).filter(filter_value).order_by(sort).limit(limit).all()
|
||||
|
||||
def delete_entry(self, session, obj_type, *args):
|
||||
|
||||
filter_value = self.combine_filter(args)
|
||||
entry = session.query(obj_type).filter(filter_value)
|
||||
|
||||
if entry.first() is not None:
|
||||
entry.delete()
|
||||
else:
|
||||
raise DeleteEntryError
|
||||
|
||||
session.commit()
|
||||
|
||||
def print_database(self, session, obj_type):
|
||||
obj_list = session.query(obj_type).all()
|
||||
|
||||
s = ''
|
||||
|
||||
for obj in obj_list:
|
||||
s = s + '\n' + obj.id
|
||||
return s
|
||||
|
||||
def combine_filter(self, filter_value):
|
||||
return expression.and_(filter_value[0])
|
||||
|
||||
|
||||
class TunnelDirection(enum.Enum):
|
||||
North = "north"
|
||||
East = "east"
|
||||
South = "south"
|
||||
West = "west"
|
||||
|
||||
def str_to_tunnel_dir(arg):
|
||||
arg = arg.lower()
|
||||
|
||||
if check_similarity(TunnelDirection.North.value, arg):
|
||||
return TunnelDirection.North
|
||||
elif check_similarity(TunnelDirection.East.value, arg):
|
||||
return TunnelDirection.East
|
||||
elif check_similarity(TunnelDirection.South.value, arg):
|
||||
return TunnelDirection.South
|
||||
elif check_similarity(TunnelDirection.West.value, arg):
|
||||
return TunnelDirection.West
|
||||
else:
|
||||
raise InvalidTunnelError
|
||||
|
||||
|
||||
class Dimension(enum.Enum):
|
||||
overworld = 'overworld'
|
||||
nether = 'nether'
|
||||
end = 'end'
|
||||
|
||||
def str_to_dimension(arg):
|
||||
arg = arg.lower()
|
||||
if check_similarity(Dimension.overworld.value, arg):
|
||||
return Dimension.overworld
|
||||
elif check_similarity(Dimension.nether.value, arg):
|
||||
return Dimension.nether
|
||||
elif check_similarity(Dimension.end.value, arg):
|
||||
return Dimension.end
|
||||
else:
|
||||
raise InvalidDimError
|
||||
|
||||
|
||||
class Player(SQL_Base):
|
||||
__tablename__ = 'geoffrey_players'
|
||||
id = Column(Integer, primary_key=True, autoincrement=True)
|
||||
mc_uuid = Column(String(128))
|
||||
discord_uuid = Column(String(128))
|
||||
name = Column(String(128))
|
||||
|
||||
locations = relationship("Location", back_populates="owner", lazy='dynamic',
|
||||
cascade="save-update, merge, delete, delete-orphan", single_parent=True)
|
||||
|
||||
tunnels = relationship("Tunnel", back_populates="owner", lazy='dynamic',
|
||||
cascade="save-update, merge, delete, delete-orphan")
|
||||
|
||||
def __init__(self, name, discord_id=None):
|
||||
self.mc_uuid = grab_UUID(name)
|
||||
self.discord_uuid = discord_id
|
||||
self.name = name
|
||||
|
||||
|
||||
class Tunnel(SQL_Base):
|
||||
__tablename__ = 'geoffrey_tunnels'
|
||||
id = Column(Integer, primary_key=True, autoincrement=True)
|
||||
tunnel_number = Column(Integer)
|
||||
tunnel_direction = Column(Enum(TunnelDirection))
|
||||
owner_id = Column(Integer, ForeignKey('geoffrey_players.id'))
|
||||
owner = relationship("Player", back_populates="tunnels", cascade="save-update, merge, delete")
|
||||
location_id = Column(Integer, ForeignKey('geoffrey_locations.id', ondelete='CASCADE'))
|
||||
location = relationship("Location", back_populates="tunnel", lazy="joined")
|
||||
|
||||
def __init__(self, owner, tunnel_direction, tunnel_number, location=None):
|
||||
try:
|
||||
self.owner = owner
|
||||
self.location = location
|
||||
self.tunnel_direction = TunnelDirection.str_to_tunnel_dir(tunnel_direction)
|
||||
self.tunnel_number = tunnel_number
|
||||
except (ValueError, IndexError):
|
||||
raise TunnelInitError
|
||||
|
||||
def full_str(self):
|
||||
if self.location is None:
|
||||
string = 'Tunnel: **{}**'.format(self.__str__())
|
||||
else:
|
||||
string = 'Location: **{}** Tunnel: **{}**'.format(self.location.name, self.__str__())
|
||||
|
||||
return string
|
||||
|
||||
def __str__(self):
|
||||
return '{} {}'.format(self.tunnel_direction.value.title(), self.tunnel_number)
|
||||
|
||||
|
||||
class Location(SQL_Base):
|
||||
__tablename__ = 'geoffrey_locations'
|
||||
|
||||
id = Column(Integer, primary_key=True)
|
||||
name = Column(String(128), unique=True)
|
||||
x = Column(Integer)
|
||||
z = Column(Integer)
|
||||
|
||||
tunnel = relationship("Tunnel", uselist=False, cascade="all, delete-orphan")
|
||||
dimension = Column(Enum(Dimension))
|
||||
|
||||
owner_id = Column(Integer, ForeignKey('geoffrey_players.id', ondelete='CASCADE'))
|
||||
owner = relationship("Player", back_populates="locations", cascade="all, delete-orphan",
|
||||
single_parent=True)
|
||||
type = Column(String(128))
|
||||
|
||||
__mapper_args__ = {
|
||||
'polymorphic_on': type,
|
||||
'polymorphic_identity': 'Location'
|
||||
}
|
||||
|
||||
def __init__(self, name, x, z, owner, dimension):
|
||||
try:
|
||||
self.name = name
|
||||
self.x = x
|
||||
self.z = z
|
||||
self.owner = owner
|
||||
|
||||
if self.dimension is not None:
|
||||
self.dimension = self.dimension = Dimension.str_to_dimension(dimension)
|
||||
else:
|
||||
self.dimension = Dimension.overworld
|
||||
|
||||
except (ValueError, IndexError):
|
||||
raise LocationInitError
|
||||
|
||||
def dynmap_link(self, bot_config):
|
||||
return '<{}/?worldname={}&mapname=surface&zoom=4&x={}&y=65&z={}>'. \
|
||||
format(bot_config.dynmap_url, bot_config.world_name, self.x, self.z)
|
||||
|
||||
def pos_to_str(self):
|
||||
pos_str = '**(x= {}, z= {})**'.format(self.x, self.z)
|
||||
if self.tunnel is not None:
|
||||
return pos_str + ', Tunnel: **{}**'.format(self.tunnel)
|
||||
else:
|
||||
return pos_str
|
||||
|
||||
def info_str(self):
|
||||
return "**{}** @ {}, Owner: **{}**, Type: **{}**".format(self.name, self.pos_to_str(), self.owner.name,
|
||||
self.type)
|
||||
|
||||
def full_str(self, bot_config):
|
||||
return self.__str__() + '\n' + self.dynmap_link(bot_config)
|
||||
|
||||
def __str__(self):
|
||||
return self.info_str()
|
||||
|
||||
|
||||
class Base(Location):
|
||||
__tablename__ = 'geoffrey_bases'
|
||||
base_id = Column(Integer, ForeignKey('geoffrey_locations.id', ondelete='CASCADE'), primary_key=True)
|
||||
name = column_property(Column(String(128)), Location.name)
|
||||
|
||||
__mapper_args__ = {
|
||||
'polymorphic_identity': 'Base',
|
||||
}
|
||||
|
||||
|
||||
class Shop(Location):
|
||||
__tablename__ = 'geoffrey_shops'
|
||||
shop_id = Column(Integer, ForeignKey('geoffrey_locations.id', ondelete='CASCADE'), primary_key=True)
|
||||
name = column_property(Column(String(128)), Location.name)
|
||||
inventory = relationship('ItemListing', back_populates='shop', cascade='all, delete-orphan', lazy='dynamic')
|
||||
__mapper_args__ = {
|
||||
'polymorphic_identity': 'Shop',
|
||||
}
|
||||
|
||||
def inv_to_str(self):
|
||||
if len(self.inventory.limit(15).all()) != 0:
|
||||
inv = '\n**Inventory**:'
|
||||
str_format = '{}\n{}'
|
||||
|
||||
for item in self.inventory:
|
||||
inv = str_format.format(inv, item.listing_str())
|
||||
|
||||
return inv
|
||||
else:
|
||||
return ''
|
||||
|
||||
def full_str(self, bot_config):
|
||||
return Location.full_str(self, bot_config) + self.inv_to_str()
|
||||
|
||||
def selling_str(self):
|
||||
return "**{}** @ {}, Owner: **{}**".format(self.name, self.pos_to_str(), self.owner.name)
|
||||
|
||||
def __str__(self):
|
||||
return Location.__str__(self)
|
||||
|
||||
def __init__(self, name, x, z, owner, dimension=None):
|
||||
Location.__init__(self, name, x, z, owner, dimension)
|
||||
|
||||
|
||||
class ItemListing(SQL_Base):
|
||||
__tablename__ = 'geoffrey_items'
|
||||
|
||||
id = Column(Integer, primary_key=True, autoincrement=True)
|
||||
name = Column(String(128))
|
||||
price = Column(Integer)
|
||||
amount = Column(Integer)
|
||||
|
||||
shop_id = Column(Integer, ForeignKey('geoffrey_shops.shop_id', ondelete='CASCADE'))
|
||||
shop = relationship("Shop", back_populates="inventory", single_parent=True)
|
||||
|
||||
def __init__(self, name, price, amount, shop):
|
||||
self.name = name
|
||||
self.price = price
|
||||
self.amount = amount
|
||||
self.shop = shop
|
||||
|
||||
@hybrid_property
|
||||
def normalized_price(self):
|
||||
return self.price / self.amount
|
||||
|
||||
@normalized_price.expression
|
||||
def normalized_price(cls):
|
||||
return case([
|
||||
(cls.amount != 0, cls.price / cls.amount),
|
||||
], else_=maxsize)
|
||||
|
||||
def listing_str(self):
|
||||
return '**{}** **{}** for **{}D**'.format(self.amount, self.name, self.price)
|
||||
|
||||
def __str__(self):
|
||||
return self.listing_str()
|
|
@ -1,29 +0,0 @@
|
|||
from itertools import zip_longest
|
||||
|
||||
|
||||
def get_name(args):
|
||||
if len(args) > 0:
|
||||
name = ' '.join(args)
|
||||
else:
|
||||
name = None
|
||||
|
||||
return name
|
||||
|
||||
|
||||
def get_nickname(discord_user, special_users):
|
||||
if discord_user.nick is None:
|
||||
name = discord_user.display_name
|
||||
else:
|
||||
name = discord_user.nick
|
||||
|
||||
if name in special_users:
|
||||
return special_users[name]
|
||||
else:
|
||||
return name
|
||||
|
||||
|
||||
def get_args_dict(args):
|
||||
if len(args) != 0:
|
||||
return dict(zip_longest(*[iter(args)] * 2, fillvalue=" "))
|
||||
else:
|
||||
return {}
|
|
@ -1,12 +0,0 @@
|
|||
""""
|
||||
Geoffrey Minecraft Info Database
|
||||
|
||||
Created by: Joey Hines (ZeroHD)
|
||||
|
||||
"""
|
||||
|
||||
from geoffrey import bot
|
||||
|
||||
if __name__ == '__main__':
|
||||
print("Starting bot...")
|
||||
bot.start_bot()
|
|
@ -1,36 +0,0 @@
|
|||
from simplejson.errors import JSONDecodeError
|
||||
|
||||
import requests
|
||||
|
||||
from geoffrey.BotErrors import UsernameLookupFailed
|
||||
|
||||
uuid_lookup_url = 'https://api.mojang.com/users/profiles/minecraft/{}'
|
||||
username_lookup_url = 'https://api.mojang.com/user/profiles/{}/names'
|
||||
|
||||
|
||||
def grab_json(url):
|
||||
try:
|
||||
json = requests.get(url).json()
|
||||
if 'error' in json:
|
||||
raise UsernameLookupFailed
|
||||
|
||||
except JSONDecodeError:
|
||||
raise UsernameLookupFailed
|
||||
|
||||
return json
|
||||
|
||||
|
||||
def grab_UUID(username):
|
||||
player_data = grab_json(uuid_lookup_url.format(username))
|
||||
return player_data['id']
|
||||
|
||||
|
||||
def grab_playername(uuid):
|
||||
player_data = grab_json(username_lookup_url.format(uuid))
|
||||
|
||||
if len(player_data) == 0:
|
||||
raise UsernameLookupFailed
|
||||
else:
|
||||
last_index = len(player_data) - 1
|
||||
|
||||
return player_data[last_index]['name']
|
|
@ -1 +0,0 @@
|
|||
__version__ = '1.2.0'
|
207
geoffrey/bot.py
207
geoffrey/bot.py
|
@ -1,207 +0,0 @@
|
|||
import asyncio
|
||||
import logging
|
||||
|
||||
from discord import Game
|
||||
from discord.ext import commands
|
||||
from discord.utils import oauth_url
|
||||
from sqlalchemy.exc import OperationalError
|
||||
import logging.handlers as handlers
|
||||
from sys import stdout
|
||||
from os import path
|
||||
|
||||
from geoffrey.BotConfig import *
|
||||
from geoffrey.BotErrors import *
|
||||
from geoffrey.Commands import Commands
|
||||
from geoffrey.DatabaseModels import Player
|
||||
from geoffrey.MinecraftAccountInfoGrabber import *
|
||||
|
||||
logger = logging.getLogger(__name__)
|
||||
|
||||
description = '''
|
||||
Geoffrey (pronounced JOFF-ree) started his life as an inside joke none of you will understand.
|
||||
At some point, she was to become an airhorn bot. Now, they know where your stuff is.
|
||||
|
||||
Please respect Geoffrey, the bot is very sensitive.
|
||||
|
||||
All commands must be prefaced with '?'
|
||||
|
||||
If have a suggestion or if something is borked, you can PM my ding dong of a creator BirbHD.
|
||||
|
||||
*You must use ?register before adding things to Geoffrey*
|
||||
|
||||
For a better a explanation on how this bot works go the following link:
|
||||
https://github.com/joeyahines/Geoffrey/blob/master/README.md
|
||||
|
||||
'''
|
||||
|
||||
bad_error_message = 'OOPSIE WOOPSIE!! Uwu We made a fucky wucky!! A wittle fucko boingo! The admins at our ' \
|
||||
'headquarters are working VEWY HAWD to fix this! (Error in command {})'
|
||||
|
||||
extensions = ['geoffrey.cogs.Add_Commands',
|
||||
'geoffrey.cogs.Delete_Commands',
|
||||
'geoffrey.cogs.Edit_Commands',
|
||||
'geoffrey.cogs.Search_Commands',
|
||||
'geoffrey.cogs.Admin_Commands']
|
||||
|
||||
|
||||
class GeoffreyBot(commands.Bot):
|
||||
def __init__(self, config):
|
||||
super().__init__(command_prefix=config.prefix, description=description, pm_help=True, case_insensitive=True)
|
||||
self.error_users = config.error_users
|
||||
self.admin_users = config.bot_mod
|
||||
self.special_users = config.special_name_list
|
||||
self.bot_commands = Commands(config)
|
||||
self.default_status = config.status
|
||||
|
||||
for extension in extensions:
|
||||
try:
|
||||
self.load_extension(extension)
|
||||
except Exception as e:
|
||||
logger.info('Failed to load extension {}'.format(extension))
|
||||
raise e
|
||||
|
||||
self.loop.create_task(self.username_update())
|
||||
|
||||
async def on_ready(self):
|
||||
logger.info("%s Online, ID: %s", self.user.name, self.user.id)
|
||||
info = await self.application_info()
|
||||
url = oauth_url(info.id)
|
||||
logger.info("Bot url: %s", url)
|
||||
await self.change_presence(activity=Game(self.default_status))
|
||||
|
||||
async def on_command(self, ctx):
|
||||
if ctx.invoked_subcommand is None:
|
||||
subcommand = ""
|
||||
else:
|
||||
subcommand = ":" + ctx.invoked_subcommand.__str__()
|
||||
|
||||
logger.info("User %s, used command %s%s with context: %s", ctx.message.author, ctx.command.name, subcommand,
|
||||
ctx.args)
|
||||
|
||||
if ctx.invoked_with.lower() == 'help' and ctx.message.guild is not None:
|
||||
await ctx.send("{}, I sent you some help in the DMs.".format(ctx.message.author.mention))
|
||||
|
||||
async def on_command_error(self, ctx, error):
|
||||
error_str = ''
|
||||
if hasattr(ctx, 'cog'):
|
||||
if "Admin_Commands" in ctx.cog.__str__():
|
||||
return
|
||||
if hasattr(error, 'original'):
|
||||
if isinstance(error.original, NoPermissionError):
|
||||
error_str = 'You don\'t have permission for that cool command.'
|
||||
elif isinstance(error.original, UsernameLookupFailed):
|
||||
error_str = 'Your user name was not found, either Mojang is having a fucky wucky ' \
|
||||
'or your nickname is not set correctly. *stares at the Mods*'
|
||||
elif isinstance(error.original, PlayerNotFound):
|
||||
error_str = 'Make sure to use ?register first you ding dong.'
|
||||
elif isinstance(error.original, EntryNameNotUniqueError):
|
||||
error_str = 'An entry in the database already has that name you ding dong.'
|
||||
elif isinstance(error.original, DatabaseValueError):
|
||||
error_str = 'Use a shorter name or a smaller value, dong ding.'
|
||||
elif isinstance(error.original, NotOnServerError):
|
||||
error_str = 'Command needs to be run on 24CC. Run this command there whoever you are.'.format()
|
||||
elif isinstance(error.original, OperationalError):
|
||||
await self.send_error_message('Error connecting to the MySQL server, is it offline?')
|
||||
error_str = 'Database connection issue, looks like some admin has to fix something.'.format()
|
||||
elif isinstance(error.original, EmptryString):
|
||||
error_str = 'Do not not pass empty string to Geoffrey. Ding dong.'
|
||||
elif isinstance(error, commands.CommandOnCooldown):
|
||||
return
|
||||
elif isinstance(error, commands.UserInputError):
|
||||
error_str = 'Invalid syntax for **{}** you ding dong:' \
|
||||
.format(ctx.invoked_with, ctx.invoked_with)
|
||||
|
||||
pages = await self.formatter.format_help_for(ctx, ctx.command)
|
||||
for page in pages:
|
||||
error_str = error_str + '\n' + page
|
||||
elif isinstance(error, commands.CommandNotFound):
|
||||
return
|
||||
|
||||
if error_str is '':
|
||||
await self.send_error_message(
|
||||
'Geoffrey encountered unhandled exception: {} Command: **{}** Context: {}'.format(error,
|
||||
ctx.command.name,
|
||||
ctx.args))
|
||||
error_str = bad_error_message.format(ctx.invoked_with)
|
||||
|
||||
logger.error("Geoffrey encountered exception: %s", error)
|
||||
|
||||
await ctx.message.channel.send('{} **Error Running Command:** {}'.format(
|
||||
ctx.message.author.mention, error_str))
|
||||
|
||||
async def send_error_message(self, msg):
|
||||
for user_id in self.error_users:
|
||||
user = await self.get_user_info(user_id)
|
||||
await user.send(msg)
|
||||
|
||||
async def username_update(self):
|
||||
await self.wait_until_ready()
|
||||
|
||||
while not self.is_closed():
|
||||
session = self.bot_commands.interface.database.Session()
|
||||
try:
|
||||
logger.info("Updating MC usernames...")
|
||||
session = self.bot_commands.interface.database.Session()
|
||||
player_list = session.query(Player).all()
|
||||
for player in player_list:
|
||||
player.name = grab_playername(player.mc_uuid)
|
||||
|
||||
session.commit()
|
||||
logger.info("Username update done.")
|
||||
|
||||
except UsernameLookupFailed:
|
||||
logger.info("Username lookup error.")
|
||||
session.rollback()
|
||||
except OperationalError:
|
||||
await self.send_error_message('Error connecting to the MySQL server, is it offline?')
|
||||
logger.info("MySQL connection error")
|
||||
finally:
|
||||
session.close()
|
||||
|
||||
await asyncio.sleep(600)
|
||||
|
||||
|
||||
def setup_logging(config):
|
||||
discord_logger = logging.getLogger('discord')
|
||||
discord_logger.setLevel(logging.INFO)
|
||||
sql_logger = logging.getLogger('sqlalchemy.engine')
|
||||
sql_logger.setLevel(logging.ERROR)
|
||||
bot_info_logger = logging.getLogger('geoffrey.bot')
|
||||
bot_info_logger.setLevel(logging.INFO)
|
||||
log_path = path.abspath(config.log_path)
|
||||
|
||||
handler = handlers.TimedRotatingFileHandler(filename="{}/Geoffrey.log".format(log_path), when='D',
|
||||
interval=config.rotation_duration, backupCount=config.count,
|
||||
encoding='utf-8')
|
||||
|
||||
handler.setFormatter(logging.Formatter('%(asctime)s:%(levelname)s:%(name)s: %(message)s'))
|
||||
|
||||
console = logging.StreamHandler(stdout)
|
||||
|
||||
console.setFormatter(logging.Formatter('%(asctime)s:%(levelname)s:%(name)s: %(message)s'))
|
||||
|
||||
discord_logger.addHandler(handler)
|
||||
sql_logger.addHandler(handler)
|
||||
bot_info_logger.addHandler(handler)
|
||||
bot_info_logger.addHandler(console)
|
||||
|
||||
|
||||
def start_bot(config_path="{}/GeoffreyConfig.ini".format(path.dirname(path.abspath(__file__)))):
|
||||
bot = None
|
||||
try:
|
||||
bot_config = get_config(config_path)
|
||||
|
||||
bot = GeoffreyBot(bot_config)
|
||||
|
||||
setup_logging(bot_config)
|
||||
|
||||
bot.run(bot_config.token)
|
||||
|
||||
except KeyboardInterrupt:
|
||||
logger.info("Bot received keyboard interrupt")
|
||||
except Exception as e:
|
||||
logger.info('Bot encountered the following unhandled exception %s', e)
|
||||
finally:
|
||||
if bot is not None:
|
||||
bot.loop.stop()
|
||||
logger.info("Bot shutting down...")
|
|
@ -1,146 +0,0 @@
|
|||
from discord.ext import commands
|
||||
|
||||
from geoffrey.BotErrors import *
|
||||
from geoffrey.DiscordHelperFunctions import *
|
||||
|
||||
|
||||
@commands.cooldown(5, 60, commands.BucketType.user)
|
||||
class Add_Commands:
|
||||
"""
|
||||
Commands for adding things to Geoffrey.
|
||||
*You must use ?register before using any of these commands!*
|
||||
"""
|
||||
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
|
||||
@commands.command(pass_context=True)
|
||||
@commands.cooldown(5, 60, commands.BucketType.user)
|
||||
async def register(self, ctx):
|
||||
"""
|
||||
Registers your Discord and Minecraft account with the the database
|
||||
You must do this before adding entries to the database.
|
||||
"""
|
||||
|
||||
try:
|
||||
player_name = get_nickname(ctx.message.author, self.bot.special_users)
|
||||
self.bot.bot_commands.register(player_name, ctx.message.author.id)
|
||||
await ctx.send('{}, you have been added to the database. Use ?help to see all the commands this bot can do.'
|
||||
.format(ctx.message.author.mention))
|
||||
except AttributeError:
|
||||
raise NotOnServerError
|
||||
except PlayerInDBError:
|
||||
await ctx.send('{}, you are already in the database. Ding dong.'.format(ctx.message.author.mention))
|
||||
|
||||
@commands.command(pass_context=True)
|
||||
@commands.cooldown(5, 60, commands.BucketType.user)
|
||||
async def add_base(self, ctx, x_pos: int, z_pos: int, *args):
|
||||
"""
|
||||
Adds your base to the database. The base name is optional if this is your first base
|
||||
?add_base [X Coordinate] [Z Coordinate] [Base Name]
|
||||
"""
|
||||
|
||||
name = get_name(args)
|
||||
|
||||
try:
|
||||
base = self.bot.bot_commands.add_base(x_pos, z_pos, base_name=name, discord_uuid=ctx.message.author.id)
|
||||
await ctx.send(
|
||||
'{}, your base has been added to the database: \n\n{}'.format(ctx.message.author.mention, base))
|
||||
except LocationInitError:
|
||||
raise commands.UserInputError
|
||||
except EntryNameNotUniqueError:
|
||||
if name is None:
|
||||
await ctx.send('{}, you already have one base in the database, you need to specify a base'
|
||||
' name'.format(ctx.message.author.mention))
|
||||
else:
|
||||
await ctx.send(
|
||||
'{}, a base called **{}** already exists. You need to specify a different name.'.format(
|
||||
ctx.message.author.mention, name))
|
||||
|
||||
@commands.command(pass_context=True)
|
||||
@commands.cooldown(5, 60, commands.BucketType.user)
|
||||
async def add_shop(self, ctx, x_pos: int, z_pos: int, *args):
|
||||
"""
|
||||
Adds your shop to the database. The name is optional if this is your first shop
|
||||
?add_shop [X Coordinate] [Z Coordinate] [Shop Name]
|
||||
"""
|
||||
|
||||
name = get_name(args)
|
||||
|
||||
try:
|
||||
shop = self.bot.bot_commands.add_shop(x_pos, z_pos, shop_name=name, discord_uuid=ctx.message.author.id)
|
||||
await ctx.send(
|
||||
'{}, your shop has been added to the database: \n\n{}'.format(ctx.message.author.mention, shop))
|
||||
except LocationInitError:
|
||||
raise commands.UserInputError
|
||||
except EntryNameNotUniqueError:
|
||||
if name is None:
|
||||
await ctx.send(
|
||||
'{}, you already have one shop in the database, you need to specify a shop name'.format(
|
||||
ctx.message.author.mention))
|
||||
else:
|
||||
await ctx.send(
|
||||
'{}, a shop called **{}** already exists. You need to specify a different name.'.format(
|
||||
ctx.message.author.mention, name))
|
||||
|
||||
@commands.command(pass_context=True)
|
||||
@commands.cooldown(5, 60, commands.BucketType.user)
|
||||
async def add_tunnel(self, ctx, tunnel_direction: str, tunnel_number: int, *args):
|
||||
"""
|
||||
Adds your tunnel to the database. If you only have one location, you do not need to specify a location name
|
||||
|
||||
Directions: North South East West
|
||||
?tunnel [Tunnel Direction] [Tunnel Number] [Location Name]
|
||||
"""
|
||||
|
||||
loc_name = get_name(args)
|
||||
try:
|
||||
self.bot.bot_commands.add_tunnel(tunnel_direction, tunnel_number, discord_uuid=ctx.message.author.id,
|
||||
location_name=loc_name)
|
||||
await ctx.send('{}, your tunnel has been added to the database'.format(ctx.message.author.mention))
|
||||
except LocationLookUpError:
|
||||
await ctx.send('{}, you do not have a location called **{}**.'.format(
|
||||
ctx.message.author.mention, loc_name))
|
||||
except NoLocationsInDatabase:
|
||||
await ctx.send('{}, you do not have a location in the database.'.format(
|
||||
ctx.message.author.mention, loc_name))
|
||||
except LocationHasTunnelError:
|
||||
await ctx.send('{}, **{}** already has a tunnel.'.format(ctx.message.author.mention, loc_name))
|
||||
except TunnelInitError:
|
||||
await ctx.send('{}, invalid tunnel direction.'.format(ctx.message.author.mention))
|
||||
except EntryNameNotUniqueError:
|
||||
await ctx.send('{}, you have more than one location, you need to specify a location.'
|
||||
.format(ctx.message.author.mention))
|
||||
except InvalidTunnelError:
|
||||
await ctx.send(
|
||||
'{}, **{}** is an invalid tunnel direction.'.format(ctx.message.author.mention, tunnel_direction))
|
||||
|
||||
@commands.command(pass_context=True)
|
||||
@commands.cooldown(5, 60, commands.BucketType.user)
|
||||
async def add_item(self, ctx, item_name: str, quantity: int, diamond_price: int, *args):
|
||||
"""
|
||||
Adds an item to a shop's inventory. If you have one shop, the shop name is not required
|
||||
|
||||
Quantity for Diamond Price. eg. 32 Dirt for 1D. If the item name has spaces in wrap in in quotes eg "Silk Touch"
|
||||
?add_item [Item Name] [Quantity] [Price] [Shop name]
|
||||
"""
|
||||
shop_name = get_name(args)
|
||||
try:
|
||||
self.bot.bot_commands.add_item(item_name, quantity, diamond_price, shop_name=shop_name,
|
||||
discord_uuid=ctx.message.author.id)
|
||||
await ctx.send(
|
||||
'{}, **{}** has been added to the inventory of your shop.'.format(ctx.message.author.mention,
|
||||
item_name))
|
||||
except NoLocationsInDatabase:
|
||||
await ctx.send('{}, you don\'t have any shops in the database.'.format(ctx.message.author.mention))
|
||||
except EntryNameNotUniqueError:
|
||||
await ctx.send('{}, you have more than one shop in the database, please specify a shop name.'
|
||||
.format(ctx.message.author.mention))
|
||||
except LocationLookUpError:
|
||||
await ctx.send(
|
||||
'{}, you don\'t have any shops named **{}** in the database.'.format(ctx.message.author.mention,
|
||||
shop_name))
|
||||
|
||||
|
||||
def setup(bot):
|
||||
bot.add_cog(Add_Commands(bot))
|
|
@ -1,166 +0,0 @@
|
|||
from discord import Game
|
||||
from discord.ext import commands
|
||||
|
||||
from geoffrey.BotErrors import *
|
||||
from geoffrey.DiscordHelperFunctions import get_name
|
||||
|
||||
|
||||
def check_mod(user, admin_users):
|
||||
try:
|
||||
for role in user.roles:
|
||||
if str(role.id) in admin_users:
|
||||
return True
|
||||
except AttributeError:
|
||||
raise NotOnServerError
|
||||
|
||||
return False
|
||||
|
||||
|
||||
class Admin_Commands:
|
||||
"""
|
||||
Commands for cool people only.
|
||||
"""
|
||||
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
|
||||
async def error(self, ctx, error):
|
||||
error_str = ""
|
||||
|
||||
if hasattr(error, "original"):
|
||||
if isinstance(error.original, PlayerNotFound):
|
||||
error_str = 'that player is not in the database.'
|
||||
elif isinstance(error.original, DeleteEntryError) or isinstance(error.original, LocationLookUpError):
|
||||
error_str = 'that player does not have a location by that name.'
|
||||
|
||||
if error_str is "":
|
||||
error_str = 'the bot encountered the following error: {}'.format(error.__str__())
|
||||
|
||||
await ctx.send('{}, {}'.format(ctx.message.author.mention, error_str))
|
||||
|
||||
@commands.command(pass_context=True)
|
||||
async def test(self, ctx):
|
||||
"""
|
||||
Checks if the bot is alive.
|
||||
"""
|
||||
if check_mod(ctx.message.author, self.bot.admin_users):
|
||||
await ctx.send('I\'m here you ding dong')
|
||||
else:
|
||||
raise NoPermissionError
|
||||
|
||||
@commands.group(pass_context=True)
|
||||
async def mod(self, ctx):
|
||||
"""
|
||||
Bot moderation tools.
|
||||
"""
|
||||
if check_mod(ctx.message.author, self.bot.admin_users):
|
||||
if ctx.invoked_subcommand is None:
|
||||
await ctx.send('{}, invalid sub-command for command **mod**.'.format(ctx.message.author.mention))
|
||||
else:
|
||||
raise NoPermissionError
|
||||
|
||||
@mod.command(pass_context=True)
|
||||
async def delete(self, ctx, discord_uuid: str, location_name: str):
|
||||
"""
|
||||
Deletes a location in the database.
|
||||
"""
|
||||
self.bot.bot_commands.delete(location_name, discord_uuid=discord_uuid)
|
||||
await ctx.send('{}, **{}** has been deleted.'.format(ctx.message.author.mention, location_name))
|
||||
|
||||
@delete.error
|
||||
async def delete_error(self, ctx, error):
|
||||
await self.error(ctx, error)
|
||||
|
||||
@mod.command(pass_context=True)
|
||||
async def edit_name(self, ctx, discord_uuid: str, new_name: str, current_name: str):
|
||||
"""
|
||||
Edits the name of a location in the database.
|
||||
"""
|
||||
self.bot.bot_commands.edit_name(new_name, current_name, discord_uuid=discord_uuid)
|
||||
await ctx.send('{}, **{}** has been rename to **{}**.'.format(ctx.message.author.mention, current_name,
|
||||
new_name))
|
||||
|
||||
@edit_name.error
|
||||
async def edit_error(self, ctx, error):
|
||||
await self.error(ctx, error)
|
||||
|
||||
@mod.command(pass_context=True)
|
||||
async def update_mc_uuid(self, ctx, discord_uuid: str, mc_uuid: str):
|
||||
"""
|
||||
Updates a user's MC UUID
|
||||
"""
|
||||
self.bot.bot_commands.update_mc_uuid(discord_uuid, mc_uuid)
|
||||
await ctx.send('{}, **{}** has been updated.'.format(ctx.message.author.mention, discord_uuid))
|
||||
|
||||
@update_mc_uuid.error
|
||||
async def update_mc_uuid_error(self, ctx, error):
|
||||
await self.error(ctx, error)
|
||||
|
||||
@mod.command(pass_context=True)
|
||||
async def update_discord_uuid(self, ctx, new_discord_uuid: str, current_discord_uuid: str):
|
||||
"""
|
||||
Updates a user's Discord UUID
|
||||
"""
|
||||
self.bot.bot_commands.update_mc_uuid(current_discord_uuid, new_discord_uuid)
|
||||
await ctx.send('{}, user **{}** has been updated.'.format(ctx.message.author.mention, current_discord_uuid))
|
||||
|
||||
@update_discord_uuid.error
|
||||
async def update_discord_uuid_error(self, ctx, error):
|
||||
await self.error(ctx, error)
|
||||
|
||||
@mod.command(pass_context=True)
|
||||
async def update_mc_name(self, ctx, discord_uuid: str):
|
||||
"""
|
||||
Updates a user's MC name to the current name on the MC UUID
|
||||
"""
|
||||
self.bot.bot_commands.update_mc_name(discord_uuid)
|
||||
await ctx.send('{}, user **{}**\'s MC name has update.'.format(ctx.message.author.mention, discord_uuid))
|
||||
|
||||
@update_mc_name.error
|
||||
async def update_mc_name_error(self, ctx, error):
|
||||
await self.error(ctx, error)
|
||||
|
||||
@mod.command(pass_context=True)
|
||||
async def status(self, ctx, *args):
|
||||
"""
|
||||
Updates "playing [game]" status of the bot
|
||||
"""
|
||||
status = get_name(args)
|
||||
await self.bot.change_presence(activity=Game(status))
|
||||
await ctx.send('{}, status has been changed'.format(ctx.message.author.mention))
|
||||
|
||||
@mod.command(pass_context=True)
|
||||
async def add_player(self, ctx, discord_uuid: str, mc_name: str):
|
||||
"""
|
||||
Manually add a player to the database
|
||||
"""
|
||||
try:
|
||||
db_id = self.bot.bot_commands.add_player(discord_uuid, mc_name)
|
||||
await ctx.send('{}, user **{}** been added to the data base with id {}.'.format(ctx.message.author.mention,
|
||||
mc_name, db_id))
|
||||
except PlayerInDBError:
|
||||
await ctx.send('{}, user **{}** is already in the database.'.format(ctx.message.author.mention, mc_name))
|
||||
|
||||
@add_player.error
|
||||
async def add_player_error(self, ctx, error):
|
||||
await self.error(ctx, error)
|
||||
|
||||
@mod.command(pass_context=True)
|
||||
async def find_player(self, ctx, discord_uuid: str):
|
||||
"""
|
||||
Finds a player in the database
|
||||
"""
|
||||
try:
|
||||
db_id, username, discord_uuid, minecraft_uuid = self.bot.bot_commands.find_player(discord_uuid)
|
||||
await ctx.send('Username: {}, id: {}, Discord UUID: {}, Minecraft UUID: {}'
|
||||
.format(username, db_id, discord_uuid, minecraft_uuid))
|
||||
except PlayerNotFound:
|
||||
await ctx.send('That player is not in the database...')
|
||||
|
||||
@find_player.error
|
||||
async def find_player_error(self, ctx, error):
|
||||
await self.error(ctx, error)
|
||||
|
||||
|
||||
def setup(bot):
|
||||
bot.add_cog(Admin_Commands(bot))
|
|
@ -1,65 +0,0 @@
|
|||
from discord.ext import commands
|
||||
|
||||
from geoffrey.BotErrors import *
|
||||
from geoffrey.DiscordHelperFunctions import *
|
||||
|
||||
|
||||
class Delete_Commands:
|
||||
"""
|
||||
Commands to help Geoffrey forget.
|
||||
|
||||
*You must use ?register before using any of these commands!*
|
||||
"""
|
||||
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
|
||||
@commands.command(pass_context=True)
|
||||
async def delete(self, ctx, *args):
|
||||
"""
|
||||
Deletes a location from the database
|
||||
|
||||
?delete [Location name]
|
||||
"""
|
||||
loc = get_name(args)
|
||||
try:
|
||||
if loc is None:
|
||||
raise commands.UserInputError
|
||||
|
||||
self.bot.bot_commands.delete(loc, discord_uuid=ctx.message.author.id)
|
||||
await ctx.send(
|
||||
'{}, your location named **{}** has been deleted.'.format(ctx.message.author.mention, loc))
|
||||
except (DeleteEntryError, PlayerNotFound):
|
||||
await ctx.send('{}, you do not have a location named **{}**.'.format(ctx.message.author.mention, loc))
|
||||
|
||||
@commands.command(pass_context=True)
|
||||
async def delete_item(self, ctx, item: str, *args):
|
||||
"""
|
||||
Deletes an item listing from a shop inventory
|
||||
|
||||
The item name must be wrapped in quotes if it has a space in it
|
||||
?delete_name [Item] [Shop Name]
|
||||
"""
|
||||
|
||||
shop = get_name(args)
|
||||
try:
|
||||
shop_name = self.bot.bot_commands.delete_item(item, shop, discord_uuid=ctx.message.author.id)
|
||||
|
||||
await ctx.send('{}, **{}** has been removed from the inventory of **{}**.'.
|
||||
format(ctx.message.author.mention, item, shop_name))
|
||||
except LocationLookUpError:
|
||||
await ctx.send('{}, you do not have a shop called **{}**.'.format(ctx.message.author.mention, shop))
|
||||
except NoLocationsInDatabase:
|
||||
await ctx.send('{}, you do have any shops in the database.'.format(ctx.message.author.mention))
|
||||
except EntryNameNotUniqueError:
|
||||
await ctx.send('{}, you have more than one shop in the database, please specify a shop name.'
|
||||
.format(ctx.message.author.mention))
|
||||
except DeleteEntryError:
|
||||
if shop is not None:
|
||||
await ctx.send('{}, **{}** does not sell **{}**.'.format(ctx.message.author.mention, shop, item))
|
||||
else:
|
||||
await ctx.send('{}, your shop does not sell **{}**.'.format(ctx.message.author.mention, item))
|
||||
|
||||
|
||||
def setup(bot):
|
||||
bot.add_cog(Delete_Commands(bot))
|
|
@ -1,76 +0,0 @@
|
|||
from discord.ext import commands
|
||||
|
||||
from geoffrey.BotErrors import *
|
||||
from geoffrey.DiscordHelperFunctions import *
|
||||
|
||||
|
||||
class Edit_Commands:
|
||||
"""
|
||||
Commands for editing your stuff in Geoffrey.
|
||||
"""
|
||||
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
|
||||
@commands.command(pass_context=True)
|
||||
@commands.cooldown(5, 60, commands.BucketType.user)
|
||||
async def edit_pos(self, ctx, x_pos: int, z_pos: int, *args):
|
||||
"""
|
||||
Edits the position of a location
|
||||
|
||||
?edit_pos [X Coordinate] [Z Coordinate] [Location Name]
|
||||
"""
|
||||
loc = get_name(args)
|
||||
try:
|
||||
loc_str = self.bot.bot_commands.edit_pos(x_pos, z_pos, loc, discord_uuid=ctx.message.author.id)
|
||||
|
||||
await ctx.send(
|
||||
'{}, the following location has been updated: \n\n{}'.format(ctx.message.author.mention, loc_str))
|
||||
except LocationLookUpError:
|
||||
await ctx.send('{}, you do not have a location called **{}**.'.format(
|
||||
ctx.message.author.mention, loc))
|
||||
|
||||
@commands.command(pass_context=True)
|
||||
@commands.cooldown(5, 60, commands.BucketType.user)
|
||||
async def edit_tunnel(self, ctx, tunnel_direction: str, tunnel_number: int, *args):
|
||||
"""
|
||||
Edits the tunnel of a location
|
||||
|
||||
Directions: North South East West
|
||||
?edit_tunnel [Tunnel Direction] [Tunnel Number] [Location Name]
|
||||
"""
|
||||
loc = get_name(args)
|
||||
try:
|
||||
loc_str = self.bot.bot_commands.edit_tunnel(tunnel_direction, tunnel_number, loc,
|
||||
discord_uuid=ctx.message.author.id)
|
||||
|
||||
await ctx.send(
|
||||
'{}, the following location has been updated: \n\n{}'.format(ctx.message.author.mention, loc_str))
|
||||
except LocationLookUpError:
|
||||
await ctx.send('{}, you do not have a location called **{}**.'.format(
|
||||
ctx.message.author.mention, loc))
|
||||
except InvalidTunnelError:
|
||||
await ctx.send(
|
||||
'{}, **{}** is an invalid tunnel direction.'.format(ctx.message.author.mention, tunnel_direction))
|
||||
|
||||
@commands.command(pass_context=True)
|
||||
@commands.cooldown(5, 60, commands.BucketType.user)
|
||||
async def edit_name(self, ctx, new_name: str, current_name: str):
|
||||
"""
|
||||
Edits the name of a location
|
||||
|
||||
IF A NAME HAS SPACES IN IT YOU NEED TO WRAP IT IN QUOTATION MARKS. eg. "Cool Shop 123"
|
||||
?edit_name [New Name] [Current Name]
|
||||
"""
|
||||
try:
|
||||
loc_str = self.bot.bot_commands.edit_name(new_name, current_name, discord_uuid=ctx.message.author.id)
|
||||
|
||||
await ctx.send(
|
||||
'{}, the following location has been updated: \n\n{}'.format(ctx.message.author.mention, loc_str))
|
||||
except LocationLookUpError:
|
||||
await ctx.send('{}, you do not have a location called **{}**.'.format(
|
||||
ctx.message.author.mention, current_name))
|
||||
|
||||
|
||||
def setup(bot):
|
||||
bot.add_cog(Edit_Commands(bot))
|
|
@ -1,139 +0,0 @@
|
|||
from discord.ext import commands
|
||||
|
||||
from geoffrey.BotErrors import *
|
||||
from geoffrey.DiscordHelperFunctions import *
|
||||
|
||||
|
||||
class Search_Commands:
|
||||
"""
|
||||
Commands to find stuff.
|
||||
"""
|
||||
|
||||
def __init__(self, bot):
|
||||
self.bot = bot
|
||||
|
||||
@commands.command(pass_context=True)
|
||||
@commands.cooldown(5, 60, commands.BucketType.user)
|
||||
async def find(self, ctx, *args):
|
||||
"""
|
||||
Finds all the locations matching the search term
|
||||
?find [Search]
|
||||
"""
|
||||
search = get_name(args)
|
||||
try:
|
||||
|
||||
if search is None:
|
||||
raise commands.UserInputError
|
||||
|
||||
result = self.bot.bot_commands.find(search)
|
||||
|
||||
await ctx.send(
|
||||
'{}, The following entries match **{}**:\n{}'.format(ctx.message.author.mention, search, result))
|
||||
except LocationLookUpError:
|
||||
await ctx.send(
|
||||
'{}, no matches to **{}** were found in the database.'.format(ctx.message.author.mention, search))
|
||||
|
||||
@commands.command(pass_context=True)
|
||||
@commands.cooldown(5, 60, commands.BucketType.user)
|
||||
async def tunnel(self, ctx, player: str):
|
||||
"""
|
||||
Finds all the tunnels a player owns
|
||||
?tunnel [Player]
|
||||
"""
|
||||
try:
|
||||
result = self.bot.bot_commands.tunnel(player)
|
||||
|
||||
await ctx.send(
|
||||
'{}, **{}** owns the following tunnel(s): \n{}'.format(ctx.message.author.mention, player, result))
|
||||
except LocationLookUpError:
|
||||
await ctx.send('{}, no tunnels for **{}** were found in the database.'
|
||||
.format(ctx.message.author.mention, player))
|
||||
|
||||
@commands.command(pass_context=True)
|
||||
@commands.cooldown(5, 60, commands.BucketType.user)
|
||||
async def find_around(self, ctx, x_pos: int, z_pos: int, *args):
|
||||
"""
|
||||
Finds all the locations around a certain point.
|
||||
The radius defaults to 200 blocks if no value is given
|
||||
|
||||
Default dimension is the overworld
|
||||
?find_around [X Coordinate] [Z Coordinate] [Radius]
|
||||
"""
|
||||
radius = 200
|
||||
dimension = 'Overworld'
|
||||
|
||||
try:
|
||||
if len(args) > 0:
|
||||
radius = int(args[0])
|
||||
|
||||
base_string = self.bot.bot_commands.find_around(x_pos, z_pos, radius, dimension)
|
||||
|
||||
if len(base_string) != 0:
|
||||
await ctx.send('{}, the following locations(s) are within **{}** blocks of that point: \n {}'.format(
|
||||
ctx.message.author.mention, radius, base_string))
|
||||
else:
|
||||
await ctx.send('{}, there are no locations within {} blocks of that point'
|
||||
.format(ctx.message.author.mention, radius))
|
||||
except ValueError:
|
||||
await ctx.send(
|
||||
'{}, invalid radius, the radius must be a whole number.'.format(ctx.message.author.mention,
|
||||
radius))
|
||||
except InvalidDimError:
|
||||
await ctx.send('{}, {} is an invalid dimension.'.format(ctx.message.author.mention, dimension))
|
||||
|
||||
@commands.command(pass_context=True)
|
||||
@commands.cooldown(5, 60, commands.BucketType.user)
|
||||
async def selling(self, ctx, *args):
|
||||
"""
|
||||
Lists all the shops selling an item
|
||||
|
||||
?selling [item]
|
||||
"""
|
||||
item_name = get_name(args)
|
||||
|
||||
if item_name is None:
|
||||
raise commands.UserInputError
|
||||
try:
|
||||
|
||||
result = self.bot.bot_commands.selling(item_name)
|
||||
await ctx.send(
|
||||
'{}, the following shop(s) sell **{}**: \n{}'.format(ctx.message.author.mention, item_name, result))
|
||||
except ItemNotFound:
|
||||
await ctx.send('{}, no shop sells **{}**.'.format(ctx.message.author.mention, item_name))
|
||||
|
||||
@commands.command(pass_context=True)
|
||||
@commands.cooldown(5, 60, commands.BucketType.user)
|
||||
async def info(self, ctx, *args):
|
||||
"""
|
||||
Displays info about a location.
|
||||
|
||||
If the location is a shop, it displays the shop's inventory
|
||||
?info [Location Name]
|
||||
"""
|
||||
loc = get_name(args)
|
||||
try:
|
||||
|
||||
if loc is None:
|
||||
raise commands.UserInputError
|
||||
|
||||
info_str = self.bot.bot_commands.info(loc)
|
||||
await ctx.send(info_str)
|
||||
except LocationLookUpError:
|
||||
await ctx.send('{}, no locations in the database match **{}**.'.format(ctx.message.author.mention, loc))
|
||||
|
||||
@commands.command(pass_context=True)
|
||||
@commands.cooldown(5, 60, commands.BucketType.user)
|
||||
async def me(self, ctx):
|
||||
"""
|
||||
Displays all your locations in the database
|
||||
"""
|
||||
try:
|
||||
loc_str = self.bot.bot_commands.me(discord_uuid=ctx.message.author.id)
|
||||
await ctx.send('{}, here are your location(s) in the database: \n {}'.format(ctx.message.author.mention,
|
||||
loc_str))
|
||||
except PlayerNotFound:
|
||||
await ctx.send('{}, you don\'t have any locations in the database.'.format(ctx.message.author.mention))
|
||||
|
||||
|
||||
def setup(bot):
|
||||
bot.add_cog(Search_Commands(bot))
|
|
@ -1 +0,0 @@
|
|||
|
|
@ -1,348 +0,0 @@
|
|||
import os
|
||||
from unittest import TestCase
|
||||
|
||||
from geoffrey.Commands import *
|
||||
from geoffrey.BotConfig import get_config
|
||||
|
||||
zerohd = 'zerohd'
|
||||
|
||||
class TestCommands(TestCase):
|
||||
def setUp(self):
|
||||
path = os.path.dirname(os.path.abspath(__file__))
|
||||
self.bot_config = get_config('{}/GeoffreyConfig.ini'.format(path))
|
||||
self.commands = Commands(self.bot_config, True)
|
||||
self.session = self.commands.interface.database.Session()
|
||||
self.commands.interface.database.clear_all(self.session)
|
||||
self.session.close()
|
||||
|
||||
def test_get_player(self):
|
||||
session = self.commands.interface.database.Session()
|
||||
self.commands.interface.add_player(session, zerohd, discord_uuid='143072699567177728')
|
||||
|
||||
player = self.commands.get_player(session, discord_uuid='143072699567177728')
|
||||
|
||||
self.assertEqual(player.name, zerohd)
|
||||
|
||||
self.assertRaises(AttributeError, self.commands.get_player, session)
|
||||
session.close()
|
||||
|
||||
def test_get_location(self):
|
||||
session = self.commands.interface.database.Session()
|
||||
self.commands.interface.add_player(session, zerohd, discord_uuid='143072699567177728')
|
||||
session.close()
|
||||
|
||||
session = self.commands.interface.database.Session()
|
||||
|
||||
player = self.commands.get_player(session, discord_uuid='143072699567177728')
|
||||
|
||||
self.assertRaises(NoLocationsInDatabase, self.commands.get_location,
|
||||
session, player, name=None, loc_type=Location)
|
||||
|
||||
session.close()
|
||||
|
||||
self.commands.add_base(0, 0, discord_uuid='143072699567177728')
|
||||
session = self.commands.interface.database.Session()
|
||||
|
||||
self.commands.get_location(session, player, name=None, loc_type=Location)
|
||||
|
||||
session.close()
|
||||
|
||||
self.commands.add_base(0, 0, base_name='Birb', discord_uuid='143072699567177728')
|
||||
|
||||
session = self.commands.interface.database.Session()
|
||||
|
||||
self.assertRaises(EntryNameNotUniqueError, self.commands.get_location,
|
||||
session, player, name=None, loc_type=Location)
|
||||
|
||||
self.commands.get_location(session, player, name="Birb", loc_type=Location)
|
||||
|
||||
self.assertRaises(LocationLookUpError, self.commands.get_location,
|
||||
session, player, name="Henlo", loc_type=Location)
|
||||
|
||||
session.close()
|
||||
|
||||
|
||||
def test_register(self):
|
||||
self.commands.register(zerohd, '143072699567177728')
|
||||
|
||||
player = self.commands.get_player(self.session, discord_uuid='143072699567177728')
|
||||
|
||||
self.assertEqual(player.name, zerohd)
|
||||
|
||||
def test_addbase(self):
|
||||
player_name = self.commands.register(zerohd, '143072699567177728')
|
||||
base = self.commands.add_base(0, 0, discord_uuid='143072699567177728')
|
||||
|
||||
self.assertRaises(EntryNameNotUniqueError, self.commands.add_base, 0, 0, discord_uuid='143072699567177728')
|
||||
|
||||
if player_name not in base:
|
||||
self.fail()
|
||||
else:
|
||||
pass
|
||||
|
||||
def test_addshop(self):
|
||||
player_name = self.commands.register(zerohd, '143072699567177728')
|
||||
shop = self.commands.add_shop(0, 0, discord_uuid='143072699567177728')
|
||||
|
||||
self.assertRaises(EntryNameNotUniqueError, self.commands.add_shop, 0, 0, discord_uuid='143072699567177728')
|
||||
|
||||
if player_name not in shop:
|
||||
self.fail()
|
||||
else:
|
||||
pass
|
||||
|
||||
def test_addtunnel(self):
|
||||
self.commands.register(zerohd, '143072699567177728')
|
||||
self.commands.add_shop(0, 0, shop_name='test shop', discord_uuid='143072699567177728')
|
||||
self.commands.add_shop(0, 0, shop_name='test shop2', discord_uuid='143072699567177728')
|
||||
|
||||
tunnel2 = self.commands.add_tunnel("East", 50, location_name='test_shop',
|
||||
discord_uuid='143072699567177728')
|
||||
|
||||
if "East" not in tunnel2:
|
||||
self.fail()
|
||||
|
||||
self.assertRaises(LocationHasTunnelError, self.commands.add_tunnel, "East", 50,
|
||||
location_name='test_shop', discord_uuid='143072699567177728')
|
||||
|
||||
self.assertRaises(EntryNameNotUniqueError, self.commands.add_tunnel, "East", 50,
|
||||
discord_uuid='143072699567177728')
|
||||
|
||||
def test_find(self):
|
||||
self.commands.register(zerohd, '143072699567177728')
|
||||
self.commands.add_shop(0, 0, shop_name='frick', discord_uuid='143072699567177728')
|
||||
self.commands.add_base(0, 0, 'heck', discord_uuid='143072699567177728')
|
||||
|
||||
result = self.commands.find(zerohd)
|
||||
|
||||
if ('frick' in result) & ('heck' in result):
|
||||
pass
|
||||
else:
|
||||
self.fail()
|
||||
|
||||
def test_delete(self):
|
||||
self.commands.register(zerohd, '143072699567177728')
|
||||
self.commands.add_shop(0, 0, shop_name='frick', discord_uuid='143072699567177728')
|
||||
|
||||
self.commands.delete('frick', discord_uuid='143072699567177728')
|
||||
|
||||
self.assertRaises(LocationLookUpError, self.commands.find, zerohd)
|
||||
|
||||
def test_findaround(self):
|
||||
self.commands.register(zerohd, '143072699567177728')
|
||||
self.commands.add_shop(0, 0, shop_name='frick', discord_uuid='143072699567177728')
|
||||
|
||||
result = self.commands.find_around(0, 0)
|
||||
|
||||
if 'frick' in result:
|
||||
pass
|
||||
else:
|
||||
self.fail()
|
||||
|
||||
def test_additem(self):
|
||||
self.commands.register(zerohd, '143072699567177728')
|
||||
self.assertRaises(NoLocationsInDatabase, self.commands.add_item, 'dirt', 5, 5
|
||||
, discord_uuid='143072699567177728')
|
||||
|
||||
self.commands.add_shop(0, 0, discord_uuid='143072699567177728')
|
||||
|
||||
result = self.commands.add_item('dirt', 5, 5, None, discord_uuid='143072699567177728')
|
||||
|
||||
if 'dirt' in result:
|
||||
pass
|
||||
else:
|
||||
self.fail()
|
||||
|
||||
self.commands.add_shop(0, 0, shop_name='frick', discord_uuid='143072699567177728')
|
||||
|
||||
result = self.commands.add_item('cool', 5, 5, shop_name='frick', discord_uuid='143072699567177728')
|
||||
|
||||
if 'cool' in result:
|
||||
pass
|
||||
else:
|
||||
self.fail()
|
||||
|
||||
def test_selling(self):
|
||||
self.commands.register(zerohd, '143072699567177728')
|
||||
self.commands.add_shop(0, 0, shop_name='frick', discord_uuid='143072699567177728')
|
||||
|
||||
self.commands.add_item('cool', 5, 5, shop_name='frick', discord_uuid='143072699567177728')
|
||||
|
||||
result = self.commands.selling('cool')
|
||||
|
||||
if 'cool' in result:
|
||||
pass
|
||||
else:
|
||||
self.fail()
|
||||
|
||||
def test_info(self):
|
||||
self.commands.register(zerohd, '143072699567177728')
|
||||
self.commands.add_shop(0, 0, shop_name='frick', discord_uuid='143072699567177728')
|
||||
|
||||
self.commands.add_tunnel("West", 50, location_name='frick', discord_uuid='143072699567177728')
|
||||
|
||||
result = self.commands.info('frick')
|
||||
|
||||
if "West" in result:
|
||||
pass
|
||||
else:
|
||||
self.fail()
|
||||
|
||||
def test_add_tunnel(self):
|
||||
self.commands.register(zerohd, '143072699567177728')
|
||||
|
||||
self.assertRaises(NoLocationsInDatabase, self.commands.add_tunnel, "soUTH", 50, None,
|
||||
discord_uuid='143072699567177728')
|
||||
|
||||
self.commands.add_shop(0, 0, shop_name='test shop', discord_uuid='143072699567177728')
|
||||
|
||||
self.commands.add_tunnel("soUTH", 50, None, discord_uuid='143072699567177728')
|
||||
|
||||
result = self.commands.tunnel(zerohd)
|
||||
|
||||
if "South" in result:
|
||||
pass
|
||||
else:
|
||||
self.fail()
|
||||
|
||||
def test_tunnel(self):
|
||||
self.commands.register(zerohd, '143072699567177728')
|
||||
self.commands.add_shop(0, 0, shop_name='test shop', discord_uuid='143072699567177728')
|
||||
|
||||
self.assertRaises(LocationLookUpError, self.commands.tunnel, zerohd)
|
||||
|
||||
result = self.commands.add_tunnel("WEST", 50, None, discord_uuid='143072699567177728')
|
||||
|
||||
if "West" in result:
|
||||
pass
|
||||
else:
|
||||
self.fail()
|
||||
|
||||
def test_edit_name(self):
|
||||
self.commands.register(zerohd, '143072699567177728')
|
||||
self.commands.add_shop(0, 0, shop_name='test shop', discord_uuid='143072699567177728')
|
||||
|
||||
self.commands.edit_name('cool shop', 'test shop', discord_uuid='143072699567177728')
|
||||
|
||||
result = self.commands.info('cool shop')
|
||||
|
||||
if 'cool' in result:
|
||||
pass
|
||||
else:
|
||||
self.fail()
|
||||
|
||||
def test_edit_pos(self):
|
||||
self.commands.register(zerohd, '143072699567177728')
|
||||
self.commands.add_shop(0, 0, shop_name='test shop', discord_uuid='143072699567177728')
|
||||
|
||||
self.commands.edit_pos(500, 500, 'test shop', discord_uuid='143072699567177728')
|
||||
|
||||
result = self.commands.info('test shop')
|
||||
|
||||
if '500' in result:
|
||||
pass
|
||||
else:
|
||||
self.fail()
|
||||
|
||||
self.commands.edit_pos(500, 500, None, discord_uuid='143072699567177728')
|
||||
|
||||
if '500' in result:
|
||||
pass
|
||||
else:
|
||||
self.fail()
|
||||
|
||||
self.assertRaises(DatabaseValueError, self.commands.edit_pos, 9999999999999999999999999999999999999999999999999,
|
||||
5, None, discord_uuid='143072699567177728')
|
||||
|
||||
self.assertRaises(LocationLookUpError, self.commands.edit_pos, 5, 5, 'henlo',
|
||||
discord_uuid='143072699567177728')
|
||||
|
||||
self.commands.delete(name='test shop', discord_uuid='143072699567177728')
|
||||
|
||||
self.assertRaises(NoLocationsInDatabase, self.commands.edit_pos, 5, 5, None,
|
||||
discord_uuid='143072699567177728')
|
||||
|
||||
def test_edit_tunnel(self):
|
||||
self.commands.register(zerohd, '143072699567177728')
|
||||
self.commands.add_shop(0, 0, shop_name='test shop', discord_uuid='143072699567177728')
|
||||
|
||||
self.commands.edit_tunnel("West", 500, 'test shop', discord_uuid='143072699567177728')
|
||||
|
||||
result = self.commands.info('test shop')
|
||||
|
||||
if "West" in result:
|
||||
pass
|
||||
else:
|
||||
self.fail()
|
||||
|
||||
self.commands.edit_tunnel("East", 500, 'test shop', discord_uuid='143072699567177728')
|
||||
|
||||
result = self.commands.info('test shop')
|
||||
|
||||
if "East" in result:
|
||||
pass
|
||||
else:
|
||||
self.fail()
|
||||
|
||||
def test_delete_item(self):
|
||||
self.commands.register(zerohd, '143072699567177728')
|
||||
self.commands.add_shop(0, 0, shop_name='test shop', discord_uuid='143072699567177728')
|
||||
|
||||
self.commands.add_item('dirt', 5, 5, shop_name='test shop', discord_uuid='143072699567177728')
|
||||
self.commands.add_item('wood', 5, 5, shop_name='test shop', discord_uuid='143072699567177728')
|
||||
|
||||
self.commands.delete_item('dirt', None, discord_uuid='143072699567177728')
|
||||
|
||||
self.assertRaises(ItemNotFound, self.commands.selling, 'dirt')
|
||||
|
||||
self.commands.add_shop(0, 0, shop_name='test shop2', discord_uuid='143072699567177728')
|
||||
self.assertRaises(EntryNameNotUniqueError, self.commands.delete_item, 'wood', None,
|
||||
discord_uuid='143072699567177728')
|
||||
|
||||
self.commands.delete('test shop', discord_uuid='143072699567177728')
|
||||
self.commands.delete('test shop2', discord_uuid='143072699567177728')
|
||||
|
||||
self.assertRaises(NoLocationsInDatabase, self.commands.delete_item, 'wood', None,
|
||||
discord_uuid='143072699567177728')
|
||||
|
||||
def test_me(self):
|
||||
self.commands.register(zerohd, '143072699567177728')
|
||||
self.commands.add_shop(0, 0, shop_name='test shop', discord_uuid='143072699567177728')
|
||||
|
||||
result = self.commands.me(discord_uuid='143072699567177728')
|
||||
|
||||
if 'test shop' in result:
|
||||
pass
|
||||
else:
|
||||
self.fail()
|
||||
|
||||
def test_update_mc_uuid(self):
|
||||
self.commands.register(zerohd, '143072699567177728')
|
||||
|
||||
self.commands.update_mc_uuid('143072699567177728', '0')
|
||||
|
||||
self.assertRaises(PlayerNotFound, self.commands.add_shop, 0, 0, shop_name='test shop',
|
||||
mc_uuid='fe7e84132570458892032b69ff188bc3')
|
||||
|
||||
def test_update_mc_name(self):
|
||||
self.commands.register(zerohd, '143072699567177728')
|
||||
|
||||
self.commands.update_mc_name('143072699567177728')
|
||||
|
||||
def test_update_discord_uuid(self):
|
||||
self.commands.register(zerohd, '143072699567177728')
|
||||
|
||||
self.commands.update_discord_uuid('143072699567177728', '0')
|
||||
|
||||
self.assertRaises(PlayerNotFound, self.commands.add_shop, 0, 0, shop_name='test shop',
|
||||
discord_uuid='143072699567177728')
|
||||
|
||||
def test_add_player(self):
|
||||
self.commands.add_player('143072699567177728', zerohd)
|
||||
|
||||
self.assertRaises(PlayerInDBError, self.commands.add_player, '143072699567177728', zerohd)
|
||||
|
||||
if zerohd in self.commands.find_player('143072699567177728'):
|
||||
pass
|
||||
else:
|
||||
self.fail()
|
|
@ -1,291 +0,0 @@
|
|||
import os
|
||||
from unittest import TestCase
|
||||
|
||||
from geoffrey.DatabaseInterface import *
|
||||
from geoffrey.BotConfig import *
|
||||
|
||||
zerohd = 'zerohd'
|
||||
|
||||
|
||||
class TestGeoffreyDatabase(TestCase):
|
||||
def setUp(self):
|
||||
path = os.path.dirname(os.path.abspath(__file__))
|
||||
self.bot_config = get_config('{}/GeoffreyConfig.ini'.format(path))
|
||||
|
||||
self.interface = DatabaseInterface(self.bot_config, True)
|
||||
self.session = self.interface.database.Session()
|
||||
self.interface.database.clear_all(self.session)
|
||||
self.owner = Player(zerohd, '143072699567177728')
|
||||
self.loc = Location('test', 1, 3, self.owner, dimension='Nether')
|
||||
self.tunnel = Tunnel(self.owner, "west", 105, self.loc)
|
||||
|
||||
def tearDown(self):
|
||||
self.session.commit()
|
||||
self.session.close()
|
||||
|
||||
def test_find_top_shops_selling_items(self):
|
||||
owner = self.add_player()
|
||||
shop = self.add_shop(owner)
|
||||
self.interface.add_item(self.session, owner, 'test', 'dirt', 1, 15)
|
||||
self.interface.add_item(self.session, owner, 'test', 'dirt', 1, 5)
|
||||
self.interface.add_loc(self.session, owner, 'test2', 1, 3, "nether", loc_type=Shop)
|
||||
self.interface.add_item(self.session, owner, 'test2', 'dirt', 1, 5)
|
||||
shop_list = self.interface.find_top_shops_selling_item(self.session, "Dirt")
|
||||
|
||||
self.assertEquals(shop_list[0][0].id, shop.id)
|
||||
|
||||
def add_shop(self, player):
|
||||
shop = self.interface.add_loc(self.session, player, 'test', 1, 3, "nether", loc_type=Shop)
|
||||
return shop
|
||||
|
||||
def add_player(self):
|
||||
player = self.interface.add_player(self.session, zerohd, discord_uuid='143072699567177728')
|
||||
return player
|
||||
|
||||
def add_loc(self, player):
|
||||
loc = self.interface.add_loc(self.session, player, 'test', 0, 0, loc_type=Base)
|
||||
return loc
|
||||
|
||||
def test_add_object(self):
|
||||
self.interface.database.add_object(self.session, self.loc)
|
||||
self.interface.database.add_object(self.session, self.owner)
|
||||
self.interface.database.add_object(self.session, self.tunnel)
|
||||
|
||||
uuid = grab_UUID(zerohd)
|
||||
expr = Player.mc_uuid == uuid
|
||||
p = self.interface.database.query_by_filter(self.session, Player, expr)[0]
|
||||
|
||||
expr = Location.owner == p
|
||||
loc2 = self.interface.database.query_by_filter(self.session, Location, expr)[0]
|
||||
|
||||
self.assertEqual(self.loc.id, loc2.id)
|
||||
|
||||
def test_query_by_filter(self):
|
||||
self.interface.database.add_object(self.session, self.loc)
|
||||
self.interface.database.add_object(self.session, self.owner)
|
||||
expr = (Location.owner == self.owner)
|
||||
loc2 = self.interface.database.query_by_filter(self.session, Location, expr)[0]
|
||||
self.assertEqual(loc2.id, self.loc.id)
|
||||
|
||||
def test_delete_entry(self):
|
||||
self.interface.database.add_object(self.session, self.loc)
|
||||
self.interface.database.add_object(self.session, self.owner)
|
||||
self.session.commit()
|
||||
|
||||
expr = Location.owner == self.owner
|
||||
self.interface.database.delete_entry(self.session, Location, expr)
|
||||
|
||||
expr = Player.name == zerohd
|
||||
player = self.interface.database.query_by_filter(self.session, Player, expr)[0]
|
||||
self.assertEqual(player.name, zerohd)
|
||||
|
||||
expr = Location.owner == player
|
||||
|
||||
loc2 = self.interface.database.query_by_filter(self.session, Location, expr)
|
||||
|
||||
self.assertEqual(len(loc2), 0)
|
||||
|
||||
self.assertRaises(DeleteEntryError, self.interface.database.delete_entry, self.session, Location, expr)
|
||||
|
||||
def test_add_player(self):
|
||||
self.add_player()
|
||||
self.assertRaises(PlayerInDBError, self.interface.add_player, self.session, zerohd,
|
||||
discord_uuid='143072699567177728')
|
||||
|
||||
def test_add_shop(self):
|
||||
owner = self.add_player()
|
||||
shop = self.add_shop(owner)
|
||||
|
||||
self.assertEqual(type(shop), Shop)
|
||||
|
||||
shop_list = self.interface.find_location_by_name(self.session, 'test', loc_type=Shop)
|
||||
self.assertEqual(shop_list[0].dimension, shop.dimension)
|
||||
|
||||
def test_add_two_shops(self):
|
||||
owner = self.add_player()
|
||||
self.add_shop(owner)
|
||||
shop2 = self.interface.add_loc(self.session, owner, 'no u', 1, 3, loc_type=Shop)
|
||||
|
||||
loc_list = self.interface.find_location_by_owner(self.session, owner)
|
||||
|
||||
self.assertEqual(loc_list[1].id, shop2.id)
|
||||
|
||||
def test_add_tunnel(self):
|
||||
player = self.add_player()
|
||||
tunnel1 = self.interface.add_tunnel(self.session, player, "South", 155, None)
|
||||
|
||||
tunnel2 = self.interface.find_tunnel_by_owner_name(self.session, zerohd)[0]
|
||||
self.assertEqual(tunnel1, tunnel2)
|
||||
|
||||
self.assertRaises(EntryNameNotUniqueError, self.interface.add_tunnel, self.session, player, "South", 155, None)
|
||||
|
||||
loc = self.add_loc(player)
|
||||
|
||||
tunnel3 = self.interface.add_tunnel(self.session, player, "South", 155, 'test')
|
||||
|
||||
tunnel4 = self.interface.find_tunnel_by_owner_name(self.session, zerohd)[0]
|
||||
self.assertEqual(tunnel3, tunnel4)
|
||||
|
||||
self.assertRaises(LocationHasTunnelError, self.interface.add_tunnel, self.session, player, "South", 155,
|
||||
'test')
|
||||
|
||||
self.assertRaises(LocationLookUpError, self.interface.add_tunnel, self.session, player, "South", 155,
|
||||
'no u')
|
||||
|
||||
def test_add_item(self):
|
||||
owner = self.add_player()
|
||||
self.add_shop(owner)
|
||||
self.interface.add_item(self.session, owner, 'test', 'dirt', 1, 15)
|
||||
|
||||
shops = self.interface.find_shop_selling_item(self.session, 'dirt')
|
||||
self.assertGreater(len(shops), 0)
|
||||
|
||||
self.assertRaises(LocationLookUpError, self.interface.add_item, self.session, owner, 'no u', 'dirt', 1, 15)
|
||||
|
||||
def test_find_player_by_discord_uuid(self):
|
||||
p1 = self.add_player()
|
||||
p2 = self.interface.find_player_by_discord_uuid(self.session, 143072699567177728)
|
||||
|
||||
self.assertEqual(p1, p2)
|
||||
|
||||
self.assertRaises(PlayerNotFound, self.interface.find_player_by_discord_uuid, self.session, 143072698)
|
||||
|
||||
def test_find_player_by_mc_uuid(self):
|
||||
p1 = self.add_player()
|
||||
p2 = self.interface.find_player_by_mc_uuid(self.session, 'fe7e84132570458892032b69ff188bc3')
|
||||
|
||||
self.assertEqual(p1, p2)
|
||||
|
||||
self.assertRaises(PlayerNotFound, self.interface.find_player_by_discord_uuid, self.session, 143072698)
|
||||
|
||||
def test_find_location_by_owner(self):
|
||||
owner = self.add_player()
|
||||
shop = self.add_shop(owner)
|
||||
|
||||
loc_list = self.interface.find_location_by_owner(self.session, owner)
|
||||
|
||||
self.assertEqual(loc_list[0].id, shop.id)
|
||||
|
||||
def test_find_location_by_name_and_owner(self):
|
||||
owner = self.add_player()
|
||||
shop = self.add_shop(owner)
|
||||
|
||||
loc_list = self.interface.find_location_by_name_and_owner(self.session, owner, 'test')
|
||||
|
||||
self.assertEqual(loc_list[0].id, shop.id)
|
||||
|
||||
def test_delete_base(self):
|
||||
owner = self.add_player()
|
||||
self.add_loc(owner)
|
||||
|
||||
self.interface.delete_location(self.session, owner, 'test')
|
||||
|
||||
loc_list = self.interface.find_location_by_name(self.session, 'test')
|
||||
|
||||
self.assertEqual(len(loc_list), 0)
|
||||
|
||||
def test_find_location_around(self):
|
||||
owner = self.add_player()
|
||||
self.add_loc(owner)
|
||||
|
||||
dim = "o"
|
||||
|
||||
loc_list = self.interface.find_location_around(self.session, 100, 100, 100, dim)
|
||||
|
||||
self.assertGreater(len(loc_list), 0)
|
||||
|
||||
loc_list = self.interface.find_location_around(self.session, 200, 200, 100, dim)
|
||||
|
||||
self.assertEqual(len(loc_list), 0)
|
||||
|
||||
loc_list = self.interface.find_location_around(self.session, -100, -100, 100, dim)
|
||||
|
||||
self.assertGreater(len(loc_list), 0)
|
||||
|
||||
loc_list = self.interface.find_location_around(self.session, 100, -100, 100, dim)
|
||||
|
||||
self.assertGreater(len(loc_list), 0)
|
||||
|
||||
loc_list = self.interface.find_location_around(self.session, -100, 100, 100, dim)
|
||||
|
||||
self.assertGreater(len(loc_list), 0)
|
||||
|
||||
loc_list = self.interface.find_location_around(self.session, 50, -50, 100, dim)
|
||||
|
||||
self.assertGreater(len(loc_list), 0)
|
||||
|
||||
def test_find_location_by_name(self):
|
||||
owner = self.add_player()
|
||||
loc = self.add_loc(owner)
|
||||
|
||||
loc_list = self.interface.find_location_by_name(self.session, 'test')
|
||||
|
||||
self.assertEqual(loc_list[0].name, loc.name)
|
||||
|
||||
def test_find_matching_location_by_name(self):
|
||||
owner = self.add_player()
|
||||
loc = self.add_loc(owner)
|
||||
|
||||
loc_list = self.interface.find_location_by_name_closest_match(self.session, 'test')
|
||||
|
||||
self.assertEqual(loc_list.name, loc.name)
|
||||
|
||||
shop = self.interface.add_loc(self.session, owner, 'tes', 1, 3, "nether", loc_type=Shop)
|
||||
|
||||
loc_list = self.interface.find_location_by_name_closest_match(self.session, shop.name)
|
||||
|
||||
self.assertEqual(loc_list.name, shop.name)
|
||||
|
||||
def test_search_all(self):
|
||||
owner = self.add_player()
|
||||
self.add_loc(owner)
|
||||
|
||||
loc_list = self.interface.search_all_fields(self.session, zerohd)
|
||||
|
||||
self.assertGreater(len(loc_list), 0)
|
||||
|
||||
def test_wrong_case(self):
|
||||
owner = self.add_player()
|
||||
loc = self.add_loc(owner)
|
||||
|
||||
loc_list = self.interface.find_location_by_owner_name(self.session, zerohd)
|
||||
|
||||
self.assertEqual(loc_list[0].id, loc.id)
|
||||
|
||||
self.interface.add_loc(self.session, owner, 'testshop', 1, 3, 'neThEr', loc_type=Shop)
|
||||
|
||||
self.interface.add_item(self.session, owner, 'testshop', 'dirts', 1, 15)
|
||||
|
||||
shops = self.interface.find_shop_selling_item(self.session, 'diRt')
|
||||
|
||||
self.assertGreater(len(shops), 0)
|
||||
|
||||
loc_list = self.interface.find_location_by_name(self.session, 'TEST')
|
||||
|
||||
self.assertEqual(loc_list[0].name, 'test')
|
||||
|
||||
def test_big_input(self):
|
||||
owner = self.add_player()
|
||||
|
||||
self.assertRaises(DatabaseValueError, self.interface.add_loc, self.session, owner,
|
||||
'TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT'
|
||||
'TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT'
|
||||
'TTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTTT', 0, 0, Shop)
|
||||
|
||||
def test_duplicate_name(self):
|
||||
owner = self.add_player()
|
||||
self.add_loc(owner)
|
||||
|
||||
self.assertRaises(EntryNameNotUniqueError, self.interface.add_loc, self.session,
|
||||
owner, 'test', 0, 0, Shop)
|
||||
|
||||
def test_delete_parent(self):
|
||||
owner = self.add_player()
|
||||
self.add_shop(owner)
|
||||
|
||||
self.interface.add_item(self.session, owner, 'test', 'dirt', 1, 15)
|
||||
|
||||
self.interface.delete_location(self.session, owner, 'test')
|
||||
|
||||
shops = self.interface.find_shop_selling_item(self.session, 'dirt')
|
||||
self.assertEqual(len(shops), 0)
|
|
@ -1,15 +0,0 @@
|
|||
from unittest import TestCase
|
||||
|
||||
from geoffrey.DiscordHelperFunctions import get_nickname
|
||||
|
||||
|
||||
class TestGet_nickname(TestCase):
|
||||
def test_get_nickname(self):
|
||||
class test:
|
||||
def __init__(self):
|
||||
self.display_name = 'dootb.in ꙩ ⃤'
|
||||
self.nick = 'dootb.in ꙩ ⃤'
|
||||
|
||||
tmp = test()
|
||||
|
||||
self.assertEqual(get_nickname(tmp, {'dootb.in ꙩ ⃤':'aeskdar'}), 'aeskdar')
|
|
@ -1,18 +0,0 @@
|
|||
from unittest import TestCase
|
||||
|
||||
from geoffrey.MinecraftAccountInfoGrabber import *
|
||||
|
||||
|
||||
class TestMinecraftInfoGrabber(TestCase):
|
||||
|
||||
def test_handle_data(self):
|
||||
self.assertEqual(grab_UUID('YMCA'), '5c084bd60c6a417ba084e2c5a382d0e1')
|
||||
|
||||
def test_grab_playername(self):
|
||||
self.assertEqual(grab_playername('5c084bd60c6a417ba084e2c5a382d0e1'), 'YMCA')
|
||||
|
||||
def test_grab_playername_wrong_case(self):
|
||||
self.assertEqual(grab_UUID('ymca'), '5c084bd60c6a417ba084e2c5a382d0e1')
|
||||
|
||||
def test_grab_invalid_player(self):
|
||||
self.assertRaises(UsernameLookupFailed, grab_UUID, 'lsdlkjsljglfjgldkj')
|
|
@ -1,34 +0,0 @@
|
|||
from unittest import TestCase
|
||||
import os
|
||||
from geoffrey.Commands import *
|
||||
from geoffrey.BotConfig import get_config
|
||||
from Mgeoffrey.inecraftAccountInfoGrabber import *
|
||||
from time import sleep
|
||||
|
||||
|
||||
class StressTest(TestCase):
|
||||
def setUp(self):
|
||||
path = os.path.dirname(os.path.abspath(__file__))
|
||||
self.bot_config = get_config('{}/GeoffreyConfig.ini'.format(path))
|
||||
self.commands = Commands(self.bot_config, True)
|
||||
|
||||
def clr_db(self):
|
||||
self.session = self.commands.interface.database.Session()
|
||||
self.commands.interface.database.clear_all(self.session)
|
||||
self.session.close()
|
||||
|
||||
def test_commands(self):
|
||||
self.clr_db()
|
||||
self.commands.register('BirbHD', '143072699567177728')
|
||||
|
||||
for i in range(0, 1000):
|
||||
self.commands.add_shop(0, 0, shop_name='test shop{}'.format(i), discord_uuid='143072699567177728')
|
||||
|
||||
self.commands.find('BirbHD')
|
||||
sleep(0.5)
|
||||
|
||||
def test_mc_query(self):
|
||||
for i in range(0, 1000):
|
||||
grab_playername('fe7e84132570458892032b69ff188bc3')
|
||||
|
||||
sleep(0.1)
|
|
@ -0,0 +1,80 @@
|
|||
# Generated by Django 2.1.2 on 2018-10-26 22:05
|
||||
|
||||
from django.db import migrations, models
|
||||
import django.db.models.deletion
|
||||
|
||||
|
||||
class Migration(migrations.Migration):
|
||||
|
||||
initial = True
|
||||
|
||||
dependencies = [
|
||||
]
|
||||
|
||||
operations = [
|
||||
migrations.CreateModel(
|
||||
name='ItemListing',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('item_name', models.CharField(max_length=128)),
|
||||
('price', models.IntegerField()),
|
||||
('amount', models.IntegerField()),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Location',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=128, unique=True)),
|
||||
('x_coord', models.IntegerField()),
|
||||
('z_coord', models.IntegerField()),
|
||||
('dimension', models.CharField(choices=[('O', 'Overworld'), ('N', 'Nether'), ('E', 'The End')], max_length=1)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Player',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('name', models.CharField(max_length=30)),
|
||||
('mc_uuid', models.CharField(max_length=36)),
|
||||
('discord_uuid', models.CharField(max_length=50)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Tunnel',
|
||||
fields=[
|
||||
('id', models.AutoField(auto_created=True, primary_key=True, serialize=False, verbose_name='ID')),
|
||||
('tunnel_number', models.IntegerField()),
|
||||
('tunnel_direction', models.CharField(choices=[('N', 'North'), ('E', 'East'), ('S', ''), ('W', '')], max_length=1)),
|
||||
],
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Base',
|
||||
fields=[
|
||||
('location_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='geoffrey.Location')),
|
||||
],
|
||||
bases=('geoffrey.location',),
|
||||
),
|
||||
migrations.CreateModel(
|
||||
name='Shop',
|
||||
fields=[
|
||||
('location_ptr', models.OneToOneField(auto_created=True, on_delete=django.db.models.deletion.CASCADE, parent_link=True, primary_key=True, serialize=False, to='geoffrey.Location')),
|
||||
],
|
||||
bases=('geoffrey.location',),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='tunnel',
|
||||
name='location',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='tunnel_location', to='geoffrey.Location'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='location',
|
||||
name='owner',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='owner_player', to='geoffrey.Player'),
|
||||
),
|
||||
migrations.AddField(
|
||||
model_name='itemlisting',
|
||||
name='shop',
|
||||
field=models.ForeignKey(on_delete=django.db.models.deletion.CASCADE, related_name='shop_selling', to='geoffrey.Shop'),
|
||||
),
|
||||
]
|
|
@ -0,0 +1,64 @@
|
|||
from django.db import models
|
||||
from django.conf import settings
|
||||
|
||||
# Create your models here.
|
||||
|
||||
|
||||
class Player(models.Model):
|
||||
name = models.CharField(max_length=30)
|
||||
mc_uuid = models.CharField(max_length=36)
|
||||
discord_uuid = models.CharField(max_length=50)
|
||||
|
||||
|
||||
class Location(models.Model):
|
||||
DIMENSIONS = (
|
||||
('O', 'Overworld'),
|
||||
('N', 'Nether'),
|
||||
('E', 'The End')
|
||||
)
|
||||
|
||||
name = models.CharField(max_length=128, unique=True)
|
||||
|
||||
x_coord = models.IntegerField()
|
||||
z_coord = models.IntegerField()
|
||||
dimension = models.CharField(max_length=1, choices=DIMENSIONS)
|
||||
|
||||
owner = models.ForeignKey(Player, related_name='owner_player', on_delete=models.CASCADE)
|
||||
|
||||
|
||||
class Shop(Location):
|
||||
def __str__(self):
|
||||
return "Shop: %s" % self.name
|
||||
|
||||
|
||||
class Base(Location):
|
||||
def __str__(self):
|
||||
return "Base: %s" % self.name
|
||||
|
||||
|
||||
class ItemListing(models.Model):
|
||||
item_name = models.CharField(max_length=128)
|
||||
price = models.IntegerField()
|
||||
amount = models.IntegerField()
|
||||
|
||||
shop = models.ForeignKey(Shop, related_name="shop_selling", on_delete=models.CASCADE)
|
||||
|
||||
def __str__(self):
|
||||
return "Item: %d %s for %d" % (self.amount, self.item_name, self.amount)
|
||||
|
||||
|
||||
class Tunnel(models.Model):
|
||||
TUNNEL_NAMES = (
|
||||
('N', getattr(settings, 'NORTH', '')),
|
||||
('E', getattr(settings, 'EAST', '')),
|
||||
('S', getattr(settings, 'SOUTH', '')),
|
||||
('W', getattr(settings, 'WEST', ''))
|
||||
)
|
||||
|
||||
tunnel_number = models.IntegerField()
|
||||
tunnel_direction = models.CharField(max_length=1, choices=TUNNEL_NAMES)
|
||||
|
||||
location = models.ForeignKey(Location, related_name="tunnel_location", on_delete=models.CASCADE)
|
||||
|
||||
def __str__(self):
|
||||
return "Tunnel: %s %d" % (self.tunnel_direction, self.tunnel_number)
|
9
setup.py
9
setup.py
|
@ -1,9 +0,0 @@
|
|||
from distutils.core import setup
|
||||
|
||||
setup(
|
||||
name='Geoffrey',
|
||||
version=__import__('geoffrey').__version__,
|
||||
packages=['geoffrey', 'geoffrey.cogs'],
|
||||
install_requires=['discord.py', 'SQLAlchemy', 'pymysql', 'requests', 'simplejson'],
|
||||
long_description=open('README').read(),
|
||||
)
|
|
@ -0,0 +1,3 @@
|
|||
from django.test import TestCase
|
||||
|
||||
# Create your tests here.
|
|
@ -0,0 +1,7 @@
|
|||
from django.urls import path
|
||||
|
||||
from . import views
|
||||
|
||||
urlpatterns = [
|
||||
path('', views.index, name='index'),
|
||||
]
|
Loading…
Reference in New Issue