简体   繁体   中英

How to make a Discord Bot that can accept arguments from Python of what message to send to who and be able to close itself?

I'm trying to do something pretty simple. I just want Python to be able to call a quick function that sends a direct message over Discord. Basically a modified version of the FAQ example . I want another Python class to start the Discord client and pass the message string and user id. And I want the Discord client to simply send the string and then close and delete the entire class. After looking through docs I made these modifications:

import discord
class MyClient(discord.Client):
    async def on_ready(self):
        print('Logged on as {0}!'.format(self.user))
        user = await self.fetch_user(self.destination_user)
        await user.send(self.message)
        await self.close()
    def __init__(self, user_id, user_message):
        self.destination_user = user_id
        self.message = user_message

client = MyClient(desired_id, desired_message)
client.run('My Client ID')
#wait for client to end and then continue

However, I'm running into 2 problems. It looks like discord.Client doesn't allow an __init__() function, and when I try to do async def __init__() there's also an error. Are there other ways to pass arguments to it through Python , rather than react to messages in Discord? Also, self.close() results in "RuntimeError: Cannot close a running event loop" . What's the proper way to wait for on_ready() to finish and then close it?

I can get it working by hardcoding the user ID and message, eliminating __init__() and simply not closing the class. However, for some reason, even then self.get_user() doesn't work, only self.fetch_user() . The docs say to use get_user() , so I'd prefer that, but I don't know what I'm doing wrong. My bot is in the same server as the target user, and I've given it both privileged intents, but get_user() continues to return "None", whereas fetch_user() properly messages the user, with the same exact arguments.

I found out what seems the proper way to run discord.Client in this fashion:

import discord
import nest_asyncio
import asyncio
nest_asyncio.apply()

class DiscordClient(discord.Client):
    async def on_ready(self):
        user = await self.fetch_user(self.send_user)
        await user.send(self.message)

    async def on_message(self, message):
        #Pause so there's no warning about operations not finishing when class closes
        await asyncio.sleep(0.1)
        await DiscordClient.close(self)
        
    async def parameters(self, user, message):
        self.send_user = user
        self.message = message

async def send_discord(user, message):
    print("Sending Discord message")
    client = DiscordClient()
    await client.parameters(user, message)
    await client.start('Private Key')
    print("Discord message sent")

asyncio.run(send_discord(user_id, "Test message contents"))

on_message runs even it's the bot that sent the message, so it will quickly close itself. I had to add the wait or there were some race conditions or something causing a warning every time it closed.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM