Add AI spam monitoring via classifier.dev (monitor-only) - #36
Open
rezhajulio wants to merge 3 commits into
Open
rezhajulio wants to merge 3 commits into
rezhajulio wants to merge 3 commits into
Conversation
New ai_spam_monitor plugin registers two handlers: - Message handler at group=7 (highest group) so only messages that survived every enforcement handler get classified; runs as a background task so the update pipeline never awaits the network - Callback handler at group=0 for admin action buttons on alerts services/classifier_client.py wraps the free classifier.dev zero-shot API with a circuit breaker (3 failures -> 10 min cooldown) and a daily budget (default 15k, reset at midnight WIB) so a dead or rate-limited upstream fails soft instead of hammering per message. High-confidence results alert the per-group ai_spam_alert_chat_id (private admin group or DM) with buttons: delete, delete+restrict, delete+ban, dismiss. Profile metadata (photo/username) is fetched locally for the alert only and never sent to the API. No auto-enforcement, no UserWarning records, no ApplicationHandlerStop. Per-group gating via guard_plugin (ai_spam_monitor / ai_spam_callback); both new modules at 100% test coverage with Hypothesis property tests for the breaker and budget logic.
- Use the module-level circuit breaker as the single source of truth: the in-task re-check read a bot_data CircuitState nothing wrote to, so it never fired; classifier_cooldown_seconds is now honored at both gate points - Build alert mentions as plain text: get_user_mention returns Markdown, which rendered literally in alerts sent without parse_mode - Answer the callback query once; the edit-failure fallback answered an already-answered query, so the admin never saw it - Drop the hardcoded httpx client timeout so classifier_timeout_seconds is the single timeout knob; correct the breaker cooldown docstring
A single long-lived client with a bounded pool cannot leak in production, but leaving it open emitted asyncio unclosed-session warnings on shutdown. Add post_shutdown hook that closes the shared client; tests now close it via an async fixture.
This file contains hidden or bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
Sign up for free
to join this conversation on GitHub.
Already have an account?
Sign in to comment
Add this suggestion to a batch that can be applied as a single commit.This suggestion is invalid because no changes were made to the code.Suggestions cannot be applied while the pull request is closed.Suggestions cannot be applied while viewing a subset of changes.Only one suggestion per line can be applied in a batch.Add this suggestion to a batch that can be applied as a single commit.Applying suggestions on deleted lines is not supported.You must change the existing code in this line in order to create a valid suggestion.Outdated suggestions cannot be applied.This suggestion has been applied or marked resolved.Suggestions cannot be applied from pending reviews.Suggestions cannot be applied on multi-line comments.Suggestions cannot be applied while the pull request is queued to merge.Suggestion cannot be applied right now. Please check back later.
Summary
Adds a monitor-only AI spam layer using the free classifier.dev zero-shot classification API, positioned as the last defense: a message handler at PTB group 7 only classifies messages that survived every existing enforcement handler (all of which raise
ApplicationHandlerStopafter acting).context.application.create_task); the update pipeline never awaits the networkai_spam_alert_chat_id(private admin group or DM) with inline buttons — Hapus pesan / Abaikan / Hapus + batasi / Hapus + ban. The bot itself never deletes, restricts, or warns; the warning topic is never touchedgroup_id(aispam:{action}:{group_id}:{user_id}:{message_id}) and verify the clicker viais_user_admin_in_groupon that groupcheck_user_profilefor the alert text only✔ Ditangani oleh @admin); dedup keeps one alert per(group_id, message_id)parse_modeto avoid Markdown injection from quoted message content)Test plan
ruff checkandmypy src/bot/ tests/cleanmain.post_shutdownhook