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>
64 lines
2.1 KiB
Go
64 lines
2.1 KiB
Go
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)
|
|
}
|