繁体   English   中英

如何使用 discord.py 从线程发送消息?

[英]How do I send a message from a thread using discord.py?

我希望我的 discord 用户能够排队一些任务。 在此示例中,它只是 ping 网站,但我最终希望它执行其他长时间运行的任务。 当我运行我的机器人时,出现以下错误:

ping-bot.py:22: RuntimeWarning: coroutine 'respond_to_channel' was never awaited
  respond_to_channel()
RuntimeWarning: Enable tracemalloc to get the object allocation traceback

这是代码:

import os, discord, subprocess, asyncio
from discord import app_commands
from dotenv import load_dotenv
from time import sleep
from threading import Thread

load_dotenv()
TOKEN = os.getenv('DISCORD_TOKEN')
CHANNEL=os.getenv('CHANNEL_ID')
GUILD=os.getenv('GUILD_ID')

queue = []


def ping_test():
    global queue
    old_queue = queue.copy() 
    while True:
        if queue != old_queue and len(queue) > 0:
            old_queue = queue.copy()
            retcode = subprocess.call("ping " + "-c 5 " + old_queue[0][0], shell=True)
            queue.pop(0)
            if len(queue) > 0:
                respond_to_channel()
                print(f"Now working on {queue[0][0]}")
        sleep(1)

async def respond_to_channel():
    ping_channel = client.get_channel(CHANNEL)
    await ping_channel.send(f"Testing... Now working on {queue[0][0]}")

class MyClient(discord.Client):
    def __init__(self):
        super().__init__(intents=discord.Intents.default())
        self.synced = False
        daemon = Thread(target=ping_test, daemon=True, name='Monitor')
        daemon.start()

    async def on_ready(self):
        print(f'Logged on as {self.user}!')
        if not self.synced:
            await tree.sync(guild = discord.Object(id = GUILD))
            self.synced = True

client = MyClient()
tree = app_commands.CommandTree(client)

@tree.command(name = "greet", description = "Greetings!", guild = discord.Object(id = GUILD))

async def self(interaction: discord.Interaction, name: str):
    await interaction.response.send_message(f"Hello {name}! I was made with Discord.py!")
    print(f'Sent from {interaction.user}')
    
@tree.command(name = "ping-test", description = "Use my computer to ping websites", guild = discord.Object(id = GUILD))

async def self(interaction: discord.Interaction, website: str):
    queue.append([website, interaction.user.id])
    await interaction.response.send_message(f"Hello <@{interaction.user.id}>! You want me to ping {website}. There are currently {len(queue) - 1} jobs in front of you.", file=discord.File('test.png'))


client.run(TOKEN)

我找到了一些适用于 ping 测试的“解决方案”,但我将允许我的 discord 用户使用我的计算机执行一些可能需要 5 分钟以上的计算量大的任务。 如果任务需要超过几分钟,我发现的这些其他解决方案会破坏机器人。

出于这个原因,我决定实现一个线程来处理列表中的项目,完成后将在频道中标记用户。

我实际上想使用discord.ext.tasks ,因为它会为您处理所有事情并在异步循环中运行,因此不会中断。

我将线程调用更改为

@tasks.loop(seconds = 1)
async def ping_test():
    global queue
    global being_worked 
    global client
    ping_channel = client.get_channel(CHANNEL)
    if len(queue) > 0:
        if queue[0] != being_worked[0]:
            being_worked = queue.copy()
            retcode = subprocess.call("ping " + "-c 5 " + being_worked[0][0], shell=True)
            queue.pop(0)
            await ping_channel.send(f"Done working on {being_worked[0][0]}")
            if len(queue) > 0:
                await ping_channel.send(f"Testing... Now working on {queue[0][0]}")
                print(f"Now working on {queue[0][0]}")
    return

所以现在完整的代码如下所示:

import os, discord, subprocess
from discord import app_commands
from discord.ext import tasks
from dotenv import load_dotenv

load_dotenv()
TOKEN = os.getenv('DISCORD_TOKEN')
CHANNEL=int(os.getenv('CHANNEL_ID'))
GUILD=os.getenv('GUILD_ID')

queue = []
being_worked = []

@tasks.loop(seconds = 1)
async def ping_test():
    global queue
    global being_worked 
    global client
    ping_channel = client.get_channel(CHANNEL)
    if len(queue) > 0:
        if queue != being_worked:
            being_worked = queue.copy()
            retcode = subprocess.call("ping " + "-c 15 " + being_worked[0][0], shell=True)
            queue.pop(0)
            await ping_channel.send(f"Done working on {being_worked[0][0]}")
            if len(queue) > 0:
                await ping_channel.send(f"Testing... Now working on {queue[0][0]}")
                print(f"Now working on {queue[0][0]}")
    return

class MyClient(discord.Client):
    def __init__(self):
        super().__init__(intents=discord.Intents.default())
        self.synced = False

    async def on_ready(self):
        print(f'Logged on as {self.user}!')
        if not self.synced:
            await tree.sync(guild = discord.Object(id = GUILD))
            self.synced = True
        await ping_test.start()
        

client = MyClient()
tree = app_commands.CommandTree(client)

@tree.command(name = "greet", description = "Greetings!", guild = discord.Object(id = GUILD))

async def self(interaction: discord.Interaction, name: str):
    await interaction.response.send_message(f"Hello {name}! I was made with Discord.py!")
    print(f'Sent from {interaction.user}')
    
@tree.command(name = "ping-test", description = "Use my computer to ping websites", guild = discord.Object(id = GUILD))

async def self(interaction: discord.Interaction, website: str):
    queue.append([website, interaction.user.id])
    await interaction.response.send_message(f"Hello <@{interaction.user.id}>! You want me to ping {website}. There are currently {len(queue) - 1} jobs in front of you.", file=discord.File('test.png'))


                
client.run(TOKEN)

在 function respond_to_channel()前面添加await应该可以解决这个问题。

await respond_to_channel()

暂无
暂无

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

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