spark-server/internal/module/message/logic/service.go
DESKTOP-L8OUL9F\gfl0034 d293de34f5 实现 TCP READ(命令 8),已读水位前进时清未读并通知其他设备。
补上会员价格按平台筛选,并修正广场机器人测试的 Feed 调用,使 go test 能通过。

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-10-16 18:22:08 +08:00

104 lines
3.2 KiB
Go

package logic
import (
"context"
"time"
conventity "spark-server/internal/module/conversation/entity"
deliverentity "spark-server/internal/module/deliver/entity"
"spark-server/internal/module/message/entity"
)
const (
defaultHistoryLimit = 200
recallWindow = 2 * time.Minute
msgIDSkew = 5 * time.Minute
)
type Repository interface {
Create(ctx context.Context, message *entity.Message) error
CreateAndBump(ctx context.Context, message *entity.Message) error
GetByID(ctx context.Context, id int64) (*entity.Message, error)
GetByClientMsgID(ctx context.Context, senderID, conversationID int64, clientMsgID string) (*entity.Message, error)
ListByConversation(ctx context.Context, conversationID, viewerID, lastMsgID int64, limit int) ([]*entity.Message, error)
Recall(ctx context.Context, id int64) error
HideForUser(ctx context.Context, userID int64, msg *entity.Message) error
PurgeUser(ctx context.Context, userID int64) error
}
type Conversations interface {
Get(ctx context.Context, id int64) (*conventity.Conversation, error)
GetMember(ctx context.Context, conversationID, userID int64) (*conventity.Member, error)
ListMemberIDs(ctx context.Context, conversationID int64) ([]int64, error)
UpdateLastRead(ctx context.Context, conversationID, userID, msgID int64) error
}
// DialogUnread clears one conversation's Redis unread (HDEL + unread ZSET → read ZSET).
type DialogUnread interface {
ClearUnread(ctx context.Context, userID, conversationID, score int64) error
}
type P2POpener interface {
EnsureP2P(ctx context.Context, userA, userB int64) (int64, error)
}
type FriendGate interface {
CanSend(ctx context.Context, fromUserID, toUserID int64) error
}
type GroupGate interface {
CanSend(ctx context.Context, userID, conversationID int64) error
MemberIDs(ctx context.Context, conversationID int64) ([]int64, error)
CheckMentions(ctx context.Context, userID, conversationID int64, atAll bool, uids []int64) error
IDByConversation(ctx context.Context, conversationID int64) (int64, error)
}
type IDGen interface {
NextID() (int64, error)
}
type DeliverQueue interface {
Push(ctx context.Context, job *deliverentity.Job) error
}
// Service is send / recall / delete / read / history. HTTP and TCP share it.
type Service struct {
repo Repository
chats Conversations
p2p P2POpener
friends FriendGate
groups GroupGate
ids IDGen
queue DeliverQueue
inbox DialogUnread
account AccountGate
filter TextFilter
penalty Penalty
}
func NewService(repo Repository, chats Conversations, p2p P2POpener, friends FriendGate, groups GroupGate, ids IDGen, queue DeliverQueue) *Service {
return &Service{repo: repo, chats: chats, p2p: p2p, friends: friends, groups: groups, ids: ids, queue: queue}
}
// BindInbox wires the Redis dialog list. Nil skips the unread clear.
func (s *Service) BindInbox(inbox DialogUnread) {
if s == nil {
return
}
s.inbox = inbox
}
// BindModeration wires account gate and text filter (optional; nil skips).
func (s *Service) BindModeration(account AccountGate, filter TextFilter, penalty Penalty) {
if s == nil {
return
}
s.account = account
s.filter = filter
s.penalty = penalty
}
func (s *Service) ready() bool {
return s != nil && s.repo != nil && s.chats != nil && s.ids != nil
}