code.gitea.io/gitea@v1.22.3/models/repo/star.go (about) 1 // Copyright 2016 The Gitea Authors. All rights reserved. 2 // SPDX-License-Identifier: MIT 3 4 package repo 5 6 import ( 7 "context" 8 9 "code.gitea.io/gitea/models/db" 10 user_model "code.gitea.io/gitea/models/user" 11 "code.gitea.io/gitea/modules/timeutil" 12 ) 13 14 // Star represents a starred repo by an user. 15 type Star struct { 16 ID int64 `xorm:"pk autoincr"` 17 UID int64 `xorm:"UNIQUE(s)"` 18 RepoID int64 `xorm:"UNIQUE(s)"` 19 CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"` 20 } 21 22 func init() { 23 db.RegisterModel(new(Star)) 24 } 25 26 // StarRepo or unstar repository. 27 func StarRepo(ctx context.Context, doer *user_model.User, repo *Repository, star bool) error { 28 ctx, committer, err := db.TxContext(ctx) 29 if err != nil { 30 return err 31 } 32 defer committer.Close() 33 staring := IsStaring(ctx, doer.ID, repo.ID) 34 35 if star { 36 if user_model.IsUserBlockedBy(ctx, doer, repo.OwnerID) { 37 return user_model.ErrBlockedUser 38 } 39 40 if staring { 41 return nil 42 } 43 44 if err := db.Insert(ctx, &Star{UID: doer.ID, RepoID: repo.ID}); err != nil { 45 return err 46 } 47 if _, err := db.Exec(ctx, "UPDATE `repository` SET num_stars = num_stars + 1 WHERE id = ?", repo.ID); err != nil { 48 return err 49 } 50 if _, err := db.Exec(ctx, "UPDATE `user` SET num_stars = num_stars + 1 WHERE id = ?", doer.ID); err != nil { 51 return err 52 } 53 } else { 54 if !staring { 55 return nil 56 } 57 58 if _, err := db.DeleteByBean(ctx, &Star{UID: doer.ID, RepoID: repo.ID}); err != nil { 59 return err 60 } 61 if _, err := db.Exec(ctx, "UPDATE `repository` SET num_stars = num_stars - 1 WHERE id = ?", repo.ID); err != nil { 62 return err 63 } 64 if _, err := db.Exec(ctx, "UPDATE `user` SET num_stars = num_stars - 1 WHERE id = ?", doer.ID); err != nil { 65 return err 66 } 67 } 68 69 return committer.Commit() 70 } 71 72 // IsStaring checks if user has starred given repository. 73 func IsStaring(ctx context.Context, userID, repoID int64) bool { 74 has, _ := db.GetEngine(ctx).Get(&Star{UID: userID, RepoID: repoID}) 75 return has 76 } 77 78 // GetStargazers returns the users that starred the repo. 79 func GetStargazers(ctx context.Context, repo *Repository, opts db.ListOptions) ([]*user_model.User, error) { 80 sess := db.GetEngine(ctx).Where("star.repo_id = ?", repo.ID). 81 Join("LEFT", "star", "`user`.id = star.uid") 82 if opts.Page > 0 { 83 sess = db.SetSessionPagination(sess, &opts) 84 85 users := make([]*user_model.User, 0, opts.PageSize) 86 return users, sess.Find(&users) 87 } 88 89 users := make([]*user_model.User, 0, 8) 90 return users, sess.Find(&users) 91 } 92 93 // ClearRepoStars clears all stars for a repository and from the user that starred it. 94 // Used when a repository is set to private. 95 func ClearRepoStars(ctx context.Context, repoID int64) error { 96 if _, err := db.Exec(ctx, "UPDATE `user` SET num_stars=num_stars-1 WHERE id IN (SELECT `uid` FROM `star` WHERE repo_id = ?)", repoID); err != nil { 97 return err 98 } 99 100 if _, err := db.Exec(ctx, "UPDATE `repository` SET num_stars = 0 WHERE id = ?", repoID); err != nil { 101 return err 102 } 103 104 return db.DeleteBeans(ctx, Star{RepoID: repoID}) 105 }