You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

如何为Discord Bot设置定时执行特定函数并维持常规运行?

解决方案

你的代码逻辑存在核心问题:当前代码只会在Bot启动时做一次时间判断,要么执行定时函数,要么注册消息事件,无法同时实现持续运行Bot+定时触发函数的需求。下面提供两种可行的实现方式:

方法一:使用discord.py内置的tasks扩展(推荐)

discord.py自带的任务调度工具可以轻松实现定时任务,无需额外依赖:

import someFile
import discord
import responses
from discord.ext import commands, tasks
from datetime import time

def run_discord_bot():
    TOKEN = '你的Bot Token'
    intents = discord.Intents.all()
    # 注意:command_prefix是commands.Bot的参数,discord.Client不支持,这里改用Bot类
    bot = commands.Bot(command_prefix="-", intents=intents)

    # 定义定时任务:每天22:30执行
    @tasks.loop(time=time(hour=22, minute=30))
    async def daily_scheduled_task():
        # 调用你的目标函数,若函数是异步类型需加await
        someFile.someFunction()
        # 可选:让Bot发送任务执行通知(替换成你的目标频道ID)
        target_channel = bot.get_channel(1234567890)
        if target_channel:
            await target_channel.send("定时任务已执行")

    @bot.event
    async def on_ready():
        print(f'{bot.user} 已启动运行!')
        # 启动定时任务,判断is_running避免重复启动
        if not daily_scheduled_task.is_running():
            daily_scheduled_task.start()

    @bot.event
    async def on_message(message):
        if message.author == bot.user:
            return
        username = str(message.author)
        user_message = str(message.content)
        channel = str(message.channel)
        print(f'{username} 在{channel}发送:{user_message}')
        await send_message(message, user_message, is_private=True)
        # 必须调用此方法,否则Bot无法响应命令
        await bot.process_commands(message)

    # 实现消息发送逻辑(若已有可忽略)
    async def send_message(message, user_message, is_private):
        try:
            response = responses.handle_response(user_message)
            if is_private:
                await message.author.send(response)
            else:
                await message.channel.send(response)
        except Exception as e:
            print(f"消息发送出错:{e}")

    bot.run(TOKEN)

关键说明:

  • tasks.loop(time=time(hour=22, minute=30)):设置每天固定时间执行任务,如需指定时区可添加timezone参数(需安装pytz库)
  • 在on_ready中启动任务,通过is_running()判断避免重复触发
  • 改用commands.Bot而非discord.Client,更好兼容命令前缀和任务扩展

方法二:使用APScheduler第三方库

如果需要更复杂的调度规则(如每周一三五执行),可以用APScheduler:

  1. 先安装依赖:pip install apscheduler

  2. 代码实现:

import someFile
import discord
import responses
from discord.ext import commands
from apscheduler.schedulers.asyncio import AsyncIOScheduler

def run_discord_bot():
    TOKEN = '你的Bot Token'
    intents = discord.Intents.all()
    bot = commands.Bot(command_prefix="-", intents=intents)
    # 初始化适配异步环境的调度器
    scheduler = AsyncIOScheduler()

    def scheduled_task():
        someFile.someFunction()

    @bot.event
    async def on_ready():
        print(f'{bot.user} 已启动运行!')
        # 添加定时任务:每天22:30执行,支持cron复杂规则
        scheduler.add_job(scheduled_task, 'cron', hour=22, minute=30)
        scheduler.start()

    @bot.event
    async def on_message(message):
        if message.author == bot.user:
            return
        username = str(message.author)
        user_message = str(message.content)
        channel = str(message.channel)
        print(f'{username} 在{channel}发送:{user_message}')
        await send_message(message, user_message, is_private=True)
        await bot.process_commands(message)

    async def send_message(message, user_message, is_private):
        try:
            response = responses.handle_response(user_message)
            if is_private:
                await message.author.send(response)
            else:
                await message.channel.send(response)
        except Exception as e:
            print(f"消息发送出错:{e}")

    bot.run(TOKEN)

关键说明:

  • AsyncIOScheduler适配discord.py的异步事件循环,避免阻塞
  • cron参数支持复杂规则,例如day_of_week='mon-wed,fri'表示每周一、二、三、五执行

原代码核心问题总结

  • 错误地将command_prefix传给discord.Client,该参数仅属于commands.Bot
  • 启动时仅做一次时间判断,无法持续监听时间触发任务
  • 事件处理函数被放在else分支,导致只能二选一,无法同时运行消息处理和定时任务

内容的提问来源于stack exchange,提问作者dohyunii

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.06.30 14:58:15