code.gitea.io/gitea@v1.22.3/models/user/follow.go (about)

     1  // Copyright 2017 The Gitea Authors. All rights reserved.
     2  // SPDX-License-Identifier: MIT
     3  
     4  package user
     5  
     6  import (
     7  	"context"
     8  
     9  	"code.gitea.io/gitea/models/db"
    10  	"code.gitea.io/gitea/modules/timeutil"
    11  )
    12  
    13  // Follow represents relations of user and their followers.
    14  type Follow struct {
    15  	ID          int64              `xorm:"pk autoincr"`
    16  	UserID      int64              `xorm:"UNIQUE(follow)"`
    17  	FollowID    int64              `xorm:"UNIQUE(follow)"`
    18  	CreatedUnix timeutil.TimeStamp `xorm:"INDEX created"`
    19  }
    20  
    21  func init() {
    22  	db.RegisterModel(new(Follow))
    23  }
    24  
    25  // IsFollowing returns true if user is following followID.
    26  func IsFollowing(ctx context.Context, userID, followID int64) bool {
    27  	has, _ := db.GetEngine(ctx).Get(&Follow{UserID: userID, FollowID: followID})
    28  	return has
    29  }
    30  
    31  // FollowUser marks someone be another's follower.
    32  func FollowUser(ctx context.Context, user, follow *User) (err error) {
    33  	if user.ID == follow.ID || IsFollowing(ctx, user.ID, follow.ID) {
    34  		return nil
    35  	}
    36  
    37  	if IsUserBlockedBy(ctx, user, follow.ID) || IsUserBlockedBy(ctx, follow, user.ID) {
    38  		return ErrBlockedUser
    39  	}
    40  
    41  	ctx, committer, err := db.TxContext(ctx)
    42  	if err != nil {
    43  		return err
    44  	}
    45  	defer committer.Close()
    46  
    47  	if err = db.Insert(ctx, &Follow{UserID: user.ID, FollowID: follow.ID}); err != nil {
    48  		return err
    49  	}
    50  
    51  	if _, err = db.Exec(ctx, "UPDATE `user` SET num_followers = num_followers + 1 WHERE id = ?", follow.ID); err != nil {
    52  		return err
    53  	}
    54  
    55  	if _, err = db.Exec(ctx, "UPDATE `user` SET num_following = num_following + 1 WHERE id = ?", user.ID); err != nil {
    56  		return err
    57  	}
    58  	return committer.Commit()
    59  }
    60  
    61  // UnfollowUser unmarks someone as another's follower.
    62  func UnfollowUser(ctx context.Context, userID, followID int64) (err error) {
    63  	if userID == followID || !IsFollowing(ctx, userID, followID) {
    64  		return nil
    65  	}
    66  
    67  	ctx, committer, err := db.TxContext(ctx)
    68  	if err != nil {
    69  		return err
    70  	}
    71  	defer committer.Close()
    72  
    73  	if _, err = db.DeleteByBean(ctx, &Follow{UserID: userID, FollowID: followID}); err != nil {
    74  		return err
    75  	}
    76  
    77  	if _, err = db.Exec(ctx, "UPDATE `user` SET num_followers = num_followers - 1 WHERE id = ?", followID); err != nil {
    78  		return err
    79  	}
    80  
    81  	if _, err = db.Exec(ctx, "UPDATE `user` SET num_following = num_following - 1 WHERE id = ?", userID); err != nil {
    82  		return err
    83  	}
    84  	return committer.Commit()
    85  }