async def _limited_disable(self, ctx): '''Disables limited role requests for the guild''' doc = utils.getGuildDoc(ctx.bot, ctx.guild) if doc['requests_opts']['channel'] == None: return await utils.cmdFail( ctx, f'Requests are already disabled for this guild.') utils.guildKeySet(ctx.bot, ctx.guild, 'requests_opts.channel', None) return await utils.cmdSuccess( ctx, f'Requests are now disabled for this guild.')
async def _limited_channel(self, ctx, channel: discord.TextChannel): '''Sets the channel that limited role requests will be posted in''' doc = utils.getGuildDoc(ctx.bot, ctx.guild) if doc['requests_opts']['channel'] == channel.id: return await utils.cmdFail( ctx, f'The requests channel is already {channel}.') utils.guildKeySet(ctx.bot, ctx.guild, 'requests_opts.channel', channel.id) return await utils.cmdSuccess( ctx, f'The requests channel is now {channel}.')
async def _limited_option_toggle(self, ctx, user_setting, setting_key, setting_string): doc = utils.getGuildDoc(ctx.bot, ctx.guild) current = doc['requests_opts'][setting_key] if user_setting is None: user_setting = not current human = 'enabled' if user_setting else 'disabled' if user_setting == current: return await utils.cmdFail( ctx, f'Limited role join command {setting_string} is already **{human}**.' ) utils.guildKeySet(ctx.bot, ctx.guild, f'requests_opts.{setting_key}', user_setting) return await utils.cmdSuccess( ctx, f'Limited role join command {setting_string} is now **{human}**.')
async def _role(self, ctx, role: discord.Role, option: typing.Optional[str]): '''Adds, modifies, or removes a requestable role Adds or removes a role from the server's requestable roles or modifies an existing requestable roles type.''' doc = utils.getGuildDoc(ctx.bot, ctx.guild) options = { 'open': ['open', 'o'], 'limited': ['limited', 'limit', 'l'], 'remove': ['delete', 'del', 'd', 'remove', 'rem', 'r'], 'add': ['add', 'a'] # Option resolves to 'open' but only for new roles. } resolved_option = None for key, val in options.items(): if option in val: resolved_option = key if option and not resolved_option: return await utils.cmdFail(ctx, f'"{option}" is not a valid option.') # @everyone role or managed if role.is_default() or role.managed: return await utils.cmdFail(ctx, f'"{role.name}" is not a valid role.') role_request_type = None if not (doc and str( role.id) in doc['roles']) else doc['roles'][str(role.id)]['type'] # Role info if resolved_option is None: embed = discord.Embed( title='Role Info', description=f'<@&{role.id}> (`{role.id}`)\n' + f'**Color:** {"None" if role.color == discord.Colour.default() else role.color}\n' + f'**Hoisted:** {"Yes" if role.hoist else "No"}\n' + f'**Mentionable:** {"Yes" if role.mentionable else "No"}\n' + '**Requestable:** ' + ('No' if not role_request_type else f'Yes, {role_request_type.title()}'), color=discord.Embed.Empty if role.color == discord.Colour.default() else role.colour) if commands.has_permissions(manage_roles=True)(ctx): embed.set_footer( text=f'See "{ctx.prefix}help role" for valid subcommands.') return await ctx.send(embed=embed) # Remove role if resolved_option == 'remove': if not role_request_type: return await utils.cmdFail( ctx, f'"{role.name}" is not a requestable role.') utils.guildKeyDel(ctx.bot, ctx.guild, f'roles.{role.id}') return await utils.cmdSuccess( ctx, f'"{role.name}" has been removed as a requestable role.') # Modify role type if role_request_type: if resolved_option == 'add': return await utils.cmdFail( ctx, f'"{role.name}" is already a requestable role.') if role_request_type == resolved_option: return await utils.cmdFail( ctx, f'"{role.name}" is already a {resolved_option} requestable role.' ) utils.guildKeySet(ctx.bot, ctx.guild, f'roles.{role.id}.type', resolved_option) return await utils.cmdSuccess( ctx, f'"{role.name}" is now a {resolved_option} requestable role.') # Add role else: if resolved_option == 'add': resolved_option = 'open' utils.guildKeySet(ctx.bot, ctx.guild, f'roles.{role.id}', {'type': resolved_option}) return await utils.cmdSuccess( ctx, f'"{role.name}" has been added as a requestable {resolved_option} role.' )
async def request_create(self, ctx, role): doc = utils.getGuildDoc(ctx.bot, ctx.guild) channel = doc['requests_opts']['channel'] users_requests = list( filter(lambda e: e['user'] == ctx.author.id, doc['requests'].values())) if doc['requests_opts']['hidejoins']: try: await ctx.message.delete(delay=5) except: pass delete = 15 else: delete = None if not channel: return await utils.cmdFail( ctx, f'Limited role requests are currently disabled for this guild.', delete_after=delete) existing_request = list( filter(lambda e: e['role'] == role.id, users_requests)) if existing_request and existing_request[-1]['status'] == 'pending': return await utils.cmdFail( ctx, f'You already have a request pending for the role "{role.name}".', delete_after=delete) # Ratelimit if enabled & ratelimit score above maximum; score calculated from status of requests in last 24h if doc['requests_opts']['ratelimit']: rl_score = 0 for r in users_requests: rl_score += 0 if not r[ "status"] in LIMITED_RATELIMIT_SCORES else LIMITED_RATELIMIT_SCORES[ r["status"]] if rl_score > LIMITED_RATELIMIT_SCORE_MAX: return await utils.cmdFail( ctx, 'You have too many recent requests. Please try again later.', delete_after=delete) embed = discord.Embed( title='Limited Role Request', description= f'<@{ctx.message.author.id}> requested the <@&{role.id}> role.', color=discord.Colour.blurple(), timestamp=datetime.datetime.utcnow() + datetime.timedelta(hours=24)) embed.set_author( name=f'{ctx.message.author} ({ctx.message.author.id})', icon_url=ctx.message.author.avatar_url) embed.add_field(name='Status', value='Pending. React to approve or deny the request.') embed.set_footer(text='Request expires') embed_message = await ctx.guild.get_channel(channel).send(embed=embed) await embed_message.add_reaction(config.greenTick) await embed_message.add_reaction(config.redTick) utils.guildKeySet( ctx.bot, ctx.guild, f'requests.{embed_message.id}', { 'channel': embed_message.channel.id, 'created': datetime.datetime.utcnow().timestamp(), 'role': role.id, 'status': 'pending', 'user': ctx.author.id, }) return await utils.cmdSuccess( ctx, f'Your request for "{role.name}" has been submitted.', delete_after=delete)
async def request_update(self, guild, message_id, request, status, mod=None): statuses = { 'cancelled': { 'colour': discord.Colour.darker_grey(), 'footer': 'Request cancelled', 'status': 'Cancelled by user.' }, 'approved': { 'colour': discord.Colour.dark_green(), 'dm': 'been approved.', 'footer': 'Request approved', 'status': f'Approved by {mod}.' }, 'denied': { 'colour': discord.Colour.dark_red(), 'dm': 'been denied.', 'footer': 'Request denied', 'status': f'Denied by {mod}.' }, 'expired': { 'colour': discord.Colour.greyple(), 'dm': 'expired due to lack of moderator response.', 'footer': 'Request expired', 'status': f'Request expired due to lack of moderator response.' } } member = await guild.fetch_member(request['user']) role = guild.get_role(request['role']) layout = statuses[status] if status == 'approved': await member.add_roles(role, reason='User role request approved') if status == 'expired': utils.guildKeyDel(self.bot, guild, f'requests.{message_id}') else: utils.guildKeySet(self.bot, guild, f'requests.{message_id}.status', status) if request['status'] == 'pending': channel = await self.bot.fetch_channel(request['channel']) try: embed_message = await channel.fetch_message(message_id) embed = embed_message.embeds[0] embed.colour = layout['colour'] embed.timestamp = datetime.datetime.utcnow() embed.set_footer(text=layout['footer']) embed.remove_field(0) embed.add_field(name='Status', value=layout['status']) await embed_message.edit(embed=embed) await embed_message.clear_reactions() except: pass if status != 'cancelled': try: await member.send( f'Your request for "{role}" in "{guild}" has {layout["dm"]}' ) except: pass return