226 lines
5.8 KiB
Go
226 lines
5.8 KiB
Go
package model
|
|
|
|
import (
|
|
"context"
|
|
"time"
|
|
|
|
"gorm.io/gorm"
|
|
"gorm.io/gorm/clause"
|
|
|
|
"spark-server/internal/module/square/entity"
|
|
"spark-server/internal/pkg/errs"
|
|
)
|
|
|
|
func (m *Repo) CreatePost(ctx context.Context, post *entity.Post, audience []int64) error {
|
|
if post == nil || post.ID <= 0 || post.UserID <= 0 {
|
|
return errs.ErrInvalidArgument
|
|
}
|
|
db, err := m.session(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
row := postFrom(post)
|
|
if row.CreatedAt.IsZero() {
|
|
row.CreatedAt = time.Now()
|
|
}
|
|
return db.Transaction(func(tx *gorm.DB) error {
|
|
if err := tx.Create(row).Error; err != nil {
|
|
return mapDBErr(err)
|
|
}
|
|
for _, peer := range audience {
|
|
if err := tx.Create(&Audience{PostID: post.ID, PeerID: peer}).Error; err != nil {
|
|
return mapDBErr(err)
|
|
}
|
|
}
|
|
return nil
|
|
})
|
|
}
|
|
|
|
func (m *Repo) SoftDeletePost(ctx context.Context, userID, postID int64) (*entity.Post, error) {
|
|
db, err := m.session(ctx)
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
var row Post
|
|
err = db.Transaction(func(tx *gorm.DB) error {
|
|
if err := tx.Where("id = ? AND user_id = ?", postID, userID).Take(&row).Error; err != nil {
|
|
return mapDBErr(err)
|
|
}
|
|
if row.Status == int16(entity.StatusDeleted) {
|
|
return errs.ErrNotFound
|
|
}
|
|
res := tx.Model(&row).Update("status", entity.StatusDeleted)
|
|
if res.Error != nil {
|
|
return mapDBErr(res.Error)
|
|
}
|
|
if res.RowsAffected == 0 {
|
|
return errs.ErrNotFound
|
|
}
|
|
row.Status = int16(entity.StatusDeleted)
|
|
return nil
|
|
})
|
|
if err != nil {
|
|
return nil, err
|
|
}
|
|
return row.Entity(), nil
|
|
}
|
|
|
|
func (m *Repo) AddLike(ctx context.Context, like *entity.Like) (bool, error) {
|
|
if like == nil || like.PostID <= 0 || like.UserID <= 0 {
|
|
return false, errs.ErrInvalidArgument
|
|
}
|
|
db, err := m.session(ctx)
|
|
if err != nil {
|
|
return false, err
|
|
}
|
|
row := Like{PostID: like.PostID, UserID: like.UserID, CreatedAt: time.Now()}
|
|
if like.CreatedAtMS > 0 {
|
|
row.CreatedAt = time.UnixMilli(like.CreatedAtMS)
|
|
}
|
|
created := false
|
|
err = db.Transaction(func(tx *gorm.DB) error {
|
|
res := tx.Clauses(clause.OnConflict{
|
|
Columns: []clause.Column{{Name: "post_id"}, {Name: "user_id"}},
|
|
DoNothing: true,
|
|
}).Create(&row)
|
|
if res.Error != nil {
|
|
return mapDBErr(res.Error)
|
|
}
|
|
if res.RowsAffected == 0 {
|
|
return nil
|
|
}
|
|
created = true
|
|
return bumpCount(tx, like.PostID, "like_count", 1)
|
|
})
|
|
return created, err
|
|
}
|
|
|
|
func (m *Repo) RemoveLike(ctx context.Context, postID, userID int64) error {
|
|
db, err := m.session(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return db.Transaction(func(tx *gorm.DB) error {
|
|
res := tx.Where("post_id = ? AND user_id = ?", postID, userID).Delete(&Like{})
|
|
if res.Error != nil {
|
|
return mapDBErr(res.Error)
|
|
}
|
|
if res.RowsAffected == 0 {
|
|
return errs.ErrNotFound
|
|
}
|
|
return bumpCount(tx, postID, "like_count", -1)
|
|
})
|
|
}
|
|
|
|
func (m *Repo) AddComment(ctx context.Context, c *entity.Comment) error {
|
|
if c == nil || c.ID <= 0 || c.PostID <= 0 || c.UserID <= 0 {
|
|
return errs.ErrInvalidArgument
|
|
}
|
|
db, err := m.session(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
row := commentFrom(c)
|
|
if row.CreatedAt.IsZero() {
|
|
row.CreatedAt = time.Now()
|
|
}
|
|
return db.Transaction(func(tx *gorm.DB) error {
|
|
if err := tx.Create(row).Error; err != nil {
|
|
return mapDBErr(err)
|
|
}
|
|
return bumpCount(tx, c.PostID, "comment_count", 1)
|
|
})
|
|
}
|
|
|
|
func (m *Repo) SoftDeleteComment(ctx context.Context, id int64) error {
|
|
db, err := m.session(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
return db.Transaction(func(tx *gorm.DB) error {
|
|
var row Comment
|
|
if err := tx.Where("id = ?", id).Take(&row).Error; err != nil {
|
|
return mapDBErr(err)
|
|
}
|
|
if row.Status == int16(entity.StatusDeleted) {
|
|
return errs.ErrNotFound
|
|
}
|
|
if err := tx.Model(&row).Update("status", entity.StatusDeleted).Error; err != nil {
|
|
return mapDBErr(err)
|
|
}
|
|
return bumpCount(tx, row.PostID, "comment_count", -1)
|
|
})
|
|
}
|
|
|
|
func (m *Repo) CreateNotices(ctx context.Context, rows []*entity.Notice) error {
|
|
if len(rows) == 0 {
|
|
return nil
|
|
}
|
|
db, err := m.session(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
now := time.Now()
|
|
for _, n := range rows {
|
|
row := Notice{
|
|
ID: n.ID, ToUserID: n.ToUserID, FromUserID: n.FromUserID, Kind: int16(n.Kind),
|
|
PostID: n.PostID, CommentID: n.CommentID, CreatedAt: now,
|
|
}
|
|
if n.CreatedAtMS > 0 {
|
|
row.CreatedAt = time.UnixMilli(n.CreatedAtMS)
|
|
}
|
|
if err := db.Create(&row).Error; err != nil {
|
|
return mapDBErr(err)
|
|
}
|
|
}
|
|
return nil
|
|
}
|
|
|
|
func (m *Repo) MarkNoticesRead(ctx context.Context, userID, cursor int64) error {
|
|
db, err := m.session(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
q := db.Model(&Notice{}).Where("to_user_id = ? AND read_at IS NULL", userID)
|
|
if cursor > 0 {
|
|
q = q.Where("id <= ?", cursor)
|
|
}
|
|
return mapDBErr(q.Update("read_at", time.Now()).Error)
|
|
}
|
|
|
|
func (m *Repo) AdvanceNoticeRead(ctx context.Context, userID, noticeID int64) error {
|
|
if userID <= 0 || noticeID <= 0 {
|
|
return errs.ErrInvalidArgument
|
|
}
|
|
db, err := m.session(ctx)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
cur, err := m.GetNoticeState(ctx, userID)
|
|
if err != nil {
|
|
return err
|
|
}
|
|
if cur.LastReadNoticeID >= noticeID {
|
|
return nil
|
|
}
|
|
cur.LastReadNoticeID = noticeID
|
|
cur.UpdatedAtMS = time.Now().UnixMilli()
|
|
row := NoticeState{
|
|
UserID: cur.UserID, LastReadNoticeID: cur.LastReadNoticeID,
|
|
UpdatedAt: time.UnixMilli(cur.UpdatedAtMS),
|
|
}
|
|
return mapDBErr(db.Clauses(clause.OnConflict{
|
|
Columns: []clause.Column{{Name: "user_id"}},
|
|
DoUpdates: clause.AssignmentColumns([]string{"last_read_notice_id", "updated_at"}),
|
|
}).Create(&row).Error)
|
|
}
|
|
|
|
func bumpCount(tx *gorm.DB, postID int64, col string, delta int) error {
|
|
expr := col + " + ?"
|
|
if delta < 0 {
|
|
expr = "CASE WHEN " + col + " + ? < 0 THEN 0 ELSE " + col + " + ? END"
|
|
return mapDBErr(tx.Model(&Post{}).Where("id = ?", postID).Update(col, gorm.Expr(expr, delta, delta)).Error)
|
|
}
|
|
return mapDBErr(tx.Model(&Post{}).Where("id = ?", postID).Update(col, gorm.Expr(expr, delta)).Error)
|
|
}
|