fix: 优化群成员分页并补齐头像资料

This commit is contained in:
richjohnrambo
2026-09-09 09:38:20 +08:00
parent aae13c9265
commit 9ac2b412cc
7 changed files with 167 additions and 61 deletions
+53 -29
View File
@@ -4807,8 +4807,14 @@ func serveIMGroupMembers(wrt http.ResponseWriter, req *http.Request, topic strin
return
}
limit := parseIMLimit(req.URL.Query().Get("limit"), 30, 100)
cursor, err := parseIMNonNegativeCursor(req.URL.Query().Get("cursor"))
if err != nil {
cursor := strings.TrimSpace(req.URL.Query().Get("cursor"))
if cursor != "" {
if _, err := strconv.ParseInt(cursor, 10, 64); err != nil {
writeIMError(wrt, req, http.StatusBadRequest, 30000, imReasonMalformedRequest, "malformed request", map[string]any{"field": "cursor"})
return
}
}
if parsed, err := parseIMNonNegativeCursor(cursor); err != nil || parsed < 0 {
writeIMError(wrt, req, http.StatusBadRequest, 30000, imReasonMalformedRequest, "malformed request", map[string]any{"field": "cursor"})
return
}
@@ -4822,25 +4828,22 @@ func serveIMGroupMembers(wrt http.ResponseWriter, req *http.Request, topic strin
writeIMSuccess(wrt, req, cached)
return
}
members, err := store.Topics.GetUsers(principal.TenantID, topic, &types.QueryOpt{Limit: 1000})
members, nextCursor, err := store.GroupBusiness.ListMembers(principal.TenantID, topic, types.GroupMemberListOptions{
Role: roleFilter,
EligibleRole: eligibleRole,
Query: query,
Cursor: cursor,
Limit: limit,
Mentionable: mentionableOnly,
})
if err != nil {
writeIMError(wrt, req, http.StatusInternalServerError, 90000, imReasonInternal, "internal error", nil)
return
}
items := make([]map[string]any, 0, limit)
seen := 0
nextCursor := ""
for _, member := range members {
access := member.ModeGiven & member.ModeWant
mentionable := access.IsJoiner() && access.IsReader()
role := groupMemberRole(access)
if roleFilter != "" && role != roleFilter {
continue
}
if mentionableOnly && !mentionable {
continue
}
item := groupMemberPayload(member, mentionable)
access := groupMemberAccess(member)
item := groupBusinessMemberPayload(member)
if eligibleRole != "" {
eligible, reason := groupRoleEligibility(selfAccess, access, eligibleRole)
item["eligible"] = eligible
@@ -4855,19 +4858,7 @@ func serveIMGroupMembers(wrt http.ResponseWriter, req *http.Request, topic strin
item["ineligible_reason"] = reason
}
}
if query != "" && !groupMemberMatches(item, query) {
continue
}
if seen < cursor {
seen++
continue
}
if len(items) == limit {
nextCursor = strconv.Itoa(seen)
break
}
items = append(items, item)
seen++
}
permissions := map[string]any{
"can_mention_all": selfAccess.IsAdmin(),
@@ -7320,6 +7311,38 @@ func groupMemberPayload(sub types.Subscription, mentionable bool) map[string]any
return data
}
func groupBusinessMemberPayload(member types.GroupMember) map[string]any {
access := groupMemberAccess(member)
user := &types.User{ObjHeader: types.ObjHeader{Id: member.UserID.String()}, Public: member.Public, Trusted: member.Trusted}
data := userSummaryPayload(user, "")
if nickname := strings.TrimSpace(member.Nickname); nickname != "" {
data["group_nickname"] = nickname
}
data["role"] = groupMemberRole(access)
data["mentionable"] = access.IsJoiner() && access.IsReader()
data["acs"] = map[string]any{
"mode": access.String(),
"want": member.ModeWant.String(),
"given": member.ModeGiven.String(),
}
return data
}
func groupMemberAccess(member types.GroupMember) types.AccessMode {
access := member.ModeGiven & member.ModeWant
if access != types.ModeNone {
return access
}
switch member.Role {
case types.GroupMemberRoleOwner:
return types.ModeCFull
case types.GroupMemberRoleAdmin:
return types.ModeCPublic | types.ModeApprove
default:
return types.ModeCPublic
}
}
func groupMemberProfilePayload(topic string, sub *types.Subscription, user *types.User, ctx *types.RelationshipContext) map[string]any {
data := groupMemberPayload(*sub, true)
data["topic"] = topic
@@ -7771,16 +7794,17 @@ func groupMemberMatches(item map[string]any, query string) bool {
}
func groupMemberPageCacheKey(topic string, uid types.Uid, access types.AccessMode, query, roleFilter, eligibleRole string,
limit, cursor int, mentionableOnly, muteEligible bool) string {
limit int, cursor string, mentionableOnly, muteEligible bool) string {
return strings.Join([]string{
topic,
"v3",
uid.UserId(),
access.String(),
strings.ToLower(strings.TrimSpace(query)),
strings.TrimSpace(roleFilter),
strings.TrimSpace(eligibleRole),
strconv.Itoa(limit),
strconv.Itoa(cursor),
strings.TrimSpace(cursor),
strconv.FormatBool(mentionableOnly),
strconv.FormatBool(muteEligible),
}, "|")