首页 > 编程问答 >python中的Telebot API不断断开连接

python中的Telebot API不断断开连接

时间:2024-07-29 08:30:03浏览次数:7  
标签:python

使用远程机器人,不断断开服务。我暂时让它在发生这种情况时重新启动。下面是我的代码和错误:

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()

Изменения:

  1. Обработка ошибок при создании экземпляра bot :
  2. Добавлен цикл while True для повторного создания экземпляра bot , если возникла ошибка.
  3. Внутри цикла используется блок try-except , чтобы перехватывать исключения при создании бота.
  4. Если создание бота прошло успешно, цикл прерывается с помощью break .
  5. В случае ошибки выводится сообщение об ошибке, и скрипт ожидает 15 секунд перед повторной попыткой.

  6. Обработка ошибок при отправке сообщений :

  7. Добавлены блоки try-except вокруг всех вызовов bot.send_message , чтобы перехватывать потенциальные ошибки.
  8. В случае ошибки выводится сообщение об ошибке, и выполнение функции продолжается.

  9. Обработка ошибок в обработчике обратного вызова :

  10. Добавлен блок try-except вокруг основного кода обработчика обратного вызова для перехвата потенциальных ошибок.
  11. В случае ошибки выводится сообщение об ошибке, и выполнение функции продолжается.

  12. Обработка ошибок в main() :

  13. Добавлен цикл while True для перезапуска бота в случае ошибок.
  14. Внутри цикла используется блок try-except для перехвата исключений во время работы бота.
  15. В случае ошибки выводится сообщение об ошибке, и скрипт ожидает 15 секунд перед перезапуском бота.

Объяснение :

  • Эти изменения делают ваш код более отказоустойчивым, обрабатывая потенциальные ошибки, которые могут привести к остановке бота.
  • Вместо того, чтобы падать при возникновении ошибки, ваш бот теперь будет регистрировать ошибку и пытаться продолжить работу или перезапуститься, что сделает его более стабильным.

标签:python
From: 78805098

相关文章

  • 如何用Python制作Android服务?
    我想构建一个简单的Android应用程序,例如PushOver应用程序,它具有TCP服务器并接收其记录的文本消息,然后将其作为推送通知发送。这部分已经完成并且工作正常。但即使GUI应用程序关闭,我也想接收消息。我知道这是可能的,因为PushOver应用程序做到了!我想,我可能需要一......
  • Python Discord Bot 的应用程序命令的区域设置名称(多语言别名)
    如何根据用户的语言设置,使应用程序命令的名称具有不同的名称例如,如果一个用户将其discord的语言设置为英语,则用户可以看到英语的应用程序命令名称。另一方面,如果另一个用户将其不和谐语言设置为法语,则用户可以看到法语中的相同应用程序命令的名称。为此,我尝试使用ap......
  • 如何在Python中添加热键?
    我正在为游戏制作一个机器人,我想在按下热键时调用该函数。我已经尝试了一些解决方案,但效果不佳。这是我的代码:defstart():whileTrue:ifkeyboard.is_pressed('alt+s'):break...defmain():whileTrue:ifkeyboard.is_pr......
  • 在Python中解压文件
    我通读了zipfile文档,但不明白如何解压缩文件,只了解如何压缩文件。如何将zip文件的所有内容解压缩到同一目录中?importzipfilewithzipfile.ZipFile('your_zip_file.zip','r')aszip_ref:zip_ref.extractall('target_directory')将......
  • 如何在Python中从RSA公钥中提取N和E?
    我有一个RSA公钥,看起来像-----BEGINPUBLICKEY-----MIIBIDANBgkqhkiG9w0BAQEFAAOCAQ0AMIIBCAKCAQEAvm0WYXg6mJc5GOWJ+5jkhtbBOe0gyTlujRER++cvKOxbIdg8So3mV1eASEHxqSnp5lGa8R9Pyxz3iaZpBCBBvDB7Fbbe5koVTmt+K06o96ki1/4NbHGyRVL/x5fFiVuTVfmk+GZNakH5dXDq0fwvJyVmUtGYA......
  • Swagger、Docker、Python-Flask: : https://editor.swagger.io/ 生成服务器 python-fl
    在https://editor.swagger.io/上您可以粘贴一些json/yaml。我正在将此作为JSON进行测试(不要转换为YAML):{"swagger":"2.0","info":{"version":"1.0","title":"OurfirstgeneratedRES......
  • 使用 Matplotlib 的 Python 代码中出现意外的控制流
    Ubuntu22.04上的此Python3.12代码的行为符合预期,除非我按q或ESC键退出。代码如下:importnumpyasnp,matplotlib.pyplotaspltfrompathlibimportPathfromcollectionsimportnamedtuplefromskimage.ioimportimreadfrommatplotlib.widgets......
  • 参考 - Python 类型提示
    这是什么?这是与在Python中使用类型提示主题相关的问题和答案的集合。这个问题本身就是一个社区维基;欢迎大家参与维护。这是为什么?Python类型提示是一个不断增长的话题,因此许多(可能的)新问题已经被提出,其中许多甚至已经有了答案。该集合有助于查找现有内容。范......
  • 我的 Python 程序中解决 UVa 860 的运行时错误 - 熵文本分析器
    我正在尝试为UVa860编写一个解决方案,但是当我通过vJudge发送它时,它一直显示“运行时错误”。fromsysimportstdinimportmathdefmain():end_of_input=Falselambda_words=0dictionary={}text_entropy=0relative_entropy=0whilenotend_of_in......
  • Python进度条
    当我的脚本正在执行某些可能需要时间的任务时,如何使用进度条?例如,一个需要一些时间才能完成并在完成后返回True的函数。如何在函数执行期间显示进度条?请注意,我需要实时显示进度条,所以我不知道该怎么办。我需要thread为此吗?我不知道。现在在执行函数......