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)
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
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)
async def __local_check(self, ctx): return ctx.guild and checks.member_is_moderator(ctx.author)
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)