spark-server/internal/module/friend/model/memory_write.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

152 lines
3.9 KiB
Go

package model
import (
"context"
"time"
"spark-server/internal/module/friend/entity"
"spark-server/internal/pkg/errs"
)
func (m *MemoryRepo) GetRemark(_ context.Context, userID, friendID int64) (string, error) {
m.mu.Lock()
defer m.mu.Unlock()
return m.remarks[remarkKey{UserID: userID, FriendID: friendID}], nil
}
func (m *MemoryRepo) ListRemarks(_ context.Context, userID int64, friendIDs []int64) (map[int64]string, error) {
m.mu.Lock()
defer m.mu.Unlock()
out := make(map[int64]string, len(friendIDs))
for _, id := range friendIDs {
if s := m.remarks[remarkKey{UserID: userID, FriendID: id}]; s != "" {
out[id] = s
}
}
return out, nil
}
func (m *MemoryRepo) SetRemark(_ context.Context, userID, friendID int64, remark string) error {
if userID <= 0 || friendID <= 0 {
return errs.ErrInvalidArgument
}
m.mu.Lock()
defer m.mu.Unlock()
key := remarkKey{UserID: userID, FriendID: friendID}
if remark == "" {
delete(m.remarks, key)
return nil
}
m.remarks[key] = remark
return nil
}
func (m *MemoryRepo) IsBlocked(_ context.Context, userID, targetID int64) (bool, error) {
m.mu.Lock()
defer m.mu.Unlock()
_, ok := m.blocks[blockKey{UserID: userID, BlockedID: targetID}]
return ok, nil
}
func (m *MemoryRepo) BlockedEither(_ context.Context, a, b int64) (bool, error) {
m.mu.Lock()
defer m.mu.Unlock()
_, ab := m.blocks[blockKey{UserID: a, BlockedID: b}]
_, ba := m.blocks[blockKey{UserID: b, BlockedID: a}]
return ab || ba, nil
}
func (m *MemoryRepo) CreateBlock(_ context.Context, b *entity.Block) error {
if b == nil || b.UserID <= 0 || b.BlockedID <= 0 {
return errs.ErrInvalidArgument
}
m.mu.Lock()
defer m.mu.Unlock()
now := b.CreatedAt
if now.IsZero() {
now = time.Now()
}
m.blocks[blockKey{UserID: b.UserID, BlockedID: b.BlockedID}] = now
delete(m.relations, pairOf(b.UserID, b.BlockedID))
delete(m.remarks, remarkKey{UserID: b.UserID, FriendID: b.BlockedID})
delete(m.remarks, remarkKey{UserID: b.BlockedID, FriendID: b.UserID})
m.rejectPendingLocked(b.UserID, b.BlockedID, now)
return nil
}
func (m *MemoryRepo) DeleteBlock(_ context.Context, userID, blockedID int64) error {
m.mu.Lock()
defer m.mu.Unlock()
delete(m.blocks, blockKey{UserID: userID, BlockedID: blockedID})
return nil
}
func (m *MemoryRepo) CreateReport(_ context.Context, r *entity.Report) error {
if r == nil || r.UserID <= 0 || r.TargetID <= 0 {
return errs.ErrInvalidArgument
}
m.mu.Lock()
defer m.mu.Unlock()
cp := *r
m.reports = append(m.reports, &cp)
return nil
}
func (m *MemoryRepo) AcceptFriend(_ context.Context, in entity.AcceptParams) error {
if in.Relation == nil {
return errs.ErrInvalidArgument
}
m.mu.Lock()
defer m.mu.Unlock()
now := in.Relation.CreatedAt
if now.IsZero() {
now = time.Now()
in.Relation.CreatedAt = now
}
key := pairKey{Small: in.Relation.UserSmall, Big: in.Relation.UserBig}
if _, ok := m.relations[key]; !ok {
cp := *in.Relation
m.relations[key] = &cp
}
for _, id := range in.Requests {
if req := m.requests[id]; req != nil {
req.Status = entity.RequestAccepted
req.UpdatedAt = now
}
}
for i := range in.Remarks {
r := in.Remarks[i]
if r.Text == "" {
continue
}
m.remarks[remarkKey{UserID: r.UserID, FriendID: r.FriendID}] = r.Text
}
return nil
}
func (m *MemoryRepo) DeleteFriend(_ context.Context, a, b int64) error {
m.mu.Lock()
defer m.mu.Unlock()
key := pairOf(a, b)
if _, ok := m.relations[key]; !ok {
return errs.ErrNotFound
}
delete(m.relations, key)
delete(m.remarks, remarkKey{UserID: a, FriendID: b})
delete(m.remarks, remarkKey{UserID: b, FriendID: a})
return nil
}
func (m *MemoryRepo) rejectPendingLocked(a, b int64, at time.Time) {
for _, req := range m.requests {
if req.Status != entity.RequestPending {
continue
}
pair := (req.FromUser == a && req.ToUser == b) || (req.FromUser == b && req.ToUser == a)
if pair {
req.Status = entity.RequestRejected
req.UpdatedAt = at
}
}
}