python 如何使用www.example.com自动发送消息discord.py?

ulydmbyx  于 2023-05-16  发布在  Python
关注(0)|答案(1)|浏览(156)

我做了一个示例代码片段,看看我是否可以自动化我的discord bot,以便它以设定的间隔(秒)自动发送消息:

import os
import discord
import discord.ext
from discord import app_commands
import asyncio

TOKEN = 'BOT TOKEN HERE'
GUILD = 'GUILD NAME HERE'

intents = discord.Intents.default()
intents.message_content = True
client = discord.Client(intents=intents)

@client.event
async def on_ready():

    for guild in client.guilds:
        if guild.name == GUILD:
            break

    print(
        f'{client.user} has successfully connected to the following guild(s):\n'
        f'{guild.name}(id: {guild.id})'
    )
    await client.change_presence(activity=discord.Activity(name='anything', type=discord.ActivityType.playing))

@client.event
async def auto_send():
    await send_message('MESSAGE HERE')
    await asyncio.sleep(i)    #replace 'i' with any number(seconds)

async def send_message(message):
    channel = await client.fetch_channel('CHANNEL ID HERE') #must be of type 'int'
    await channel.send(message)

client.loop.create_task(auto_send())
client.run(TOKEN)

运行代码后,我得到了这个错误:

Traceback (most recent call last):
  File "", line 92, in <module>
    client.loop.create_task(auto_send())
    ^^^^^^^^^^^^^^^^^^^^^^^
  File "", line 140, in __getattr__
    raise AttributeError(msg)
AttributeError: loop attribute cannot be accessed in non-async contexts. Consider using either an asynchronous main function and passing it to asyncio.run or using asynchronous initialisation hooks such as Client.setup_hook

我尝试将client.loop.create_task()命令移到异步函数定义中,但没有得到任何输出,也没有任何错误消息。
我的目标是尝试看看机器人是否会在设定的时间间隔(比如10秒)后自动向特定的通道发送消息。
我不明白这个错误,所以请让我知道是否有一个修复。先谢谢你。

额外信息:

1.我使用Python 3.11 IDLE并在Pycharm中运行程序。
1.我使用discord.Client而不是commands.Bot()

  1. Discord.py版本:2.2.3
wtzytmuj

wtzytmuj1#

您可以通过创建asyncio任务,让您的bot每X秒发送一条消息。
discord.py提供了discord.ext.tasks模块来轻松实现这一点。具体操作如下:

**第一步:**使用tasks.loop装饰器创建一个Loop

@tasks.loop(seconds=10)
async def auto_send(channel : discord.TextChannel):
    await channel.send("Test message")

我正在创建一个名为auto_sendLoop,它接收一个TextChannel作为参数,告诉机器人将消息发送到哪里。机器人将在装饰器中配置的每10秒提供的通道中发送 “测试消息”

**第二步:**使用tasks.Loop.start初始化Loop。您可以在on_ready()事件中执行此操作:

task_launched = False

# ...

@client.event
async def on_ready():
    global task_launched

    await client.wait_until_ready()
    print('Ready')

    if not task_launched:
        task_launched = True
        channel = await client.fetch_channel('channel id (as int)')
        await auto_send.start(channel)

on_ready()事件可以被多次调用:
此函数不保证是第一个被调用的事件。同样,这个函数也不能保证只被调用一次。这个库实现了重新连接逻辑,因此只要RESUME请求失败,就会调用这个事件。
这就是为什么我使用task_lauched变量来确保任务只启动一次。

**注意:**请务必将on_ready()事件中的await auto_send.start(channel)行添加到最后,作为startinfg后的代码,否则不会执行任务。

您的完整代码:

import discord
from discord.ext import tasks

TOKEN = 'BOT TOKEN HERE'
GUILD = 'GUILD NAME HERE'

intents = discord.Intents.default()
intents.message_content = True
client = discord.Client(intents=intents)

task_launched = False

@tasks.loop(seconds=10)
async def auto_send(channel : discord.TextChannel):
    await channel.send('Test message')

@client.event
async def on_ready():
    global task_launched

    await client.wait_until_ready()

    for guild in client.guilds:
        if guild.name == GUILD:
            break

    print(
        f'{client.user} has successfully connected to the following guild(s):\n'
        f'{guild.name}(id: {guild.id})'
    )

    await client.change_presence(
        activity=discord.Activity(name='anything', type=discord.ActivityType.playing)
    )

    if not task_launched:
        task_launched = True
        channel = await client.fetch_channel('channel id (as int)')
        await auto_send.start(channel)

client.run(TOKEN)

参考文献:

  • discord.ext.tasks.loop
  • discord.ext.tasks.Loop.start

相关问题