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:
parent
b0fd3976f1
commit
fff8de783a
169 changed files with 55769 additions and 282 deletions
|
|
@ -27,7 +27,6 @@ func tgSelfUser(u domain.User) *tg.User {
|
|||
Contact: u.Contact,
|
||||
MutualContact: u.Mutual,
|
||||
CloseFriend: u.CloseFriend,
|
||||
Usernames: tgUsernames(u.Username),
|
||||
}
|
||||
applyTgUserBotFields(out, u)
|
||||
applyTgUserPremiumFields(out, u)
|
||||
|
|
@ -60,7 +59,6 @@ func tgUser(u domain.User) *tg.User {
|
|||
Contact: u.Contact,
|
||||
MutualContact: u.Mutual,
|
||||
CloseFriend: u.CloseFriend,
|
||||
Usernames: tgUsernames(u.Username),
|
||||
}
|
||||
applyTgUserBotFields(out, u)
|
||||
applyTgUserPremiumFields(out, u)
|
||||
|
|
@ -240,6 +238,9 @@ func tgUserStatus(status domain.UserStatus) tg.UserStatusClass {
|
|||
return &tg.UserStatusRecently{}
|
||||
}
|
||||
|
||||
// tgUsernames builds the vector carried by updateUserName. Ordinary user/channel
|
||||
// constructors keep using their scalar username until at least one collectible
|
||||
// is associated with the peer.
|
||||
func tgUsernames(username string) []tg.Username {
|
||||
if username == "" {
|
||||
return nil
|
||||
|
|
@ -247,6 +248,45 @@ func tgUsernames(username string) []tg.Username {
|
|||
return []tg.Username{{Editable: true, Active: true, Username: username}}
|
||||
}
|
||||
|
||||
// tgUsernamesFromRegistry is the single builder of the full username#b4073647
|
||||
// vector in stored order (see domain.SortUsernames), with editable/active taken
|
||||
// from the registry row rather than assumed.
|
||||
//
|
||||
// It degrades to tgUsernames(fallback) whenever the registry contributed nothing
|
||||
// usable, which is what keeps a missing/failing registry service byte-identical
|
||||
// to the pre-collectible wire shape.
|
||||
func tgUsernamesFromRegistry(list []domain.Username, fallback string) []tg.Username {
|
||||
if len(list) == 0 {
|
||||
return tgUsernames(fallback)
|
||||
}
|
||||
sorted := domain.SortUsernames(list)
|
||||
out := make([]tg.Username, 0, len(sorted))
|
||||
for _, item := range sorted {
|
||||
name := domain.NormalizeUsername(item.Username)
|
||||
if name == "" {
|
||||
continue
|
||||
}
|
||||
out = append(out, tg.Username{
|
||||
Editable: item.Editable,
|
||||
Active: item.Active,
|
||||
Username: name,
|
||||
})
|
||||
}
|
||||
if len(out) == 0 {
|
||||
return tgUsernames(fallback)
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
func hasCollectibleUsername(list []domain.Username) bool {
|
||||
for _, item := range list {
|
||||
if item.Collectible() {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func tgContacts(list domain.ContactList) tg.ContactsContactsClass {
|
||||
out := &tg.ContactsContacts{
|
||||
Contacts: make([]tg.Contact, 0, len(list.Contacts)),
|
||||
|
|
|
|||
Loading…
Add table
Add a link
Reference in a new issue