spark-server/internal/module/friend/logic/service.go
zhr ae9a71034d feat: implement Spark IM V3 modular monolith
Add HTTP /v1 MVC, TCP send path, groups with server-side member-avatar collage, object-storage upload, and friends/favorites around the architecture-v3 layout.

Co-authored-by: Cursor <cursoragent@cursor.com>
2026-09-17 19:52:11 +08:00

75 lines
2.9 KiB
Go

package logic
import (
"context"
"spark-server/internal/module/friend/entity"
msgentity "spark-server/internal/module/message/entity"
userentity "spark-server/internal/module/user/entity"
)
// Repository is friend persistence. Model implements it; do not split this by table.
type Repository interface {
GetRelation(ctx context.Context, a, b int64) (*entity.Relation, error)
ListFriends(ctx context.Context, userID int64, limit int) ([]*entity.Relation, error)
GetRequest(ctx context.Context, id int64) (*entity.Request, error)
GetRequestByPair(ctx context.Context, from, to int64) (*entity.Request, error)
UpsertRequest(ctx context.Context, req *entity.Request) error
ListIncoming(ctx context.Context, toUserID int64, status, limit int) ([]*entity.Request, error)
GetRemark(ctx context.Context, userID, friendID int64) (string, error)
ListRemarks(ctx context.Context, userID int64, friendIDs []int64) (map[int64]string, error)
SetRemark(ctx context.Context, userID, friendID int64, remark string) error
IsBlocked(ctx context.Context, userID, targetID int64) (bool, error)
BlockedEither(ctx context.Context, a, b int64) (bool, error)
CreateBlock(ctx context.Context, b *entity.Block) error
DeleteBlock(ctx context.Context, userID, blockedID int64) error
CreateReport(ctx context.Context, r *entity.Report) error
AcceptFriend(ctx context.Context, in entity.AcceptParams) error
DeleteFriend(ctx context.Context, a, b int64) error
}
// UserFinder resolves accounts by uid / email / spark_id / qrcode ticket.
type UserFinder interface {
Get(ctx context.Context, id int64) (*userentity.User, error)
GetByEmail(ctx context.Context, email string) (*userentity.User, error)
GetBySparkID(ctx context.Context, sparkID string) (*userentity.User, error)
GetByQRCode(ctx context.Context, qrcode string) (*userentity.User, error)
}
// IDGen issues Snowflake ids for requests, reports, and system messages.
type IDGen interface {
NextID() (int64, error)
}
// Greeter writes the "became friends" system message. Nil skips greeting.
type Greeter interface {
BecameFriends(ctx context.Context, userA, userB int64) error
}
// P2PChats opens (or reuses) the 1:1 conversation for a pair.
type P2PChats interface {
EnsureP2P(ctx context.Context, userA, userB int64) (int64, error)
UpdateLastMsg(ctx context.Context, conversationID, msgID, atMS int64) error
}
// Messages persists a row in messages.
type Messages interface {
Create(ctx context.Context, m *msgentity.Message) error
}
// Service is the friend use-case layer (HTTP and TCP share it).
type Service struct {
repo Repository
users UserFinder
ids IDGen
greeter Greeter
}
func NewService(repo Repository, users UserFinder, ids IDGen, greeter Greeter) *Service {
return &Service{repo: repo, users: users, ids: ids, greeter: greeter}
}
func (s *Service) ready() bool {
return s != nil && s.repo != nil && s.users != nil && s.ids != nil
}