I have a python script that contains code for the discord bot. When I run it, it activates the discord bot and shows the status for the bot as online. But, when I end the python script, it disables the bot. How could I keep the bot active without using a server even when I'm offline?
I used a keep_alive script on mine.
Add to start of main.py code:
from keep_alive import keep_alive
Add to bottom of main.py code:
keep_alive()
Then create a file called keep_alive.py, and add the code:
from flask import Flask
from threading import Thread
app = Flask('')
#app.route('/')
def home():
return "Server Host Connected and Synced to Main Code."
def run():
app.run(host='0.0.0.0',port=8080)
def keep_alive():
t = Thread(target=run)
t.start()
If you make a file called requirements.txt, or use it if you already have one.
Add:
flask
If the bot is Python this should work. It works for me on repl.it
Maybe try using if/else statements, so something like:
User = (your userID)
Bot = (Bot userID)
If User online keep Bot online
Else keep Bot online
Related
This was asked previously, but never answered (as in marked) and did not have the same specifics as me (here)
For context, I was working on my bot, specifically on a command that add and removes roles, I restarted the bot, and it just stopped responding to commands. I say that instead of "stopped working" because it still works. It comes online, it can put its status up, and it responds to on_message functions. Any attempt at calling a command does nothing, it doesn't respond in chat, it doesn't give an error, throwing a print statement in the command shows that it doesn't even run the command.
I have already tried reverting the roles command because it happened right after, did not fix it. I removed the command entirely and the same problem occurred. I re-installed all my packages whether they related to discord or not and updated. Nothing fixed it.
I suspect it has something to do with the way I'm running the bot. I'm using Pycord. Here is some code that may be helpful, but I really don't know what would help resolve the problem
# Top of main.py file
import discord, random, json, os
from discord.ext import commands
from keep_alive import keep_alive
from discord.utils import find
# discord.py API docs: https://discordpy.readthedocs.io/en/latest/api.html
intents = discord.Intents.default()
intents.members = True
client = commands.Bot(command_prefix='!', intents=intents)
client.remove_command('help')
# ...
# unrelated code here
# ...
# I use cogs for my commands, here is the imports for all cogs
client.load_extension('cogs.commands.fun')
client.load_extension('cogs.commands.msg')
client.load_extension('cogs.commands.mod')
client.load_extension('cogs.commands.games')
client.load_extension('cogs.commands.role')
client.load_extension('cogs.commands.misc')
client.load_extension('cogs.commands.secretCommands')
client.load_extension('cogs.commands.msgTriggers')
# ...
# unrelated code here
# ...
# Bottom of main.py file
keep_alive()
client.run(os.getenv('token'))
# Top of one of my cogs (fun commands cog)
import discord, json, randfacts, random
from discord.ext import commands
from random import randint
from cogs import assets
class Fun(commands.Cog):
def __init__(self, client):
self.client = client
# ...
# unrelated code here
# ...
# Bottom of one of my cogs (fun commands cog)
def setup(client):
client.add_cog(Fun(client))
I am trying to make a Discord bot that listens for a webhook and sends messages in a discord channel when it receives a ping from the webhook. It seems that due to the way threads work in python, I cannot run both the Quart server and the Discord.py bot on the main thread. I am trying to migrate both the bot and server onto their own threads. Quart is an async implementation of Flask, so that thread would need to be async. Does anybody know how I can accomplish this? I have tried several methods none of which work
Here's a short bit of code I wrote. It should all work. If you don't use .env files you can just copy-paste your token in. However, I would strongly recommend using .env files for secret things.
import discord
import os
from discord.ext import commands
from dotenv import load_dotenv
from quart import Quart
load_dotenv()
TOKEN = os.getenv("DISCORD_TOKEN")
PREFIX = "!"
bot = commands.Bot(command_prefix=PREFIX)
#bot.event
async def on_ready():
print(f'{bot.user} has connected to Discord!')
#bot.command(name="hi")
async def hi_command(ctx):
await ctx.channel.send("hello")
app = Quart(__name__)
#app.route("/")
async def hello():
return "hello world"
bot.loop.create_task(app.run_task())
bot.run(TOKEN)
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.
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`
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.
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.
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')
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).
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)
Below is my code, I made a bot using Discord.Py, Its basis is to take a screenshot, then post the screenshot to discord, it is supposed to repeat this process every 5 minutes continuously. this works within my script, however after a bit the bot then goes offline in discord, and is no longer under its role, or under online members, and is shown offline. Is their a way to force the bot to stay online?
import pyautogui
import pyscreeze
import time
import discord
from discord.ext import tasks
from discord.ext.commands import Bot
from discord.ext import commands
class MyClient(discord.Client) :
async def on_ready(self):
print('online')
game = discord.Game("Watching Logs")
await client.change_presence(status=discord.Status.online, activity=game)
while True:
time.sleep(300 - time.time() % 300)
im1 = pyscreeze.screenshot()
im2 = pyscreeze.screenshot(r'C:\Users\Tyler\Desktop\discord-screenshot-bot-master\371logs.png')
print('Screenshot Taken')
time.sleep(5)
channel = client.get_channel(780053606753239050)
await channel.send('371 Logs')
await channel.send(file=discord.File(r'C:\Users\Tyler\Desktop\discord-screenshot-bot-master\371logs.png'))
print('Screenshot Posted to Discord')
client = MyClient()
client.run('token')
Are you running the bot on a computer you own, or is it being hosted? Some hosts might consider a sleeping Python program to be "inactive". Also, can you see the stdout it is printing? It might be crashing you not know it. Also, you might want to check out the logging module. If you want it, here is a tutorial.
(This looks pretty similar to this page...)
EDIT:
Discord's python module has some pretty weird error catching, as it is intended for use with logging.
Here is a snippet of code from my own Discord bot:
import logging
import discord
logger = logging.getLogger("discord")
logger.setLevel(logging.INFO) # Do not allow DEBUG messages through
handler = logging.FileHandler(filename="bot.log", encoding="utf-8", mode="w")
handler.setFormatter(logging.Formatter("{asctime}: {levelname}: {name}: {message}", style="{"))
logger.addHandler(handler)
If you want more messsages (for example, when debugging, as you are now), comment out logger.setLevel(logging.INFO) # Do not allow DEBUG messages through.
So I wrote a Discord bot in Python and it worked. But, when I close my Python shell (where I run my code) the bot stops working. Is there anything I can do so my bot keeps working no matter if the shell is closed or not? Just in case if you need the code, here it is
import os
import random
import datetime
import discord
bot = discord.Client()
#bot.event
async def on_member_join(member):
if member.id == bot.id:
return
channel = discord.utils.get(bot.guilds[0].channels,name="genral")
member_id = member.id
response = f"Welcome to For Testing,<#{member_id}> !"
await channel.send(response)
#bot.event
async def on_message(message):
if message.author == bot.user:
return
Keywords = ["sup","lol","yeet"]
channel = message.channel
for keyword in Keywords:
if keyword.lower() in message.content.lower():
user_id = message.author.id
response = f"Did someone say {keyword.lower()}? I guess it was <#{user_id}>"
await channel.send(response)
#bot.event
async def reminder():
while(True):
await bot.wait_until_ready()
online_members = []
for member in bot.get_all_members():
online_members.append(member.id)
if len(online_members) > 0:
user = random.choice(online_members)
channel = discord.utils.get(bot.guilds[0].channels,name="genral")
response = f"So what are u up to <#{user.id}>"
await channel.send(response)
await asyncio.sleep(3600)
bot.loop.create_task(reminder())
real_token = "THE TOKEN"
bot.run("THE TOKEN")
You can save your script as a file with the file extension .py and then run it through your file manager (e.g. double-click the file in Windows). That should run your script without needing the shell open.
https://realpython.com/run-python-scripts/#how-to-run-python-scripts-from-a-file-manager
On Windows, you can use pythonw.exe in order to run a python script as a background process:
Python scripts (files with the extension .py) will be executed by python.exe by default. This executable opens a terminal, which stays open even if the program uses a GUI. If you do not want this to happen, use the extension .pyw which will cause the script to be executed by pythonw.exe by default (both executables are located in the top-level of your Python installation directory). This suppresses the terminal window on startup.
For example,
C:\ThanosDodd\Python3.6\pythonw.exe C:\\Python\Scripts\moveDLs.py
or
pythonw.exe pythonFile.py
You can export code onto repl.it and make one more file called keep_alive.py
from flask import Flask
from threading import Thread
app = Flask('')
#app.route('/')
def main():
return "Your bot is alive!"
def run():
app.run(host="0.0.0.0", port=<any Port>)
def keep_alive():
server = Thread(target=run)
server.start()
then do
from keep_alive import keep_alive
then call the keep_alive function before bot.run
this makes a flask server then u can take the server link and make a monitor in http://uptimerobot.com/
For more info check the link
https://repl.it/talk/learn/Hosting-discordpy-bots-with-replit/11008