async def copulate(self, ctx:utils.Context, user:discord.Member): """Lets you... um... heck someone""" # Check for the most common catches text_processor = utils.random_text.RandomText('copulate', ctx.author, user) text = text_processor.process(check_for_instigator=False) if text: return await ctx.send(text) # Check if they are related x = utils.FamilyTreeMember.get(ctx.author.id, ctx.family_guild_id) y = utils.FamilyTreeMember.get(user.id, ctx.family_guild_id) async with ctx.channel.typing(): relationship = x.get_relation(y) if relationship is None or relationship.casefold() == 'partner' or self.bot.allows_incest(ctx.guild.id): pass else: return await ctx.send(text_processor.target_is_family()) # Ping out a message for them await ctx.send(text_processor.valid_target()) # Wait for a response try: check = utils.AcceptanceCheck(user.id, ctx.channel.id).check m = await self.bot.wait_for('message', check=check, timeout=60.0) response = check(m) except asyncio.TimeoutError: return await ctx.send(text_processor.request_timeout(), ignore_error=True) # Process response if response == "NO": return await ctx.send(text_processor.request_denied()) await ctx.send(text_processor.request_accepted())
async def propose(self, ctx: utils.Context, *, target: utils.converters.UnblockedMember): """Lets you propose to another Discord user""" # Variables we're gonna need for later instigator = ctx.author instigator_tree = utils.FamilyTreeMember.get(instigator.id, ctx.family_guild_id) target_tree = utils.FamilyTreeMember.get(target.id, ctx.family_guild_id) # Manage output strings text_processor = utils.random_text.RandomText('propose', instigator, target) text = text_processor.process() if text: return await ctx.send(text) # See if our user is already married if instigator_tree._partner: return await ctx.send(text_processor.instigator_is_unqualified()) # See if the *target* is already married if target_tree._partner: return await ctx.send(text_processor.target_is_unqualified()) # See if they're already related async with ctx.channel.typing(): relation = instigator_tree.get_relation(target_tree) if relation and not self.bot.allows_incest(ctx.guild.id): return await ctx.send(text_processor.target_is_family()) # Check the size of their trees max_family_members = self.bot.guild_settings[ ctx.guild.id]['max_family_members'] async with ctx.channel.typing(): if instigator_tree.family_member_count + target_tree.family_member_count > max_family_members: return await ctx.send( f"If you added {target.mention} to your family, you'd have over {max_family_members} in your family, so I can't allow you to do that. Sorry!" ) # Neither are married, set up the proposal await ctx.send(text_processor.valid_target()) await self.bot.proposal_cache.add(instigator, target, 'MARRIAGE') # Wait for a response check = utils.AcceptanceCheck(target.id, ctx.channel.id) try: await check.wait_for_response(self.bot) except utils.AcceptanceCheck.TIMEOUT: return await ctx.send(text_processor.request_timeout(), ignore_error=True) # They said no if check.response == 'NO': await self.bot.proposal_cache.remove(instigator, target) return await ctx.send(text_processor.request_denied(), ignore_error=True) # They said yes! async with self.bot.database() as db: await db.marry(instigator, target, ctx.family_guild_id) await ctx.send(text_processor.request_accepted(), ignore_error=True) # Cache values locally instigator_tree._partner = target.id target_tree._partner = instigator.id # Ping em off over redis async with self.bot.redis() as re: await re.publish_json('TreeMemberUpdate', instigator_tree.to_json()) await re.publish_json('TreeMemberUpdate', target_tree.to_json()) # Remove users from proposal cache await self.bot.proposal_cache.remove(instigator, target)
async def makeparent(self, ctx: utils.Context, *, target: utils.converters.UnblockedMember): """Picks a user that you want to be your parent""" # Variables we're gonna need for later instigator = ctx.author instigator_tree = utils.FamilyTreeMember.get(instigator.id, ctx.family_guild_id) target_tree = utils.FamilyTreeMember.get(target.id, ctx.family_guild_id) # Manage output strings text_processor = utils.random_text.RandomText('makeparent', instigator, target) text = text_processor.process() if text: return await ctx.send(text) # See if our user already has a parent if instigator_tree._parent: return await ctx.send(text_processor.instigator_is_unqualified()) # See if they're already related async with ctx.channel.typing(): relation = instigator_tree.get_relation(target_tree) if relation and not self.bot.allows_incest(ctx.guild.id): return await ctx.send(text_processor.target_is_family()) # Manage children if ctx.original_author_id not in self.bot.owner_ids: children_amount = await self.get_max_children_for_member( ctx.guild, target) if len(target_tree._children) >= children_amount: return await ctx.send( "They're currently at the maximum amount of children you can have - see `m!perks` for more information." ) # Check the size of their trees if ctx.original_author_id not in self.bot.owner_ids: max_family_members = self.bot.get_max_family_members(ctx.guild) async with ctx.channel.typing(): if instigator_tree.family_member_count + target_tree.family_member_count > max_family_members: return await ctx.send( f"If you added {target.mention} to your family, you'd have over {max_family_members} in your family, so I can't allow you to do that. Sorry!" ) # Valid request - ask the other person if not target.bot: await ctx.send(text_processor.valid_target()) await self.bot.proposal_cache.add(instigator, target, 'MAKEPARENT') check = utils.AcceptanceCheck(target.id, ctx.channel.id) try: await check.wait_for_response(self.bot) except utils.AcceptanceCheck.TIMEOUT: return await ctx.send(text_processor.request_timeout(), ignore_error=True) # They said no if check.response == 'NO': await self.bot.proposal_cache.remove() return await ctx.send(text_processor.request_denied(), ignore_error=True) # They said yes async with self.bot.database() as db: try: await db( 'INSERT INTO parents (child_id, parent_id, guild_id, timestamp) VALUES ($1, $2, $3, $4)', instigator.id, target.id, ctx.family_guild_id, dt.utcnow()) except asyncpg.UniqueViolationError: return await ctx.send( "I ran into an error saving your family data - please try again later." ) await ctx.send(text_processor.request_accepted(), ignore_error=True) # Cache instigator_tree._parent = target.id target_tree._children.append(instigator.id) # Ping em off over redis async with self.bot.redis() as re: await re.publish_json('TreeMemberUpdate', instigator_tree.to_json()) await re.publish_json('TreeMemberUpdate', target_tree.to_json()) # Uncache await self.bot.proposal_cache.remove(instigator, target)
async def adopt(self, ctx: utils.Context, *, target: utils.converters.UnblockedMember): """Adopt another user into your family""" # Variables we're gonna need for later instigator = ctx.author instigator_tree = utils.FamilyTreeMember.get(instigator.id, ctx.family_guild_id) target_tree = utils.FamilyTreeMember.get(target.id, ctx.family_guild_id) # Manage output strings text_processor = utils.random_text.RandomText('adopt', instigator, target) text = text_processor.process() if text: return await ctx.send(text) # See if our user already has a parent if target_tree._parent: return await ctx.send(text_processor.target_is_unqualified()) # See if the target is a bot if target.bot: return await ctx.send(text_processor.target_is_bot()) # See if they're already related async with ctx.channel.typing(): relation = instigator_tree.get_relation(target_tree) if relation and not self.bot.allows_incest(ctx.guild.id): return await ctx.send(text_processor.target_is_family()) # Manage children if self.bot.is_server_specific: guild_max_children = self.bot.guild_settings[ ctx.guild.id]['max_children'] if guild_max_children: gold_children_amount = max([ amount if int(role_id) in ctx.author._roles else 0 for role_id, amount in guild_max_children.items() ]) else: gold_children_amount = 0 else: gold_children_amount = 0 normal_children_amount = self.bot.config['max_children'][ await utils.checks.get_patreon_tier(self.bot, ctx.author)] children_amount = min([ max([ gold_children_amount, normal_children_amount, self.bot.config['max_children'][0] ]), self.bot.config['max_children'][-1] ]) if len(instigator_tree._children) >= children_amount: return await ctx.send( f"You're currently at the maximum amount of children you can have - see `m!perks` for more information." ) # Check the size of their trees max_family_members = self.bot.guild_settings[ ctx.guild.id]['max_family_members'] async with ctx.channel.typing(): if instigator_tree.family_member_count + target_tree.family_member_count > max_family_members: return await ctx.send( f"If you added {target.mention} to your family, you'd have over {max_family_members} in your family, so I can't allow you to do that. Sorry!" ) # No parent, send request await ctx.send(text_processor.valid_target()) await self.bot.proposal_cache.add(instigator, target, 'ADOPT') # Wait for a response check = utils.AcceptanceCheck(target.id, ctx.channel.id) try: await check.wait_for_response(self.bot) except utils.AcceptanceCheck.TIMEOUT: return await ctx.send(text_processor.request_timeout(), ignore_error=True) # Valid response recieved, see what their answer was if check.response == 'NO': await self.bot.proposal_cache.remove(instigator, target) return await ctx.send(text_processor.request_denied(), ignore_error=True) # Database it up async with self.bot.database() as db: await db( 'INSERT INTO parents (parent_id, child_id, guild_id, timestamp) VALUES ($1, $2, $3, $4)', instigator.id, target.id, ctx.family_guild_id, dt.utcnow()) # Add family caching instigator_tree._children.append(target.id) target_tree._parent = instigator_tree.id # Ping em off over redis async with self.bot.redis() as re: await re.publish_json('TreeMemberUpdate', instigator_tree.to_json()) await re.publish_json('TreeMemberUpdate', target_tree.to_json()) # Uncache await self.bot.proposal_cache.remove(instigator, target) # Output to user await ctx.send(text_processor.request_accepted(), ignore_error=True)