Esempio n. 1
0
    async def message_violator():
        logger.debug("Sending message to user who violated the filter")
        response = StringBuilder()
        response.write(
            f"The message you posted in {message.channel.mention} contains or links to a file "
        )
        response.writeln(
            f"that violates a {filter_type.value} content filter: `{hashsum.hex()}`."
        )
        response.writeln(f"Your original link: <{url}>")

        if reupload:
            response.writeln(
                "The filtered file has been attached to this message.")

        if severity >= FilterType.JAIL.level:
            if roles.jail is not None:
                response.writeln(
                    "This offense is serious enough to warrant immediate revocation of posting privileges.\n"
                    f"As such, you have been assigned the `{roles.jail.name}` role, until a moderator clears you."
                )

        kwargs = {}
        if reupload:
            response.writeln(
                "In case the link is broken, the file has been attached below:"
            )
            filename = os.path.basename(urlparse(url).path)
            kwargs["file"] = discord.File(binio.getbuffer(), filename=filename)

        kwargs["content"] = str(response)
        await message.author.send(**kwargs)
Esempio n. 2
0
    async def ufind(self, ctx, *, name: str):
        """
        Perform a fuzzy search to find users who match the given name.
        They are listed with the closest matches first.
        Users not in this guild are marked with a \N{GLOBE WITH MERIDIANS}.
        """

        logger.info("Running ufind on '%s'", name)
        users = await similar_users(self.bot, name)
        users_not_in_guild = (set(
            member.id for member in ctx.guild.members) if ctx.guild else set())
        descr = StringBuilder()

        for user in users:
            extra = "\N{GLOBE WITH MERIDIANS}" if user in users_not_in_guild else ""
            descr.writeln(
                f"- {user.mention} {user.name}#{user.discriminator} {extra}")

        if users:
            embed = discord.Embed(description=str(descr),
                                  colour=discord.Colour.teal())
        else:
            embed = discord.Embed(description="**No users found!**",
                                  colour=discord.Colour.red())

        await ctx.send(embed=embed)
Esempio n. 3
0
    async def roles(self, ctx):
        """ Lists all roles in the guild. """

        contents = []
        content = StringBuilder()

        logger.info("Listing roles within the guild")
        for role in ctx.guild.roles:
            content.writeln(
                f"- {role.mention} id: `{role.id}`, members: `{len(role.members)}`"
            )

            if len(content) > 1900:
                # Too long, break into new embed
                contents.append(str(content))

                # Start content over
                content.clear()

        if content:
            contents.append(str(content))

        for i, content in enumerate(contents):
            embed = discord.Embed(description=content,
                                  colour=discord.Colour.dark_teal())
            embed.set_footer(text=f"Page {i + 1}/{len(contents)}")
            await ctx.send(embed=embed)
Esempio n. 4
0
    async def log_show(self, ctx, *channels: TextChannelConv):
        """
        Displays current settings for this guild.
        If channels are provided, then only outputs for those channels are fetched.
        """

        if not channels:
            channels = ctx.guild.channels

        outputs = self.bot.sql.journal.get_journals_on_channels(*channels)
        outputs = sorted(outputs, key=lambda out: out.path)
        attributes = []
        descr = StringBuilder()

        for output in outputs:
            if not output.settings.recursive:
                attributes.append("exact path")

            attr_str = f'({", ".join(attributes)})' if attributes else ""
            descr.writeln(
                f"- `{output.path}` mounted at {output.sink.mention} {attr_str}"
            )
            attributes.clear()

        if outputs:
            embed = discord.Embed(colour=discord.Colour.teal(), description=str(descr))
            embed.set_author(name="Current journal outputs")
        else:
            embed = discord.Embed(colour=discord.Colour.dark_purple())
            embed.set_author(name="No journal outputs!")

        await ctx.send(embed=embed)
Esempio n. 5
0
    async def log_dm_show(self, ctx, user: UserConv = None):
        """
        Displays current journal mounts for a user.
        """

        if user is None:
            user = self.bot.get_user(ctx.author.id)
        else:
            user = self.bot.get_user(user.id)

        outputs = self.bot.sql.journal.get_journals_on_user(user)
        outputs = sorted(outputs, key=lambda out: out.path)
        attributes = []
        descr = StringBuilder(f"{user.mention}:\n\n")

        for output in outputs:
            if not output.settings.recursive:
                attributes.append("exact path")

            attr_str = f'({", ".join(attributes)})' if attributes else ""
            descr.writeln(f"- `{output.path}` {attr_str}")
            attributes.clear()

        if outputs:
            embed = discord.Embed(colour=discord.Colour.teal(), description=str(descr))
            embed.set_author(name="Current journal outputs")
        else:
            embed = discord.Embed(colour=discord.Colour.dark_purple())
            embed.set_author(name="No journal outputs!")

        await ctx.send(embed=embed)
Esempio n. 6
0
    async def reactions(self, ctx, *, message: MessageConv):
        """
        Displays all reactions on a message.
        """

        logger.info("Displaying reactions for message ID %d", message.id)

        if not message.reactions:
            embed = discord.Embed(colour=discord.Colour.dark_purple())
            embed.description = "This message has no reactions."
            await ctx.send(embed=embed)
            return

        descr = StringBuilder()
        for reaction in message.reactions:
            if descr:
                descr.writeln()

            descr.write(reaction.emoji)
            async for user in reaction.users():
                descr.write(f" {user.mention}")

                if len(descr) > 1800:
                    embed = discord.Embed(colour=discord.Colour.teal())
                    embed.description = str(descr)
                    await ctx.send(embed=embed)
                    descr.clear()
                    descr.write(reaction.emoji)

        if descr:
            embed = discord.Embed(colour=discord.Colour.teal())
            embed.description = str(descr)
            await ctx.send(embed=embed)
Esempio n. 7
0
    async def listcogs(self, ctx):
        """ Lists all currently loaded cogs. """

        content = StringBuilder("```\n")

        extensions = defaultdict(list)
        for cog_name, cog in self.bot.cogs.items():
            ext_name = cog.__module__.rsplit(".", 1)[0]
            ext_name = ext_name.rsplit(".", 1)[1]

            extensions[ext_name].append(cog_name)

        # I hate this but tree-format uses lists and tuples for some reason
        # So this takes the nice dictionary and converts it to that
        extensions = [(ext, [(cog_name, []) for cog_name in cog])
                      for ext, cog in extensions.items()]

        tree = ("futaba", [("cogs", extensions)])

        content.writeln(
            format_tree(tree,
                        format_node=itemgetter(0),
                        get_children=itemgetter(1)))
        content.writeln("```")
        await ctx.send(content=str(content))
Esempio n. 8
0
    async def uinfo(self, ctx, *, name: str = None):
        """
        Fetch information about a user, whether they are in the guild or not.
        If no argument is passed, the caller is checked instead.
        """

        user = await self.get_user(ctx, name)
        usernames, nicknames = self.bot.sql.alias.get_alias_names(
            ctx.guild, user)

        logger.info("Running uinfo on '%s' (%d)", user.name, user.id)

        # Status
        content = StringBuilder()
        if getattr(user, "status", None):
            status = ("do not disturb"
                      if user.status == discord.Status.dnd else user.status)
            content.writeln(f"{user.mention}, {status}")
        else:
            content.writeln(user.mention)

        embed = discord.Embed()
        embed.timestamp = user.created_at
        embed.set_author(name=user_discrim(user))
        embed.set_thumbnail(url=user.avatar_url)

        # User colour
        if hasattr(user, "colour"):
            embed.colour = user.colour

        embed.add_field(name="ID", value=f"`{user.id}`")
        self.uinfo_add_roles(embed, user)
        self.uinfo_add_activity(embed, user, content)

        embed.description = str(content)
        content.clear()

        self.uinfo_add_voice(embed, user)
        self.uinfo_add_aliases(embed, content, usernames, nicknames)

        # Guild join date
        if hasattr(user, "joined_at"):
            embed.add_field(name="Member for",
                            value=fancy_timedelta(user.joined_at))

        # Discord join date
        embed.add_field(name="Account age",
                        value=fancy_timedelta(user.created_at))

        # Send them
        await ctx.send(embed=embed)
Esempio n. 9
0
    async def message_count(self, ctx, user: UserConv, *exclude: TextChannelConv):
        """
        Gets the total number of messages this user has sent in the guild.
        Text channels to exclude from the search can be added as optional arguments.
        """

        message_count, edited_count, deleted_count = self.sql.message_count(
            ctx.guild, user, exclude
        )

        descr = StringBuilder()
        descr.writeln(
            f"Found `{message_count}` message{plural(message_count)} from {user.mention}."
        )

        if message_count:
            descr.writeln(
                f"Of those, `{edited_count}` (or `{edited_count / message_count * 100:.2f}%`) are edited,\n"
                f"and `{deleted_count}` (or `{deleted_count / message_count * 100:.2f}%`) are deleted."
            )

        if hasattr(user, "joined_at"):
            descr.writeln()
            descr.writeln(
                f"They have been a member for {fancy_timedelta(user.joined_at)}."
            )

        embed = discord.Embed(colour=discord.Colour.teal())
        embed.description = str(descr)

        await ctx.send(embed=embed)
Esempio n. 10
0
    async def alert_add(self, ctx, attribute: str, relationship: str, *,
                        amount: str):
        """
        Adds a join alert with the given condition.

        Possible attributes: id, created, name, discrim, avatar, status
        Possible relationships: > >= = != < <= ~
        """

        logging.info(
            "Got request to add new join alert for '%s' (%d)",
            ctx.guild.name,
            ctx.guild.id,
        )

        try:
            key = JoinAlertKey.parse(attribute)
        except ValueError:
            raise ManualCheckFailure(content=f"Invalid attribute: {attribute}")

        try:
            op = ValueRelationship(relationship)
        except ValueError:
            raise ManualCheckFailure(
                content=f"Invalid relationship: {relationship}")

        try:
            value = key.parse_value(amount)
        except ValueError as error:
            raise ManualCheckFailure(content=str(error))

        alert = JoinAlert(ctx.guild, None, key, op, value)
        logging.info("Adding join alert: %s", alert)

        with self.bot.sql.transaction():
            self.bot.sql.welcome.add_alert(ctx.guild, alert)

        self.alerts[alert.id] = alert

        # Notify the user
        embed = discord.Embed(colour=discord.Colour.dark_teal())
        embed.set_author(name="Successfully added join alert")
        descr = StringBuilder()
        descr.writeln(f"ID: #`{alert.id:05}`, Condition: `{alert}`")
        descr.writeln(
            "To get these notifications in a channel, add a logger for path `/welcome/alert`"
        )
        embed.description = str(descr)
        await ctx.send(embed=embed)
Esempio n. 11
0
    async def list_emojis(self, ctx, all_guilds=False):
        contents = []
        content = StringBuilder()

        if all_guilds:
            if not mod_perm(ctx):
                raise ManualCheckFailure(
                    content="Only moderators can do this.")

            guild_emojis = (guild.emojis for guild in self.bot.guilds)
            emojis = chain(*guild_emojis)
        else:
            emojis = ctx.guild.emojis

        logger.info("Listing all emojis within the guild")
        for emoji in emojis:
            managed = "M" if emoji.managed else ""
            content.writeln(
                f"- [{emoji}]({emoji.url}) id: `{emoji.id}`, name: `{emoji.name}` {managed}"
            )

            if len(content) > 1900:
                # Too long, break into new embed
                contents.append(str(content))

                # Start content over
                content.clear()

        if content:
            contents.append(str(content))

        for i, content in enumerate(contents):
            embed = discord.Embed(description=content,
                                  colour=discord.Colour.dark_teal())
            embed.set_footer(text=f"Page {i + 1}/{len(contents)}")

            if i == 0:
                if all_guilds:
                    embed.set_author(name="Emojis in all guilds")
                else:
                    embed.set_author(name=f"Emojis within {ctx.guild.name}")

            await ctx.send(embed=embed)
Esempio n. 12
0
    async def message_violator(jailed):
        response = StringBuilder(
            f"The {name_type.value} you just set violates a {filter_type.value} text filter "
            f"disallowing `{escaped_filter_text}`.\n"
        )

        if jailed:
            if roles.jail is not None:
                response.writeln(
                    f"In the mean time, you have been assigned the `{roles.jail.name}` role, "
                    "revoking your posting privileges until a moderator clears you."
                )
        else:
            response.writeln(
                "Your name has been manually cleared. Please do not set your name to "
                "anything offensive in the future."
            )

        await member.send(content=str(response))
Esempio n. 13
0
    async def log_find(self, ctx, *, condition: str = None):
        """
        List previous journal events that match the given conditions.
        The condition is a Python expression with no variables but
        the following attributes:

        path: str
        ppath: PurePath
        guild: discord.Guild
        content: str
        attributes: dict
        """

        events, error_embeds = self.log_filter(ctx.guild, condition, 10)

        if error_embeds:
            await ctx.send(embed=error_embeds[0])

        if events:
            embed = discord.Embed(colour=discord.Colour.dark_teal())
            embed.set_author(name="Matching journal events")
            descr = StringBuilder()

            embeds = []
            for event in events:
                descr.writeln(f"Path: `{event.path}`, Content: {event.content}")
                descr.writeln(f"Attributes: ```py\n{pformat(event.attributes)}\n```\n")
                if len(descr) > 1400:
                    embed.description = str(descr)
                    embeds.append(embed)
                    descr.clear()
                    embed = discord.Embed(colour=discord.Colour.dark_teal())
                    embed.set_author(name="Matched journal events")
            embed.description = str(descr)
        else:
            embed = discord.Embed(colour=discord.Colour.dark_purple())
            embed.set_author(name="No matching journal entries")
            embeds = (embed,)

        for i, embed in enumerate(embeds):
            embed.set_footer(text=f"Page {i + 1}/{len(embeds)}")
            await ctx.send(embed=embed)
Esempio n. 14
0
    async def remind_list(self, ctx):
        """ Lists all reminders for the current user. """

        reminders = self.bot.sql.navi.get_reminders(ctx.author)
        if reminders:
            descr = StringBuilder()
            for reminder in reminders:
                until = fancy_timedelta(reminder.timestamp)
                message = escape_backticks(reminder.message)
                descr.writeln(
                    f"ID: #`{reminder.id:05}`: in `{until}` with message: `{message}`"
                )

            embed = discord.Embed(colour=discord.Colour.dark_teal())
            embed.set_author(name=f"Reminders for {ctx.author.display_name}")
            embed.description = str(descr)
        else:
            embed = discord.Embed(colour=discord.Colour.dark_purple())
            embed.description = f"No reminders for {ctx.author.mention}"

        await ctx.send(embed=embed)
Esempio n. 15
0
def elevated_role_embed(guild, role, level):
    """
    Takes the result of elevated_role_perms() and produces an embed listing the permissions.
    The parameter level must be 'warning' or 'error'.
    """

    elevated = elevated_role_perms(guild, role)
    if not elevated:
        return None

    if level == "warning":
        colour = discord.Colour.gold()
        icon = "\N{WARNING SIGN}"
    elif level == "error":
        colour = discord.Colour.red()
        icon = "\N{NO ENTRY}"
    else:
        raise ValueError(f"Unknown severity level: '{level}'")

    embed = discord.Embed()
    embed.colour = colour
    embed.title = f"{icon} Role gives elevated permissions"
    descr = StringBuilder()
    for location, perm in elevated:
        perm = perm.replace("_", " ").title()
        if isinstance(location, discord.Guild):
            descr.writeln(f"- {perm}")
        elif isinstance(location, discord.TextChannel):
            descr.writeln(f"- {perm} in {location.mention}")
        else:
            descr.writeln(f"- {perm} in {location.name}")
    embed.description = str(descr)
    return embed
Esempio n. 16
0
    async def alert_show(self, ctx):
        """ Lists all join alerts for this guild. """

        logging.info("Showing all join alerts for '%s' (%d)", ctx.guild.name,
                     ctx.guild.id)

        embed = discord.Embed()
        embed.set_author(name="Join alerts")
        descr = StringBuilder()
        descr.writeln("__Alert ID__ | __Condition__")

        for alert in self.alerts.values():
            assert alert.id is not None, "Alert was not given an ID"
            descr.writeln(f"#**`{alert.id:05}`** | `{alert}`")

        if self.alerts:
            embed.colour = discord.Colour.dark_teal()
            embed.description = str(descr)
        else:
            embed.colour = discord.Colour.dark_purple()
            embed.description = "No alerts for this guild"

        await ctx.send(embed=embed)
Esempio n. 17
0
async def check_text_filter(cog, message):
    # Also check embed content
    content = StringBuilder(message.content)
    for embed in message.embeds:
        embed_dict = embed.to_dict()
        content.writeln(embed_dict.get("description", ""))
        content.writeln(embed_dict.get("title", ""))

        for field in embed_dict.get("fields", []):
            content.writeln(field.get("name", ""))
            content.writeln(field.get("value", ""))

    # This is the string we will validate against
    to_check = str(content)
    logger.debug("Content to check: %r", to_check)

    # Iterate through all guild filters
    triggered = None
    filter_groups = (
        (LocationType.GUILD, cog.filters[message.guild]),
        (LocationType.CHANNEL, cog.filters[message.channel]),
    )

    for location_type, all_filters in filter_groups:
        for filter_text, (filter, filter_type) in all_filters.items():
            if filter.matches(to_check):
                if triggered is None or filter_type.value > triggered.filter_type.value:
                    triggered = FoundTextViolation(
                        bot=cog.bot,
                        journal=cog.journal,
                        message=message,
                        content=to_check,
                        location_type=location_type,
                        filter_type=filter_type,
                        filter_text=filter_text,
                    )

    if triggered is not None:
        roles = cog.bot.sql.settings.get_special_roles(message.guild)
        await found_text_violation(triggered, roles)
Esempio n. 18
0
    async def rinfo(self, ctx, *, name: str = None):
        """
        Fetches and prints information about a particular role in the current guild.
        If no role is specified, it displays information about the default role.
        """

        if name is None:
            role = ctx.guild.default_role
        else:
            conv = RoleConv()
            try:
                role = await conv.convert(ctx, name)
            except commands.BadArgument:
                embed = discord.Embed(colour=discord.Colour.red())
                embed.description = (
                    f"No role found in this guild for `{escape_backticks(name)}`."
                )
                raise CommandFailed(embed=embed)

        logger.info("Running rinfo on '%s' (%d)", role.name, role.id)

        embed = discord.Embed(colour=role.colour)
        embed.timestamp = role.created_at
        embed.add_field(name="ID", value=str(role.id))
        embed.add_field(name="Position", value=str(role.position))

        descr = StringBuilder(f"{role.mention}\n")
        if role.mentionable:
            descr.writeln("Mentionable")
        if role.hoist:
            descr.writeln("Hoisted")
        if role.managed:
            descr.writeln("Managed")
        embed.description = str(descr)

        if role.members:
            max_members = 10
            members = ", ".join(
                map(lambda m: m.mention, islice(role.members, 0, max_members)))
            if len(role.members) > max_members:
                diff = len(role.members) - max_members
                members += f" (and {diff} other{plural(diff)})"
        else:
            members = "(none)"

        embed.add_field(name="Members", value=members)

        await ctx.send(embed=embed)
Esempio n. 19
0
    async def sha1sum(self, ctx, *urls: str):
        """ Gives the SHA1 hashes of any files attached to the message. """

        # Check all URLs
        links = []
        for url in urls:
            match = URL_REGEX.match(url)
            if match is None:
                raise CommandFailed(content=f"Not a valid url: {url}")
            links.append(match[1])
        links.extend(attach.url for attach in ctx.message.attachments)

        # Get list of "names"
        names = list(urls)
        names.extend(attach.filename for attach in ctx.message.attachments)

        # Send error if no URLS
        if not links:
            raise CommandFailed(content="No URLs listed or files attached.")

        # Download and check files
        contents = []
        content = StringBuilder("Hashes:\n```")
        buffers = await download_links(links)
        for i, binio in enumerate(buffers):
            if binio is None:
                hashsum = SHA1_ERROR_MESSAGE
            else:
                hashsum = sha1(binio.getbuffer()).hexdigest()

            content.writeln(f"{hashsum} {names[i]}")
            if len(content) > 1920:
                contents.append(content)
                if i < len(buffers) - 1:
                    content.clear()
                    content.writeln("```")

        if len(content) > 4:
            content.writeln("```")
            contents.append(content)

        for content in contents:
            await ctx.send(content=str(content))
Esempio n. 20
0
    async def message_violator():
        logger.debug("Sending message to user who violated the filter")
        response = StringBuilder(
            f"The message you posted in {message.channel.mention} violates a {location_type.value} "
            f"{filter_type.value} filter disallowing `{escaped_filter_text}`.")

        if severity >= FilterType.JAIL.level:
            if roles.jail is not None:
                response.writeln(
                    "This offense is serious enough to warrant immediate revocation of posting privileges.\n"
                    f"As such, you have been assigned the `{roles.jail.name}` role, until a moderator clears you."
                )

        await message.author.send(content=str(response))
        response.clear()

        if message.content != content:
            embed_caveat = "(including text from all embeds attached to your message)"
        else:
            embed_caveat = ""

        embed = discord.Embed(description=content)
        embed.timestamp = discord.utils.snowflake_time(message.id)
        embed.set_author(name=message.author.display_name,
                         icon_url=message.author.avatar_url)
        to_send = f"The content of the deleted message {embed_caveat} is:"
        await message.author.send(content=to_send, embed=embed)

        response.writeln("or, quoted:")
        response.writeln("```")
        response.writeln(escaped_content)
        response.writeln("```")
        response.writeln("Contact a moderator if you have questions.")
        await message.author.send(content=str(response))
Esempio n. 21
0
    async def alert_match(self, ctx, id: int):
        """
        Lists all members currently joined who matches the conditions given by the join alert ID.
        """

        logging.info(
            "Showing all members matching join alert %d in guild '%s' (%d)",
            id,
            ctx.guild.name,
            ctx.guild.id,
        )

        try:
            alert = self.alerts[id]
        except KeyError:
            embed = discord.Embed(colour=discord.Colour.red())
            embed.set_author(name="Alert check failed")
            embed.description = f"No such join alert id: `{id}`"
            raise CommandFailed(embed=embed)

        embed = discord.Embed()
        embed.set_author(name="Matching members")
        descr = StringBuilder()
        descr.writeln(f"Join alert: `{alert}`")

        matching_members = list(filter(alert.matches, ctx.guild.members))
        if matching_members:
            embed.colour = discord.Colour.dark_teal()
            descr.writeln(f"Found {len(matching_members)} matching members:")
            descr.writeln()

            max_members = 8
            for member in islice(matching_members, 0, max_members):
                descr.writeln(f"- {member.mention}")
            if len(matching_members) > max_members:
                descr.writeln(
                    f"... and {len(matching_members) - max_members} more")
        else:
            embed.colour = discord.Colour.dark_purple()
            descr.writeln("**No members matching this condition**")

        embed.description = str(descr)
        await ctx.send(embed=embed)
Esempio n. 22
0
    async def aliases(self, ctx, *, user: UserConv):
        """ Gets information about known aliases of the given user. """

        logger.info(
            "Getting and printing alias information for some user '%s' (%d)",
            user.name,
            user.id,
        )

        avatars, usernames, nicknames, alt_user_ids = self.bot.sql.alias.get_aliases(
            ctx.guild, user)

        # Remove self from chain
        try:
            alt_user_ids.remove(user.id)
        except KeyError:
            pass

        embed = discord.Embed(colour=discord.Colour.dark_teal())
        embed.set_author(name="Member alias information")

        if not any((avatars, usernames, nicknames, alt_user_ids)):
            embed.colour = discord.Colour.dark_purple()
            embed.description = f"No information found for {user.mention}"

            await ctx.send(embed=embed)
            return

        embed.description = f"{user.mention}\n"
        content = StringBuilder()
        files = []

        if avatars:
            for i, (avatar_bin, avatar_ext,
                    timestamp) in enumerate(avatars, 1):
                time_since = fancy_timedelta(timestamp)
                content.writeln(f"**{i}.** set {time_since} ago")
                files.append(
                    discord.File(avatar_bin,
                                 filename=f"avatar {time_since}.{avatar_ext}"))
            embed.add_field(name="Past avatars", value=str(content))
            content.clear()

        if usernames:
            for username, timestamp in usernames:
                content.writeln(
                    f"- `{username}` set {fancy_timedelta(timestamp)} ago")
            embed.add_field(name="Past usernames", value=str(content))
            content.clear()

        if nicknames:
            for nickname, timestamp in nicknames:
                content.writeln(
                    f"- `{nickname}` set {fancy_timedelta(timestamp)} ago")
            embed.add_field(name="Past nicknames", value=str(content))
            content.clear()

        if alt_user_ids:
            for alt_user_id in alt_user_ids:
                content.writeln(f"<@!{alt_user_id}>")
            embed.add_field(name="Possible alts", value=str(content))

        await ctx.send(embed=embed)
        for i, file in enumerate(files, 1):
            await ctx.send(content=f"#{i}", file=file)
Esempio n. 23
0
async def show_content_filter(all_filters, message):
    if all_filters:
        contents = []
        content = StringBuilder()
        content.writeln(f"**Filtered SHA1 hashes for {message.guild.name}:**")

        # Set up filter list
        filters = {filter_type: [] for filter_type in FilterType}
        for hashsum, (filter_type, description) in all_filters.items():
            filters[filter_type].append((hashsum.hex(), description))

        # Iterate through filters
        for filter_type in FilterType:
            filter_list = filters[filter_type]
            filter_list.sort()

            content.writeln(
                f"{filter_type.emoji} {filter_type.description} hashes {filter_type.emoji}"
            )
            content.writeln("```")

            if not filter_list:
                content.writeln("(none)")
                content.writeln("```")
                continue

            for hexsum, description in filter_list:
                content.writeln(f"{hexsum} {description}")

                if len(content) > 1900:
                    content.writeln("```")
                    contents.append(str(content))
                    content.clear()
                    content.writeln("```")

            if len(content) > 4:
                content.writeln("```")
            else:
                content.clear()

        if content:
            contents.append(str(content))
    else:
        contents = (f"**No filtered SHA1 hashes for {message.guild.name}**", )

    for content in contents:
        await message.author.send(content=content)
Esempio n. 24
0
    async def ginfo(self, ctx):
        """ Gets information about the current guild. """

        embed = discord.Embed()
        embed.timestamp = ctx.guild.created_at
        embed.set_author(name=ctx.guild.name)
        embed.set_thumbnail(url=ctx.guild.icon_url)

        descr = StringBuilder()
        descr.writeln(f"\N{MAN} **Members:** {len(ctx.guild.members):,}")
        descr.writeln(
            f"\N{MILITARY MEDAL} **Roles:** {len(ctx.guild.roles):,}")
        descr.writeln(
            f"\N{BAR CHART} **Channel categories:** {len(ctx.guild.categories):,}"
        )
        descr.writeln(
            f"\N{MEMO} **Text Channels:** {len(ctx.guild.text_channels):,}")
        descr.writeln(
            f"\N{STUDIO MICROPHONE} **Voice Channels:** {len(ctx.guild.voice_channels):,}"
        )
        descr.writeln(
            f"\N{CLOCK FACE TWO OCLOCK} **Age:** {fancy_timedelta(ctx.guild.created_at)}"
        )
        descr.writeln()

        moderators = 0
        admins = 0
        bots = 0

        # Do a single loop instead of generator expressions
        for member in ctx.guild.members:
            if member.bot:
                bots += 1

            perms = member.permissions_in(ctx.channel)
            if perms.administrator:
                admins += 1
            elif perms.manage_messages:
                moderators += 1

        if bots:
            descr.writeln(f"\N{ROBOT FACE} **Bots:** {bots:,}")
        if moderators:
            descr.writeln(
                f"\N{CONSTRUCTION WORKER} **Moderators:** {moderators:,}")
        if admins:
            descr.writeln(f"\N{POLICE OFFICER} **Administrators:** {admins:,}")
        descr.writeln(f"\N{CROWN} **Owner:** {ctx.guild.owner.mention}")
        embed.description = str(descr)

        await ctx.send(embed=embed)
Esempio n. 25
0
async def show_filter(all_filters, author, location_name):
    if all_filters:
        contents = []
        content = StringBuilder(f"**Filtered strings for {location_name}:**\n")
        filters = defaultdict(list)

        for filter_text, (_, filter_type) in all_filters.items():
            filters[filter_type].append(filter_text)

        for filter_type, filter_texts in filters.items():
            content.writeln(
                f"{filter_type.emoji} {filter_type.description} strings {filter_type.emoji}"
            )
            content.writeln("```")

            if not filter_texts:
                content.writeln("(none)")
                continue

            for filter_text in filter_texts:
                if all(ch in READABLE_CHAR_SET for ch in filter_text):
                    content.writeln(f'- "{filter_text}"')
                else:
                    content.writeln(
                        f'- {unicode_repr(filter_text)} ["{filter_text}"]')

                if len(content) > 1900:
                    # Too long, break into new message
                    content.writeln("```")
                    contents.append(str(content))

                    # Start buffer over
                    content.clear()
                    content.writeln("```")

            content.writeln("```")
        contents.append(str(content))
        content.clear()
    else:
        contents = [f"**No filtered strings for {location_name}**"]

    for content in contents:
        await author.send(content=content)
Esempio n. 26
0
    async def reapply_add(self, ctx, *roles: RoleConv):
        """
        Designate a collection of roles as "reappliable".
        Reappliable roles, in addition to all punishment and self-assignable roles, are
        automatically reapplied when the member rejoins the guild.
        """

        warning = StringBuilder()
        roles = set(roles)

        # Filter out roles that shouldn't be reassignable
        special_roles = self.bot.sql.settings.get_special_roles(ctx.guild)

        if ctx.guild.default_role in roles:
            warning.writeln("You should not make @everyone reappliable.")
            roles.remove(ctx.guild.default_role)

        if special_roles.guest_role in roles:
            warning.writeln(
                f"You should not make {special_roles.guest_role.mention} reappliable."
            )
        if special_roles.member_role in roles:
            warning.writeln(
                f"You should not make {special_roles.member_role.mention} reappliable."
            )

        # Warn on roles that are already reappliable
        if special_roles.mute_role in roles:
            warning.writeln(
                f"The {special_roles.mute_role.mention} is always reappliable."
            )
        if special_roles.jail_role in roles:
            warning.writeln(
                f"The {special_roles.jail_role.mention} is always reappliable."
            )

        if "SelfAssignableRoles" in self.bot.cogs:
            assignable_roles = self.bot.sql.roles.get_assignable_roles(
                ctx.guild)
        else:
            assignable_roles = ()

        for role in roles:
            if role in assignable_roles:
                warning.writeln(
                    f"The {role.mention} is already reappliable since it is self-assignable."
                )

        if warning:
            embed = discord.Embed(colour=discord.Colour.dark_purple())
            embed.description = str(warning)
            await ctx.send(embed=embed)

        logger.info(
            "Setting roles as 'reappliable': [%s]",
            ", ".join(role.name for role in roles),
        )

        with self.bot.sql.transaction():
            self.bot.sql.settings.update_reapply_roles(ctx.guild, roles, True)