spark-server/internal/module/message/logic/service.go
2026-09-29 16:37:36 +08:00

89 lines
2.8 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)
}
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 / history. HTTP and TCP share it.
type Service struct {
repo Repository
chats Conversations
p2p P2POpener
friends FriendGate
groups GroupGate
ids IDGen
queue DeliverQueue
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}
}
// 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
}