2017-03-11 11:46:53 +03:00
// Copyright 2017 The Gitea Authors. All rights reserved.
2022-11-27 21:20:29 +03:00
// SPDX-License-Identifier: MIT
2017-03-11 11:46:53 +03:00
2021-11-17 12:58:31 +03:00
package user
2017-03-11 11:46:53 +03:00
2020-10-13 03:01:57 +03:00
import (
2023-09-16 17:39:12 +03:00
"context"
2021-09-19 14:49:59 +03:00
"code.gitea.io/gitea/models/db"
2020-10-13 03:01:57 +03:00
"code.gitea.io/gitea/modules/timeutil"
)
2022-06-26 01:50:12 +03:00
// Follow represents relations of user and their followers.
2017-03-11 11:46:53 +03:00
type Follow struct {
2020-10-13 03:01:57 +03:00
ID int64 ` xorm:"pk autoincr" `
UserID int64 ` xorm:"UNIQUE(follow)" `
FollowID int64 ` xorm:"UNIQUE(follow)" `
CreatedUnix timeutil . TimeStamp ` xorm:"INDEX created" `
2017-03-11 11:46:53 +03:00
}
2021-09-19 14:49:59 +03:00
func init ( ) {
db . RegisterModel ( new ( Follow ) )
}
2017-03-11 11:46:53 +03:00
// IsFollowing returns true if user is following followID.
2023-09-16 17:39:12 +03:00
func IsFollowing ( ctx context . Context , userID , followID int64 ) bool {
has , _ := db . GetEngine ( ctx ) . Get ( & Follow { UserID : userID , FollowID : followID } )
2017-03-11 11:46:53 +03:00
return has
}
// FollowUser marks someone be another's follower.
2024-03-04 11:16:03 +03:00
func FollowUser ( ctx context . Context , user , follow * User ) ( err error ) {
if user . ID == follow . ID || IsFollowing ( ctx , user . ID , follow . ID ) {
2017-03-11 11:46:53 +03:00
return nil
}
2024-03-04 11:16:03 +03:00
if IsUserBlockedBy ( ctx , user , follow . ID ) || IsUserBlockedBy ( ctx , follow , user . ID ) {
return ErrBlockedUser
}
2023-09-16 17:39:12 +03:00
ctx , committer , err := db . TxContext ( ctx )
2021-11-21 18:41:00 +03:00
if err != nil {
2017-03-11 11:46:53 +03:00
return err
}
2021-11-21 18:41:00 +03:00
defer committer . Close ( )
2017-03-11 11:46:53 +03:00
2024-03-04 11:16:03 +03:00
if err = db . Insert ( ctx , & Follow { UserID : user . ID , FollowID : follow . ID } ) ; err != nil {
2017-03-11 11:46:53 +03:00
return err
}
2024-03-04 11:16:03 +03:00
if _ , err = db . Exec ( ctx , "UPDATE `user` SET num_followers = num_followers + 1 WHERE id = ?" , follow . ID ) ; err != nil {
2017-03-11 11:46:53 +03:00
return err
}
2024-03-04 11:16:03 +03:00
if _ , err = db . Exec ( ctx , "UPDATE `user` SET num_following = num_following + 1 WHERE id = ?" , user . ID ) ; err != nil {
2017-03-11 11:46:53 +03:00
return err
}
2021-11-21 18:41:00 +03:00
return committer . Commit ( )
2017-03-11 11:46:53 +03:00
}
// UnfollowUser unmarks someone as another's follower.
2023-09-16 17:39:12 +03:00
func UnfollowUser ( ctx context . Context , userID , followID int64 ) ( err error ) {
if userID == followID || ! IsFollowing ( ctx , userID , followID ) {
2017-03-11 11:46:53 +03:00
return nil
}
2023-09-16 17:39:12 +03:00
ctx , committer , err := db . TxContext ( ctx )
2021-11-21 18:41:00 +03:00
if err != nil {
2017-03-11 11:46:53 +03:00
return err
}
2021-11-21 18:41:00 +03:00
defer committer . Close ( )
2017-03-11 11:46:53 +03:00
2021-11-21 18:41:00 +03:00
if _ , err = db . DeleteByBean ( ctx , & Follow { UserID : userID , FollowID : followID } ) ; err != nil {
2017-03-11 11:46:53 +03:00
return err
}
2021-11-21 18:41:00 +03:00
if _ , err = db . Exec ( ctx , "UPDATE `user` SET num_followers = num_followers - 1 WHERE id = ?" , followID ) ; err != nil {
2017-03-11 11:46:53 +03:00
return err
}
2021-11-21 18:41:00 +03:00
if _ , err = db . Exec ( ctx , "UPDATE `user` SET num_following = num_following - 1 WHERE id = ?" , userID ) ; err != nil {
2017-03-11 11:46:53 +03:00
return err
}
2021-11-21 18:41:00 +03:00
return committer . Commit ( )
2017-03-11 11:46:53 +03:00
}