Skip to content

Change /unmute command so that the exception on permissions is dropped#52

Open
keobox wants to merge 1 commit into
pythonitalia:masterfrom
keobox:fix_stale_users
Open

Change /unmute command so that the exception on permissions is dropped#52
keobox wants to merge 1 commit into
pythonitalia:masterfrom
keobox:fix_stale_users

Conversation

@keobox

@keobox keobox commented Jun 4, 2026

Copy link
Copy Markdown

Why

I've 4 stale users sitting in a muted state forever in the @PythonMilano telegram channel.

Behavior

I'm experiencing This.
The captcha for new user maybe was not displayed, but for sure is not displayed if a user leave the group and then tries to subscribe again.
New users are subscribed but muted meaning that the default permission are overridden by exceptions for them. I suspect that the exception are not cleared from the bot database once a user unsubscribe. Another bug is that the /unmute command does not remove the exception, the result looks like a user is muted forever.

How to test it

In the https://t.me/PythonMilano there are currently 4 stale users, I know this people personally and I want to un-mute them even if they do not clicked the captcha.

@MattiaFailla MattiaFailla self-requested a review June 4, 2026 17:05
Comment on lines -365 to -367
can_change_info=False,
can_change_info=True,
can_invite_users=True,
can_pin_messages=False,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Pinning messages and changing group-related info are not privileges granted to normal users: I'd revert this change.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

This will re-introduce the bug

  • restrictChatMember with can_pin_messages=True does NOT mean "this user can pin messages." It means "remove the per-user restriction on this permission" the user falls back to group defaults.
  • restrictChatMember with can_pin_messages=False means "explicitly restrict this user from pinning, regardless of group defaults."

This creates/keeps a per-user exception.

The Telegram Bot API docs are explicit:
"Pass True for all permissions to lift restrictions from a user."

If even one permission is False, Telegram keeps the per-user restriction record which is exactly the bug we're seeing (users appear restricted in the member list, /unmute "succeeds" but changes nothing visible).

See https://core.telegram.org/bots/api#restrictchatmember

Comment on lines +135 to +137
can_change_info=True,
can_invite_users=True,
can_pin_messages=False,
can_pin_messages=True,

Copy link
Copy Markdown
Member

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Must be reverted in here too.

Copy link
Copy Markdown
Author

Choose a reason for hiding this comment

The reason will be displayed to describe this comment to others. Learn more.

Same as above comment.

MattiaFailla added a commit that referenced this pull request Jun 17, 2026
… on rejoin

Stale users sat muted forever in public supergroups for two reasons:

1. On rejoin, _handle_new_member re-restricted the user and re-added the
   pending row, then returned early at the has_been_welcomed() guard before
   sending the captcha. The user was silently muted with no way to verify,
   because no LEFT/KICKED handler ever cleared the per-chat welcome state.

2. /unmute only deletes from the mutes table, but stale users were restricted
   by the captcha flow (pending_verifications), so /unmute never cleared their
   "exception".

Changes:
- Add a departure branch to _handle_new_member: on LEFT/BANNED, clear the
  welcomed + pending state for that (user, chat) so a genuine rejoin re-shows
  the captcha. Global verification is intentionally preserved.
- Add /unlock @handle: an admin command that globally verifies a stuck user,
  clears pending state, and restores send permissions in their pending chats.
  Kept distinct from /unmute, which stays a pure moderation-mute reversal.
- Add Repository.remove_welcomed (in-memory + postgres) and CaptchaService
  wrappers (remove_welcomed, remove_pending).

Deliberately did NOT flip can_change_info / can_pin_messages to True (as
proposed in #52). Per the Telegram Bot API docs those fields are "Ignored in
public supergroups", so the flip is a no-op there and a latent privilege
escalation in any private supergroup, and it is unrelated to the mute itself
(which is can_send_messages=False).

Tests: /unlock (admin / non-admin / private chat / restored permissions) and
rejoin state-clearing (LEFT, BANNED, global-verification preserved).
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.

2 participants