Подробное руководство для разработчиков SalvageDB Telegram Bot. ## Архитектура бота Бот построен на `aiogram 3.x` с Oracle Database для хранения данных о транспорте. ### Основные компоненты - **main.py** - основная логика бота (1700+ строк) - **db.py** - класс для работы с Oracle DB (470+ строк) - **middlewares/db.py** - middleware для БД подключения ### Схема работы ``` User Input → FSM States → Database Query → Response → Telegram API ``` ## Переменные окружения ### Обязательные ```env BOT_TOKEN=токен_от_BotFather BOT_NAME=имя_бота db_user=пользователь_oracle db_password=пароль_oracle db_dsn=строка_подключения_oracle ADMIN_USER_ID=id_администратора ``` ### Опциональные ```env DEBUG=1 # Детальное логирование DECODE_PRICE=1 # Цена декодирования (звезды) CHECK_PRICE=10 # Цена проверки salvage (звезды) IMG_PRICE=100 # Цена фотографий (звезды) ``` ## FSM Состояния ```python class VinStates(StatesGroup): waiting_for_vin = State() # Ожидание VIN для декодирования waiting_for_check_vin = State() # Ожидание VIN для проверки salvage waiting_for_photo_vin = State() # Ожидание VIN для поиска фото ``` ### Переходы состояний - **Start** → `waiting_for_vin` (кнопка "Decode VIN") - **Start** → `waiting_for_check_vin` (кнопка "Check VIN") - **Start** → `waiting_for_photo_vin` (кнопка "Car photo") - **Any State** → **Start** (кнопка "Back to Main Menu") ## Основные функции ### Системные утилиты ```python def get_operating_system() -> str: """Возвращает: Windows, Linux, macOS или Unknown""" def is_windows() -> bool: def is_linux() -> bool: def is_macos() -> bool: """Быстрые проверки ОС""" def log_system_info(): """Логирует информацию о системе при запуске""" ``` ### Обработка данных ```python def get_us_state_name(state_code: str) -> str: """TX → Texas""" def format_sale_date(date_str: str) -> str: """3/2023 → March 2023""" def parse_location(location_str: str) -> str: """TX/DALLAS → Dallas, Texas""" def escape_markdown(text: str) -> str: """Экранирует Markdown символы""" ``` ### Работа с фотографиями ```python def convert_photo_path(db_path: str) -> str: """ Конвертирует путь БД в полный путь с учетом ОС: Windows: D:\SALVAGEDB\salvagedb_bot\images\20250530\vin\photo.jpg Linux: /images/20250530/vin/photo.jpg """ async def send_vehicle_photos(message, vin, photo_paths, make, model, year): """ Отправляет фото группами по 10 штук - Пауза 0.5 сек между группами - Обработка ошибок для каждого фото - Итоговое сообщение с количеством """ ``` ## Callback Handlers ### Навигация ```python @dp.callback_query(lambda c: c.data == "decode_vin") async def decode_vin_callback(): """Переход в состояние waiting_for_vin""" @dp.callback_query(lambda c: c.data == "check_vin") async def check_vin_callback(): """Переход в состояние waiting_for_check_vin""" @dp.callback_query(lambda c: c.data == "search_car_photo") async def search_car_photo_callback(): """Переход в состояние waiting_for_photo_vin""" @dp.callback_query(lambda c: c.data == "main_menu") async def main_menu_callback(): """Возврат в главное меню, очистка состояния""" ``` ### Платежи (Telegram Stars) ```python @dp.callback_query(lambda c: c.data.startswith("pay_detailed_info:")) async def pay_detailed_info_callback(): """Payload: detailed_vin_info:{vin}, Цена: DECODE_PRICE""" @dp.callback_query(lambda c: c.data.startswith("pay_check_detailed:")) async def pay_check_detailed_callback(): """Payload: detailed_salvage_check:{vin}, Цена: CHECK_PRICE""" @dp.callback_query(lambda c: c.data.startswith("pay_photos:")) async def pay_photos_callback(): """Payload: vehicle_photos:{vin}, Цена: IMG_PRICE""" ``` ## Message Handlers ### Команды ```python @dp.message(Command("start")) async def command_start_handler(): """Главное меню с кнопками: - Decode VIN - Check VIN - Car photo - Help """ @dp.message(Command("admin_stats")) async def admin_stats_handler(): """Статистика для администратора (только ADMIN_USER_ID)""" ``` ### Обработка VIN ```python @dp.message(VinStates.waiting_for_vin) async def process_vin_input(): """ Декодирование VIN: 1. Валидация VIN (17 символов) 2. Поиск в БД по VIN 3. Базовая информация бесплатно 4. Детальная информация за плату """ @dp.message(VinStates.waiting_for_check_vin) async def process_check_vin_input(): """ Проверка salvage: 1. Поиск записей о повреждениях 2. Краткая сводка бесплатно 3. Детальная информация за плату """ @dp.message(VinStates.waiting_for_photo_vin) async def process_photo_vin_input(): """ Поиск фотографий: 1. Поиск фото по VIN в БД 2. Превью количества бесплатно 3. Доступ к фото за плату """ ``` ## База данных (db.py) ### Основные методы ```python class Database: async def get_vehicle_info_by_vin(self, vin: str): """Базовая информация о транспорте""" async def get_detailed_vehicle_info(self, vin: str): """Детальная информация за плату""" async def check_salvage_records(self, vin: str): """Проверка записей о повреждениях""" async def get_vehicle_photos(self, vin: str): """Получение путей к фотографиям""" async def save_user(self, user: User, interaction_source: str): """Сохранение пользователя для аналитики""" async def update_user_payment(self, user_id: int, amount: float): """Обновление платежных данных""" ``` ## Система платежей ### Telegram Stars Integration ```python # Создание платежа invoice = LabeledPrice(label=description, amount=price) await message.answer_invoice( title=f"Pay {price} ⭐️", description=description, payload=payload, provider_token="", # Telegram Stars currency="XTR", prices=[invoice] ) # Обработка успешного платежа @dp.pre_checkout_query() async def pre_checkout_handler(query: PreCheckoutQuery): await query.answer(ok=True) @dp.message(ContentType.SUCCESSFUL_PAYMENT) async def successful_payment_handler(message: Message): # Обработка по payload ``` ## Автоматические пути Система автоматически определяет пути к изображениям: ```python # Windows image_path = "D:\\SALVAGEDB\\salvagedb_bot\\images" # Linux/Docker image_path = "/images/" ``` ## Развертывание для разработки ### 1. Настройка окружения ```bash # Установка зависимостей uv install # Копирование конфигурации cp env.example .env # Отредактируйте .env с вашими данными ``` ### 2. Запуск с автоперезагрузкой ```bash uv run -m watchfiles --filter python 'uv run main.py' ``` ### 3. Отладка ```bash # Включение DEBUG режима export DEBUG=1 # Проверка подключения к БД python -c "from db import Database; import asyncio; asyncio.run(Database().test_connection())" ``` ## Middleware ### DatabaseMiddleware ```python # middlewares/db.py class DatabaseMiddleware: """Передает подключение к БД в handlers""" async def __call__(self, handler, event, data): data["db"] = Database() return await handler(event, data) ``` ## Структура проекта ``` salvagedb_bot/ ├── main.py # Основная логика (1714 строк) ├── db.py # База данных (475 строк) ├── middlewares/ │ └── db.py # Database middleware ├── .gitea/workflows/ # CI/CD конфигурация ├── logs/ # Логи приложения ├── images/ # Фотографии автомобилей └── requirements.txt # Python зависимости ``` ## Связанные страницы - [[Docker-Setup]] - развертывание в Docker - [[User-Tracking]] - система аналитики пользователей - [[Gitea-Actions]] - CI/CD конфигурация