167 lines
8.7 KiB
Python
167 lines
8.7 KiB
Python
"""
|
||
Пользовательские команды 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 — Правила")
|