Esempio n. 1
0
    async def copulate(self, ctx: vbu.Context, target: discord.Member):
        """
        Lets you... um... heck someone.
        """

        # Variables we're gonna need for later
        family_guild_id = utils.get_family_guild_id(ctx)
        author_tree, target_tree = utils.FamilyTreeMember.get_multiple(
            ctx.author.id, target.id, guild_id=family_guild_id)

        # Check they're not a bot
        if target.id == self.bot.user.id:
            return await ctx.send("Ew. No. Thanks.", wait=False)
        if target.id == ctx.author.id:
            return

        # See if they're already related
        async with ctx.typing():
            relation = author_tree.get_relation(target_tree)
        if relation and relation != "partner" and utils.guild_allows_incest(
                ctx) is False:
            return await ctx.send(
                f"Woah woah woah, it looks like you guys are related! {target.mention} is your {relation}!",
                allowed_mentions=utils.only_mention(ctx.author),
                wait=False,
            )

        # Set up the proposal
        if target.id != ctx.author.id:
            try:
                result = await utils.send_proposal_message(
                    ctx,
                    target,
                    f"Hey, {target.mention}, {ctx.author.mention} do you wanna... smash? \N{SMIRKING FACE}",
                    allow_bots=True,
                )
            except Exception:
                result = None
        if result is None:
            return

        # Respond
        await result.ctx.send(
            random.choice(utils.random_text.Copulate.VALID).format(
                author=ctx.author, target=target),
            wait=False,
        )
Esempio n. 2
0
    async def makeparent(self, ctx: utils.Context, *,
                         target: localutils.converters.UnblockedMember):
        """
        Picks a user that you want to be your parent.
        """

        # Variables we're gonna need for later
        family_guild_id = localutils.get_family_guild_id(ctx)
        author_tree, target_tree = localutils.FamilyTreeMember.get_multiple(
            ctx.author.id, target.id, guild_id=family_guild_id)

        # Check they're not themselves
        if target.id == ctx.author.id:
            return await ctx.send(
                "That's you. You can't make yourself your parent.")

        # Check they're not a bot
        if target.id == self.bot.user.id:
            return await ctx.send(
                "I think I could do better actually, but thank you!")

        # Lock those users
        re = await self.bot.redis.get_connection()
        try:
            lock = await localutils.ProposalLock.lock(re, ctx.author.id,
                                                      target.id)
        except localutils.ProposalInProgress:
            return await ctx.send(
                "Aren't you popular! One of you is already waiting on a proposal - please try again later."
            )

        # See if the *target* is already married
        if author_tree.parent:
            await lock.unlock()
            return await ctx.send(
                f"Hey! {ctx.author.mention}, you already have a parent \N{ANGRY FACE}",
                allowed_mentions=localutils.only_mention(ctx.author),
            )

        # See if we're already married
        if ctx.author.id in target_tree._children:
            await lock.unlock()
            return await ctx.send(
                f"Hey isn't {target.mention} already your child? \N{FACE WITH ROLLING EYES}",
                allowed_mentions=localutils.only_mention(ctx.author),
            )

        # See if they're already related
        async with ctx.channel.typing():
            relation = author_tree.get_relation(target_tree)
        if relation and localutils.guild_allows_incest(ctx) is False:
            await lock.unlock()
            return await ctx.send(
                f"Woah woah woah, it looks like you guys are already related! {target.mention} is your {relation}!",
                allowed_mentions=localutils.only_mention(ctx.author),
            )

        # Manage children
        children_amount = await self.get_max_children_for_member(
            ctx.guild, target)
        if len(author_tree._children) >= children_amount:
            return await ctx.send(
                f"You're currently at the maximum amount of children you can have - see `{ctx.prefix}perks` for more information."
            )

        # Check the size of their trees
        # TODO I can make this a util because I'm going to use it a couple times
        max_family_members = localutils.get_max_family_members(ctx)
        async with ctx.channel.typing():
            family_member_count = 0
            for i in author_tree.span(add_parent=True, expand_upwards=True):
                if family_member_count >= max_family_members:
                    break
                family_member_count += 1
            for i in target_tree.span(add_parent=True, expand_upwards=True):
                if family_member_count >= max_family_members:
                    break
                family_member_count += 1
            if family_member_count >= max_family_members:
                await lock.unlock()
                return await ctx.send(
                    f"If you added {target.mention} to your family, you'd have over {max_family_members} in your family. Sorry!",
                    allowed_mentions=localutils.only_mention(ctx.author),
                )

        # Set up the proposal
        try:
            result = await localutils.send_proposal_message(
                ctx,
                target,
                f"Hey, {target.mention}, {ctx.author.mention} wants to be your child! What do you think?",
                allow_bots=True,
            )
        except Exception:
            result = None
        if result is None:
            return await lock.unlock()

        # Database it up
        async with self.bot.database() as db:
            try:
                await db(
                    """INSERT INTO parents (parent_id, child_id, guild_id, timestamp) VALUES ($1, $2, $3, $4)""",
                    target.id,
                    ctx.author.id,
                    family_guild_id,
                    dt.utcnow(),
                )
            except asyncpg.UniqueViolationError:
                await lock.unlock()
                return await ctx.send(
                    "I ran into an error saving your family data - please try again later."
                )
        await ctx.send(
            f"I'm happy to introduce {ctx.author.mention} as your child, {target.mention}!",
            ignore_error=True)

        # And we're done
        target_tree._children.append(author_tree.id)
        author_tree._parent = target.id
        await re.publish('TreeMemberUpdate', author_tree.to_json())
        await re.publish('TreeMemberUpdate', target_tree.to_json())
        await re.disconnect()
        await lock.unlock()
Esempio n. 3
0
    async def propose(self, ctx:utils.Context, *, target:localutils.converters.UnblockedMember):
        """
        Lets you propose to another Discord user.
        """

        # Get the family tree member objects
        family_guild_id = localutils.get_family_guild_id(ctx)
        author_tree, target_tree = localutils.FamilyTreeMember.get_multiple(ctx.author.id, target.id, guild_id=family_guild_id)

        # Check they're not themselves
        if target.id == ctx.author.id:
            return await ctx.send("That's you. You can't marry yourself.")

        # Check they're not a bot
        if target.bot:
            if target.id == self.bot.user.id:
                return await ctx.send("I think I could do better actually, but thank you!")
            return await ctx.send("That is a robot. Robots cannot consent to marriage.")

        # Lock those users
        re = await self.bot.redis.get_connection()
        try:
            lock = await localutils.ProposalLock.lock(re, ctx.author.id, target.id)
        except localutils.ProposalInProgress:
            return await ctx.send("Aren't you popular! One of you is already waiting on a proposal - please try again later.")

        # See if we're already married
        if author_tree._partner:
            await lock.unlock()
            return await ctx.send(
                f"Hey, {ctx.author.mention}, you're already married! Try divorcing your partner first \N{FACE WITH ROLLING EYES}",
                allowed_mentions=localutils.only_mention(ctx.author),
            )

        # See if the *target* is already married
        if target_tree._partner:
            await lock.unlock()
            return await ctx.send(
                f"Sorry, {ctx.author.mention}, it looks like {target.mention} is already married \N{PENSIVE FACE}",
                allowed_mentions=localutils.only_mention(ctx.author),
            )

        # See if they're already related
        async with ctx.channel.typing():
            relation = author_tree.get_relation(target_tree)
        if relation and localutils.guild_allows_incest(ctx) is False:
            await lock.unlock()
            return await ctx.send(
                f"Woah woah woah, it looks like you guys are already related! {target.mention} is your {relation}!",
                allowed_mentions=localutils.only_mention(ctx.author),
            )

        # Check the size of their trees
        # TODO I can make this a util because I'm going to use it a couple times
        max_family_members = localutils.get_max_family_members(ctx)
        async with ctx.channel.typing():
            family_member_count = 0
            for i in author_tree.span(add_parent=True, expand_upwards=True):
                if family_member_count >= max_family_members:
                    break
                family_member_count += 1
            for i in target_tree.span(add_parent=True, expand_upwards=True):
                if family_member_count >= max_family_members:
                    break
                family_member_count += 1
            if family_member_count >= max_family_members:
                await lock.unlock()
                return await ctx.send(
                    f"If you added {target.mention} to your family, you'd have over {max_family_members} in your family. Sorry!",
                    allowed_mentions=localutils.only_mention(ctx.author),
                )

        # Set up the proposal
        try:
            result = await localutils.send_proposal_message(
                ctx, target,
                f"Hey, {target.mention}, it would make {ctx.author.mention} really happy if you would marry them. What do you say?",
            )
        except Exception:
            result = None
        if result is None:
            return await lock.unlock()

        # They said yes!
        async with self.bot.database() as db:
            try:
                await db.start_transaction()
                await db(
                    "INSERT INTO marriages (user_id, partner_id, guild_id, timestamp) VALUES ($1, $2, $3, $4), ($2, $1, $3, $4)",
                    ctx.author.id, target.id, family_guild_id, dt.utcnow(),
                )
                await db.commit_transaction()
            except asyncpg.UniqueViolationError:
                await lock.unlock()
                return await ctx.send("I ran into an error saving your family data.")
        await ctx.send(f"I'm happy to introduce {target.mention} into the family of {ctx.author.mention}!")

        # Ping over redis
        author_tree._partner = target.id
        target_tree._partner = ctx.author.id
        await re.publish('TreeMemberUpdate', author_tree.to_json())
        await re.publish('TreeMemberUpdate', target_tree.to_json())
        await re.disconnect()
        await lock.unlock()