Compare commits
1 Commits
master
...
fix-vin-ha
| Author | SHA1 | Date | |
|---|---|---|---|
| c29772d5e4 |
@ -72,7 +72,8 @@ env.example
|
|||||||
*.db
|
*.db
|
||||||
*.sqlite3
|
*.sqlite3
|
||||||
data/
|
data/
|
||||||
|
@.cmd
|
||||||
|
wiki/*
|
||||||
# Бекапы и архивы
|
# Бекапы и архивы
|
||||||
*.bak
|
*.bak
|
||||||
*.backup
|
*.backup
|
||||||
|
|||||||
58
autostart.txt
Normal file
58
autostart.txt
Normal file
@ -0,0 +1,58 @@
|
|||||||
|
Чтобы Telegram-бот автоматически запускал логику при первом входе пользователя, нужно обрабатывать команду /start, которую Telegram автоматически отправляет боту при первом открытии чата или при нажатии на кнопку "Start".
|
||||||
|
|
||||||
|
Однако Telegram не поддерживает "автозапуск бота без действия пользователя" — пользователь обязательно должен нажать "Start". Это сделано из соображений безопасности и предотвращения спама.
|
||||||
|
|
||||||
|
Что можно реализовать:
|
||||||
|
Обработка /start, чтобы при первом входе пользователь получал приветствие или стартовую логику.
|
||||||
|
|
||||||
|
Использование force_reply или inline-кнопок для вовлечения пользователя.
|
||||||
|
|
||||||
|
Пример на Python с использованием python-telegram-bot:
|
||||||
|
python
|
||||||
|
Копировать
|
||||||
|
Редактировать
|
||||||
|
from telegram import Update
|
||||||
|
from telegram.ext import Application, CommandHandler, ContextTypes
|
||||||
|
|
||||||
|
async def start(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||||
|
await update.message.reply_text("Привет! Я твой бот. Чем могу помочь?")
|
||||||
|
|
||||||
|
if __name__ == '__main__':
|
||||||
|
app = Application.builder().token("YOUR_BOT_TOKEN").build()
|
||||||
|
|
||||||
|
app.add_handler(CommandHandler("start", start))
|
||||||
|
|
||||||
|
print("Бот запущен...")
|
||||||
|
app.run_polling()
|
||||||
|
Если нужен "автозапуск" при повторном входе:
|
||||||
|
Telegram не отправляет /start при каждом заходе, но вы можете:
|
||||||
|
|
||||||
|
Проверять, есть ли пользователь в базе, и если нет — значит это первый вход.
|
||||||
|
|
||||||
|
Или предложить пользователю в меню нажать кнопку "Начать".
|
||||||
|
|
||||||
|
Альтернатива: "Deep linking"
|
||||||
|
Вы можете создать ссылку вида:
|
||||||
|
|
||||||
|
arduino
|
||||||
|
Копировать
|
||||||
|
Редактировать
|
||||||
|
https://t.me/your_bot_username?start=welcome
|
||||||
|
При нажатии на неё, Telegram автоматически отправит:
|
||||||
|
|
||||||
|
bash
|
||||||
|
Копировать
|
||||||
|
Редактировать
|
||||||
|
/start welcome
|
||||||
|
И вы можете обрабатывать этот параметр:
|
||||||
|
|
||||||
|
python
|
||||||
|
Копировать
|
||||||
|
Редактировать
|
||||||
|
async def start(update: Update, context: ContextTypes.DEFAULT_TYPE):
|
||||||
|
args = context.args
|
||||||
|
if args and args[0] == "welcome":
|
||||||
|
await update.message.reply_text("Добро пожаловать по ссылке!")
|
||||||
|
else:
|
||||||
|
await update.message.reply_text("Обычный старт.")
|
||||||
|
Если хочешь, я могу помочь с конкретной логикой — например, регистрацией, проверкой в базе данных, меню и т.д.
|
||||||
@ -11,6 +11,80 @@ from .base import OracleDatabase
|
|||||||
class UserManager(OracleDatabase):
|
class UserManager(OracleDatabase):
|
||||||
"""Класс для управления пользователями"""
|
"""Класс для управления пользователями"""
|
||||||
|
|
||||||
|
async def add_user_if_not_exists(self, user_id: int, username: str, first_name: str, last_name: str) -> bool:
|
||||||
|
"""
|
||||||
|
Добавляет пользователя в базу данных, если его еще нет
|
||||||
|
Упрощенная версия save_user для совместимости
|
||||||
|
"""
|
||||||
|
def _add_user():
|
||||||
|
try:
|
||||||
|
with self._get_connection() as conn:
|
||||||
|
with conn.cursor() as cur:
|
||||||
|
# Проверяем, существует ли пользователь
|
||||||
|
cur.execute("SELECT id FROM bot_users WHERE id = :user_id", {"user_id": user_id})
|
||||||
|
existing_user = cur.fetchone()
|
||||||
|
|
||||||
|
if not existing_user:
|
||||||
|
# Создаем нового пользователя
|
||||||
|
insert_query = """
|
||||||
|
INSERT INTO bot_users (
|
||||||
|
id, first_name, last_name, username, language_code,
|
||||||
|
is_bot, is_premium, added_to_attachment_menu,
|
||||||
|
registration_source, first_interaction_date,
|
||||||
|
last_interaction_date, interaction_count
|
||||||
|
) VALUES (
|
||||||
|
:user_id, :first_name, :last_name, :username, :language_code,
|
||||||
|
:is_bot, :is_premium, :added_to_attachment_menu,
|
||||||
|
:registration_source, SYSDATE, SYSDATE, 1
|
||||||
|
)
|
||||||
|
"""
|
||||||
|
|
||||||
|
params = {
|
||||||
|
"user_id": user_id,
|
||||||
|
"first_name": first_name,
|
||||||
|
"last_name": last_name,
|
||||||
|
"username": username,
|
||||||
|
"language_code": "en", # По умолчанию
|
||||||
|
"is_bot": 0,
|
||||||
|
"is_premium": 0,
|
||||||
|
"added_to_attachment_menu": 0,
|
||||||
|
"registration_source": "bot"
|
||||||
|
}
|
||||||
|
cur.execute(insert_query, params)
|
||||||
|
else:
|
||||||
|
# Обновляем данные существующего пользователя
|
||||||
|
update_query = """
|
||||||
|
UPDATE bot_users SET
|
||||||
|
first_name = :first_name,
|
||||||
|
last_name = :last_name,
|
||||||
|
username = :username,
|
||||||
|
last_interaction_date = SYSDATE,
|
||||||
|
interaction_count = interaction_count + 1
|
||||||
|
WHERE id = :user_id
|
||||||
|
"""
|
||||||
|
|
||||||
|
params = {
|
||||||
|
"user_id": user_id,
|
||||||
|
"first_name": first_name,
|
||||||
|
"last_name": last_name,
|
||||||
|
"username": username
|
||||||
|
}
|
||||||
|
cur.execute(update_query, params)
|
||||||
|
|
||||||
|
conn.commit()
|
||||||
|
return True
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"SQL Error in add_user_if_not_exists:")
|
||||||
|
logging.error(f"User ID: {user_id}")
|
||||||
|
logging.error(f"Error: {e}")
|
||||||
|
raise
|
||||||
|
|
||||||
|
try:
|
||||||
|
return await self._execute_query(_add_user)
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"Error adding user {user_id}: {e}")
|
||||||
|
return False
|
||||||
|
|
||||||
async def save_user(self, user: User, interaction_source: str = "bot") -> bool:
|
async def save_user(self, user: User, interaction_source: str = "bot") -> bool:
|
||||||
"""
|
"""
|
||||||
Сохраняет или обновляет данные пользователя в базе данных
|
Сохраняет или обновляет данные пользователя в базе данных
|
||||||
|
|||||||
@ -40,6 +40,161 @@ async def decode_vin_callback(callback: CallbackQuery, state: FSMContext, db: Da
|
|||||||
await callback.answer("Произошла ошибка", show_alert=True)
|
await callback.answer("Произошла ошибка", show_alert=True)
|
||||||
|
|
||||||
|
|
||||||
|
@router.callback_query(lambda c: c.data == "check_vin")
|
||||||
|
async def check_vin_callback(callback: CallbackQuery, state: FSMContext, db: DatabaseManager = None):
|
||||||
|
"""Начало процесса проверки VIN"""
|
||||||
|
try:
|
||||||
|
await state.set_state(VinStates.waiting_for_check_vin)
|
||||||
|
|
||||||
|
builder = InlineKeyboardBuilder()
|
||||||
|
builder.button(text="🏠 Main Menu", callback_data="main_menu")
|
||||||
|
|
||||||
|
await callback.message.edit_text(
|
||||||
|
"🚗 **VIN Check Service**\n\nPlease enter the VIN number to check salvage history:\n\nExample: `1HGBH41JXMN109186`",
|
||||||
|
reply_markup=builder.as_markup(),
|
||||||
|
parse_mode="Markdown"
|
||||||
|
)
|
||||||
|
await callback.answer()
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"Error in check_vin_callback: {e}")
|
||||||
|
await callback.answer("Произошла ошибка", show_alert=True)
|
||||||
|
|
||||||
|
|
||||||
|
@router.callback_query(lambda c: c.data == "search_car_photo")
|
||||||
|
async def search_car_photo_callback(callback: CallbackQuery, state: FSMContext, db: DatabaseManager = None):
|
||||||
|
"""Начало процесса поиска фотографий"""
|
||||||
|
try:
|
||||||
|
await state.set_state(VinStates.waiting_for_photo_vin)
|
||||||
|
|
||||||
|
builder = InlineKeyboardBuilder()
|
||||||
|
builder.button(text="🏠 Main Menu", callback_data="main_menu")
|
||||||
|
|
||||||
|
await callback.message.edit_text(
|
||||||
|
"📸 **Photo Search Service**\n\nPlease enter the VIN number to search for vehicle photos:\n\nExample: `1HGBH41JXMN109186`",
|
||||||
|
reply_markup=builder.as_markup(),
|
||||||
|
parse_mode="Markdown"
|
||||||
|
)
|
||||||
|
await callback.answer()
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"Error in search_car_photo_callback: {e}")
|
||||||
|
await callback.answer("Произошла ошибка", show_alert=True)
|
||||||
|
|
||||||
|
|
||||||
|
@router.callback_query(lambda c: c.data and c.data.startswith("check_vin:"))
|
||||||
|
async def check_vin_direct_callback(callback: CallbackQuery, db: DatabaseManager = None):
|
||||||
|
"""Прямая проверка VIN из кнопки после декодирования"""
|
||||||
|
try:
|
||||||
|
vin = callback.data.split(":", 1)[1]
|
||||||
|
|
||||||
|
if not vin or len(vin) != 17:
|
||||||
|
await callback.answer("Некорректный VIN", show_alert=True)
|
||||||
|
return
|
||||||
|
|
||||||
|
# Получаем информацию о VIN и количество записей
|
||||||
|
vin_info = await db.get_vin_info(vin)
|
||||||
|
salvage_records = await db.get_salvage_records(vin)
|
||||||
|
|
||||||
|
if not vin_info:
|
||||||
|
builder = InlineKeyboardBuilder()
|
||||||
|
builder.button(text="🏠 Main Menu", callback_data="main_menu")
|
||||||
|
|
||||||
|
await callback.message.edit_text(
|
||||||
|
f"❌ **VIN не найден**\n\nVIN `{escape_markdown(vin)}` не найден в базе данных.",
|
||||||
|
reply_markup=builder.as_markup(),
|
||||||
|
parse_mode="Markdown"
|
||||||
|
)
|
||||||
|
await callback.answer()
|
||||||
|
return
|
||||||
|
|
||||||
|
year, make, model, engine, body_style, fuel_type = vin_info
|
||||||
|
salvage_count = len(salvage_records) if salvage_records else 0
|
||||||
|
|
||||||
|
response_text = f"🚗 **{year} {make} {model}**\n\n"
|
||||||
|
response_text += f"📊 **Records found:** {salvage_count}\n\n"
|
||||||
|
|
||||||
|
builder = InlineKeyboardBuilder()
|
||||||
|
|
||||||
|
if salvage_count > 0:
|
||||||
|
response_text += "✅ Salvage records found for this vehicle."
|
||||||
|
builder.button(text="🚗 Get Detailed Report ($2.99)", callback_data=f"pay_check_detailed:{vin}")
|
||||||
|
else:
|
||||||
|
response_text += "✅ No salvage records found for this vehicle."
|
||||||
|
|
||||||
|
builder.button(text="📸 Search Photos", callback_data=f"search_photos:{vin}")
|
||||||
|
builder.button(text="🔍 Check Another VIN", callback_data="check_vin")
|
||||||
|
builder.button(text="🏠 Main Menu", callback_data="main_menu")
|
||||||
|
builder.adjust(1)
|
||||||
|
|
||||||
|
await callback.message.edit_text(
|
||||||
|
response_text,
|
||||||
|
reply_markup=builder.as_markup(),
|
||||||
|
parse_mode="Markdown"
|
||||||
|
)
|
||||||
|
await callback.answer()
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"Error in check_vin_direct_callback: {e}")
|
||||||
|
await callback.answer("Произошла ошибка при проверке VIN", show_alert=True)
|
||||||
|
|
||||||
|
|
||||||
|
@router.callback_query(lambda c: c.data and c.data.startswith("search_photos:"))
|
||||||
|
async def search_photos_direct_callback(callback: CallbackQuery, db: DatabaseManager = None):
|
||||||
|
"""Прямой поиск фотографий из кнопки после декодирования"""
|
||||||
|
try:
|
||||||
|
vin = callback.data.split(":", 1)[1]
|
||||||
|
|
||||||
|
if not vin or len(vin) != 17:
|
||||||
|
await callback.answer("Некорректный VIN", show_alert=True)
|
||||||
|
return
|
||||||
|
|
||||||
|
# Получаем информацию о VIN и количество фотографий
|
||||||
|
vin_info = await db.get_vin_info(vin)
|
||||||
|
photo_paths = await db.get_photo_paths(vin)
|
||||||
|
|
||||||
|
if not vin_info:
|
||||||
|
builder = InlineKeyboardBuilder()
|
||||||
|
builder.button(text="🏠 Main Menu", callback_data="main_menu")
|
||||||
|
|
||||||
|
await callback.message.edit_text(
|
||||||
|
f"❌ **VIN не найден**\n\nVIN `{escape_markdown(vin)}` не найден в базе данных.",
|
||||||
|
reply_markup=builder.as_markup(),
|
||||||
|
parse_mode="Markdown"
|
||||||
|
)
|
||||||
|
await callback.answer()
|
||||||
|
return
|
||||||
|
|
||||||
|
year, make, model, engine, body_style, fuel_type = vin_info
|
||||||
|
photo_count = len(photo_paths) if photo_paths else 0
|
||||||
|
|
||||||
|
response_text = f"🚗 **{year} {make} {model}**\n\n"
|
||||||
|
|
||||||
|
builder = InlineKeyboardBuilder()
|
||||||
|
|
||||||
|
if photo_count > 0:
|
||||||
|
response_text += f"📸 **{photo_count} photos** found for this vehicle."
|
||||||
|
builder.button(text="📸 Get Photos ($1.99)", callback_data=f"pay_photos:{vin}")
|
||||||
|
else:
|
||||||
|
response_text += "📸 No photos found for this vehicle."
|
||||||
|
|
||||||
|
builder.button(text="🚗 Check History", callback_data=f"check_vin:{vin}")
|
||||||
|
builder.button(text="📸 Search Another VIN", callback_data="search_car_photo")
|
||||||
|
builder.button(text="🏠 Main Menu", callback_data="main_menu")
|
||||||
|
builder.adjust(1)
|
||||||
|
|
||||||
|
await callback.message.edit_text(
|
||||||
|
response_text,
|
||||||
|
reply_markup=builder.as_markup(),
|
||||||
|
parse_mode="Markdown"
|
||||||
|
)
|
||||||
|
await callback.answer()
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"Error in search_photos_direct_callback: {e}")
|
||||||
|
await callback.answer("Произошла ошибка при поиске фотографий", show_alert=True)
|
||||||
|
|
||||||
|
|
||||||
@router.message(VinStates.waiting_for_vin)
|
@router.message(VinStates.waiting_for_vin)
|
||||||
async def process_vin(message: Message, state: FSMContext, db: DatabaseManager = None):
|
async def process_vin(message: Message, state: FSMContext, db: DatabaseManager = None):
|
||||||
"""Обработка VIN для декодирования"""
|
"""Обработка VIN для декодирования"""
|
||||||
@ -59,21 +214,50 @@ async def process_vin(message: Message, state: FSMContext, db: DatabaseManager =
|
|||||||
|
|
||||||
await state.clear()
|
await state.clear()
|
||||||
|
|
||||||
# Заглушка для декодирования VIN
|
# Получаем реальную информацию о VIN
|
||||||
|
vin_info = await db.get_vin_info(vin)
|
||||||
|
|
||||||
|
if not vin_info:
|
||||||
|
builder = InlineKeyboardBuilder()
|
||||||
|
builder.button(text="🔍 Try Another VIN", callback_data="decode_vin")
|
||||||
|
builder.button(text="🏠 Main Menu", callback_data="main_menu")
|
||||||
|
builder.adjust(1)
|
||||||
|
|
||||||
|
await message.answer(
|
||||||
|
f"❌ **VIN not found**\n\nVIN `{escape_markdown(vin)}` not found in database.",
|
||||||
|
reply_markup=builder.as_markup(),
|
||||||
|
parse_mode="Markdown"
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
year, make, model, engine, body_style, fuel_type = vin_info
|
||||||
|
|
||||||
|
# Создаем клавиатуру с действиями
|
||||||
builder = InlineKeyboardBuilder()
|
builder = InlineKeyboardBuilder()
|
||||||
builder.button(text="🔍 Check History", callback_data=f"check_vin:{vin}")
|
builder.button(text="🔍 Check History", callback_data=f"check_vin:{vin}")
|
||||||
builder.button(text="📸 Search Photos", callback_data=f"search_photos:{vin}")
|
builder.button(text="📸 Search Photos", callback_data=f"search_photos:{vin}")
|
||||||
|
builder.button(text="🔍 Decode Another VIN", callback_data="decode_vin")
|
||||||
builder.button(text="🏠 Main Menu", callback_data="main_menu")
|
builder.button(text="🏠 Main Menu", callback_data="main_menu")
|
||||||
builder.adjust(1)
|
builder.adjust(1)
|
||||||
|
|
||||||
|
# Формируем текст ответа
|
||||||
|
response_text = f"✅ **VIN Decoded Successfully**\n\n"
|
||||||
|
response_text += f"**VIN:** `{vin}`\n"
|
||||||
|
response_text += f"**Year:** {year}\n"
|
||||||
|
response_text += f"**Make:** {make}\n"
|
||||||
|
response_text += f"**Model:** {model}\n"
|
||||||
|
|
||||||
|
if engine and str(engine) != "None":
|
||||||
|
response_text += f"**Engine:** {engine}\n"
|
||||||
|
if body_style and str(body_style) != "None":
|
||||||
|
response_text += f"**Body Style:** {body_style}\n"
|
||||||
|
if fuel_type and str(fuel_type) != "None":
|
||||||
|
response_text += f"**Fuel Type:** {fuel_type}\n"
|
||||||
|
|
||||||
|
response_text += f"\nChoose an action:"
|
||||||
|
|
||||||
await message.answer(
|
await message.answer(
|
||||||
f"✅ **VIN Decoded Successfully**\n\n"
|
response_text,
|
||||||
f"**VIN:** `{vin}`\n"
|
|
||||||
f"**Make:** Toyota\n"
|
|
||||||
f"**Model:** Camry\n"
|
|
||||||
f"**Year:** 2015\n"
|
|
||||||
f"**Engine:** 2.5L\n\n"
|
|
||||||
f"Choose an action:",
|
|
||||||
reply_markup=builder.as_markup(),
|
reply_markup=builder.as_markup(),
|
||||||
parse_mode="Markdown"
|
parse_mode="Markdown"
|
||||||
)
|
)
|
||||||
@ -83,6 +267,148 @@ async def process_vin(message: Message, state: FSMContext, db: DatabaseManager =
|
|||||||
await message.answer("Произошла ошибка при обработке VIN")
|
await message.answer("Произошла ошибка при обработке VIN")
|
||||||
|
|
||||||
|
|
||||||
|
@router.message(VinStates.waiting_for_check_vin)
|
||||||
|
async def process_check_vin(message: Message, state: FSMContext, db: DatabaseManager = None):
|
||||||
|
"""Обработка VIN для проверки истории аварий"""
|
||||||
|
try:
|
||||||
|
vin = message.text.strip().upper()
|
||||||
|
|
||||||
|
if len(vin) != 17 or not vin.isalnum() or any(c in vin for c in ["I", "O", "Q"]):
|
||||||
|
builder = InlineKeyboardBuilder()
|
||||||
|
builder.button(text="🏠 Main Menu", callback_data="main_menu")
|
||||||
|
|
||||||
|
await message.answer(
|
||||||
|
"❌ **Invalid VIN**\n\nVIN number must be exactly 17 characters (letters and numbers, no I, O, Q).\nPlease try again:",
|
||||||
|
reply_markup=builder.as_markup(),
|
||||||
|
parse_mode="Markdown"
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
await state.clear()
|
||||||
|
|
||||||
|
# Получаем информацию о VIN и количество записей
|
||||||
|
vin_info = await db.get_vin_info(vin)
|
||||||
|
salvage_records = await db.get_salvage_records(vin)
|
||||||
|
|
||||||
|
if not vin_info:
|
||||||
|
builder = InlineKeyboardBuilder()
|
||||||
|
builder.button(text="🔍 Try Another VIN", callback_data="check_vin")
|
||||||
|
builder.button(text="🏠 Main Menu", callback_data="main_menu")
|
||||||
|
builder.adjust(1)
|
||||||
|
|
||||||
|
await message.answer(
|
||||||
|
f"❌ **VIN not found**\n\nVIN `{escape_markdown(vin)}` not found in database.",
|
||||||
|
reply_markup=builder.as_markup(),
|
||||||
|
parse_mode="Markdown"
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
year, make, model, engine, body_style, fuel_type = vin_info
|
||||||
|
salvage_count = len(salvage_records) if salvage_records else 0
|
||||||
|
|
||||||
|
# Формируем текст ответа
|
||||||
|
response_text = f"🚗 **{year} {make} {model}**\n\n"
|
||||||
|
response_text += f"📊 **Records found in database:** {salvage_count}\n\n"
|
||||||
|
|
||||||
|
# Создаем клавиатуру в зависимости от наличия записей
|
||||||
|
builder = InlineKeyboardBuilder()
|
||||||
|
|
||||||
|
if salvage_count > 0:
|
||||||
|
response_text += "✅ Salvage records found for this vehicle."
|
||||||
|
builder.button(text="🚗 Get Detailed Report ($2.99)", callback_data=f"pay_check_detailed:{vin}")
|
||||||
|
builder.button(text="🔍 Try Another VIN", callback_data="check_vin")
|
||||||
|
builder.button(text="🏠 Main Menu", callback_data="main_menu")
|
||||||
|
builder.adjust(1)
|
||||||
|
else:
|
||||||
|
response_text += "ℹ️ **No salvage records found for this VIN**"
|
||||||
|
builder.button(text="🔍 Try Another VIN", callback_data="check_vin")
|
||||||
|
builder.button(text="🏠 Main Menu", callback_data="main_menu")
|
||||||
|
builder.adjust(1)
|
||||||
|
|
||||||
|
await message.answer(
|
||||||
|
response_text,
|
||||||
|
reply_markup=builder.as_markup(),
|
||||||
|
parse_mode="Markdown"
|
||||||
|
)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"Error in process_check_vin: {e}")
|
||||||
|
await message.answer("❌ Error retrieving data from database. Please try again later.")
|
||||||
|
|
||||||
|
|
||||||
|
@router.message(VinStates.waiting_for_photo_vin)
|
||||||
|
async def process_photo_vin(message: Message, state: FSMContext, db: DatabaseManager = None):
|
||||||
|
"""Обработка VIN для поиска фотографий"""
|
||||||
|
try:
|
||||||
|
vin = message.text.strip().upper()
|
||||||
|
|
||||||
|
if len(vin) != 17 or not vin.isalnum() or any(c in vin for c in ["I", "O", "Q"]):
|
||||||
|
builder = InlineKeyboardBuilder()
|
||||||
|
builder.button(text="🏠 Main Menu", callback_data="main_menu")
|
||||||
|
|
||||||
|
await message.answer(
|
||||||
|
"❌ **Invalid VIN**\n\nVIN number must be exactly 17 characters (letters and numbers, no I, O, Q).\nPlease try again:",
|
||||||
|
reply_markup=builder.as_markup(),
|
||||||
|
parse_mode="Markdown"
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
await state.clear()
|
||||||
|
|
||||||
|
# Получаем информацию о VIN и количество фотографий
|
||||||
|
vin_info = await db.get_vin_info(vin)
|
||||||
|
photo_paths = await db.get_photo_paths(vin)
|
||||||
|
|
||||||
|
if not vin_info:
|
||||||
|
builder = InlineKeyboardBuilder()
|
||||||
|
builder.button(text="📸 Try Another VIN", callback_data="search_car_photo")
|
||||||
|
builder.button(text="🏠 Main Menu", callback_data="main_menu")
|
||||||
|
builder.adjust(1)
|
||||||
|
|
||||||
|
await message.answer(
|
||||||
|
f"❌ **VIN not found**\n\nVIN `{escape_markdown(vin)}` not found in database.",
|
||||||
|
reply_markup=builder.as_markup(),
|
||||||
|
parse_mode="Markdown"
|
||||||
|
)
|
||||||
|
return
|
||||||
|
|
||||||
|
year, make, model, engine, body_style, fuel_type = vin_info
|
||||||
|
photo_count = len(photo_paths) if photo_paths else 0
|
||||||
|
|
||||||
|
# Формируем ответ в зависимости от наличия фотографий
|
||||||
|
builder = InlineKeyboardBuilder()
|
||||||
|
|
||||||
|
if photo_count > 0:
|
||||||
|
# Есть фотографии - показываем информацию и кнопку оплаты
|
||||||
|
response_text = f"🚗 **{year} {make} {model}**\n\n"
|
||||||
|
response_text += f"📸 **Photo Information**\n\n"
|
||||||
|
response_text += f"🖼️ **{photo_count} damage photos** found in our database for this vehicle.\n"
|
||||||
|
response_text += f"These photos show the actual condition and damage of the vehicle during auction."
|
||||||
|
|
||||||
|
builder.button(text="📸 Get Photos ($1.99)", callback_data=f"pay_photos:{vin}")
|
||||||
|
builder.button(text="📸 Try Another VIN", callback_data="search_car_photo")
|
||||||
|
builder.button(text="🏠 Main Menu", callback_data="main_menu")
|
||||||
|
builder.adjust(1)
|
||||||
|
else:
|
||||||
|
# Нет фотографий
|
||||||
|
response_text = f"🚗 **{year} {make} {model}**\n\n"
|
||||||
|
response_text += f"📸 **No damage photos found** for this VIN in our database."
|
||||||
|
|
||||||
|
builder.button(text="📸 Try Another VIN", callback_data="search_car_photo")
|
||||||
|
builder.button(text="🏠 Main Menu", callback_data="main_menu")
|
||||||
|
builder.adjust(1)
|
||||||
|
|
||||||
|
await message.answer(
|
||||||
|
response_text,
|
||||||
|
reply_markup=builder.as_markup(),
|
||||||
|
parse_mode="Markdown"
|
||||||
|
)
|
||||||
|
|
||||||
|
except Exception as e:
|
||||||
|
logging.error(f"Error in process_photo_vin: {e}")
|
||||||
|
await message.answer("❌ Error retrieving data from database. Please try again later.")
|
||||||
|
|
||||||
|
|
||||||
async def send_vehicle_photos(message: Message, vin: str, photo_paths: List[str], make: str, model: str, year: str):
|
async def send_vehicle_photos(message: Message, vin: str, photo_paths: List[str], make: str, model: str, year: str):
|
||||||
"""Отправка фотографий автомобиля пользователю"""
|
"""Отправка фотографий автомобиля пользователю"""
|
||||||
try:
|
try:
|
||||||
|
|||||||
Loading…
x
Reference in New Issue
Block a user