I am creating a Telegram Bot using 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 for the same on GitHub.
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
Since this was not working, I willingly used this wrong method:
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
Here's the whole code. I've also added my GitHub link of this code:
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
"""
You are using telebot
(pyTelegramBotAPI) package in the wrong way:
send_msg
where there is already send_message
method in telebot
exists?My suggestion to you is to learn how to use the
pyTelegramBotAPI
properly!
Here is a demonstration code, that solves your problem:
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)
Explanation:
flag
as a global variable and set it to 1
flag
to 0
, which terminates your running loop