运行 一个 Telegram Bot 无法跳出循环

Not able to break from loop while running a Telegram Bot

我正在使用 pyTelegramBotAPI that sends real-time updates of ongoing cricket matches. I want to break the loop whenever the user enters the "/stop" command. I've looked up various sources and also tried several methods to achieve the same but all in vain. The loop continues to iterate. The closest I've reached is by exiting the program by raising an error. Also, while inside the loop, the getUpdates method always returns an empty list. I've also written an issue 在 GitHub 上创建一个 Telegram 机器人。

def loop(match_url):
    prev_info = ""
    flag = 1
    #continuously fetch data 
    while flag:
        response = requests.get(match_url)
        info = response.json()['score']
        #display only when the score updates 
        if str(info) != prev_info:
            prev_info = str(info)
            send_msg(info)
        else:
            pass
        send_msg(info)
        #this handler needs to be fixed 
        @bot.message_handler(commands=['stop', 'end'])
        def stop(message):
            #code to break the loop
            flag = 0
            return
            

既然不行,我就自愿用这个错误的方法:

while flag:
        response = requests.get(match_url)
        info = response.json()['score']
        if str(info) != prev_info:
            prev_info = str(info)
            send_msg(info)
        else:
            pass
        send_msg(info)
        @bot.message_handler(commands=['stop', 'end'])
        def stop(message):
            bot.polling.abort = True #an arbitrary function that raises error and exits the program

这是完整的代码。我还添加了我的 GitHub link 代码:

import requests, json, telebot

token = <TOKEN>
bot = telebot.TeleBot(token)

#parsing data from cricapi.com
def live_matches():
    #here I'm using the KEY obtained from cricapi.com
    curr_matches_url = "https://cricapi.com/api/cricket?apikey=<KEY>"  
    curr_matches = requests.get(curr_matches_url)
    match_data = curr_matches.json()['data']
    global unique_id_arr, score_arr
    unique_id_arr, score_arr = [], []
    match_details = ""
    for i in match_data:
        unique_id_arr.append(i["unique_id"])
    for i in range(len(match_data)):
        score_arr.append(match_data[i]["title"])
        score_arr[i] += "\n"
        match_details += str(i+1) + ". "
        match_details += score_arr[i]
    send_msg(match_details)

def send_msg(msg):
    url2 = 'https://api.telegram.org/bot'+token+'/sendMessage'
    data = {'chat_id': chat_id, 'text': msg}
    requests.post(url2, data).json()


@bot.message_handler(commands=['start', 'help'])
def send_welcome(message):
    bot.reply_to(message, "Howdy, how are you doing?")
    global chat_id
    chat_id = message.chat.id
    msg = bot.reply_to(message, "Welcome to test project\nEnter the match number whose updates you want to receive")
    live_matches()
    bot.register_next_step_handler(msg, fetch_score)

def fetch_score(message):
    chat_id = message.chat.id
    match_no = message.text
    #checking if the number entered is present in the displayed list
    if not match_no.isdigit():
        msg = bot.reply_to(message, 'Error1!\nSelect a no. from the above list only')
        return bot.register_next_step_handler(msg, fetch_score)
    elif 1 <= int(match_no) <= len(score_arr):
        unique_id = unique_id_arr[int(match_no)-1]
        global match_url
        #get the data of the desired match
        match_url = "https://cricapi.com/api/cricketScore?unique_id="+unique_id+"&apikey=<KEY>"
        loop(match_url)
    else:
        msg = bot.reply_to(message, "Error2!\nSelect a no. from the above list only")
        return bot.register_next_step_handler(msg, fetch_score)

def loop(match_url):
    prev_info = ""
    flag = 1
    #continuously fetch data
    while flag:
        response = requests.get(match_url)
        info = response.json()['score']
        #display only when the score updates
        if str(info) != prev_info:
            prev_info = str(info)
            send_msg(info)
        else:
            pass
        send_msg(info)
        #this handler needs to be fixed
        @bot.message_handler(commands=['stop', 'end'])
        def stop(message):
            #an arbitrary function that raises error and then exits
            bot.polling.abort = True 
bot.polling()
"""
#currently not using
def receive_msg():
    url1 = 'https://api.telegram.org/bot'+token+'/getUpdates'
    response = requests.get(url1)
    text = response.json()['result']
    if len(text) > 0:
        user_msg = text[-1]['message']['text']
        return user_msg
    return text
"""

您正在以错误的方式使用 telebot(pyTelegramBotAPI) 包:

  1. 为什么在 telebot 中已有 send_message 方法的地方创建自己的函数 send_msg
  2. 您在循环中重新声明了“停止”处理程序,这是错误的!

My suggestion to you is to learn how to use the pyTelegramBotAPI properly!

这是一个演示代码,可以解决您的问题:

import telebot
from time import sleep

bot = telebot.TeleBot(BOT_TOKEN)
flag = 1

@bot.message_handler(commands=['loop'])
def loop(msg):
    while flag:
        bot.send_message(msg.chat.id, "ping")
        sleep(1)

@bot.message_handler(commands=['stop', 'end'])
def stop(msg):
    global flag
    flag = 0
    bot.send_message(msg.chat.id, "stopped")


bot.polling(none_stop=True)

解释:

  • flag声明为全局变量并将其设置为1
  • 用于启动每秒向您发送“ping”消息的循环的“循环”处理程序
  • “停止”处理程序,将 flag 更改为 0,从而终止您的 运行 循环