feat: add NFT usernames and bot verification (#22)

Implements collectible usernames, official verification workflows, and third-party bot verification after maintainer protocol and migration review.

The composite activity/moderation rating remains an admin-only read model; Telegram Stars Rating wire fields stay unset pending a dedicated official-semantics implementation.

Reviewed-Head: 2796345775ea0f908fb7734601e5e1dee4b653b9
Original-Head: fa082b892fd5180c9c9bc53c81c21cf5d250a75b

Co-authored-by: Egor Egorov <business.egor.sg@gmail.com>
This commit is contained in:
Egor Egorov 2026-07-27 20:18:00 +03:00 • committed by GitHub
parent b0fd3976f1
commit fff8de783a
No known key found for this signature in database
GPG key ID: B5690EEEBB952194
169 changed files with 55769 additions and 282 deletions

View file

@ -116,7 +116,7 @@ func (r *Router) onChannelsGetChannels(ctx context.Context, ids []tg.InputChanne
chats = append(chats, tgChannelChatForView(userID, view))
}
}
r.applyStoryMaxIDsToPeerObjects(ctx, userID, nil, chats)
r.applyPeerReadModels(ctx, userID, nil, chats)
return &tg.MessagesChats{Chats: chats}, nil
}
@ -172,11 +172,12 @@ func (r *Router) onChannelsGetFullChannel(ctx context.Context, input tg.InputCha
r.applyStarGiftsCountToChannelFull(ctx, ref.ID, &full)
r.applyStoriesPinnedAvailableToChannelFull(ctx, userID, ref.ID, &full)
r.applyNotifySettingsToChannelFull(ctx, userID, ref.ID, &full)
r.applyBotVerificationToChannelFull(ctx, ref.ID, &full)
r.applyAndroidChannelReactionEditorCompat(ctx, &full, cached.canChangeInfo)
chats := append([]tg.ChatClass(nil), cached.chats...)
chats = r.appendLinkedDiscussionChat(ctx, userID, ref.ID, chats)
r.trackChannelInterest(ctx, userID, ref.ID)
r.applyStoryMaxIDsToPeerObjects(ctx, userID, nil, chats)
r.applyPeerReadModels(ctx, userID, nil, chats)
return &tg.MessagesChatFull{
FullChat: &full,
Chats: chats,
@ -220,8 +221,11 @@ func (r *Router) onChannelsGetFullChannel(ctx context.Context, input tg.InputCha
}
r.applyStoriesPinnedAvailableToChannelFull(ctx, userID, view.Channel.ID, full)
r.applyNotifySettingsToChannelFull(ctx, userID, view.Channel.ID, full)
// After StoreIfEpoch on purpose: the mark stays out of the per-(viewer,channel)
// projection cache so a revoked badge cannot outlive the change by a cache TTL.
r.applyBotVerificationToChannelFull(ctx, view.Channel.ID, full)
r.applyAndroidChannelReactionEditorCompat(ctx, full, canChangeInfo)
r.applyStoryMaxIDsToPeerObjects(ctx, userID, nil, chats)
r.applyPeerReadModels(ctx, userID, nil, chats)
return &tg.MessagesChatFull{
FullChat: full,
Chats: chats,