domovoy_bot/handlers/users.py

167 lines
8.7 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.

"""
Пользовательские команды LKM37 REBORN
Доступны всем жильцам.
"""
import logging
from aiogram import Router, F
from aiogram.types import Message, CallbackQuery
from aiogram.filters import Command, CommandStart
from sqlalchemy import select
from database.db import AsyncSessionLocal
from database.models import User, InitiativeGroup
from keyboards.inline import get_main_menu, get_phones_menu
import config
logger = logging.getLogger(__name__)
router = Router()
@router.message(CommandStart())
async def cmd_start(message: Message):
"""Команда /start"""
from utils.ui_styles import fmt_msg, get_level_badge, get_user_level_key
if message.chat.type != 'private': return
user_id = message.from_user.id
async with AsyncSessionLocal() as session:
stmt = select(User).where(User.user_id == user_id)
result = await session.execute(stmt)
user = result.scalar_one_or_none()
if not user:
user = User(user_id=user_id, username=message.from_user.username, first_name=message.from_user.first_name, last_name=message.from_user.last_name)
session.add(user)
await session.commit()
welcome_text = (f"{fmt_msg('Инициализация протокола связи...', 'system')}\n"
f"{fmt_msg('Обнаружен новый субъект.', 'system')}\n\n"
"Добро пожаловать в цифровую экосистему <b>ЛКМ37</b>.\n"
"Я твой проводник и помощник по дому.\n\n"
"🛡️ <b>Для доступа ко всем функциям нажми кнопку верификации в меню.</b>")
is_ig = False
else:
ig_stmt = select(InitiativeGroup).where(InitiativeGroup.user_id == user_id, InitiativeGroup.is_active == True)
is_ig = (await session.execute(ig_stmt)).scalar_one_or_none() is not None
level_key = get_user_level_key(user_id, user.is_admin, user.verified, is_ig)
welcome_text = (f"{fmt_msg('Доступ разрешен.', 'system')}\n"
f"{fmt_msg(f'Статус: {get_level_badge(level_key)}', 'system')}\n\n"
f"Рад видеть тебя снова, {message.from_user.first_name}!\n"
"Чем могу помочь сегодня?")
await message.answer(welcome_text, reply_markup=get_main_menu(verified=user.verified, is_ig=is_ig, is_admin=(user.is_admin or user_id == config.ADMIN_USER_ID), is_superadmin=(user_id == config.ADMIN_USER_ID)), parse_mode='HTML')
@router.message(Command('phones'))
@router.callback_query(F.data == 'phones')
async def cb_phones(event):
msg = event if isinstance(event, Message) else event.message
if isinstance(event, CallbackQuery): await event.answer()
await msg.answer('📞 <b>ЭКСТРЕННЫЕ ТЕЛЕФОНЫ</b>\n\nВыберите категорию ниже:', reply_markup=get_phones_menu())
@router.callback_query(F.data.startswith('phones_'))
async def cb_phone_category(callback: CallbackQuery):
"""Выдача телефонов по категориям"""
from database.models import Service
from aiogram.types import FSInputFile
import os
category_map = {
'phones_emergency': 'emergency',
'phones_utility': 'utility',
'phones_police': 'police',
'phones_masters': 'masters'
}
cat_code = category_map.get(callback.data)
if not cat_code: return await callback.answer()
async with AsyncSessionLocal() as session:
stmt = select(Service).where(Service.category == cat_code).order_by(Service.name)
services = list((await session.execute(stmt)).scalars().all())
if not services:
return await callback.message.answer("👷 Данные для этой категории еще не заполнены.", reply_markup=get_main_menu())
# Формируем текст
text = f"📞 <b>СПИСОК ТЕЛЕФОНОВ: {cat_code.upper()}</b>\n\n"
for s in services:
text += f"🔹 <b>{s.name}</b>\n └ 📱 <code>{s.phone}</code>\n"
if s.description: text += f" └ 📝 <i>{s.description}</i>\n"
text += "\n"
# Ищем картинку (берем от первой службы в категории, если есть)
photo_path = services[0].image_path if services[0].image_path else None
try:
if photo_path and os.path.exists(photo_path):
await callback.message.answer_photo(FSInputFile(photo_path), caption=text, parse_mode='HTML')
else:
await callback.message.answer(text, parse_mode='HTML')
except Exception as e:
logger.error(f"Error sending phones: {e}")
await callback.message.answer(text, parse_mode='HTML')
await callback.answer()
@router.message(Command('rules'))
@router.callback_query(F.data == 'rules')
async def cb_rules(event):
msg = event if isinstance(event, Message) else event.message
if isinstance(event, CallbackQuery): await event.answer()
text = "<b>📜 ПРАВИЛА ЧАТА ЛКМ37</b>\n\n1. Уважение к соседям\n2. Никакого спама и рекламы\n3. Мат запрещен\n4. Обсуждаем только дела дома."
await msg.answer(text, parse_mode='HTML')
@router.message(Command('about'))
@router.callback_query(F.data == 'about_house')
async def cb_about(event):
msg = event if isinstance(event, Message) else event.message
if isinstance(event, CallbackQuery): await event.answer()
text = ("<b>🏢 О НАШЕМ ДОМЕ (ЛКМ37)</b>\n\n"
"📍 Адрес: пр-т Ленинского Комсомола, д. 37\n"
"🏗️ Тип дома: Многоквартирный жилой дом\n"
"🛠️ Управляющая компания: (укажите вашу УК)\n\n"
"<i>Этот бот создан для объединения жильцов и быстрого решения проблем.</i>")
await msg.answer(text, parse_mode='HTML')
@router.callback_query(F.data == 'my_profile')
async def cb_profile(event):
from utils.ui_styles import get_level_badge, get_user_level_key
user_id = event.from_user.id
msg = event if isinstance(event, Message) else event.message
if isinstance(event, CallbackQuery): await event.answer()
async with AsyncSessionLocal() as session:
user = await session.get(User, user_id)
ig_stmt = select(InitiativeGroup).where(InitiativeGroup.user_id == user_id, InitiativeGroup.is_active == True)
is_ig = (await session.execute(ig_stmt)).scalar_one_or_none() is not None
badge = get_level_badge(get_user_level_key(user_id, user.is_admin, user.verified, is_ig))
text = (f"👤 <b>ТВОЙ ПРОФИЛЬ</b>\n\n"
f"ID: <code>{user_id}</code>\n"
f"Статус: {badge}\n"
f"Квартира: {user.apartment or 'Не указана'}\n"
f"Подъезд: {user.staircase or ''} | Этаж: {user.floor or ''}\n"
f"Рейтинг: {user.rating} 🏆")
kb = InlineKeyboardBuilder()
kb.row(InlineKeyboardButton(text="📍 Указать подъезд/этаж", callback_data="edit_location"))
kb.row(InlineKeyboardButton(text="🏠 В меню", callback_data="main_menu"))
await msg.answer(text, reply_markup=kb.as_markup(), parse_mode='HTML')
@router.callback_query(F.data == "edit_location")
async def edit_location_start(callback: CallbackQuery):
await callback.message.answer("Введите ваш подъезд и этаж через пробел\n<i>Например: '3 5' (3 подъезд, 5 этаж)</i>")
await callback.answer()
@router.message(F.text.regexp(r"^\d+\s+\d+$"))
async def process_location(message: Message):
staircase, floor = map(int, message.text.split())
async with AsyncSessionLocal() as session:
await session.execute(update(User).where(User.user_id == message.from_user.id).values(staircase=staircase, floor=floor))
await session.commit()
await message.answer(f"✅ Данные обновлены: Подъезд {staircase}, Этаж {floor}")
@router.message(Command('help'))
@router.callback_query(F.data == 'help')
async def cb_help(event):
msg = event if isinstance(event, Message) else event.message
if isinstance(event, CallbackQuery): await event.answer()
await msg.answer("<b>❓ СПРАВКА</b>\n\n/start — Главное меню\n/phones — Телефоны\n/about — О доме\n/profile — Твой профиль\n/rules — Правила")