2016-12-29 17:58:24 +03:00
// Copyright 2016 The Gitea Authors. All rights reserved.
2022-11-27 21:20:29 +03:00
// SPDX-License-Identifier: MIT
2016-12-29 17:58:24 +03:00
2021-12-12 18:48:20 +03:00
package repo
2016-12-29 17:58:24 +03:00
2020-10-13 03:01:57 +03:00
import (
2022-05-20 17:08:52 +03:00
"context"
2021-09-19 14:49:59 +03:00
"code.gitea.io/gitea/models/db"
2021-11-24 12:49:20 +03:00
user_model "code.gitea.io/gitea/models/user"
2020-10-13 03:01:57 +03:00
"code.gitea.io/gitea/modules/timeutil"
)
2016-12-29 17:58:24 +03:00
// Star represents a starred repo by an user.
type Star struct {
2020-10-13 03:01:57 +03:00
ID int64 ` xorm:"pk autoincr" `
UID int64 ` xorm:"UNIQUE(s)" `
RepoID int64 ` xorm:"UNIQUE(s)" `
CreatedUnix timeutil . TimeStamp ` xorm:"INDEX created" `
2016-12-29 17:58:24 +03:00
}
2021-09-19 14:49:59 +03:00
func init ( ) {
db . RegisterModel ( new ( Star ) )
}
2016-12-29 17:58:24 +03:00
// StarRepo or unstar repository.
2024-03-04 11:16:03 +03:00
func StarRepo ( ctx context . Context , doer * user_model . User , repo * Repository , star bool ) error {
2023-09-15 09:13:19 +03:00
ctx , committer , err := db . TxContext ( ctx )
2021-11-21 18:41:00 +03:00
if err != nil {
2016-12-29 17:58:24 +03:00
return err
}
2021-11-21 18:41:00 +03:00
defer committer . Close ( )
2024-03-04 11:16:03 +03:00
staring := IsStaring ( ctx , doer . ID , repo . ID )
2016-12-29 17:58:24 +03:00
if star {
2024-03-04 11:16:03 +03:00
if user_model . IsUserBlockedBy ( ctx , doer , repo . OwnerID ) {
return user_model . ErrBlockedUser
}
2021-11-21 18:41:00 +03:00
if staring {
2016-12-29 17:58:24 +03:00
return nil
}
2024-03-04 11:16:03 +03:00
if err := db . Insert ( ctx , & Star { UID : doer . ID , RepoID : repo . ID } ) ; err != nil {
2016-12-29 17:58:24 +03:00
return err
}
2024-03-04 11:16:03 +03:00
if _ , err := db . Exec ( ctx , "UPDATE `repository` SET num_stars = num_stars + 1 WHERE id = ?" , repo . ID ) ; err != nil {
2016-12-29 17:58:24 +03:00
return err
}
2024-03-04 11:16:03 +03:00
if _ , err := db . Exec ( ctx , "UPDATE `user` SET num_stars = num_stars + 1 WHERE id = ?" , doer . ID ) ; err != nil {
2016-12-29 17:58:24 +03:00
return err
}
} else {
2021-11-21 18:41:00 +03:00
if ! staring {
2016-12-29 17:58:24 +03:00
return nil
}
2024-03-04 11:16:03 +03:00
if _ , err := db . DeleteByBean ( ctx , & Star { UID : doer . ID , RepoID : repo . ID } ) ; err != nil {
2016-12-29 17:58:24 +03:00
return err
}
2024-03-04 11:16:03 +03:00
if _ , err := db . Exec ( ctx , "UPDATE `repository` SET num_stars = num_stars - 1 WHERE id = ?" , repo . ID ) ; err != nil {
2016-12-29 17:58:24 +03:00
return err
}
2024-03-04 11:16:03 +03:00
if _ , err := db . Exec ( ctx , "UPDATE `user` SET num_stars = num_stars - 1 WHERE id = ?" , doer . ID ) ; err != nil {
2016-12-29 17:58:24 +03:00
return err
}
}
2021-11-21 18:41:00 +03:00
return committer . Commit ( )
2016-12-29 17:58:24 +03:00
}
// IsStaring checks if user has starred given repository.
2022-05-20 17:08:52 +03:00
func IsStaring ( ctx context . Context , userID , repoID int64 ) bool {
has , _ := db . GetEngine ( ctx ) . Get ( & Star { UID : userID , RepoID : repoID } )
2016-12-29 17:58:24 +03:00
return has
}
// GetStargazers returns the users that starred the repo.
2023-09-15 09:13:19 +03:00
func GetStargazers ( ctx context . Context , repo * Repository , opts db . ListOptions ) ( [ ] * user_model . User , error ) {
sess := db . GetEngine ( ctx ) . Where ( "star.repo_id = ?" , repo . ID ) .
2017-01-06 10:05:09 +03:00
Join ( "LEFT" , "star" , "`user`.id = star.uid" )
2020-01-24 22:00:29 +03:00
if opts . Page > 0 {
2021-09-24 14:32:56 +03:00
sess = db . SetSessionPagination ( sess , & opts )
2020-01-24 22:00:29 +03:00
2021-11-24 12:49:20 +03:00
users := make ( [ ] * user_model . User , 0 , opts . PageSize )
2020-01-24 22:00:29 +03:00
return users , sess . Find ( & users )
2017-01-06 10:05:09 +03:00
}
2020-01-24 22:00:29 +03:00
2021-11-24 12:49:20 +03:00
users := make ( [ ] * user_model . User , 0 , 8 )
2017-01-06 10:05:09 +03:00
return users , sess . Find ( & users )
2016-12-29 17:58:24 +03:00
}
2023-06-05 16:25:43 +03:00
// ClearRepoStars clears all stars for a repository and from the user that starred it.
// Used when a repository is set to private.
func ClearRepoStars ( ctx context . Context , repoID int64 ) error {
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 {
return err
}
if _ , err := db . Exec ( ctx , "UPDATE `repository` SET num_stars = 0 WHERE id = ?" , repoID ) ; err != nil {
return err
}
return db . DeleteBeans ( ctx , Star { RepoID : repoID } )
}