コード例 #1
0
ファイル: core.py プロジェクト: Scrub000/futaba
    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)
コード例 #2
0
ファイル: core.py プロジェクト: Scrub000/futaba
    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)
コード例 #3
0
ファイル: text.py プロジェクト: EllVEBIT/futaba-1
    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))
コード例 #4
0
ファイル: core.py プロジェクト: telugu-boy/futaba
    async def reapply_show(self, ctx):
        """
        Lists all roles that are reappliable.
        Reappliable roles, in addition to all punishment and self-assignable roles, are
        automatically reapplied when the member rejoins the guild.
        """

        reapply_roles = self.bot.sql.settings.get_reapply_roles(ctx.guild)
        special_roles = self.bot.sql.settings.get_special_roles(ctx.guild)

        embed = discord.Embed(colour=discord.Colour.dark_teal())
        descr = StringBuilder(sep=", ")
        has_roles = False

        # Manually set
        for role in sorted(reapply_roles, key=lambda r: r.name):
            descr.write(role.mention)
        if descr:
            embed.add_field(name="Manually designated", value=str(descr))
            has_roles = True
        else:
            embed.add_field(name="Manually designated", value="(none)")

        # Punishment roles
        descr.clear()
        if special_roles.mute_role is not None:
            descr.write(special_roles.mute_role.mention)
        if special_roles.jail_role is not None:
            descr.write(special_roles.jail_role.mention)
        if descr:
            embed.add_field(name="Punishment roles", value=str(descr))
            has_roles = True

        # Self-assignable roles
        if "SelfAssignableRoles" in self.bot.cogs:
            assignable_roles = self.bot.sql.roles.get_assignable_roles(
                ctx.guild)
            if assignable_roles:
                embed.add_field(
                    name="Self-assignable roles",
                    value=", ".join(role.mention
                                    for role in sorted(assignable_roles,
                                                       key=lambda r: r.name)),
                )
                has_roles = True

        # Send final embed
        if has_roles:
            embed.title = "\N{MILITARY MEDAL} Roles which are automatically reapplied"
        else:
            embed.colour = discord.Colour.dark_purple()

        await ctx.send(embed=embed)
コード例 #5
0
ファイル: core.py プロジェクト: Scrub000/futaba
    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)
コード例 #6
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)
コード例 #7
0
ファイル: filter.py プロジェクト: Scrub000/futaba
    def build_regex(text, groups):
        # Build similar character tree
        chars = {}
        pattern = StringBuilder()
        for group in groups:
            pattern.write("[")
            char = group["character"]
            pattern.write(re.escape(char))
            for homoglyph in group["homoglyphs"]:
                pattern.write(re.escape(homoglyph["c"]))
            pattern.write("]")
            chars[char] = str(pattern)
            pattern.clear()

        # Create pattern
        for char in text:
            pattern.write(chars.get(char, char))

        return str(pattern)
コード例 #8
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))
コード例 #9
0
ファイル: core.py プロジェクト: Scrub000/futaba
    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)
コード例 #10
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)
コード例 #11
0
ファイル: core.py プロジェクト: EllVEBIT/futaba-1
    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)
コード例 #12
0
    async def channel_delete(self, ctx, *channels: TextChannelConv):
        """ Removes the channel(s) from the restricted role channel list. """

        logger.info(
            "Removing channels to be used for role commands in guild '%s' (%d): [%s]",
            ctx.guild.name,
            ctx.guild.id,
            ", ".join(channel.mention for channel in channels),
        )

        if not channels:
            raise CommandFailed()

        # Remove channels from database
        with self.bot.sql.transaction():
            for channel in channels:
                self.bot.sql.roles.remove_role_command_channel(
                    ctx.guild, channel)

        # Send response
        embed = discord.Embed(colour=discord.Colour.dark_teal())
        embed.set_author(name="Removed channels to be used for adding roles")

        all_channels = self.bot.sql.roles.get_role_command_channels(ctx.guild)
        descr = StringBuilder(sep=", ")
        for channel in channels:
            descr.write(channel.mention)
        embed.add_field(name="Removed", value=str(descr))

        descr.clear()
        for channel in all_channels:
            descr.write(channel.mention)
        embed.add_field(name="Remaining", value=str(descr) or "(none)")
        await ctx.send(embed=embed)

        # Send journal event
        self.channel_journal(ctx.guild)
コード例 #13
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)