2
votes

Purpose: To add more commands without interrupting other commands

I have been looking around to find a way to roll out updates without interrupting the flow of my bot, since it has some asyncio functions that execute a while after the function has been called

I have tried: await client.logout()

Above will logout the bot, but also closes the command line. I found this on the discord.py docs.

I am running Windows 10, with Python version 3.9

Any help would be appreciated. Thanks in advance.

6
1. What do you want to do after this? Because there is no real possibility to just close the connection and then just letting the window open 2. Can you give us that part of code where you want to do that?FlexGames
Why would you even want that? What's the purpose of that?Łukasz Kwieciński
I am attempting to make a reboot command for the bot, if you were confused.OdorousWo1f
If you want to roll out updates without interrupting the flow of your bot consider looking into cogs and dynamic code loading. You can group functions into a class (cog) and have a command like !reload COGNAME that would reload that cog with the updated code. You wouldn't need to even touch the command or interrupt connection.Kingsley Zhong

6 Answers

0
votes

Create a new python file in the same directory with the name startup.py for example. Inside this file do the following:

import os
import time

time.sleep(5)
os.system('python YOUR_BOTS_FILE_NAME.py')

Then in the file where your bot's code is add a new command that we are going to call restart for example:

import discord
from discord.ext import commands
import os

@client.command()
@commands.is_owner()
async def restart(ctx):
    os.system('python startup.py')
    exit()

In the startup.py file, os waits 5 seconds for your bot's file to turn off and then turns it on. The restart command in your bot's file starts the startup file then shuts itself down.

@commands.is_owner()

Makes sure the author of the message is you so people don't restart your bot.

0
votes

I am developing a bot myself and I have made a shutdown command myself which shuts down the bot without using terminal.

First I would add the code and then explain it.

Code:

myid = <my discord account ID>

@MyBot.command()
async def shutdown(ctx):
    if ctx.author.id == myid:
        shutdown_embed = discord.Embed(title='Bot Update', description='I am now shutting down. See you later. BYE! :slight_smile:', color=0x8ee6dd)
        await ctx.channel.send(embed=shutdown_embed)
        await MyBot.logout()
    if ctx.author.id != myid:
        errorperm_embed = discord.Embed(title='Access Denied!', description='This command is `OWNER` only. You are not allowed to use this. Try not to execute it another time.', color=0xFF0000)
        errorperm_embed.set_footer(text=ctx.author)
        await ctx.channel.send(embed=errorperm_embed, delete_after=10.0)

I have not added any has_permissions as I don't need it when I using my discord ID to restrict its usage.

Explanation:

  • I have defined a variable, myid which is equal to my discord account ID. Check here on how to get user ID:

https://support.discord.com/hc/en-us/articles/206346498-Where-can-I-find-my-User-Server-Message-ID-

  • I have added a condition that if the ID of the user who used this command is equal to myid or if it is not. If it is equal to my account' ID then it would shutdown the bot otherwise it would show an error to the user.

  • I have simply used await MyBot.logout() which logs you out and disconnect.

0
votes

You can place your code in a while True loop.

while True:
    client = commands.Bot(command_prefix='!')

    async def restart(ctx):
        await client.logout()

    client.run('token')
0
votes

You could just replace the current process with the same process, starting anew. You have to flush buffers and close file-pointers beforehand, but that's easy to do:

import os
import sys
from typing import List

def restart(filepointers: List):
    # this cleanup part is optional, don't need it if your bot is ephemeral

    # flush output buffers
    sys.stdout.flush()
    sys.stderr.flush()

    # flush and close filepointers
    for fp in filepointers:
         os.fsync(fp)
         fp.close()

    # replace current process
    os.execl(*sys.argv)

Then just call this function with your bot as you would(from the same file).

0
votes

If you want to update your code you must restart the program.

import os
path = "your .py file path"

@client.command(name="restart")
async def restart_command(ctx):
    await client.close()
    os.system("python " + path)
0
votes

If you don't want to kill the current process and instead just want hot-reloading of different functionality, you might want to look into discord.py's extensions feature. Using extensions and cogs will allow you to enable/disable/reload certain features in your bot without stopping it (which should keep tasks running). It's also the built-in method for hot-reloading.

Extensions and cogs are typically used together (though they don't have to be). You can create files for each group of similar commands you want to reload together.

The following code samples should be integrated into your setup. You'll probably also want to add error handling and input checks, but it should give you an idea of what's going on. For a detailed explanation or method options, check out the docs.

# info.py

# ...
# this is just an example
class Info(commands.Cog):
    def __init__(self, bot):
        self.bot = bot

    @commands.command()
    async def about(self, ctx):
        await ctx.send("something here")

    # ...

# extensions need a setup function
def setup(bot):
    bot.add_cog(Info(bot))
# main.py

# ...

bot = commands.Bot(
    # ...
)
bot.load_extension("info")

bot.run(token)
# reload command
@bot.command()
async def reload(ctx, extension):
    # probably want to add a check to make sure
    # only you can reload things.
    # also handle the input
    bot.reload_extension(extension)
to use, you might do something like `prefix!reload info`