@@ -0,0 +1,67 @@
|
||||
package followmod
|
||||
|
||||
import (
|
||||
"91porn-server/models/commod"
|
||||
"91porn-server/models/v/vidmod"
|
||||
"time"
|
||||
)
|
||||
|
||||
// BaseInfo 返回的关注或者粉丝信息
|
||||
type BaseInfo struct { //用户id
|
||||
UID uint64 `json:"uid"` //名字
|
||||
Name string `json:"name"` //性别
|
||||
Gender string `json:"gender"` //头像
|
||||
Portrait string `json:"portrait"` //已禁止登陆
|
||||
HasLocked bool `json:"hasLocked"` //已禁言
|
||||
HasBanned bool `json:"hasBanned"` //会员等级
|
||||
VipLevel int `json:"vipLevel"` //是否vip
|
||||
IsVip bool `json:"isVip"` //是否逆向关注
|
||||
Via string `json:"via"` //粉丝来源
|
||||
Fans int64 `json:"fans"` //粉丝数
|
||||
Summary *string `json:"summary"` //简介
|
||||
SuperUser bool `json:"superUser"` //是否大v
|
||||
Awards []int `json:"awards"` //用户奖章
|
||||
TotalWorks int64 `json:"totalWorks"` //总作品数
|
||||
CreatedAt time.Time `json:"createdAt"` //创建时间
|
||||
// 其他数据
|
||||
HasFollow bool `json:"hasFollow"` // 是否关注
|
||||
}
|
||||
|
||||
// ListReq 用户关注、粉丝列表
|
||||
type ListReq struct {
|
||||
PageNumber int `form:"pageNumber" json:"pageNumber"`
|
||||
PageSize int `form:"pageSize" json:"pageSize"`
|
||||
UID uint64 `form:"uid" json:"uid"`
|
||||
IsShort bool `form:"isShort" json:"isShort"`
|
||||
}
|
||||
|
||||
// UserFollowReq 用户关注动作
|
||||
type UserFollowReq struct {
|
||||
FollowUID uint64 `form:"followUID" json:"followUID"`
|
||||
IsFollow bool `form:"isFollow" json:"isFollow"`
|
||||
IsShort bool `form:"isShort" json:"isShort"`
|
||||
}
|
||||
|
||||
// ListResp 列表返回
|
||||
type ListResp struct {
|
||||
//数据列表
|
||||
List []*BaseInfo `json:"list"`
|
||||
//是否还有下一页
|
||||
HasNext bool `json:"hasNext"`
|
||||
}
|
||||
|
||||
// DynamicsResp 关注用户的动态信息
|
||||
type DynamicsResp struct {
|
||||
//视频列表
|
||||
List []*vidmod.VideoInfo `json:"list"`
|
||||
VInfos []*vidmod.VideoInfo `json:"vInfos"`
|
||||
HasNext bool `json:"hasNext"`
|
||||
//总页数
|
||||
TotalPages int `json:"totalPages"`
|
||||
}
|
||||
|
||||
// AppDynamicsListReq 用户关注、粉丝列表
|
||||
type AppDynamicsListReq struct {
|
||||
commod.Page
|
||||
NewsType string `form:"newsType" json:"newsType"` // SHORT:短视频 SP:长视频
|
||||
}
|
||||
@@ -0,0 +1,332 @@
|
||||
package followmod
|
||||
|
||||
import (
|
||||
"91porn-server/common/db"
|
||||
"91porn-server/common/log"
|
||||
"91porn-server/models"
|
||||
"fmt"
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/mongo"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
"time"
|
||||
)
|
||||
|
||||
var mdb *db.MongoDB
|
||||
|
||||
const table = models.Follow
|
||||
|
||||
func coll(t *db.MongoTool) *db.MongoTool {
|
||||
if t == nil {
|
||||
return mdb.Coll(table)
|
||||
}
|
||||
return t.Coll(table)
|
||||
}
|
||||
|
||||
// initIndex 初始化索引
|
||||
func initIndex() {
|
||||
many := []mongo.IndexModel{
|
||||
{
|
||||
Keys: bson.D{{"followUID", -1}},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{{"uid", 1}, {"followUID", 1}},
|
||||
Options: options.Index().SetUnique(true),
|
||||
},
|
||||
{
|
||||
Keys: bson.D{{"uniq", 1}},
|
||||
},
|
||||
{
|
||||
Keys: bson.D{{"createdAt", -1}},
|
||||
},
|
||||
}
|
||||
_, err := coll(nil).CreateIndex(many)
|
||||
if err != nil {
|
||||
panic(fmt.Sprintf("%s model set index err ==>[%+v]", table, err))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// AddFollow 添加关注
|
||||
func AddFollow(uid uint64, followUID uint64, isShort bool) (int64, error) {
|
||||
set := bson.M{"uniq": Unique(uid, followUID), "createdAt": time.Now()}
|
||||
if isShort {
|
||||
set["newsType"] = "SHORT"
|
||||
}
|
||||
res, err := coll(nil).UpsertOne(
|
||||
bson.M{"uid": uid, "followUID": followUID},
|
||||
bson.M{"$set": set})
|
||||
if err != nil {
|
||||
log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "AddFollow", table, "UpsertOne", err),
|
||||
log.Any("uid", uid), log.Any("followUID", followUID),
|
||||
)
|
||||
}
|
||||
if res != nil {
|
||||
return res.UpsertedCount, err
|
||||
}
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// CloseFollow 取消关注
|
||||
func CloseFollow(uid uint64, followUID uint64) (int64, error) {
|
||||
res, err := coll(nil).DeleteOne(
|
||||
bson.M{"uid": uid, "followUID": followUID})
|
||||
if err != nil {
|
||||
log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "CloseFollow", table, "DeleteOne", err),
|
||||
log.Any("uid", uid), log.Any("followUID", followUID),
|
||||
)
|
||||
}
|
||||
if res != nil {
|
||||
return res.DeletedCount, err
|
||||
}
|
||||
return 0, err
|
||||
}
|
||||
|
||||
// IsFollow 是否关注
|
||||
func IsFollow(uid uint64, followUID uint64) (bool, error) {
|
||||
f := FollowModel{}
|
||||
err := coll(nil).FindOne(&f, bson.M{"uid": uid, "followUID": followUID})
|
||||
if err != nil {
|
||||
log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "IsFollow", table, "Count", err), log.Any("uid", uid), log.Any("followUID", followUID))
|
||||
return false, err
|
||||
}
|
||||
if f.FollowUID == 0 {
|
||||
return false, err
|
||||
}
|
||||
return true, nil
|
||||
}
|
||||
|
||||
// IsFollowUsers 是否关注这些用户
|
||||
func IsFollowUsers(uid uint64, followUIDs []uint64) (map[uint64]bool, error) {
|
||||
if followUIDs == nil {
|
||||
followUIDs = []uint64{}
|
||||
}
|
||||
m := make(map[uint64]bool)
|
||||
if uid == 0 || len(followUIDs) == 0 {
|
||||
return m, nil
|
||||
}
|
||||
var infos []FollowModel
|
||||
err := coll(nil).Find(&infos, bson.M{"uid": uid, "followUID": bson.M{"$in": followUIDs}})
|
||||
if err != nil {
|
||||
log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "IsFollowUsers", table, "Find", err),
|
||||
log.Any("uid", uid), log.Any("followUIDs", followUIDs),
|
||||
)
|
||||
return m, err
|
||||
}
|
||||
for _, i := range infos {
|
||||
m[i.FollowUID] = true
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// IsFollowedByUsers 是否被这些用户关注
|
||||
func IsFollowedByUsers(followUID uint64, uids []uint64) (map[uint64]bool, error) {
|
||||
if uids == nil {
|
||||
uids = []uint64{}
|
||||
}
|
||||
m := make(map[uint64]bool)
|
||||
var infos []FollowModel
|
||||
err := coll(nil).Find(&infos, bson.M{"followUID": followUID, "uid": bson.M{"$in": uids}})
|
||||
if err != nil {
|
||||
log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "IsFollowedByUsers", table, "Find", err),
|
||||
log.Any("followUID", followUID), log.Any("uids", uids),
|
||||
)
|
||||
return m, err
|
||||
}
|
||||
for _, i := range infos {
|
||||
m[i.UID] = true
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// FollowStatueMap 从给定的hash列表中获取like状态映射:hash->Statue
|
||||
// hash通过Vector.hash()获取
|
||||
func FollowStatueMap(uniqList []string) (map[string]bool, error) {
|
||||
filter := bson.M{
|
||||
"uniq": bson.M{"$in": uniqList},
|
||||
}
|
||||
existLikeList := make([]FollowModel, 0, len(uniqList))
|
||||
err := coll(nil).Find(&existLikeList, filter)
|
||||
if err != nil {
|
||||
log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "FollowStatueMap", table, "Find", err),
|
||||
log.Any("uniqList", uniqList),
|
||||
)
|
||||
return nil, err
|
||||
}
|
||||
m := make(map[string]bool, len(existLikeList))
|
||||
//初始化
|
||||
for _, uniq := range uniqList {
|
||||
m[uniq] = false
|
||||
}
|
||||
//已经关注的
|
||||
for _, v := range existLikeList {
|
||||
uniq := v.Uniq
|
||||
m[uniq] = true
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// GetFollowCount 获取关注总数
|
||||
func GetFollowCount(uid uint64) (int64, error) {
|
||||
total, err := coll(nil).Count(bson.M{"uid": uid})
|
||||
if err != nil {
|
||||
log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "IsFollowEachOther", table, "Count", err),
|
||||
log.Any("uid", uid),
|
||||
)
|
||||
return 0, err
|
||||
}
|
||||
return total, nil
|
||||
}
|
||||
|
||||
// GetFansCount 获取粉丝总数
|
||||
func GetFansCount(uid uint64) (int64, error) {
|
||||
total, err := coll(nil).Count(bson.M{"followUID": uid})
|
||||
if err != nil {
|
||||
log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "GetFansCount", table, "Count", err),
|
||||
log.Any("uid", uid),
|
||||
)
|
||||
return 0, err
|
||||
}
|
||||
return total, nil
|
||||
}
|
||||
|
||||
// GetFollowList 获取关注列表
|
||||
func GetFollowList(uid uint64, page int, size int, isShort bool) ([]uint64, map[uint64]FollowModel, bool, error) {
|
||||
hasNext := false
|
||||
m := make(map[uint64]FollowModel)
|
||||
cond := bson.M{"uid": uid}
|
||||
sort := bson.D{{Key: "createdAt", Value: -1}}
|
||||
opts := options.FindOptions{}
|
||||
opts.SetSort(sort).SetSkip(int64((page - 1) * size)).SetLimit(int64(size + 1))
|
||||
|
||||
if isShort {
|
||||
cond["newsType"] = "SHORT"
|
||||
}
|
||||
|
||||
var data []*FollowModel
|
||||
err := coll(nil).Find(&data, cond, &opts)
|
||||
if err != nil {
|
||||
log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "GetFollowList", table, "Find", err),
|
||||
log.Any("uid", uid), log.Any("page", page), log.Any("size", size),
|
||||
)
|
||||
return nil, m, false, err
|
||||
}
|
||||
if len(data) > size {
|
||||
hasNext = true
|
||||
data = data[:size]
|
||||
}
|
||||
var uids []uint64
|
||||
for _, d := range data {
|
||||
if d == nil {
|
||||
continue
|
||||
}
|
||||
uids = append(uids, d.FollowUID)
|
||||
m[d.FollowUID] = *d
|
||||
}
|
||||
return uids, m, hasNext, nil
|
||||
}
|
||||
|
||||
// GetFansList 获取粉丝列表
|
||||
func GetFansList(uid uint64, page int, size int) ([]uint64, map[uint64]FollowModel, bool, error) {
|
||||
hasNext := false
|
||||
m := make(map[uint64]FollowModel)
|
||||
cond := bson.M{"followUID": uid}
|
||||
sort := bson.D{{Key: "createdAt", Value: -1}}
|
||||
opts := options.FindOptions{}
|
||||
opts.SetSort(sort).SetSkip(int64((page - 1) * size)).SetLimit(int64(size + 1))
|
||||
var data []*FollowModel
|
||||
err := coll(nil).Find(&data, cond, &opts)
|
||||
if err != nil {
|
||||
log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "GetFansList", table, "Find", err),
|
||||
log.Any("uid", uid), log.Any("page", page), log.Any("size", size),
|
||||
)
|
||||
return nil, m, hasNext, err
|
||||
}
|
||||
if len(data) > size {
|
||||
hasNext = true
|
||||
data = data[:size]
|
||||
}
|
||||
var uids []uint64
|
||||
for _, d := range data {
|
||||
if d == nil {
|
||||
continue
|
||||
}
|
||||
uids = append(uids, d.UID)
|
||||
m[d.UID] = *d
|
||||
}
|
||||
return uids, m, hasNext, nil
|
||||
}
|
||||
|
||||
// GetAllFansUid 获取所有粉丝用户id
|
||||
func GetAllFansUid(uid uint64) ([]uint64, error) {
|
||||
var data []*FollowModel
|
||||
cond := bson.M{"followUID": uid}
|
||||
sort := bson.D{{Key: "createdAt", Value: -1}}
|
||||
opts := options.FindOptions{}
|
||||
opts.SetSort(sort)
|
||||
err := coll(nil).Find(&data, cond, &opts)
|
||||
if err != nil {
|
||||
log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "GetAllFansUid", table, "Find", err),
|
||||
log.Any("uid", uid),
|
||||
)
|
||||
return nil, err
|
||||
}
|
||||
var uids []uint64
|
||||
for _, d := range data {
|
||||
uids = append(uids, d.UID)
|
||||
}
|
||||
return uids, nil
|
||||
}
|
||||
|
||||
// GetTotalFollowList 获取所有关注用户
|
||||
func GetTotalFollowList(uid uint64) ([]uint64, error) {
|
||||
var data []*FollowModel
|
||||
cond := bson.M{"uid": uid}
|
||||
sort := bson.D{{Key: "createdAt", Value: -1}}
|
||||
opts := options.FindOptions{}
|
||||
opts.SetSort(sort).SetLimit(5)
|
||||
err := coll(nil).Find(&data, cond, &opts)
|
||||
if err != nil {
|
||||
log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "GetTotalFollowList", table, "Find", err),
|
||||
log.Any("uid", uid),
|
||||
)
|
||||
return nil, err
|
||||
}
|
||||
var uids []uint64
|
||||
for _, d := range data {
|
||||
uids = append(uids, d.FollowUID)
|
||||
}
|
||||
return uids, nil
|
||||
}
|
||||
|
||||
// GetTotalFollowListLimit 获取所有关注用户
|
||||
func GetTotalFollowListLimit(uid uint64, limit int64) ([]uint64, error) {
|
||||
var data []*FollowModel
|
||||
cond := bson.M{"uid": uid}
|
||||
sort := bson.D{{Key: "createdAt", Value: -1}}
|
||||
opts := options.FindOptions{}
|
||||
opts.SetSort(sort).SetLimit(limit)
|
||||
err := coll(nil).Find(&data, cond, &opts)
|
||||
if err != nil {
|
||||
log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "GetTotalFollowListLimit", table, "Find", err),
|
||||
log.Any("uid", uid),
|
||||
)
|
||||
return nil, err
|
||||
}
|
||||
var uids []uint64
|
||||
for _, d := range data {
|
||||
uids = append(uids, d.FollowUID)
|
||||
}
|
||||
return uids, nil
|
||||
}
|
||||
|
||||
// WeekFollowLeaderboard 周关注榜单
|
||||
func WeekFollowLeaderboard(bind interface{}, filter bson.M, limit int) error {
|
||||
opt := options.Aggregate().SetAllowDiskUse(true)
|
||||
pip := []bson.M{
|
||||
{"$match": filter}, // 过滤条件 由外部决定
|
||||
{"$group": bson.M{"_id": "$followUID", "count": bson.M{"$sum": 1}}}, // 统计用户被关注
|
||||
{"$sort": bson.M{"count": -1}}, // 按照作品数排序
|
||||
{"$limit": limit}, // 限制返回条数
|
||||
}
|
||||
return coll(nil).Aggregate(bind, pip, opt)
|
||||
}
|
||||
@@ -0,0 +1,55 @@
|
||||
package followmod
|
||||
|
||||
import (
|
||||
"91porn-server/common/pageopt"
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
"time"
|
||||
)
|
||||
|
||||
type Matcher = pageopt.Matcher
|
||||
|
||||
// CreatedAtGTEMatch
|
||||
type CreatedAtGTEMatch struct {
|
||||
GTE *time.Time
|
||||
}
|
||||
|
||||
func (c *CreatedAtGTEMatch) New() Matcher {
|
||||
return pageopt.NewGTEMatch("createdAt", c.GTE)
|
||||
}
|
||||
|
||||
// FollowUIDMatch
|
||||
type FollowUIDMatch struct {
|
||||
FollowUID *uint64
|
||||
}
|
||||
|
||||
func (f *FollowUIDMatch) New() Matcher {
|
||||
return pageopt.NewAssignMatch("followUID", f.FollowUID)
|
||||
}
|
||||
|
||||
// List
|
||||
func List(sort bson.D, skip, limit int64, matchers ...Matcher) ([]FollowModel, error) {
|
||||
filter := pageopt.MergeM(matchers)
|
||||
opt := &options.FindOptions{}
|
||||
if len(sort) != 0 {
|
||||
opt.SetSort(sort)
|
||||
}
|
||||
opt.SetSkip(skip)
|
||||
opt.SetLimit(limit)
|
||||
list := make([]FollowModel, 0, limit)
|
||||
err := coll(nil).Find(&list, filter, opt)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return list, nil
|
||||
}
|
||||
|
||||
// Count
|
||||
func Count(matchers ...Matcher) (int64, error) {
|
||||
filter := pageopt.MergeM(matchers)
|
||||
count, err := coll(nil).Count(filter)
|
||||
if err != nil {
|
||||
return 0, err
|
||||
}
|
||||
return count, nil
|
||||
}
|
||||
@@ -0,0 +1,46 @@
|
||||
package followmod
|
||||
|
||||
import (
|
||||
"91porn-server/common/db"
|
||||
"strconv"
|
||||
"strings"
|
||||
"time"
|
||||
)
|
||||
|
||||
const (
|
||||
//最大关注人数
|
||||
MaxFollowUsers = 500
|
||||
//单日关注上限
|
||||
ToDayFollowLimit = 50
|
||||
)
|
||||
|
||||
// FollowModel 用户关注列表
|
||||
type FollowModel struct {
|
||||
UID uint64 `json:"uid" bson:"uid"` //关注者
|
||||
FollowUID uint64 `json:"followUID" bson:"followUID"` //被关注的uid
|
||||
Uniq string `bson:"uniq"` //uid.followUID
|
||||
Via string `json:"via"` //粉丝来源
|
||||
NewsType string `json:"newsType" bson:"newsType"` //用户的类型 SHORT:短视频用户
|
||||
CreatedAt time.Time `json:"createdAt" bson:"createdAt"`
|
||||
}
|
||||
|
||||
// FollowCnt 关注人数统计
|
||||
type FollowCnt struct {
|
||||
ID uint64 `bson:"_id"`
|
||||
Count int `bson:"count"`
|
||||
}
|
||||
|
||||
func Init() {
|
||||
mdb = db.Init(table)
|
||||
initIndex()
|
||||
}
|
||||
|
||||
// Unique uid.followUID
|
||||
func Unique(uid uint64, followUID uint64) string {
|
||||
list := []string{
|
||||
strconv.FormatInt(int64(uid), 10),
|
||||
strconv.FormatInt(int64(followUID), 10),
|
||||
}
|
||||
s := strings.Join(list, ".")
|
||||
return s
|
||||
}
|
||||
Reference in New Issue
Block a user