From 7748ab4010381ddc3250e00878c071fbfef55e42 Mon Sep 17 00:00:00 2001 From: Joey Hines Date: Fri, 26 Oct 2018 18:42:53 -0500 Subject: [PATCH] Initial Commit for v2 Began migration of project to Django Created Django models for all current SQLAlchemy models --- .gitignore | 2 + __init__.py | 0 admin.py | 9 + apps.py | 5 + geoffrey/BotConfig.py | 85 ---- geoffrey/BotErrors.py | 82 ---- geoffrey/Commands.py | 428 -------------------- geoffrey/DatabaseInterface.py | 194 --------- geoffrey/DatabaseModels.py | 311 -------------- geoffrey/DiscordHelperFunctions.py | 29 -- geoffrey/Geoffrey.py | 12 - geoffrey/MinecraftAccountInfoGrabber.py | 36 -- geoffrey/__init__.py | 1 - geoffrey/bot.py | 207 ---------- geoffrey/cogs/Add_Commands.py | 146 ------- geoffrey/cogs/Admin_Commands.py | 166 -------- geoffrey/cogs/Delete_Commands.py | 65 --- geoffrey/cogs/Edit_Commands.py | 76 ---- geoffrey/cogs/Search_Commands.py | 139 ------- geoffrey/cogs/__init__.py | 1 - geoffrey/tests/test_commands.py | 348 ---------------- geoffrey/tests/test_geoffreyDatabase.py | 291 ------------- geoffrey/tests/test_get_nickname.py | 15 - geoffrey/tests/test_minecraftInfoGrabber.py | 18 - geoffrey/tests/test_stress.py | 34 -- migrations/0001_initial.py | 80 ++++ migrations/__init__.py | 0 models.py | 64 +++ setup.py | 9 - tests.py | 3 + urls.py | 7 + views.py | 6 + 32 files changed, 176 insertions(+), 2693 deletions(-) create mode 100644 .gitignore create mode 100644 __init__.py create mode 100644 admin.py create mode 100644 apps.py delete mode 100644 geoffrey/BotConfig.py delete mode 100644 geoffrey/BotErrors.py delete mode 100644 geoffrey/Commands.py delete mode 100644 geoffrey/DatabaseInterface.py delete mode 100644 geoffrey/DatabaseModels.py delete mode 100644 geoffrey/DiscordHelperFunctions.py delete mode 100644 geoffrey/Geoffrey.py delete mode 100644 geoffrey/MinecraftAccountInfoGrabber.py delete mode 100644 geoffrey/__init__.py delete mode 100644 geoffrey/bot.py delete mode 100644 geoffrey/cogs/Add_Commands.py delete mode 100644 geoffrey/cogs/Admin_Commands.py delete mode 100644 geoffrey/cogs/Delete_Commands.py delete mode 100644 geoffrey/cogs/Edit_Commands.py delete mode 100644 geoffrey/cogs/Search_Commands.py delete mode 100644 geoffrey/cogs/__init__.py delete mode 100644 geoffrey/tests/test_commands.py delete mode 100644 geoffrey/tests/test_geoffreyDatabase.py delete mode 100644 geoffrey/tests/test_get_nickname.py delete mode 100644 geoffrey/tests/test_minecraftInfoGrabber.py delete mode 100644 geoffrey/tests/test_stress.py create mode 100644 migrations/0001_initial.py create mode 100644 migrations/__init__.py create mode 100644 models.py delete mode 100644 setup.py create mode 100644 tests.py create mode 100644 urls.py create mode 100644 views.py diff --git a/.gitignore b/.gitignore new file mode 100644 index 0000000..d42fd7d --- /dev/null +++ b/.gitignore @@ -0,0 +1,2 @@ +*.pyc +__pycache__/* diff --git a/__init__.py b/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/admin.py b/admin.py new file mode 100644 index 0000000..a149091 --- /dev/null +++ b/admin.py @@ -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) \ No newline at end of file diff --git a/apps.py b/apps.py new file mode 100644 index 0000000..4af1988 --- /dev/null +++ b/apps.py @@ -0,0 +1,5 @@ +from django.apps import AppConfig + + +class GeoffreyConfig(AppConfig): + name = 'geoffrey' diff --git a/geoffrey/BotConfig.py b/geoffrey/BotConfig.py deleted file mode 100644 index 03f1370..0000000 --- a/geoffrey/BotConfig.py +++ /dev/null @@ -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) diff --git a/geoffrey/BotErrors.py b/geoffrey/BotErrors.py deleted file mode 100644 index a375263..0000000 --- a/geoffrey/BotErrors.py +++ /dev/null @@ -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""" diff --git a/geoffrey/Commands.py b/geoffrey/Commands.py deleted file mode 100644 index b989a0f..0000000 --- a/geoffrey/Commands.py +++ /dev/null @@ -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 diff --git a/geoffrey/DatabaseInterface.py b/geoffrey/DatabaseInterface.py deleted file mode 100644 index ff248ab..0000000 --- a/geoffrey/DatabaseInterface.py +++ /dev/null @@ -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) diff --git a/geoffrey/DatabaseModels.py b/geoffrey/DatabaseModels.py deleted file mode 100644 index ed0b537..0000000 --- a/geoffrey/DatabaseModels.py +++ /dev/null @@ -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() diff --git a/geoffrey/DiscordHelperFunctions.py b/geoffrey/DiscordHelperFunctions.py deleted file mode 100644 index d13883e..0000000 --- a/geoffrey/DiscordHelperFunctions.py +++ /dev/null @@ -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 {} diff --git a/geoffrey/Geoffrey.py b/geoffrey/Geoffrey.py deleted file mode 100644 index 1f1ff14..0000000 --- a/geoffrey/Geoffrey.py +++ /dev/null @@ -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() diff --git a/geoffrey/MinecraftAccountInfoGrabber.py b/geoffrey/MinecraftAccountInfoGrabber.py deleted file mode 100644 index 5047eba..0000000 --- a/geoffrey/MinecraftAccountInfoGrabber.py +++ /dev/null @@ -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'] diff --git a/geoffrey/__init__.py b/geoffrey/__init__.py deleted file mode 100644 index 58d478a..0000000 --- a/geoffrey/__init__.py +++ /dev/null @@ -1 +0,0 @@ -__version__ = '1.2.0' diff --git a/geoffrey/bot.py b/geoffrey/bot.py deleted file mode 100644 index 02006be..0000000 --- a/geoffrey/bot.py +++ /dev/null @@ -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...") diff --git a/geoffrey/cogs/Add_Commands.py b/geoffrey/cogs/Add_Commands.py deleted file mode 100644 index 5517ce5..0000000 --- a/geoffrey/cogs/Add_Commands.py +++ /dev/null @@ -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)) diff --git a/geoffrey/cogs/Admin_Commands.py b/geoffrey/cogs/Admin_Commands.py deleted file mode 100644 index 0b90c82..0000000 --- a/geoffrey/cogs/Admin_Commands.py +++ /dev/null @@ -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)) diff --git a/geoffrey/cogs/Delete_Commands.py b/geoffrey/cogs/Delete_Commands.py deleted file mode 100644 index 8f2b2fd..0000000 --- a/geoffrey/cogs/Delete_Commands.py +++ /dev/null @@ -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)) diff --git a/geoffrey/cogs/Edit_Commands.py b/geoffrey/cogs/Edit_Commands.py deleted file mode 100644 index a347047..0000000 --- a/geoffrey/cogs/Edit_Commands.py +++ /dev/null @@ -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)) diff --git a/geoffrey/cogs/Search_Commands.py b/geoffrey/cogs/Search_Commands.py deleted file mode 100644 index fe64204..0000000 --- a/geoffrey/cogs/Search_Commands.py +++ /dev/null @@ -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)) diff --git a/geoffrey/cogs/__init__.py b/geoffrey/cogs/__init__.py deleted file mode 100644 index 8b13789..0000000 --- a/geoffrey/cogs/__init__.py +++ /dev/null @@ -1 +0,0 @@ - diff --git a/geoffrey/tests/test_commands.py b/geoffrey/tests/test_commands.py deleted file mode 100644 index e36b47e..0000000 --- a/geoffrey/tests/test_commands.py +++ /dev/null @@ -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() \ No newline at end of file diff --git a/geoffrey/tests/test_geoffreyDatabase.py b/geoffrey/tests/test_geoffreyDatabase.py deleted file mode 100644 index e707cf3..0000000 --- a/geoffrey/tests/test_geoffreyDatabase.py +++ /dev/null @@ -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) diff --git a/geoffrey/tests/test_get_nickname.py b/geoffrey/tests/test_get_nickname.py deleted file mode 100644 index 0e2684b..0000000 --- a/geoffrey/tests/test_get_nickname.py +++ /dev/null @@ -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') diff --git a/geoffrey/tests/test_minecraftInfoGrabber.py b/geoffrey/tests/test_minecraftInfoGrabber.py deleted file mode 100644 index 19d65f4..0000000 --- a/geoffrey/tests/test_minecraftInfoGrabber.py +++ /dev/null @@ -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') diff --git a/geoffrey/tests/test_stress.py b/geoffrey/tests/test_stress.py deleted file mode 100644 index 36aabeb..0000000 --- a/geoffrey/tests/test_stress.py +++ /dev/null @@ -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) diff --git a/migrations/0001_initial.py b/migrations/0001_initial.py new file mode 100644 index 0000000..d714d08 --- /dev/null +++ b/migrations/0001_initial.py @@ -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'), + ), + ] diff --git a/migrations/__init__.py b/migrations/__init__.py new file mode 100644 index 0000000..e69de29 diff --git a/models.py b/models.py new file mode 100644 index 0000000..7a62bf4 --- /dev/null +++ b/models.py @@ -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) diff --git a/setup.py b/setup.py deleted file mode 100644 index b5eaac1..0000000 --- a/setup.py +++ /dev/null @@ -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(), -) diff --git a/tests.py b/tests.py new file mode 100644 index 0000000..7ce503c --- /dev/null +++ b/tests.py @@ -0,0 +1,3 @@ +from django.test import TestCase + +# Create your tests here. diff --git a/urls.py b/urls.py new file mode 100644 index 0000000..3ef24d9 --- /dev/null +++ b/urls.py @@ -0,0 +1,7 @@ +from django.urls import path + +from . import views + +urlpatterns = [ + path('', views.index, name='index'), +] \ No newline at end of file diff --git a/views.py b/views.py new file mode 100644 index 0000000..47865be --- /dev/null +++ b/views.py @@ -0,0 +1,6 @@ +from django.shortcuts import render +from django.http import HttpResponse + +# Create your views here. +def index(request): + return HttpResponse("Geoffrey is here!")