一方关注只记关注。双方互关时写入已有双向好友边;取消关注若不再互关只删好友边,不删消息。 Co-authored-by: Cursor <cursoragent@cursor.com>
79 lines
3.1 KiB
Go
79 lines
3.1 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, userID, friendID int64) (*entity.Relation, error)
|
|
ListFriends(ctx context.Context, userID int64, limit int) ([]*entity.Relation, error)
|
|
ListFriendIDs(ctx context.Context, userID int64) ([]int64, error)
|
|
ListBlockedPeerIDs(ctx context.Context, userID int64) ([]int64, 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 entity.RequestStatus, limit int) ([]*entity.Request, error)
|
|
SetRemark(ctx context.Context, userID, friendID int64, remark string) error
|
|
SetPinned(ctx context.Context, userID, friendID int64, pinned bool) error
|
|
SetBlocked(ctx context.Context, userID, friendID int64, blocked bool) error
|
|
IsBlocked(ctx context.Context, userID, targetID int64) (bool, error)
|
|
BlockedEither(ctx context.Context, a, b int64) (bool, 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
|
|
PutFollow(ctx context.Context, userID, targetID int64) error
|
|
DeleteFollow(ctx context.Context, userID, targetID int64) error
|
|
HasFollow(ctx context.Context, userID, targetID int64) (bool, error)
|
|
PurgeUser(ctx context.Context, userID 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
|
|
}
|