Skip to content

Implement plans/01: cache cap + RetryAfter helper + handler refactor + /status command#22

Merged
rezhajulio merged 15 commits into
mainfrom
improvement/bot-recommendations
Jul 6, 2026
Merged

Implement plans/01: cache cap + RetryAfter helper + handler refactor + /status command#22
rezhajulio merged 15 commits into
mainfrom
improvement/bot-recommendations

Conversation

@rezhajulio

@rezhajulio rezhajulio commented Jul 6, 2026

Copy link
Copy Markdown
Owner

Summary

Implements Phases 1a, 1b, 3, and 4 from plans/01-bot-improvement-recommendations.md.

Changes

  • 1a — Cap unbounded RECENT_MESSAGES_KEY in duplicate_spam.py (mirror of bio_bait USER_BIO_CACHE_MAX_SIZE pattern); new eviction tests
  • 1bsend_message_with_retry + restrict_chat_member_with_retry in telegram_utils.py; applied to 4 multi-group broadcast sites (handlers/check.py, handlers/dm.py, handlers/bio_bait.py, services/scheduler.py); handles both int and timedelta RetryAfter.retry_after
  • Phase 3 — Extracted helpers from 5 complex handlers: _unrestrict_in_groups (dm), guard-clause predicates (anti_spam, message, check), bio_bait tail; behavior-preserving
  • Phase 4 — New DM-admin /status command: uptime, per-group plugin toggles, probation/captcha counts, DB size, last job timestamps; stamps last_admin_refresh / last_auto_restrict on real work

Verification

  • 965 tests pass (was 947; +18 new)
  • Coverage 99% (30 missed statements; was 22 baseline)
  • ruff clean, mypy clean

Multi-Model Review

Reviewed by 3 agents (correctness, reliability, maintainability). Applied:

  • Inline premature _should_skip_profile_check predicate
  • Track processed_any to skip false stamp on no-op auto-restrict cycle
  • logger.warning for missing message in status handler
  • Drop dead group_titles read in status

Skipped (test additions for NIT findings; defer to follow-up):

  • Direct unit tests for _should_skip_* predicates
  • Coverage for status.py "never" / "N/A" branches
  • last_admin_refresh not-stamped-on-all-fail test
  • Watermark tuning for duplicate_spam eviction

Phase 5 (Dockerfile HEALTHCHECK) skipped per plan — low value for polling bot.

rezhajulio added 13 commits July 6, 2026 15:33
Behavior-preserving readability refactor with zero test changes:

1. bio_bait.py: extract enforce delete+restrict+notify into
   _enforce_bio_bait_restriction() — parent raises ApplicationHandlerStop
2. dm.py: extract unrestrict loop into _unrestrict_in_groups()
   returning success count — parent handles response messages
3. anti_spam.py: extract guard clauses into
   _should_skip_new_user_spam_check() predicate
4. message.py: extract is_bot guard into
   _should_skip_profile_check() predicate
5. check.py: extract callback data parsing into
   _parse_warn_callback_data() returning (user_id, missing_code) or None

All 948 tests pass, coverage 99% (22 missed, unchanged).
Ruff + mypy clean.
…r_with_retry

- Two helpers in telegram_utils.py: RetryAfter-aware wrappers that sleep
  + retry once, return False on second RetryAfter, re-raise other errors
- unrestrict_user uses restrict_chat_member_with_retry internally
- 4 call sites updated: check.py handle_warn_callback, scheduler.py
  auto-restrict loop, dm.py unrestrict loop, bio_bait.py monitor alert
- 8 unit tests for helpers, 2 integration tests for bio_bait error paths
- 958 tests pass, 99% coverage, ruff clean, mypy clean

ponytail: scheduler.py RetryAfter-fallback continue (lines 95-98) not
covered by tests; add scheduler-level RetryAfter test if it becomes a
real problem.
…ct stamp on real work

Applies multi-model review feedback:
- Remove premature-abstraction _should_skip_profile_check predicate (M1)
- Track processed_any in auto_restrict to skip stamp on no-op cycles (R3)
- Add logger.warning for missing message/from_user in status handler (C3)
- Drop group_titles read; use str(gid) directly (M2, M6)
Plan docs are working notes for a session, not source. Untrack the one
that snuck into the improvement branch's history.
- verify.py: catch RuntimeError from unrestrict_user retry exhaustion;
  wrap clearance notification with send_message_with_retry
- bio_bait.py: wrap enforcement path (restrict + notify) with retry helpers
  (the monitor-only alert path was already wrapped)
- scheduler.py: stamp last_auto_restrict unconditionally on every successful
  run (matches admin_cache behavior)
- telegram_utils.py: cap retry sleep at 30s to prevent one bad RetryAfter
  from stalling per-group loop for a minute-plus
- status.py: drop dead title variable (was duplicating group_id)
@rezhajulio

Copy link
Copy Markdown
Owner Author

Pushed additional fixes from reviewer feedback (commit 3f7d33a):

  • verify.py: catch RuntimeError from unrestrict_user retry exhaustion (was falling through to outer except Exception: continue, skipping delete_user_warnings + clearance notification). Wrap clearance notification with send_message_with_retry.
  • bio_bait.py: wrap the enforcement path (restrict_chat_member + warning-topic notification) with retry helpers — only the monitor-only alert path was wrapped before. The enforcement path is the more consequential one.
  • scheduler.py: stamp last_auto_restrict unconditionally on every successful run, matching admin_cache.py behavior. Stamping only on processed_any made /status show 'never' whenever there were zero expired warnings — indistinguishable from the job being dead.
  • telegram_utils.py: cap retry sleep at 30s via _clamped_retry_seconds helper. Without this, one bad RetryAfter could stall a per-group loop for a minute-plus per group.
  • status.py: dropped dead title variable that was duplicating group_id in the per-group output.

title = str(gid) just re-stringified the same group_id with nothing else
feeding it (GroupConfig has no name/title field), so each group line
printed the ID twice: `-100123` — -100123. Show it once.
@rezhajulio rezhajulio merged commit 2fc9b5c into main Jul 6, 2026
5 checks passed
@rezhajulio rezhajulio deleted the improvement/bot-recommendations branch July 6, 2026 14:09
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment

Labels

None yet

Projects

None yet

Development

Successfully merging this pull request may close these issues.

1 participant