When loading room data with admin_user_ids=null in JSON,
the code now properly initializes admin_user_ids to []
instead of incorrectly creating a new RoomData.
Also removed debug logging added during troubleshooting.
- config.py: Added _resolve_bot_token() to read from config file
- bot.py: Uses config.config.bot_token instead of env var directly
- test_config.py: Added test for config file token reading
- Add /recover command for listing and recovering soft-deleted bounties
- /recover - list recoverable bounties (admin only)
- /recover <id> [<id>...] - recover specific bounties (admin only)
- Fix /admin list to show @username instead of admin_id
- Add recover_bounty and recover_bounties methods to BountyService
- Add get_deleted_bounty method to BountyService
- Clean up duplicate cmd_admin functions
- Add /recover to bot command menu
- Fixes#49 and #50
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