Как передать данные пользователя из Telegram бота в приложение Flet

    При разработке связки Telegram-бота (на библиотеке telebot) и WebApp на Flet часто возникает задача синхронизации данных. Пользователь пишет боту, бот сохраняет его ID, имя и баланс монет в базу данных SQLite. Затем пользователь переходит в игру на Flet, где ему нужно показать текущее количество монет и обновлять его при нажатии кнопки. Разберём, как организовать передачу данных и обратную запись в БД.

    Архитектура взаимодействия: Telegram бот, Flet WebApp и база данных

    Основная сложность - Flet-приложение запускается отдельно (например, через ngrok) и не имеет прямого доступа к переменным бота. Данные нужно передавать через URL-параметры или Webhook. Рассмотрим пошагово.

    Шаг 1: Инициализация пользователя в Telegram боте

    Когда пользователь отправляет любое сообщение боту, используйте message.from_user.id и message.from_user.first_name. Проверьте, есть ли запись в таблице SQLite. Если нет - добавьте с coins = 0.

    import sqlite3
    conn = sqlite3.connect('game.db')
    c = conn.cursor()
    c.execute('''CREATE TABLE IF NOT EXISTS users (user TEXT, id INTEGER PRIMARY KEY, coins INTEGER)''')
    user_id = message.from_user.id
    c.execute('SELECT * FROM users WHERE id=?', (user_id,))
    if c.fetchone() is None:
        c.execute('INSERT INTO users (user, id, coins) VALUES (?, ?, 0)', (message.from_user.first_name, user_id))
    conn.commit()

    Шаг 2: Генерация ссылки на игру с параметрами

    При нажатии на кнопку в боте, формируйте URL для Flet-приложения, содержащий user_id и coins. Например, через ngrok ваш Flet-сервер доступен по адресу https://ваш-адрес.ngrok.io. Добавьте параметры: ?user_id=123&coins=0.

    import telebot
    from telebot.types import InlineKeyboardMarkup, InlineKeyboardButton
    
    user_id = message.from_user.id
    coins = c.execute('SELECT coins FROM users WHERE id=?', (user_id,)).fetchone()[0]
    url = f'https://ваш-адрес.ngrok.io/?user_id={user_id}&coins={coins}'
    
    keyboard = InlineKeyboardMarkup()
    keyboard.add(InlineKeyboardButton('Играть', url=url))
    bot.send_message(message.chat.id, 'Нажми, чтобы начать игру!', reply_markup=keyboard)

    Шаг 3: Получение параметров в Flet-приложении

    В Flet используйте page.client_storage или напрямую разбирайте URL. Самый простой способ - передать параметры через query string и прочитать их в page.on_connect или в функции main.

    import flet as ft
    import urllib.parse
    
    def main(page: ft.Page):
        params = urllib.parse.parse_qs(page.platform.views[0].url.query)
        user_id = int(params.get('user_id', [0])[0])
        coins = int(params.get('coins', [0])[0])
        
        coin_counter = ft.Text(f'Монеты: {coins}', size=30)
        
        def on_click(e):
            nonlocal coins
            coins += 1
            coin_counter.value = f'Монеты: {coins}'
            # Здесь будет вызов обновления БД
            update_db(user_id, coins)
            page.update()
        
        page.add(coin_counter, ft.ElevatedButton('Нажми меня!', on_click=on_click))
    
    ft.app(target=main)

    Шаг 4: Обновление базы данных из Flet

    Flet-приложение должно напрямую подключаться к той же базе данных SQLite. Для этого разместите файл game.db в общей папке или на сервере. При каждом нажатии кнопки вызывайте функцию обновления.

    import sqlite3
    
    def update_db(user_id, coins):
        conn = sqlite3.connect('game.db')
        c = conn.cursor()
        c.execute('UPDATE users SET coins=? WHERE id=?', (coins, user_id))
        conn.commit()
        conn.close()

    Важно: если бот и Flet запущены на разных серверах, используйте общую базу данных (например, через SQLite на общем сетевом диске) или переходите на MySQL/PostgreSQL для одновременного доступа.

    Какие базы данных лучше использовать: SQLite vs MySQL

    SQLite отлично подходит для небольших проектов и тестирования. Однако при одновременных запросах от бота и Flet возможны конфликты блокировок. Рекомендуем использовать MySQL или PostgreSQL для продакшена - они поддерживают параллельные подключения и транзакции. Пример с MySQL:

    import mysql.connector
    conn = mysql.connector.connect(host='localhost', user='root', password='pass', database='game')

    Код запросов останется практически тем же, изменится только подключение.

    Альтернативный подход: централизованный API-сервер

    Вместо прямого доступа к БД из Flet, создайте простой HTTP-сервер (на FastAPI или Flask), который будет обрабатывать запросы на получение и обновление монет. Бот и Flet будут общаться через этот API. Это повышает безопасность и упрощает масштабирование.

    Заключение

    Передача данных между Telegram ботом и Flet-приложением возможна через URL-параметры. Для синхронизации используйте общую базу данных (SQLite для малых проектов, MySQL/PostgreSQL для серьёзных). Обновляйте баланс монет напрямую из Flet, подключаясь к той же БД. Не забывайте экранировать параметры и проверять ID пользователя для безопасности.

    Часто задаваемые вопросы