From 45eef9566a4dad283f37a2bd0ec9eecff4bd08ea Mon Sep 17 00:00:00 2001 From: Sean Du Date: Fri, 5 Jun 2026 22:54:38 +0800 Subject: [PATCH] Fix client friend status mapping - Add explicit client friend status constants and resolver - Return dynamic friend status from profileInfo and friend/search - Accept invite_code when loading profileInfo targets - Align live support friend status values with client expectations Signed-off-by: Sean Du --- internal/handler/api/profile/info.go | 17 +++++++++-- internal/handler/friend/search.go | 7 ++++- internal/handler/live/partylist.go | 2 +- internal/handler/live/support.go | 2 +- internal/model/user/userfriend.go | 45 ++++++++++++++++++++++++++++ 5 files changed, 68 insertions(+), 5 deletions(-) diff --git a/internal/handler/api/profile/info.go b/internal/handler/api/profile/info.go index fd20889..f5a4455 100644 --- a/internal/handler/api/profile/info.go +++ b/internal/handler/api/profile/info.go @@ -48,6 +48,11 @@ func profileInfo(ctx *gin.Context, targetUserID int) (res any, err error) { return nil, err } + friendStatus, err := usermodel.ResolveClientFriendStatus(ss.UserEng, ss.UserID, targetUserID) + if err != nil { + return nil, err + } + if naviRaw != nil { centerUnitInfo.Costume = profileapischema.Costume{ UnitID: naviRaw.UnitID, @@ -80,7 +85,7 @@ func profileInfo(ctx *gin.Context, targetUserID int) (res any, err error) { CenterUnitInfo: centerUnitInfo, NaviUnitInfo: naviUnitInfo, IsAlliance: false, - FriendStatus: 0, + FriendStatus: friendStatus, SettingAwardID: targetPref.AwardID, SettingBackgroundID: targetPref.BackgroundID, }, @@ -104,13 +109,21 @@ func getTargetUserPref(ss *session.Session, targetUserID int) (usermodel.UserPre if err != nil { return usermodel.UserPref{}, err } + if !has { + has, err = ss.UserEng.Table(new(usermodel.UserPref)). + Where("invite_code = ?", strconv.Itoa(targetUserID)). + Get(&pref) + if err != nil { + return usermodel.UserPref{}, err + } + } if !has { return usermodel.UserPref{}, errors.New("user not found") } if pref.NeedsProfileMigration() { pref.ApplyProfileDefaults() _, err = ss.UserEng.Table(new(usermodel.UserPref)). - Where("user_id = ?", targetUserID). + Where("user_id = ?", pref.UserID). Cols(usermodel.UserPrefProfileColumns()...). Update(&pref) if err != nil { diff --git a/internal/handler/friend/search.go b/internal/handler/friend/search.go index 5cde615..efe4931 100644 --- a/internal/handler/friend/search.go +++ b/internal/handler/friend/search.go @@ -86,6 +86,11 @@ func search(ctx *gin.Context) { return } + friendStatus, err := usermodel.ResolveClientFriendStatus(ss.UserEng, ss.UserID, targetUserID) + if ss.CheckErr(err) { + return + } + ss.Respond(friendschema.SearchResp{ ResponseData: friendschema.SearchData{ UserInfo: friendschema.SearchUserInfo{ @@ -103,7 +108,7 @@ func search(ctx *gin.Context) { CenterUnitInfo: toSearchCenterUnitInfo(centerUnitInfo, costume), SettingAwardID: row.AwardID, IsAlliance: false, - FriendStatus: 0, + FriendStatus: friendStatus, ServerTimestamp: time.Now().Unix(), }, ReleaseInfo: []any{}, diff --git a/internal/handler/live/partylist.go b/internal/handler/live/partylist.go index 831518e..f1f8ee4 100644 --- a/internal/handler/live/partylist.go +++ b/internal/handler/live/partylist.go @@ -39,7 +39,7 @@ func partyList(ctx *gin.Context) { selfParty := liveschema.PartyList{ UserInfo: ss.GetUserInfo(), SettingAwardID: pref.AwardID, - FriendStatus: 0, + FriendStatus: usermodel.ClientFriendStatusNone, } selfParty.AvailableSocialPoint = 10 selfParty.CenterUnitInfo, err = mustFindCenterUnitInfo(ss, ss.UserID, pref.UnitOwningUserID) diff --git a/internal/handler/live/support.go b/internal/handler/live/support.go index 5710b78..92d81b9 100644 --- a/internal/handler/live/support.go +++ b/internal/handler/live/support.go @@ -51,7 +51,7 @@ func buildLiveSupportParty(ss *session.Session, row liveSupportRow) (liveschema. CenterUnitInfo: centerUnitInfo, SettingAwardID: row.AwardID, AvailableSocialPoint: 10, - FriendStatus: 0, + FriendStatus: usermodel.ClientFriendStatusApproved, }, nil } diff --git a/internal/model/user/userfriend.go b/internal/model/user/userfriend.go index 7e2b449..ec56b2d 100644 --- a/internal/model/user/userfriend.go +++ b/internal/model/user/userfriend.go @@ -16,6 +16,13 @@ const ( FriendListPageSize = 40 ) +const ( + ClientFriendStatusNone = iota + ClientFriendStatusApproved + ClientFriendStatusPending + ClientFriendStatusAwaitingApproval +) + type UserFriend struct { ID int `xorm:"id pk autoincr"` UserID int `xorm:"user_id unique(friend_pair) index"` @@ -86,6 +93,44 @@ func EnsureMutualFriendWithIsNew(dbSession *xorm.Session, userID, friendUserID, return EnsureFriendLink(dbSession, friendUserID, userID, status, friendIsNew) } +func ResolveClientFriendStatus(dbSession *xorm.Session, userID, targetUserID int) (int, error) { + if dbSession == nil || userID <= 0 || targetUserID <= 0 || userID == targetUserID { + return ClientFriendStatusNone, nil + } + + link := UserFriend{} + has, err := dbSession.Table(new(UserFriend)). + Where("user_id = ? AND friend_user_id = ?", userID, targetUserID). + Cols("status"). + Get(&link) + if err != nil { + return ClientFriendStatusNone, err + } + if !has { + return ClientFriendStatusNone, nil + } + + switch link.Status { + case FriendStatusApproved: + isMutual, err := dbSession.Table(new(UserFriend)). + Where("user_id = ? AND friend_user_id = ?", targetUserID, userID). + Where("status = ?", FriendStatusApproved). + Exist() + if err != nil { + return ClientFriendStatusNone, err + } + if isMutual { + return ClientFriendStatusApproved, nil + } + case FriendStatusPending: + return ClientFriendStatusPending, nil + case FriendStatusAwaitingApproval: + return ClientFriendStatusAwaitingApproval, nil + } + + return ClientFriendStatusNone, nil +} + func EnsureDefaultFriendship(dbSession *xorm.Session, userID int) error { if dbSession == nil || userID <= 0 { return nil