async def contribute(ctx):
    embed = officialEmbed(
        "Contribute",
        "Contribute to this project, help create more cool features",
        url=config.get_config("info")["url"])
    embed.set_thumbnail(url=config.get_string("logos")["github"])
    await ctx.send(embed=embed)
예제 #2
0
파일: userrank.py 프로젝트: aikocc/THM-Bot
    async def rank(self, ctx, user=None):
        is_id = False

        # Empty arg, so we retrieve sender's id.
        if user == None:
            await self.rank_from_id(ctx, ctx.author.id)
            return

        # Contains a user.
        ## Is it a mention or THM username?
        ### Mentions.
        if "<@!" in user:
            is_id = True
            user = user[3:len(user) - 1]
        elif "<@" in user:
            is_id = True
            user = user[2:len(user) - 1]

        # THM Username.
        if sanitize_check(user) == False:
            await ctx.send(config.get_string("not_sanitized"))
            return
        if is_id:
            await self.rank_from_id(ctx, user)
        else:
            await self.send_rank(ctx, user)
예제 #3
0
    async def dark(self, ctx):
        darkQuotes = config.get_string("quotes")["dark"]
        quote = darkQuotes[random.randint(0, len(darkQuotes) - 1)]

        response = officialEmbed(title=quote,
                                 color=0xff4500,
                                 author="DarkStar7471",
                                 author_img="https://i.imgur.com/jZ908d1.png",
                                 footer="")
        await ctx.send(embed=response)
예제 #4
0
    async def rule(self, ctx, ruleNb):

        if not sanitize_check(ruleNb):
            await ctx.send(config.get_string("not_sanitized"))
            return

        message = "Rule " + ruleNb + " does not exist."

        ruleNb = int(ruleNb)

        if ruleNb >= 1 and ruleNb <= len(rules):
            message = "**__Rule " + str(ruleNb) + ":__** " + rules[ruleNb-1]

        await ctx.send(message)
예제 #5
0
async def send_verify(channel):
    """Sends the instructions on how to verify yourself."""

    # Embed making.
    response = officialEmbed("How to get verified?")
    response.set_thumbnail(url=config.get_config("info")["logo"])

    # Loading text from JSON.
    steps = config.get_string("faq")["verify"]
    i = 0

    # Add each step to the embed.
    for step in steps:
        response.add_field(name=("Step "+str(i+1)), value=step)
        i = i + 1

    # Sending the created embed in DM to the user.
    await channel.send(embed=response)
예제 #6
0
import libs.config as config
from libs.embedmaker import officialEmbed
from libs.utils import sanitize_check

####################
# Config variables #
####################

c_file_gtfobins = config.get_config("data_files")["gtfobins"]

####################
# String variables #
####################

s_not_sanitized = config.get_string("not_sanitized")
s_gfto = config.get_string("gtfobins")

############
# COG Body #
############


class Gtfobins(commands.Cog):
    def __init__(self, bot):
        self.bot = bot

    @commands.command(description=s_gfto["help_desc"], usage="[query]")
    async def gtfobins(self, ctx, search_term=""):
        if sanitize_check(search_term) == False:
            await ctx.send(s_not_sanitized)
예제 #7
0
class _Channels():
    def __init__(self):
        self._roles_id = config.get_config("channels")

        self.WELCOME = self._roles_id["welcome"]
        self.ANNOUNCEMENTS = self._roles_id["announcements"]
        self.STATS_THM_USERS = self._roles_id["stats_thm_users"]
        self.STATS_DISCORD_USERS = self._roles_id["stats_discord_users"]
        self.STATS_ROOMS = self._roles_id["stats_rooms"]
        self.STAFF_VOTING_CM = self._roles_id["staff_voting_cm"]


roles = _Roles()
channels = _Channels()

s_cmd = config.get_string("commands")


def __has_role__(member, id):
    """Check if the member has the roles."""

    for role in member.roles:
        if id == role.id:
            return True
    return False

def __check_context__(ctx, context):
    """Checks that the current context fits the desired one."""

    if context == Context.DM and (not isinstance(ctx.channel, DMChannel)):
        raise Exception(s_cmd["context_dm_only"])
예제 #8
0
import requests
import json
import urllib.parse
import os

from bs4 import BeautifulSoup
import discord
from discord.ext import commands

import libs.config as config
from libs.models import Student, Result, Faculty
from libs.command_manager import custom_check, contribute
from libs.embed import officialEmbed
from cogs.help import extract_commands

institute_config = config.get_string("commands")["institute"]

api_key = os.getenv("API_KEY")
api_url = os.getenv("API_URL")
nith_url = "https://nith.ac.in/"

student_by_name = "student_name_search"
faculty_by_name = "faculty_name_search"
student_by_roll = "student_info"
result_using_roll = "result/"
"""
Requests api for data using name and beautifies text using ``` ``` blocks

Also if result is longer tha 2000 characters (Discord Single Msg Limit), It Splits msg into parts providing part number at bottom

Args:
예제 #9
0
from libs.embedmaker import officialEmbed
from libs.utils import has_role

####################
# Config variables #
####################

# Channel and role ID.
id_announcements = config.get_config("channels")["announcements"]
id_admin = config.get_config("roles")["admin"]

# Persistence File.
file_persistence = config.get_config("persistence")["giveaway"]

# Strings.
s_no_perm = config.get_string("commands")["no_perm"]
s_giveaway = config.get_string("giveaway")

#############
# Functions #
#############


def clear_file():
    """Resets the giveaway persistance file to an empty one."""

    ret = None

    file = open(file_persistence, "r").read()
    data = json.loads(file)
예제 #10
0
import discord
from discord.ext import commands

import libs.config as config
from libs.embedmaker import officialEmbed

# QoL / TODO
# Look into integrating HelpJuice API so all topics can be retrieved via requests and parameters

###################
# Other variables #
###################

# Embeds data.
s_docs = config.get_string("docs")

# Retrieve list of all topics and commands & unexpected error message
s_topics = s_docs["topics"]
s_commands = s_docs["commands"]
s_error = s_docs["error"]

# Store all objects in strings "topics"
s_topics = s_docs["topics"]

# THM Logo & Color for embed
c_docs_picture = config.get_config("info")["logo"]
c_docs_color = config.get_config("colors")["site"]

# Begin grabbing string entries for individual topics

# URL topic
예제 #11
0
import discord
from discord.ext import commands

import libs.config as config
from libs.command_manager import custom_check, get_role, db_client, get_member

mod_roles = config.get_config("roles")["mod"]
moderation_config = config.get_string("commands")["moderation"]
optional_roles = config.get_config("roles")["optional"]

"""
Args:
    ctx: Context object

Returns:
    msg: String with member count
"""

async def get_count(ctx):
    msg = "```\n"
    bot_count = 0
    human_count = 0
    for member in ctx.author.guild.members:
        if member.bot:
            bot_count += 1
        else:
            human_count += 1
    msg += f"{'Total Members':20s}: {ctx.author.guild.member_count}\n\n"

    msg += f"{'Humans':20s}: {ctx.author.guild.member_count-bot_count}\n"
    msg += f"{'Bots':20s}: {bot_count}\n\n"
예제 #12
0
import libs.config as config
from libs.thm_api import get_leaderboard_data

####################
# Config variables #
####################

c_monthly_data = config.get_config("data_files")["monthly_leaderboard"]
c_channels = config.get_config("channels")

#####################
# Strings variables #
#####################

s_leader = config.get_string("ranks")["leaderboard"]
s_monthly = config.get_string("ranks")["monthly"]

###################
# Other variables #
###################

# Channels ID.
id_announcement = c_channels["announcements"]

# Fonts and color.
font1 = ImageFont.truetype("fonts/Ubuntu-Light.ttf", 75)
font2 = ImageFont.truetype("fonts/Ubuntu-Light.ttf", 50)
font3 = ImageFont.truetype("fonts/Ubuntu-Bold.ttf", 30)
red = (162, 6, 6)
gray = (52, 60, 66)
예제 #13
0
###
### PS: It is planned to eventually rework this.
### PS 2: You can find me on Discord and I'll try to help.

####################
# Config variables #
####################

c_sleeptime = config.get_config("sleep_time")["roles_update"]
c_api_token = config.get_config("url")["api"]["token"]

#####################
# Strings variables #
#####################

s_verify = config.get_string("verify")
s_verify_del = config.get_string("verify_delete")

###################
# Other variables #
###################

id_guild = config.get_config("server")

roles = config.get_config("roles")
id_admin = roles["admin"]
id_mod = roles["mod"]
id_ranks = roles["ranks"]
id_sub = roles["sub"]
id_contrib = roles["contrib"]
id_verified = roles["verified"]
예제 #14
0
    async def vote(self, ctx):
        vDesc = ""
        vOpt = []
        vReac = []
        vTimeHour = 0

        # Remove the command.
        await ctx.message.delete()

        # Check for the user to be admin.
        if not has_role(ctx.author, id_admin):
            botMsg = await ctx.send(config.get_string("commands")["no_perm"])
            await asyncio.sleep(5)
            await botMsg.delete()
            return

        # Check for the author.
        def checkAuth(m):
            return m.author == ctx.author

        def checkDone(m):
            return (m.author == ctx.author and m.content.lower() == "done")

        botMsgCancel = await ctx.send(s_vote["cancel_message"])

        # Retrieve the vote's description.
        botMsg = await ctx.send(s_vote["vote_desc"])
        vDescMsg = await self.bot.wait_for('message', check=checkAuth)
        vDesc = vDescMsg.content

        await botMsg.delete()
        await vDescMsg.delete()

        if vDescMsg.content.lower() == "cancel":
            await botMsgCancel.delete()
            confirmDelMsg = await ctx.send(s_vote["canceled"])
            await asyncio.sleep(5)
            await confirmDelMsg.delete()
            return

        # Retrieve the vote's options and reactions.
        botMsg = await ctx.send(s_vote["vote_options"])

        isDone = False
        optMsg = []

        # Gettings all options.
        while not isDone:
            msg = await self.bot.wait_for('message', check=checkAuth)
            if msg.content.lower() == "done":
                isDone = True
            elif msg.content.lower() == "cancel":
                await botMsgCancel.delete()
                await botMsg.delete()
                await msg.delete()
                for m in optMsg:
                    await m.delete()

                confirmDelMsg = await ctx.send(s_vote["canceled"])
                await asyncio.sleep(5)
                await confirmDelMsg.delete()
                return
            else:
                vOpt.append(msg.content)
            optMsg.append(msg)

        # Clearing the messages.
        await botMsg.delete()
        for m in optMsg:
            await m.delete()

        # Doing the same but for reactions.
        botMsgText = s_vote["vote_reactions"]
        for i in range(0, len(vOpt)):
            botMsgText += ("\n" + str(i + 1) + ". - " + vOpt[i])
        botMsg = await ctx.send(botMsgText)

        # Waits for the DONE message.
        isDone = False
        while not isDone:
            msg = await self.bot.wait_for('message', check=checkAuth)

            if msg.content.lower() == "cancel":
                await botMsgCancel.delete()
                await botMsg.delete()
                await msg.delete()
                confirmDelMsg = await ctx.send(s_vote["canceled"])
                await asyncio.sleep(5)
                await confirmDelMsg.delete()
                return

            # Checks if the amount of emojis matches the amount of options.
            cacheBotMsg = await ctx.channel.fetch_message(botMsg.id)

            if len(cacheBotMsg.reactions) != len(vOpt):
                await msg.delete()
                errorMsg = await ctx.send(s_vote["reactions_amount_wrong"])
                await asyncio.sleep(5)
                await errorMsg.delete()
            else:
                isDone = True

        # Sets the emojis.
        for r in cacheBotMsg.reactions:
            vReac.append(r.emoji)

        # Clears msg.
        await botMsg.delete()
        await msg.delete()

        # Gets the time the vote should last.
        isDone = False
        while (not isDone):
            timeAsk = await ctx.send(s_vote["vote_time"])
            msg = await self.bot.wait_for('message', check=checkAuth)

            if msg.content.lower() == "cancel":
                await botMsgCancel.delete()
                await msg.delete()
                await timeAsk.delete()
                confirmDelMsg = await ctx.send(s_vote["canceled"])
                await asyncio.sleep(5)
                await confirmDelMsg.delete()
                return

            try:
                vTimeHour = int(msg.content)
                isDone = True
            except:
                errorMsg = await ctx.send(s_vote["time_int_only"])
                await asyncio.sleep(2)
                await errorMsg.delete()
                isDone = False
            finally:
                await timeAsk.delete()
        await msg.delete()

        # Confirmation embed.
        embed = officialEmbed(title=s_vote["recap"],
                              desc=vDesc,
                              footer=s_vote["recap_time"].format(vTimeHour))
        for i in range(0, len(vOpt)):
            embed.add_field(name=vReac[i], value=vOpt[i])

        # Sends embed.
        botEmbed = await ctx.send(embed=embed)

        # Asks for validation.
        botMsg = await ctx.send(s_vote["confirm"])
        voteValid = await self.bot.wait_for('message', check=checkAuth)

        # Checks validation's answer.
        if not voteValid.content.lower() == "yes":
            cancelMsg = await ctx.send(s_vote["canceled"])

            # Removes useless msg.
            await botMsgCancel.delete()
            await botEmbed.delete()
            await botMsg.delete()
            await voteValid.delete()
            await cancelMsg.delete()
        else:
            # Removes useless msg.
            await botMsgCancel.delete()
            await botMsg.delete()
            await voteValid.delete()

            # Makes embed.
            embed = officialEmbed("Vote", vDesc)
            for i in range(0, len(vOpt)):
                embed.add_field(name=vReac[i], value=vOpt[i])

            # Sends the vote.
            chan_announcement = self.bot.get_channel(id_announcements)
            vEmbed = await chan_announcement.send(embed=embed)
            # Adds the reactions to it.
            for i in range(0, len(vReac)):
                await vEmbed.add_reaction(vReac[i])

            # Saves it in the persistence file.
            endingTime = (
                datetime.now() +
                timedelta(hours=vTimeHour)).strftime('%Y-%m-%dT%H:%M:%S.%f')
            data = {
                "desc": vDesc,
                "options": vOpt,
                "ending_time": endingTime,
                "message_id": vEmbed.id
            }

            with open(file_persistence, 'w') as outfile:
                json.dump(data, outfile)

            # Waits and fetches results.
            await self.vote_output(data)
예제 #15
0
파일: userrank.py 프로젝트: aikocc/THM-Bot
from libs.embedmaker import officialEmbed
from libs.utils import sanitize_check
from libs.utils import api_fetch
from libs.thm_api import get_sub_status, get_user_data

####################
# Config variables #
####################

c_api_token = config.get_config("url")["api"]["token"]

#####################
# Strings variables #
#####################

s_userrank = config.get_string("ranks")["userrank"]
s_quotes = config.get_string("quotes")["regular_quotes"]

#############
# Functions #
#############


def get_moto():
    """Returns a random quote from the list."""

    return s_quotes[random.randint(0, len(s_quotes) - 1)]


############
# COG Body #
예제 #16
0
import asyncio
import json
from datetime import datetime, timedelta

import discord
from discord.ext import commands

import libs.config as config
from libs.embedmaker import officialEmbed
from libs.utils import has_role

#####################
# Strings variables #
#####################

s_vote = config.get_string("vote")

###################
# Other variables #
###################

# Channel & role ID.
id_announcements = config.get_config("channels")["announcements"]
id_admin = config.get_config("roles")["admin"]

# Persistence File.
file_persistence = config.get_config("persistence")["vote"]

#############
# Functions #
#############
예제 #17
0
import json
from datetime import datetime, timedelta

import discord
from discord.ext import commands

import libs.config as config
from libs.embedmaker import officialEmbed
from libs.utils import has_role


#####################
# Strings variables #
#####################

s_vote = config.get_string("vote")
s_no_perm = config.get_string("commands")["no_perm"]

###################
# Other variables #
###################

# Channel & role ID.
id_announcements = config.get_config("channels")["announcements"]
id_admin = config.get_config("roles")["admin"]

# Persistence File.
file_persistence = config.get_config("persistence")["vote"]


#############
예제 #18
0
import discord
import requests
from discord.ext import commands

import libs.config as config
import tweepy
from libs.embedmaker import officialEmbed


###################
# Other variables #
###################

# Embeds data.
social = config.get_string("socials")

# Twitter API key.
file_twitter_cred = config.get_config("twitter_creds")

# Socials.
github = social["github"]
twitter = social["twitter"]
reddit = social["reddit"]
website = social["website"]
tweet = social["tweet"]

# URLs.
gitURL = github["url"]
twitterURL = twitter["url"]
redditURL = reddit["url"]
예제 #19
0
####################
# Config variables #
####################

c_room_data = config.get_config("data_files")["room"]
c_room_default_data = config.get_config("data_files")["room_default"]
c_sleep_time = config.get_config("sleep_time")["room_listener"]
c_api_url = config.get_config("url")["api"]
c_url_room = config.get_config("url")["room"]
c_join_room = config.get_config("url")["room_join"]

#####################
# Strings variables #
#####################

s_no_perm = config.get_string("commands")["no_perm"]
s_room = config.get_string("room")

###################
# Other variables #
###################

# Channel ID.
id_channels = config.get_config("channels")
id_channel = id_channels["announcements"]

# Role IDs.
id_admin = config.get_config("roles")["admin"]
id_announcerole = config.get_config("roles")["announcementrole"]

예제 #20
0
import discord
import libs.config as config
from discord.ext import commands

####################
# Config variables #
####################

s_help = config.get_string("help")

#############
# Functions #
#############


def get_msg(bot, isStaff):
    """Fabricates the output message by loading COGs and commands informations."""

    msg = "```markdown\n#####\tHELP\t#####\n{required args} | [optional args]\n"

    # Loops through cogs.
    for cog_name in bot.cogs:
        cog = f"\n> {cog_name}\n"

        # Command number.
        i = 0

        # Loops all commands in cog.
        commands = bot.get_cog(cog_name).get_commands()
        for command in commands:
import time
import asyncio

import discord
from discord.ext import commands
from discord.ext.commands import Context

import libs.config as config
from libs.command_manager import custom_check
from cogs.help import extract_commands

role_manager_config = config.get_string("commands")["role_manager"]


def extract_roles(ctx, *args):
    valid_roles = []
    invalid_role_ids = []
    for role_id in args:
        if role_id.lower() in config.get_config("roles")["all"]:
            role = ctx.guild.get_role(config.get_config("roles")[
                                      "all"][role_id.lower()])
        else:
            role = None
        if role:
            valid_roles.append(role)
        else:
            invalid_role_ids.append(role_id)
    return (valid_roles, invalid_role_ids)


async def delete_message(ctx:Context, messages):
예제 #22
0
from libs.embedmaker import officialEmbed
from libs.utils import has_role

####################
# Config variables #
####################

# Channel and role ID.
id_announcements = config.get_config("channels")["announcements"]
id_admin = config.get_config("roles")["admin"]

# Persistence File.
file_persistence = config.get_config("persistence")["giveaway"]

# Strings.
s_no_perm = config.get_string("no_perm")
s_giveaway = config.get_string("giveaway")

#############
# Functions #
#############


def clear_file():
    """Resets the giveaway persistance file to an empty one."""

    ret = None

    file = open(file_persistence, "r").read()
    data = json.loads(file)
예제 #23
0
                           channels=["staff_channel",],)
    async fun_command(self, ctx, user_input=""): # Your command to be executed after the check
        if command_manager.is_sanitized(user_input):
            do_thing()
        else:
            command_manager.error_response(ctx, "not_sanitized")
        ...
"""
import libs.config as config
from discord.channel import DMChannel
from discord.ext import commands
import functools
import asyncio

# GLOBAL VARIABLES
ERROR_STRING = config.get_string("commands")
ROLE_IDS = config.get_config("roles")
CHANNEL_IDS = config.get_config("channels")
DEFAULT_BANNED = ["/", ";", "-", ">", "<", ":", "`", "\"", "|"]


def check(roles="", channels="", dm_flag=None):
    """Decorator to check role permissions and context for the user invoking a bot command.

    Wrap around a bot command to check appropriate permission and channel context of the executed command from
    the Context object provided by the bot's event listener method, and errors out if checks do not pass.
    String names of roles and channels are derived from config/config.json keys.
    All exceptions raised are inherited from Discord.ext.commands

    Args:
        roles: String array of whitelisted roles from config.json that the user must have .
예제 #24
0
import discord
from discord.ext import commands

import libs.config as config
from libs.command_manager import custom_check, get_member

help_config = config.get_string("commands")["help"]

mod_roles = config.get_config("roles")["mod"]


def get_count(all_commands, is_mod=False):
    count = 0
    for command in all_commands:
        if command.hidden and not is_mod:
            continue
        if isinstance(command, commands.core.Group):
            if get_count(command.commands, is_mod=is_mod) > 0:
                count += 1
        else:
            count += 1
    return count


def extract_commands(all_commands, margin="", is_mod=False):
    padding = 24 - len(margin)

    count = get_count(all_commands, is_mod=is_mod)

    i = 0
    msg = ""
예제 #25
0
import libs.config as config
from libs.utils import has_role as has_role

####################
# Config variables #
####################

# Role IDs.
id_devLead = config.get_config("roles")["devLead"]
id_dev = config.get_config("roles")["dev"]

####################
# String variables #
####################

s_no_perm = config.get_string("no_perm")
s_devrole = config.get_string("devrole")

############
# COG Body #
############


class DevRole(commands.Cog, name="BOT Dev"):
    def __init__(self, bot):
        self.bot = bot

    @commands.command(name="botdev",
                      description=s_devrole["help_desc"] + " (Bot-dev Lead)",
                      usage="{@member}",
                      hidden=True)
예제 #26
0
from discord.utils import get

import libs.config as config
from libs.utils import has_role as has_role

####################
# Config variables #
####################

id_announcerole = config.get_config("roles")["announcementrole"]

####################
# String variables #
####################

s_announcementrole = config.get_string("announcementrole")

############
# COG Body #
############


class AnnouncementRole(commands.Cog, name="Announcements"):
    def __init__(self, bot):
        self.bot = bot

    @commands.command(name="notifyme",
                      description=s_announcementrole["help_desc"])
    async def role_announce(self, ctx):
        announceRole = ctx.guild.get_role(id_announcerole)
예제 #27
0
import re

from discord import guild
from discord.ext import commands

import libs.config as config
import libs.database as database

from libs.command_manager import check, error_response

from libs.embedmaker import officialEmbed

# Command specific strings
from libs.thm_api import get_user_by_token

s_lookup = config.get_string("moderation")["lookup"]

# Other variables
id_guild = config.get_config("server")
thm_user_link = config.get_config("url")["user_profile"]
token_regex = re.compile(r"^[0-9a-f]{24}$")
mention_regex = re.compile(r"^<@(?:!|)(\d+)>$")
user_id_regex = re.compile(r"^(?:\d+)$")
user_discrim_regex = re.compile(r"^(?:.+)#(?:\d{4})$")


class Moderation(commands.Cog, name="Moderation commands"):
    def __init__(self, bot):
        self.bot = bot
        self.conn = database.connect_to_db()
예제 #28
0
from libs.embedmaker import officialEmbed
from libs.utils import sanitize_check
from libs.utils import api_fetch
from libs.thm_api import get_sub_status, get_user_data

####################
# Config variables #
####################

c_api_token = config.get_config("url")["api"]["token"]

#####################
# Strings variables #
#####################

s_userrank = config.get_string("ranks")["userrank"]
s_quotes = config.get_string("quotes")["regular_quotes"]
s_not_sanitized = config.get_string("commands")["not_sanitized"]

#############
# Functions #
#############


def get_moto():
    """Returns a random quote from the list."""

    return s_quotes[random.randint(0, len(s_quotes) - 1)]


############
예제 #29
0
import json
import time

import aiohttp
import discord
from discord.ext import commands

import libs.config as config
from libs.embedmaker import officialEmbed

####################
# Config variables #
####################

# Strings and images.
s_faq = config.get_string("faq")
img_openvpn = config.get_config("images")["openvpn"]
img_aocfaq = config.get_config("images")["aocfaq"]

############
# COG Body #
############


class FAQ(commands.Cog):
    def __init__(self, bot):
        self.bot = bot

    @commands.command(description=s_faq["vpn"][0])
    async def vpn(self, ctx):
        response = officialEmbed()
예제 #30
0
import discord
from discord.ext import commands
from discord.ext.commands import CommandNotFound, MissingRequiredArgument

import libs.config as config

command_prefixes = config.get_config("prefix")

c_extensions = config.get_config("cogs")
# c_disabled_extensions = config.get_config("disabled_cogs")

# String variables

# Loads the bot's activity status
s_status = config.get_string("status")

intents = discord.Intents.default()
intents.members = True
intents.guilds = True

bot = commands.Bot(command_prefix=command_prefixes,
                   intents=intents,
                   case_insensitive=True)

# Loading the cogs.
if __name__ == "__main__":

    # Remove default help command
    bot.remove_command("help")