示例#1
0
    async def snippetclear(self, ctx):
        async with self.bot.pool.acquire() as conn:
            await conn.execute("DELETE FROM snippet WHERE guild=$1",
                               ctx.guild.id)

        await ctx.send(Embed("All snippets were removed successfully."))
示例#2
0
async def select_guild(bot, message, msg):
    guilds = {}

    user_guilds = await get_user_guilds(bot, message.author)
    if user_guilds is None:
        embed = Embed(
            f"Please [click here]({bot.config.BASE_URI}/login?redirect=/authorized) to verify. "
            "This will allow the bot to see your servers and is required for the bot to function. "
            "Then, close the page and return back here."
        )
        await msg.edit(embed)

        await bot.state.set(
            f"user_select:{message.author.id}",
            {
                "message": message._data,
                "msg": msg._data,
            },
        )

        return

    for guild in user_guilds:
        guild = await bot.get_guild(guild)
        if guild is None:
            continue

        channel = None
        for text_channel in await guild.text_channels():
            if is_modmail_channel(text_channel, message.author.id):
                channel = text_channel

        if not channel:
            guilds[str(guild.id)] = (guild.name, False)
        else:
            guilds[str(guild.id)] = (guild.name, True)

    if len(guilds) == 0:
        await message.channel.send(ErrorEmbed("Oops, something strange happened. No server found."))
        return

    embeds = []

    for chunk in [list(guilds.items())[i : i + 10] for i in range(0, len(guilds), 10)]:
        embed = Embed(
            "Select Server",
            "Please select the server you want to send this message to. You can do so by reacting "
            "with the corresponding emote.",
        )
        embed.set_footer("Use the reactions to flip pages.")

        for guild, value in chunk:
            embed.add_field(
                f"{len(embed.fields) + 1}: {value[0]}",
                f"{'Create a new ticket.' if value[1] is False else 'Existing ticket.'}\n"
                f"Server ID: {guild}",
            )

        embeds.append(embed)

    await msg.edit(embeds[0])

    await msg.add_reaction("◀️")
    await msg.add_reaction("▶️")
    for reaction in ["1⃣", "2⃣", "3⃣", "4⃣", "5⃣", "6⃣", "7⃣", "8⃣", "9⃣", "🔟"][
        : len(embeds[0].fields)
    ]:
        await msg.add_reaction(reaction)

    await bot.state.set(
        f"reaction_menu:{msg.channel.id}:{msg.id}",
        {
            "kind": "selection",
            "end": int(time.time()) + 180,
            "data": {
                "msg": message._data,
                "page": 0,
                "all_pages": [embed.to_dict() for embed in embeds],
            },
        },
    )
    await bot.state.sadd("reaction_menu_keys", f"reaction_menu:{msg.channel.id}:{msg.id}")
示例#3
0
 async def restart(self, ctx):
     await ctx.send(Embed("Restarting..."))
     await self.bot.session.post(f"{self.bot.http_uri}/restart")
示例#4
0
    async def serverinfo(self, ctx):
        guild = await self.bot.get_guild(ctx.guild.id)

        embed = Embed(title="Server Information")
        embed.add_field("Name", guild.name)
        embed.add_field("ID", guild.id)
        embed.add_field("Owner", f"<@{guild.owner_id}>" if guild.owner_id else "Unknown")
        embed.add_field(
            "Icon",
            f"[Link]({guild.icon_url_as(static_format='png')})" if guild.icon else "*Not set*",
        )
        embed.add_field("Server Created", guild.created_at.replace(microsecond=0))
        embed.add_field("Members", guild.member_count)
        embed.add_field("Channels", str(len(await guild.channels())))
        embed.add_field("Roles", str(len(await guild.roles())))
        embed.add_field("Emojis", str(len(await guild.emojis())))

        if guild.icon:
            embed.set_thumbnail(guild.icon_url)

        await ctx.send(embed)
示例#5
0
    async def on_raw_reaction_add(self, payload):
        if payload.user_id == self.bot.id:
            return

        if payload.member:
            return

        if payload.emoji.name in ["✅", "🔁", "❌"]:
            menu, channel, msg = await tools.get_reaction_menu(
                self.bot, payload, "confirmation")
            if menu is None:
                return

            guild = await self.bot.get_guild(menu["data"]["guild"])
            message = Message(state=self.bot.state,
                              channel=channel,
                              data=menu["data"]["msg"])

            if payload.emoji.name == "✅":
                await self.send_mail(message, guild)
                await msg.delete()
            else:
                if payload.emoji.name == "🔁":
                    await msg.edit(Embed("Loading servers..."))
                    self.bot.loop.create_task(
                        tools.select_guild(self.bot, message, msg))
                elif payload.emoji.name == "❌":
                    await msg.edit(
                        ErrorEmbed("Request cancelled successfully."))

                for reaction in ["✅", "🔁", "❌"]:
                    await msg.remove_reaction(reaction, self.bot.user)

            await self.bot.state.delete(f"reaction_menu:{channel.id}:{msg.id}")
            await self.bot.state.srem(
                "reaction_menu_keys",
                f"reaction_menu:{channel.id}:{msg.id}",
            )
            return

        numbers = ["1⃣", "2⃣", "3⃣", "4⃣", "5⃣", "6⃣", "7⃣", "8⃣", "9⃣", "🔟"]
        arrows = ["◀️", "▶️"]
        if payload.emoji.name in numbers + arrows:
            menu, channel, msg = await tools.get_reaction_menu(
                self.bot, payload, "selection")
            if menu is None:
                return

            page = menu["data"]["page"]
            all_pages = menu["data"]["all_pages"]

            if payload.emoji.name not in arrows:
                chosen = numbers.index(payload.emoji.name)
                await msg.delete()

                fields = all_pages[page]["fields"]
                if chosen > len(fields):
                    return

                guild = await self.bot.get_guild(
                    fields[chosen]["value"].split()[-1])
                message = Message(state=self.bot.state,
                                  channel=channel,
                                  data=menu["data"]["msg"])
                await self.send_mail(message, guild)

                await self.bot.state.delete(
                    f"reaction_menu:{channel.id}:{msg.id}")
                await self.bot.state.srem(
                    "reaction_menu_keys",
                    f"reaction_menu:{channel.id}:{msg.id}",
                )
                return

            if payload.emoji.name == "◀️" and page > 0:
                page -= 1

                new_page = Embed.from_dict(all_pages[page])
                await msg.edit(new_page)

                for reaction in numbers[:len(new_page.fields)]:
                    await msg.add_reaction(reaction)

            if payload.emoji.name == "▶️" and page < len(all_pages) - 1:
                page += 1

                new_page = Embed.from_dict(all_pages[page])
                await msg.edit(new_page)

                for reaction in numbers[len(new_page.fields):]:
                    try:
                        await msg.remove_reaction(reaction, self.bot.user)
                    except discord.NotFound:
                        pass

            menu["data"]["page"] = page
            menu["end"] = int(time.time()) + 180
            await self.bot.state.set(f"reaction_menu:{channel.id}:{msg.id}",
                                     menu)
示例#6
0
    async def on_message(self, message):
        if message.author.bot or not isinstance(message.channel,
                                                discord.DMChannel):
            return

        for prefix in [
                f"<@{self.bot.id}> ", f"<@!{self.bot.id}> ",
                self.bot.config.DEFAULT_PREFIX
        ]:
            if message.content.startswith(prefix):
                return

        if await tools.is_user_banned(self.bot, message.author):
            await message.channel.send(
                ErrorEmbed("You are banned from this bot."))
            return

        guild = None
        async for msg in message.channel.history(limit=30):
            if (msg.author.id == self.bot.id and len(msg.embeds) > 0
                    and msg.embeds[0].title
                    in ["Message Received", "Message Sent"]):
                guild = msg.embeds[0].footer.text.split()[-1]
                guild = await self.bot.get_guild(int(guild))
                break

        settings = await tools.get_user_settings(self.bot, message.author.id)
        confirmation = True if settings is None or settings[
            0] is True else False

        if guild and confirmation is True:
            embed = Embed(
                "Confirmation",
                f"You're sending this message to **{guild.name}** (ID: {guild.id}). React with ✅ "
                "to confirm.\nWant to send to another server? React with 🔁.\nTo cancel this "
                "request, react with ❌.",
            )
            embed.set_footer(
                "Tip: You can disable confirmation messages with the "
                f"{self.bot.config.DEFAULT_PREFIX}confirmation command.")
            msg = await message.channel.send(embed)

            await msg.add_reaction("✅")
            await msg.add_reaction("🔁")
            await msg.add_reaction("❌")

            await self.bot.state.set(
                f"reaction_menu:{msg.channel.id}:{msg.id}",
                {
                    "kind": "confirmation",
                    "end": int(time.time()) + 180,
                    "data": {
                        "guild": guild.id,
                        "msg": message._data,
                    },
                },
            )
            await self.bot.state.sadd(
                "reaction_menu_keys",
                f"reaction_menu:{msg.channel.id}:{msg.id}",
            )
        elif guild:
            await self.send_mail(message, guild)
        else:
            msg = await message.channel.send(Embed("Loading servers..."))
            await tools.select_guild(self.bot, message, msg)
示例#7
0
 async def invite(self, ctx):
     await ctx.send(Embed("Invite Link", f"{self.bot.config.BASE_URI}/invite"))
示例#8
0
    async def help(self, ctx, *, command: str = None):
        if command:
            command = self.bot.get_command(command.lower())
            if not command:
                await ctx.send(
                    embed=Embed(
                        description=f"That command does not exist. Use `{ctx.prefix}help` to see all the commands.",
                    )
                )
                return

            embed = Embed(title=command.name, description=command.description)
            usage = "\n".join([ctx.prefix + x.strip() for x in command.usage.split("\n")])
            embed.add_field(name="Usage", value=f"```{usage}```", inline=False)

            if len(command.aliases) > 1:
                embed.add_field(name="Aliases", value=f"`{'`, `'.join(command.aliases)}`")
            elif len(command.aliases) > 0:
                embed.add_field(name="Alias", value=f"`{command.aliases[0]}`")

            await ctx.send(embed=embed)
            return

        bot_user = await self.bot.real_user()

        all_pages = []

        page = Embed(
            title=f"{bot_user.name} Help Menu",
            description="Thank you for using ModMail! Please direct message me if you wish to contact staff. You can "
            "also invite me to your server with the link below, or join our support server if you need further help.\n"
            f"\nDon't forget to check out our partners with the `{ctx.prefix}partners` command!",
        )
        page.set_thumbnail(url=bot_user.avatar_url)
        page.set_footer(text="Use the reactions to flip pages.")
        page.add_field(name="Invite", value="https://modmail.xyz/invite", inline=False)
        page.add_field(name="Support Server", value="https://discord.gg/wjWJwJB", inline=False)
        all_pages.append(page)

        page = Embed(title=f"{bot_user.name} Help Menu")
        page.set_thumbnail(url=bot_user.avatar_url)
        page.set_footer(text="Use the reactions to flip pages.")
        page.add_field(
            name="About ModMail",
            value="ModMail is a feature-rich Discord bot designed to enable your server members to contact staff "
            "easily. A new channel is created whenever a user messages the bot, and the channel will serve as a shared "
            "inbox for seamless communication between staff and the user.",
            inline=False,
        )
        page.add_field(
            name="Getting Started",
            value="Follow these steps to get the bot all ready to serve your server!\n1. Invite the bot with "
            f"[this link](https://modmail.xyz/invite)\n2. Run `{ctx.prefix}setup`, there will be an interactive guide."
            f"\n3. All done! For a full list of commands, see `{ctx.prefix}help`.",
            inline=False,
        )
        all_pages.append(page)

        for cog_name in self.bot.cogs:
            if cog_name in ["Owner", "Admin"]:
                continue

            cog = self.bot.get_cog(cog_name)
            cog_commands = cog.get_commands()

            if len(cog_commands) == 0:
                continue

            page = Embed(
                title=cog_name,
                description=f"My prefix is `{ctx.prefix}`. Use `{ctx.prefix}help <command>` for more information on a "
                "command.",
            )

            page.set_author(name=f"{bot_user.name} Help Menu", icon_url=bot_user.avatar_url)
            page.set_thumbnail(url=bot_user.avatar_url)
            page.set_footer(text="Use the reactions to flip pages.")

            for cmd in cog_commands:
                page.add_field(name=cmd.name, value=cmd.description, inline=False)

            all_pages.append(page)

        for page in range(len(all_pages)):
            all_pages[page].set_footer(text=f"Use the reactions to flip pages. (Page {page + 1}/{len(all_pages)})")

        await tools.create_paginator(self.bot, ctx, all_pages)
示例#9
0
    async def stats(self, ctx):
        total_seconds = int((datetime.utcnow() - await self.bot.started()).total_seconds())
        hours, remainder = divmod(total_seconds, 3600)
        minutes, seconds = divmod(remainder, 60)
        days, hours = divmod(hours, 24)

        bot_user = await self.bot.real_user()

        embed = Embed(
            "ModMail Statistics",
            f"Visit the bot status page [here]({self.bot.config.BASE_URI}/status) for more "
            "information.",
        )
        embed.add_field("Owner", "CHamburr#2591")
        embed.add_field("Bot Version", self.bot.version)
        if days:
            embed.add_field("Uptime", f"{days}d {hours}h {minutes}m {seconds}s")
        else:
            embed.add_field("Uptime", f"{hours}h {minutes}m {seconds}s")
        embed.add_field("Clusters", self.bot.cluster_count)
        if ctx.guild:
            embed.add_field("Shards", f"{ctx.guild.shard_id + 1}/{await self.bot.shard_count()}")
        else:
            embed.add_field("Shards", f"0/{await self.bot.shard_count()}")
        embed.add_field("Servers", str(await self.bot.state.scard("guild_keys")))
        embed.add_field("CPU Usage", f"{psutil.cpu_percent(interval=None)}%")
        embed.add_field("RAM Usage", f"{psutil.virtual_memory().percent}%")
        embed.add_field("Python Version", platform.python_version())
        embed.set_thumbnail(bot_user.avatar_url)

        await ctx.send(embed)
示例#10
0
 async def partners(self, ctx):
     await ctx.send(Embed("Partners", f"{self.bot.config.BASE_URI}/partners"))
示例#11
0
    async def close_channel(self, ctx, reason, anon: bool = False):
        await ctx.send(Embed("Closing channel..."))

        data = await tools.get_data(self.bot, ctx.guild.id)

        if data[7] is True:
            messages = await ctx.channel.history(limit=10000).flatten()

        try:
            await ctx.channel.delete()
        except discord.Forbidden:
            await ctx.send(
                ErrorEmbed("Missing permissions to delete this channel."))
            return

        embed = ErrorEmbed(
            "Ticket Closed",
            reason if reason else "No reason was provided.",
            timestamp=True,
        )
        embed.set_author(
            str(ctx.author) if anon is False else "Anonymous#0000",
            ctx.author.avatar_url if anon is False else
            "https://cdn.discordapp.com/embed/avatars/0.png",
        )
        embed.set_footer(f"{ctx.guild.name} | {ctx.guild.id}",
                         ctx.guild.icon_url)

        try:
            member = await ctx.guild.fetch_member(
                tools.get_modmail_user(ctx.channel).id)
        except discord.NotFound:
            member = None
        else:
            dm_channel = tools.get_modmail_channel(self.bot, ctx.channel)

            if data[6]:
                embed2 = Embed(
                    "Closing Message",
                    tools.tag_format(data[6], member),
                    colour=0xFF4500,
                    timestamp=True,
                )
                embed2.set_footer(f"{ctx.guild.name} | {ctx.guild.id}",
                                  ctx.guild.icon_url)
                try:
                    await dm_channel.send(embed2)
                except discord.Forbidden:
                    pass

            try:
                await dm_channel.send(embed)
            except discord.Forbidden:
                pass

        if data[4] is None:
            return

        channel = await ctx.guild.get_channel(data[4])
        if channel is None:
            return

        if member is None:
            try:
                member = await self.bot.fetch_user(
                    tools.get_modmail_user(ctx.channel))
            except discord.NotFound:
                pass

        if member:
            embed.set_footer(f"{member} | {member.id}", member.avatar_url)
        else:
            embed.set_footer(
                "Unknown#0000 | 000000000000000000",
                "https://cdn.discordapp.com/embed/avatars/0.png",
            )

        embed.set_author(
            str(ctx.author) if anon is False else f"{ctx.author} (Anonymous)",
            ctx.author.avatar_url,
        )

        if data[7] is True:
            history = ""

            for message in messages:
                if message.author.bot and (
                        message.author.id != self.bot.id
                        or len(message.embeds) <= 0 or message.embeds[0].title
                        not in ["Message Received", "Message Sent"]):
                    continue

                if not message.author.bot and message.content == "":
                    continue

                if message.author.bot:
                    if not message.embeds[0].author.name:
                        author = f"{' '.join(message.embeds[0].footer.text.split()[:-2])} (User)"
                    elif message.embeds[0].author.name.endswith(
                            " (Anonymous)"):
                        author = f"{message.embeds[0].author.name[:-12]} (Staff)"
                    else:
                        author = f"{message.embeds[0].author.name} (Staff)"

                    description = message.embeds[0].description

                    for attachment in [
                            field.value for field in message.embeds[0].fields
                            if field.name.startswith("Attachment ")
                    ]:
                        if not description:
                            description = f"(Attachment: {attachment})"
                        else:
                            description += f" (Attachment: {attachment})"
                else:
                    author = f"{message.author} (Comment)"
                    description = message.content

                history = (
                    f"[{str(message.created_at.replace(microsecond=0))}] {author}: {description}\n"
                    + history)

            history = io.BytesIO(history.encode())

            file = discord.File(
                history,
                f"modmail_log_{tools.get_modmail_user(ctx.channel).id}.txt")

            try:
                msg = await channel.send(embed, file=file)
            except discord.Forbidden:
                return

            log_url = msg.attachments[0].url[39:-4]
            log_url = log_url.replace("modmail_log_", "")
            log_url = [hex(int(some_id))[2:] for some_id in log_url.split("/")]
            log_url = f"{self.bot.config.BASE_URI}/logs/{'-'.join(log_url)}"
            embed.add_field("Message Logs", log_url, False)

            await asyncio.sleep(0.5)
            await msg.edit(embed)
            return

        try:
            await channel.send(embed)
        except discord.Forbidden:
            pass
示例#12
0
    async def blacklistclear(self, ctx):
        async with self.bot.pool.acquire() as conn:
            await conn.execute("UPDATE data SET blacklist=$1 WHERE guild=$2",
                               [], ctx.guild.id)

        await ctx.send(Embed("The blacklist is cleared successfully."))
示例#13
0
    async def viewsnippet(self, ctx, *, name: str = None):
        if name:
            async with self.bot.pool.acquire() as conn:
                res = await conn.fetchrow(
                    "SELECT name, content FROM snippet WHERE name=$1 AND guild=$2",
                    name.lower(),
                    ctx.guild.id,
                )

            if not res:
                await ctx.send(embed=ErrorEmbed(
                    description="A snippet with that name was not found."))
                return

            embed = Embed(title="Snippet")
            embed.add_field(name="Name", value=res[0], inline=False)
            embed.add_field(name="Content", value=res[1], inline=False)
            await ctx.send(embed=embed)
            return

        async with self.bot.pool.acquire() as conn:
            res = await conn.fetch(
                "SELECT name, content FROM snippet WHERE guild=$1",
                ctx.guild.id)

        if not res:
            await ctx.send(embed=Embed(
                description="No snippet has been added yet."))
            return

        all_pages = []
        for chunk in [res[i:i + 10] for i in range(0, len(res), 10)]:
            page = Embed(title="Snippets")

            for snippet in chunk:
                page.add_field(
                    name=snippet[0],
                    value=snippet[1][:97] +
                    "..." if len(snippet[1]) > 100 else snippet[1],
                    inline=False,
                )

            page.set_footer(text="Use the reactions to flip pages.")
            all_pages.append(page)

        if len(all_pages) == 1:
            embed = all_pages[0]
            embed.set_footer(text=discord.Embed.Empty)
            await ctx.send(embed=embed)
            return

        await tools.create_paginator(self.bot, ctx, all_pages)
示例#14
0
    async def stats(self, ctx):
        total_seconds = int((datetime.utcnow() - await self.bot.started()).total_seconds())
        hours, remainder = divmod(total_seconds, 3600)
        minutes, seconds = divmod(remainder, 60)
        days, hours = divmod(hours, 24)

        bot_user = await self.bot.real_user()

        embed = Embed(
            title=f"{bot_user.name} Statistics",
            description="Visit the bot status page [here](https://status.modmail.xyz) for more information.",
        )
        embed.add_field(name="Owner", value="CHamburr#2591")
        embed.add_field(name="Bot Version", value=self.bot.version)
        if days:
            embed.add_field(name="Uptime", value=f"{days}d {hours}h {minutes}m {seconds}s")
        else:
            embed.add_field(name="Uptime", value=f"{hours}h {minutes}m {seconds}s")
        embed.add_field(name="Clusters", value=self.bot.cluster_count)
        if ctx.guild:
            embed.add_field(name="Shards", value=f"{ctx.guild.shard_id + 1}/{await self.bot.shard_count()}")
        else:
            embed.add_field(name="Shards", value=f"0/{await self.bot.shard_count()}")
        embed.add_field(name="Servers", value=str(await self.bot.state.scard("guild_keys")))
        embed.add_field(name="Channels", value=str(await self.bot.state.scard("channel_keys")))
        embed.add_field(name="Users", value=str(await self.bot.state.scard("user_keys")))
        embed.add_field(name="CPU Usage", value=f"{psutil.cpu_percent(interval=None)}%")
        embed.add_field(name="RAM Usage", value=f"{psutil.virtual_memory().percent}%")
        embed.add_field(name="Platform", value=" ".join(distro.linux_distribution()[:2]))
        embed.add_field(name="Python Version", value=platform.python_version())
        embed.set_thumbnail(url=bot_user.avatar_url)

        await ctx.send(embed=embed)
示例#15
0
 async def support(self, ctx):
     await ctx.send(Embed("Support Server", "https://discord.gg/wjWJwJB"))
示例#16
0
    async def partners(self, ctx):
        all_pages = []

        page = Embed(
            title="Discord Templates",
            description="Discord Templates is the place for you to discover a huge variety of Discord server templates "
            "for all purposes.",
        )
        page.add_field(name="Link", value="https://discordtemplates.me")
        page.set_thumbnail(
            url="https://cdn.discordapp.com/icons/696179394057732237/cf54e042456638eba2ea5abddfc7910e.png"
        )
        all_pages.append(page)

        page = Embed(
            title="Call of Duty Mobile",
            description="The Activision-supported, community-run discord for the Call of Duty: Mobile Community.",
        )
        page.add_field(name="Link", value="https://discord.gg/codmobile")
        page.set_thumbnail(
            url="https://cdn.discordapp.com/icons/619762818266431547/a_cce3e6b3b6e64dcf7bbb6fa92c9fc4e6.gif"
        )
        all_pages.append(page)

        page = Embed(
            title="Eden of Gaming",
            description="Eden of Gaming is a global gaming community that aims to share knowledge and build "
            "relationships between members and fellow global gaming communities.",
        )
        page.add_field(name="Link", value="https://discord.gg/edenofgaming")
        page.set_thumbnail(
            url="https://cdn.discordapp.com/icons/457151179072339978/a_6b2bf427b3f07f209386dcf85ea94a9a.gif"
        )
        all_pages.append(page)

        page = Embed(
            title="Homework Help",
            description="Got assignments? Need help? Then come join Discord's premier hub for students, scholars, "
            "professionals, and hobbyists interested in discussions, challenges, as well as news, views, and reviews "
            "that runs the gamut of academic disciplines.",
        )
        page.add_field(name="Link", value="https://discord.gg/homework")
        page.set_thumbnail(
            url="https://cdn.discordapp.com/icons/238956364729155585/468ac0a7dc84db45d018e0c442fe8447.png"
        )
        all_pages.append(page)

        page = Embed(
            title="Otzdarva's Dungeon",
            description="Otzdarva's Dungeon is a community for the Dead by Daylight streamer Otzdarva, also known for "
            "being a PUBG and Dark Souls YouTuber in the past.",
        )
        page.add_field(name="Link", value="https://discord.gg/otzdarva")
        page.set_thumbnail(
            url="https://cdn.discordapp.com/icons/227900298549657601/a_74313704119f88dc252e9b0b98c3ab25.gif"
        )
        all_pages.append(page)

        page = Embed(
            title="DOOM",
            description="Hell’s armies have invaded Earth. Become the Slayer in an epic single-player campaign to "
            "conquer demons across dimensions and stop the final destruction of humanity. The only thing they fear... "
            "is you. RAZE HELL in DOOM Eternal!",
        )
        page.add_field(name="Link", value="https://discord.gg/doom")
        page.set_thumbnail(
            url="https://cdn.discordapp.com/icons/162891400684371968/a_4363040f917b4920a2e78da1e302d9dc.gif"
        )
        all_pages.append(page)

        page = Embed(
            title="Sea of Thieves",
            description="One of the longest running and largest community-run Sea of Thieves Discord servers. A great "
            "and most of all welcoming place to chat about Sea of Thieves and maybe find a few crew mates along the "
            "way.",
        )
        page.add_field(name="Link", value="https://discord.gg/seaofthievescommunity")
        page.set_thumbnail(
            url="https://cdn.discordapp.com/icons/209815380946845697/a_04c8ae80dce6e6ef1e3d574dca61b4a2.png"
        )
        all_pages.append(page)

        page = Embed(
            title="Underlords",
            description="Underlords Discord server acts as a secondary platform to r/Underlords where users can have "
            "casual chit-chat, give suggestions, share tactics and discuss everything related to Underlords.",
        )
        page.add_field(name="Link", value="https://discord.gg/underlords")
        page.set_thumbnail(
            url="https://cdn.discordapp.com/icons/580534040692654101/a_0a6f7616c7d9b98f740809dbea272967.gif"
        )
        all_pages.append(page)

        page = Embed(
            title="CH's amburr",
            description="CH's amburr is my personal community server. It is a fun and friendly place where you can "
            "talk about everything cool.",
        )
        page.add_field(name="Link", value="https://discord.gg/TYe3U4w")
        page.set_thumbnail(
            url="https://cdn.discordapp.com/icons/447732123340767232/5a1064a156540e36e22a38abc527c737.png"
        )
        all_pages.append(page)

        page = Embed(
            title="Member Count",
            description="Member Count is another bot that I am actively developing on. It shows stats on your server "
            "using channel names.",
        )
        page.add_field(name="Link", value="https://discordbots.org/bot/membercount")
        page.set_thumbnail(
            url="https://cdn.discordapp.com/icons/496964682972659712/0b61c5cb7b9ace8f8f5e2fef37cacb5b.png"
        )
        all_pages.append(page)

        for page in range(len(all_pages)):
            bot_user = await self.bot.real_user()
            all_pages[page].set_author(name=f"{bot_user.name} partners", icon_url=bot_user.avatar_url)
            all_pages[page].set_footer(text=f"Use the reactions to flip pages. (Page {page + 1}/{len(all_pages)})")

        await tools.create_paginator(self.bot, ctx, all_pages)
示例#17
0
 async def website(self, ctx):
     await ctx.send(Embed("Website", f"{self.bot.config.BASE_URI}"))
示例#18
0
    async def send_mail_mod(self, message, prefix, anon=False, snippet=False):
        self.bot.prom.tickets_message.inc({})

        data = await tools.get_data(self.bot, message.guild.id)
        user = tools.get_modmail_user(message.channel)

        if user.id in data[9]:
            await message.channel.send(
                ErrorEmbed(
                    "That user is blacklisted from sending a message here. You need to whitelist "
                    "them before you can send them a message."))
            return

        try:
            member = await message.guild.fetch_member(user.id)
        except discord.NotFound:
            await message.channel.send(
                ErrorEmbed(
                    f"The user was not found. Use `{prefix}close [reason]` to close this channel."
                ))
            return

        if snippet is True:
            message.content = tools.tag_format(message.content, member)

        embed = Embed("Message Received",
                      message.content,
                      colour=0xFF4500,
                      timestamp=True)
        embed.set_author(
            str(message.author) if anon is False else "Anonymous#0000",
            message.author.avatar_url if anon is False else
            "https://cdn.discordapp.com/embed/avatars/0.png",
        )
        embed.set_footer(f"{message.guild.name} | {message.guild.id}",
                         message.guild.icon_url)

        files = []
        for file in message.attachments:
            saved_file = io.BytesIO()
            await file.save(saved_file)
            files.append(discord.File(saved_file, file.filename))

        dm_channel = tools.get_modmail_channel(self.bot, message.channel)

        try:
            dm_message = await dm_channel.send(embed, files=files)
        except discord.Forbidden:
            await message.channel.send(
                ErrorEmbed(
                    "The message could not be sent. The user might have disabled Direct Messages."
                ))
            return

        embed.title = "Message Sent"
        embed.set_author(
            str(message.author)
            if anon is False else f"{message.author} (Anonymous)",
            message.author.avatar_url,
        )
        embed.set_footer(f"{member} | {member.id}", member.avatar_url)

        for count, attachment in enumerate(
            [attachment.url for attachment in dm_message.attachments],
                start=1):
            embed.add_field(f"Attachment {count}", attachment, False)

        for file in files:
            file.reset()

        await message.channel.send(embed, files=files)

        try:
            await message.delete()
        except (discord.Forbidden, discord.NotFound):
            pass
示例#19
0
 async def source(self, ctx):
     await ctx.send(Embed("GitHub Repository", "https://github.com/chamburr/modmail"))
示例#20
0
    async def send_mail(self, message, guild):
        self.bot.prom.tickets_message.inc({})

        if not guild:
            await message.channel.send(ErrorEmbed("The server was not found."))
            return

        try:
            member = await guild.fetch_member(message.author.id)
        except discord.NotFound:
            await message.channel.send(
                ErrorEmbed(
                    "You are not in that server, and the message is not sent.")
            )
            return

        data = await tools.get_data(self.bot, guild.id)

        category = await guild.get_channel(data[2])
        if not category:
            await message.channel.send(
                ErrorEmbed(
                    "A ModMail category is not found. The bot is not set up properly in the server."
                ))
            return

        if message.author.id in data[9]:
            await message.channel.send(
                ErrorEmbed(
                    "That server has blacklisted you from sending a message there."
                ))
            return

        channel = None
        for text_channel in await guild.text_channels():
            if tools.is_modmail_channel(text_channel, message.author.id):
                channel = text_channel
                break

        if channel is None:
            self.bot.prom.tickets.inc({})

            name = "".join([
                x for x in message.author.name.lower()
                if x not in string.punctuation and x.isprintable()
            ])

            if name:
                name = name + f"-{message.author.discriminator}"
            else:
                name = message.author.id

            try:
                channel = await guild.create_text_channel(
                    name=name,
                    category=category,
                    topic=
                    f"ModMail Channel {message.author.id} {message.channel.id} (Please do "
                    "not change this)",
                )
            except discord.HTTPException as e:
                await message.channel.send(
                    ErrorEmbed(
                        "An HTTPException error occurred. Please contact an admin on the server "
                        f"with the following information: {e.text} ({e.code})."
                    ))
                return

            log_channel = await guild.get_channel(data[4])
            if log_channel:
                embed = Embed(
                    title="New Ticket",
                    colour=0x00FF00,
                    timestamp=True,
                )
                embed.set_footer(
                    f"{message.author.name}#{message.author.discriminator} | "
                    f"{message.author.id}",
                    message.author.avatar_url,
                )

                try:
                    await log_channel.send(embed)
                except discord.Forbidden:
                    pass

            prefix = await tools.get_guild_prefix(self.bot, guild)

            embed = Embed(
                "New Ticket",
                "Type a message in this channel to reply. Messages starting with the server prefix "
                f"`{prefix}` are ignored, and can be used for staff discussion. Use the command "
                f"`{prefix}close [reason]` to close this ticket.",
                timestamp=True,
            )
            embed.add_field("User",
                            f"<@{message.author.id}> ({message.author.id})")
            embed.add_field(
                "Roles",
                "*None*" if len(member._roles) == 0 else " ".join(
                    [f"<@&{x}>" for x in member._roles]),
            )
            embed.set_footer(f"{message.author} | {message.author.id}",
                             message.author.avatar_url)

            roles = []
            for role in data[8]:
                if role == guild.id:
                    roles.append("@everyone")
                elif role == -1:
                    roles.append("@here")
                else:
                    roles.append(f"<@&{role}>")

            try:
                await channel.send(" ".join(roles), embed=embed)
            except discord.HTTPException:
                await message.channel.send(
                    ErrorEmbed(
                        "The bot is missing permissions. Please contact an admin on the server."
                    ))
                return

            if data[5]:
                embed = Embed(
                    "Greeting Message",
                    tools.tag_format(data[5], message.author),
                    colour=0xFF4500,
                    timestamp=True,
                )
                embed.set_footer(f"{guild.name} | {guild.id}", guild.icon_url)

                await message.channel.send(embed)

        embed = Embed("Message Sent",
                      message.content,
                      colour=0x00FF00,
                      timestamp=True)
        embed.set_footer(f"{guild.name} | {guild.id}", guild.icon_url)

        files = []
        for file in message.attachments:
            saved_file = io.BytesIO()
            await file.save(saved_file)
            files.append(discord.File(saved_file, file.filename))

        dm_message = await message.channel.send(embed, files=files)

        embed.title = "Message Received"
        embed.set_footer(
            f"{message.author.name}#{message.author.discriminator} | {message.author.id}",
            message.author.avatar_url,
        )

        for count, attachment in enumerate(
            [attachment.url for attachment in dm_message.attachments],
                start=1):
            embed.add_field(f"Attachment {count}", attachment, False)

        for file in files:
            file.reset()

        try:
            await channel.send(embed, files=files)
        except discord.Forbidden:
            await dm_message.delete()
            await message.channel.send(
                ErrorEmbed(
                    "The bot is missing permissions. Please contact an admin on the server."
                ))
示例#21
0
    async def help(self, ctx, *, command: str = None):
        if command:
            command = self.bot.get_command(command.lower())
            if not command:
                await ctx.send(
                    Embed(
                        f"That command does not exist. Use `{ctx.prefix}help` to see all the "
                        "commands.",
                    )
                )
                return

            embed = Embed(command.name, command.description)
            usage = "\n".join([ctx.prefix + x.strip() for x in command.usage.split("\n")])
            embed.add_field("Usage", f"```{usage}```", False)

            if len(command.aliases) > 1:
                embed.add_field("Aliases", f"`{'`, `'.join(command.aliases)}`")
            elif len(command.aliases) > 0:
                embed.add_field("Alias", f"`{command.aliases[0]}`")

            await ctx.send(embed)
            return

        bot_user = await self.bot.real_user()

        all_pages = []

        page = Embed(
            "ModMail Help Menu",
            "ModMail is a feature-rich Discord bot designed to enable your server members to "
            "contact staff easily.\n\nPlease direct message me if you wish to contact staff. You "
            "can also invite me to your server with the link below, or join our support server if "
            f"you need further help.\n\nTo setup the bot, run `{ctx.prefix}setup`.",
        )
        page.set_thumbnail(bot_user.avatar_url)
        page.set_footer("Use the reactions to flip pages.")
        page.add_field("Invite", f"{self.bot.config.BASE_URI}/invite", False)
        page.add_field("Support Server", "https://discord.gg/wjWJwJB", False)
        all_pages.append(page)

        for cog_name in self.bot.cogs:
            if cog_name in ["Owner", "Admin"]:
                continue

            cog = self.bot.get_cog(cog_name)
            cog_commands = cog.get_commands()

            if len(cog_commands) == 0:
                continue

            page = Embed(
                cog_name,
                f"My prefix is `{ctx.prefix}`. Use `{ctx.prefix}help <command>` for more "
                "information on a command.",
            )

            page.set_author("ModMail Help Menu", bot_user.avatar_url)
            page.set_thumbnail(bot_user.avatar_url)
            page.set_footer("Use the reactions to flip pages.")

            for cmd in cog_commands:
                page.add_field(cmd.name, cmd.description, False)

            all_pages.append(page)

        for page in range(len(all_pages)):
            all_pages[page].set_footer(
                f"Use the reactions to flip pages. (Page {page + 1}/{len(all_pages)})"
            )

        await tools.create_paginator(self.bot, ctx, all_pages)
示例#22
0
    async def new(self, ctx, *, message: str):
        ctx.message.content = message

        msg = await ctx.send(Embed("Loading servers..."))
        await tools.select_guild(self.bot, ctx.message, msg)
示例#23
0
    async def closingmessage(self, ctx, *, text: str = None):
        async with self.bot.pool.acquire() as conn:
            await conn.execute("UPDATE data SET goodbye=$1 WHERE guild=$2", text, ctx.guild.id)

        await ctx.send(Embed("The closing message is set successfully."))
示例#24
0
    async def userinfo(self, ctx, *, member: MemberConverter = None):
        if member is None:
            member = ctx.message.member

        roles = [f"<@&{role}>" for role in member._roles]
        if len(roles) == 0:
            roles.append("*No roles*")

        embed = Embed(title="User Information")
        embed.add_field("Name", str(member))
        embed.add_field("ID", member.id)
        embed.add_field("Nickname", member.nick if member.nick else "*Not set*")
        embed.add_field("Avatar", f"[Link]({member.avatar_url_as(static_format='png')})")
        embed.add_field(
            "Joined Server",
            member.joined_at.replace(microsecond=0) if member.joined_at else "Unknown",
        )
        embed.add_field("Account Created", member.created_at.replace(microsecond=0))
        embed.add_field(
            "Roles",
            f"{len(roles)} roles" if len(", ".join(roles)) > 1000 else ", ".join(roles),
        )
        embed.set_thumbnail(member.avatar_url)

        await ctx.send(embed)
示例#25
0
    async def viewconfig(self, ctx):
        data = await tools.get_data(self.bot, ctx.guild.id)
        category = await ctx.guild.get_channel(data[2])
        logging_channel = await ctx.guild.get_channel(data[4])

        access_roles = []
        for role in data[3]:
            access_roles.append(f"<@&{role}>")

        ping_roles = []
        for role in data[8]:
            if role == -1:
                ping_roles.append("@here")
            elif role == ctx.guild.id:
                ping_roles.append("@everyone")
            else:
                ping_roles.append(f"<@&{role}>")

        greeting = data[5]
        if greeting and len(greeting) > 1000:
            greeting = greeting[:997] + "..."

        closing = data[6]
        if closing and len(closing) > 1000:
            closing = closing[:997] + "..."

        embed = Embed(title="Server Configurations")
        embed.add_field("Prefix", ctx.prefix)
        embed.add_field("Category", "*Not set*" if category is None else category.name)
        embed.add_field(
            "Access Roles",
            "*Not set*" if len(access_roles) == 0 else " ".join(access_roles),
        )
        embed.add_field("Ping Roles", "*Not set*" if len(ping_roles) == 0 else " ".join(ping_roles))
        embed.add_field(
            "Logging",
            "*Not set*" if logging_channel is None else f"<#{logging_channel.id}>",
        )
        embed.add_field("Advanced Logging", "Enabled" if data[7] is True else "Disabled")
        embed.add_field("Anonymous Messaging", "Enabled" if data[10] is True else "Disabled")
        embed.add_field("Greeting Message", "*Not set*" if greeting is None else greeting, False)
        embed.add_field("Closing message", "*Not set*" if closing is None else closing, False)

        await ctx.send(embed)
示例#26
0
    async def userinfo(self, ctx, *, member: MemberConverter = None):
        if member is None:
            member = ctx.message.member

        roles = [role.name for role in await member.roles()]

        embed = Embed(title="User Information")
        embed.add_field(name="Name", value=str(member))
        embed.add_field(name="ID", value=member.id)
        embed.add_field(name="Nickname",
                        value=member.nick if member.nick else "*Not set*")
        embed.add_field(
            name="Avatar",
            value=f"[Link]({member.avatar_url_as(static_format='png')})")
        embed.add_field(name="Joined Server",
                        value=member.joined_at.replace(
                            microsecond=0) if member.joined_at else "Unknown")
        embed.add_field(name="Account Created",
                        value=member.created_at.replace(microsecond=0))
        embed.add_field(name="Roles",
                        value=f"{len(roles)} roles"
                        if len(", ".join(roles)) > 1000 else ", ".join(roles))
        embed.set_thumbnail(url=member.avatar_url)

        await ctx.send(embed=embed)
示例#27
0
    async def select_guild(self, message, msg=None):
        guilds = {}

        for guild in await self.bot.state.smembers(f"user:{message.author.id}"
                                                   ):
            guild = await self.bot.get_guild(int(guild))

            channel = None
            for text_channel in await guild.text_channels():
                if tools.is_modmail_channel(text_channel, message.author.id):
                    channel = text_channel

            if not channel:
                guilds[str(guild.id)] = (guild.name, False)
            else:
                guilds[str(guild.id)] = (guild.name, True)

        if len(guilds) == 0:
            await message.channel.send(embed=ErrorEmbed(
                description=
                "Oops, no server found. Please change your Discord status to online and try again."
            ))
            return

        embeds = []

        for chunk in [
                list(guilds.items())[i:i + 10]
                for i in range(0, len(guilds), 10)
        ]:
            embed = Embed(
                title="Select Server",
                description=
                "Please select the server you want to send this message to. You can do so by reacting "
                "with the corresponding emote.",
            )
            embed.set_footer(text="Use the reactions to flip pages.")

            for guild, value in chunk:
                embed.add_field(
                    name=f"{len(embed.fields) + 1}: {value[0]}",
                    value=
                    f"{'Create a new ticket.' if value[1] is False else 'Existing ticket.'}\nServer ID: {guild}",
                )

            embeds.append(embed)

        if msg:
            msg = await msg.edit(embed=embeds[0])
        else:
            msg = await message.channel.send(embed=embeds[0])

        await msg.add_reaction("◀")
        await msg.add_reaction("▶")
        for reaction in [
                "1⃣", "2⃣", "3⃣", "4⃣", "5⃣", "6⃣", "7⃣", "8⃣", "9⃣", "🔟"
        ][:len(embeds[0].fields)]:
            await msg.add_reaction(reaction)

        await self.bot.state.sadd(
            "reaction_menus",
            {
                "kind": "selection",
                "channel": msg.channel.id,
                "message": msg.id,
                "end": int(time.time()) + 180,
                "data": {
                    "msg": message._data,
                    "page": 0,
                    "all_pages": [embed.to_dict() for embed in embeds],
                },
            },
        )