Files
drivers_bot/bot/main.py
2026-05-12 19:14:21 +09:00

118 lines
4.3 KiB
Python
Raw Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

import asyncio
import logging
from aiogram import Bot, Dispatcher, F
from aiogram.filters import Command, CommandObject
from aiogram.types import (
CallbackQuery,
InlineKeyboardButton,
InlineKeyboardMarkup,
KeyboardButton,
Message,
ReplyKeyboardMarkup,
WebAppInfo,
)
from app.core.config import settings
from bot.api_client import ApiClient
logging.basicConfig(level=logging.INFO)
dp = Dispatcher()
api = ApiClient()
def main_keyboard() -> ReplyKeyboardMarkup:
return ReplyKeyboardMarkup(
keyboard=[
[KeyboardButton(text="Открыть гараж", web_app=WebAppInfo(url=settings.effective_webapp_url))],
[KeyboardButton(text="Мои авто"), KeyboardButton(text="Помощь")],
],
resize_keyboard=True,
)
@dp.message(Command("start"))
async def start(message: Message) -> None:
user = await api.upsert_user(message.from_user)
text = (
f"Готово, {user.get('first_name') or 'водитель'}.\n\n"
"Здесь можно вести заправки, обслуживание, ремонты и смотреть стоимость владения. "
"Основная работа идет в mini app, а бот остается быстрым входом."
)
await message.answer(text, reply_markup=main_keyboard())
@dp.message(Command("add_car"))
async def add_car(message: Message, command: CommandObject) -> None:
user = await api.upsert_user(message.from_user)
name = command.args.strip() if command.args else ""
if not name:
await message.answer("Напиши так: /add_car Toyota Camry")
return
car = await api.create_car(user["id"], name, message.from_user.id)
await message.answer(f"Добавил авто: {car['name']}")
@dp.message(Command("cars"))
@dp.message(F.text == "Мои авто")
async def cars(message: Message) -> None:
user = await api.upsert_user(message.from_user)
items = await api.list_cars(user["id"], message.from_user.id)
if not items:
await message.answer("Автомобилей пока нет. Добавь через mini app или командой /add_car Название.")
return
buttons = [
[InlineKeyboardButton(text=car["name"], callback_data=f"stats:{car['id']}")] for car in items
]
await message.answer("Твой гараж:", reply_markup=InlineKeyboardMarkup(inline_keyboard=buttons))
@dp.callback_query(F.data.startswith("stats:"))
async def show_stats(callback: CallbackQuery) -> None:
car_id = int(callback.data.split(":", 1)[1])
stats = await api.stats(car_id, callback.from_user.id)
consumption = stats["avg_consumption_l_per_100km"]
cost_per_km = stats["cost_per_km"]
await callback.message.answer(
"\n".join(
[
"Статистика авто:",
f"Расходы всего: {stats['total_cost']}",
f"Топливо: {stats['fuel_cost']}",
f"Сервис и ремонты: {stats['service_cost']}",
f"Пробег по записям: {stats['distance_km']} км",
f"Средний расход: {consumption:.2f} л/100 км" if consumption else "Средний расход: нет данных",
f"Стоимость 1 км: {cost_per_km:.2f}" if cost_per_km else "Стоимость 1 км: нет данных",
]
)
)
await callback.answer()
@dp.message(F.text == "Помощь")
@dp.message(Command("help"))
async def help_message(message: Message) -> None:
await message.answer(
"Команды:\n"
"/add_car Название - быстро добавить авто\n"
"/cars - список авто и статистика\n\n"
"Заправки, ремонты и обслуживание удобнее вести через кнопку «Открыть гараж».",
reply_markup=main_keyboard(),
)
async def main() -> None:
if not settings.bot_token:
raise RuntimeError("BOT_TOKEN is empty")
if not settings.internal_api_token:
raise RuntimeError("INTERNAL_API_TOKEN is empty")
settings.validate_webapp_url_for_telegram()
bot = Bot(settings.bot_token)
await dp.start_polling(bot)
if __name__ == "__main__":
asyncio.run(main())