feat: add Discord reminder and timezone settings
This commit is contained in:
@@ -33,3 +33,29 @@ local midnight (including DST). Delivery claims, nonce, opt-out, and retry rules
|
||||
are unchanged. The dashboard preview explicitly disables buttons because it has
|
||||
no signed interaction endpoint configured. Global command registration and the
|
||||
Discord interaction endpoint must be configured separately before production use.
|
||||
## Preferences
|
||||
|
||||
`preferences.ts` implements global `/settings` and `/reminders`. Reminder menus
|
||||
paginate ten named schedules at a time; entries with matching name and schedule
|
||||
are edited together as multiple comma-separated 24-hour times. Forms accept
|
||||
weekday names (or `every day`) or one ISO calendar date. Delivery is toggled for
|
||||
all schedules. Removing the last schedule disables delivery and stores an empty
|
||||
list; the shared contract permits empty lists only while disabled. Invalid forms
|
||||
provide a prefilled retry button. UTC accounts receive a timezone setup hint.
|
||||
|
||||
`ReminderService` is shared with the website routes. Every save advances its
|
||||
`updatedAt` monotonically; Discord controls compare the saved preference snapshot
|
||||
and the user's timezone/update version before editing. `HabitService.setTimezone`
|
||||
also advances the user timestamp monotonically, including repeated writes in the
|
||||
same millisecond. This rejects old Discord forms after edits from either interface,
|
||||
including change-and-revert sequences. Website PUT retains its existing request
|
||||
contract. Delivery receipts do not invalidate preference controls.
|
||||
|
||||
Integration: retain the `preferences` command dispatch and `preferencesAction`
|
||||
component dispatch in `routes.ts`, the two definitions in `commands.ts`, and the
|
||||
preference fields in `ControlData`. `CommandConfig.remindersAvailable` supplies
|
||||
availability; `createApi` derives it from the existing sharing bot token, matching
|
||||
the website and reminder worker. Direct route fixtures default it to false.
|
||||
No new environment variables, migrations, outbound requests, or remote command
|
||||
registration are needed by this module. Global command registration remains an
|
||||
integration step. Successful mutations invoke the supplied live-card dirty hook.
|
||||
|
||||
Reference in New Issue
Block a user