Обновлены обработчики в main.py для улучшения логики обработки запросов на получение информации о повреждениях. Добавлены новые функции для работы с данными о повреждениях, включая оптимизацию SQL-запросов и улучшение форматирования выводимой информации. Эти изменения повышают точность и удобство использования бота.
This commit is contained in:
parent
5f3d478adb
commit
fe0aaefbec
540
read_dev.md
Normal file
540
read_dev.md
Normal file
@ -0,0 +1,540 @@
|
||||
# SalvageDB Telegram Bot - Developer Documentation
|
||||
|
||||
## Оглавление
|
||||
1. [Архитектура бота](#архитектура-бота)
|
||||
2. [Переменные окружения](#переменные-окружения)
|
||||
3. [Состояния FSM](#состояния-fsm)
|
||||
4. [Основные функции](#основные-функции)
|
||||
5. [Callback Handlers](#callback-handlers)
|
||||
6. [Message Handlers](#message-handlers)
|
||||
7. [Функции базы данных](#функции-базы-данных)
|
||||
8. [Система платежей](#система-платежей)
|
||||
9. [Работа с фотографиями](#работа-с-фотографиями)
|
||||
10. [Системные функции](#системные-функции)
|
||||
11. [Middleware](#middleware)
|
||||
12. [Структура проекта](#структура-проекта)
|
||||
13. [API Endpoints](#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
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Переменные окружения
|
||||
|
||||
### Обязательные переменные:
|
||||
```env
|
||||
BOT_TOKEN=ваш_токен_бота
|
||||
BOT_NAME=имя_бота
|
||||
db_user=пользователь_oracle
|
||||
db_password=пароль_oracle
|
||||
db_dsn=строка_подключения_oracle
|
||||
ADMIN_USER_ID=id_администратора
|
||||
```
|
||||
|
||||
### Опциональные переменные:
|
||||
```env
|
||||
DEBUG=1 # Включает детальное логирование
|
||||
DECODE_PRICE=1 # Цена за детальную информацию VIN (звезды)
|
||||
CHECK_PRICE=10 # Цена за проверку salvage записей (звезды)
|
||||
IMG_PRICE=100 # Цена за фотографии (звезды)
|
||||
```
|
||||
|
||||
### Автоматические пути к изображениям:
|
||||
```python
|
||||
if is_windows():
|
||||
image_path = "D:\\SALVAGEDB\\salvagedb_bot\\images"
|
||||
else:
|
||||
image_path = "/images/"
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Состояния FSM
|
||||
|
||||
Бот использует Finite State Machine для управления диалогами:
|
||||
|
||||
```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` (кнопка "Search car Photo")
|
||||
- **Any State** → **Start** (кнопка "Back to Main Menu")
|
||||
|
||||
---
|
||||
|
||||
## Основные функции
|
||||
|
||||
### Системные функции
|
||||
|
||||
#### `get_operating_system() -> str`
|
||||
Определяет операционную систему.
|
||||
```python
|
||||
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`
|
||||
Конвертирует двухбуквенный код штата США в полное название.
|
||||
```python
|
||||
get_us_state_name("TX") # Returns: "Texas"
|
||||
```
|
||||
|
||||
#### `format_sale_date(date_str: str) -> str`
|
||||
Форматирует дату из MM/YYYY в читаемый формат.
|
||||
```python
|
||||
format_sale_date("3/2023") # Returns: "March 2023"
|
||||
```
|
||||
|
||||
#### `parse_location(location_str: str) -> str`
|
||||
Парсит локацию из формата ST/TOWN в "City, State".
|
||||
```python
|
||||
parse_location("TX/DALLAS") # Returns: "Dallas, Texas"
|
||||
```
|
||||
|
||||
#### `escape_markdown(text: str) -> str`
|
||||
Экранирует специальные символы Markdown для безопасной отправки.
|
||||
|
||||
### Функции работы с фотографиями
|
||||
|
||||
#### `convert_photo_path(db_path: str) -> str`
|
||||
Конвертирует путь из БД в полный путь с учетом OS.
|
||||
```python
|
||||
# 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`
|
||||
**Логика:**
|
||||
1. Валидация VIN (17 символов, без I/O/Q)
|
||||
2. Запрос `fetch_vin_info(vin)`
|
||||
3. Проверка успешности декодирования (не все UNKNOWN)
|
||||
4. Показ кнопки детальной информации при `cnt > 9`
|
||||
|
||||
#### `@dp.message(VinStates.waiting_for_check_vin)`
|
||||
**Функция:** `process_check_vin`
|
||||
**Логика:**
|
||||
1. Валидация VIN
|
||||
2. Запрос `fetch_vin_info(vin)` и `count_salvage_records(vin)`
|
||||
3. Показ информации о количестве найденных записей
|
||||
4. Кнопка оплаты при наличии записей
|
||||
|
||||
#### `@dp.message(VinStates.waiting_for_photo_vin)`
|
||||
**Функция:** `process_photo_vin`
|
||||
**Логика:**
|
||||
1. Валидация VIN
|
||||
2. Запрос `fetch_vin_info(vin)` и `count_photo_records(vin)`
|
||||
3. Показ информации о количестве фотографий
|
||||
4. Кнопка оплаты при наличии фотографий
|
||||
|
||||
### `@dp.message(lambda message: message.successful_payment)`
|
||||
**Функция:** `successful_payment_handler`
|
||||
**Логика обработки платежей по payload:**
|
||||
|
||||
#### `detailed_vin_info:{vin}`
|
||||
1. Запрос `fetch_detailed_vin_info(vin)`
|
||||
2. Форматирование детального отчета по категориям
|
||||
3. Возврат денег при отсутствии данных
|
||||
4. Автоматический возврат админу
|
||||
|
||||
#### `detailed_salvage_check:{vin}`
|
||||
1. Запрос `fetch_salvage_detailed_info(vin)`
|
||||
2. Форматирование salvage отчета с повреждениями
|
||||
3. Отдельное сообщение о фотографиях
|
||||
4. Возврат денег при отсутствии данных
|
||||
5. Автоматический возврат админу
|
||||
|
||||
#### `vehicle_photos:{vin}`
|
||||
1. Запрос `fetch_photo_paths(vin)`
|
||||
2. Конвертация путей под текущую OS
|
||||
3. Отправка фотографий группами по 10
|
||||
4. Возврат денег при отсутствии фотографий
|
||||
5. Автоматический возврат админу
|
||||
|
||||
---
|
||||
|
||||
## Функции базы данных
|
||||
|
||||
### Класс `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 запрос:**
|
||||
```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 запрос:**
|
||||
```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 для приема платежей.
|
||||
|
||||
### Типы платежей:
|
||||
1. **Детальная информация VIN** - `DECODE_PRICE` звезд
|
||||
2. **Salvage проверка** - `CHECK_PRICE` звезд
|
||||
3. **Фотографии автомобиля** - `IMG_PRICE` звезд
|
||||
|
||||
### Процесс оплаты:
|
||||
1. Пользователь нажимает кнопку оплаты
|
||||
2. Создается invoice с уникальным payload
|
||||
3. Pre-checkout подтверждение
|
||||
4. Successful payment обработка
|
||||
5. Предоставление услуги или возврат средств
|
||||
|
||||
### Автоматический возврат админу:
|
||||
Если `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
|
||||
```
|
||||
|
||||
### Процесс отправки:
|
||||
1. Получение путей из БД
|
||||
2. Конвертация под текущую OS
|
||||
3. Разбивка на группы по 10 фотографий
|
||||
4. Отправка media groups с описаниями
|
||||
5. Итоговое сообщение
|
||||
|
||||
### Ограничения:
|
||||
- Максимум 10 фотографий в одной группе (Telegram API)
|
||||
- Пауза 0.5 сек между группами
|
||||
- Проверка существования файлов
|
||||
|
||||
---
|
||||
|
||||
## Системные функции
|
||||
|
||||
### Логирование:
|
||||
```python
|
||||
# Основное логирование
|
||||
logging.basicConfig(level=logging.WARNING)
|
||||
|
||||
# Debug режим
|
||||
if getenv("DEBUG",'0') == '1':
|
||||
logging.basicConfig(level=logging.INFO)
|
||||
```
|
||||
|
||||
### Middleware:
|
||||
```python
|
||||
# Передача подключения к БД во все handlers
|
||||
dp.message.middleware(DbSessionMiddleware(oracle_db))
|
||||
dp.callback_query.middleware(DbSessionMiddleware(oracle_db))
|
||||
dp.pre_checkout_query.middleware(DbSessionMiddleware(oracle_db))
|
||||
```
|
||||
|
||||
### Startup/Shutdown:
|
||||
```python
|
||||
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.
|
||||
|
||||
**Использование:**
|
||||
```python
|
||||
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:
|
||||
```python
|
||||
await dp.start_polling(bot)
|
||||
```
|
||||
|
||||
---
|
||||
|
||||
## Примеры использования
|
||||
|
||||
### Запуск бота:
|
||||
```bash
|
||||
# Установка переменных окружения
|
||||
export BOT_TOKEN="your_token"
|
||||
export db_user="oracle_user"
|
||||
# ... другие переменные
|
||||
|
||||
# Запуск
|
||||
python main.py
|
||||
```
|
||||
|
||||
### Тестирование платежей:
|
||||
1. Установить `ADMIN_USER_ID` на свой Telegram ID
|
||||
2. Выполнить любую оплату
|
||||
3. Получить услугу + автоматический возврат звезд
|
||||
|
||||
### Debug режим:
|
||||
```bash
|
||||
export DEBUG=1
|
||||
python main.py
|
||||
```
|
||||
Включает детальное логирование всех операций.
|
||||
|
||||
---
|
||||
|
||||
## Troubleshooting
|
||||
|
||||
### Проблемы с фотографиями:
|
||||
1. Проверить права доступа к директории images
|
||||
2. Убедиться в правильности путей для текущей OS
|
||||
3. Проверить логи на ошибки файловой системы
|
||||
|
||||
### Проблемы с БД:
|
||||
1. Проверить строку подключения DSN
|
||||
2. Убедиться в доступности Oracle DB
|
||||
3. Проверить права пользователя БД
|
||||
|
||||
### Проблемы с платежами:
|
||||
1. Убедиться в корректности BOT_TOKEN
|
||||
2. Проверить что бот добавлен в Telegram Stars
|
||||
3. Проверить логи на ошибки Telegram API
|
||||
|
||||
---
|
||||
|
||||
## Обновления и изменения
|
||||
|
||||
При внесении изменений в код обязательно обновляйте эту документацию.
|
||||
|
||||
### История изменений:
|
||||
- **v1.0** - Базовая функциональность (decode VIN, check VIN)
|
||||
- **v1.1** - Добавлена поддержка фотографий
|
||||
- **v1.2** - Улучшена отправка множественных фотографий
|
||||
- **v1.3** - Добавлены функции определения OS и автоматические пути
|
||||
|
||||
---
|
||||
|
||||
*Документация актуальна на момент последнего обновления кода.*
|
||||
Loading…
x
Reference in New Issue
Block a user