diff --git a/app/database/models.py b/app/database/models.py index 6cd830c1..b9129832 100644 --- a/app/database/models.py +++ b/app/database/models.py @@ -57,10 +57,9 @@ class Event(Base): end = Column(DateTime, nullable=False) content = Column(String) location = Column(String) - color = Column(String, nullable=True) + invitees = Column(String) owner_id = Column(Integer, ForeignKey("users.id")) - invitees = Column(String) color = Column(String, nullable=True) category_id = Column(Integer, ForeignKey("categories.id")) diff --git a/app/internal/event.py b/app/internal/event.py index 005a59c1..13ba1600 100644 --- a/app/internal/event.py +++ b/app/internal/event.py @@ -1,8 +1,10 @@ import logging import re +from typing import List, Set from email_validator import EmailSyntaxError, validate_email from fastapi import HTTPException +from sqlalchemy.orm import Session from starlette.status import HTTP_400_BAD_REQUEST from app.database.models import Event @@ -16,25 +18,69 @@ def raise_if_zoom_link_invalid(location): detail="VC type with no valid zoom link") -def get_invited_emails(invited_from_form): +def get_invited_emails(invited_from_form: str) -> List[str]: invited_emails = [] for invited_email in invited_from_form.split(','): invited_email = invited_email.strip() try: validate_email(invited_email, check_deliverability=False) - invited_emails.append(invited_email) except EmailSyntaxError: - logging.error(f'{invited_email} is not a valid email address') + logging.exception(f'{invited_email} is not a valid email address') + continue + invited_emails.append(invited_email) return invited_emails -def get_uninvited_regular_emails(session, owner_id, title, invited_emails): - regular_invitees = set() +def get_uninvited_regular_emails(session: Session, + owner_id: int, + title: str, + invited_emails: List[str]) -> Set[str]: invitees_query = session.query(Event).with_entities(Event.invitees) similar_events_invitees = invitees_query.filter(Event.owner_id == owner_id, Event.title == title).all() + regular_invitees = set() for record in similar_events_invitees: - regular_invitees.update(record[0].split(',')) + if record: + regular_invitees.update(record[0].split(',')) return regular_invitees - set(invited_emails) + + +def check_diffs(checked_event: Event, + all_events: List[Event]): + """Returns the repeated events and the week difference""" + diffs = [] + for event in all_events: + start_delta = checked_event.start - event.start + end_delta = checked_event.end - event.end + + # The current event is before the new event and they take the same time + if start_delta.total_seconds() > 0 and start_delta == end_delta: + # Difference is in multiple of 7 days + if start_delta.seconds == 0 and start_delta.days % 7 == 0: + diffs.append(int(start_delta.days / 7)) + + return diffs + + +def find_pattern(session, event): + all_events_with_same_name = session.query(Event).filter( + Event.owner_id == event.owner_id, Event.title == event.title).all() + + return check_diffs(event, all_events_with_same_name) + + +def get_messages(session: Session, + event: Event, + uninvited_contacts: List[str]) -> List[str]: + messages = [] + if uninvited_contacts: + messages.append(f'Forgot to invite ' + f'{", ".join(uninvited_contacts)} maybe?') + + pattern = find_pattern(session, event) + for weeks_diff in pattern: + messages.append(f'Same event happened {weeks_diff} weeks before too. ' + f'Want to create another one {weeks_diff} after too?') + return messages diff --git a/app/routers/event.py b/app/routers/event.py index cf5bc68d..33ada15b 100644 --- a/app/routers/event.py +++ b/app/routers/event.py @@ -12,7 +12,7 @@ from app.database.models import Event, User, UserEvent from app.dependencies import get_db, logger, templates from app.internal.event import ( - get_invited_emails, get_uninvited_regular_emails, + get_invited_emails, get_messages, get_uninvited_regular_emails, raise_if_zoom_link_invalid, ) from app.internal.utils import create_model @@ -73,11 +73,11 @@ async def create_new_event(request: Request, session=Depends(get_db)): event = create_event(session, title, start, end, owner_id, content, location, invited_emails, category_id=category_id) - message = '' - if uninvited_contacts: - message = f'Forgot to invite {", ".join(uninvited_contacts)} maybe?' + + messages = get_messages(session, event, uninvited_contacts) return RedirectResponse(router.url_path_for('eventview', event_id=event.id) - + f'?{message}', status_code=status.HTTP_302_FOUND) + + f'messages={"---".join(messages)}', + status_code=status.HTTP_302_FOUND) @router.get("/{event_id}") @@ -87,12 +87,12 @@ async def eventview(request: Request, event_id: int, start_format = '%A, %d/%m/%Y %H:%M' end_format = ('%H:%M' if event.start.date() == event.end.date() else start_format) - message = request.query_params.get('message', '') + messages = request.query_params.get('messages', '').split("---") return templates.TemplateResponse("event/eventview.html", {"request": request, "event": event, "start_format": start_format, "end_format": end_format, - "message": message}) + "messages": messages}) def by_id(db: Session, event_id: int) -> Event: diff --git a/app/templates/event/eventview.html b/app/templates/event/eventview.html index 11f398dc..708195da 100644 --- a/app/templates/event/eventview.html +++ b/app/templates/event/eventview.html @@ -11,6 +11,11 @@

{{ message }}

+
+ {% for message in messages %} +

{{ message }}

+ {% endfor %} +