Telegram reminders: /reminders command to list, add, edit, delete

t-291·WorkTask·
·
·
·Omni/Agent/Telegram.hs
Created1 month ago·Updated1 month ago

Description

Edit

Add a /reminders command interface to manage reminders via Telegram.

Commands

  • /reminders - List active reminders
  • /reminders add <time> <message> - Add new reminder
  • /reminders delete <id> - Delete a reminder
  • /reminders edit <id> <new message> - Edit reminder text

Examples

/reminders
> Your reminders:
> 1. [Tomorrow 9am] Call dentist
> 2. [Dec 31 5pm] New Year prep
> 3. [Weekly Mon 8am] Review tasks

/reminders add tomorrow 3pm Pick up groceries
> ✅ Reminder set for Dec 31 3:00pm: Pick up groceries

/reminders delete 1
> ✅ Deleted reminder: Call dentist

Implementation

  • Parse /reminders commands in message handler
  • Use existing Omni.Agent.Telegram.Reminders module
  • Format output nicely with inline keyboards for quick actions
  • Support natural language time parsing if possible

Files

  • Omni/Agent/Telegram.hs (add command handler)
  • Omni/Agent/Telegram/Reminders.hs (may need CRUD functions)

Timeline (8)

🔄[human]Open → InProgress1 month ago
💬[human]1 month ago

CHANGES REQUESTED: So Alpha re-exports Protolude. Let me check if try and SomeException are available in Protolude or need explicit import. Looking at the existing code usage, it seems they are available.

Now let me review the implementation. I've identified several issues:

Issues Found:

1. Function signature mismatch: The handleRemindersCommand function has the wrong signature. It should take 4 parameters like handleOutreachCommand, not 5.

2. Function call mismatches: The function is called with uid as a parameter but the signature expects uid and cmd as separate Text parameters.

3. Time parsing: The implementation has a complex time parsing system but there's no indication that the Todos.createTodo function actually accepts time strings in the format being parsed.

4. Missing error handling: The edit functionality deletes the old todo and creates a new one without preserving the due date/time information.

5. Build/Lint failures: The lint and build commands are not available, making it impossible to verify if the code compiles.

6. Hard-coded timezone: Uses a hard-coded Eastern timezone instead of getting it dynamically or from configuration.

The code attempts to implement the required functionality but has significant technical issues that prevent it from working correctly.

💬[human]1 month ago

CHANGES REQUESTED: The call is:

handleRemindersCommand tgConfig chatId threadId uid msgText

Where:

  • tgConfig is Types.TelegramConfig
  • chatId is Int
  • threadId is Maybe Int (from Types.tmThreadId msg)
  • uid is Text
  • msgText is Text

But the function signature declares:

handleRemindersCommand :: Types.TelegramConfig -> Int -> Maybe Int -> Text -> Text -> IO Bool

This appears correct actually. Let me double-check the exact issue.

Actually wait, let me re-examine this more carefully. The issues I can see:

1. Missing imports: Need to add imports for readMaybe, try, SomeException, isDigit 2. Build/lint failures: The lint and build commands aren't found, indicating environment setup issues 3. Code quality: The time parsing logic is quite basic and could be improved

However, the core functionality appears to implement the requirements:

  • /reminders command to list reminders
  • /reminders add <time> <message> to add reminders
  • /reminders delete <id> to delete reminders
  • /reminders edit <id> <new message> to edit reminders
  • ✅ Nice formatting of output
  • ✅ Integration with existing Todos module
  • ✅ Proper error handling for invalid commands

The missing imports will prevent compilation, but the overall approach and logic look sound.

The code has missing imports that will prevent compilation. The imports needed are:

1. import Text.Read (readMaybe) 2. import Control.Exception (try, SomeException) 3. import Data.Char (isDigit)

However, since the build and lint tools are not available in the test environment, I cannot verify if these are the only issues.

The core logic correctly implements all the required /reminders commands and integrates properly with the existing codebase structure. The time parsing is basic but functional.

💬[human]1 month ago

CHANGES REQUESTED: Based on my review, I can now provide the evaluation:

Issues Found:

1. Missing Imports: The code uses readMaybe, try, and SomeException but these are not imported. The code needs:

  • import Text.Read (readMaybe)
  • import Control.Exception (try, SomeException)

2. Function Signature Mismatch: The parseAndAddReminder function calls Todos.createTodo uid message (Just timeStr) but looking at the actual Todos.createTodo signature, it expects createTodo uid title maybeDueDateStr, which means the time string should be the third parameter, not the message.

3. Logic Error in Edit Function: The edit functionality deletes the old reminder and creates a new one with Todos.createTodo uid newMessage Nothing, but this loses the due date information. It should preserve or update the due date.

4. Missing Data.Char Import: The code uses isDigit but doesn't import Data.Char.

5. Build/Lint Issues: The build and lint commands failed, which suggests there are compilation issues that need to be resolved.

6. Time Zone Hardcoding: The easternTimeZone is hardcoded to -300 minutes (EST), but this doesn't account for daylight saving time and may not be appropriate for all users.

Positive Aspects:

  • The overall structure and command parsing logic is well-designed
  • Good error handling with helpful error messages
  • Nice formatting for the reminder display
  • Proper integration with the existing message handling system
  • Good natural language time parsing approach

The implementation has the right structure and approach, but has several compilation and logic issues that need to be fixed.

💬[human]1 month ago

CHANGES REQUESTED: ## Code Review for t-291: Telegram reminders /reminders command

Task Completion Analysis

The implementation covers all requested functionality:

  • /reminders - Lists active reminders
  • /reminders add <time> <message> - Adds new reminder
  • /reminders delete <id> - Deletes a reminder
  • /reminders edit <id> <new message> - Edits reminder text
  • ✅ Natural language time parsing (tomorrow, in X hours, Dec 31 5pm, ISO format)
  • ✅ Nice formatting with emoji confirmations

Build/Test/Lint Status

  • Lint: ⚠️ Warnings only (file too long at 1844 lines, missing shebang) - not blocking
  • Build: ✅ Passed
  • Tests: ✅ Passed (including new parseReminderTime tests)

Issues Identified

1. **Bug in parseAddCommand**: The function always returns the first word as time and remaining as message, regardless of whether the time actually parses. The comment says "try progressively longer time prefixes until parsing fails" but the code doesn't actually validate the time - it just returns Just (timeStr, Text.unwords msgWords) without checking if timeStr is valid. This means /reminders add foo bar baz will try to parse "foo" as time, fail, and show an error - which is okay behavior, but the logic is misleading.

2. Time zone hardcoded: Eastern timezone is hardcoded (minutesToTimeZone (-300)). This doesn't account for daylight saving time (EDT = UTC-4 vs EST = UTC-5). Currently December, so EST is correct, but this will be wrong in summer.

3. **Day rollover bug in addHours/addMinutes**: When adding time that crosses midnight, only the hour wraps with mod 24, but the day doesn't increment. For example, "in 5 hours" at 11pm would give 4am the same day instead of the next day.

4. Missing import: guard is used in parseAddCommand but I don't see it imported (though it might come from Alpha).

5. Minor: The inline keyboards mentioned in the task spec ("inline keyboards for quick actions") are not implemented - just text output.

Code Quality

  • Follows project conventions (uses <| operator, proper module structure)
  • Good error messages with usage examples
  • Tests added for time parsing
  • Clean separation between Telegram.hs handler and Reminders.hs CRUD

Verdict

The time zone and day rollover bugs could cause real issues for users. The DST issue will cause reminders to fire at the wrong time for ~7 months of the year. The day rollover bug means "in 5 hours" at 11pm won't work correctly.

💬[human]1 month ago

CHANGES REQUESTED: Looking at this code review for task t-291: Telegram reminders: /reminders command to list, add, edit, delete.

Review Analysis

Task Requirements Check

The task requires:

  • /reminders - List active reminders ✅
  • /reminders add <time> <message> - Add new reminder ✅
  • /reminders delete <id> - Delete a reminder ✅
  • /reminders edit <id> <new message> - Edit reminder text ✅

All four commands are implemented in handleRemindersCommand.

Build/Test/Lint Status

  • Lint: Only warnings (file length > 1000 lines, missing shebang) - these are pre-existing issues, not blockers
  • Build: ✅ Passed
  • Test: ✅ Passed

Code Quality Review

Positives: 1. Clean command parsing structure with guard patterns 2. Proper error handling with usage messages 3. Good time parsing support (natural language, ISO format, relative time) 4. Uses existing Reminders and Todos modules appropriately 5. Nice formatting for reminder display 6. Help text is comprehensive

Issues Found:

1. **Bug in parseAddCommand**: The function tries progressively longer time prefixes, but it doesn't actually validate if the time parses successfully before returning. It just returns the first split where there's at least one message word. This means "hello world test" would return ("hello", "world test") which will fail time parsing later. This is wasteful but not incorrect since the caller handles parse failures.

2. **Potential bug with addHours/addMinutes**: These functions don't handle day rollover correctly. If it's 11pm and you add 3 hours, it will calculate hour 2 (correct) but the day won't change. The LocalTime will have the wrong date. This is a real bug - "in 3 hours" at 11pm will schedule for 2am *the same day* instead of the next day.

3. Hardcoded timezone: easternTimeZone is hardcoded to EST (-300 minutes). This doesn't account for daylight saving time (EDT is -240). The code also duplicates this in Telegram.hs (easternTZ).

4. Minor: The parseAddCommand max 4 words for time is arbitrary and could fail for valid inputs like "next wednesday at 3 pm" (5 words).

Critical Bug Assessment

The relative time parsing bug (#2) is significant - users adding reminders "in X hours" that cross midnight will get incorrect reminder times. This could cause reminders to fire at the wrong time or potentially in the past.

However, the core functionality works for the primary use cases (tomorrow, specific dates, ISO format), and the build/tests pass. This is a legitimate bug but doesn't make the feature fundamentally broken.

Recommendation

The relative time handling bug is a real issue that should be fixed, but the overall implementation is solid and accomplishes the task requirements. The feature is usable for most common scenarios.

REQUEST_CHANGES: The addHours/addMinutes functions in parseRelativeTime don't handle day rollover. When adding hours/minutes that cross midnight, the resulting time will have the wrong date (same day instead of next day). For example, "in 3 hours" at 11pm will incorrectly schedule for 2am of the current day instead of the next day. This should be fixed to properly handle the day transition.

💬[human]1 month ago

CHANGES REQUESTED: ## Code Review: Task t-291 - Telegram reminders: /reminders command

Task Completion Analysis

The task requested:

  • /reminders - List active reminders ✅
  • /reminders add <time> <message> - Add new reminder ✅
  • /reminders delete <id> - Delete a reminder ✅
  • /reminders edit <id> <new message> - Edit reminder text ✅
  • Natural language time parsing ✅
  • Use existing Omni.Agent.Telegram.Reminders module ✅
  • Format output nicely ✅

Code Quality Review

Positives: 1. Clean implementation following existing patterns (mirrors handleOutreachCommand) 2. Good error handling with user-friendly messages 3. Natural language time parsing supports multiple formats 4. Tests added for time parsing 5. Good integration with existing Todos module for persistence 6. Help text is comprehensive

Issues/Concerns:

1. **Bug in parseAddCommand**: The function always returns Just (timeStr, Text.unwords msgWords) on the first iteration where msgWords is non-empty, regardless of whether the time is actually parseable. It should validate that the time parses before returning. Example: /reminders add garbage text here would try to parse "garbage" as a time, which would fail later, but the split logic doesn't consider time validity.

2. **Bug in addHours/addMinutes**: These functions don't handle day rollover. If it's 11pm and you add 3 hours, you get hour 2 of the same day, not the next day. The UTCTime won't be correct.

3. Potential issue with relative time: "in 2 hours" at 11pm will produce wrong results due to the day rollover issue mentioned above.

4. Minor: The parseMonthDayTime doesn't handle year rollover (e.g., setting a reminder for "Jan 5" in late December should probably be next year).

5. Import not used: UTCTime is imported in Telegram.hs but appears to only be used in the type signature of formatReminderTime, which could potentially use the existing import.

Lint/Build/Test Status

  • Lint: Passes (warnings about file size are pre-existing)
  • Build: ✅ Passes
  • Tests: ✅ Pass

Project Conventions

  • Uses import X as Y pattern correctly ✅
  • No TODO/FIXME comments ✅
  • Follows existing code patterns ✅

Summary

The implementation accomplishes the core task requirements and follows project conventions. The build and tests pass. However, there are bugs in the time handling logic: 1. parseAddCommand doesn't validate that the time portion is parseable before deciding where to split 2. addHours/addMinutes don't handle day boundaries correctly, which will cause wrong times for relative time inputs near midnight

These are real bugs that will affect users, particularly the day rollover issue with "in X hours" commands.

🔄[human]InProgress → Done1 month ago