Discord机器人定时提醒功能失效问题求助
问题排查与修复方案
核心问题分析
- 上下文未定义:
check_notes函数里的await ctx.send(embed=embed)完全错误,这个后台任务没有ctx对象,直接调用会抛出异常,导致提醒无法发送。 - 任务未启动: 代码里没有启动
check_notes这个后台循环任务,机器人根本不会定时检查待发送的提醒。 - 过时API调用:
author.avatar_url是discord.py旧版本的写法,新版本已废弃,会引发属性错误。 - 时区不一致: 使用
datetime.now()(本地时间)处理时间,若机器人运行时区和用户输入时区不同,会导致时间判断错误。
修复后的完整代码
import discord from discord.ext import commands import datetime import asyncio bot = commands.Bot(command_prefix="!", intents=discord.Intents.all()) # 确保启用必要的Intents notes = {} @bot.command() async def note(ctx, time_str: str, *, message): try: # 使用UTC时间统一处理,避免时区问题 time = datetime.datetime.strptime(time_str, "%y.%m.%d %H:%M").replace(tzinfo=datetime.timezone.utc) now = datetime.datetime.now(datetime.timezone.utc) if time <= now: await ctx.send("你选择的是过去的时间,请设置未来的时间。") return notes[time] = {"author_id": ctx.author.id, "channel_id": ctx.channel.id, "message": message} await ctx.send(f"提醒已保存,时间:{time.strftime('%y.%m.%d %H:%M')} (UTC)") except ValueError: await ctx.send("时间格式错误,请使用 'yy.mm.dd HH:MM' 格式(24小时制)。") async def check_notes(): await bot.wait_until_ready() while not bot.is_closed(): now = datetime.datetime.now(datetime.timezone.utc) for time, note in list(notes.items()): if time <= now: # 通过ID获取用户和频道,避免上下文丢失 author = bot.get_user(note["author_id"]) channel = bot.get_channel(note["channel_id"]) if author and channel: embed = discord.Embed( title="提醒!", description=f"{author.mention}, 你的提醒:\n{note['message']}", color=discord.Color.blue() ) embed.set_thumbnail(url=author.avatar.url if author.avatar else author.default_avatar.url) try: await channel.send(embed=embed) except discord.Forbidden: # 处理无法发送消息的情况(比如频道权限不足) pass del notes[time] await asyncio.sleep(60) @bot.command() async def my_notes(ctx): embed = discord.Embed() embed.set_author(name="🌌 | 你的提醒", icon_url=ctx.author.avatar.url if ctx.author.avatar else ctx.author.default_avatar.url) user_notes = [(t, n) for t, n in notes.items() if n["author_id"] == ctx.author.id] if not user_notes: embed.description = ":calendar: 你目前没有任何提醒。" else: note_list = "\n".join([f"• **{t.strftime('%y.%m.%d %H:%M')} (UTC)**: {n['message']}" for t, n in user_notes]) embed.description = f":calendar: | 你的提醒列表:\n{note_list}" await ctx.send(embed=embed) # 启动后台任务 bot.loop.create_task(check_notes()) bot.run("你的机器人令牌")
关键修复说明
- 上下文问题解决: 不再依赖
ctx存储提醒,而是保存用户ID和频道ID,在发送时通过bot.get_user()和bot.get_channel()获取对象,确保后台任务能正常发送消息。 - 启动后台任务: 添加
bot.loop.create_task(check_notes()),让机器人启动时自动运行定时检查任务。 - API更新: 替换
author.avatar_url为author.avatar.url,并添加默认头像 fallback,避免头像不存在时出错。 - 时区统一: 全部使用UTC时间处理,消除时区差异导致的时间判断错误,同时在提示中明确标注UTC时区。
- 错误处理: 添加发送消息时的权限错误捕获,避免因权限问题导致任务崩溃。
内容的提问来源于stack exchange,提问作者Domi
相关产品推荐
相关产品推荐

