Home > other >  How to send message with discord.py bot from another python file?
How to send message with discord.py bot from another python file?

Time:01-07

Here are skeleton versions of my code:

bot.py

import discord

client = discord.Client()

async def send_notification(notification):#this method is tested and works when called from same file
    for guild in client.guilds:
        for channel in guild.text_channels:
            if channel.name == CHANNEL_NAME:
                await channel.sent(notification)

def start_bot():
    client.run(TOKEN)

def notification(notification):
    asyncio.create_task(send_notification(notification))#likely error here

main.py

import bot
from time import sleep

def main():
  bot.start_bot()
  sleep(10)
  bot.notification('some notification')

main()

Hello, I am trying to send a message to all guilds from a different python file. I understand that I am making some fundamental error with how asynchronous tasks are handled. Currently main.py doesn't even get to the sleep() statement.

  1. Is there some way to reference the client from main.py so that it would be possible to call methods with it
  2. Could I create some api so any python file can access methods inside the bot

Thanks in advance.

CodePudding user response:

Workaround found. Looking more into the documentation of discord.py it is clear that it likes to be it's own self contained thing, which is why my approach of referencing it from other files was not ideal. I ended up continuously reading from a json file:

async def update_notifications():
    while True:
        with open(JSON_PATH, 'r') as file:# extract all content from json file
            content = json.load(file)
        while len(content['notifications']) > 0:# send all notifications one by one
            await send_notification(content['notifications'][0])
            content['notifications'].pop(0)
        with open(JSON_PATH, 'w') as file:# write the now empty content back to json file
            json.dump(content, file, indent=4)
        await asyncio.sleep(20)# sleep in seconds

The json file is structured as such:

{
    "notifications":["notification1","notification2",...]
}

And to trigger the coroutine update_notifications() a loop is created on_ready.

@client.event
async def on_ready():
    client.loop.create_task(update_notifications())

This approach has the advantage that any python script, or even other languages can tell the bot to send a notification by writing to the json file.

CodePudding user response:

client.run(TOKEN) blocks execution of the main thread because it starts an async event loop. If you want to just run a task after the bot is started up, you can use the bot's on_ready handler:

import discord

client = discord.Client()

CHANNEL_NAME = "some-channel"

@client.event
async def on_ready():
    for guild in client.guilds:
        for channel in guild.text_channels:
            if channel.name == CHANNEL_NAME:
                await channel.send("hello world!")

client.run('your token here')

See: https://discordpy.readthedocs.io/en/stable/quickstart.html

To answer your 2 questions:

  1. bot.client should do that, but what you're doing is kind of an anti-pattern when making Discord bots. It's probably best to stick to the documentation. However, you could subclass your bot using inheritance, but that's a bit more advanced.
  2. You can already access the bot methods. See above.
  •  Tags:  
  • Related