You need to enable JavaScript to run this app. Python Discord API 投票Bot开发:实现24小时定时投票结果自动统计
优惠活动
大模型
产品
解决方案
定价
更多

Python Discord API 投票Bot开发:实现24小时定时投票结果自动统计

适配现有代码的24小时投票计时器+自动统计落地方案

核心前置注意事项

  • 禁止在指令回调中使用time.sleep(86400)做定时,该操作属于阻塞式等待,会直接卡死Bot的整个事件循环,导致所有指令、交互完全无响应
  • 采用异步等待方案实现单条投票的独立24小时计时,全程不影响Bot正常处理其他用户消息

分步实现流程(完全兼容已完成的基础投票发消息、加反应逻辑)

  • 第一步:建立活动投票的映射存储
    新增全局字典存储正在计时中的投票,避免不同投票的消息、结果统计混淆:
    active_polls = {}
    
    执行+poll指令时,完成投票消息发送、添加👍/👎初始反应后,立刻将该条投票消息的ID作为key,关联消息对象、所属频道存入字典
  • 第二步:为每条投票绑定独立异步定时任务
    引入异步任务创建工具,给每条新投票单独启动计时协程,24小时等待过程不占用Bot的事件循环资源:
    import asyncio
    async def end_poll_timer(poll_message, channel):
        # 异步等待24小时(共86400秒)
        await asyncio.sleep(86400)
        # 计时结束后,将该投票从活动列表移除
        if poll_message.id in active_polls:
            del active_polls[poll_message.id]
        # 触发结果统计流程
        await calculate_poll_result(poll_message, channel)
    
    发完投票消息后,直接启动该定时任务:
    asyncio.create_task(end_poll_timer(poll_message, ctx.channel))
    
  • 第三步:修复统计逻辑缺陷的结果计算函数
    针对性解决旧逻辑中“把Bot自己的初始反应算入票数、用到缓存旧数据漏统计最新反应”的问题:
    async def calculate_poll_result(poll_message, channel):
        # 从服务器拉取最新的投票消息,替换本地缓存的旧数据
        latest_message = await channel.fetch_message(poll_message.id)
        up_votes = 0
        down_votes = 0
        # 遍历消息上的所有反应
        for reaction in latest_message.reactions:
            # 匹配👍反应
            if str(reaction.emoji) == "👍":
                # 遍历所有点反应的用户,过滤掉Bot账号本身,避免把初始反应算入票数
                user_list = [user async for user in reaction.users() if not user.bot]
                up_votes = len(user_list)
            # 匹配👎反应
            elif str(reaction.emoji) == "👎":
                user_list = [user async for user in reaction.users() if not user.bot]
                down_votes = len(user_list)
        # 生成对比结果
        result_content = f"投票「{latest_message.content}」已到期\n👍 支持票数:{up_votes}\n👎 反对票数:{down_votes}\n"
        if up_votes > down_votes:
            result_content += "✅ 支持方获得最终胜利"
        elif down_votes > up_votes:
            result_content += "❌ 反对方获得最终胜利"
        else:
            result_content += "⚖️ 双方票数持平"
        # 将结果发送到原投票所在频道
        await channel.send(result_content)
    

常见踩坑补全

  • 不要直接使用reaction.count属性统计票数,该属性数值包含Bot自身添加的初始反应,会导致基础票数虚高1票
  • 统计前必须调用fetch_message拉取服务器端的最新消息状态,不能直接使用之前发送消息时返回的旧对象,避免漏掉计时最后时刻用户的投票反应
  • 新手开发阶段无需额外做数据库持久化,内存字典存储的投票信息足够支撑基础功能运行,等后续功能迭代再适配重启后恢复计时的能力即可

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.11.03 00:36:03