Discord.py命令签名报错排查及定时任务实现求助
报错解决与定时任务实现方案
一、当前报错的修复
1. 事件函数误用命令装饰器
on_ready和on_message是Discord Bot的事件函数,不能用@bot.command()装饰,必须改用@bot.event。原代码把它们当成命令注册,导致参数不匹配触发报错。
2. 命令装饰器语法错误
start_count函数里的@bot.commands()多了个s,正确写法是@bot.command();且装饰器会自动完成命令注册,不需要额外调用bot.add_command(start_count)。
3. 消息作者判断逻辑错误
message.author == bot.id判断无效,应该用message.author == bot.user来识别机器人自身发送的消息。
修复后的基础代码:
from discord.ext import commands import requests import discord import asyncio from discord.ext import tasks intents = discord.Intents.all() bot = commands.Bot(command_prefix="?", intents=intents) @bot.command() async def foo(ctx, arg): await ctx.send(arg) @bot.event async def on_ready(): print("bot online") @bot.event async def on_message(message): if message.author == bot.user: return # 必须保留该行,否则自定义命令会失效 await bot.process_commands(message) if message.content == "ana": await message.channel.send("baban") @bot.command() async def start_count(ctx): key = "some-crypto-shit-api" data = requests.get(key) data = data.json() price = data["price"] coin = data["symbol"] await ctx.send(f"{coin} 当前价格: {price}") bot.run('my_Token')
二、定时任务实现(每n分钟执行特定代码)
使用discord.ext.tasks模块的loop装饰器实现定时任务,步骤如下:
- 导入
tasks模块:from discord.ext import tasks - 用
@tasks.loop(minutes=n)装饰定时任务函数(n为你需要的间隔分钟数) - 在
on_ready事件中启动任务,或通过命令触发启动 - 可通过全局变量或命令上下文指定消息发送的目标频道
示例代码(以每5分钟查询价格并发送到指定频道为例):
# 全局变量存储目标频道ID,也可通过命令动态设置 target_channel_id = None @tasks.loop(minutes=5) # 每5分钟执行一次 async def price_reminder(): if target_channel_id is None: return channel = bot.get_channel(target_channel_id) if not channel: return try: key = "some-crypto-shit-api" data = requests.get(key) data.raise_for_status() # 捕获请求异常 data_json = data.json() price = data_json["price"] coin = data_json["symbol"] await channel.send(f"⏰ {coin} 价格提醒: {price}") except Exception as e: await channel.send(f"价格查询失败: {str(e)}") @bot.command() async def start_count(ctx): global target_channel_id target_channel_id = ctx.channel.id # 任务未运行时启动 if not price_reminder.is_running(): price_reminder.start() await ctx.send("价格提醒已启动,每5分钟发送一次更新!") @bot.command() async def stop_count(ctx): if price_reminder.is_running(): price_reminder.stop() await ctx.send("价格提醒已停止") else: await ctx.send("价格提醒未在运行")
注意事项:
- 定时任务中的网络请求需用
try-except捕获异常,避免任务崩溃 - 若需动态调整间隔,可调用
price_reminder.change_interval(minutes=new_n) - 需确保开启
intents.message_content权限,否则无法读取消息内容
内容的提问来源于stack exchange,提问作者Shaumne
相关产品推荐
相关产品推荐

