Re-implement the timezone command that was reverted.
- Add cmd_timezone function with get/set functionality
- Validate timezone using zoneinfo (IANA format)
- Admin-only permission via service layer
- Update help text and bot command list
- Fix indentation bug in cmd_add (duplicate lines)
Fixes#53
This reverts:
- cmd_timezone function (issue #67)
- format_due_date with human-readable dates (issue #68)
- Reverts date display back to time.strftime("%Y-%m-%d")
- Keeps /edit command with -link/-date flags (issue #46)
- Add format_due_date() function that formats dates as '4 April 2026'
or '4 April 2026 14:30 (Asia/Jakarta)' with timezone support
- Update format_bounty() to use timezone-aware date formatting
- Update cmd_bounty, cmd_my, cmd_add to pass room_id for timezone
- Dates now display in room's configured timezone
- Fixes#54
- Add cmd_timezone handler for /timezone command
- Validate timezone using IANA format (zoneinfo.ZoneInfo)
- Use existing BountyService.get_timezone and set_timezone methods
- Admin-only permission via service layer
- Update help text and bot command list
- Fixes#53
- Default shows 5 bounties per page
- /bounty 10 - show 10 bounties
- /bounty all - show all active (exclude overdue >24h)
- /bounty all 10 - show 10 including expired
Filtering:
- Overdue >24h filtered out by default
- 'all' flag includes overdue
Sorting:
- Bounties with due date sorted by due_date_ts (earliest first)
- Bounties without due date shown last, sorted by created_at
Output format updated:
- Header shows 'Showing X of Y bounties'
- Description sliced to 40 chars when showing pagination info
- Date format changed to '4 Apr 2026' style
Fixes#48
- Add -link and -date flags to /edit command for field clearing
- /edit <id> -link - clear link
- /edit <id> -date - clear date
- /edit <id> -link <url> - set link
- /edit <id> -date <date> - set date
- /edit <id> text -link - update text, clear link
- /edit <id> text <url> - update text and set link
- Parse_args now returns (text, link, due_date_ts, clear_link, clear_date)
- Update usage messages and help text
- Fixes#46
- Add cmd_show function to display bounty details including:
- ID and full text (not sliced)
- Link if exists
- Due date formatted with room timezone
- Created by username
- Created at timestamp
- Register show command handler in bot.py
- Add show command to help text and bot command list
- Fixes#44
Add filtering methods to JsonFileRoomStorage for Phase 2 soft delete support:
- list_bounties(room_id): returns only non-deleted bounties for normal queries
- list_all_bounties(room_id, include_deleted=True): returns all bounties for /recover
Update RoomStorage protocol to include the new methods.
Update mock classes in tests to pass isinstance checks.
Fixes#42
Issue #41: Model updates for Phase 2 features
Bounty model:
- Add deleted_at: int | None - timestamp when deleted (soft-delete)
- Add created_by_username: str | None - username for display purposes
RoomData model:
- Add timezone: str | None - room's timezone (e.g., "Asia/Jakarta")
- Add admin_user_ids: list[int] - list of admin user IDs
Storage adapter updated to handle new fields in load/save operations.
Tests added for new fields.
Add tests/__init__.py to make tests/ a proper Python package,
enabling cross-imports between test modules (e.g., test_services
importing from test_ports).
All 145 tests pass:
- tests/: 90 tests
- apps/telegram-bot/tests/: 55 tests
- Delete apps/telegram-bot/storage.py (replaced by adapters/storage/json_file.py)
- Delete apps/telegram-bot/__init__.py (empty file)
- Delete apps/telegram-bot/requirements-dev.txt (dev deps in pyproject.toml)
- Update SPEC.md with new hexagonal architecture (core, adapters, apps)
- Update SPEC.md command reference: /update -> /edit
- Update README.md with new project structure and quick start
- Update CONTRIBUTING.md with new architecture and dev setup
- Add cmd_edit as alias for cmd_update
- Update bot.py to import commands directly instead of via module
- Register /edit command in bot and post_init commands list
- Clean up unused imports in bot.py
Fixes#14
- Tests mock dependencies and verify command existence, flag processing, and output format
- Tests use --group-id=-1001 format (equals sign) to avoid argparse treating -1001 as a flag
- All 17 tests passing
Add comprehensive unit tests for all command handlers:
- TestHelperFunctions: is_group, get_group_id, get_user_id, get_room_id
- TestCmdBounty: lists bounties, handles empty
- TestCmdMy: shows tracked in groups, personal in DM
- TestCmdAdd: add bounty success, validation
- TestCmdUpdate: update bounty, permission denied, invalid ID
- TestCmdDelete: delete bounty, invalid ID
- TestCmdTrack: track in group, reject in DM
- TestCmdUntrack: untrack in group, reject in DM
- TestCmdStart: group vs DM behavior
- TestCmdHelp: shows all commands
Also fix conftest.py to remove obsolete fresh_db fixture
that referenced non-existent db module.
All 55 tests pass.
Addresses han's feedback on PR #33
Create cli/main.py with the following commands:
- add <text> [--link url] [--due date] - Add a new bounty
- list - List all bounties in room
- my - List tracked bounties for user
- update <id> [text] [--link url] [--due date] [--clear-link] [--clear-due]
- delete <id> - Delete a bounty
- track <id> - Track a bounty
- untrack <id> - Untrack a bounty
Context flags:
- --group-id <id> - Group context
- --user-id <id> - User context
Requires either --group-id or --user-id for all commands.
Fixes#11
- Add tests/test_json_file.py with unit tests for JsonFileRoomStorage and JsonFileTrackingStorage
- Reorganize data directories per han's feedback:
- Rooms: ~/.jigaido/data/room/<room_id>.json (was ~/.jigaido/data/<room_id>.json)
- Tracking: ~/.jigaido/data/tracking/<room_id>_<user_id>.json (was ~/.jigaido/tracking/...)
- Note: duplicate tracking is handled at TrackingService layer (returns False if already tracking), adapter allows duplicates by design