9.5 KiB
9.5 KiB
Подробное руководство для разработчиков 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
Переменные окружения
Обязательные
BOT_TOKEN=токен_от_BotFather
BOT_NAME=имя_бота
db_user=пользователь_oracle
db_password=пароль_oracle
db_dsn=строка_подключения_oracle
ADMIN_USER_ID=id_администратора
Опциональные
DEBUG=1 # Детальное логирование
DECODE_PRICE=1 # Цена декодирования (звезды)
CHECK_PRICE=10 # Цена проверки salvage (звезды)
IMG_PRICE=100 # Цена фотографий (звезды)
FSM Состояния
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")
Основные функции
Системные утилиты
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():
"""Логирует информацию о системе при запуске"""
Обработка данных
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 символы"""
Работа с фотографиями
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
Навигация
@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)
@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
Команды
@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
@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)
Основные методы
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
# Создание платежа
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
Автоматические пути
Система автоматически определяет пути к изображениям:
# Windows
image_path = "D:\\SALVAGEDB\\salvagedb_bot\\images"
# Linux/Docker
image_path = "/images/"
Развертывание для разработки
1. Настройка окружения
# Установка зависимостей
uv install
# Копирование конфигурации
cp env.example .env
# Отредактируйте .env с вашими данными
2. Запуск с автоперезагрузкой
uv run -m watchfiles --filter python 'uv run main.py'
3. Отладка
# Включение DEBUG режима
export DEBUG=1
# Проверка подключения к БД
python -c "from db import Database; import asyncio; asyncio.run(Database().test_connection())"
Middleware
DatabaseMiddleware
# 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 конфигурация