Read user profile display from profile table

This commit is contained in:
richjohnrambo
2026-09-04 10:49:33 +08:00
parent 3173313ab9
commit 62af772260
3 changed files with 146 additions and 28 deletions
+102 -19
View File
@@ -47,6 +47,83 @@ func stampTenantUser(id t.TenantID, user *t.User) *t.User {
return user
}
type profileUserRow struct {
TenantID t.TenantID `db:"tenant_id"`
ID string `db:"id"`
UpdatedAt time.Time `db:"updatedat"`
State t.ObjState `db:"state"`
Access t.DefaultAccess
LastSeen sql.NullTime `db:"lastseen"`
UserAgent string `db:"useragent"`
Public any `db:"public"`
Trusted any `db:"trusted"`
ProfileNickname sql.NullString `db:"profile_nickname"`
ProfileAvatarFileID sql.NullString `db:"profile_avatar_file_id"`
ProfileUpdatedAt sql.NullTime `db:"profile_updated_at"`
}
func (row profileUserRow) effectiveUpdatedAt() time.Time {
if row.ProfileUpdatedAt.Valid {
return common.SelectLatestTime(row.UpdatedAt, row.ProfileUpdatedAt.Time)
}
return row.UpdatedAt
}
func (row profileUserRow) lastSeen() *time.Time {
if row.LastSeen.Valid {
return &row.LastSeen.Time
}
return nil
}
func (row profileUserRow) profilePublic() any {
return profilePublicFromFields(common.FromJSON(row.Public), row.ProfileNickname, row.ProfileAvatarFileID)
}
func profilePublicFromFields(base any, nickname, avatarFileID sql.NullString) any {
public := publicMap(base)
if nickname.Valid {
value := strings.TrimSpace(nickname.String)
for _, key := range []string{"display_name", "nickname", "fn", "name"} {
if value == "" {
delete(public, key)
} else {
public[key] = value
}
}
}
if avatarFileID.Valid {
value := strings.TrimSpace(avatarFileID.String)
for _, key := range []string{"avatar_file_id", "photo", "avatar"} {
if value == "" {
delete(public, key)
} else if key == "avatar_file_id" {
public[key] = value
}
}
}
return public
}
func publicMap(value any) map[string]any {
switch public := value.(type) {
case map[string]any:
out := make(map[string]any, len(public))
for key, val := range public {
out[key] = val
}
return out
case map[string]string:
out := make(map[string]any, len(public))
for key, val := range public {
out[key] = val
}
return out
default:
return map[string]any{}
}
}
func stampTenantUsers(id t.TenantID, users []t.User) []t.User {
for i := range users {
users[i].TenantID = id
@@ -870,10 +947,12 @@ func (a *adapter) TenantTopicsForUser(id t.TenantID, uid t.Uid, keepDeleted bool
}
}
if len(usrq) > 0 {
q = "SELECT tenant_id,id,updatedat,state,access,lastseen,useragent,public,trusted FROM im_users WHERE tenant_id=? AND id IN (?)"
q = `SELECT u.tenant_id,u.id,u.updatedat,u.state,u.access,u.lastseen,u.useragent,u.public,u.trusted,
p.nickname AS profile_nickname,p.avatar_file_id AS profile_avatar_file_id,p.updated_at AS profile_updated_at
FROM im_users AS u LEFT JOIN im_user_profiles AS p ON p.user_id=u.id WHERE u.tenant_id=? AND u.id IN (?)`
q, args, _ = sqlx.In(q, id, usrq)
if !keepDeleted {
q += " AND state!=?"
q += " AND u.state!=?"
args = append(args, t.StateDeleted)
}
rows, err = a.db.QueryxContext(ctx, a.db.Rebind(q), args...)
@@ -881,19 +960,19 @@ func (a *adapter) TenantTopicsForUser(id t.TenantID, uid t.Uid, keepDeleted bool
return nil, err
}
for rows.Next() {
var user t.User
var user profileUserRow
if err = rows.StructScan(&user); err != nil {
rows.Close()
return nil, err
}
joinOn := uid.P2PName(common.EncodeUidString(user.Id))
joinOn := uid.P2PName(common.EncodeUidString(user.ID))
if sub, ok := join[joinOn]; ok {
sub.UpdatedAt = common.SelectLatestTime(sub.UpdatedAt, user.UpdatedAt)
sub.UpdatedAt = common.SelectLatestTime(sub.UpdatedAt, user.effectiveUpdatedAt())
sub.SetState(user.State)
sub.SetPublic(common.FromJSON(user.Public))
sub.SetPublic(user.profilePublic())
sub.SetTrusted(common.FromJSON(user.Trusted))
sub.SetDefaultAccess(user.Access.Auth, user.Access.Anon)
sub.SetLastSeenAndUA(user.LastSeen, user.UserAgent)
sub.SetLastSeenAndUA(user.lastSeen(), user.UserAgent)
join[joinOn] = sub
}
}
@@ -8791,7 +8870,8 @@ func (a *adapter) TenantFriendshipList(id t.TenantID, uid t.Uid, queryText, init
if cancel != nil {
defer cancel()
}
rows, err := a.db.QueryxContext(ctx, `SELECT fs.*,u.public,u.trusted
rows, err := a.db.QueryxContext(ctx, `SELECT fs.*,u.public,u.trusted,
p.nickname AS profile_nickname,p.avatar_file_id AS profile_avatar_file_id,p.updated_at AS profile_updated_at
FROM im_friendships AS fs
JOIN im_users AS u ON u.id=fs.peer_id
LEFT JOIN im_user_profiles AS p ON p.user_id=u.id
@@ -8805,16 +8885,19 @@ func (a *adapter) TenantFriendshipList(id t.TenantID, uid t.Uid, queryText, init
nextCursor := ""
for rows.Next() {
row := struct {
ID int64
UserID int64 `db:"user_id"`
PeerID int64 `db:"peer_id"`
Status string
Remark string
Topic string
CreatedAt time.Time `db:"created_at"`
UpdatedAt time.Time `db:"updated_at"`
Public any
Trusted any
ID int64
UserID int64 `db:"user_id"`
PeerID int64 `db:"peer_id"`
Status string
Remark string
Topic string
CreatedAt time.Time `db:"created_at"`
UpdatedAt time.Time `db:"updated_at"`
Public any
Trusted any
ProfileNickname sql.NullString `db:"profile_nickname"`
ProfileAvatarFileID sql.NullString `db:"profile_avatar_file_id"`
ProfileUpdatedAt sql.NullTime `db:"profile_updated_at"`
}{}
if err = rows.StructScan(&row); err != nil {
return nil, "", err
@@ -8838,7 +8921,7 @@ func (a *adapter) TenantFriendshipList(id t.TenantID, uid t.Uid, queryText, init
Peer: &t.User{
ObjHeader: t.ObjHeader{Id: peerID.String()},
TenantID: id,
Public: common.FromJSON(row.Public),
Public: profilePublicFromFields(common.FromJSON(row.Public), row.ProfileNickname, row.ProfileAvatarFileID),
Trusted: common.FromJSON(row.Trusted),
},
})