89 lines
3.1 KiB
Go
89 lines
3.1 KiB
Go
package memory
|
||
|
||
import (
|
||
"context"
|
||
"time"
|
||
|
||
"telesrv/internal/domain"
|
||
)
|
||
|
||
// 私聊消息 poll 投票/关闭:消息可见性在本 store 校验,poll 级校验与状态全部
|
||
// 委托共享 PollStore(与 postgres 实现共用 domain 纯函数语义)。
|
||
|
||
func (s *MessageStore) VoteMessagePoll(_ context.Context, req domain.VotePrivateMessagePollRequest) (domain.PrivateMessagePollResult, error) {
|
||
target, err := s.pollMessageTarget(req.UserID, req.Peer, req.MessageID)
|
||
if err != nil {
|
||
return domain.PrivateMessagePollResult{}, err
|
||
}
|
||
if req.Date == 0 {
|
||
req.Date = int(time.Now().Unix())
|
||
}
|
||
if err := s.polls.Vote(target.Media.Poll.ID, req.UserID, req.Options, req.Date); err != nil {
|
||
return domain.PrivateMessagePollResult{}, err
|
||
}
|
||
return s.privatePollResult(target.UID, target.Media.Poll.ID, req.Date), nil
|
||
}
|
||
|
||
func (s *MessageStore) CloseMessagePoll(_ context.Context, req domain.ClosePrivateMessagePollRequest) (domain.PrivateMessagePollResult, error) {
|
||
target, err := s.pollMessageTarget(req.UserID, req.Peer, req.MessageID)
|
||
if err != nil {
|
||
return domain.PrivateMessagePollResult{}, err
|
||
}
|
||
if req.Date == 0 {
|
||
req.Date = int(time.Now().Unix())
|
||
}
|
||
if err := s.polls.Close(target.Media.Poll.ID, req.UserID); err != nil {
|
||
return domain.PrivateMessagePollResult{}, err
|
||
}
|
||
return s.privatePollResult(target.UID, target.Media.Poll.ID, req.Date), nil
|
||
}
|
||
|
||
// pollMessageTarget 定位 viewer box 中带 poll 的目标消息。
|
||
func (s *MessageStore) pollMessageTarget(userID int64, peer domain.Peer, messageID int) (domain.Message, error) {
|
||
if s == nil || s.polls == nil {
|
||
return domain.Message{}, domain.ErrMessageIDInvalid
|
||
}
|
||
if userID == 0 || peer.Type != domain.PeerTypeUser || peer.ID == 0 || messageID <= 0 || messageID > domain.MaxMessageBoxID {
|
||
return domain.Message{}, domain.ErrMessageIDInvalid
|
||
}
|
||
s.mu.RLock()
|
||
defer s.mu.RUnlock()
|
||
for _, msg := range s.m[userID] {
|
||
if msg.ID != messageID || msg.Peer != peer {
|
||
continue
|
||
}
|
||
if msg.Media == nil || msg.Media.Kind != domain.MessageMediaKindPoll || msg.Media.Poll == nil || msg.Media.Poll.ID == 0 {
|
||
return domain.Message{}, domain.ErrMessageIDInvalid
|
||
}
|
||
return msg, nil
|
||
}
|
||
return domain.Message{}, domain.ErrMessageIDInvalid
|
||
}
|
||
|
||
// privatePollResult 收集同一 UID 的全部 owner 副本,并按各自 owner 视角 enrich poll。
|
||
func (s *MessageStore) privatePollResult(uid, pollID int64, now int) domain.PrivateMessagePollResult {
|
||
out := domain.PrivateMessagePollResult{PollID: pollID}
|
||
s.mu.RLock()
|
||
defer s.mu.RUnlock()
|
||
for _, messages := range s.m {
|
||
for _, msg := range messages {
|
||
if msg.UID != uid {
|
||
continue
|
||
}
|
||
item := cloneMessage(msg)
|
||
item.Media = enrichPollMediaForViewer(s.polls, item.Media, item.OwnerUserID, now)
|
||
out.Messages = append(out.Messages, item)
|
||
}
|
||
}
|
||
return out
|
||
}
|
||
|
||
// enrichPrivateMessagePolls 是私聊读路径的 poll enrichment 入口(与 reactions 填充并列)。
|
||
func (s *MessageStore) enrichPrivateMessagePolls(messages []domain.Message, now int) {
|
||
if s == nil || s.polls == nil {
|
||
return
|
||
}
|
||
for i := range messages {
|
||
messages[i].Media = enrichPollMediaForViewer(s.polls, messages[i].Media, messages[i].OwnerUserID, now)
|
||
}
|
||
}
|