"""
Управление телефонами пользователей
"""
import logging
import re
from aiogram import Router, F
from aiogram.types import Message
from aiogram.filters import Command
from sqlalchemy.ext.asyncio import AsyncSession
from sqlalchemy import select
from database.db import AsyncSessionLocal
from database.models import User
from utils.decorators import admin_only
from utils.validators import validate_phone, normalize_phone
logger = logging.getLogger(__name__)
router = Router()
def format_phone_display(phone: str) -> str:
"""Форматирование телефона для отображения"""
if not phone:
return 'не указан'
# Добавляем кликабельную ссылку tel:
cleaned = re.sub(r'[^\d+]', '', phone)
return f'{phone}'
@router.message(Command('add_phone'))
@admin_only
async def cmd_add_phone(message: Message):
"""
Добавить телефон пользователю
Использование: /add_phone <телефон>
"""
args = message.text.split(maxsplit=2)
if len(args) < 3:
await message.answer(
'Использование: /add_phone <user_id> <телефон>\n\n'
'Пример: /add_phone 123456789 +7 (999) 123-45-67',
parse_mode='HTML'
)
return
try:
user_id = int(args[1])
except ValueError:
await message.answer('❌ Неверный ID пользователя')
return
phone = args[2].strip()
if not validate_phone(phone):
await message.answer('❌ Неверный формат телефона\n\nПример: +7 (999) 123-45-67')
return
# Нормализуем телефон
phone = normalize_phone(phone)
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:
await message.answer('❌ Пользователь не найден')
return
# Добавляем телефон
user.phone = phone
await session.commit()
logger.info(f'Добавлен телефон пользователю {user_id}: {phone}')
await message.answer(
f'✅ Телефон добавлен\n\n'
f'Пользователь: {user.full_name}\n'
f'ID: {user_id}\n'
f'Телефон: {phone}\n\n'
f'💡 Теперь можно позвонить кликом!',
parse_mode='HTML'
)
@router.message(Command('edit_phone'))
@admin_only
async def cmd_edit_phone(message: Message):
"""
Изменить телефон пользователю
Использование: /edit_phone <телефон>
"""
args = message.text.split(maxsplit=2)
if len(args) < 3:
await message.answer(
'Использование: /edit_phone <user_id> <телефон>\n\n'
'Пример: /edit_phone 123456789 +7 (999) 999-99-99',
parse_mode='HTML'
)
return
try:
user_id = int(args[1])
except ValueError:
await message.answer('❌ Неверный ID пользователя')
return
phone = args[2].strip()
if not validate_phone(phone):
await message.answer('❌ Неверный формат телефона')
return
phone = normalize_phone(phone)
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:
await message.answer('❌ Пользователь не найден')
return
old_phone = user.phone
user.phone = phone
await session.commit()
logger.info(f'Изменён телефон пользователю {user_id}: {old_phone} → {phone}')
await message.answer(
f'✅ Телефон изменён\n\n'
f'Пользователь: {user.full_name}\n'
f'ID: {user_id}\n'
f'Было: {old_phone or "не указан"}\n'
f'Стало: {phone}',
parse_mode='HTML'
)
@router.message(Command('remove_phone'))
@router.message(Command('del_phone'))
@admin_only
async def cmd_remove_phone(message: Message):
"""
Удалить телефон у пользователя
Использование: /remove_phone
"""
args = message.text.split()
if len(args) < 2:
await message.answer(
'Использование: /remove_phone <user_id>\n\n'
'Пример: /remove_phone 123456789',
parse_mode='HTML'
)
return
try:
user_id = int(args[1])
except ValueError:
await message.answer('❌ Неверный ID пользователя')
return
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:
await message.answer('❌ Пользователь не найден')
return
old_phone = user.phone
user.phone = None
await session.commit()
logger.info(f'Удалён телефон пользователю {user_id}: {old_phone}')
await message.answer(
f'✅ Телефон удалён\n\n'
f'Пользователь: {user.full_name}\n'
f'ID: {user_id}\n'
f'Был: {old_phone or "не указан"}',
parse_mode='HTML'
)
@router.message(Command('myphone'))
async def cmd_myphone(message: Message):
"""
Добавить/изменить свой телефон (для жильцов)
Использование: /myphone +7 (999) 123-45-67
"""
args = message.text.split(maxsplit=1)
if len(args) < 2:
# Показываем текущий телефон
async with AsyncSessionLocal() as session:
stmt = select(User).where(User.user_id == message.from_user.id)
result = await session.execute(stmt)
user = result.scalar_one_or_none()
if user and user.phone:
await message.answer(
f'📱 Ваш телефон\n\n'
f'{user.phone}\n\n'
f'Чтобы изменить: /myphone +7 (999) 123-45-67',
parse_mode='HTML'
)
else:
await message.answer(
'📱 Ваш телефон не указан\n\n'
'Добавьте телефон командой:\n'
'/myphone +7 (999) 123-45-67\n\n'
'Это поможет соседям связаться с вами!',
parse_mode='HTML'
)
return
phone = args[1].strip()
if not validate_phone(phone):
await message.answer('❌ Неверный формат телефона\n\nПример: +7 (999) 123-45-67')
return
phone = normalize_phone(phone)
async with AsyncSessionLocal() as session:
stmt = select(User).where(User.user_id == message.from_user.id)
result = await session.execute(stmt)
user = result.scalar_one_or_none()
if not user:
await message.answer('❌ Вы не зарегистрированы. Нажмите /start')
return
old_phone = user.phone
user.phone = phone
await session.commit()
logger.info(f'Пользователь {message.from_user.id} установил телефон: {phone}')
await message.answer(
f'✅ Телефон сохранён\n\n'
f'{phone}\n\n'
f'Теперь соседи могут связаться с вами!',
parse_mode='HTML'
)
@router.message(Command('phone'))
@admin_only
async def cmd_phone_info(message: Message):
"""
Показать телефон пользователя
Использование: /phone
"""
args = message.text.split()
if len(args) < 2:
await message.answer(
'Использование: /phone <user_id>\n\n'
'Пример: /phone 123456789',
parse_mode='HTML'
)
return
try:
user_id = int(args[1])
except ValueError:
await message.answer('❌ Неверный ID пользователя')
return
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:
await message.answer('❌ Пользователь не найден')
return
phone_text = format_phone_display(user.phone)
await message.answer(
f'📱 Телефон\n\n'
f'Пользователь: {user.full_name}\n'
f'Квартира: {user.apartment or "не указана"}\n'
f'Телефон: {phone_text}\n\n'
f'💡 Нажмите на номер чтобы позвонить!',
parse_mode='HTML'
)