discord.py中如何在@tasks.loop()里无需on_message变量发送消息
问题核心原因
你在机器人还未完成登录、内部缓存未加载的阶段就调用client.get_channel()获取频道对象,此时拿到的channel值为None,调用None.send()自然会抛出属性错误,这是你发送消息失败的根本原因。
修复方案
- 将频道获取逻辑移到
on_ready事件中,确保机器人登录完成、资源加载完毕后再获取频道对象 - 补充缺失的discord导入和新版discord.py要求的权限声明(intents)
- 循环任务可直接在
on_ready中启动,完全不需要依赖on_message的消息变量
修正后完整代码
import discord from discord.ext import tasks, commands import os from keep_alive import keep_alive token = os.environ['goofyToken'] # 替换为你实际的频道ID CHANNEL_ID = 替换为你的数字频道ID # 新版discord.py需要显式声明intents intents = discord.Intents.default() intents.message_content = True client = discord.Client(intents=intents) # 先初始化频道变量 channel = None @client.event async def on_ready(): global channel # 登录完成后再获取频道 channel = client.get_channel(CHANNEL_ID) print('We have logged in as {0.user}'.format(client)) # 可直接在此处启动循环任务,不需要等用户发命令,完全不依赖message变量 # 如果你需要循环定时运行,把count=1改成seconds=你的间隔秒数即可 myloop.start("初始触发的消息") # count=1代表只运行一次,需要循环的话改为seconds=间隔秒数 @tasks.loop(count=1) async def myloop(word): if channel is not None: await channel.send(word) @client.event async def on_message(message): msg = message.content if msg.startswith('!'): message_to_send = 'Hello World!' if channel is not None: await channel.send(message_to_send) # 避免重复启动loop的判断可按需添加 if not myloop.is_running(): myloop.start(message_to_send) keep_alive() client.run(token)
额外说明
修复后你的循环任务完全独立于on_message事件运行,uptimerobot的ping操作只会触发你keep_alive服务的web请求,不会影响机器人的任务逻辑,也不会出现变量丢失导致循环中断的问题。
内容的提问来源于stack exchange,提问作者Seth Bowers
相关产品推荐
相关产品推荐

