def __init__(self, bot:utils.Bot): super().__init__(bot) self._channels = [] # Populated automatically # Set up our redis handlers baybee task = bot.loop.create_task self.handlers = [ task(self.channel_handler('DBLVote', lambda data: bot.dbl_votes.__setitem__(data['user_id'], dt.strptime(data['datetime'], "%Y-%m-%dT%H:%M:%S.%f")))), task(self.channel_handler('ProposalCacheAdd', lambda data: bot.proposal_cache.raw_add(**data))), task(self.channel_handler('ProposalCacheRemove', lambda data: bot.proposal_cache.raw_remove(*data))), task(self.channel_handler('BlockedUserAdd', lambda data: bot.blocked_users[data['user_id']].append(data['blocked_user_id']))), task(self.channel_handler('BlockedUserRemove', lambda data: bot.blocked_users[data['user_id']].remove(data['blocked_user_id']))), task(self.channel_handler('EvalAll', self.eval_all)), task(self.channel_handler('UpdateGuildPrefix', self.update_guild_prefix)), task(self.channel_handler('UpdateFamilyMaxMembers', self.update_max_family_members)), task(self.channel_handler('UpdateIncestAllowed', self.update_incest_alllowed)), task(self.channel_handler('UpdateMaxChildren', self.update_max_children)), task(self.channel_handler('UpdateGifsEnabled', self.update_gifs_enabled)), task(self.channel_handler('SendUserMessage', self.send_user_message)), task(self.channel_handler('AddGoldUser', self.add_gold_user)), ] # if not self.bot.is_server_specific: self.handlers.extend([ task(self.channel_handler('TreeMemberUpdate', lambda data: utils.FamilyTreeMember(**data))), ])
async def recachefamily(self, ctx:utils.Context, user:utils.converters.UserID, guild_id:int=0): """Recaches a user's family tree member object, but through their whole family""" # Get connections db = await self.bot.database.get_connection() re = await self.bot.redis.get_connection() # Loop through their tree family = utils.FamilyTreeMember.get(user, guild_id).span(expand_upwards=True, add_parent=True)[:] for i in family: parent = await db('SELECT parent_id FROM parents WHERE child_id=$1 AND guild_id=$2', i.id, guild_id) children = await db('SELECT child_id FROM parents WHERE parent_id=$1 AND guild_id=$2', i.id, guild_id) partner = await db('SELECT partner_id FROM marriages WHERE user_id=$1 AND guild_id=$2', i.id, guild_id) # Load data into cache children = [i['child_id'] for i in children] parent_id = parent[0]['parent_id'] if len(parent) > 0 else None partner_id = partner[0]['partner_id'] if len(partner) > 0 else None f = utils.FamilyTreeMember( i.id, children=children, parent_id=parent_id, partner_id=partner_id, guild_id=guild_id, ) # Push update via redis await re.publish_json('TreeMemberUpdate', f.to_json()) # Disconnect from database await db.disconnect() await re.disconnect() # Output to user await ctx.send(f"Published `{len(family)}` updates.")
async def recache(self, ctx:utils.Context, user:utils.converters.UserID, guild_id:int=0): """Recaches a user's family tree member object""" # Read data from DB async with self.bot.database() as db: parent = await db('SELECT parent_id FROM parents WHERE child_id=$1 AND guild_id=$2', user, guild_id) children = await db('SELECT child_id FROM parents WHERE parent_id=$1 AND guild_id=$2', user, guild_id) partner = await db('SELECT partner_id FROM marriages WHERE user_id=$1 AND guild_id=$2', user, guild_id) # Load data into cache children = [i['child_id'] for i in children] parent_id = parent[0]['parent_id'] if len(parent) > 0 else None partner_id = partner[0]['partner_id'] if len(partner) > 0 else None f = utils.FamilyTreeMember( user, children=children, parent_id=parent_id, partner_id=partner_id, guild_id=guild_id, ) # Push update via redis async with self.bot.redis() as re: await re.publish_json('TreeMemberUpdate', f.to_json()) # Output to user await ctx.send("Published update for user.")
def handle_partner(row): utils.FamilyTreeMember( discord_id=row['user_id'], children=[], parent_id=None, partner_id=row['partner_id'], guild_id=row['guild_id'], )
async def cache_setup(self, db): """ Set up the cache for the users. """ # Get family data from database try: if self.bot.config['is_server_specific']: partnerships = await db( "SELECT * FROM marriages WHERE guild_id<>0") parents = await db("SELECT * FROM parents WHERE guild_id<>0") else: partnerships = await db( "SELECT * FROM marriages WHERE guild_id=0") parents = await db("SELECT * FROM parents WHERE guild_id=0") except Exception as e: self.logger.critical( f"Ran into an error selecting either marriages or parents: {e}" ) exit(1) # Clear the current cache self.logger.info(f"Clearing the cache of all family tree members") localutils.FamilyTreeMember.all_users.clear() # Cache the family data - partners self.logger.info( f"Caching {len(partnerships)} partnerships from partnerships") for i in partnerships: localutils.FamilyTreeMember(discord_id=i['user_id'], children=[], parent_id=None, partner_id=i['partner_id'], guild_id=i['guild_id']) # - children self.logger.info( f"Caching {len(parents)} parents/children from parents") for i in parents: parent = localutils.FamilyTreeMember.get(i['parent_id'], i['guild_id']) parent._children.append(i['child_id']) child = localutils.FamilyTreeMember.get(i['child_id'], i['guild_id']) child._parent = i['parent_id'] # And done return True
def __init__(self, bot: utils.CustomBot): super().__init__(bot) self._channels = [] # Populated automatically # Set up our redis handlers baybee task = bot.loop.create_task self.handlers = [ task( self.channel_handler( 'DBLVote', lambda data: bot.dbl_votes.__setitem__( data['user_id'], dt.strptime(data['datetime'], "%Y-%m-%dT%H:%M:%S.%f"))) ), task( self.channel_handler( 'ProposalCacheAdd', lambda data: bot.proposal_cache.raw_add(**data))), task( self.channel_handler( 'ProposalCacheRemove', lambda data: bot.proposal_cache.raw_remove(*data))), task( self.channel_handler( 'BlockedUserAdd', lambda data: bot.blocked_users[data[ 'user_id'].append(data['blocked_user_id'])])), task( self.channel_handler( 'BlockedUserRemove', lambda data: bot.blocked_users[data[ 'user_id'].remove(data['blocked_user_id'])])), task(self.channel_handler('EvalAll', self.eval_all)), task( self.channel_handler('UpdateGuildPrefix', self.update_guild_prefix)), ] # if not self.bot.is_server_specific: self.handlers.extend([ task( self.channel_handler( 'TreeMemberUpdate', lambda data: utils.FamilyTreeMember(**data))), ])
def tree_member_update(self, payload): utils.FamilyTreeMember(**payload)
async def startup(self): """The startup method for the bot - clears all the caches and reads everything out again from the database, essentially starting anew as if rebooted""" # Remove caches self.logger.debug("Clearing family tree member cache") utils.FamilyTreeMember.all_users.clear() self.logger.debug("Clearing blacklisted guilds cache") self.blacklisted_guilds.clear() self.logger.debug("Clearing guild settings cache") self.guild_settings.clear() self.logger.debug("Clearing DBL votes cache") self.dbl_votes.clear() self.logger.debug("Clearing blocked users cache") self.blocked_users.clear() self.logger.debug("Clearing random text cache") utils.random_text.RandomText.original.all_random_text.clear() # Grab a database connection db: utils.DatabaseConnection = await self.database.get_connection() # Load in all of the random text try: random_text = await db('SELECT * FROM random_text') except Exception as e: self.logger.critical( f"Ran into an errorr selecting random text: {e}") exit(1) self.logger.debug(f"Caching {len(random_text)} lines of random text") for row in random_text: utils.random_text.RandomText.original.all_random_text[ row['command_name']][row['event_name']].append(row['string']) # Pick up the blacklisted guilds from the db try: blacklisted = await db('SELECT * FROM blacklisted_guilds') except Exception as e: self.logger.critical( f"Ran into an error selecting blacklisted guilds: {e}") exit(1) self.logger.debug(f"Caching {len(blacklisted)} blacklisted guilds") self.blacklisted_guilds = [i['guild_id'] for i in blacklisted] # Pick up the blocked users try: blocked = await db('SELECT * FROM blocked_user') except Exception as e: self.logger.critical( f"Ran into an error selecting blocked users: {e}") exit(1) self.logger.debug(f"Caching {len(blocked)} blocked users") for user in blocked: self.blocked_users[user['user_id']].append(user['blocked_user_id']) # Grab the command prefixes per guild try: all_settings = await db('SELECT * FROM guild_settings') except Exception as e: self.logger.critical( f"Ran into an error selecting guild settings: {e}") exit(1) self.logger.debug(f"Caching {len(all_settings)} guild settings") for items in all_settings: current_settings = self.guild_settings[ items] # Get current (which should include defaults) current_settings.update(**dict(items)) # Update from db if self.is_server_specific: current_settings['prefix'] = current_settings['gold_prefix'] self.guild_settings[items['guild_id']] = current_settings # Cache # Grab the last vote times of each user try: votes = await db( "SELECT * FROM dbl_votes WHERE timestamp > NOW() - INTERVAL '12 hours'" ) except Exception as e: self.logger.critical(f"Ran into an error selecting DBL votes: {e}") exit(1) self.logger.debug(f"Caching {len(votes)} DBL votes") for v in votes: self.dbl_votes[v['user_id']] = v['timestamp'] # Wait for the bot to cache users before continuing self.logger.debug( "Waiting until ready before completing startup method.") await self.wait_until_ready() # Look through and find what servers the bot is allowed to be on, if server specific if self.is_server_specific: try: allowed_guilds = await db( 'SELECT guild_id FROM guild_specific_families') except Exception as e: self.logger.critical( f"Ran into an error selecting server specific guilds: {e}") exit(1) allowed_guild_ids = [i['guild_id'] for i in allowed_guilds] current_guild_ids = self._connection._guilds.keys() guild_ids_to_leave = [ i for i in current_guild_ids if i not in allowed_guild_ids ] for guild_id in guild_ids_to_leave: guild = self.get_guild(guild_id) self.logger.warn( f"Automatically left guild {guild.name} ({guild.id}) for non-subscription" ) await guild.leave() # Get family data from database try: if self.is_server_specific: partnerships = await db( 'SELECT * FROM marriages WHERE guild_id<>0') parents = await db('SELECT * FROM parents WHERE guild_id<>0') else: partnerships = await db( 'SELECT * FROM marriages WHERE guild_id=0') parents = await db('SELECT * FROM parents WHERE guild_id=0') except Exception as e: self.logger.critical( f"Ran into an error selecting either marriages or parents: {e}" ) exit(1) # Cache the family data - partners self.logger.debug( f"Caching {len(partnerships)} partnerships from partnerships") for i in partnerships: utils.FamilyTreeMember(discord_id=i['user_id'], children=[], parent_id=None, partner_id=i['partner_id'], guild_id=i['guild_id']) # - children self.logger.debug( f"Caching {len(parents)} parents/children from parents") for i in parents: parent = utils.FamilyTreeMember.get(i['parent_id'], i['guild_id']) parent._children.append(i['child_id']) child = utils.FamilyTreeMember.get(i['child_id'], i['guild_id']) child._parent = i['parent_id'] # Disconnect from the database await db.disconnect() # Save all available names to redis async with self.redis() as re: for user in self.users: await re.set(f'UserName-{user.id}', str(user)) # And update DBL await self.post_guild_count()