async def newcontributors_fetch(self, ctx: GuildContext) -> None: """Fetches all contributors and puts them in pending list. This command should only be ran on first setup. """ async with ctx.typing(): await self._newcontributors_fetch(ctx)
async def mee6rank(self, ctx: commands.GuildContext, member: Optional[discord.Member] = None) -> None: """Get detailed information about Mee6 rank for you or given member.""" async with ctx.typing(): if (player := await self._maybe_get_player(ctx, member)) is None: return embed = discord.Embed(title=f"Mee6 rank for {player.member.name}") embed.add_field(name="Level", value=str(player.level)) embed.add_field(name="XP amount", value=str(player.total_xp)) xp_needed = player.xp_until_next_level embed.add_field(name="XP needed to next level", value=str(xp_needed)) embed.add_field( name="Average amount of messages to next lvl", value=str(self._message_amount_from_xp(xp_needed)), ) next_role_reward = player.next_role_reward if next_role_reward is not None: xp_needed = player.xp_until_level(next_role_reward.rank) embed.add_field( name=f"XP to next role - {next_role_reward.role.name}", value=str(xp_needed), ) embed.add_field( name=("Average amount of messages to next role" f" - {next_role_reward.role.name}"), value=str(self._message_amount_from_xp(xp_needed)), ) await ctx.send(embed=embed)
async def resetnicks(self, ctx: commands.GuildContext) -> None: """ Reset everyone's nicknames to what they were before `[p]renameall` command was used. """ not_changed = [] async with ctx.typing(): for member in ctx.guild.members: original_nick = await self.config.member(member ).original_nick() if original_nick is False: continue if (member.top_role >= ctx.guild.me.top_role and member is not ctx.guild.me): not_changed.append( f"{member} - Member's top role is not lower than mine." ) continue try: await member.edit(nick=original_nick, reason="Revert April Fools joke") except discord.HTTPException as exc: not_changed.append( f"{member} - An unexpected error occurred" f" when trying to edit member's nickname: {exc}") else: await self.config.member(member).original_nick.clear() msg = "Nicknames updated!\n" if not_changed: msg += "Nicknames of these users have not been updated:\n" msg += "\n".join(not_changed) for page in pagify(msg): await ctx.send(page)
async def setmessage(self, ctx: commands.GuildContext, message: str): """ Set the message to add the emoji's """ guild = ctx.message.guild current_message = await self._config.guild(guild).welcome_message() # Check if the guild alrdy has used 'setmessage' if current_message: await ctx.send("A Message has already been set for this server. Would you like to change it? (respond with yes or no)") continue_setup = await bot.wait_for( 'message', check=lambda message: message if message.author == ctx.author and message.channel in guild.channels and (message.lower() == "yes" or message.lower() == "no")) if continue_setup.lower() == "yes": pass else: return await ctx.send("Stopped the setup") # Intermediate Update about the progress ctx.send(""" Succesfully received the new message for RoleManager! Which channel would you like to post it? (Type the exact channel name in chat) """) # Simple watcher which_channel = await bot.wait_for( 'message', check=lambda message: message if message.author == ctx.author and message.channel in guild.channels else False) if not which_channel: return # Create try/except blocks to check for assignment availability try: assigned_channel = discord.utils.get( ctx.guild.channels, name=which_channel) except Exception as exc: return await ctx.send(f"Could not find channel {which_channel}. Encountered error: {exc}") try: await self._config.guild(guild).welcome_message.set(message) await self._config.guild(guild).welcome_message_channel.set(assigned_channel.id) except Exception as exc: return await ctx.send(f"Could not assign given content to {guild} guild Configuration. Encountered Error: {exc}") # Purposely taking the message from the Config object for persistence. return await assigned_channel.send(self._config.guild(guild).welcome_message())
async def renameall(self, ctx: commands.GuildContext) -> None: """ Rename everyone in the server. These values will be substituted: $index - Member's number/index on the members list. First server member (with the earliest join date) has $index=1, second member $index=2 and so on. """ nick_template = await self.config.guild(ctx.guild).nick_template() if nick_template is None: command = inline(f"{ctx.clean_prefix}setnicktemplate") await ctx.send("Nickname template needs to be set" f" with {command} before you can use this command.") return tmpl = Template(nick_template) if len(tmpl.safe_substitute(index=len(ctx.guild.members))) > 32: await ctx.send("The set nickname is too long!") return members = sorted(ctx.guild.members, key=lambda m: m.joined_at) rename_exclusions = await self.config.guild(ctx.guild ).rename_exclusions() not_changed = [] async with ctx.typing(): for idx, member in enumerate(members, start=1): nick = tmpl.safe_substitute(index=idx) if member.id in rename_exclusions: not_changed.append( f"{member} (would be: {nick})" " - Member is set to be excluded from renaming.") continue if (member.top_role >= ctx.guild.me.top_role and member is not ctx.guild.me): not_changed.append( f"{member} (would be: {nick})" " - Member's top role is not lower than mine.") continue original_nick = member.nick try: await member.edit(nick=nick, reason="April Fools joke") except discord.HTTPException as exc: not_changed.append( f"{member} (would be: {nick}) - An unexpected error occurred" f" when trying to edit member's nickname: {exc}") else: await self.config.member(member).original_nick.set( original_nick) msg = "Nicknames updated!\n" if not_changed: msg += "Nicknames of these users have not been updated:\n" msg += "\n".join(not_changed) await ctx.send(msg)
async def importbans(self, ctx: commands.GuildContext): """ Imports bans from json """ if not ctx.message.attachments: return await ctx.send( _( "You definitely need to supply me an exported ban list to be imported." ) ) fp = io.BytesIO() a = ctx.message.attachments[0] await a.save(fp) try: data = json.load(fp) if not isinstance(data, list) or not all(isinstance(x, int) for x in data): raise TypeError() from None except (json.JSONDecodeError, TypeError): return await ctx.send(_("That wasn't an exported ban list")) current_bans = await ctx.guild.bans() to_ban = set(data) - {b.user.id for b in current_bans} if not to_ban: return await ctx.send( _("That list doesn't contain anybody not already banned.") ) async with ctx.typing(): exit_codes = [ await self.ban_or_hackban( ctx.guild, idx, mod=ctx.author, reason=f"Imported ban by {ctx.author}({ctx.author.id})", ) for idx in to_ban ] if all(exit_codes): await ctx.message.add_reaction("\N{HAMMER}") elif not any(exit_codes): await ctx.send(_("You are not worthy")) else: await ctx.send( _( "I got some of those, but other's couldn't be banned for some reason." ) )
async def mrole_complex(self, ctx: GuildContext, *, _query: ComplexActionConverter): """ Similar syntax to search, while applying/removing roles --has-all roles --has-none roles --has-any roles --has-no-roles --has-exactly-nroles number --has-more-than-nroles number --has-less-than-nroles number --has-perm permissions --any-perm permissions --not-perm permissions --above role --below role --only-humans --only-bots --everyone --add roles --remove roles """ query = _query.parsed apply = query["add"] + query["remove"] if not await self.all_are_valid_roles(ctx, *apply): return await ctx.send( "Either you or I don't have the required permissions " "or position in the hierarchy.") members = set(ctx.guild.members) members = self.search_filter(members, query) if len(members) > 100: await ctx.send( "This may take a while given the number of members to update.") async with ctx.typing(): for member in members: try: await self.update_roles_atomically(who=member, give=query["add"], remove=query["remove"]) except RoleManagementException: log.debug( "Internal filter failure on member id %d guild id %d query %s", member.id, ctx.guild.id, query, ) except discord.HTTPException: log.debug( "Unpredicted failure for member id %d in guild id %d query %s", member.id, ctx.guild.id, query, ) await ctx.tick()