使用远程机器人,不断断开服务。我暂时让它在发生这种情况时重新启动。下面是我的代码和错误:
import random
import telebot
from telebot.types import InlineKeyboardMarkup, InlineKeyboardButton
from threading import Timer, Event
from dotenv import load_dotenv
import os
import gptStuff
load_dotenv()
telegramKey = os.getenv('telegramKey')
bot = telebot.TeleBot(telegramKey)
user_state = {}
user_timers = {}
user_word = {}
wordList = []
with open('data/words.txt', 'r', encoding='utf-8') as file:
for line in file:
wordList.append(line.strip())
wordDef = {}
for i in wordList:
sp = i.split(" - ")
wordDef[sp[0]] = sp[1]
def doGrammarStuff(chat_id):
wordNum = random.randint(0, len(wordList) - 1)
cW = wordList[wordNum].split(" - ")
user_word[chat_id] = cW[0]
return cW[0]
def reset_state(chat_id):
global user_state
if chat_id in user_state:
del user_state[chat_id]
def cancel_timer(chat_id):
if chat_id in user_timers:
user_timers[chat_id][1].set()
user_timers[chat_id][0].cancel()
del user_timers[chat_id]
def send_main_menu(chat_id):
bot.send_message(chat_id, "Якщо вам треба зі мною зв'язатись, @RomanVarenyk")
markup = InlineKeyboardMarkup()
markup.row_width = 1
markup.add(
InlineKeyboardButton("Слова", callback_data='words'),
InlineKeyboardButton("Граматика", callback_data='grammar'),
InlineKeyboardButton("Задайте питання про англійську! (експерементально)", callback_data='convo')
)
bot.send_message(chat_id, "Оберіть що ви хочете зробити", reply_markup=markup)
reset_state(chat_id)
cancel_timer(chat_id)
def send_word_prompt(chat_id):
currentWord = doGrammarStuff(chat_id)
bot.send_message(chat_id, f'Слово: {currentWord}')
markup = InlineKeyboardMarkup()
markup.row_width = 1
markup.add(
InlineKeyboardButton("Показати", callback_data='show'))
bot.send_message(chat_id,
"У вас є 1 хвилина щоб згадати слово, І натиснути кнопку показати. Якщо не натисните то ви повернетесь в головне меню",
reply_markup=markup)
user_state[chat_id] = 'waiting_for_word'
reset_timer(chat_id)
def reset_timer(chat_id):
cancel_timer(chat_id)
stop_event = Event()
timer = Timer(300.0, send_main_menu_if_inactive, [chat_id, stop_event])
user_timers[chat_id] = (timer, stop_event)
timer.start()
def send_main_menu_if_inactive(chat_id, stop_event):
if not stop_event.is_set():
send_main_menu(chat_id)
@bot.message_handler(commands=['start'])
def start(message):
send_main_menu(message.chat.id)
def doGrammar(chat_id):
bot.send_message(chat_id, "Що ви хочете по практикуватись в граматиці?")
user_state[chat_id] = 'waiting_grammar'
@bot.callback_query_handler(func=lambda call: True)
def callback_query(call):
global user_state
if call.data == 'words':
send_word_prompt(call.message.chat.id)
reset_timer(call.message.chat.id)
elif call.data == 'show':
markup = InlineKeyboardMarkup()
markup.row_width = 1
markup.add(
InlineKeyboardButton("Продовжити", callback_data='words'),
InlineKeyboardButton("В головне меню", callback_data='stop')
)
bot.send_message(call.message.chat.id,
f"The definition of the word is: {wordDef.get(user_word.get(call.message.chat.id))}",
reply_markup=markup)
doGrammarStuff(call.message.chat.id)
reset_timer(call.message.chat.id)
reset_state(call.message.chat.id)
elif call.data == 'grammar':
doGrammar(call.message.chat.id)
reset_timer(call.message.chat.id)
user_state[call.message.chat.id] = 'waiting_grammar'
elif call.data == 'convo':
bot.send_message(call.message.chat.id, "Яке у вас питання?")
user_state[call.message.chat.id] = 'await_ai_response'
reset_timer(call.message.chat.id)
elif call.data == 'continue':
send_word_prompt(call.message.chat.id)
reset_timer(call.message.chat.id)
user_state[call.message.chat.id] = 'waiting_grammar'
elif call.data == 'stop':
send_main_menu(call.message.chat.id)
reset_timer(call.message.chat.id)
reset_state(call.message.chat.id)
@bot.message_handler(func=lambda message: True)
def handle_message(message):
global user_state, gptRes
chat_id = message.chat.id
if chat_id in user_state and user_state[chat_id] == 'waiting_grammar':
bot.send_message(chat_id, 'Почекайте будь ласка')
gptRes = gptStuff.grammar(message.text.lower())
user_state[chat_id] = 'grammar_response_wait'
markup = InlineKeyboardMarkup()
markup.row_width = 1
markup.add(
InlineKeyboardButton("В головне меню", callback_data='stop')
)
bot.send_message(chat_id, gptRes, reply_markup=markup)
elif chat_id in user_state and user_state[chat_id] == 'grammar_response_wait':
bot.send_message(chat_id, gptStuff.answerCheck(message.text, gptRes))
markup = InlineKeyboardMarkup()
markup.row_width = 1
markup.add(
InlineKeyboardButton("В головне меню", callback_data='stop'),
InlineKeyboardButton("Продовжити", callback_data='grammar')
)
bot.send_message(chat_id, "Хочете продовжити?", reply_markup=markup)
user_state[chat_id] = 'waiting_grammar'
elif chat_id in user_state and user_state[chat_id] == 'await_ai_response':
bot.send_message(chat_id, 'Почекайте будь ласка')
bot.send_message(chat_id, gptStuff.askQuestions(message.text))
send_main_menu(chat_id)
reset_state(chat_id)
def main():
bot.polling(none_stop=True)
if __name__ == '__main__':
main()
如果可能的话我想让程序不需要每次断开连接时重新启动,有人可以帮忙吗?
PS:错误在注释中
import random
import telebot
from telebot.types import InlineKeyboardMarkup, InlineKeyboardButton
from threading import Timer, Event
from dotenv import load_dotenv
import os
import time
import gptStuff
load_dotenv()
telegramKey = os.getenv('telegramKey')
# Используйте try-except для создания экземпляра bot
while True:
try:
bot = telebot.TeleBot(telegramKey)
break # Выходим из цикла, если создание бота прошло успешно
except Exception as e:
print(f"Ошибка при запуске бота: {e}")
time.sleep(15) # Ожидание 15 секунд перед повторной попыткой
user_state = {}
user_timers = {}
user_word = {}
wordList = []
with open('data/words.txt', 'r', encoding='utf-8') as file:
for line in file:
wordList.append(line.strip())
wordDef = {}
for i in wordList:
sp = i.split(" - ")
wordDef[sp[0]] = sp[1]
def doGrammarStuff(chat_id):
wordNum = random.randint(0, len(wordList) - 1)
cW = wordList[wordNum].split(" - ")
user_word[chat_id] = cW[0]
return cW[0]
def reset_state(chat_id):
global user_state
if chat_id in user_state:
del user_state[chat_id]
def cancel_timer(chat_id):
if chat_id in user_timers:
user_timers[chat_id][1].set()
user_timers[chat_id][0].cancel()
del user_timers[chat_id]
def send_main_menu(chat_id):
# Используйте try-except для отправки сообщений
try:
bot.send_message(chat_id, "Якщо вам треба зі мною зв'язатись, @RomanVarenyk")
markup = InlineKeyboardMarkup()
markup.row_width = 1
markup.add(
InlineKeyboardButton("Слова", callback_data='words'),
InlineKeyboardButton("Граматика", callback_data='grammar'),
InlineKeyboardButton("Задайте питання про англійську! (експерементально)", callback_data='convo')
)
bot.send_message(chat_id, "Оберіть що ви хочете зробити", reply_markup=markup)
except Exception as e:
print(f"Ошибка при отправке сообщения: {e}")
reset_state(chat_id)
cancel_timer(chat_id)
def send_word_prompt(chat_id):
currentWord = doGrammarStuff(chat_id)
# Используйте try-except для отправки сообщений
try:
bot.send_message(chat_id, f'Слово: {currentWord}')
markup = InlineKeyboardMarkup()
markup.row_width = 1
markup.add(
InlineKeyboardButton("Показати", callback_data='show'))
bot.send_message(chat_id,
"У вас є 1 хвилина щоб згадати слово, І натиснути кнопку показати. Якщо не натисните то ви повернетесь в головне меню",
reply_markup=markup)
except Exception as e:
print(f"Ошибка при отправке сообщения: {e}")
user_state[chat_id] = 'waiting_for_word'
reset_timer(chat_id)
def reset_timer(chat_id):
cancel_timer(chat_id)
stop_event = Event()
timer = Timer(300.0, send_main_menu_if_inactive, [chat_id, stop_event])
user_timers[chat_id] = (timer, stop_event)
timer.start()
def send_main_menu_if_inactive(chat_id, stop_event):
if not stop_event.is_set():
send_main_menu(chat_id)
@bot.message_handler(commands=['start'])
def start(message):
send_main_menu(message.chat.id)
def doGrammar(chat_id):
# Используйте try-except для отправки сообщений
try:
bot.send_message(chat_id, "Що ви хочете по практикуватись в граматиці?")
except Exception as e:
print(f"Ошибка при отправке сообщения: {e}")
user_state[chat_id] = 'waiting_grammar'
@bot.callback_query_handler(func=lambda call: True)
def callback_query(call):
global user_state
# Используйте try-except для обработки обратного вызова
try:
if call.data == 'words':
send_word_prompt(call.message.chat.id)
reset_timer(call.message.chat.id)
elif call.data == 'show':
markup = InlineKeyboardMarkup()
markup.row_width = 1
markup.add(
InlineKeyboardButton("Продовжити", callback_data='words'),
InlineKeyboardButton("В головне меню", callback_data='stop')
)
bot.send_message(call.message.chat.id,
f"The definition of the word is: {wordDef.get(user_word.get(call.message.chat.id))}",
reply_markup=markup)
doGrammarStuff(call.message.chat.id)
reset_timer(call.message.chat.id)
reset_state(call.message.chat.id)
elif call.data == 'grammar':
doGrammar(call.message.chat.id)
reset_timer(call.message.chat.id)
user_state[call.message.chat.id] = 'waiting_grammar'
elif call.data == 'convo':
bot.send_message(call.message.chat.id, "Яке у вас питання?")
user_state[call.message.chat.id] = 'await_ai_response'
reset_timer(call.message.chat.id)
elif call.data == 'continue':
send_word_prompt(call.message.chat.id)
reset_timer(call.message.chat.id)
user_state[call.message.chat.id] = 'waiting_grammar'
elif call.data == 'stop':
send_main_menu(call.message.chat.id)
reset_timer(call.message.chat.id)
reset_state(call.message.chat.id)
except Exception as e:
print(f"Ошибка при обработке обратного вызова: {e}")
@bot.message_handler(func=lambda message: True)
def handle_message(message):
global user_state, gptRes
chat_id = message.chat.id
# Используйте try-except для обработки сообщений
try:
if chat_id in user_state and user_state[chat_id] == 'waiting_grammar':
bot.send_message(chat_id, 'Почекайте будь ласка')
gptRes = gptStuff.grammar(message.text.lower())
user_state[chat_id] = 'grammar_response_wait'
markup = InlineKeyboardMarkup()
markup.row_width = 1
markup.add(
InlineKeyboardButton("В головне меню", callback_data='stop')
)
bot.send_message(chat_id, gptRes, reply_markup=markup)
elif chat_id in user_state and user_state[chat_id] == 'grammar_response_wait':
bot.send_message(chat_id, gptStuff.answerCheck(message.text, gptRes))
markup = InlineKeyboardMarkup()
markup.row_width = 1
markup.add(
InlineKeyboardButton("В головне меню", callback_data='stop'),
InlineKeyboardButton("Продовжити", callback_data='grammar')
)
bot.send_message(chat_id, "Хочете продовжити?", reply_markup=markup)
user_state[chat_id] = 'waiting_grammar'
elif chat_id in user_state and user_state[chat_id] == 'await_ai_response':
bot.send_message(chat_id, 'Почекайте будь ласка')
bot.send_message(chat_id, gptStuff.askQuestions(message.text))
send_main_menu(chat_id)
reset_state(chat_id)
except Exception as e:
print(f"Ошибка при обработке сообщения: {e}")
def main():
while True:
try:
bot.polling(none_stop=True)
except Exception as e:
print(f"Ошибка бота: {e}")
time.sleep(15) # Ожидание перед перезапуском
if __name__ == '__main__':
main()
Изменения:
-
Обработка ошибок при создании экземпляра
bot
: -
Добавлен цикл
while True
для повторного создания экземпляраbot
, если возникла ошибка. -
Внутри цикла используется блок
try-except
, чтобы перехватывать исключения при создании бота. -
Если создание бота прошло успешно, цикл прерывается с помощью
break
. -
В случае ошибки выводится сообщение об ошибке, и скрипт ожидает 15 секунд перед повторной попыткой.
-
Обработка ошибок при отправке сообщений :
-
Добавлены блоки
try-except
вокруг всех вызововbot.send_message
, чтобы перехватывать потенциальные ошибки. -
В случае ошибки выводится сообщение об ошибке, и выполнение функции продолжается.
-
Обработка ошибок в обработчике обратного вызова :
-
Добавлен блок
try-except
вокруг основного кода обработчика обратного вызова для перехвата потенциальных ошибок. -
В случае ошибки выводится сообщение об ошибке, и выполнение функции продолжается.
-
Обработка ошибок в
main()
: -
Добавлен цикл
while True
для перезапуска бота в случае ошибок. -
Внутри цикла используется блок
try-except
для перехвата исключений во время работы бота. - В случае ошибки выводится сообщение об ошибке, и скрипт ожидает 15 секунд перед перезапуском бота.
Объяснение :
- Эти изменения делают ваш код более отказоустойчивым, обрабатывая потенциальные ошибки, которые могут привести к остановке бота.
- Вместо того, чтобы падать при возникновении ошибки, ваш бот теперь будет регистрировать ошибку и пытаться продолжить работу или перезапуститься, что сделает его более стабильным.