fix(telegram): grant write to restricted members in default-deny chats
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Successful in 11s
CI / integration (pull_request) Successful in 15s
CI / ui (pull_request) Successful in 57s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m22s
CI / changes (pull_request) Successful in 2s
CI / unit (pull_request) Successful in 11s
CI / integration (pull_request) Successful in 15s
CI / ui (pull_request) Successful in 57s
CI / gate (pull_request) Successful in 0s
CI / deploy (pull_request) Successful in 1m22s
A default-deny discussion group reports a present or freshly joined member as `restricted` (no send right), not `member`. The join filter required `member`, so the real case never matched and a registered user stayed muted. Grant any eligible in-chat member (member or restricted) that still lacks the send right, with a loop guard (skip when send is already allowed) so the bot's own grant does not re-fire. Revoking a now-ineligible user stays the chat-gate path's job, so this never fights a chat_muted/block.
This commit is contained in:
@@ -272,23 +272,36 @@ func (t *Bot) handleChatMember(ctx context.Context, cm *models.ChatMemberUpdated
|
||||
if t.chatID == 0 || cm.Chat.ID != t.chatID {
|
||||
return
|
||||
}
|
||||
// Only a transition into plain membership is a join to evaluate.
|
||||
if cm.NewChatMember.Type != models.ChatMemberTypeMember || cm.OldChatMember.Type == models.ChatMemberTypeMember {
|
||||
return
|
||||
}
|
||||
if user == nil || user.IsBot {
|
||||
return
|
||||
}
|
||||
// (Re)grant write to an eligible user who is in the chat but cannot yet send: a join
|
||||
// into the default-deny chat (where a joined member appears `restricted`, sometimes
|
||||
// `member`) or a restricted member still lacking send rights. A user who can already
|
||||
// send is skipped — which also breaks the feedback loop from the bot's own grant,
|
||||
// since restricting re-fires a chat_member event. Revoking a now-ineligible user is
|
||||
// the chat-gate path's job (an admin block or chat_muted change), not this one.
|
||||
switch cm.NewChatMember.Type {
|
||||
case models.ChatMemberTypeMember:
|
||||
// A plain member follows the chat default; in the gated (default-deny) chat that
|
||||
// denies sending, so (re)grant.
|
||||
case models.ChatMemberTypeRestricted:
|
||||
if cm.NewChatMember.Restricted.CanSendMessages {
|
||||
return // already allowed to send
|
||||
}
|
||||
default:
|
||||
return // left / kicked / administrator / owner — nothing to grant here
|
||||
}
|
||||
if t.eligibility == nil {
|
||||
t.log.Warn("chat join: eligibility resolver not wired", zap.Int64("user_id", uid))
|
||||
t.log.Warn("chat access: eligibility resolver not wired", zap.Int64("user_id", uid))
|
||||
return
|
||||
}
|
||||
eligible, err := t.eligibility(ctx, strconv.FormatInt(user.ID, 10))
|
||||
if err != nil {
|
||||
t.log.Warn("chat join eligibility failed", zap.Int64("user_id", user.ID), zap.Error(err))
|
||||
t.log.Warn("chat access eligibility failed", zap.Int64("user_id", user.ID), zap.Error(err))
|
||||
return
|
||||
}
|
||||
t.log.Info("chat join evaluated", zap.Int64("user_id", user.ID), zap.Bool("eligible", eligible))
|
||||
t.log.Info("chat access evaluated", zap.Int64("user_id", user.ID), zap.Bool("eligible", eligible))
|
||||
if !eligible {
|
||||
return // not registered or blocked: leave muted
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user