133 lines
4.1 KiB
Go
133 lines
4.1 KiB
Go
package model
|
||
|
||
import (
|
||
"context"
|
||
"time"
|
||
|
||
"gorm.io/gorm"
|
||
"gorm.io/gorm/clause"
|
||
|
||
"spark-server/internal/module/friend/entity"
|
||
"spark-server/internal/pkg/errs"
|
||
)
|
||
|
||
// FriendRequest maps table friend_requests.
|
||
type FriendRequest struct {
|
||
ID int64 `gorm:"column:id;primaryKey;comment:Snowflake 申请 id"`
|
||
FromUser int64 `gorm:"column:from_user;comment:申请人 user_id"`
|
||
ToUser int64 `gorm:"column:to_user;comment:被申请人 user_id"`
|
||
Source int `gorm:"column:source;comment:来源:1=二维码 2=邮箱 3=spark_id"`
|
||
Reason string `gorm:"column:reason;comment:申请理由"`
|
||
Remark string `gorm:"column:remark;comment:申请人对对方的备注,同意后写入自己的好友边"`
|
||
Status int `gorm:"column:status;comment:1=待处理 2=已同意 3=已拒绝"`
|
||
CreatedAt time.Time `gorm:"column:created_at;comment:首次申请时间"`
|
||
UpdatedAt time.Time `gorm:"column:updated_at;comment:最近一次申请或处理时间"`
|
||
}
|
||
|
||
func (FriendRequest) TableName() string { return "friend_requests" }
|
||
|
||
func (r *FriendRequest) entity() *entity.Request {
|
||
if r == nil {
|
||
return nil
|
||
}
|
||
return &entity.Request{
|
||
ID: r.ID, FromUser: r.FromUser, ToUser: r.ToUser, Source: entity.Source(r.Source),
|
||
Reason: r.Reason, Remark: r.Remark, Status: entity.RequestStatus(r.Status),
|
||
CreatedAt: r.CreatedAt, UpdatedAt: r.UpdatedAt,
|
||
}
|
||
}
|
||
|
||
func requestFromEntity(r *entity.Request) FriendRequest {
|
||
return FriendRequest{
|
||
ID: r.ID, FromUser: r.FromUser, ToUser: r.ToUser, Source: int(r.Source),
|
||
Reason: r.Reason, Remark: r.Remark, Status: int(r.Status),
|
||
CreatedAt: r.CreatedAt, UpdatedAt: r.UpdatedAt,
|
||
}
|
||
}
|
||
|
||
func (m *Repo) GetRequest(ctx context.Context, id int64) (*entity.Request, error) {
|
||
db, err := m.session(ctx)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
var row FriendRequest
|
||
if err := db.Where("id = ?", id).Take(&row).Error; err != nil {
|
||
return nil, mapDBErr(err)
|
||
}
|
||
return row.entity(), nil
|
||
}
|
||
|
||
func (m *Repo) GetRequestByPair(ctx context.Context, from, to int64) (*entity.Request, error) {
|
||
db, err := m.session(ctx)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
var row FriendRequest
|
||
if err := db.Where("from_user = ? AND to_user = ?", from, to).Take(&row).Error; err != nil {
|
||
return nil, mapDBErr(err)
|
||
}
|
||
return row.entity(), nil
|
||
}
|
||
|
||
func (m *Repo) UpsertRequest(ctx context.Context, req *entity.Request) error {
|
||
if req == nil || req.FromUser <= 0 || req.ToUser <= 0 {
|
||
return errs.ErrInvalidArgument
|
||
}
|
||
db, err := m.session(ctx)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
row := requestFromEntity(req)
|
||
err = db.Clauses(clause.OnConflict{
|
||
Columns: []clause.Column{{Name: "from_user"}, {Name: "to_user"}},
|
||
DoUpdates: clause.AssignmentColumns([]string{"source", "reason", "remark", "status", "updated_at"}),
|
||
}).Create(&row).Error
|
||
if err != nil {
|
||
return mapDBErr(err)
|
||
}
|
||
saved, err := m.GetRequestByPair(ctx, req.FromUser, req.ToUser)
|
||
if err != nil {
|
||
return err
|
||
}
|
||
*req = *saved
|
||
return nil
|
||
}
|
||
|
||
func (m *Repo) ListIncoming(ctx context.Context, toUserID int64, status entity.RequestStatus, limit int) ([]*entity.Request, error) {
|
||
db, err := m.session(ctx)
|
||
if err != nil {
|
||
return nil, err
|
||
}
|
||
limit = entity.ClampLimit(limit)
|
||
var rows []FriendRequest
|
||
q := db.Where("to_user = ?", toUserID)
|
||
if status > 0 {
|
||
q = q.Where("status = ?", status)
|
||
}
|
||
if err := q.Order("updated_at DESC").Limit(limit).Find(&rows).Error; err != nil {
|
||
return nil, mapDBErr(err)
|
||
}
|
||
out := make([]*entity.Request, 0, len(rows))
|
||
for i := range rows {
|
||
out = append(out, rows[i].entity())
|
||
}
|
||
return out, nil
|
||
}
|
||
|
||
func markRequestsAccepted(tx *gorm.DB, ids []int64, at time.Time) error {
|
||
if len(ids) == 0 {
|
||
return nil
|
||
}
|
||
return mapDBErr(tx.Model(&FriendRequest{}).Where("id IN ?", ids).Updates(map[string]any{
|
||
"status": entity.RequestAccepted,
|
||
"updated_at": at,
|
||
}).Error)
|
||
}
|
||
|
||
func rejectPairRequests(tx *gorm.DB, a, b int64, at time.Time) error {
|
||
return mapDBErr(tx.Model(&FriendRequest{}).
|
||
Where("(from_user = ? AND to_user = ?) OR (from_user = ? AND to_user = ?)", a, b, b, a).
|
||
Where("status = ?", entity.RequestPending).
|
||
Updates(map[string]any{"status": entity.RequestRejected, "updated_at": at}).Error)
|
||
}
|