如何通过‘no’按钮实现功能,停止Telegram机器人自动发送消息?
问题分析与修复方案
你的代码存在几个核心问题:
- 局部变量
flag无法被外部回调修改,点击no按钮时无法终止自动发送 while循环会阻塞TeleBot的消息轮询线程,导致点击no后机器人无法响应这个回调请求- 已添加的schedule任务没有被取消,即使跳出循环,任务仍会继续执行
以下是修复后的代码:
import schedule import telebot from telebot import types import time from threading import Thread token = '' bot = telebot.TeleBot(token) # 全局变量控制发送状态,以及保存schedule任务引用 running_flag = False spam_job = None user_id = None def spam(): if running_flag and user_id: bot.send_message(user_id, 'testtest') def run_schedule(): while True: if running_flag: schedule.run_pending() time.sleep(1) # 启动schedule线程,避免阻塞主轮询 Thread(target=run_schedule, daemon=True).start() @bot.message_handler(commands=['start']) def start_handler(message): global user_id user_id = message.from_user.id markup = types.InlineKeyboardMarkup() btn1 = types.InlineKeyboardButton('yes', callback_data='yes') btn2 = types.InlineKeyboardButton('no', callback_data='no') markup.add(btn1, btn2) bot.send_message(message.chat.id, '是否开始自动发送?', reply_markup=markup) @bot.callback_query_handler(func=lambda callback: True) def callback_message(callback): global running_flag, spam_job if callback.data == 'yes': if not running_flag: running_flag = True # 仅在未启动时添加任务 spam_job = schedule.every().second.do(spam) bot.answer_callback_query(callback.id, '已开始自动发送') else: running_flag = False if spam_job: schedule.cancel_job(spam_job) spam_job = None bot.answer_callback_query(callback.id, '已停止自动发送') bot.infinity_polling()
关键改动说明:
- 使用**全局变量
running_flag**控制发送状态,确保回调可以修改状态 - 把schedule的运行逻辑放到独立线程中,避免阻塞TeleBot的主消息轮询线程
- 保存schedule任务的引用
spam_job,点击no时可以直接取消任务 - 添加
bot.answer_callback_query给用户反馈,提升交互体验 - 增加判断逻辑,避免重复添加schedule任务
内容的提问来源于stack exchange,提问作者FaweR
相关产品推荐
相关产品推荐

