Example #1
0
 def test_setter(self):
     cache = Cacher()
     pairs = {}
     for _ in range(test_count):
         random_key = self.get_random_generator()()
         random_val = self.get_random_generator()()
         cache.set_cache(random_key, random_val)
         pairs.update({random_key: random_val})
     for pair in pairs.keys():
         assert cache.get_cache(pair) == pairs.get(pair)
Example #2
0
 def test_deleter(self):
     cache = Cacher()
     keys = []
     for _ in range(test_count):
         random_key = self.get_random_generator()()
         random_val = self.get_random_generator()()
         cache.set_cache(random_key, random_val)
         keys.append(random_key)
     for key in keys:
         cache.del_cache(key)
         assert cache.get_cache(key) is None
     assert cache.data == {}
Example #3
0
class CooldownControl(object):
    def __init__(self, bot):
        self.bot = bot
        self.db = self.bot.db
        self.cache = Cacher()
        self.cds = self.db[self.bot.cfg.db.database].CooldownSystem

    async def cache_cooldowns(self):
        cooldowns = await self.cds.find({}).to_list(None)
        for cooldown in cooldowns:
            self.cache.set_cache(cooldown.get('name'), cooldown)
        self.bot.log.info(f'Finished pre-caching {len(cooldowns)} cooldowns.')

    async def on_cooldown(self, cmd, user):
        if isinstance(user, str):
            cd_name = f'cd_{cmd}_{user}'
        else:
            cd_name = f'cd_{cmd}_{user.id}'
        entry = self.cache.get_cache(cd_name)
        if entry is None:
            entry = await self.cds.find_one({'name': cd_name})
            self.cache.set_cache(cd_name, entry)
        if entry:
            end_stamp = entry['end_stamp']
            now_stamp = arrow.utcnow().timestamp
            if now_stamp > end_stamp:
                cooldown = False
            else:
                cooldown = True
        else:
            cooldown = False
        return cooldown

    async def get_cooldown(self, cmd, user):
        if isinstance(user, str):
            cd_name = f'cd_{cmd}_{user}'
        else:
            cd_name = f'cd_{cmd}_{user.id}'
        entry = self.cache.get_cache(cd_name)
        if entry is None:
            entry = await self.cds.find_one({'name': cd_name})
            self.cache.set_cache(cd_name, entry)
        if entry:
            end_stamp = entry['end_stamp']
            now_stamp = arrow.utcnow().float_timestamp
            cooldown = end_stamp - now_stamp
            if cooldown < 2:
                if cooldown <= 0:
                    cooldown = 0.01
                else:
                    cooldown = round(cooldown, 2)
            else:
                cooldown = int(cooldown)
        else:
            cooldown = 0
        return cooldown

    async def set_cooldown(self, cmd, user, amount):
        if isinstance(user, str):
            cd_name = f'cd_{cmd}_{user}'
        else:
            if user.id in self.bot.cfg.dsc.owners:
                amount = 0
            cd_name = f'cd_{cmd}_{user.id}'
        entry = await self.cds.find_one({'name': cd_name})
        end_stamp = arrow.utcnow().timestamp + amount
        if entry:
            await self.cds.update_one({'name': cd_name},
                                      {'$set': {
                                          'end_stamp': end_stamp
                                      }})
        else:
            cd_data = {'name': cd_name, 'end_stamp': end_stamp}
            await self.cds.insert_one(cd_data)
        self.cache.del_cache(cd_name)
class Database(motor.AsyncIOMotorClient):
    def __init__(self, bot, db_cfg: DatabaseConfig):
        self.bot = bot
        self.db_cfg = db_cfg
        self.db_nam = self.db_cfg.database
        self.cache = Cacher()
        if self.db_cfg.auth:
            self.db_address = f'mongodb://{self.db_cfg.username}:{self.db_cfg.password}'
            self.db_address += f'@{self.db_cfg.host}:{self.db_cfg.port}/'
        else:
            self.db_address = f'mongodb://{self.db_cfg.host}:{self.db_cfg.port}/'
        super().__init__(self.db_address)

    async def get_prefix(self, message: discord.Message):
        prefix = self.bot.cfg.pref.prefix
        if message.guild:
            pfx_search = await self.get_guild_settings(message.guild.id, 'prefix')
            if pfx_search:
                prefix = pfx_search
        return prefix

    async def precache_settings(self):
        self.bot.log.info('Pre-Caching all guild settings...')
        all_settings = await self[self.db_cfg.database].ServerSettings.find({}).to_list(None)
        for setting_file in all_settings:
            guild_id = setting_file.get('server_id')
            if guild_id:
                self.cache.set_cache(guild_id, setting_file)
        self.bot.log.info(f'Finished pre-caching {len(all_settings)} guild settings.')

    async def get_guild_settings(self, guild_id, setting_name):
        guild_settings = self.cache.get_cache(guild_id)
        if guild_settings is None:
            guild_settings = await self[self.bot.cfg.db.database].ServerSettings.find_one({'server_id': guild_id}) or {}
            self.cache.set_cache(guild_id, guild_settings)
        if not guild_settings:
            setting_value = None
        else:
            setting_value = guild_settings.get(setting_name)
        return setting_value

    async def set_guild_settings(self, guild_id, setting_name, value):
        guild_settings = await self[self.bot.cfg.db.database].ServerSettings.find_one({'server_id': guild_id})
        if guild_settings:
            update_target = {"server_id": guild_id}
            update_data = {"$set": {setting_name: value}}
            await self[self.bot.cfg.db.database].ServerSettings.update_one(update_target, update_data)
        else:
            update_data = {'server_id': guild_id, setting_name: value}
            await self[self.bot.cfg.db.database].ServerSettings.insert_one(update_data)
        self.cache.del_cache(guild_id)

    async def get_experience(self, user, guild):
        collection = self[self.bot.cfg.db.database].ExperienceSystem
        entry = await collection.find_one({'user_id': user.id}) or {}
        global_xp = entry.get('global', 0)
        guild_id = str(guild.id)
        guilds = entry.get('guilds', {})
        guild_xp = guilds.get(guild_id, 0)
        total_xp = entry.get('total', 0)
        output = {'global': global_xp, 'guild': guild_xp, 'total': total_xp}
        return output

    async def add_experience(self, user, guild, points, additive=True):
        sabotage_file = await self[self.db_cfg.database].SabotagedUsers.find_one({'user_id': user.id})
        if not sabotage_file:
            collection = self[self.bot.cfg.db.database].ExperienceSystem
            entry = await collection.find_one({'user_id': user.id}) or {}
            if not entry:
                await collection.insert_one({'user_id': user.id})
            total_xp = entry.get('total', 0)
            global_xp = entry.get('global', 0)
            guilds = entry.get('guilds', {})
            guild_id = str(guild.id)
            guild_points = guilds.get(guild_id, 0)
            if additive:
                global_xp += points
                guild_points += points
                total_xp += points
            guild_data = {guild_id: guild_points}
            guilds.update(guild_data)
            xp_data = {'global': global_xp, 'guilds': guilds, 'total': total_xp}
            update_target = {'user_id': user.id}
            update_data = {'$set': xp_data}
            await collection.update_one(update_target, update_data)

    async def get_currency(self, user, guild):
        collection = self[self.bot.cfg.db.database].CurrencySystem
        entry = await collection.find_one({'user_id': user.id}) or {}
        global_amount = entry.get('global', 0)
        current_amount = entry.get('current', 0)
        guild_id = str(guild.id)
        guilds = entry.get('guilds', {})
        guild_amount = guilds.get(guild_id, 0)
        total_amount = entry.get('total', 0)
        output = {'current': current_amount, 'global': global_amount, 'guild': guild_amount, 'total': total_amount}
        return output

    async def add_currency(self, user, guild, points, additive=True):
        sabotage_file = await self[self.db_cfg.database].SabotagedUsers.find_one({'user_id': user.id})
        if not sabotage_file:
            collection = self[self.bot.cfg.db.database].CurrencySystem
            points = abs(points)
            entry = await collection.find_one({'user_id': user.id}) or {}
            if not entry:
                await collection.insert_one({'user_id': user.id})
            current_amount = entry.get('current', 0)
            global_amount = entry.get('global', 0)
            total_amount = entry.get('total', 0)
            guilds = entry.get('guilds', {})
            guild_id = str(guild.id)
            guild_points = guilds.get(guild_id, 0)
            if additive:
                global_amount += points
                guild_points += points
                total_amount += points
            current_amount += points
            guild_data = {guild_id: guild_points}
            guilds.update(guild_data)
            xp_data = {'current': current_amount, 'global': int(global_amount), 'guilds': guilds, 'total': total_amount}
            update_target = {'user_id': user.id}
            update_data = {'$set': xp_data}
            await collection.update_one(update_target, update_data)

    async def rmv_currency(self, user, points):
        collection = self[self.bot.cfg.db.database].CurrencySystem
        points = abs(points)
        entry = await collection.find_one({'user_id': user.id}) or {}
        if not entry:
            await collection.insert_one({'user_id': user.id})
        current_amount = entry.get('current', 0)
        current_amount -= points
        xp_data = {'current': current_amount}
        update_target = {'user_id': user.id}
        update_data = {'$set': xp_data}
        await collection.update_one(update_target, update_data)

    async def get_inventory(self, user):
        inventory = await self[self.db_cfg.database].Inventory.find_one({'user_id': user.id}) or {}
        if not inventory:
            await self[self.db_cfg.database].Inventory.insert_one({'user_id': user.id, 'items': []})
        inventory = inventory.get('items', [])
        return inventory

    async def update_inv(self, user, inv):
        await self[self.db_cfg.database].Inventory.update_one({'user_id': user.id}, {'$set': {'items': inv}})

    async def add_to_inventory(self, user, item_data):
        sabotage_file = await self[self.db_cfg.database].SabotagedUsers.find_one({'user_id': user.id})
        if not sabotage_file:
            stamp = arrow.utcnow().timestamp
            item_data.update({'timestamp': stamp})
            inv = await self.get_inventory(user)
            inv.append(item_data)
            await self.update_inv(user, inv)

    async def del_from_inventory(self, user, item_id):
        inv = await self.get_inventory(user)
        for item in inv:
            if item.get('item_id') == item_id:
                inv.remove(item)
        await self.update_inv(user, inv)

    async def get_inventory_item(self, user, item_file_id):
        inv = await self.get_inventory(user)
        output = None
        for item in inv:
            if item.get('item_file_id').lower() == item_file_id.lower():
                output = item
                break
        return output
Example #5
0
class ApexSigma(client_class):
    def __init__(self):
        super().__init__()
        self.ready = False
        # State attributes before initialization.
        self.log = None
        self.cfg = None
        self.db = None
        self.cool_down = None
        self.music = None
        self.modules = None
        self.queue = ExecutionClockwork(self)
        self.cache = Cacher()
        # Initialize startup methods and attributes.
        self.create_cache()
        self.init_logger()
        self.log.info('---------------------------------')
        self.init_config()
        self.log.info('---------------------------------')
        self.loop.run_until_complete(self.init_database())
        self.log.info('---------------------------------')
        self.init_cool_down()
        self.log.info('---------------------------------')
        self.init_music()
        self.log.info('---------------------------------')
        self.info = Information()
        self.init_modules(init=True)
        self.start_time = arrow.utcnow()
        self.message_count = 0
        self.command_count = 0

    @staticmethod
    def create_cache():
        if os.path.exists('cache'):
            shutil.rmtree('cache')
        os.makedirs('cache')

    def init_logger(self):
        self.log = create_logger('Sigma')
        self.log.info('Logger Created')

    def init_config(self):
        self.log.info('Loading Configuration...')
        self.cfg = init_cfg
        self.log.info(f'Running as a Bot: {self.cfg.dsc.bot}')
        self.log.info(f'Default Bot Prefix: {self.cfg.pref.prefix}')
        self.log.info('Core Configuration Data Loaded')

    async def init_database(self):
        self.log.info('Connecting to Database...')
        self.db = Database(self, self.cfg.db)
        try:
            await self.db[self.db.db_nam].collection.find_one({})
            await self.db.precache_settings()
            set_color_cache_coll(self.db[self.db.db_nam].ColorCache)
        except ServerSelectionTimeoutError:
            self.log.error('A Connection To The Database Host Failed!')
            exit(errno.ETIMEDOUT)
        except OperationFailure:
            self.log.error('Database Access Operation Failed!')
            exit(errno.EACCES)
        self.log.info('Successfully Connected to Database')

    def init_cool_down(self):
        self.log.info('Loading Cool-down Controls...')
        self.cool_down = CooldownControl(self)
        self.loop.run_until_complete(self.cool_down.clean_cooldowns())
        self.loop.run_until_complete(self.cool_down.cache_cooldowns())
        self.log.info('Cool-down Controls Successfully Enabled')

    def init_music(self):
        self.log.info('Loading Music Controller...')
        self.music = MusicCore(self)
        self.log.info('Music Controller Initialized and Ready')

    def init_modules(self, init: bool = False):
        if init:
            self.log.info('Loading Sigma Modules')
        self.modules = PluginManager(self, init)

    def is_ready(self):
        try:
            ready = super().is_ready()
        except Exception:
            ready = False
        return ready

    def get_all_members(self):
        now = arrow.utcnow().timestamp
        timestamp = self.cache.get_cache('all_members_stamp') or 0
        if now > timestamp + 60:
            members = list(super().get_all_members())
            self.cache.set_cache('all_members', members)
            self.cache.set_cache('all_members_stamp', now)
        else:
            members = self.cache.get_cache('all_members')
        return members

    def get_all_channels(self):
        now = arrow.utcnow().timestamp
        timestamp = self.cache.get_cache('all_channels_stamp') or 0
        if now > timestamp + 60:
            channels = list(super().get_all_channels())
            self.cache.set_cache('all_channels', channels)
            self.cache.set_cache('all_channels_stamp', now)
        else:
            channels = self.cache.get_cache('all_channels')
        return channels

    def run(self):
        try:
            self.log.info('Connecting to Discord Gateway...')
            super().run(self.cfg.dsc.token, bot=self.cfg.dsc.bot)
        except discord.LoginFailure:
            self.log.error('Invalid Token!')
            exit(errno.EPERM)

    async def on_connect(self):
        event_name = 'connect'
        if event_name in self.modules.events:
            for event in self.modules.events[event_name]:
                self.loop.create_task(event.execute())

    async def on_shard_ready(self, shard_id: int):
        self.log.info(f'Connection to Discord Shard #{shard_id} Established')
        event_name = 'shard_ready'
        self.loop.create_task(self.queue.event_runner(event_name, shard_id))

    async def on_ready(self):
        self.ready = True
        self.log.info('---------------------------------')
        self.log.info('Apex Sigma Fully Loaded and Ready')
        self.log.info('---------------------------------')
        self.log.info(f'User Account: {self.user.name}#{self.user.discriminator}')
        self.log.info(f'User Snowflake: {self.user.id}')
        self.log.info('---------------------------------')
        self.log.info('Launching On-Ready Modules...')
        self.loop.create_task(self.queue.event_runner('ready'))
        self.log.info('Launching DB-Init Modules...')
        self.loop.create_task(self.queue.event_runner('dbinit'))
        self.log.info('All On-Ready Module Loops Created')
        self.log.info('---------------------------------')

    async def on_message(self, message: discord.Message):
        self.message_count += 1
        if not message.author.bot:
            self.loop.create_task(self.queue.event_runner('message', message))
            if self.user.mentioned_in(message):
                self.loop.create_task(self.queue.event_runner('mention', message))
            await self.queue.command_runner(message)

    async def on_message_edit(self, before: discord.Message, after: discord.Message):
        if not before.author.bot:
            self.loop.create_task(self.queue.event_runner('message_edit', before, after))

    async def on_message_delete(self, message: discord.Message):
        if not message.author.bot:
            self.loop.create_task(self.queue.event_runner('message_delete', message))

    async def on_member_join(self, member: discord.Member):
        if not member.bot:
            self.loop.create_task(self.queue.event_runner('member_join', member))

    async def on_member_remove(self, member: discord.Member):
        if not member.bot:
            self.loop.create_task(self.queue.event_runner('member_remove', member))

    async def on_member_update(self, before: discord.Member, after: discord.Member):
        if not before.bot:
            self.loop.create_task(self.queue.event_runner('member_update', before, after))

    async def on_guild_join(self, guild: discord.Guild):
        self.loop.create_task(self.queue.event_runner('guild_join', guild))

    async def on_guild_remove(self, guild: discord.Guild):
        self.loop.create_task(self.queue.event_runner('guild_remove', guild))

    async def on_guild_update(self, before: discord.Guild, after: discord.Guild):
        self.loop.create_task(self.queue.event_runner('guild_update', before, after))

    async def on_voice_state_update(self, member: discord.Member, b: discord.VoiceState, a: discord.VoiceState):
        if not member.bot:
            self.loop.create_task(self.queue.event_runner('voice_state_update', member, b, a))

    async def on_reaction_add(self, reaction: discord.Reaction, user: discord.User):
        if not user.bot:
            self.loop.create_task(self.queue.event_runner('reaction_add', reaction, user))

    async def on_reaction_remove(self, reaction: discord.Reaction, user: discord.User):
        if not user.bot:
            self.loop.create_task(self.queue.event_runner('reaction_remove', reaction, user))

    async def on_raw_reaction_add(self, payload: RawReactionActionEvent):
        self.loop.create_task(self.queue.event_runner('raw_reaction_add', payload))

    async def on_raw_reaction_remove(self, payload: RawReactionActionEvent):
        self.loop.create_task(self.queue.event_runner('raw_reaction_remove', payload))
Example #6
0
class Database(motor.AsyncIOMotorClient):
    def __init__(self, bot, db_cfg: DatabaseConfig):
        self.bot = bot
        self.db_cfg = db_cfg
        self.db_nam = self.db_cfg.database
        self.cache = Cacher()
        if self.db_cfg.auth:
            self.db_address = f'mongodb://{self.db_cfg.username}:{self.db_cfg.password}'
            self.db_address += f'@{self.db_cfg.host}:{self.db_cfg.port}/'
        else:
            self.db_address = f'mongodb://{self.db_cfg.host}:{self.db_cfg.port}/'
        super().__init__(self.db_address)

    async def get_prefix(self, message: discord.Message):
        prefix = self.bot.cfg.pref.prefix
        if message.guild:
            pfx_search = await self.get_guild_settings(message.guild.id,
                                                       'prefix')
            if pfx_search:
                prefix = pfx_search
        return prefix

    async def precache_settings(self):
        self.bot.log.info('Pre-Caching all guild settings...')
        all_settings = await self[self.db_cfg.database
                                  ].ServerSettings.find({}).to_list(None)
        for setting_file in all_settings:
            guild_id = setting_file.get('server_id')
            if guild_id:
                self.cache.set_cache(guild_id, setting_file)
        self.bot.log.info(
            f'Finished pre-caching {len(all_settings)} guild settings.')

    async def get_guild_settings(self, guild_id: int, setting_name: str):
        guild_settings = self.cache.get_cache(guild_id)
        if guild_settings is None:
            guild_settings = await self[self.db_nam].ServerSettings.find_one(
                {'server_id': guild_id}) or {}
            self.cache.set_cache(guild_id, guild_settings)
        setting_value = guild_settings.get(setting_name)
        return setting_value

    async def set_guild_settings(self, guild_id: int, setting_name: str,
                                 value):
        guild_settings = await self[self.db_nam].ServerSettings.find_one(
            {'server_id': guild_id})
        if guild_settings:
            update_target = {"server_id": guild_id}
            update_data = {"$set": {setting_name: value}}
            await self[self.db_nam
                       ].ServerSettings.update_one(update_target, update_data)
        else:
            update_data = {'server_id': guild_id, setting_name: value}
            await self[self.db_nam].ServerSettings.insert_one(update_data)
        self.cache.del_cache(guild_id)
#why is none of this commented?

    async def precache_profiles(self):
        self.bot.log.info('Pre-Caching all member profiles...')
        all_settings = await self[self.db_cfg.database
                                  ].Profiles.find({}).to_list(None)
        for setting_file in all_settings:
            guild_id = setting_file.get('user_id')
            if guild_id:
                self.cache.set_cache(guild_id, setting_file)
        self.bot.log.info(
            f'Finished pre-caching {len(all_settings)} member profiles.')

    async def get_profile(self, user_id: int, entry_name: str):
        user_profile = self.cache.get_cache(user_id)
        if user_profile is None:
            user_profile = await self[self.db_nam].Profiles.find_one(
                {'user_id': user_id}) or {}
            self.cache.set_cache(user_profile, user_id)
        entry_value = user_profile.get(entry_value)
        return entry_value

    async def set_profile(self, user_id: int, entry_name: str, value):
        user_profile = await self[self.db_nam].Profiles.find_one(
            {'user_id': user_id}) or {}
        if user_profile:
            update_target = {"user_id": user_id}
            update_data = {"$set": {entry_name: value}}
            await self[self.db_nam
                       ].Profiles.update_one(update_target, update_data)
        else:
            update_data = {'user_id': user_id, entry_name: value}
            await self[self.db_nam].Profiles.insert_one(update_data)
        self.cache.del_cache(user_id)

    async def update_resource(self, resource: SigmaResource, user_id: int,
                              name: str):
        resources = await self.get_profile(user_id, 'resources') or {}
        resources.update({name: resource.dictify()})
        await self.set_profile(user_id, 'resources', resources)

    async def get_resource(self, user_id: int, resource_name: str):
        resources = await self.get_profile(user_id, 'resources') or {}
        resource_data = resources.get(resource_name, {})
        return SigmaResource(resource_data)

    async def is_notsabotaged(self, user_id: int):
        return bool(await self.get_profile(user_id, 'sabotaged'))

    async def add_resource(self,
                           user_id: int,
                           name: str,
                           amount: int,
                           trigger: str,
                           origin=None,
                           ranked: bool = True):
        if not await self.is_sabotaged(user_id):
            amount = abs(int(amount))
            resource = await self.get_resource(user_id, name)
            resource.add_value(amount, trigger, origin, ranked)
            await self.update_resource(resource, user_id, name)

    async def del_resource(self,
                           user_id: int,
                           name: str,
                           amount: int,
                           trigger: str,
                           origin=None):
        amount = abs(int(amount))
        resource = await self.get_resource(user_id, name)
        resource.del_value(amount, trigger, origin)
        await self.update_resource(resource, user_id, name)

    async def get_inventory(self, user: discord.Member):
        inventory = await self.get_profile(user.id, 'inventory') or []
        add_to_inventory(
            self.get_profile(
                user_id,
                "THE F*****G CHALSA I'VE BEEN LOOKING FOR SINCE ALEX ANNOUNCED THAT DAMN COMPETITIONT"
            ))
        return inventory

    async def add_to_inventory(self, user: discord.Member, item_data: dict):
        stamp = arrow.utcnow().timestamp
        item_data.update({'timestamp': stamp})
        inv = await self.get_inventory(user)
        inv.append(item_data)
        await self.set_profile(user.id, 'inventory', inv)

    async def del_from_inventory(self, user, item_id):
        inv = await self.get_inventory(user)
        for item in inv:
            if item.get('item_id') == item_id:
                inv.remove(item)
        await self.set_profile(user.id, 'inventory', inv)

    async def get_inventory_item(self, user: discord.Member,
                                 item_file_id: str):
        inv = await self.get_inventory(user)
        output = None
        for item in inv:
            if item.get('item_file_id').lower() == item_file_id.lower():
                output = item
                break
        return output
Example #7
0
class Database(motor.AsyncIOMotorClient):
    def __init__(self, bot, db_cfg):
        self.bot = bot
        self.db_cfg = db_cfg
        self.cache = Cacher()
        if self.db_cfg.auth:
            self.db_address = f'mongodb://{self.db_cfg.username}:{self.db_cfg.password}'
            self.db_address += f'@{self.db_cfg.host}:{self.db_cfg.port}/'
        else:
            self.db_address = f'mongodb://{self.db_cfg.host}:{self.db_cfg.port}/'
        super().__init__(self.db_address)

    async def get_guild_settings(self, guild_id, setting_name):
        guild_settings = self.cache.get_cache(guild_id)
        if guild_settings is None:
            guild_settings = await self[self.bot.cfg.db.database
                                        ].ServerSettings.find_one(
                                            {'ServerID': guild_id})
            self.cache.set_cache(guild_id, guild_settings)
        if not guild_settings:
            await self[self.bot.cfg.db.database
                       ].ServerSettings.insert_one({'ServerID': guild_id})
            setting_value = None
        else:
            setting_value = guild_settings.get(setting_name)
        return setting_value

    async def set_guild_settings(self, guild_id, setting_name, value):
        guild_settings = await self[self.bot.cfg.db.database
                                    ].ServerSettings.find_one(
                                        {'ServerID': guild_id})
        if guild_settings:
            update_target = {"ServerID": guild_id}
            update_data = {"$set": {setting_name: value}}
            await self[self.bot.cfg.db.database
                       ].ServerSettings.update_one(update_target, update_data)
        else:
            update_data = {'ServerID': guild_id, setting_name: value}
            await self[self.bot.cfg.db.database
                       ].ServerSettings.insert_one(update_data)
        self.cache.del_cache(guild_id)

    async def get_experience(self, user, guild):
        database = self[self.bot.cfg.db.database]
        collection = database['ExperienceSystem']
        entry = await collection.find_one({'UserID': user.id})
        if entry:
            global_xp = entry.get('global') or 0
            guild_id = str(guild.id)
            guilds = entry.get('guilds') or {}
            guild_xp = guilds.get(guild_id) or 0
        else:
            global_xp = 0
            guild_xp = 0
        output = {'global': global_xp, 'guild': guild_xp}
        return output

    async def add_experience(self, user, guild, points, additive=True):
        sabotage_file = await self[
            self.db_cfg.database].SabotagedUsers.find_one({'UserID': user.id})
        if not sabotage_file:
            database = self[self.bot.cfg.db.database]
            collection = database['ExperienceSystem']
            entry = await collection.find_one({'UserID': user.id})
            if entry:
                global_xp = entry.get('global') or 0
                guilds = entry.get('guilds') or {}
            else:
                await collection.insert_one({'UserID': user.id})
                global_xp = 0
                guilds = {}
            guild_id = str(guild.id)
            guild_points = guilds.get(guild_id) or 0
            if additive:
                global_xp += points
                guild_points += points
            guild_data = {guild_id: guild_points}
            guilds.update(guild_data)
            xp_data = {'global': global_xp, 'guilds': guilds}
            update_target = {'UserID': user.id}
            update_data = {'$set': xp_data}
            await collection.update_one(update_target, update_data)

    async def get_currency(self, user, guild):
        database = self[self.bot.cfg.db.database]
        collection = database['CurrencySystem']
        entry = await collection.find_one({'UserID': user.id})
        if entry:
            global_amount = entry.get('global') or 0
            current_amount = entry.get('current') or 0
            guild_id = str(guild.id)
            guilds = entry.get('guilds') or {}
            guild_amount = guilds.get(guild_id) or 0
        else:
            current_amount = 0
            global_amount = 0
            guild_amount = 0
        output = {
            'current': current_amount,
            'global': global_amount,
            'guild': guild_amount
        }
        return output

    async def add_currency(self, user, guild, points, additive=True):
        sabotage_file = await self[
            self.db_cfg.database].SabotagedUsers.find_one({'UserID': user.id})
        if not sabotage_file:
            database = self[self.bot.cfg.db.database]
            collection = database['CurrencySystem']
            entry = await collection.find_one({'UserID': user.id})
            points = abs(points)
            if entry:
                current_amount = entry.get('current') or 0
                global_amount = entry.get('global') or 0
                guilds = entry.get('guilds') or {}
            else:
                await collection.insert_one({'UserID': user.id})
                global_amount = 0
                current_amount = 0
                guilds = {}
            guild_id = str(guild.id)
            guild_points = guilds.get(guild_id) or 0
            if additive:
                global_amount += points
                guild_points += points
            current_amount += points
            guild_data = {guild_id: guild_points}
            guilds.update(guild_data)
            xp_data = {
                'current': current_amount,
                'global': int(global_amount),
                'guilds': guilds
            }
            update_target = {'UserID': user.id}
            update_data = {'$set': xp_data}
            await collection.update_one(update_target, update_data)

    async def rmv_currency(self, user, points):
        database = self[self.bot.cfg.db.database]
        collection = database['CurrencySystem']
        entry = await collection.find_one({'UserID': user.id})
        points = abs(points)
        if entry:
            current_amount = entry.get('current') or 0
        else:
            await collection.insert_one({'UserID': user.id})
            current_amount = 0
        current_amount -= points
        xp_data = {'current': current_amount}
        update_target = {'UserID': user.id}
        update_data = {'$set': xp_data}
        await collection.update_one(update_target, update_data)

    async def get_inventory(self, user):
        inventory = await self[self.db_cfg.database
                               ]['Inventory'].find_one({'UserID': user.id})
        if not inventory:
            await self[self.db_cfg.database]['Inventory'].insert_one({
                'UserID':
                user.id,
                'Items': []
            })
            inventory = []
        else:
            inventory = inventory.get('Items')
        return inventory

    async def update_inv(self, user, inv):
        await self[self.db_cfg.database
                   ]['Inventory'].update_one({'UserID': user.id},
                                             {'$set': {
                                                 'Items': inv
                                             }})

    async def add_to_inventory(self, user, item_data):
        sabotage_file = await self[
            self.db_cfg.database].SabotagedUsers.find_one({'UserID': user.id})
        if not sabotage_file:
            stamp = arrow.utcnow().timestamp
            item_data.update({'Timestamp': stamp})
            inv = await self.get_inventory(user)
            inv.append(item_data)
            await self.update_inv(user, inv)

    async def del_from_inventory(self, user, item_id):
        inv = await self.get_inventory(user)
        for item in inv:
            if item['item_id'] == item_id:
                inv.remove(item)
        await self.update_inv(user, inv)

    async def get_inventory_item(self, user, item_file_id):
        inv = await self.get_inventory(user)
        output = None
        for item in inv:
            if item['item_file_id'].lower() == item_file_id.lower():
                output = item
                break
        return output