From 4bd88744f8512ac38ef46afa9cf4cd2f27105b62 Mon Sep 17 00:00:00 2001 From: Big-Lolo <95545807+Big-Lolo@users.noreply.github.com> Date: Mon, 17 Nov 2025 09:54:30 +0100 Subject: [PATCH 1/6] Modified Slack endpoint Slack URL Was hardcoded. Now you have slack url as an argument --- src/impl/Event/router_v1.py | 4 ++-- src/impl/Event/service.py | 4 ++-- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/src/impl/Event/router_v1.py b/src/impl/Event/router_v1.py index 709ca668..1725bda9 100644 --- a/src/impl/Event/router_v1.py +++ b/src/impl/Event/router_v1.py @@ -380,8 +380,8 @@ def resend_accept_mail( @router.get("/{event_id}/send_slack_mail/") -def send_slack_mail(event_id: int, token: BaseToken = Depends(JWTBearer())): - event_service.send_slack_mail(event_id, token) +def send_slack_mail(event_id: int, slackUrl: str, token: BaseToken = Depends(JWTBearer())): + event_service.send_slack_mail(event_id, slackUrl, token) return {"success": True} diff --git a/src/impl/Event/service.py b/src/impl/Event/service.py index 3b0f2dff..695bd9a9 100644 --- a/src/impl/Event/service.py +++ b/src/impl/Event/service.py @@ -972,7 +972,7 @@ def resend_mail(self, event_id: int, hacker_id: int, data: BaseToken): db.session.commit() @BaseService.needs_service(MailClient) - def send_slack_mail(self, event_id: int, data: BaseToken): + def send_slack_mail(self, event_id: int, slackUrl: str, data: BaseToken): if not data.check([UserType.LLEIDAHACKER]): raise AuthenticationException("Not authorized") event = self.get_by_id(event_id) @@ -992,7 +992,7 @@ def send_slack_mail(self, event_id: int, data: BaseToken): subject="HackEPS2024 slack invitation", receiver_id=str(hacker.id), receiver_mail=str(hacker.email), - fields="https://join.slack.com/t/hackeps2024/shared_invite/zt-2usc9qny9-z3NkybNlCXFAI9m0Cl~FsQ", + fields=slackUrl, ) ) From 9324eccaaf4614c4a4b8d19beaca27d40ad64919 Mon Sep 17 00:00:00 2001 From: Big-Lolo <95545807+Big-Lolo@users.noreply.github.com> Date: Mon, 17 Nov 2025 10:08:24 +0100 Subject: [PATCH 2/6] Feature: Reminder Endpoint Created reminder endpoint --- src/impl/Event/router_v1.py | 13 +++++++- src/impl/Event/service.py | 44 ++++++++++++++++++++++++++++ src/impl/Mail/internall_templates.py | 2 ++ 3 files changed, 58 insertions(+), 1 deletion(-) diff --git a/src/impl/Event/router_v1.py b/src/impl/Event/router_v1.py index 1725bda9..f078d259 100644 --- a/src/impl/Event/router_v1.py +++ b/src/impl/Event/router_v1.py @@ -379,11 +379,22 @@ def resend_accept_mail( return {"success": True} -@router.get("/{event_id}/send_slack_mail/") +@router.post("/{event_id}/send_slack_mail/") def send_slack_mail(event_id: int, slackUrl: str, token: BaseToken = Depends(JWTBearer())): event_service.send_slack_mail(event_id, slackUrl, token) return {"success": True} +@router.post("/{event_id}/send_reminder_mails/") +def send_reminder_mails( + event_id: int, + token: BaseToken = Depends(JWTBearer()), +): + """ + Send reminder mails to all accepted hackers of an event + """ + event_service.send_reminder_mails(event_id, token) + return {"success": True} + # @router.post("/{event_id}/send_remember") # def send_remember( diff --git a/src/impl/Event/service.py b/src/impl/Event/service.py index 695bd9a9..6dd38265 100644 --- a/src/impl/Event/service.py +++ b/src/impl/Event/service.py @@ -997,3 +997,47 @@ def send_slack_mail(self, event_id: int, slackUrl: str, data: BaseToken): ) db.session.commit() + + @BaseService.needs_service(MailClient) + def send_reminder_mails( + self, + event_id: int, + data: BaseToken, + ): + if not data.check([UserType.LLEIDAHACKER]): + raise AuthenticationException("Not authorized") + event = self.get_by_id(event_id) + if event.archived: + raise InvalidDataException( + "Unable to operate with an archived event, unarchive it first" + ) + + hackers = event.accepted_hackers + + for hacker in hackers: + reg = ( + db.session.query(HackerRegistration) + .filter( + HackerRegistration.user_id == hacker.id, + HackerRegistration.event_id == event.id, + ) + .first() + ) + # send reminder only if registration exists and assistance not confirmed + if reg is None or reg.confirmed_assistance: + continue + + mail = self.mail_client.create_mail( + MailCreate( + template_id=self.mail_client.get_internall_template_id( + InternalTemplate.EVENT_HACKER_REMINDER + ), + subject=f"{event.name} - Recordatori de confirmació d'assistència", + receiver_id=str(hacker.id), + receiver_mail=str(hacker.email), + fields=f"{hacker.name},{event.name},{event.start_date.strftime('%d/%m/%Y %H:%M')}", + ) + ) + # send the created mail + self.mail_client.send_mail_by_id(mail.id) + db.session.commit() \ No newline at end of file diff --git a/src/impl/Mail/internall_templates.py b/src/impl/Mail/internall_templates.py index e50fd964..18b695ca 100644 --- a/src/impl/Mail/internall_templates.py +++ b/src/impl/Mail/internall_templates.py @@ -11,5 +11,7 @@ class InternalTemplate(Enum): EVENT_HACKER_REGISTERED = "event_hacker_registered" EVENT_HACKER_ACCEPTED = "event_hacker_accepted" + + EVENT_HACKER_REMINDER = "event_hacker_reminder" # EVENT_HACKER_REJECTED = 'event_hacker_accepted' # EVENT_HACKER_CONFIRMATION = 'event_hacker_confirmation' From 64dece856b8810baea322ab9bf85f281affa6d7d Mon Sep 17 00:00:00 2001 From: Big-Lolo <95545807+Big-Lolo@users.noreply.github.com> Date: Mon, 17 Nov 2025 10:26:25 +0100 Subject: [PATCH 3/6] Update fields --- src/impl/Event/service.py | 16 +++++++++++++++- 1 file changed, 15 insertions(+), 1 deletion(-) diff --git a/src/impl/Event/service.py b/src/impl/Event/service.py index 6dd38265..edc04e76 100644 --- a/src/impl/Event/service.py +++ b/src/impl/Event/service.py @@ -1027,6 +1027,20 @@ def send_reminder_mails( if reg is None or reg.confirmed_assistance: continue + # ensure there is a confirmation token for this registration + if not reg.confirm_assistance_token: + reg.confirm_assistance_token = AssistenceToken(hacker, event.id).to_token() + + # compute days left until event (rounded down) + try: + delta = event.start_date - datetime.now() + days_left = max(0, int(delta.total_seconds() // 86400)) + except Exception: + days_left = 0 + + # fields expected: name, days_left, token, event_name + fields = f"{hacker.name},{days_left},{reg.confirm_assistance_token},{event.name}" + mail = self.mail_client.create_mail( MailCreate( template_id=self.mail_client.get_internall_template_id( @@ -1035,7 +1049,7 @@ def send_reminder_mails( subject=f"{event.name} - Recordatori de confirmació d'assistència", receiver_id=str(hacker.id), receiver_mail=str(hacker.email), - fields=f"{hacker.name},{event.name},{event.start_date.strftime('%d/%m/%Y %H:%M')}", + fields=fields, ) ) # send the created mail From fd586c580a379e695c286a44dc0f99aaa6b356ba Mon Sep 17 00:00:00 2001 From: Big-Lolo <95545807+Big-Lolo@users.noreply.github.com> Date: Mon, 17 Nov 2025 11:20:24 +0100 Subject: [PATCH 4/6] Update service.py --- src/impl/Event/service.py | 3 +-- 1 file changed, 1 insertion(+), 2 deletions(-) diff --git a/src/impl/Event/service.py b/src/impl/Event/service.py index edc04e76..0f12fae9 100644 --- a/src/impl/Event/service.py +++ b/src/impl/Event/service.py @@ -1038,8 +1038,7 @@ def send_reminder_mails( except Exception: days_left = 0 - # fields expected: name, days_left, token, event_name - fields = f"{hacker.name},{days_left},{reg.confirm_assistance_token},{event.name}" + fields = f"{hacker.name},{event.name},{days_left},{reg.confirm_assistance_token}" mail = self.mail_client.create_mail( MailCreate( From b754750fe62396a372fe8597c8a0c25b4f4fe697 Mon Sep 17 00:00:00 2001 From: Big-Lolo <95545807+Big-Lolo@users.noreply.github.com> Date: Mon, 17 Nov 2025 11:25:00 +0100 Subject: [PATCH 5/6] Update service.py --- src/impl/Event/service.py | 4 +++- 1 file changed, 3 insertions(+), 1 deletion(-) diff --git a/src/impl/Event/service.py b/src/impl/Event/service.py index 0f12fae9..345909be 100644 --- a/src/impl/Event/service.py +++ b/src/impl/Event/service.py @@ -984,7 +984,7 @@ def send_slack_mail(self, event_id: int, slackUrl: str, data: BaseToken): hackers = event.accepted_hackers for hacker in hackers: - self.mail_client.create_mail( + mail = self.mail_client.create_mail( MailCreate( template_id=self.mail_client.get_internall_template_id( InternalTemplate.EVENT_SLACK_INVITE @@ -995,6 +995,8 @@ def send_slack_mail(self, event_id: int, slackUrl: str, data: BaseToken): fields=slackUrl, ) ) + # send the created mail + self.mail_client.send_mail_by_id(mail.id) db.session.commit() From b5f12d26d0958dbeb6d8c66e4f9b67afc602a0ac Mon Sep 17 00:00:00 2001 From: Lotfi Bouakel <95545807+Big-Lolo@users.noreply.github.com> Date: Mon, 17 Nov 2025 11:44:27 +0100 Subject: [PATCH 6/6] Update src/impl/Event/service.py Co-authored-by: Copilot <175728472+Copilot@users.noreply.github.com> --- src/impl/Event/service.py | 80 +++++++++++++++++++++------------------ 1 file changed, 43 insertions(+), 37 deletions(-) diff --git a/src/impl/Event/service.py b/src/impl/Event/service.py index 345909be..49fd510d 100644 --- a/src/impl/Event/service.py +++ b/src/impl/Event/service.py @@ -1017,42 +1017,48 @@ def send_reminder_mails( hackers = event.accepted_hackers for hacker in hackers: - reg = ( - db.session.query(HackerRegistration) - .filter( - HackerRegistration.user_id == hacker.id, - HackerRegistration.event_id == event.id, - ) - .first() - ) - # send reminder only if registration exists and assistance not confirmed - if reg is None or reg.confirmed_assistance: - continue - - # ensure there is a confirmation token for this registration - if not reg.confirm_assistance_token: - reg.confirm_assistance_token = AssistenceToken(hacker, event.id).to_token() - - # compute days left until event (rounded down) try: - delta = event.start_date - datetime.now() - days_left = max(0, int(delta.total_seconds() // 86400)) - except Exception: - days_left = 0 - - fields = f"{hacker.name},{event.name},{days_left},{reg.confirm_assistance_token}" - - mail = self.mail_client.create_mail( - MailCreate( - template_id=self.mail_client.get_internall_template_id( - InternalTemplate.EVENT_HACKER_REMINDER - ), - subject=f"{event.name} - Recordatori de confirmació d'assistència", - receiver_id=str(hacker.id), - receiver_mail=str(hacker.email), - fields=fields, + reg = ( + db.session.query(HackerRegistration) + .filter( + HackerRegistration.user_id == hacker.id, + HackerRegistration.event_id == event.id, + ) + .first() ) - ) - # send the created mail - self.mail_client.send_mail_by_id(mail.id) - db.session.commit() \ No newline at end of file + # send reminder only if registration exists and assistance not confirmed + if reg is None or reg.confirmed_assistance: + continue + + # ensure there is a confirmation token for this registration + if not reg.confirm_assistance_token: + reg.confirm_assistance_token = AssistenceToken(hacker, event.id).to_token() + + # compute days left until event (rounded down) + try: + delta = event.start_date - datetime.now() + days_left = max(0, int(delta.total_seconds() // 86400)) + except Exception: + days_left = 0 + + fields = f"{hacker.name},{event.name},{days_left},{reg.confirm_assistance_token}" + + mail = self.mail_client.create_mail( + MailCreate( + template_id=self.mail_client.get_internall_template_id( + InternalTemplate.EVENT_HACKER_REMINDER + ), + subject=f"{event.name} - Recordatori de confirmació d'assistència", + receiver_id=str(hacker.id), + receiver_mail=str(hacker.email), + fields=fields, + ) + ) + # send the created mail + self.mail_client.send_mail_by_id(mail.id) + db.session.commit() + except Exception as e: + db.session.rollback() + # Optionally log the error here, e.g.: + # print(f"Failed to send reminder to hacker {hacker.id}: {e}") + continue \ No newline at end of file