Files
huangguo_server/app/service/followser/followser.go
T
rootandClaude Opus 5 8679200f41 Initial commit
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-15 13:57:10 +08:00

361 lines
12 KiB
Go

package followser
import (
"91porn-server/app/appg"
"91porn-server/app/service/vidhelpser"
"91porn-server/common/log"
"91porn-server/common/services/follow"
"91porn-server/common/stderr"
topser "91porn-server/common/top"
"91porn-server/common/top/weektop"
"91porn-server/models/commod"
"91porn-server/models/v/followmod"
"91porn-server/models/v/usermod"
"91porn-server/models/v/vidmod"
"errors"
"fmt"
goredis "github.com/go-redis/redis"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo/options"
"strconv"
"time"
)
func encodeUserBase(uids []uint64, uInfo []*usermod.BaseInfoVip, mModel map[uint64]followmod.FollowModel, mFollow map[uint64]bool) []*followmod.BaseInfo {
var infos []*followmod.BaseInfo
mInfo := make(map[uint64]usermod.BaseInfoVip)
for _, u := range uInfo {
if u == nil {
continue
}
mInfo[u.UID] = *u
}
for _, u := range uids {
bi := followmod.BaseInfo{
UID: u,
Name: mInfo[u].Name,
Gender: mInfo[u].Gender,
Portrait: mInfo[u].Portrait,
HasLocked: mInfo[u].HasLocked,
HasBanned: mInfo[u].HasBanned,
VipLevel: mInfo[u].VipLevel,
IsVip: mInfo[u].IsVip,
HasFollow: true,
Via: mModel[u].Via,
Fans: mInfo[u].Fans,
Summary: mInfo[u].Summary,
CreatedAt: mModel[u].CreatedAt,
SuperUser: mInfo[u].SuperUser,
Awards: mInfo[u].Awards,
TotalWorks: mInfo[u].TotalWorks,
}
infos = append(infos, &bi)
}
return infos
}
// GetHisFollowList 获取他关注列表
func GetHisFollowList(uid, oid uint64, page int, size int) (code stderr.Code, data interface{}) {
uids, mModel, hasNext, err := followmod.GetFollowList(oid, page, size, false)
if err != nil {
return stderr.ErrDbQueryError, nil
}
uInfos, err := usermod.GetUsersBaseInfoWithVip(uids)
if err != nil {
return stderr.ErrDbQueryError, nil
}
mFollow, err := followmod.IsFollowedByUsers(uid, uids)
if err != nil {
return stderr.ErrDbQueryError, nil
}
datas := encodeUserBase(uids, uInfos, mModel, mFollow)
data = followmod.ListResp{List: datas, HasNext: hasNext}
return stderr.Success, data
}
// GetFollowList 获取关注列表
func GetFollowList(uid uint64, page int, size int, isShort bool) (code stderr.Code, data interface{}) {
uids, mModel, hasNext, err := followmod.GetFollowList(uid, page, size, isShort)
if err != nil {
return stderr.ErrDbQueryError, nil
}
uInfos, err := usermod.GetUsersBaseInfoWithVip(uids)
if err != nil {
return stderr.ErrDbQueryError, nil
}
mFollow, err := followmod.IsFollowedByUsers(uid, uids)
if err != nil {
return stderr.ErrDbQueryError, nil
}
datas := encodeUserBase(uids, uInfos, mModel, mFollow)
data = followmod.ListResp{List: datas, HasNext: hasNext}
return stderr.Success, data
}
// GetHisFansList 获取他的粉丝列表
func GetHisFansList(uid, oid uint64, page int, size int) (code stderr.Code, data interface{}) {
uids, mModel, hasNext, err := followmod.GetFansList(oid, page, size)
if err != nil {
return stderr.ErrDbQueryError, nil
}
uInfos, err := usermod.GetUsersBaseInfoWithVip(uids)
if err != nil {
return stderr.ErrDbQueryError, nil
}
mFollow, err := followmod.IsFollowUsers(uid, uids)
if err != nil {
return stderr.ErrDbQueryError, nil
}
datas := encodeUserBase(uids, uInfos, mModel, mFollow)
data = followmod.ListResp{List: datas, HasNext: hasNext}
return stderr.Success, data
}
// GetFansList 获取粉丝列表
func GetFansList(uid uint64, page int, size int) (code stderr.Code, data interface{}) {
uids, mModel, hasNext, err := followmod.GetFansList(uid, page, size)
if err != nil {
return stderr.ErrDbQueryError, nil
}
uInfos, err := usermod.GetUsersBaseInfoWithVip(uids)
if err != nil {
return stderr.ErrDbQueryError, nil
}
mFollow, err := followmod.IsFollowUsers(uid, uids)
if err != nil {
return stderr.ErrDbQueryError, nil
}
datas := encodeUserBase(uids, uInfos, mModel, mFollow)
data = followmod.ListResp{List: datas, HasNext: hasNext}
return stderr.Success, data
}
// GetDynamicsList 获取关注用户动态
func GetDynamicsList(uid uint64, req followmod.AppDynamicsListReq) (data followmod.DynamicsResp, code stderr.Code) {
// 处理用户关注消息状态
_ = follow.CancelTip(uid)
var infos []*vidmod.VideoModel
// 获取官方帖子
//vid, err := vidmod.FindOneByUid(bson.M{"publisherID": 100000, "newsType": "COVER", "status": 1})
//if err != nil {
// return stderr.ErrDbQueryError, nil
//}
//
//if vid != nil && !vid.ID.IsZero() {
// infos = append(infos, vid)
//}
uids, err := followmod.GetTotalFollowList(uid)
if err != nil {
return data, stderr.ErrDbQueryError
}
if len(uids) == 0 {
//if len(infos) > 0 {
// list := vidhelpser.EncodeVideoInfo(uid, infos)
// data = followmod.DynamicsResp{VInfos: list, List: list, TotalPages: 1, HasNext: false}
//} else {
//data = followmod.DynamicsResp{VInfos: nil, List: nil, HasNext: false, TotalPages: 0}
//}
return data, stderr.Success
}
filter := bson.M{
"publisherID": bson.M{"$in": uids},
"newsType": vidmod.SHORT, // 默认短视频
"status": vidmod.CheckPass,
}
if req.NewsType != "" {
filter["newsType"] = req.NewsType
}
sort := bson.D{{Key: "reviewAt", Value: -1}}
opt := options.Find().SetSkip(req.Skip64()).SetLimit(req.Limit64()).SetSort(sort)
videos, hasNext, err := vidmod.FindList(filter, opt)
if err != nil {
return data, stderr.ErrDbQueryError
}
if len(videos) == 0 {
//if len(infos) > 0 {
// list := vidhelpser.EncodeVideoInfo(uid, infos)
// data = followmod.DynamicsResp{VInfos: list, List: list, TotalPages: 1, HasNext: false}
//} else {
//data = followmod.DynamicsResp{VInfos: nil, List: nil, HasNext: false, TotalPages: 0}
//}
return data, stderr.Success
}
infos = append(infos, videos...)
list := vidhelpser.EncodeVideoInfo(uid, infos)
data = followmod.DynamicsResp{VInfos: list, List: list, TotalPages: 0, HasNext: hasNext}
return data, stderr.Success
}
// 短视频-获取关注用户和作品,若无关注,则获取推荐用户及作品
type (
GetFollowUpUsersWithShortReq struct {
commod.Page
ShowType int `json:"showType" form:"showType"` //0:优先获取已关注没有则获取推荐 1:已关注 2:推荐
}
GetFollowUpUsersWithShortRep struct {
RecoUsers []*RecoUser `json:"recoUsers"` // 官方推荐(没有关注用户则使用此数据)
//FollowUsers []*UserInfo `json:"followUsers"` // 已关注的博主列表
List []*vidmod.VideoInfo `json:"list"` // 已关注的博主发布的视频列表
ShowType int `json:"showType"` // 1:已关注 2:推荐
HasNext bool `json:"hasNext"` // 是否有下一页
}
UserInfo struct {
Uid uint64 `json:"uid" bson:"uid"` //UID
Gender string `json:"gender" bson:"gender"` //性别
Name string `json:"name" bson:"name"` //姓名
Portrait string `json:"portrait" bson:"portrait"` //头像
Fans int64 `json:"fans" bson:"fans"` //粉丝数
Summary string `json:"summary" bson:"summary"` //简介
OfficialCert bool `json:"officialCert" bson:"officialCert"` //是否官方认证
IsFollow bool `json:"isFollow"` //是否关注
TotalWorks int64 `json:"totalWorks" bson:"totalWorks"` // 总作品数
}
RecoUser struct {
UserInfo UserInfo `json:"userInfo"` // 用户信息
List []*vidmod.VideoBase `json:"list"` // 用户发布的视频信息
}
)
// GetFollowUpUserListWithShort 获取用户关注的UP主短视频 或 短视频推荐UP主以及UP主发布的短视频
func (req *GetFollowUpUsersWithShortReq) GetFollowUpUserListWithShort(uid uint64) (data GetFollowUpUsersWithShortRep, code stderr.Code) {
if req.ShowType <= 1 {
data, code = req.GetFollowUpUserListAndShortVideo(uid)
if code != stderr.Success || data.ShowType == 1 {
return data, code
}
}
// 短视频推荐
data, code = req.getRecoUserByShortVideo()
return data, stderr.Success
}
// GetFollowUpUserListAndShortVideo 获取关注用户和用户下的短视频
func (req *GetFollowUpUsersWithShortReq) GetFollowUpUserListAndShortVideo(uid uint64) (data GetFollowUpUsersWithShortRep, code stderr.Code) {
// 已关注的用户列表不需要展示
var uids []uint64
uids, err := followmod.GetTotalFollowListLimit(uid, 30)
if err != nil {
return data, stderr.ErrDbQueryError
}
if len(uids) == 0 {
return data, stderr.Success
}
//users, err := usermod.FindUsersMapByUID(uids)
//if err != nil {
// return data, stderr.Failure
//}
//
//if len(users) == 0 {
// return data, stderr.Success
//}
//
//for _, user := range users {
// data.FollowUsers = append(data.FollowUsers, &UserInfo{
// Uid: user.UID,
// Gender: user.Gender,
// Name: user.Name,
// Portrait: user.Portrait,
// Fans: user.Fans,
// OfficialCert: user.OfficialCert,
// IsFollow: true,
// Summary: user.Summary,
// TotalWorks: user.TotalWorks,
// })
//}
cond := bson.M{"newsType": vidmod.SHORT, "publisherID": bson.M{"$in": uids}, "status": vidmod.CheckPass} // 下层函数已经设置过滤status
sort := bson.D{{Key: "reviewAt", Value: -1}}
videos, hasNext, err := vidmod.FindList(cond, options.Find().SetSort(sort).SetLimit(req.Limit64()).SetSkip(req.Skip64()))
if err != nil {
return data, stderr.Failure
}
list := vidhelpser.EncodeVideoInfo(uid, videos)
data.List = list
data.HasNext = hasNext
data.ShowType = 1 // 当前是关注用户
return data, stderr.Success
}
// getRecoUserByShortVideo 获取推荐用户
func (req *GetFollowUpUsersWithShortReq) getRecoUserByShortVideo() (data GetFollowUpUsersWithShortRep, code stderr.Code) {
req.PageSize = 6 // 短视频推荐每页固定条数
key := fmt.Sprintf("recoUserAndShortVideo:%d_%d", req.PageSize, req.PageNumber)
err := appg.Redis.GetWithJson2Any(key, &data)
if err == nil {
return data, stderr.Success
}
if !errors.Is(err, goredis.Nil) {
log.Warn("GetFollowUpUserPublishVideosReq.getRecoVideoList error", log.E(err))
}
defer func() {
_ = appg.Redis.SetWithAny2Json(key, data, time.Minute*5)
}()
recoUsers, _, hasNext := weektop.GetTopByPage(topser.TypeRecommendUser, req.Limit64(), req.Limit64()+1)
if len(recoUsers) > int(req.Limit64()) {
recoUsers = recoUsers[:req.Limit64()]
hasNext = true
}
if len(recoUsers) == 0 {
return data, stderr.Success
}
var (
dataMap = map[uint64]*RecoUser{}
uids []uint64
)
for _, v := range recoUsers {
uid, e := strconv.ParseUint(v, 10, 64)
if e != nil {
continue
}
uids = append(uids, uid)
}
users, err := usermod.FindUsersByUID(uids)
if err != nil {
return data, stderr.Failure
}
uids = uids[:0]
for _, user := range users {
recoUser := &RecoUser{
UserInfo: UserInfo{
Uid: user.UID,
Gender: user.Gender,
Name: user.Name,
Portrait: user.Portrait,
Fans: user.Fans,
Summary: user.Summary,
OfficialCert: user.OfficialCert,
TotalWorks: user.TotalWorks,
},
}
dataMap[user.UID] = recoUser
// 获取用户的视频
filterTmp := bson.M{"newsType": vidmod.SP, "publisherID": user.UID, "status": vidmod.CheckPass}
optTmp := options.Find().SetSort(bson.D{{"reviewAt", -1}}).SetLimit(6)
list, _, err := vidmod.FindList(filterTmp, optTmp)
if err != nil {
return data, stderr.Failure
}
for _, model := range list {
baseVid := vidhelpser.ToVideoBaseInfo(model, nil, 0)
recoUser.List = append(recoUser.List, baseVid)
}
data.RecoUsers = append(data.RecoUsers, recoUser)
}
data.HasNext = hasNext
data.ShowType = 2 // 当前是推荐用户
return data, stderr.Success
}