```python
# main.py
import os
import string
import random
import asyncio
import logging
import json
from telegram import (
    Update,
    ReplyKeyboardMarkup,
    InlineKeyboardButton,
    InlineKeyboardMarkup,
)
from telegram.ext import (
    ApplicationBuilder,
    CommandHandler,
    ContextTypes,
    CallbackQueryHandler,
)
from dotenv import load_dotenv
import aiosqlite  # Асинхронная работа с SQLite
from gradio_client import Client

# Настройка логирования
logging.basicConfig(
    format='%(asctime)s - %(name)s - %(levelname)s - %(message)s',
    level=logging.INFO
)
logger = logging.getLogger(__name__)

# Загрузка переменных окружения из .env файла
load_dotenv()

BOT_TOKEN = os.getenv('BOT_TOKEN')
ADMIN_USER_ID = os.getenv('ADMIN_USER_ID')  # ID администратора для уведомлений
SBERBANK_NUMBER = os.getenv('SBERBANK_NUMBER')
SBERBANK_AMOUNT = os.getenv('SBERBANK_AMOUNT')
O1MINI_CLIENT_URL = os.getenv('O1MINI_CLIENT_URL')  # URL вашего нейросетевого API

# Проверка наличия всех необходимых переменных окружения
if not all([BOT_TOKEN, ADMIN_USER_ID, SBERBANK_NUMBER, SBERBANK_AMOUNT, O1MINI_CLIENT_URL]):
    raise ValueError("Пожалуйста, убедитесь, что все переменные окружения корректно настроены.")

# Генерация уникального ID
def generate_unique_id(length=8):
    characters = string.ascii_letters + string.digits
    return ''.join(random.choice(characters) for _ in range(length))

# Асинхронная функция для инициализации базы данных
async def init_db():
    async with aiosqlite.connect('payments.db') as db:
        await db.execute('''
            CREATE TABLE IF NOT EXISTS payments (
                user_id INTEGER PRIMARY KEY,
                unique_id TEXT UNIQUE,
                payment_status TEXT,
                requests_left INTEGER DEFAULT 0,
                chat_counter INTEGER DEFAULT 0,
                chatbot TEXT DEFAULT '[]'
            )
        ''')
        await db.commit()

# Функция для парсинга ответа нейросети и обновления состояния чата
def parse_neural_response(response, user_query, chat_counter, chatbot):
    """
    Функция для парсинга ответа нейросети и обновления состояния чата.
    Поддерживает несколько форматов ответа.
    """
    try:
        if isinstance(response, tuple):
            # Предполагаем, что первый элемент кортежа — это список с вопросом и ответом
            first_elem = response[0]
            if isinstance(first_elem, list) and len(first_elem) > 0:
                inner_list = first_elem[0]
                if isinstance(inner_list, list) and len(inner_list) > 1:
                    answer = inner_list[1]
                    chatbot.append([user_query, answer])
                    chat_counter += 1
                    return answer, chat_counter, chatbot
        elif isinstance(response, list):
            if len(response) >= 2:
                # Предполагаем, что второй элемент списка содержит ответ
                answer = response[1]
                chatbot.append([user_query, answer])
                chat_counter += 1
                return answer, chat_counter, chatbot
            elif len(response) == 1:
                # В случае, если есть только один элемент, предполагаем, что это ответ
                answer = response[0]
                chatbot.append([user_query, answer])
                chat_counter += 1
                return answer, chat_counter, chatbot
        elif isinstance(response, dict):
            # Если ответ в виде словаря, попытаться извлечь значение по ключу
            answer = response.get('answer', "❌ Не удалось извлечь ответ из полученных данных.")
            chatbot.append([user_query, answer])
            chat_counter += 1
            return answer, chat_counter, chatbot
    except Exception as e:
        logger.error(f"Ошибка при разборе ответа нейросети: {e}")
    return "❌ Не удалось извлечь ответ из структуры ответа нейросети.", chat_counter, chatbot

# Команда /start
async def start(update: Update, context: ContextTypes.DEFAULT_TYPE):
    user = update.effective_user
    user_id = user.id

    async with aiosqlite.connect('payments.db') as db:
        db.row_factory = aiosqlite.Row
        cursor = await db.execute("SELECT payment_status FROM payments WHERE user_id=?", (user_id,))
        result = await cursor.fetchone()
        await cursor.close()

    if result and result['payment_status'] == 'paid':
        welcome_text = (
            f"👋 Привет, @{user.username if user.username else 'Неведомый пользователь'}!\n\n"
            "Вы уже оплатили доступ. Вы можете задать вопрос нейросети с помощью команды /ask."
        )
        await update.message.reply_text(welcome_text)
    else:
        unique_id = generate_unique_id()
        chatbot_initial = json.dumps([])  # Инициализация пустого списка чата

        async with aiosqlite.connect('payments.db') as db:
            await db.execute("""
                INSERT INTO payments 
                (user_id, unique_id, payment_status, requests_left, chat_counter, chatbot) 
                VALUES (?, ?, ?, ?, ?, ?)
                ON CONFLICT(user_id) DO UPDATE SET
                    unique_id=excluded.unique_id,
                    payment_status=excluded.payment_status,
                    requests_left=excluded.requests_left,
                    chat_counter=excluded.chat_counter,
                    chatbot=excluded.chatbot
            """, (user_id, unique_id, 'pending', 0, 0, chatbot_initial))
            await db.commit()

        payment_instructions = (
            "👋 Привет! Добро пожаловать в нашего Telegram-бота с нейросетью.\n\n"
            "📄 **Доступные Команды:**\n"
            "/start - Запустить бота и получить инструкции.\n"
            "/ask - Задать вопрос нейросети.\n"
            "/me - Просмотреть ваш профиль.\n"
            "/help - Показать список доступных команд.\n\n"
            "🛒 **Оплата:**\n"
            "Чтобы получить доступ к функциям бота и общению с нейросетью, пожалуйста, совершите перевод на следующую карту Сбербанк:\n\n"
            f"📱 **Номер для перевода:** `{SBERBANK_NUMBER}`\n"
            f"💰 **Сумма:** `{SBERBANK_AMOUNT}` рублей\n"
            f"🆔 **Уникальный ID:** `{unique_id}`\n\n"
            "❗ **Важно:** Введите ваш Уникальный ID в комментарии к переводу.\n\n"
            "После совершения перевода, нажмите кнопку с вашим уникальным ID для подтверждения оплаты."
        )

        # Кнопка для подтверждения оплаты
        keyboard = [
            [InlineKeyboardButton(unique_id, callback_data=f"confirm_{unique_id}")]
        ]
        reply_markup = InlineKeyboardMarkup(keyboard)

        await update.message.reply_text(
            payment_instructions,
            reply_markup=reply_markup,
            parse_mode='Markdown'
        )

# Обработка нажатий кнопок
async def button_handler(update: Update, context: ContextTypes.DEFAULT_TYPE):
    query = update.callback_query
    await query.answer()

    data = query.data

    if data.startswith("confirm_"):
        unique_id = data.split("_", 1)[1]
        user_id = query.from_user.id
        username = query.from_user.username or "N/A"

        # Уведомление администратора о подтверждении оплаты
        admin_message = (
            f"🔔 **Запрос на Подтверждение Оплаты**\n"
            f"Пользователь @{username} (ID: {user_id}) запросил подтверждение оплаты.\n\n"
            f"🆔 **Уникальный ID:** `{unique_id}`\n\n"
            f"Пожалуйста, используйте административную панель для подтверждения оплаты."
        )

        try:
            await context.bot.send_message(chat_id=ADMIN_USER_ID, text=admin_message, parse_mode='Markdown')
            await query.edit_message_text("✅ Ваш запрос на подтверждение оплаты отправлен администратору. Ожидайте подтверждения.")
        except Exception as e:
            logger.error(f"Ошибка при отправке сообщения администратору: {e}")
            await query.edit_message_text("❌ Произошла ошибка при отправке запроса администратору. Пожалуйста, попробуйте позже.")

# Команда /me для просмотра профиля
async def me(update: Update, context: ContextTypes.DEFAULT_TYPE):
    user = update.effective_user
    user_id = user.id

    async with aiosqlite.connect('payments.db') as db:
        db.row_factory = aiosqlite.Row
        cursor = await db.execute("SELECT unique_id, payment_status, requests_left FROM payments WHERE user_id=?", (user_id,))
        result = await cursor.fetchone()
        await cursor.close()

    if not result:
        await update.message.reply_text("❌ Вы ещё не зарегистрированы. Введите /start для начала.")
        return

    unique_id = result['unique_id']
    payment_status = result['payment_status']
    requests_left = result['requests_left']

    profile_info = (
        f"📝 **Ваш Профиль:**\n\n"
        f"**Никнейм:** @{user.username if user.username else 'N/A'}\n"
        f"**ID Пользователя:** {user_id}\n"
        f"**Уникальный ID:** `{unique_id}`\n"
        f"**Статус Оплаты:** {'✅ Оплачено' if payment_status == 'paid' else '❌ Неоплачено'}\n"
        f"**Доступные Запросы:** {requests_left}"
    )

    await update.message.reply_text(profile_info, parse_mode='Markdown')

# Команда /help
async def help_command(update: Update, context: ContextTypes.DEFAULT_TYPE):
    help_text = (
        "📖 **Доступные Команды:**\n\n"
        "/start - Запустить бота и получить инструкции.\n"
        "/ask - Задать вопрос нейросети.\n"
        "/me - Просмотреть ваш профиль.\n"
        "/help - Показать список доступных команд."
    )
    await update.message.reply_text(help_text, parse_mode='Markdown')

# Команда /ask для взаимодействия с нейросетью
async def ask_neural_network(update: Update, context: ContextTypes.DEFAULT_TYPE):
    user = update.effective_user
    user_id = user.id
    user_input_text = update.message.text.strip()

    # Исключить команду /ask из запроса
    if user_input_text.startswith('/ask'):
        user_query = user_input_text[4:].strip()
    else:
        user_query = user_input_text

    if not user_query:
        await update.message.reply_text("❗ Пожалуйста, задайте свой вопрос после команды /ask.")
        return

    async with aiosqlite.connect('payments.db') as db:
        db.row_factory = aiosqlite.Row
        cursor = await db.execute("SELECT payment_status, requests_left, chat_counter, chatbot FROM payments WHERE user_id=?", (user_id,))
        result = await cursor.fetchone()
        await cursor.close()

    if not result or result['payment_status'] != 'paid':
        await update.message.reply_text(
            "🚫 Для доступа, пожалуйста, оплатите.",
            reply_markup=ReplyKeyboardMarkup([["Отправить ID"]], one_time_keyboard=True),
        )
        return

    requests_left = result['requests_left']
    if requests_left <= 0:
        await update.message.reply_text("⚠️ У вас закончились запросы. Пожалуйста, продлите подписку.")
        return

    # Извлечение состояния чата
    chat_counter = result['chat_counter']
    chatbot_serialized = result['chatbot']
    try:
        chatbot = json.loads(chatbot_serialized)
    except json.JSONDecodeError:
        chatbot = []

    # Получаем Gradio client из контекста приложения
    client = context.application['client']

    # Отправка запроса к нейросети
    await update.message.reply_text("🔄 Обрабатываю ваш запрос...")

    try:
        # Получить текущий цикл событий
        loop = asyncio.get_running_loop()
        response = await loop.run_in_executor(None, lambda: client.predict(
            inputs=user_query,
            top_p=1,
            temperature=1,
            chat_counter=chat_counter,
            chatbot=chatbot,
            api_name="/predict"
        ))

        # Логирование полного ответа для отладки
        logger.info(f"Полный ответ от нейросети: {response}")

        # Обработка формата ответа и извлечение обновленного состояния чата
        neural_response, updated_chat_counter, updated_chatbot = parse_neural_response(response, user_query, chat_counter, chatbot)

        # Проверка содержимого нейросетевого ответа
        if neural_response and not neural_response.startswith("❌"):
            await update.message.reply_text(neural_response)
            # Уменьшаем количество запросов и обновляем состояние чата
            updated_chatbot_serialized = json.dumps(updated_chatbot)

            async with aiosqlite.connect('payments.db') as db:
                await db.execute("""
                    UPDATE payments 
                    SET requests_left = requests_left - 1, chat_counter = ?, chatbot = ?
                    WHERE user_id=?
                """, (updated_chat_counter, updated_chatbot_serialized, user_id))
                await db.commit()
        else:
            await update.message.reply_text(neural_response if neural_response else "❌ Не удалось получить содержательный ответ от нейросети.")

    except Exception as e:
        logger.error(f"Ошибка при взаимодействии с нейросетью: {e}")
        await update.message.reply_text("❌ Произошла ошибка при обработке вашего запроса. Пожалуйста, попробуйте позже.")

# Асинхронная основная функция для запуска бота
async def main_async():
    # Инициализация базы данных
    await init_db()

    # Инициализация клиента для нейросети внутри main_async
    client = Client(O1MINI_CLIENT_URL)

    # Создание приложения Telegram
    application = ApplicationBuilder().token(BOT_TOKEN).build()

    # Сохранение клиента в контексте приложения для доступа внутри обработчиков
    application['client'] = client

    # Регистрация обработчиков команд
    application.add_handler(CommandHandler("start", start))
    application.add_handler(CommandHandler("ask", ask_neural_network))
    application.add_handler(CommandHandler("me", me))
    application.add_handler(CommandHandler("help", help_command))

    # Регистрация обработчика нажатий кнопок
    application.add_handler(CallbackQueryHandler(button_handler))

    logger.info("Бот запущен...")
    await application.run_polling()

if __name__ == '__main__':
    try:
        asyncio.run(main_async())
    except RuntimeError as e:
        if "Cannot close a running event loop" in str(e):
            logger.error("Невозможно закрыть уже запущенный цикл событий.")
        else:
            raise
```
Очень сильно прошу тебя оптимизировать код, структурировать его, убрать ненужное, исправить баги и ошибки, а так же сверить работу API  с документацией.
Возникло исключение: TypeError
'Application' object does not support item assignment
  File "C:\Users\Admin\Desktop\telegrambot\main.py", line 333, in main_async
    application['client'] = client
    ~~~~~~~~~~~^^^^^^^^^^
  File "C:\Users\Admin\Desktop\telegrambot\main.py", line 349, in <module>
    asyncio.run(main_async())
TypeError: 'Application' object does not support item assignment
API:"API documentation
yuntian-deng/o1mini

API Recorder

5 API endpoints


Choose a language to see the code snippets for interacting with the API.

1. Install the python client (docs) if you don't already have it installed.

copy
$ pip install gradio_client
2. Find the API endpoint below corresponding to your desired function in the app. Copy the code snippet, replacing the placeholder values with your own input data. If this is a private Space, you may need to pass your Hugging Face token as well (read more). Or use the 
API Recorder

 to automatically generate your API requests.

api_name: /enable_inputs
copy
from gradio_client import Client

client = Client("yuntian-deng/o1mini")
result = client.predict(
		api_name="/enable_inputs"
)
print(result)
Accepts 0 parameters:
Returns 1 element
api_name: /reset_textbox
copy
from gradio_client import Client

client = Client("yuntian-deng/o1mini")
result = client.predict(
		api_name="/reset_textbox"
)
print(result)
Accepts 0 parameters:
Returns 1 element
str

The output value that appears in the "Type an input and press Enter" Textbox component.

api_name: /predict
copy
from gradio_client import Client

client = Client("yuntian-deng/o1mini")
result = client.predict(
		inputs="Hello!!",
		top_p=1,
		temperature=1,
		chat_counter=0,
		chatbot=[],
		api_name="/predict"
)
print(result)
Accepts 5 parameters:
inputs str Required

The input value that is provided in the "Type an input and press Enter" Textbox component.

top_p float Default: 1

The input value that is provided in the "Top-p (nucleus sampling)" Slider component.

temperature float Default: 1

The input value that is provided in the "Temperature" Slider component.

chat_counter float Default: 0

The input value that is provided in the "parameter_16" Number component.

chatbot Tuple[str | Dict(file: filepath, alt_text: str | None) | Dict(component: str, value: Any, constructor_args: Dict(), props: Dict()) | None, str | Dict(file: filepath, alt_text: str | None) | Dict(component: str, value: Any, constructor_args: Dict(), props: Dict()) | None] Default: []

The input value that is provided in the "parameter_4" Chatbot component.

Returns tuple of 4 elements
[0] Tuple[str | Dict(file: filepath, alt_text: str | None) | Dict(component: str, value: Any, constructor_args: Dict(), props: Dict()) | None, str | Dict(file: filepath, alt_text: str | None) | Dict(component: str, value: Any, constructor_args: Dict(), props: Dict()) | None]

The output value that appears in the "value_4" Chatbot component.

[1] float

The output value that appears in the "value_16" Number component.

[2] str

The output value that appears in the "Status code from OpenAI server" Textbox component.

[3] str

The output value that appears in the "Type an input and press Enter" Textbox component.

api_name: /reset_textbox_1
copy
from gradio_client import Client

client = Client("yuntian-deng/o1mini")
result = client.predict(
		api_name="/reset_textbox_1"
)
print(result)
Accepts 0 parameters:
Returns 1 element
str

The output value that appears in the "Type an input and press Enter" Textbox component.

api_name: /predict_1
copy
from gradio_client import Client

client = Client("yuntian-deng/o1mini")
result = client.predict(
		inputs="Hello!!",
		top_p=1,
		temperature=1,
		chat_counter=0,
		chatbot=[],
		api_name="/predict_1"
)
print(result)
Accepts 5 parameters:
inputs str Required

The input value that is provided in the "Type an input and press Enter" Textbox component."