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
64
internal/rpc/username_notify.go
Normal file
64
internal/rpc/username_notify.go
Normal file
|
|
@ -0,0 +1,64 @@
|
|||
package rpc
|
||||
|
||||
import (
|
||||
"context"
|
||||
"fmt"
|
||||
|
||||
"telesrv/internal/domain"
|
||||
)
|
||||
|
||||
// NotifyPeerUsernamesChanged is the domain-only edge hook invoked after a
|
||||
// collectible username registry mutation commits. It invalidates the cached
|
||||
// peer projection and pushes the ordinary non-PTS updateUser/updateChannel
|
||||
// refresh to online viewers. The shared projection paths preload the registry
|
||||
// once, so fan-out cannot turn the change into an N+1 query.
|
||||
func (r *Router) NotifyPeerUsernamesChanged(ctx context.Context, peer domain.Peer) error {
|
||||
if r == nil {
|
||||
return nil
|
||||
}
|
||||
if peer.ID <= 0 {
|
||||
return fmt.Errorf("notify peer usernames changed: invalid peer id %d", peer.ID)
|
||||
}
|
||||
switch peer.Type {
|
||||
case domain.PeerTypeUser:
|
||||
return r.notifyUserUsernamesChanged(ctx, peer.ID)
|
||||
case domain.PeerTypeChannel:
|
||||
return r.notifyChannelUsernamesChanged(ctx, peer.ID)
|
||||
default:
|
||||
return fmt.Errorf("notify peer usernames changed: unsupported peer type %q for peer %d", peer.Type, peer.ID)
|
||||
}
|
||||
}
|
||||
|
||||
func (r *Router) notifyUserUsernamesChanged(ctx context.Context, userID int64) error {
|
||||
r.invalidateRPCProjectionForUser(userID)
|
||||
if r.deps.Users == nil {
|
||||
return nil
|
||||
}
|
||||
user, found, err := r.verificationUser(ctx, userID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("notify peer usernames changed: load user %d: %w", userID, err)
|
||||
}
|
||||
if !found || user.ID == 0 {
|
||||
return fmt.Errorf("notify peer usernames changed: user %d not found", userID)
|
||||
}
|
||||
return r.NotifyUserModerationFlagsChanged(ctx, user)
|
||||
}
|
||||
|
||||
func (r *Router) notifyChannelUsernamesChanged(ctx context.Context, channelID int64) error {
|
||||
r.invalidateRPCProjectionForChannel(channelID)
|
||||
if r.deps.Channels == nil {
|
||||
return nil
|
||||
}
|
||||
directory, ok := r.deps.Channels.(verificationChannelDirectory)
|
||||
if !ok {
|
||||
return fmt.Errorf("notify peer usernames changed: channel service does not expose GetChannelByID")
|
||||
}
|
||||
channel, err := directory.GetChannelByID(ctx, channelID)
|
||||
if err != nil {
|
||||
return fmt.Errorf("notify peer usernames changed: load channel %d: %w", channelID, err)
|
||||
}
|
||||
if channel.ID == 0 {
|
||||
return fmt.Errorf("notify peer usernames changed: channel %d not found", channelID)
|
||||
}
|
||||
return r.NotifyChannelChanged(ctx, channel)
|
||||
}
|
||||
Loading…
Add table
Add a link
Reference in a new issue