spark-server/internal/module/message/logic/history.go
DESKTOP-L8OUL9F\gfl0034 e27ae8723a fix: 单聊系统消息带回当前用户视角的对方
SYNC_INBOX 补 conversation_type、peer_id、group_id 和 last_read_msg_id。历史消息在 sender 为 0 时用 peer_id 定位对方。已读清未读时保留会话 ZSET 分数,避免被毫秒时间戳冲到游标后面。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-19 15:04:03 +08:00

75 lines
1.9 KiB
Go

package logic
import (
"context"
"errors"
conventity "spark-server/internal/module/conversation/entity"
"spark-server/internal/pkg/errs"
)
type HistoryRequest struct {
ConversationID int64
LastMsgID int64
Limit int
}
type HistoryResponse struct {
Items []*Item `json:"items"`
HasMore bool `json:"has_more"`
}
func (s *Service) GetHistory(ctx context.Context, userID int64, req HistoryRequest) (*HistoryResponse, error) {
if !s.ready() || userID <= 0 {
return nil, errs.ErrUnauthorized
}
if req.ConversationID <= 0 {
return nil, errs.ErrInvalidArgument
}
if _, err := s.chats.GetMember(ctx, req.ConversationID, userID); err != nil {
if errors.Is(err, errs.ErrNotFound) {
return nil, errs.ErrForbidden
}
return nil, err
}
limit := req.Limit
if limit <= 0 || limit > defaultHistoryLimit {
limit = defaultHistoryLimit
}
rows, err := s.repo.ListByConversation(ctx, req.ConversationID, userID, req.LastMsgID, limit+1)
if err != nil {
return nil, err
}
hasMore := len(rows) > limit
if hasMore {
rows = rows[:limit]
}
peer := s.viewerPeer(ctx, userID, req.ConversationID)
items := make([]*Item, 0, len(rows))
for _, row := range rows {
item := itemOf(row)
item.PeerID = peer
items = append(items, item)
}
return &HistoryResponse{Items: items, HasMore: hasMore}, nil
}
// viewerPeer is the other member of a P2P conversation. Group chats stay 0; use group_id.
// System messages keep sender_id=0 and receiver_id=0; this field is how the viewer finds the peer.
func (s *Service) viewerPeer(ctx context.Context, viewerID, conversationID int64) int64 {
conv, err := s.chats.Get(ctx, conversationID)
if err != nil || conv == nil || conv.Type != conventity.TypeP2P {
return 0
}
ids, err := s.chats.ListMemberIDs(ctx, conversationID)
if err != nil {
return 0
}
for _, id := range ids {
if id > 0 && id != viewerID {
return id
}
}
return 0
}