20 KiB
SalvageDB Telegram Bot - Developer Documentation
Оглавление
- Архитектура бота
- Переменные окружения
- Состояния FSM
- Основные функции
- Callback Handlers
- Message Handlers
- Функции базы данных
- Система платежей
- Работа с фотографиями
- Системные функции
- Middleware
- Структура проекта
- API Endpoints
Архитектура бота
Бот построен на фреймворке aiogram 3.x с использованием Oracle Database для хранения данных о транспортных средствах и их истории повреждений.
Основные компоненты:
- main.py - основной файл с логикой бота
- db.py - класс для работы с Oracle Database
- middlewares/db.py - middleware для передачи подключения к БД
Схема работы:
User Input → FSM States → Database Query → Response Formatting → Telegram API
Переменные окружения
Обязательные переменные:
BOT_TOKEN=ваш_токен_бота
BOT_NAME=имя_бота
db_user=пользователь_oracle
db_password=пароль_oracle
db_dsn=строка_подключения_oracle
ADMIN_USER_ID=id_администратора
Опциональные переменные:
DEBUG=1 # Включает детальное логирование
DECODE_PRICE=1 # Цена за детальную информацию VIN (звезды)
CHECK_PRICE=10 # Цена за проверку salvage записей (звезды)
IMG_PRICE=100 # Цена за фотографии (звезды)
Автоматические пути к изображениям:
if is_windows():
image_path = "D:\\SALVAGEDB\\salvagedb_bot\\images"
else:
image_path = "/images/"
Состояния FSM
Бот использует Finite State Machine для управления диалогами:
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(кнопка "Search car Photo") - Any State → Start (кнопка "Back to Main Menu")
Основные функции
Системные функции
get_operating_system() -> str
Определяет операционную систему.
Returns: 'Windows', 'Linux', 'macOS' или 'Unknown'
is_windows() -> bool, is_linux() -> bool, is_macos() -> bool
Быстрые проверки операционной системы.
log_system_info()
Логирует подробную информацию о системе при запуске.
Функции обработки данных
get_us_state_name(state_code: str) -> str
Конвертирует двухбуквенный код штата США в полное название.
get_us_state_name("TX") # Returns: "Texas"
format_sale_date(date_str: str) -> str
Форматирует дату из MM/YYYY в читаемый формат.
format_sale_date("3/2023") # Returns: "March 2023"
parse_location(location_str: str) -> str
Парсит локацию из формата ST/TOWN в "City, State".
parse_location("TX/DALLAS") # Returns: "Dallas, Texas"
escape_markdown(text: str) -> str
Экранирует специальные символы Markdown для безопасной отправки.
Функции работы с фотографиями
convert_photo_path(db_path: str) -> str
Конвертирует путь из БД в полный путь с учетом OS.
# Windows
convert_photo_path("20250530/vin/photo.jpg")
# Returns: "D:\SALVAGEDB\salvagedb_bot\images\20250530\vin\photo.jpg"
# Linux
convert_photo_path("20250530/vin/photo.jpg")
# Returns: "/images/20250530/vin/photo.jpg"
prepare_photo_paths(db_paths: list) -> list
Подготавливает список полных путей к фотографиям.
send_vehicle_photos(message, vin, photo_paths, make, model, year)
Отправляет фотографии пользователю группами по 10 штук.
Особенности:
- Разбивает фотографии на группы по 10 (лимит Telegram)
- Добавляет описания к первым фото каждой группы
- Пауза 0.5 сек между группами
- Обработка ошибок для каждой фотографии
- Итоговое сообщение с количеством отправленных фото
Callback Handlers
@dp.callback_query(lambda c: c.data == "decode_vin")
Функция: decode_vin_callback
Действие: Устанавливает состояние waiting_for_vin, запрашивает VIN для декодирования.
@dp.callback_query(lambda c: c.data == "check_vin")
Функция: check_vin_callback
Действие: Устанавливает состояние waiting_for_check_vin, запрашивает VIN для проверки salvage.
@dp.callback_query(lambda c: c.data == "search_car_photo")
Функция: search_car_photo_callback
Действие: Устанавливает состояние waiting_for_photo_vin, запрашивает VIN для поиска фотографий.
@dp.callback_query(lambda c: c.data == "main_menu")
Функция: main_menu_callback
Действие: Очищает состояние, возвращает в главное меню.
Платежные handlers
@dp.callback_query(lambda c: c.data.startswith("pay_detailed_info:"))
Функция: pay_detailed_info_callback
Payload: detailed_vin_info:{vin}
Цена: DECODE_PRICE звезд
@dp.callback_query(lambda c: c.data.startswith("pay_check_detailed:"))
Функция: pay_check_detailed_callback
Payload: detailed_salvage_check:{vin}
Цена: CHECK_PRICE звезд
@dp.callback_query(lambda c: c.data.startswith("pay_photos:"))
Функция: pay_photos_callback
Payload: vehicle_photos:{vin}
Цена: IMG_PRICE звезд
Message Handlers
@dp.message(Command("start"))
Функция: command_start_handler
Действие: Показывает приветственное сообщение и главное меню.
Кнопки:
- Decode VIN
- Check VIN
- Search car Photo
- Help
- Prices
- Go Salvagedb.com
@dp.message(Command("admin_stats"))
Функция: admin_stats_handler
Доступ: Только для ADMIN_USER_ID
Действие: Показывает статистику пользователей бота.
Обработчики состояний
@dp.message(VinStates.waiting_for_vin)
Функция: process_vin
Логика:
- Валидация VIN (17 символов, без I/O/Q)
- Запрос
fetch_vin_info(vin) - Проверка успешности декодирования (не все UNKNOWN)
- Показ кнопки детальной информации при
cnt > 9
@dp.message(VinStates.waiting_for_check_vin)
Функция: process_check_vin
Логика:
- Валидация VIN
- Запрос
fetch_vin_info(vin)иcount_salvage_records(vin) - Показ информации о количестве найденных записей
- Кнопка оплаты при наличии записей
@dp.message(VinStates.waiting_for_photo_vin)
Функция: process_photo_vin
Логика:
- Валидация VIN
- Запрос
fetch_vin_info(vin)иcount_photo_records(vin) - Показ информации о количестве фотографий
- Кнопка оплаты при наличии фотографий
@dp.message(lambda message: message.successful_payment)
Функция: successful_payment_handler
Логика обработки платежей по payload:
detailed_vin_info:{vin}
- Запрос
fetch_detailed_vin_info(vin) - Форматирование детального отчета по категориям
- Возврат денег при отсутствии данных
- Автоматический возврат админу
detailed_salvage_check:{vin}
- Запрос
fetch_salvage_detailed_info(vin) - Форматирование salvage отчета с повреждениями
- Отдельное сообщение о фотографиях
- Возврат денег при отсутствии данных
- Автоматический возврат админу
vehicle_photos:{vin}
- Запрос
fetch_photo_paths(vin) - Конвертация путей под текущую OS
- Отправка фотографий группами по 10
- Возврат денег при отсутствии фотографий
- Автоматический возврат админу
Функции базы данных
Класс OracleDatabase
__init__(user, password, dsn)
Инициализация подключения к Oracle DB.
async def connect()
Создает пул подключений (min=1, max=4).
async def fetch_vin_info(vin: str) -> Tuple[str, str, str, int]
Возвращает: (make, model, year, nhtsa_records_count)
SQL запрос:
select 'None',
COALESCE((select value from salvagedb.m_JSONS_FROM_NHTSA v3
where v3.svin = s.svin and v3.variableid = '26'),
(select val from salvagedb.vind2
where svin = substr(s.vin, 1, 8) || '*' || substr(s.vin, 10, 2)
and varb = 'Make'),'UNKNOWN') make,
-- аналогично для model и year
(select count(*) from salvagedb.m_JSONS_FROM_NHTSA v3
where v3.svin = s.svin) cnt
from (select substr(:vin,1,10) svin, :vin vin from dual) s
async def count_salvage_records(vin: str) -> int
SQL: SELECT COUNT(*) FROM salvagedb.salvagedb WHERE vin = :vin and svin = substr(:vin,1,10)
async def count_photo_records(vin: str) -> int
SQL: SELECT COUNT(*) FROM salvagedb.salvage_images WHERE vin = :vin AND fn = 1
async def fetch_photo_paths(vin: str) -> list
SQL: SELECT ipath FROM salvagedb.salvage_images WHERE fn = 1 AND vin = :vin
Возвращает: Список путей к фотографиям.
async def fetch_salvage_detailed_info(vin: str) -> list
Возвращает: Детальную информацию о salvage записях. SQL запрос:
SELECT
odo, odos, dem1, dem2,
month||'/'||year as sale_date,
JSON_VALUE(jdata, '$.RepCost') AS j_rep_cost,
JSON_VALUE(jdata, '$.Runs_Drive') AS j_runs_drive,
JSON_VALUE(jdata, '$.Locate') AS j_locate,
(select count(*) from salvagedb.salvage_images si
where si.vin = s.vin and fn = 1) img_count
FROM salvagedb.salvagedb s
LEFT JOIN salvagedb.addinfo i ON s.num = i.numid
WHERE vin = :vin AND svin = substr(:vin, 1, 10)
ORDER BY year DESC, month DESC
async def fetch_detailed_vin_info(vin: str) -> dict
Возвращает: Детальную информацию о VIN по категориям. Категории:
- basic_characteristics
- engine_and_powertrain
- transmission
- active_safety
- passive_safety
- dimensions_and_construction
- brake_system
- lighting
- additional_features
- manufacturing_and_localization
- ncsa_data
- technical_information_and_errors
Пользовательские функции
async def save_user(user: User, interaction_source: str) -> bool
Сохраняет/обновляет данные пользователя при каждом взаимодействии.
async def update_user_payment(user_id: int, payment_amount: float) -> bool
Обновляет статистику платежей пользователя.
async def get_user_stats(user_id: int) -> dict
Возвращает статистику конкретного пользователя.
async def get_users_summary() -> dict
Возвращает общую статистику по всем пользователям.
Система платежей
Telegram Stars
Бот использует Telegram Stars для приема платежей.
Типы платежей:
- Детальная информация VIN -
DECODE_PRICEзвезд - Salvage проверка -
CHECK_PRICEзвезд - Фотографии автомобиля -
IMG_PRICEзвезд
Процесс оплаты:
- Пользователь нажимает кнопку оплаты
- Создается invoice с уникальным payload
- Pre-checkout подтверждение
- Successful payment обработка
- Предоставление услуги или возврат средств
Автоматический возврат админу:
Если message.from_user.id == ADMIN_USER_ID, после предоставления услуги автоматически возвращаются потраченные звезды.
Обработка ошибок:
- Отсутствие данных → автоматический возврат
- Ошибка сервера → автоматический возврат
- Ошибка возврата → уведомление с transaction ID
Работа с фотографиями
Структура хранения:
База данных: 20250530/1c4hjxdg0pw697757/photo.jpg
Windows: D:\SALVAGEDB\salvagedb_bot\images\20250530\1c4hjxdg0pw697757\photo.jpg
Linux: /images/20250530/1c4hjxdg0pw697757/photo.jpg
Процесс отправки:
- Получение путей из БД
- Конвертация под текущую OS
- Разбивка на группы по 10 фотографий
- Отправка media groups с описаниями
- Итоговое сообщение
Ограничения:
- Максимум 10 фотографий в одной группе (Telegram API)
- Пауза 0.5 сек между группами
- Проверка существования файлов
Системные функции
Логирование:
# Основное логирование
logging.basicConfig(level=logging.WARNING)
# Debug режим
if getenv("DEBUG",'0') == '1':
logging.basicConfig(level=logging.INFO)
Middleware:
# Передача подключения к БД во все handlers
dp.message.middleware(DbSessionMiddleware(oracle_db))
dp.callback_query.middleware(DbSessionMiddleware(oracle_db))
dp.pre_checkout_query.middleware(DbSessionMiddleware(oracle_db))
Startup/Shutdown:
async def on_startup():
log_system_info() # Системная информация
await oracle_db.connect() # Подключение к БД
# Регистрация middleware
async def on_shutdown():
await oracle_db.close() # Закрытие пула подключений
Middleware
DbSessionMiddleware
Файл: middlewares/db.py
Назначение: Передает экземпляр подключения к БД во все handlers.
Использование:
async def handler(message: Message, db: OracleDatabase = None):
database = db or oracle_db # Fallback на глобальный
Структура проекта
salvagedb_bot/
├── main.py # Основной файл бота
├── db.py # Класс работы с БД
├── read_dev.md # Документация (этот файл)
├── middlewares/
│ └── db.py # Middleware для БД
└── images/ # Директория с фотографиями (Windows)
└── 20250530/
└── vin_lower/
└── photo.jpg
API Endpoints
Telegram Bot API
Бот использует стандартные методы Telegram Bot API:
Отправка сообщений:
message.answer()- текстовые сообщенияmessage.answer_media_group()- группы фотографий
Платежи:
bot.send_invoice()- создание счетаbot.refund_star_payment()- возврат звезд
Webhook vs Polling:
Текущая конфигурация использует polling:
await dp.start_polling(bot)
Примеры использования
Запуск бота:
# Установка переменных окружения
export BOT_TOKEN="your_token"
export db_user="oracle_user"
# ... другие переменные
# Запуск
python main.py
Тестирование платежей:
- Установить
ADMIN_USER_IDна свой Telegram ID - Выполнить любую оплату
- Получить услугу + автоматический возврат звезд
Debug режим:
export DEBUG=1
python main.py
Включает детальное логирование всех операций.
Troubleshooting
Проблемы с фотографиями:
- Проверить права доступа к директории images
- Убедиться в правильности путей для текущей OS
- Проверить логи на ошибки файловой системы
Проблемы с БД:
- Проверить строку подключения DSN
- Убедиться в доступности Oracle DB
- Проверить права пользователя БД
Проблемы с платежами:
- Убедиться в корректности BOT_TOKEN
- Проверить что бот добавлен в Telegram Stars
- Проверить логи на ошибки Telegram API
Обновления и изменения
При внесении изменений в код обязательно обновляйте эту документацию.
История изменений:
- v1.0 - Базовая функциональность (decode VIN, check VIN)
- v1.1 - Добавлена поддержка фотографий
- v1.2 - Улучшена отправка множественных фотографий
- v1.3 - Добавлены функции определения OS и автоматические пути
Документация актуальна на момент последнего обновления кода.