Skip to content

Commit

Permalink
Merge pull request #17 from ShanghaitechGeekPie/prince213-reward
Browse files Browse the repository at this point in the history
Implement #7 #8 and #15.
  • Loading branch information
WAAutoMaton authored Apr 28, 2024
2 parents 9080ba9 + 4f6f3cb commit 0f2a936
Show file tree
Hide file tree
Showing 7 changed files with 195 additions and 26 deletions.
2 changes: 2 additions & 0 deletions internal/controllers/comments.go
Original file line number Diff line number Diff line change
Expand Up @@ -2,6 +2,7 @@ package controllers

import (
"coursebench-backend/internal/controllers/comments"

"github.com/gofiber/fiber/v2"
)

Expand All @@ -14,6 +15,7 @@ func CommentRoutes(r fiber.Router) {
route.Get("/course_group/:id", comments.CourseGroupComment)
route.Get("/course/:id", comments.CourseComment)
route.Get("/recent", comments.RecentComment)
route.Get("/recent/:id", comments.RecentCommentByPage)
route.Post("/like", comments.Like)
route.Post("/fold", comments.Fold)
route.Post("/cover", comments.Cover)
Expand Down
27 changes: 26 additions & 1 deletion internal/controllers/comments/post.go
Original file line number Diff line number Diff line change
Expand Up @@ -6,9 +6,10 @@ import (
"coursebench-backend/pkg/errors"
"coursebench-backend/pkg/models"
"coursebench-backend/pkg/queries"
"time"

"github.com/gofiber/fiber/v2"
"gorm.io/gorm"
"time"
)

type PostRequest struct {
Expand Down Expand Up @@ -117,6 +118,30 @@ func Post(c *fiber.Ctx) (err error) {
if err != nil {
return errors.Wrap(err, errors.DatabaseError)
}

// If this is the first time for the poster to post a comment, the reward the inviter.
var user models.User
err = tx.First(&user, uid).Error
if err != nil {
return errors.Wrap(err, errors.DatabaseError)
}

if user.HasPostedComments {
return nil
}
user.HasPostedComments = true
tx.Save(user)

if user.InvitedByUserID == 0 {
return nil
}
inviter, err := queries.GetUserByID(tx, user.InvitedByUserID)
if err != nil {
return errors.Wrap(err, errors.DatabaseError)
}
inviter.Reward += 100
tx.Save(inviter)

return nil
})
if err != nil {
Expand Down
57 changes: 57 additions & 0 deletions internal/controllers/comments/recent_by_page.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,57 @@
package comments

import (
"coursebench-backend/internal/middlewares/session"
"coursebench-backend/internal/utils"
"coursebench-backend/pkg/database"
"coursebench-backend/pkg/errors"
"coursebench-backend/pkg/models"
"strconv"

"github.com/gofiber/fiber/v2"
)

type RecentCommentByPageResponse struct {
PageCount int64 `json:"page_count"`
HasMore bool `json:"has_more"`
Comments []CommentResponse `json:"comments"`
}

func RecentCommentByPage(c *fiber.Ctx) (err error) {
uid, err := session.GetUserID(c)
if err != nil {
uid = 0
}

id_s := c.Params("id", "1")
id, err := strconv.Atoi(id_s)
if err != nil {
return errors.New(errors.InvalidArgument)
}

db := database.GetDB()
var comments []models.Comment
var count int64
result := db.Preload("User").Preload("CourseGroup").Preload("CourseGroup.Course").Preload("CourseGroup.Teachers").Count(&count).
Order("update_time DESC").Offset((id - 1) * 30).Limit(30).Find(&comments)
if err := result.Error; err != nil {
return errors.Wrap(err, errors.DatabaseError)
}

var likeResult []CommentLikeResult
if uid != 0 {
db.Raw("SELECT comment_likes.comment_id, comment_likes.is_like from comments, comment_likes where comment_likes.user_id = ? and comment_likes.comment_id = comments.id and comment_likes.deleted_at is NULL and comments.deleted_at is NULL order by create_time desc OFFSET ? LIMIT 30",
(id-1)*30,
uid).Scan(&likeResult)
}
var response []CommentResponse
response = GenerateResponse(comments, uid, likeResult, true, utils.GetIP(c))
return c.Status(fiber.StatusOK).JSON(models.OKResponse{
Data: RecentCommentByPageResponse{
PageCount: (count + 29) / 30, // ceil
HasMore: count > int64(id)*30,
Comments: response,
},
Error: false,
})
}
1 change: 1 addition & 0 deletions internal/controllers/reward.go
Original file line number Diff line number Diff line change
Expand Up @@ -9,4 +9,5 @@ import (
func RewardRoutes(r fiber.Router) {
route := r.Group("/reward")
route.Get("/ranklist", reward.Ranklist)
route.Post("/set/:id", reward.SetComment)
}
71 changes: 71 additions & 0 deletions internal/controllers/reward/setcomment.go
Original file line number Diff line number Diff line change
@@ -0,0 +1,71 @@
package reward

import (
"coursebench-backend/internal/middlewares/session"
"coursebench-backend/pkg/database"
"coursebench-backend/pkg/errors"
"coursebench-backend/pkg/models"
"coursebench-backend/pkg/queries"
"strconv"

"github.com/gofiber/fiber/v2"
"gorm.io/gorm"
)

type SetCommentRequest struct {
Reward int `json:"reward"`
}

func SetComment(c *fiber.Ctx) error {
c.Accepts("application/json")
var request SetCommentRequest
if err := c.BodyParser(&request); err != nil {
return errors.Wrap(err, errors.InvalidArgument)
}

idRaw := c.Params("id", "GG")
id, err := strconv.Atoi(idRaw)
if err != nil {
return errors.New(errors.InvalidArgument)
}

uid, err := session.GetUserID(c)
if err != nil {
uid = 0
}

db := database.GetDB()
user, err := queries.GetUserByID(db, uid)
if err != nil {
return errors.Wrap(err, errors.DatabaseError)
}
if !(user.IsCommunityAdmin || user.IsAdmin) {
return errors.New(errors.PermissionDenied)
}

comment := &models.Comment{}
result := db.First(&comment, id)
if result.Error != nil {
return errors.Wrap(result.Error, errors.DatabaseError)
}

comment.User.Reward -= comment.Reward
comment.Reward = request.Reward
comment.User.Reward += comment.Reward

if err := db.Transaction(func(tx *gorm.DB) error {
if err := tx.Save(comment).Error; err != nil {
return err
}
if err := tx.Save(user).Error; err != nil {
return err
}
return nil
}); err != nil {
return errors.Wrap(err, errors.DatabaseError)
}

return c.Status(fiber.StatusOK).JSON(models.OKResponse{
Error: false,
})
}
28 changes: 15 additions & 13 deletions pkg/models/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -17,19 +17,21 @@ const (

type User struct {
gorm.Model
Email string `gorm:"index"`
Password string
NickName string
RealName string
Year int
Grade GradeType
IsActive bool
Avatar string
IsAnonymous bool
IsAdmin bool `gorm:"default:false"`
IsCommunityAdmin bool `gorm:"default:false"`
InvitationCode string
Reward int
Email string `gorm:"index"`
Password string
NickName string
RealName string
Year int
Grade GradeType
IsActive bool
Avatar string
IsAnonymous bool
IsAdmin bool `gorm:"default:false"`
IsCommunityAdmin bool `gorm:"default:false"`
InvitationCode string
InvitedByUserID uint
Reward int
HasPostedComments bool `gorm:"default:false"`
}

func init() {
Expand Down
35 changes: 23 additions & 12 deletions pkg/queries/user.go
Original file line number Diff line number Diff line change
Expand Up @@ -103,15 +103,18 @@ func Register(db *gorm.DB, u *models.User, invitation_code string) error {

// check if the invitation code is valid
if invitation_code != "" {
taken, err := isInvitationCodeTaken(db, invitation_code)
inviter, err := GetUserByInvitationCode(db, invitation_code)
if err != nil {
if errors.Is(err, errors.UserNotExists) {
return errors.New(errors.InvitationCodeInvalid)
}
return err
}
if !taken {
return errors.New(errors.InvitationCodeInvalid)
}

// TODO: Inform the inviter
u.InvitedByUserID = inviter.ID
// TODO: only once for the inviter?
inviter.Reward += 100
db.Save(inviter)
}

// 检查邮箱是否已存在
Expand Down Expand Up @@ -445,23 +448,31 @@ func createInvitationCode(db *gorm.DB) (string, error) {
}
code := string(codeRunes)

taken, err := isInvitationCodeTaken(db, code)
_, err := GetUserByInvitationCode(db, code)
if err != nil {
if errors.Is(err, errors.UserNotExists) {
return code, nil
}
return "", err
}
if !taken {
return code, nil
}
}

return "", errors.New(errors.InternalServerError)
}

func isInvitationCodeTaken(db *gorm.DB, code string) (bool, error) {
func GetUserByInvitationCode(db *gorm.DB, code string) (*models.User, error) {
if db == nil {
db = database.GetDB()
}

user := &models.User{}
result := db.Where("invitation_code = ?", code).Take(user)
if err := result.Error; err != nil && !errors.Is(err, gorm.ErrRecordNotFound) {
return false, errors.Wrap(err, errors.DatabaseError)
return nil, errors.Wrap(err, errors.DatabaseError)
}
if result.RowsAffected == 0 {
return nil, errors.New(errors.UserNotExists)
}
return result.RowsAffected != 0, nil

return user, nil
}

0 comments on commit 0f2a936

Please sign in to comment.