Initial Commit for v2

Began migration of project to Django
Created Django models for all current SQLAlchemy models
doc_update
Joey Hines 2018-10-26 18:42:53 -05:00
parent 2557e75a2f
commit 7748ab4010
32 changed files with 176 additions and 2693 deletions

2
.gitignore vendored 100644
View File

@ -0,0 +1,2 @@
*.pyc
__pycache__/*

0
__init__.py 100644
View File

9
admin.py 100644
View File

@ -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)

5
apps.py 100644
View File

@ -0,0 +1,5 @@
from django.apps import AppConfig
class GeoffreyConfig(AppConfig):
name = 'geoffrey'

View File

@ -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)

View File

@ -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"""

View File

@ -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

View File

@ -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)

View File

@ -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()

View File

@ -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 {}

View File

@ -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()

View File

@ -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']

View File

@ -1 +0,0 @@
__version__ = '1.2.0'

View File

@ -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...")

View File

@ -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))

View File

@ -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))

View File

@ -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))

View File

@ -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))

View File

@ -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))

View File

@ -1 +0,0 @@

View File

@ -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()

View File

@ -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)

View File

@ -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')

View File

@ -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')

View File

@ -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)

View File

@ -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'),
),
]

View File

64
models.py 100644
View File

@ -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)

View File

@ -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(),
)

3
tests.py 100644
View File

@ -0,0 +1,3 @@
from django.test import TestCase
# Create your tests here.

7
urls.py 100644
View File

@ -0,0 +1,7 @@
from django.urls import path
from . import views
urlpatterns = [
path('', views.index, name='index'),
]

6
views.py 100644
View File

@ -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!")