Beispiel #1
0
    async def fetch_filled_fields(self, db) -> typing.Dict[uuid.UUID, FilledField]:
        """Fetch the fields for this profile and store them in .all_filled_fields"""

        if self.template is None or len(self.template.all_fields) == 0:
            await self.fetch_template(db, fetch_fields=True)
        field_rows = await db("SELECT * FROM filled_field WHERE user_id=$1 AND name=$2 AND field_id=ANY($3::UUID[])", self.user_id, self.name, self.template.all_fields.keys())
        self.all_filled_fields.clear()
        for f in field_rows:
            filled = FilledField(**f)
            filled.field = self.template.all_fields[filled.field_id]
            self.all_filled_fields[filled.field_id] = filled
        return self.all_filled_fields
Beispiel #2
0
    async def startup(self):
        """Clears all the bot's caches and fills them from a DB read"""

        # Remove caches
        self.logger.debug("Clearing caches")
        self.guild_settings.clear()
        Field.all_fields.clear()
        Field.all_profile_fields.clear()
        FilledField.all_filled_fields.clear()
        Profile.all_guilds.clear()
        Profile.all_profiles.clear()
        UserProfile.all_profiles.clear()

        # Get database connection
        db = await self.database.get_connection()

        # Get stored prefixes
        try:
            guild_data = await db("SELECT * FROM guild_settings")
        except Exception as e:
            self.logger.critical(f"Error selecting from guild_settings - {e}")
            exit(1)
        for row in guild_data:
            self.guild_settings[row['guild_id']] = dict(row)

        # Fill caches
        fields = await db('SELECT * FROM field')
        filled_fields = await db('SELECT * FROM filled_field')
        profiles = await db('SELECT * FROM profile')
        user_profiles = await db('SELECT * FROM created_profile')

        if fields:
            for i in fields:
                Field(**i)
        if filled_fields:
            for i in filled_fields:
                FilledField(**i)
        if profiles:
            for i in profiles:
                Profile(**i)
        if user_profiles:
            for i in user_profiles:
                UserProfile(**i)

        # Wait for the bot to cache users before continuing
        self.logger.debug(
            "Waiting until ready before completing startup method.")
        await self.wait_until_ready()

        # Close database connection
        await db.disconnect()
Beispiel #3
0
    async def startup(self):
        '''
        Resets and fills the FamilyTreeMember cache with objects
        '''

        # Remove caches
        LOGGER.debug("Clearing caches")
        Field.all_fields.clear()
        Field.all_profile_fields.clear()
        FilledField.all_filled_fields.clear()
        Profile.all_guilds.clear()
        Profile.all_profiles.clear()
        UserProfile.all_profiles.clear()

        # Fill caches
        async with self.database() as db:
            fields = await db('SELECT * FROM field')
            filled_fields = await db('SELECT * FROM filled_field')
            profiles = await db('SELECT * FROM profile')
            user_profiles = await db('SELECT * FROM created_profile')

        if fields:
            for i in fields:
                Field(**i)
        if filled_fields:
            for i in filled_fields:
                FilledField(**i)
        if profiles:
            for i in profiles:
                Profile(**i)
        if user_profiles:
            for i in user_profiles:
                UserProfile(**i)

        # Wait for the bot to cache users before continuing
        LOGGER.debug("Waiting until ready before completing startup method.")
        await self.wait_until_ready()
Beispiel #4
0
    async def setprofilemeta(self, ctx: Context, profile: Profile,
                             target_user: Member):
        """Talks a user through setting up a profile on a given server"""

        # Set up some variaballlales
        user = ctx.author
        target_user = target_user or user
        fields = profile.fields

        # Check if they're setting someone else's profile and they're not a mod
        if target_user != ctx.author and not member_is_moderator(
                ctx.bot, ctx.author):
            await ctx.send(
                f"You're missing the `manage_roles` permission required to do this."
            )
            return

        # Check if they already have a profile set
        user_profile = profile.get_profile_for_member(target_user)
        if user_profile is not None:
            await ctx.send(
                f"{'You' if target_user == user else target_user.mention} already {'have' if target_user == user else 'has'} a profile set for `{profile.name}`."
            )
            return

        # See if you we can send them the PM
        try:
            await user.send(
                f"Now talking you through setting up a `{profile.name}` profile{' for ' + target_user.mention if target_user != user else ''}."
            )
            await ctx.send("Sent you a PM!")
        except Exception:
            await ctx.send(
                "I'm unable to send you PMs to set up the profile :/")
            return

        # Talk the user through each field
        filled_fields = []
        for field in fields:
            await user.send(field.prompt)

            # User text input
            if isinstance(field.field_type, (TextField, NumberField)):
                check = lambda m: m.author == user and isinstance(
                    m.channel, DMChannel)
                while True:
                    try:
                        m = await self.bot.wait_for('message',
                                                    check=check,
                                                    timeout=field.timeout)
                    except AsyncTimeoutError:
                        await user.send(
                            f"Your input for this field has timed out. Please try running `set{profile.name}` on your server again."
                        )
                        return
                    try:
                        field.field_type.check(m.content)
                        field_content = m.content
                        break
                    except FieldCheckFailure as e:
                        await user.send(e.message)

            # Image input
            elif isinstance(field.field_type, ImageField):
                check = lambda m: m.author == user and isinstance(
                    m.channel, DMChannel)
                while True:
                    try:
                        m = await self.bot.wait_for('message',
                                                    check=check,
                                                    timeout=field.timeout)
                    except AsyncTimeoutError:
                        await user.send(
                            f"Your input for this field has timed out. Please try running `set{profile.name}` on your server again."
                        )
                        return
                    try:
                        if m.attachments:
                            content = m.attachments[0].url
                        else:
                            content = m.content
                        field.field_type.check(content)
                        field_content = content
                        break
                    except FieldCheckFailure as e:
                        await user.send(e.message)

            # Invalid field type apparently
            else:
                raise Exception(
                    f"Field type {field.field_type} is not catered for")

            # Add field to list
            filled_fields.append(
                FilledField(target_user.id, field.field_id, field_content))

        # Make the UserProfile object
        up = UserProfile(target_user.id, profile.profile_id,
                         profile.verification_channel_id == None)

        # Make sure the bot can send the embed at all
        try:
            await user.send(embed=up.build_embed())
        except Exception as e:
            await user.send(
                f"Your profile couldn't be sent to you - `{e}`.\nPlease try again later."
            )
            return

        # Make sure the bot can send the embed to the channel
        if profile.verification_channel_id:
            try:
                channel = await self.bot.fetch_channel(
                    profile.verification_channel_id)
                embed = up.build_embed()
                embed.set_footer(
                    text=f'{profile.name.upper()} // Verification Check')
                v = await channel.send(
                    f"New **{profile.name}** submission from {target_user.mention}\n{target_user.id}/{profile.profile_id}",
                    embed=embed)
                await v.add_reaction(self.TICK_EMOJI)
                await v.add_reaction(self.CROSS_EMOJI)
            except Exception as e:
                await user.send(
                    f"Your profile couldn't be send to the verification channel? - `{e}`."
                )
                return

        # Database me up daddy
        async with self.bot.database() as db:
            try:
                await db(
                    'INSERT INTO created_profile (user_id, profile_id, verified) VALUES ($1, $2, $3)',
                    up.user_id, up.profile.profile_id, up.verified)
            except UniqueViolationError:
                await db(
                    'UPDATE created_profile SET verified=$3 WHERE user_id=$1 AND profile_id=$2',
                    up.user_id, up.profile.profile_id, up.verified)
                await db(
                    'DELETE FROM filled_field WHERE user_id=$1 AND field_id in (SELECT field_id FROM field WHERE profile_id=$2)',
                    up.user_id, up.profile.profile_id)
                self.log_handler.warn(
                    f"Deleted profile for {up.user_id} on UniqueViolationError"
                )
            for field in filled_fields:
                await db(
                    'INSERT INTO filled_field (user_id, field_id, value) VALUES ($1, $2, $3)',
                    field.user_id, field.field_id, field.value)

        # Respond to user
        await user.send("Your profile has been created and saved.")