owpengram-server/internal/store/memory/message_polls.go

89 lines
3.1 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters

This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.

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)
}
}