Example #1
0
    def can_touch_tag(self, ctx: DogbotContext, tag: Tag) -> bool:
        """Returns whether someone can touch a tag (modify, delete, or edit it)."""
        perms = ctx.author.guild_permissions

        predicates = [
            # they can manage the server
            perms.manage_guild,

            # they own the server
            ctx.author.guild.owner == ctx.author,

            # they created the tag
            tag.creator == ctx.author,

            # is dogbot moderator
            checks.member_is_moderator(ctx.author)
        ]

        return any(predicates)
Example #2
0
    def can_touch_tag(self, ctx: commands.Context, tag: Tag) -> bool:
        """ Returns whether someone can touch a tag (modify, delete, or edit it). """
        perms = ctx.author.guild_permissions

        # they can manage the server
        if perms.manage_guild:
            return True

        # they own the server
        if ctx.author.guild.owner == ctx.author:
            return True

        # they created the tag
        if tag.creator == ctx.author:
            return True

        # is dogbot moderator
        if checks.member_is_moderator(ctx.author):
            return True

        return False
Example #3
0
    async def skip(self, ctx):
        """
        Votes to skip this song.

        40% of users in the voice channel must skip in order for the song to be skipped.
        If someone leaves the voice channel, just rerun this command to recalculate the amount
        of votes needed.

        If you are a Dogbot Moderator, the song is skipped instantly.
        """

        state = self.state_for(ctx.guild)

        if not state.is_playing():
            return await ctx.send('I\'m not playing anything at the moment.')

        if checks.member_is_moderator(ctx.author):
            logger.debug('Instantly skipping.')
            state.skip()
            return

        state = self.state_for(ctx.guild)
        existing_votes = state.skip_votes
        voice_members = len(
            state.channel.members)  # how many people in the channel?
        votes_with_this_one = len(
            existing_votes) + 1  # votes with this one counted
        required = required_votes(voice_members)  # how many votes do we need?

        # recalculate amount of users it takes to vote, not counting this vote.
        # (just in case someone left the channel)
        if len(existing_votes) >= required:
            logger.debug('Voteskip: Recalculated. Skipping. %d/%d',
                         len(existing_votes), required)
            state.skip()
            return

        # check if they already voted
        if ctx.author.id in existing_votes:
            return await ctx.send(
                'You already voted to skip. **{}** more vote(s) needed to skip.'
                .format(required - len(existing_votes)))

        # ok, their vote counts. now check if we surpass required votes with this vote!
        if votes_with_this_one >= required:
            logger.debug('Voteskip: Fresh vote! Skipping. %d/%d',
                         votes_with_this_one, required)
            state.skip()
            return

        # add the vote
        state.skip_votes.append(ctx.author.id)

        # how many more?
        more_votes = required - votes_with_this_one
        await ctx.send(
            'Your request to skip this song has been acknowledged. **{}** more vote(s) to '
            'skip.'.format(more_votes))

        logger.debug('Voteskip: Now at %d/%d (%d more needed to skip.)',
                     votes_with_this_one, required, more_votes)
Example #4
0
 async def __local_check(self, ctx):
     return ctx.guild and checks.member_is_moderator(ctx.author)
Example #5
0
    async def profile(self, ctx, *, who: converters.RawUser = None):
        """Shows information about a user."""
        who = who or ctx.author

        embed = discord.Embed(title=f'{who} \N{EM DASH} {who.id}' + (
            ' <:bot:349717107124207617>' if who.bot else ''))
        embed.set_thumbnail(url=who.avatar_url)

        # shared servers
        shared_servers = sum(1 for g in ctx.bot.guilds if who in g.members)
        embed.add_field(name='Shared Servers', value=shared_servers)

        # supporter stuff <3
        if checks.is_supporter(ctx.bot, who):
            async with ctx.acquire() as conn:
                desc = await conn.fetchrow(
                    'SELECT * FROM profile_descriptions WHERE id = $1', who.id)
                if desc:
                    embed.color = discord.Color(desc['color'])
                    embed.add_field(
                        name='Profile Description', value=desc['description'])

        # shortcut for adding a field with ago and absolute datetime info
        def add_joined_field(*, attr, name, **kwargs):
            dt = getattr(who, attr)
            embed.add_field(
                name=name,
                value=f'{utils.ago(dt)}\n{utils.standard_datetime(dt)} UTC',
                **kwargs)

        add_joined_field(
            attr='created_at',
            name='Created' if who.bot else 'Joined Discord',
            inline=False)

        # if this is a member, show extended information
        if isinstance(who, discord.Member):
            add_joined_field(
                attr='joined_at', name='Joined this Server', inline=False)
            roles = ', '.join(
                r.name
                for r in sorted(
                    who.roles, key=lambda r: r.position, reverse=True)
                if r != ctx.guild.default_role)
            embed.add_field(name='Roles', value=roles)
        else:
            # not in server, make sure to note that
            embed.description = "**NOTE:** This user is not in this server."

        # show some mod-related stuff for mods
        if checks.member_is_moderator(ctx.author):
            try:
                # is this person banned?
                entry = discord.utils.find(
                    lambda ban_entry: ban_entry.user == who, await
                    ctx.guild.bans())
                if entry:
                    embed.color = discord.Color.red()
                    reason = f'Reason: {entry.reason}' if entry.reason else 'No reason was provided.'
                    embed.add_field(
                        name='Banned',
                        value=f'**This user has been banned.** {reason}')
            except discord.HTTPException:
                # ignore permission/http errors
                pass

        await ctx.send(embed=embed)