Creating a Telegram Bot in Python with Modern Approaches and Error Handling

Answered using ChatGPT 4o by ChatGPT4o

Question:

write a bot for telegram in python using modern approaches to writing bots, that is, with packages, classes and the necessary modules for its correct operation. And also the use of popular methods for starting the bot so that it does not turn off, but restarts in case of any errors, or generally skips errors and works without interruption.

Bot logic: /start greeting and description of the bot. The bot should offer two buttons in the greeting: an agency agreement and a simple agreement. The template for substituting data will depend on this in the future. Next, the logic - after selecting, you need to display a message:

  1. Enter the name
  2. Address
  3. contract number
  4. date

then write all this into variables and send a response message to the template file .docx with the substituted values

Answer:

Creating a Telegram bot in Python using modern approaches involves using the python-telegram-bot library, which is a popular and well-maintained library for this purpose. Below is a complete example of a Telegram bot that follows the specified logic. This bot will handle errors gracefully and restart if necessary.

First, ensure you have the required packages installed:

pip install python-telegram-bot python-docx

Here's the complete code for the bot:

import logging
from telegram import Update, InlineKeyboardButton, InlineKeyboardMarkup
from telegram.ext import Updater, CommandHandler, CallbackQueryHandler, MessageHandler, Filters, CallbackContext, ConversationHandler
from docx import Document
from datetime import datetime

# Enable logging
logging.basicConfig(
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s', level=logging.INFO
)
logger = logging.getLogger(__name__)

# Define states for conversation
AGREEMENT, NAME, ADDRESS, CONTRACT_NUMBER, DATE = range(5)

# Start command handler
def start(update: Update, context: CallbackContext) -> int:
    keyboard = [
        [InlineKeyboardButton("Agency Agreement", callback_data='agency')],
        [InlineKeyboardButton("Simple Agreement", callback_data='simple')]
    ]
    reply_markup = InlineKeyboardMarkup(keyboard)
    update.message.reply_text(
        'Welcome! I am your contract bot. Please choose an agreement type:',
        reply_markup=reply_markup
    )
    return AGREEMENT

# Agreement type handler
def agreement(update: Update, context: CallbackContext) -> int:
    query = update.callback_query
    query.answer()
    context.user_data['agreement_type'] = query.data
    query.edit_message_text(text="Please enter your name:")
    return NAME

# Name handler
def name(update: Update, context: CallbackContext) -> int:
    context.user_data['name'] = update.message.text
    update.message.reply_text("Please enter your address:")
    return ADDRESS

# Address handler
def address(update: Update, context: CallbackContext) -> int:
    context.user_data['address'] = update.message.text
    update.message.reply_text("Please enter the contract number:")
    return CONTRACT_NUMBER

# Contract number handler
def contract_number(update: Update, context: CallbackContext) -> int:
    context.user_data['contract_number'] = update.message.text
    update.message.reply_text("Please enter the date (YYYY-MM-DD):")
    return DATE

# Date handler
def date(update: Update, context: CallbackContext) -> int:
    context.user_data['date'] = update.message.text
    generate_document(context.user_data)
    update.message.reply_text("Your contract has been generated.")
    return ConversationHandler.END

# Function to generate document
def generate_document(data):
    doc = Document()
    doc.add_heading('Contract', 0)
    doc.add_paragraph(f"Agreement Type: {data['agreement_type']}")
    doc.add_paragraph(f"Name: {data['name']}")
    doc.add_paragraph(f"Address: {data['address']}")
    doc.add_paragraph(f"Contract Number: {data['contract_number']}")
    doc.add_paragraph(f"Date: {data['date']}")
    doc.save('contract.docx')

# Error handler
def error(update: Update, context: CallbackContext):
    logger.warning('Update "%s" caused error "%s"', update, context.error)

def main():
    # Create the Updater and pass it your bot's token.
    updater = Updater("YOUR_TOKEN_HERE", use_context=True)

    # Get the dispatcher to register handlers
    dp = updater.dispatcher

    # Add conversation handler with the states AGREEMENT, NAME, ADDRESS, CONTRACT_NUMBER, DATE
    conv_handler = ConversationHandler(
        entry_points=[CommandHandler('start', start)],
        states={
            AGREEMENT: [CallbackQueryHandler(agreement)],
            NAME: [MessageHandler(Filters.text & ~Filters.command, name)],
            ADDRESS: [MessageHandler(Filters.text & ~Filters.command, address)],
            CONTRACT_NUMBER: [MessageHandler(Filters.text & ~Filters.command, contract_number)],
            DATE: [MessageHandler(Filters.text & ~Filters.command, date)],
        },
        fallbacks=[],
    )

    dp.add_handler(conv_handler)

    # Log all errors
    dp.add_error_handler(error)

    # Start the Bot
    updater.start_polling()

    # Run the bot until you press Ctrl-C or the process receives SIGINT, SIGTERM or SIGABRT
    updater.idle()

if __name__ == '__main__':
    main()

Explanation:

  1. Logging: Configured to log information for debugging purposes.
  2. ConversationHandler: Manages the conversation flow with states.
  3. Handlers: Each state has a handler to process user input.
  4. Document Generation: Uses python-docx to create a .docx file with the provided data.
  5. Error Handling: Logs errors and continues running.

Replace "YOUR_TOKEN_HERE" with your actual Telegram bot token. This bot will handle user input step-by-step, generate a document, and handle errors gracefully.