async def remove_role(self, ctx, *roles): try: assert len(roles) > 0 roles = list( filter(lambda r: r is not None, [get_guild_role(ctx.guild, role) for role in roles])) excp = [ role for role in guild_config(ctx.bot.db, ctx.guild.id).get( "exceptions", []) ] + [role.id for role in roles] guild_config(ctx.bot.db, ctx.guild.id, {"exceptions": list(set(excp))}) except Exception: await try_react(ctx, "❗") print_exc() else: await try_react(ctx, "✅")
async def unallow_role(self, ctx, *roles): try: assert len(roles) > 0 roles = list( filter(lambda r: r is not None, [get_guild_role(ctx.guild, role) for role in roles])) allw = [ role for role in guild_config(ctx.bot.db, ctx.guild.id)["allowed"] if role not in [role.id for role in roles] ] guild_config(ctx.bot.db, ctx.guild.id, {"allowed": allw}) except Exception: await try_react(ctx, "❗") print_exc() else: await try_react(ctx, "✅")
async def update(self, ctx): try: await ctx.bot.update_roles(ctx.guild) if ctx.channel.id == guild_config(ctx.bot.db, ctx.guild.id)["channel"]: await try_delete(ctx.message) except Exception: await try_react(ctx, "❗") print_exc() else: await try_react(ctx, "✅")
async def channel(self, ctx, *, channel: str = None): if not channel: channel = get_guild_channel( ctx.guild, guild_config(ctx.bot.db, ctx.guild.id)["channel"]) try: message = ( f"Current role channel: <#{channel.id}>.\n" f"Use the command again to set the role channel...\n" f"For example: {ctx.bot.user.mention} channel <#{ctx.channel.id}>" ) except AttributeError: message = ( f"Use the command again to set the role channel...\n" f"For example: {ctx.bot.user.mention} channel <#{ctx.channel.id}>" ) try: await ctx.send(message) except (discord.HTTPException, discord.Forbidden): print_exc() return try: channel = get_guild_channel(ctx.guild, channel) guild_config(ctx.bot.db, ctx.guild.id, {"channel": channel.id}) await try_react(ctx, "✅") except Exception: await try_react(ctx, "❗") print_exc() await ctx.bot.update_roles(ctx.guild)
async def get_config(self, ctx, guild_id: int=0): try: guild = ctx.bot.get_guild(guild_id) or ctx.guild assert isinstance(guild, discord.Guild) except Exception: await try_delete(ctx.message) print_exc() return config = guild_config(ctx.bot.db, guild.id) with tempfile.TemporaryFile(mode="w+", encoding="utf-8") as fp: json.dump(config, fp, sort_keys=True, indent=2) fp.seek(0) try: await ctx.send(file=discord.File(fp, filename="roles.json")) except (discord.Forbidden, discord.HTTPException): print_exc()
async def show_roles(self, ctx, guild_id: int = 0): if await ctx.bot.is_owner(ctx.author): try: guild = ctx.bot.get_guild(guild_id) or ctx.guild assert isinstance(guild, discord.Guild) except Exception: await try_delete(ctx.message) print_exc() return else: if not (ctx.guild and has_permissions(ctx)): return guild = ctx.guild roles = {} config = guild_config(ctx.bot.db, guild.id) config = { "roles": config.get("roles", []), "exceptions": config.get("exceptions", []) } def predicate(role): role = get_guild_role(guild, role) if role: return [role.id, role.name] else: return None for key, val in config.items(): roles[key] = list(map(predicate, val)) with tempfile.TemporaryFile(mode="w+", encoding="utf-8") as fp: json.dump(roles, fp, sort_keys=True, indent=2) fp.seek(0) try: await ctx.send(file=discord.File(fp, filename="roles.json")) except (discord.Forbidden, discord.HTTPException): print_exc()
async def on_guild_join(self, guild): fprint(f"Joined a new guild: '{guild.name}' ({guild.id})") guild_config(self.db, guild.id)
async def rank(self, ctx, *, guild_id: int=0): if await ctx.bot.is_owner(ctx.author): try: guild = ctx.bot.get_guild(guild_id) or ctx.guild assert isinstance(guild, discord.Guild) except Exception: await try_delete(ctx.message) print_exc() return else: if not (ctx.guild and has_permissions(ctx)): return guild = ctx.guild roles = [] config = {} for role in guild_config(ctx.bot.db, guild.id).get("roles", []): rank = 0 for member in guild.members: if get_guild_role(guild, role) in member.roles: rank += 1 config[role] = rank def predicate(role, rank): role = get_guild_role(guild, role) if isinstance(role, discord.Role) and role.name != "@everyone": return {"rank": rank, "id": role.id, "name": role.name} else: return None for key, val in config.items(): role = predicate(key, val) if role: roles += [role] roles = json.dumps(sorted(roles, key=itemgetter("rank"), reverse=True), sort_keys=True, indent=2) # Beautify and condense decoded dictionary further roles = re.sub(r'\,\s*\n\s*"name"\,', ', "name"', roles) roles = re.sub(r'\}\,\n\s+\{', '}, {', roles) if len(f"```json\n{roles}\n```") < CHAR_LIMIT: try: await ctx.send("```json\n" + roles + "\n```") except (discord.Forbidden, discord.HTTPException): print_exc() else: with tempfile.TemporaryFile(mode="w+", encoding="utf-8") as fp: fp.write(roles) fp.seek(0) try: await ctx.send(file=discord.File(fp, filename="rank.json")) except (discord.Forbidden, discord.HTTPException): print_exc()
async def update_roles(self, guild): config = guild_config(self.db, guild.id) for channel in guild.text_channels: if int(channel.id) == config.get("channel", 0): break else: if not guild.me.guild_permissions.manage_channels: fprint(f"Couldn't update roles for {guild.name} ({guild.id}):", "Missing permission 'manage_channels'", file=sys.stderr) return try: channel = await guild.create_text_channel("tags") except Exception: return if not guild.me.permissions_in(channel).read_message_history: fprint(f"Couldn't update roles for {guild.name} ({guild.id}):", "Missing permission 'read_message_history'", file=sys.stderr) return async for message in channel.history( limit=500).filter(lambda m: m.author.bot): try: await message.delete() except Exception: fprint(f"Failed to delete message ({message}) in role channel", file=sys.stderr) if not guild.me.permissions_in(channel).send_messages: fprint(f"Couldn't update roles for {guild.name} ({guild.id}):", "Missing permission 'send_messages'", file=sys.stderr) return roles = {} for role in guild.roles: if role.id not in config.get("exceptions", []): roles[role.position] = (role.id, role.name) roles = dict(sorted(roles.items())) role = [] for r in roles.values(): role.append(r[1]) role.pop(0) tags = ["**"] while len(role) > 0: if len(tags[-1] + ", " + role[-1]) < (CHAR_LIMIT - 2): if tags[-1] == "**": tags[-1] += role.pop() else: tags[-1] += ", " + role.pop() else: tags[-1] += "**" tags.append("**") else: tags[-1] += "**" messages = [] for tag in tags: messages += [(await channel.send(content=tag)).id] config["messages"] = messages config["channel"] = channel.id config["roles"] = [ role[0] for role in roles.values() if role[0] not in config.get("exceptions", []) ] guild_config(self.db, guild.id, config) fprint(f"Updated roles for \"{guild.name}\" ({guild.id})")