domovoy_bot/services/events.py
Admin ba4676b0af v1.0 MVP - Инициализация проекта 🏠
 Регистрация и верификация жильцов
 Рейтинг активности (уровни)
 Детект шпионов (Score 0-100)
 Анти-мат система (3 предупреждения → бан)
 Админ-панель с рассылкой
 Учёт квартир (несколько жильцов)
 Телефоны экстренных служб и мастеров
 Еженедельный экспорт JSON
 Прокси (socks5) для обхода РКН

Бекап: backups/versions/v1.0_mvp_2026-02-26/

Co-authored-by: Qwen-Coder <qwen-coder@alibabacloud.com>
2026-02-27 10:54:16 +00:00

251 lines
7.9 KiB
Python
Raw Permalink 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.

"""
Events Service — календарь событий дома
"""
import logging
from datetime import datetime, timedelta
from typing import Dict, List, Optional
from sqlalchemy import select, func, delete
from sqlalchemy.ext.asyncio import AsyncSession
logger = logging.getLogger(__name__)
class EventsService:
"""Сервис событий"""
def __init__(self, session: AsyncSession):
self.session = session
async def create_event(
self,
title: str,
event_date: datetime,
description: str = None,
event_type: str = 'general',
location: str = None,
created_by: int = None
) -> int:
"""
Создать событие
Returns: ID события
"""
from database.models import Event
event = Event(
title=title,
description=description,
event_type=event_type,
event_date=event_date,
location=location,
created_by=created_by
)
self.session.add(event)
await self.session.commit()
await self.session.refresh(event)
logger.info(f"Событие {title} создано (ID: {event.id})")
return event.id
async def join_event(self, event_id: int, user_id: int) -> bool:
"""
Присоединиться к событию
Returns: True если успешно
"""
from database.models import EventParticipant
# Проверяем не участвует ли уже
stmt = select(EventParticipant).where(
EventParticipant.event_id == event_id,
EventParticipant.user_id == user_id
)
result = await self.session.execute(stmt)
if result.scalar_one_or_none():
return False
participant = EventParticipant(
event_id=event_id,
user_id=user_id
)
self.session.add(participant)
await self.session.commit()
logger.info(f"Пользователь {user_id} присоединился к событию {event_id}")
return True
async def leave_event(self, event_id: int, user_id: int) -> bool:
"""
Отписаться от события
Returns: True если успешно
"""
from database.models import EventParticipant
stmt = delete(EventParticipant).where(
EventParticipant.event_id == event_id,
EventParticipant.user_id == user_id
)
await self.session.execute(stmt)
await self.session.commit()
logger.info(f"Пользователь {user_id} отписался от события {event_id}")
return True
async def get_event(self, event_id: int) -> Optional[Dict]:
"""Получить информацию о событии"""
from database.models import Event
event = await self.session.get(Event, event_id)
if not event:
return None
# Считаем участников
stmt = select(func.count()).select_from(EventParticipant).where(
EventParticipant.event_id == event_id
)
result = await self.session.execute(stmt)
participants_count = result.scalar() or 0
return {
'id': event.id,
'title': event.title,
'description': event.description,
'event_type': event.event_type,
'event_date': event.event_date,
'location': event.location,
'created_by': event.created_by,
'participants_count': participants_count,
'is_active': event.is_active
}
async def get_upcoming_events(self, limit: int = 10) -> List[Dict]:
"""Получить предстоящие события"""
from database.models import Event
stmt = (
select(Event)
.where(Event.is_active == True)
.where(Event.event_date >= datetime.utcnow())
.order_by(Event.event_date)
.limit(limit)
)
result = await self.session.execute(stmt)
events = list(result.scalars().all())
return [
{
'id': e.id,
'title': e.title,
'event_date': e.event_date,
'location': e.location,
'event_type': e.event_type
}
for e in events
]
async def get_user_events(self, user_id: int) -> List[Dict]:
"""Получить события пользователя"""
from database.models import Event, EventParticipant
stmt = (
select(Event)
.join(EventParticipant, Event.id == EventParticipant.event_id)
.where(EventParticipant.user_id == user_id)
.where(Event.is_active == True)
.order_by(Event.event_date)
)
result = await self.session.execute(stmt)
events = list(result.scalars().all())
return [
{
'id': e.id,
'title': e.title,
'event_date': e.event_date,
'location': e.location,
'event_type': e.event_type
}
for e in events
]
async def cancel_event(self, event_id: int) -> bool:
"""Отменить событие"""
from database.models import Event
event = await self.session.get(Event, event_id)
if not event:
return False
event.is_active = False
await self.session.commit()
logger.info(f"Событие {event_id} отменено")
return True
async def get_participants(self, event_id: int) -> List[Dict]:
"""Получить участников события"""
from database.models import EventParticipant, User
stmt = (
select(User)
.join(EventParticipant, User.user_id == EventParticipant.user_id)
.where(EventParticipant.event_id == event_id)
)
result = await self.session.execute(stmt)
users = list(result.scalars().all())
return [
{
'user_id': u.user_id,
'name': u.full_name or u.username or f'user{u.user_id}',
'apartment': u.apartment
}
for u in users
]
async def get_events_for_reminder(self, hours_ahead: int = 24) -> List[Dict]:
"""Получить события для напоминания"""
from database.models import Event
now = datetime.utcnow()
future = now + timedelta(hours=hours_ahead)
stmt = (
select(Event)
.where(Event.is_active == True)
.where(Event.reminder_sent == False)
.where(Event.event_date > now)
.where(Event.event_date <= future)
)
result = await self.session.execute(stmt)
events = list(result.scalars().all())
return [
{
'id': e.id,
'title': e.title,
'event_date': e.event_date,
'location': e.location,
'description': e.description
}
for e in events
]
async def mark_reminder_sent(self, event_id: int):
"""Отметить что напоминание отправлено"""
from database.models import Event
event = await self.session.get(Event, event_id)
if event:
event.reminder_sent = True
await self.session.commit()
def get_event_type_emoji(self, event_type: str) -> str:
"""Получить emoji типа события"""
emojis = {
'meeting': '📋',
'subbotnik': '🧹',
'holiday': '🎉',
'sport': '',
'kids': '🎈',
'general': '📅'
}
return emojis.get(event_type, '📅')