package proxymod import ( "fmt" "time" "91porn-server/common/db" "91porn-server/common/log" "91porn-server/models" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/bson/primitive" "go.mongodb.org/mongo-driver/mongo" "go.mongodb.org/mongo-driver/mongo/options" ) const table = models.Invitation func coll(t *db.MongoTool) *db.MongoTool { if t == nil { return mdb.Coll(table) } return t.Coll(table) } // initIndex 索引设置 func initIndex() { many := []mongo.IndexModel{ //batch set indexes //value is the type 1 or -1 { Keys: bson.D{{Key: "uid", Value: 1}}, }, { Keys: bson.D{{Key: "invitee", Value: 1}}, Options: options.Index().SetUnique(true), }, { Keys: bson.D{{Key: "createdAt", Value: 1}}, }, { Keys: bson.D{{Key: "inviteTime", Value: 1}}, }, } if _, err := coll(nil).CreateIndex(many); err != nil { panic(fmt.Sprintf("%s model set index err ==>[%+v]", table, err)) } } // GetInvitation 获取一级代理 func GetInvitation(uid uint64) ([]uint64, error) { data := []UIDList{} if err := coll(nil).Aggregate(&data, []bson.M{ {"$match": bson.M{"uid": uid}}, {"$project": bson.M{"_id": 0, "invitee": 1}}, {"$group": bson.M{"_id": 1, "ids": bson.M{"$push": "$invitee"}}}, }); err != nil { log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "GetInvitation", table, "Aggregate", err), log.Any("uid", uid)) return nil, err } if len(data) == 0 { return make([]uint64, 0), nil } return data[0].IDS, nil } // GetInvrLv1 获取上一级代理 func GetInvrLv1(uid uint64) (uint64, error) { data := Invitation{} if err := coll(nil).FindOne(&data, bson.M{"invitee": uid}); err != nil { log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "GetInvrLv1", table, "FindOne", err), log.Any("uid", uid)) return 0, err } return data.UID, nil } // GetInvrLv1Map 获取上一级代理uid Map func GetInvrLv1Map(uidList []uint64) (map[uint64]uint64, error) { if len(uidList) == 0 { return make(map[uint64]uint64), nil } filter := bson.M{ "invitee": bson.M{ "$in": uidList, }, } invrList := make([]Invitation, 0, len(uidList)) if err := coll(nil).Find(&invrList, filter); err != nil { return nil, err } m := make(map[uint64]uint64, len(invrList)) for _, invr := range invrList { m[invr.Invitee] = invr.UID } return m, nil } // GetInvitationByUID 获取下级代理绑定记录 func GetInvitationByUID(uid uint64, pageNumber int64, pageSize int64) (data []*Invitation, hasNext bool, err error) { data = make([]*Invitation, 0) skip := pageSize * (pageNumber - 1) limit := pageSize + 1 opt := options.FindOptions{ Skip: &skip, Limit: &limit, Sort: bson.D{{Key: "createdAt", Value: -1}}, } if err = coll(nil).Find(&data, bson.M{"uid": uid}, &opt); err != nil { log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "GetInvitationByUID", table, "Find", err), log.Any("uid", uid)) return } if len(data) > int(pageSize) { hasNext = true data = data[:pageSize] } return } // GetInveNext 获取下级级代理 func GetInveNext(uids []uint64) (ids []uint64, total int64, err error) { data := []UIDList{} if err = coll(nil).Aggregate(&data, []bson.M{ {"$match": bson.M{"uid": bson.M{"$in": uids}}}, {"$project": bson.M{"_id": 0, "invitee": 1}}, {"$group": bson.M{"_id": 1, "ids": bson.M{"$push": "$invitee"}, "total": bson.M{"$sum": 1}}}, }); err != nil { log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "GetInveNext", table, "Aggregate", err), log.Any("uids", uids)) return } if len(data) > 0 { ids = data[0].IDS total = data[0].Total } return } // GetInviteesCount 获取下级代理总数 func GetInviteesCount(uids []uint64, startTime time.Time, endTime time.Time) (count int64, err error) { count, err = coll(nil).Count(bson.M{"createdAt": bson.M{"$gte": startTime, "$lte": endTime}, "uid": bson.M{"$in": uids}}) if err != nil { log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "GetInviteesCount", table, "Count", err), log.Any("uids", uids), log.Any("startTime", startTime), log.Any("endTime", endTime), ) return } return } // GetInviteesCount 获取下级代理总数map func GetInviteesCountMap(uids []uint64) (map[uint64]int64, error) { if len(uids) == 0 { return make(map[uint64]int64), nil } pipeLine := []bson.M{ { "$match": bson.M{ "uid": bson.M{"$in": uids}, }, }, { "$group": bson.M{ "_id": "$uid", "count": bson.M{ "$sum": 1, }, }, }, } list := make([]struct { UID uint64 `bson:"_id"` Count int64 `bson:"count"` }, len(uids)) if err := coll(nil).Aggregate(&list, pipeLine); err != nil { return nil, err } countMap := make(map[uint64]int64, len(list)) for _, v := range list { countMap[v.UID] = v.Count } return countMap, nil } // GetInve 获取N级代理 func GetInve(uids []uint64, lev int) ([]uint64, error) { data := []UIDList{} if err := coll(nil).Aggregate(&data, []bson.M{ {"$match": bson.M{"uid": bson.M{"$in": uids}}}, {"$project": bson.M{"_id": 0, "invitee": 1}}, {"$group": bson.M{"_id": 1, "ids": bson.M{"$push": "$invitee"}}}, }); err != nil { log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "GetInve", table, "Aggregate", err), log.Any("uids", uids), log.Any("lev", lev), ) return nil, err } if len(data) == 0 { return nil, nil } ids := data[0].IDS if lev == 1 || len(ids) <= 0 { return ids, nil } return GetInve(ids, lev-1) } func CountByUID(uid uint64) (i int64, err error) { count, err := coll(nil).Count(bson.M{"uid": uid}) if err != nil { log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "CountByUID", table, "Count", err), log.Any("uid", uid)) return 0, err } return count, nil } func CountByInviteeID(uid uint64) (i int64, err error) { count, err := coll(nil).Count(bson.M{"invitee": uid}) if err != nil { log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "CountByInviteeID", table, "Count", err), log.Any("uid", uid)) return 0, err } return count, nil } func CountPayUserByUID(uid uint64) (i int64, err error) { count, err := coll(nil).Count(bson.M{"uid": uid, "isRecharge": true}) if err != nil { log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "CountPayUserByUID", table, "Count", err), log.Any("uid", uid)) return 0, err } return count, nil } func CountAfter22_02_10(uid uint64) (i int64, err error) { count, err := coll(nil).Count(bson.M{"uid": uid, "createdAt": bson.M{"$gt": time.Unix(1612890000, 0)}}) if err != nil { log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "CountByUID", table, "Count", err), log.Any("uid", uid)) return 0, err } return count, nil } func CountByUIDAndTime(uid uint64, startTime time.Time) (i int64, err error) { count, err := coll(nil).Count(bson.M{"uid": uid, "createdAt": bson.M{"$gt": startTime}}) if err != nil { log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "CountByUIDAndTime", table, "Count", err), log.Any("uid", uid)) return 0, err } return count, nil } // GetInveNextDetails 获取下级代理详情 func GetInveNextDetails(uids []uint64) (invs []Invitation, err error) { invs = make([]Invitation, 0) if err = coll(nil).Find(&invs, bson.M{"uid": bson.M{"$in": uids}}); err != nil { log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "GetInveNextDetails", table, "Find", err), log.Any("uids", uids)) return } return } // GetInvr 获取上级代理 func GetInvr(uid uint64, lev int, ids *[]uint64) error { i := Invitation{} if err := coll(nil).FindOne(&i, bson.M{"invitee": uid}); err != nil { log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "GetInvr", table, "FindOne", err), log.Any("uid", uid), log.Any("lev", lev), log.Any("ids", ids), ) return err } if i.UID == 0 { return nil } *ids = append(*ids, i.UID) if lev == 1 { return nil } return GetInvr(i.UID, lev-1, ids) } // GetInvrDetails 获取上级代理详情 func GetInvrDetails(uid uint64, lev int) ([]Invitation, error) { ids := make([]Invitation, 0) bufI := Invitation{} if err := coll(nil).FindOne(&bufI, bson.M{"invitee": uid}); err != nil { log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "GetInvrDetails", table, "FindOne", err), log.Any("uid", uid), log.Any("lev", lev), log.Any("ids", ids), ) return nil, err } if bufI.UID == 0 { return ids, nil } ids = append(ids, bufI) if lev == 1 { return ids, nil } list, err := GetInvrDetails(bufI.UID, lev-1) if err != nil { return ids, nil } ids = append(ids, list...) return ids, nil } // WebGetUIDList 绑定记录列表,获取某邀请码的邀请关系和收益 func WebGetUIDList(start time.Time, end time.Time) (data []UIDList, err error) { data = make([]UIDList, 0) p := []bson.M{ {"$match": bson.M{"createdAt": bson.M{"$gte": start, "$lt": end}}}, {"$group": bson.M{"_id": "$uid", "ids": bson.M{"$push": "$invitee"}, "promotionCode": bson.M{"$first": "$promotionCode"}}}, } if err = coll(nil).Aggregate(&data, p); err != nil { log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "WebGetUIDList", table, "Aggregate", err), log.Any("start", start), log.Any("end", end), ) return } return } // LoopInviteError 循环推广错误 type LoopInviteError struct { Parent uint64 UID uint64 } func (l LoopInviteError) Error() string { return fmt.Sprintf("Loop Invite Error! parent: %d uid: %d", l.Parent, l.UID) } // InsertOne 插入一条邀请关系 func InsertOne(invitation Invitation) error { count, err := CountByInviteeID(invitation.Invitee) if err != nil { return err } if count != 0 { return LoopInviteError{invitation.Invitee, invitation.UID} } if _, err = coll(nil).InsertOne(invitation); err != nil { log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "InsertOne", table, "InsertOne", err)) return err } return nil } // FindMany 查询所有 func FindMany(filter bson.M, opts *options.FindOptions) (total int64, data []*Invitation, err error) { data = make([]*Invitation, 0) if err = coll(nil).Find(&data, filter, opts); err != nil { log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "FindMany", table, "Find", err), log.Any("filter", filter)) return } total, err = coll(nil).Count(filter) if err != nil { log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "FindMany", table, "Count", err), log.Any("filter", filter)) } return } // ProxyUserCount 一段时间内邀请用户数 func ProxyUserCount(start time.Time, end time.Time) (map[uint64]int64, []uint64, error) { m := make(map[uint64]int64) pipeLine := []bson.M{ {"$match": bson.M{"createdAt": bson.M{"$gte": start, "$lt": end}}}, {"$group": bson.M{"_id": "$uid", "count": bson.M{"$sum": 1}}}, } docList := []struct { UID uint64 `bson:"_id"` Count int64 `bson:"count"` }{} uids := []uint64{} if err := coll(nil).Aggregate(&docList, pipeLine); err != nil { log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "ProxyUserCount", table, "Aggregate", err), log.Any("start", start), log.Any("end", end), ) return m, uids, err } for _, doc := range docList { m[doc.UID] = doc.Count uids = append(uids, doc.UID) } return m, uids, nil } // InvitListByCreatedAt 通过CreatedAt获取Invitation List func InvitListByCreatedAt(start, end time.Time) ([]Invitation, error) { filter := bson.M{ "createdAt": bson.M{ "$gte": start, "$lt": end, }, } invitList := make([]Invitation, 0) if err := coll(nil).Find(&invitList, filter); err != nil { log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "InvitListByCreatedAt", table, "Find", err), log.Any("start", start), log.Any("end", end), ) return nil, err } return invitList, nil } // GetParentInvitList 获取指定uidList的父级Invitation List func GetParentInvitList(uids []uint64) ([]Invitation, error) { filter := bson.M{ "invitee": bson.M{"$in": uids}, } list := make([]Invitation, 0, len(uids)) if err := coll(nil).Find(&list, filter); err != nil { log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "GetParentInvitList", table, "Find", err), log.Any("uids", uids)) return nil, err } return list, nil } // GetSuperiorInvitList 获取上级Invitation func GetSuperiorInvitList(invitees []uint64, depth int) ([]Invitation, error) { invitList := []Invitation{} for i := 0; i < depth; i++ { if len(invitees) == 0 { break } parentInvitList, err := GetParentInvitList(invitees) if err != nil { return nil, err } parentUIDList := make([]uint64, len(parentInvitList)) for i, v := range parentInvitList { parentUIDList[i] = v.UID } invitList = append(invitList, parentInvitList...) invitees = parentUIDList } return invitList, nil } func NextProxyCount(uid uint64, start time.Time, end time.Time) (int64, error) { f := bson.M{"uid": uid, "createdAt": bson.M{"$gte": start, "$lt": end}} c, err := coll(nil).Count(f) if err != nil { log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "NextProxyCount", table, "count", err), log.Any("filter", f)) return 0, err } return c, nil } // UserInvitees 获取用户推广人数 func UserInvitees(startTime time.Time, endTime time.Time) (map[uint64]int, error) { data := make(map[uint64]int) infos := []InviteeCount{} pipeline := []bson.M{ { "$match": bson.M{"createdAt": bson.M{"$gt": startTime, "$lte": endTime}}, }, { "$group": bson.M{"_id": "$uid", "count": bson.M{"$sum": 1}}, }, } if err := coll(nil).Aggregate(&infos, pipeline); err != nil { log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "UserInvitees", table, "Aggregate", err), log.Any("startTime", startTime), log.Any("endTime", endTime)) return data, err } for _, v := range infos { data[v.UID] = v.Count } return data, nil } func StatCenterSyncInviteList(time time.Time, size int64) ([]Invitation, error) { opt := (&options.FindOptions{}) opt.SetLimit(size) opt.SetSort(bson.M{"inviteTime": 1}) filter := bson.M{"inviteTime": bson.M{"$gt": time}} data := make([]Invitation, 0) return data, coll(nil).Find(&data, filter, opt) } func NewStatCenterSyncInviteList(id string, size int64) ([]Invitation, error) { opt := (&options.FindOptions{}) opt.SetLimit(size) opt.SetSort(bson.M{"_id": 1}) _id, _ := primitive.ObjectIDFromHex(id) filter := bson.M{"_id": bson.M{"$gt": _id}} data := make([]Invitation, 0) return data, coll(nil).Find(&data, filter, opt) } // FindManyByApp app分页查询所有 func FindManyByApp(uid, pageNumber, pageSize uint64) (total int64, data []*Invitation, err error) { filter := bson.M{"uid": uid} opts := &options.FindOptions{} opts.SetSkip(int64((pageNumber - 1) * pageSize)).SetLimit(int64(pageSize + 1)) opts.SetSort(bson.D{{Key: "createdAt", Value: -1}}) data = make([]*Invitation, 0) if err = coll(nil).Find(&data, filter, opts); err != nil { log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "FindManyByApp", table, "Find", err), log.Any("filter", filter)) return } total, err = coll(nil).Count(filter) if err != nil { log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "FindManyByApp", table, "Count", err), log.Any("filter", filter)) } return } // FindTotal 查询所有总数 func FindTotal(uid uint64) (total int64, err error) { filter := bson.M{"uid": uid} total, err = coll(nil).Count(filter) if err != nil { log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "FindTotal", table, "Count", err), log.Any("filter", filter)) } return } // UpdateByUid 修改 func UpdateByUid(t *db.MongoTool, uid, proxyUserId uint64) error { cond := bson.M{"isRecharge": true, "updateAt": time.Now()} if _, err := coll(t).UpdateOne(bson.M{"invitee": uid, "uid": proxyUserId}, bson.M{"$set": cond}); err != nil { log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "UpdateByUid", table, "UpdateOne", err), log.Any("uid", uid), ) return err } return nil }