Sync profile source and message topic seq

This commit is contained in:
richjohnrambo
2026-09-04 16:06:57 +08:00
parent 47649d33e2
commit 7fb1ea70bc
5 changed files with 216 additions and 23 deletions
+64 -9
View File
@@ -50,9 +50,13 @@ func stampTenantUser(id t.TenantID, user *t.User) *t.User {
type profileUserRow struct {
TenantID t.TenantID `db:"tenant_id"`
ID string `db:"id"`
Username string
CreatedAt time.Time `db:"createdat"`
UpdatedAt time.Time `db:"updatedat"`
State t.ObjState `db:"state"`
StateAt *time.Time `db:"stateat"`
Access t.DefaultAccess
Phone string `db:"phone"`
LastSeen sql.NullTime `db:"lastseen"`
UserAgent string `db:"useragent"`
Public any `db:"public"`
@@ -80,8 +84,31 @@ func (row profileUserRow) profilePublic() any {
return profilePublicFromFields(common.FromJSON(row.Public), row.ProfileNickname, row.ProfileAvatarFileID)
}
func profileUserFromRow(row profileUserRow) t.User {
user := t.User{
ObjHeader: t.ObjHeader{
Id: row.ID,
CreatedAt: row.CreatedAt,
UpdatedAt: row.effectiveUpdatedAt(),
},
TenantID: row.TenantID,
State: row.State,
StateAt: row.StateAt,
Username: row.Username,
Access: row.Access,
LastSeen: row.lastSeen(),
UserAgent: row.UserAgent,
Phone: row.Phone,
Public: row.profilePublic(),
Trusted: common.FromJSON(row.Trusted),
}
user.SetUid(common.EncodeUidString(row.ID))
return user
}
func profilePublicFromFields(base any, nickname, avatarFileID sql.NullString) any {
public := publicMap(base)
clearProfilePublicFields(public)
if nickname.Valid {
value := strings.TrimSpace(nickname.String)
if value != "" {
@@ -99,6 +126,29 @@ func profilePublicFromFields(base any, nickname, avatarFileID sql.NullString) an
return public
}
func clearProfilePublicFields(public map[string]any) {
for _, key := range []string{"display_name", "nickname", "fn", "name", "avatar_file_id", "photo", "avatar"} {
delete(public, key)
}
}
func profileSeedFromPublic(public any) (nickname, avatarFileID string) {
values := publicMap(public)
for _, key := range []string{"display_name", "nickname", "fn", "name"} {
if value := strings.TrimSpace(fmt.Sprint(values[key])); value != "" && value != "<nil>" {
nickname = value
break
}
}
for _, key := range []string{"avatar_file_id", "photo", "avatar"} {
if value := strings.TrimSpace(fmt.Sprint(values[key])); value != "" && value != "<nil>" {
avatarFileID = value
break
}
}
return nickname, avatarFileID
}
func publicMap(value any) map[string]any {
switch public := value.(type) {
case map[string]any:
@@ -282,9 +332,12 @@ func (a *adapter) TenantUserGet(id t.TenantID, uid t.Uid) (*t.User, error) {
if cancel != nil {
defer cancel()
}
var user t.User
err = a.db.GetContext(ctx, &user, `SELECT tenant_id,id,username,createdat,updatedat,state,stateat,access,lastseen,useragent,
COALESCE(phone,'') AS phone,public,trusted FROM im_users WHERE tenant_id=? AND id=? AND state!=?`,
var row profileUserRow
err = a.db.GetContext(ctx, &row, `SELECT u.tenant_id,u.id,u.username,u.createdat,u.updatedat,u.state,u.stateat,u.access,u.lastseen,u.useragent,
COALESCE(u.phone,'') AS phone,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.tenant_id=u.tenant_id AND p.user_id=u.id
WHERE u.tenant_id=? AND u.id=? AND u.state!=?`,
id, decodeUID(uid), t.StateDeleted)
if err == sql.ErrNoRows {
return nil, nil
@@ -292,7 +345,7 @@ func (a *adapter) TenantUserGet(id t.TenantID, uid t.Uid) (*t.User, error) {
if err != nil {
return nil, err
}
scanTenantUser(&user)
user := profileUserFromRow(row)
return &user, nil
}
@@ -9264,8 +9317,10 @@ func (a *adapter) TenantUserSearch(id t.TenantID, viewer t.Uid, queryText, searc
if cancel != nil {
defer cancel()
}
rows, err := a.db.QueryxContext(ctx, `SELECT DISTINCT u.id,u.username,u.createdat,u.updatedat,u.state,u.stateat,u.access,u.lastseen,u.useragent,
COALESCE(u.phone,'') AS phone,u.public,u.trusted FROM im_users AS u `+strings.Join(joins, " ")+`
rows, err := a.db.QueryxContext(ctx, `SELECT DISTINCT u.tenant_id,u.id,u.username,u.createdat,u.updatedat,u.state,u.stateat,u.access,u.lastseen,u.useragent,
COALESCE(u.phone,'') AS phone,u.public,u.trusted,
profile.nickname AS profile_nickname,profile.avatar_file_id AS profile_avatar_file_id,profile.updated_at AS profile_updated_at
FROM im_users AS u `+strings.Join(joins, " ")+`
WHERE `+strings.Join(where, " AND ")+` ORDER BY u.id ASC LIMIT ?`, args...)
if err != nil {
return nil, "", err
@@ -9274,11 +9329,11 @@ func (a *adapter) TenantUserSearch(id t.TenantID, viewer t.Uid, queryText, searc
users := make([]t.User, 0, limit)
nextCursor := ""
for rows.Next() {
var user t.User
if err = rows.StructScan(&user); err != nil {
var row profileUserRow
if err = rows.StructScan(&row); err != nil {
return nil, "", err
}
scanTenantUser(&user)
user := profileUserFromRow(row)
if len(users) == limit {
nextCursor = strconv.FormatInt(decodeUID(user.Uid()), 10)
continue