savagedb_bot/main.py
Vlad dcec5ef020 Добавлены основные файлы для бота Salvagedb:
- Создан файл .gitignore для исключения временных и сгенерированных файлов.
- Добавлен файл .python-version для указания версии Python.
- Реализован класс OracleDatabase для работы с базой данных Oracle.
- Создан основной файл main.py с логикой бота на aiogram.
- Добавлен middleware для работы с сессией базы данных.
- Создан файл pyproject.toml для управления зависимостями.
- Добавлен README.md с инструкциями по запуску.
- Создан скрипт run.cmd для запуска бота с необходимыми переменными окружения.
- Добавлен файл uv.lock для управления зависимостями через uv.
2025-05-25 01:13:33 +03:00

103 lines
3.5 KiB
Python

import asyncio
from os import getenv
import logging
# import json
from aiogram import Bot, Dispatcher
from aiogram.filters import Command
from aiogram.types import Message, InlineKeyboardButton, InlineKeyboardMarkup, CallbackQuery
from aiogram.utils.keyboard import InlineKeyboardBuilder
from aiogram.fsm.state import State, StatesGroup
from aiogram.fsm.context import FSMContext
from db import OracleDatabase
from middlewares.db import DbSessionMiddleware
if getenv("DEBUG",'0') == '1':
logging.basicConfig(level=logging.INFO)
else:
logging.basicConfig(level=logging.WARNING)
TOKEN = getenv("BOT_TOKEN")
BOTNAME = getenv("BOT_NAME")
# SALVAGEDB_TOKEN=getenv("SALVAGEDB_TOKEN",'1234567890')
oracle_db = OracleDatabase(
user= getenv("db_user"),
password= getenv("db_password"),
dsn= getenv("db_dsn")
)
dp = Dispatcher()
class VinStates(StatesGroup):
waiting_for_vin = State()
# Command handler
@dp.message(Command("start"))
async def command_start_handler(message: Message) -> None:
welcome_text = (
"Welcome to SalvagedbBot — your trusted assistant for vehicle history checks via VIN!\n\n"
"🔍 What You Can Discover:\n\n"
"• Salvage or junk status\n"
"• Damage from hail, flood, or fire\n"
"• Mileage discrepancies or odometer rollback\n"
"• Gray market vehicle status\n\n"
"We don't claim that a vehicle has a salvage title, but we provide information indicating possible past damages, helping you make informed decisions."
)
builder = InlineKeyboardBuilder()
builder.button(text="Decode VIN", callback_data="decode_vin")
builder.button(text="Check VIN", callback_data="check_vin")
builder.button(text="Search car Photo", callback_data="search_car_photo")
builder.adjust(3)
builder.button(text="Help", callback_data="help")
builder.button(text="Prices", callback_data="prices")
builder.button(text="Go Salvagedb.com", url="https://salvagedb.com")
builder.adjust(3, 2)
await message.answer(welcome_text, reply_markup=builder.as_markup())
@dp.callback_query(lambda c: c.data == "decode_vin")
async def decode_vin_callback(callback: CallbackQuery, state: FSMContext):
await callback.message.answer("Please enter the vehicle VIN.")
await state.set_state(VinStates.waiting_for_vin)
await callback.answer()
@dp.message(VinStates.waiting_for_vin)
async def process_vin(message: Message, state: FSMContext, db: OracleDatabase):
vin = message.text.strip().upper()
if len(vin) == 17 and vin.isalnum() and all(c not in vin for c in ["I", "O", "Q"]):
try:
make, model, year = await db.fetch_vin_info(vin)
response_text = f"🚗 **{year} {make} {model}**"
await message.answer(response_text, parse_mode="Markdown")
except Exception as e:
logging.error(f"Database error for VIN {vin}: {e}")
await message.answer("Error retrieving data from database. Please try again later.")
await state.clear()
else:
await message.answer("Invalid VIN. Please enter a valid 17-character VIN (letters and numbers, no I, O, Q).")
async def on_startup():
await oracle_db.connect()
dp.message.middleware(DbSessionMiddleware(oracle_db))
async def on_shutdown():
await oracle_db.close()
# Run the bot
async def main() -> None:
bot = Bot(token=TOKEN)
dp.startup.register(on_startup)
dp.shutdown.register(on_shutdown)
await dp.start_polling(bot)
if __name__ == "__main__":
asyncio.run(main())