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 } 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} } func (s *Service) ready() bool { return s != nil && s.repo != nil && s.chats != nil && s.ids != nil }