Thanks to visit codestin.com
Credit goes to github.com

Skip to content
Open
Show file tree
Hide file tree
Changes from all commits
Commits
File filter

Filter by extension

Filter by extension


Conversations
Failed to load comments.
Loading
Jump to
Jump to file
Failed to load files.
Loading
Diff view
Diff view
34 changes: 16 additions & 18 deletions backend/apps/nest/handlers/calendar_events.py
Original file line number Diff line number Diff line change
Expand Up @@ -6,11 +6,20 @@
from django.utils import timezone

from apps.nest.clients.google_calendar import GoogleCalendarClient
from apps.nest.models.google_account_authorization import GoogleAccountAuthorization
from apps.nest.models.reminder import Reminder
from apps.nest.models.reminder_schedule import ReminderSchedule
from apps.owasp.models.entity_channel import EntityChannel
from apps.owasp.models.event import Event
from apps.slack.models.member import Member


def get_calendar_id(user_id: str, event_number: str) -> str:
"""Get the Google Calendar ID for a user."""
if google_calendar_id := cache.get(f"{user_id}_{event_number}"):
return google_calendar_id
message = (
"Invalid or expired event number. Please get a new event number from the events list."
)
raise ValidationError(message)


def schedule_reminder(
Expand All @@ -33,29 +42,19 @@ def schedule_reminder(


def set_reminder(
channel: str,
event_number: str,
user_id: str,
channel: EntityChannel,
minutes_before: int,
client: GoogleCalendarClient,
member,
recurrence: str | None = None,
google_calendar_id: str = "",
message: str = "",
) -> ReminderSchedule:
"""Set a reminder for a user."""
if minutes_before <= 0:
message = "Minutes before must be a positive integer."
raise ValidationError(message)
auth = GoogleAccountAuthorization.authorize(user_id)
if not isinstance(auth, GoogleAccountAuthorization):
message = "User is not authorized with Google. Please sign in first."
raise ValidationError(message)
google_calendar_id = cache.get(f"{user_id}_{event_number}")
if not google_calendar_id:
message = (
"Invalid or expired event number. Please get a new event number from the events list."
)
raise ValidationError(message)

client = GoogleCalendarClient(auth)
event = Event.parse_google_calendar_event(client.get_event(google_calendar_id))
if not event:
message = "Could not retrieve the event details. Please try again later."
Expand All @@ -74,9 +73,8 @@ def set_reminder(
# Saving event to the database after validation
event.save()

member = Member.objects.get(slack_user_id=user_id)
reminder, _ = Reminder.objects.get_or_create(
channel_id=channel,
entity_channel=channel,
event=event,
member=member,
defaults={"message": f"{event.name} - {message}" if message else event.name},
Expand Down
Original file line number Diff line number Diff line change
@@ -0,0 +1,29 @@
# Generated by Django 5.2.6 on 2025-10-08 15:16

import django.db.models.deletion
from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("nest", "0013_merge_0006_delete_apikey_0012_reminderschedule_job_id"),
("owasp", "0055_merge_20251008_1253"),
]

operations = [
migrations.RemoveField(
model_name="reminder",
name="channel_id",
),
migrations.AddField(
model_name="reminder",
name="entity_channel",
field=models.ForeignKey(
null=True,
on_delete=django.db.models.deletion.CASCADE,
related_name="reminders",
to="owasp.entitychannel",
verbose_name="Channel",
),
),
]
Original file line number Diff line number Diff line change
@@ -0,0 +1,24 @@
# Generated by Django 5.2.6 on 2025-10-09 12:45

import django.db.models.deletion
from django.db import migrations, models


class Migration(migrations.Migration):
dependencies = [
("nest", "0014_remove_reminder_channel_id_reminder_entity_channel"),
("owasp", "0055_merge_20251008_1253"),
]

operations = [
migrations.AlterField(
model_name="reminder",
name="entity_channel",
field=models.ForeignKey(
on_delete=django.db.models.deletion.CASCADE,
related_name="reminders",
to="owasp.entitychannel",
verbose_name="Channel",
),
),
]
9 changes: 7 additions & 2 deletions backend/apps/nest/models/reminder.py
Original file line number Diff line number Diff line change
Expand Up @@ -11,7 +11,12 @@ class Meta:
verbose_name = "Nest Reminder"
verbose_name_plural = "Nest Reminders"

channel_id = models.CharField(verbose_name="Channel ID", max_length=15, default="")
entity_channel = models.ForeignKey(
"owasp.EntityChannel",
verbose_name="Channel",
on_delete=models.CASCADE,
related_name="reminders",
)
event = models.ForeignKey(
"owasp.Event",
verbose_name="Event",
Expand All @@ -30,4 +35,4 @@ class Meta:

def __str__(self) -> str:
"""Reminder human readable representation."""
return f"Reminder for {self.member} in channel: {self.channel_id}: {self.message}"
return f"Reminder for {self.member} in channel: {self.entity_channel}: {self.message}"
24 changes: 12 additions & 12 deletions backend/apps/nest/schedulers/calendar_events/base.py
Original file line number Diff line number Diff line change
@@ -1,6 +1,5 @@
"""Base Scheduler for Nest Calendar Events."""

from django.utils import timezone
from django_rq import get_scheduler

from apps.nest.models.reminder_schedule import ReminderSchedule
Expand All @@ -19,23 +18,18 @@ def schedule(self):
if self.reminder_schedule.recurrence == ReminderSchedule.Recurrence.ONCE:
self.reminder_schedule.job_id = self.scheduler.enqueue_at(
self.reminder_schedule.scheduled_time,
self.__class__.send_message,
self.__class__.send_and_delete,
message=self.reminder_schedule.reminder.message,
channel_id=self.reminder_schedule.reminder.channel_id,
channel_id=self.reminder_schedule.reminder.entity_channel.pk,
reminder_schedule_id=self.reminder_schedule.pk,
).get_id()

# Schedule deletion of the reminder after sending the message
self.scheduler.enqueue_at(
self.reminder_schedule.scheduled_time + timezone.timedelta(minutes=1),
self.reminder_schedule.reminder.delete,
)
else:
self.reminder_schedule.job_id = self.scheduler.cron(
self.reminder_schedule.cron_expression,
func=self.__class__.send_and_update,
args=(
self.reminder_schedule.reminder.message,
self.reminder_schedule.reminder.channel_id,
self.reminder_schedule.reminder.entity_channel.pk,
self.reminder_schedule.pk,
),
queue_name="default",
Expand All @@ -52,13 +46,19 @@ def cancel(self):
self.reminder_schedule.reminder.delete()

@staticmethod
def send_message(message: str, channel_id: str):
def send_message(message: str, channel_id: int):
"""Send message to the specified channel. To be implemented by subclasses."""
error_message = "Subclasses must implement this method."
raise NotImplementedError(error_message)

@staticmethod
def send_and_update(message: str, channel_id: str, reminder_schedule_id: int):
def send_and_delete(message: str, channel_id: int, reminder_schedule_id: int):
"""Send message to the specified channel and delete the reminder."""
error_message = "Subclasses must implement this method."
raise NotImplementedError(error_message)

@staticmethod
def send_and_update(message: str, channel_id: int, reminder_schedule_id: int):
"""Send message and update the reminder schedule."""
error_message = "Subclasses must implement this method."
raise NotImplementedError(error_message)
19 changes: 16 additions & 3 deletions backend/apps/nest/schedulers/calendar_events/slack.py
Original file line number Diff line number Diff line change
Expand Up @@ -2,23 +2,36 @@

from apps.nest.schedulers.calendar_events.base import BaseScheduler
from apps.nest.utils.calendar_events import update_reminder_schedule_date
from apps.owasp.models.entity_channel import EntityChannel
from apps.slack.apps import SlackConfig


class SlackScheduler(BaseScheduler):
"""Slack Scheduler Class for Nest Calendar Events."""

@staticmethod
def send_message(message: str, channel_id: str):
def send_message(message: str, channel_id: int):
"""Send message to the specified Slack channel."""
entity_channel = EntityChannel.objects.get(pk=channel_id)

if app := SlackConfig.app:
app.client.chat_postMessage(
channel=channel_id,
channel=entity_channel.channel.slack_channel_id,
text=message,
)

@staticmethod
def send_and_update(message: str, channel_id: str, reminder_schedule_id: int):
def send_and_delete(message: str, channel_id: int, reminder_schedule_id: int):
"""Send message to the specified channel and delete the reminder."""
# Import here to avoid circular import issues
from apps.nest.models.reminder_schedule import ReminderSchedule

SlackScheduler.send_message(message, channel_id)
if reminder_schedule := ReminderSchedule.objects.filter(pk=reminder_schedule_id).first():
reminder_schedule.reminder.delete()

@staticmethod
def send_and_update(message: str, channel_id: int, reminder_schedule_id: int):
"""Send message and update the reminder schedule."""
SlackScheduler.send_message(message, channel_id)
update_reminder_schedule_date(reminder_schedule_id)
12 changes: 12 additions & 0 deletions backend/apps/owasp/migrations/0055_merge_20251008_1253.py
Original file line number Diff line number Diff line change
@@ -0,0 +1,12 @@
# Generated by Django 5.2.6 on 2025-10-08 12:53

from django.db import migrations


class Migration(migrations.Migration):
dependencies = [
("owasp", "0053_merge_20250918_1659"),
("owasp", "0054_event_event_end_date_desc_idx"),
]

operations = []
2 changes: 0 additions & 2 deletions backend/apps/slack/admin/entity_channel.py
Original file line number Diff line number Diff line change
Expand Up @@ -25,8 +25,6 @@ class EntityChannelAdmin(admin.ModelAdmin):
"entity_type",
"entity_id",
"channel_type",
"search_button",
"channel_search",
"channel_id",
"platform",
"is_default",
Expand Down
12 changes: 12 additions & 0 deletions backend/apps/slack/commands/command.py
Original file line number Diff line number Diff line change
Expand Up @@ -87,6 +87,18 @@ def get_user_id(self, command) -> str:
"""
return command.get("user_id")

def get_workspace_id(self, command) -> str:
"""Get the workspace ID from the command.

Args:
command (dict): The Slack event payload.

Returns:
str: The workspace ID.

"""
return command.get("team_id")

def render_blocks(self, command):
"""Get the rendered blocks.

Expand Down
4 changes: 3 additions & 1 deletion backend/apps/slack/commands/nestbot.py
Original file line number Diff line number Diff line change
Expand Up @@ -30,6 +30,8 @@ def render_blocks(self, command):
markdown("*Invalid command format. Please check your input and try again.*")
]
else:
return get_setting_reminder_blocks(args, self.get_user_id(command))
return get_setting_reminder_blocks(
args, self.get_user_id(command), self.get_workspace_id(command)
)
else:
return get_cancel_reminder_blocks(int(args.number), self.get_user_id(command))
Loading