75 lines
2.2 KiB
Go
75 lines
2.2 KiB
Go
package userprojection
|
|
|
|
import (
|
|
"context"
|
|
|
|
"telesrv/internal/domain"
|
|
"telesrv/internal/store"
|
|
)
|
|
|
|
// ForViewer applies the owner-specific user view that Telegram clients expect.
|
|
// In particular, phone is visible for self and contacts; non-contacts should not
|
|
// receive a phone field because TDesktop will prefer it over the public name.
|
|
func ForViewer(ctx context.Context, contacts store.ContactStore, viewerUserID int64, users []domain.User) ([]domain.User, error) {
|
|
if contacts == nil || viewerUserID == 0 || len(users) == 0 {
|
|
return users, nil
|
|
}
|
|
out := make([]domain.User, len(users))
|
|
copy(out, users)
|
|
cache := make(map[int64]domain.User, len(users))
|
|
for i := range out {
|
|
u := out[i]
|
|
if u.ID == 0 || u.ID == viewerUserID || u.ID == domain.OfficialSystemUserID {
|
|
continue
|
|
}
|
|
if projected, ok := cache[u.ID]; ok {
|
|
out[i] = projected
|
|
continue
|
|
}
|
|
projected, err := projectOne(ctx, contacts, viewerUserID, u)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
cache[u.ID] = projected
|
|
out[i] = projected
|
|
}
|
|
return out, nil
|
|
}
|
|
|
|
// One applies ForViewer to a single user.
|
|
func One(ctx context.Context, contacts store.ContactStore, viewerUserID int64, user domain.User) (domain.User, error) {
|
|
projected, err := ForViewer(ctx, contacts, viewerUserID, []domain.User{user})
|
|
if err != nil || len(projected) == 0 {
|
|
return domain.User{}, err
|
|
}
|
|
return projected[0], nil
|
|
}
|
|
|
|
func projectOne(ctx context.Context, contacts store.ContactStore, viewerUserID int64, user domain.User) (domain.User, error) {
|
|
contact, found, err := contacts.Get(ctx, viewerUserID, user.ID)
|
|
if err != nil {
|
|
return domain.User{}, err
|
|
}
|
|
if !found {
|
|
user.Phone = ""
|
|
user.Contact = false
|
|
user.Mutual = false
|
|
return user, nil
|
|
}
|
|
projected := user
|
|
projected.Contact = true
|
|
projected.Mutual = contact.Mutual || contact.User.Mutual
|
|
if contact.User.Phone != "" {
|
|
projected.Phone = contact.User.Phone
|
|
} else {
|
|
projected.Phone = contact.Phone
|
|
}
|
|
if contact.User.FirstName != "" || contact.User.LastName != "" {
|
|
projected.FirstName = contact.User.FirstName
|
|
projected.LastName = contact.User.LastName
|
|
} else if contact.FirstName != "" || contact.LastName != "" {
|
|
projected.FirstName = contact.FirstName
|
|
projected.LastName = contact.LastName
|
|
}
|
|
return projected, nil
|
|
}
|