예제 #1
0
    async def role(self, ctx, member: discord.Member,
                   roles: commands.Greedy[discord.Role]):
        """
        Toggle the specified role(s) for the given member - if member has the
        role then it is removed, otherwise it is added


        **Note**: for Rammus to assign any roles to any member it must:

        • At least have a higher role than the role(s) it is trying to assign
        • Have the appropriate permissions (manage roles) to do as such

        Not following through with these conditions will cause Rammus to fail
        role assignment
        """
        title = ctx.invoked_with.title()
        desc = ""
        roles_to_add = []
        roles_to_remove = []
        failed_roles = []
        roles = [
            r for r in roles if r.is_default() is False and r.managed is False
        ]

        for role in roles:
            if self.calculate_perms(ctx.author, role) is False:
                failed_roles.append(role)
            elif role in member.roles:
                roles_to_remove.append(role)
            else:
                roles_to_add.append(role)

        # if given no valid roles, end task early to prevent wasted resources
        if roles_to_add == roles_to_remove == failed_roles == EMPTY_LIST:
            desc = "No valid roles given"

            return await ctx.send(embed=create_embed(title, desc))

        add_str = (", ").join([r.mention for r in roles_to_add])
        remove_str = (", ").join([r.mention for r in roles_to_remove])
        fail_str = (", ").join([r.mention for r in failed_roles])

        if roles_to_add != EMPTY_LIST:
            desc += f"Added {add_str} to **{member}**\n"
        if roles_to_remove != EMPTY_LIST:
            desc += f"Removed {remove_str} from **{member}**\n"
        if failed_roles != EMPTY_LIST:
            desc += f"Failed to assign {fail_str} to **{member}**"

        await member.add_roles(*roles_to_add)
        await member.remove_roles(*roles_to_remove)
        await ctx.send(embed=create_embed(title, desc))
예제 #2
0
    async def remove_role(self, ctx, member: discord.Member,
                          roles: commands.Greedy[discord.Role]):
        """
        Remove the specified role(s) from the given member
        """
        title = ctx.invoked_with.title()
        desc = ""
        roles_to_remove = []
        failed_roles = []

        for role in roles:
            if self.calculate_perms(ctx.author, role) is False:
                failed_roles.append(role)
            else:
                roles_to_remove.append(role)

        roles_str = (", ").join([r.mention for r in roles_to_remove])
        failed_str = (", ").join([r.mention for r in failed_roles])

        if roles_to_remove != EMPTY_LIST:
            desc += f"Removed {roles_str} from **{member}**\n"
        if failed_roles != EMPTY_LIST:
            desc += f"Failed to assign {failed_str} to **{member}**"

        await member.remove_roles(*roles_to_remove)
        await ctx.send(embed=create_embed(title, desc))
    async def info(self, ctx, member: discord.Member = None):
        """
        Displays all of the information for either yourself, the given member
        or the server this command is used in
        """
        member = member or ctx.author
        member_format = "%a %d %b %Y %I:%M:%S %p"
        desc = ctx.guild.name
        thumbnail = member.avatar_url
        roles = [r.mention for r in member.roles if r.is_default() is False]
        statuses = {
            discord.Status.online: "Online",
            discord.Status.dnd: "Busy",
            discord.Status.idle: "AFK",
            discord.Status.offline: "Offline"
        }
        fields = {
            "ID": f"`{member.id}`",
            "Status": statuses[member.status],
            "Mobile": member.is_on_mobile() and "✅" or "❌",
            "Joined": member.joined_at.strftime(member_format),
            "Registered": member.created_at.strftime(member_format),
            f"Roles `({len(roles)})`": (" ").join(roles)
        }

        embed = create_embed(desc=desc, fields=fields, inline=True,
                             author=member, thumbnail=thumbnail)

        await ctx.send(embed=embed)
예제 #4
0
    async def mute(self, ctx, member: discord.Member, time: int):
        """
        Prevent the given member from communicating in the server this command
        is used in
        """
        timestamp = datetime.timedelta(seconds=time)
        title = "Mute"
        desc = f"Muted **{member}** for `{timestamp}`"
        limit = 60**2 * 12  # 12h
        mute_role = self.get_mute_role(ctx.guild)
        is_muted = mute_role in member.roles

        if mute_role is None:
            mute_role = await self.setup_mute_role(ctx.guild)

        if time <= 0 or time > limit or is_muted:
            return

        self.mutes.setdefault(member.id, {
            "time": time,
            "task": self.on_second.start(ctx, member)
        })

        await member.add_roles(mute_role)
        await member.edit(mute=True)
        await ctx.send(embed=create_embed(title, desc))
    async def avatar(self, ctx, member: Union[discord.Member, str] = None):
        """
        Sends either your own or the given member's profile picture
        """
        member = member or ctx.author
        is_str = type(member) is str
        lowered = is_str and member.lower() or False
        is_keyword = lowered in ["guild", "server"]
        image = ""

        if is_str and is_keyword:
            member = ctx.guild
        elif is_str and not is_keyword:
            member_found = discord.utils.get(ctx.guild.members, name=member,
                                             display_name=member)

        title = str(member)

        if hasattr(member, "avatar_url_as"):
            image = member.avatar_url_as(static_format="png", size=256)
        elif hasattr(member, "icon_url_as"):
            image = member.icon_url_as(static_format="png", size=256)
        elif member_found is None:
            title = str(ctx.author)
            desc = f'No member exists with the name "{member}"'

        if image:
            desc = f"[Link]({image})"

        embed = create_embed(title, desc, image=image)

        await ctx.send(embed=embed)
    async def _id(self, ctx, *objs: commands.Greedy[Union[discord.Member,
                  discord.TextChannel, discord.Role]]):
        """
        Displays either your own or the given member's unique Discord ID

        **Note**: this command does not support giving server IDs so if you
        would like to retrieve that then feel free to use the `info` command:

        `>info server`
        """
        fields = {}
        objs = objs or [ctx.author]

        for obj in objs:
            if type(obj) is str:
                if obj.lower() in ["server", "guild"]:
                    obj = ctx.guild
                else:
                    return

            fields.setdefault(f"ID for {obj}", f"`{obj.id}`")

        embed = create_embed(fields=fields, author=ctx.author)

        await ctx.send(embed=embed)
예제 #7
0
    async def on_ready(self):
        # debounce
        if self.ready:
            return self.ready

        self.ready = True

        # setup
        #   offline
        print("Setting up...")
        self.setup()

        #   online
        self.init_time = int(time.time())
        self.guild = self.get_guild(464446709146320897)
        self.logs = self.Log(default=self.get_channel(530005984891109386),
                             status=self.get_channel(464446775135174656),
                             error=self.get_channel(530001923399483413))

        # background tasks
        self.on_minute.start()

        # uptime report
        print("Setup complete...")
        await self.log(embed=create_embed(title="Status", desc="Online"),
                       log=self.logs.status)
        print("Running...")
    async def binary(self, ctx, mode, *, message: Union[int, str]):
        """
        Converts every character in the message to binary numbers or every
        binary number to readable text with the given mode

        Available modes: ENCRYPT, DECRYPT
        """
        mode = mode.upper()
        title = "Encrypted"
        desc = ""
        append = " "

        if mode == "DECRYPT":
            title = "Decrypted"
            append = ""
            message = message.split()

        for char in message:
            if mode == "DECRYPT":
                value = int(char, base=2)
                desc += chr(value)
            else:
                asc = ord(char)  # character ascii value
                desc += bin(asc)[2:].zfill(8)

            desc += append

        await ctx.send(embed=create_embed(title, desc))
예제 #9
0
    async def mods(self, ctx):
        """
        Displays all of the mods within a server


        **Note**: this also shows the server owner and those with the
        "administrator" permission
        """
        desc = ""
        guild_mods = await Guilds.get_mods(ctx.guild.id)
        guild_mods = guild_mods + [
            m.id for m in ctx.guild.members
            if m.guild_permissions.administrator and m.bot is False
        ]

        for member_id in guild_mods:
            member_found = ctx.guild.get_member(member_id)

            if member_found is None:
                await Guilds.del_mod(member_found)
                guild_mods.remove(member_id)

                continue
            desc += f"{member_found.mention}\n"

        await ctx.send(embed=create_embed("Mods", desc))
    async def morse(self, ctx, mode, *, message):
        """
        With the given mode, encrypts/decrypts the given message from
        text - morse and vice versa

        Available modes: ENCRYPT, DECRYPT
        """
        mode = mode.upper()
        title = "Encrypted"
        desc = ""
        append = " "
        unknown = "?"
        chars = List.morse

        if mode == "DECRYPT":
            title = "Decrypted"
            append = ""
            unknown = "..--.."
            message = message.split()
            chars = {v: k for k, v in chars.items()}

        for char in message:
            char = char.upper()

            if char in chars:
                desc += chars.get(char)
            else:
                desc += chars.get(unknown)

            desc += append

        await ctx.send(embed=create_embed(title, desc))
예제 #11
0
    async def kick(self, ctx, member: discord.Member, *, reason=None):
        """
        Kicks the given member from the guild - if a reason is specified, this
        will be displayed in the audit logs
        """
        title = member.display_name
        desc = f"{member.mention} was kicked"
        message = (f"You were kicked from **{ctx.guild}** by "
                   f"**{str(ctx.author)}**")
        fields = {}

        if reason is not None:
            fields["Reason"] = reason

        if member.id == ctx.author.id:
            desc = "You **cannot** kick yourself!"
        elif self.calculate_perms(ctx.author, member) is False:
            desc = ("You **cannot** kick someone who has a higher role than "
                    "you!")
        elif ctx.author.guild_permissions.administrator is False:
            desc = ("You **cannot** kick someone if you do not sufficient "
                    "permissions!")
        else:
            fields = {"ID": f"`{member.id}`", "Moderator": str(ctx.author)}

            await member.kick(reason=reason)
            await self.dm(member, message, reason)

        embed = create_embed(title, desc, fields=fields)

        await ctx.send(embed=embed)
예제 #12
0
    async def roll(self, ctx, dice_sides: Union[int, float] = 6):
        """
        Rolls an n-sided dice (default is 6-sided) and gives back the result

        Note: if the number of sides given is less than 0, the default will be
        used instead.
        """
        critted = ""
        unlucky = ""

        if type(dice_sides) is float:
            dice_sides = int(dice_sides)
        if dice_sides < 1:
            dice_sides = 6

        rolled = random.randint(1, dice_sides)

        if rolled == dice_sides:
            critted = "**Critical Strike!**"
        elif rolled == 1:
            unlucky = "Yikes..."

        title = f"You rolled a {dice_sides:,}-sided dice."
        desc = f"{critted} A {rolled:,} was rolled! {unlucky}"

        await ctx.send(embed=create_embed(title, desc))
예제 #13
0
    async def info_server(self, ctx):
        guild = ctx.guild
        thumbnail = guild.icon_url
        guild_format = "%m/%d/%y %I:%M:%S %p"
        desc = f"Owned by {guild.owner}"
        humans = list(filter(lambda m: m.bot is False, guild.members))
        bots = list(filter(lambda m: m.bot, guild.members))
        fields = {
            "ID": f"`{guild.id}`",
            "Owner": guild.owner.mention,
            "Region": f"**{str(guild.region).upper()}**",
            "Created": guild.created_at.strftime(guild_format),
            "Members": f"{guild.member_count:,} "
                       f"(**{len(humans):,}** People, "
                       f"**{len(bots)}** Bots",
            "Emojis": len(guild.emojis),
            "Channels": f"{len(guild.channels):,} "
                        f"(**{len(guild.text_channels):,}** Text, "
                        f"**{len(guild.voice_channels):,}** VCs, "
                        f"**{len(guild.categories):,}** Categories)",
            "Roles": len(guild.roles) - 1,
            "Large": guild.large and "✅" or "❌"
        }

        embed = create_embed(desc=desc, fields=fields, inline=True,
                             author=guild, thumbnail=thumbnail)

        await ctx.send(embed=embed)
예제 #14
0
    async def reset(self, ctx):
        """
        Removes all of your data and allows you to start anew

        WARNING: Once this is done, you are unable to get your team, caught
        Proxymon or currency back no matter what! This is permanent!
        """
        THUMBS_UP = "\U0001f44d"
        trainer = await Database.get_trainer(ctx.author)
        title = "Reset"
        desc = "Are you sure you want to reset all of your progress?"
        fields = {
            # generate information on existing progress
        }
        message = await send_with_embed(ctx, title, desc, fields=fields)

        def check(reaction, user):
            return user == ctx.author and str(reaction.emoji) == THUMBS_UP

        await message.add_reaction(THUMBS_UP)

        try:
            await self.bot.wait_for("reaction_add", timeout=30.0, check=check)
        except TimeoutError:
            await message.clear_reactions()
        else:
            name = trainer.process_name(ctx.author)
            desc = (f"Your progress as `{name}` has been reset. Sorry to see "
                    f"you go...")
            embed = create_embed(title, desc)

            await message.edit(embed=embed)
            await Database.remove_trainer(ctx.author)
예제 #15
0
    async def perms(self, ctx, member: discord.Member = None):
        """
        Show the permissions given to the specified member

        Note: if the member has the special "administrator" permission or is
        the owner of the server this command is used in, these permissions
        will be shown and by default every permission will be granted.
        """
        member = member or ctx.author
        title = "Permissions"
        desc = ""
        perms = ctx.channel.permissions_for(member)
        perm_values = []

        if ctx.guild.owner.id == member.id:
            desc += ":white_check_mark: Server owner\n"
        if perms.administrator:
            desc += ":white_check_mark: Administrator\n"

        for key in List.permissions:
            name = key.replace("_", " ").title()
            has_perm = getattr(perms, key)
            box = ":x:"
            perm_values.append(has_perm)

            if has_perm:
                box = ":white_check_mark:"

            desc += f"{box} {name}\n"

        await ctx.send(embed=create_embed(title, desc, author=member))
예제 #16
0
    async def setprefix(self, ctx, *, prefix=None):
        """
        Set Rammus's prefix in the server, give no prefix for it to be reset
        back to the default prefix (`>`)

        **Note**: as of now the character limit for the prefix is 2^5 or 32
        but this may change in the somewhat near future.
        """
        title = f"Prefix set"
        desc = f"Set **{ctx.guild.name}**'s prefix to `{prefix}`"
        limit = 2**5
        guild_prefix = await Guilds.get_prefix(ctx.guild.id)

        if prefix is None:
            # im sure theres a better way to do this...
            prefix = DEFAULT
            desc = f"Reset prefix to `{prefix}` for **{ctx.guild.name}**!"

            await Guilds.set_prefix(ctx.guild.id, prefix)
        elif len(prefix) > limit:
            desc = (f"`{prefix}` is too long to be a valid prefix. Please use "
                    f"a prefix that is less than or equal to {limit} "
                    f"characters.")
        elif guild_prefix == prefix:
            desc = (f"`{prefix}` is already the prefix for "
                    f"**{ctx.guild.name}**!")
        else:
            await Guilds.set_prefix(ctx.guild.id, prefix)

        await ctx.send(embed=create_embed(title, desc))
예제 #17
0
    async def invite(self, ctx):
        """
        Send the invite URL to invite Proxymon
        """
        embed = create_embed(title=ctx.command.name.title(),
                             desc=f"[Here]({INVITE})")

        await ctx.send(embed=embed)
예제 #18
0
    async def ping(self, ctx):
        """
        Show Rammus's latency when using Discord
        """
        title = "Ping"
        desc = f"Latency of `{int(self.bot.latency*1000):,}ms`"

        await ctx.send(embed=create_embed(title, desc))
예제 #19
0
    async def slowmode(self, ctx, delay: Union[int, str] = 15):
        """
        Toggle and control slowmode for the channel this command is used in
        """
        if type(delay) is str:
            delay = self.resolve_delay(delay)

        title = "Slowmode has been enabled"
        desc = f"You can type a new message every `{delay}` seconds!"

        if delay in List.delays:
            delays = []

            for i, v in enumerate(List.delays):
                delay = f"`{v}`"

                if i < len(List.delays):
                    delay = f"`{v},`"

                delays.append(delay)

            embed = create_embed(title="Delays", desc=("\n").join(delays))

            try:
                await ctx.author.send(embed=embed)
            except discord.Forbidden:
                pass

            title = f"The given delay is invalid"
            desc = "A list of valid delays has been DMed to you!"
        elif ctx.channel.slowmode_delay == delay:
            title = f"The slowmode delay is already at {delay}s"
            desc = "There is no need to change it!"
        # "List.delays[-1]" is the last and the highest delay you can use
        elif delay < 0 or delay > List.delays[-1]:
            scale = delay < 0 and "low" or "high"
            title = f"The delay is too {scale}"
            desc = "It must be from 0 - 120!"
        elif delay == 0:
            title = "Slowmode has been disabled"
            desc = "You may now type freely."
        else:
            await ctx.channel.edit(slowmode_delay=delay)

        await ctx.send(embed=create_embed(title, desc))
예제 #20
0
    async def manipulate_cog(self, ctx, cog):
        cog = self.process_cog_name(cog)
        path = f"bot.cogs.{cog}"
        name = ctx.invoked_with == "r" and "reload" or ctx.invoked_with
        function = self.cog_functions.get(name)
        desc = f"Successfully {name}ed!"
        function(path)

        await ctx.send(embed=create_embed(title=cog.title(), desc=desc))
예제 #21
0
    async def prefix(self, ctx):
        """
        Displays the prefix used in this server
        """
        prefix = await Guilds.get_prefix(ctx.guild.id)
        title = "Prefix"
        desc = f"The prefix for **{ctx.guild}** is `{prefix}`"

        await ctx.send(embed=create_embed(title, desc))
예제 #22
0
    async def coinflip(self, ctx):
        """
        Flips a coin and announces the winning side
        """
        sides = ["Heads", "Tails"]
        title = "Coinflip"
        desc = f"{random.choice(sides)} wins!"

        await ctx.send(embed=create_embed(title, desc))
예제 #23
0
    async def leavemsg(self, ctx, *, message=None):
        """
        Set up a message to be sent whenever a member leaves your server
        """
        title = "Leave Message"
        action = message is None and "Removed" or "Set"
        desc = f"{action} leave message"

        await Guilds.set_message(ctx.guild.id, message, leave=True)
        await ctx.send(embed=create_embed(title, desc))
예제 #24
0
    async def process_shutdown(self, ctx, title=None, desc=None, *args):
        print(title)

        if title and desc is None:
            message = f"`{title}`"
        else:
            message = (f"`{title}\n"
                       f"{desc}`")

        if "--no-embed" not in args:
            await ctx.send(embed=create_embed(title, desc))
        else:
            await ctx.send(message)

        await self.bot.log(embed=create_embed("Status", "Offline"),
                           cause=ctx.command.name.title(),
                           log=self.bot.logs.status)

        await self.bot.close(ctx)
예제 #25
0
    async def purge(self, ctx, member: Optional[discord.Member], number: int):
        """
        Deletes messages in bulk with a maximum of 500 message to delete at a
        time
        """
        messages = number == 1 and "message" or "messages"
        title = "Purge"
        desc = f"Successfully purged `{number}` {messages}"
        deleted = 0
        limit = 500
        desc = None

        def check(message):
            nonlocal deleted

            if deleted == number:
                return False

            if member is None:
                deleted += 1
                return True
            elif message.author == member:
                deleted += 1
                return True

        if number < 0 or number > limit:
            desc = (f"`Number` must be a number equal or up to `{limit}`, not "
                    f"{number}")

            return await ctx.send(embed=create_embed(title, desc))

        while deleted < number:
            purged = await ctx.channel.purge(before=ctx.message, check=check)
            deleted += len(purged)

        embed = create_embed(title, desc)
        embed.add_field(name="Note",
                        value=f"`This message will be deleted "
                        f"automatically in 8s.`")
        message = await ctx.send(desc, embed=embed)

        await message.delete(delay=8)
예제 #26
0
    async def channel(self, ctx, channel: discord.TextChannel = None):
        """
        Set up a channel for member join/leave messages to be sent in
        """
        title = "Join/Leave Channel"
        action = channel is None and "Removed" or "Set"
        desc = (f"{action} join/leave channel")
        channel = channel is not None and channel.id or channel

        await Guilds.set_channel(ctx.guild.id, channel)
        await ctx.send(embed=create_embed(title, desc))
예제 #27
0
    async def _import(self, ctx, module_name):
        title = module_name.title()
        desc = "Successfully imported!"

        try:
            globals()[module_name] = importlib.import_module(module_name)
        except Exception as e:
            desc = (f"Importing failed\n\n"
                    f"{type(e).__name__} - {e}")

        await ctx.send(embed=create_embed(title, desc))
예제 #28
0
    async def clearwarns(self, ctx, member: discord.Member):
        """
        Remove all of the warnings for the given member in the server
        this command is used in
        """
        warnings, _ = await Guilds.clear_warns(member)
        append = warnings == 1 and "warn" or "warns"
        desc = f"Cleared {warnings} {append}"

        embed = create_embed(title="Clearwarns", desc=desc)
        await ctx.send(embed=embed)
예제 #29
0
    async def addmod(self, ctx, member: discord.Member):
        """
        Add a moderator to the list of server moderators
        """
        desc = f"{member.mention} is already a mod."
        guild_mods = await Guilds.get_mods(member.guild.id)

        if member.id not in guild_mods:
            desc = f"Added {member.mention} to mods!"

            await Guilds.add_mod(member)
        elif member.bot is True:
            desc = "You cannot add **bots** as moderators."

        await ctx.send(embed=create_embed("Mods", desc))
예제 #30
0
    async def delmod(self, ctx, member: discord.Member):
        """
        Remove a moderator from the server
        """
        desc = f"{member.mention} is not a mod."
        guild_mods = await Guilds.get_mods(member.guild.id)

        if member.id in guild_mods and member.guild_permissions.administrator:
            desc = "Those with admin permissions cannot be removed from mods."
        elif member.guild_permissions.administrator is False:
            desc = f"Deleted {member.mention} from mods!"

            await Guilds.del_mod(member)

        await ctx.send(embed=create_embed("Mods", desc))