Files
common-server-public/bbs-go/server/internal/services/user_follow_service.go
2025-03-03 17:43:50 +08:00

258 lines
7.0 KiB
Go

package services
import (
"bbs-go/internal/cache"
"bbs-go/internal/models"
"bbs-go/internal/models/constants"
"bbs-go/internal/pkg/event"
"bbs-go/internal/repositories"
"github.com/emirpasic/gods/sets/hashset"
"github.com/mlogclub/simple/common/dates"
"github.com/mlogclub/simple/sqls"
"github.com/mlogclub/simple/web/params"
"gorm.io/gorm"
)
var UserFollowService = newUserFollowService()
func newUserFollowService() *userFollowService {
return &userFollowService{}
}
type userFollowService struct {
}
func (s *userFollowService) Get(id int64) *models.UserFollow {
return repositories.UserFollowRepository.Get(sqls.DB(), id)
}
func (s *userFollowService) Take(where ...interface{}) *models.UserFollow {
return repositories.UserFollowRepository.Take(sqls.DB(), where...)
}
func (s *userFollowService) Find(cnd *sqls.Cnd) []models.UserFollow {
return repositories.UserFollowRepository.Find(sqls.DB(), cnd)
}
func (s *userFollowService) FindOne(cnd *sqls.Cnd) *models.UserFollow {
return repositories.UserFollowRepository.FindOne(sqls.DB(), cnd)
}
func (s *userFollowService) FindPageByParams(params *params.QueryParams) (list []models.UserFollow, paging *sqls.Paging) {
return repositories.UserFollowRepository.FindPageByParams(sqls.DB(), params)
}
func (s *userFollowService) FindPageByCnd(cnd *sqls.Cnd) (list []models.UserFollow, paging *sqls.Paging) {
return repositories.UserFollowRepository.FindPageByCnd(sqls.DB(), cnd)
}
func (s *userFollowService) Count(cnd *sqls.Cnd) int64 {
return repositories.UserFollowRepository.Count(sqls.DB(), cnd)
}
func (s *userFollowService) Create(t *models.UserFollow) error {
return repositories.UserFollowRepository.Create(sqls.DB(), t)
}
func (s *userFollowService) Update(t *models.UserFollow) error {
return repositories.UserFollowRepository.Update(sqls.DB(), t)
}
func (s *userFollowService) Updates(id int64, columns map[string]interface{}) error {
return repositories.UserFollowRepository.Updates(sqls.DB(), id, columns)
}
func (s *userFollowService) UpdateColumn(id int64, name string, value interface{}) error {
return repositories.UserFollowRepository.UpdateColumn(sqls.DB(), id, name, value)
}
func (s *userFollowService) Delete(id int64) {
repositories.UserFollowRepository.Delete(sqls.DB(), id)
}
func (s *userFollowService) Follow(userId, otherId int64) error {
if userId == otherId {
// 自己关注自己,不进行处理。
// return errors.New("自己不能关注自己")
return nil
}
if s.IsFollowed(userId, otherId) {
return nil
}
err := sqls.DB().Transaction(func(tx *gorm.DB) error {
// 如果对方也关注了我,那么更新状态为互相关注
otherFollowed := tx.Exec("update t_user_follow set status = ? where user_id = ? and other_id = ?",
constants.FollowStatusBoth, otherId, userId).RowsAffected > 0
status := constants.FollowStatusFollow
if otherFollowed {
status = constants.FollowStatusBoth
}
if err := repositories.UserRepository.Updates(tx, userId, map[string]interface{}{
"follow_count": gorm.Expr("follow_count + 1"),
}); err != nil {
return err
}
cache.UserCache.Invalidate(userId)
if err := repositories.UserRepository.Updates(tx, otherId, map[string]interface{}{
"fans_count": gorm.Expr("fans_count + 1"),
}); err != nil {
return err
}
cache.UserCache.Invalidate(otherId)
return repositories.UserFollowRepository.Create(tx, &models.UserFollow{
UserId: userId,
OtherId: otherId,
Status: status,
CreateTime: dates.NowTimestamp(),
})
})
if err != nil {
return err
}
// 发送mq消息
event.Send(event.FollowEvent{
UserId: userId,
OtherId: otherId,
})
return nil
}
func (s *userFollowService) UnFollow(userId, otherId int64) error {
if userId == otherId {
// 自己关注自己,不进行处理。
return nil
}
if !s.IsFollowed(userId, otherId) {
return nil
}
err := sqls.DB().Transaction(func(tx *gorm.DB) error {
success := tx.Where("user_id = ? and other_id = ?", userId, otherId).Delete(models.UserFollow{}).RowsAffected > 0
if success {
tx.Exec("update t_user_follow set status = ? where user_id = ? and other_id = ?",
constants.FollowStatusFollow, otherId, userId)
}
if err := tx.Model(&models.User{}).Where("id = ? and follow_count > 0", userId).Updates(map[string]interface{}{
"follow_count": gorm.Expr("follow_count - 1"),
}).Error; err != nil {
return err
}
cache.UserCache.Invalidate(userId)
if err := tx.Model(&models.User{}).Where("id = ? and fans_count > 0", otherId).Updates(map[string]interface{}{
"fans_count": gorm.Expr("fans_count - 1"),
}).Error; err != nil {
return err
}
cache.UserCache.Invalidate(otherId)
return nil
})
if err != nil {
return err
}
// 发送mq消息
event.Send(event.UnFollowEvent{
UserId: userId,
OtherId: otherId,
})
return nil
}
// GetFans 粉丝列表
func (s *userFollowService) GetFans(userId int64, cursor int64, limit int) (itemList []int64, nextCursor int64, hasMore bool) {
cnd := sqls.NewCnd().Eq("other_id", userId)
if cursor > 0 {
cnd.Lt("id", cursor)
}
cnd.Desc("id").Limit(limit)
list := repositories.UserFollowRepository.Find(sqls.DB(), cnd)
if len(list) > 0 {
nextCursor = list[len(list)-1].Id
hasMore = len(list) >= limit
for _, e := range list {
itemList = append(itemList, e.UserId)
}
} else {
nextCursor = cursor
}
return
}
// GetFollows 关注列表
func (s *userFollowService) GetFollows(userId int64, cursor int64, limit int) (itemList []int64, nextCursor int64, hasMore bool) {
cnd := sqls.NewCnd().Eq("user_id", userId)
if cursor > 0 {
cnd.Lt("id", cursor)
}
cnd.Desc("id").Limit(limit)
list := repositories.UserFollowRepository.Find(sqls.DB(), cnd)
if len(list) > 0 {
nextCursor = list[len(list)-1].Id
hasMore = len(list) >= limit
for _, e := range list {
itemList = append(itemList, e.OtherId)
}
} else {
nextCursor = cursor
}
return
}
// ScanFans 扫描粉丝
func (s *userFollowService) ScanFans(userId int64, handle func(fansId int64)) {
var cursor int64 = 0
for {
list := s.Find(sqls.NewCnd().Eq("other_id", userId).Gt("id", cursor).Asc("id").Limit(100))
if len(list) == 0 {
break
}
cursor = list[len(list)-1].Id
for _, item := range list {
handle(item.UserId)
}
}
}
// ScanFollowed 扫描关注的用户
func (s *userFollowService) ScanFollowed(userId int64, handle func(followUserId int64)) {
var cursor int64 = 0
for {
list := s.Find(sqls.NewCnd().Eq("user_id", userId).Gt("id", cursor).Asc("id").Limit(100))
if len(list) == 0 {
break
}
cursor = list[len(list)-1].Id
for _, item := range list {
handle(item.OtherId)
}
}
}
func (s *userFollowService) IsFollowed(userId, otherId int64) bool {
if userId == otherId {
return false
}
set := s.IsFollowedUsers(userId, otherId)
return set.Contains(otherId)
}
func (s *userFollowService) IsFollowedUsers(userId int64, otherIds ...int64) hashset.Set {
set := hashset.New()
list := s.Find(sqls.NewCnd().Eq("user_id", userId).In("other_id", otherIds))
for _, follow := range list {
set.Add(follow.OtherId)
}
return *set
}