如何实现Discord机器人在非命令接收频道发送消息?
问题解决与代码优化
错误原因说明
你遇到的'Message'对象无'channelSaved'属性错误,是因为修改代码时误将全局变量channelSaved当成了message对象的属性(比如写成message.channelSaved),但channelSaved是独立的全局变量,不属于Message实例,所以触发了报错。
优化后的完整代码
我们改用discord.ext.commands框架重构代码,让命令逻辑更清晰,同时实现你需要的功能:
import os import discord from discord.ext import commands from keep_alive import keep_alive # 初始化Bot,指定命令前缀为!!,开启所有必要权限 bot = commands.Bot(command_prefix="!!", intents=discord.Intents.all()) # 用Bot的属性存储目标频道ID,替代全局变量更规范 bot.target_channel_id = None @bot.event async def on_ready(): print(f"已登录为 {bot.user}") # !!reverse 命令:反转输入文本 @bot.command(name="reverse") async def reverse(ctx, *, text: str): await ctx.send(text[::-1]) # !!saychannel 命令:设置目标频道ID,支持通过DM发送 @bot.command(name="saychannel") async def set_channel(ctx, channel_id: int): # 验证频道是否存在 channel = bot.get_channel(channel_id) if not channel: await ctx.send("无效的频道ID,请确认后重新输入") return bot.target_channel_id = channel_id await ctx.send(f"已设置目标频道为:{channel.name}(ID:{channel_id})") # !!say 命令:在指定频道发送消息 @bot.command(name="say") async def send_to_target(ctx, *, message: str): if not bot.target_channel_id: await ctx.send("请先使用 !!saychannel 频道ID 设置目标频道") return target_channel = bot.get_channel(bot.target_channel_id) if not target_channel: await ctx.send("目标频道不存在,请重新设置") bot.target_channel_id = None return await target_channel.send(message) await ctx.send(f"已在目标频道发送消息:{message}") keep_alive() my_secret = os.environ['DISCORD_BOT_SECRET'] bot.run(my_secret)
关键改进点
- 改用commands框架:替代原生
on_message的字符串判断逻辑,自动解析命令和参数,代码更简洁易维护 - 参数自动校验:比如
channel_id: int会自动将输入转为整数,无效输入会自动返回错误提示 - 完善错误处理:添加频道存在性验证,避免无效ID导致的运行报错
- 替代全局变量:用
bot.target_channel_id存储频道ID,比全局变量更符合面向对象设计,避免变量污染 - 支持DM操作:直接在DM中发送
!!saychannel 1234567890即可设置频道,!!say命令也能在DM中触发,消息会发送到指定频道
使用说明
- 发送
!!saychannel 你的频道ID(可通过DM发送),机器人会验证并保存频道ID - 发送
!!say Hello world(可在任意频道或DM发送),机器人会将消息发送到之前设置的频道 - 发送
!!reverse 要反转的文本,机器人返回反转后的内容
内容的提问来源于stack exchange,提问作者Yozy Opto
相关产品推荐
相关产品推荐

