zerver: Add endpoints and events for reminders.

There are similar to what exists for scheduled messages expect
the PATCH requests which will be added later when the
functionality is implemented.
This commit is contained in:
Aman Agrawal
2025-06-28 02:38:58 +05:30
committed by Tim Abbott
parent 0b4da0ae35
commit 25731859b6
19 changed files with 475 additions and 16 deletions

View File

@@ -65,6 +65,8 @@ from zerver.lib.event_types import (
EventRealmUserRemove,
EventRealmUserSettingsDefaultsUpdate,
EventRealmUserUpdate,
EventRemindersAdd,
EventRemindersRemove,
EventRestart,
EventSavedSnippetsAdd,
EventSavedSnippetsRemove,
@@ -197,6 +199,8 @@ check_realm_linkifiers = make_checker(EventRealmLinkifiers)
check_realm_playgrounds = make_checker(EventRealmPlaygrounds)
check_realm_user_add = make_checker(EventRealmUserAdd)
check_realm_user_remove = make_checker(EventRealmUserRemove)
check_reminder_add = make_checker(EventRemindersAdd)
check_reminder_remove = make_checker(EventRemindersRemove)
check_restart = make_checker(EventRestart)
check_saved_snippets_add = make_checker(EventSavedSnippetsAdd)
check_saved_snippets_remove = make_checker(EventSavedSnippetsRemove)

View File

@@ -821,6 +821,29 @@ class EventScheduledMessagesUpdate(BaseEvent):
scheduled_message: ScheduledMessageFields
class ReminderFields(BaseModel):
reminder_id: int
type: Literal["private"]
to: list[int]
content: str
rendered_content: str
scheduled_delivery_timestamp: int
failed: bool
reminder_target_message_id: int
class EventRemindersAdd(BaseEvent):
type: Literal["reminders"]
op: Literal["add"]
reminders: list[ReminderFields]
class EventRemindersRemove(BaseEvent):
type: Literal["reminders"]
op: Literal["remove"]
reminder_id: int
class BasicStreamFields(BaseModel):
is_archived: bool
can_administer_channel_group: int | UserGroupMembersDict

View File

@@ -51,7 +51,10 @@ from zerver.lib.onboarding_steps import get_next_onboarding_steps
from zerver.lib.presence import get_presence_for_user, get_presences_for_realm
from zerver.lib.realm_icon import realm_icon_url
from zerver.lib.realm_logo import get_realm_logo_source, get_realm_logo_url
from zerver.lib.scheduled_messages import get_undelivered_scheduled_messages
from zerver.lib.scheduled_messages import (
get_undelivered_reminders,
get_undelivered_scheduled_messages,
)
from zerver.lib.soft_deactivation import reactivate_user_if_soft_deactivated
from zerver.lib.sounds import get_available_notification_sounds
from zerver.lib.stream_subscription import handle_stream_notifications_compatibility
@@ -328,6 +331,9 @@ def fetch_initial_state_data(
[] if user_profile is None else get_undelivered_scheduled_messages(user_profile)
)
if want("reminders"):
state["reminders"] = [] if user_profile is None else get_undelivered_reminders(user_profile)
if want("muted_topics") and (
# Suppress muted_topics data for clients that explicitly
# support user_topic. This allows clients to request both the

View File

@@ -1,6 +1,7 @@
from django.conf import settings
from django.utils.translation import gettext as _
from zerver.lib.exceptions import ResourceNotFoundError
from zerver.lib.markdown.fenced_code import get_unused_fence
from zerver.lib.mention import silent_mention_syntax_for_user
from zerver.lib.message import truncate_content
@@ -8,6 +9,7 @@ from zerver.lib.message_cache import MessageDict
from zerver.lib.topic_link_util import get_message_link_syntax
from zerver.lib.url_encoding import message_link_url
from zerver.models import Message, Stream, UserProfile
from zerver.models.scheduled_jobs import ScheduledMessage
def get_reminder_formatted_content(message: Message, current_user: UserProfile) -> str:
@@ -46,3 +48,12 @@ def get_reminder_formatted_content(message: Message, current_user: UserProfile)
fence=fence,
msg_content=msg_content,
)
def access_reminder(user_profile: UserProfile, reminder_id: int) -> ScheduledMessage:
try:
return ScheduledMessage.objects.get(
id=reminder_id, sender=user_profile, delivery_type=ScheduledMessage.REMIND
)
except ScheduledMessage.DoesNotExist:
raise ResourceNotFoundError(_("Reminder does not exist"))

View File

@@ -3,6 +3,7 @@ from django.utils.translation import gettext as _
from zerver.lib.exceptions import ResourceNotFoundError
from zerver.models import ScheduledMessage, UserProfile
from zerver.models.scheduled_jobs import (
APIReminderDirectMessageDict,
APIScheduledDirectMessageDict,
APIScheduledStreamMessageDict,
)
@@ -12,7 +13,9 @@ def access_scheduled_message(
user_profile: UserProfile, scheduled_message_id: int
) -> ScheduledMessage:
try:
return ScheduledMessage.objects.get(id=scheduled_message_id, sender=user_profile)
return ScheduledMessage.objects.get(
id=scheduled_message_id, sender=user_profile, delivery_type=ScheduledMessage.SEND_LATER
)
except ScheduledMessage.DoesNotExist:
raise ResourceNotFoundError(_("Scheduled message does not exist"))
@@ -32,3 +35,20 @@ def get_undelivered_scheduled_messages(
scheduled_message.to_dict() for scheduled_message in scheduled_messages
]
return scheduled_message_dicts
def get_undelivered_reminders(
user_profile: UserProfile,
) -> list[APIReminderDirectMessageDict]:
reminders = ScheduledMessage.objects.filter(
realm_id=user_profile.realm_id,
sender=user_profile,
# Notably, we don't require failed=False, since we will want
# to display those to users.
delivered=False,
delivery_type=ScheduledMessage.REMIND,
).order_by("scheduled_timestamp")
reminder_dicts: list[APIReminderDirectMessageDict] = [
reminder.to_reminder_dict() for reminder in reminders
]
return reminder_dicts