@@ -0,0 +1,319 @@
|
||||
package usermod
|
||||
|
||||
import (
|
||||
"reflect"
|
||||
"time"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
|
||||
"91porn-server/models/v/videocoupon"
|
||||
)
|
||||
|
||||
const (
|
||||
DevIDLogin = 0
|
||||
TokenLogin = 1
|
||||
MobileLogin = 2
|
||||
QrCodeLogin = 3
|
||||
|
||||
CouponPositionUnUsed = "unused" // 未使用
|
||||
CouponPositionUsed = "used" // 已使用
|
||||
)
|
||||
|
||||
// UserSelector 用户修改参数
|
||||
type UserSelector struct {
|
||||
Gender *string `json:"gender,omitempty" bson:"gender,omitempty"` //性别
|
||||
Name *string `json:"name,omitempty" bson:"name,omitempty"`
|
||||
Portrait *string `json:"portrait,omitempty" bson:"portrait,omitempty"` //头像
|
||||
Background *[]string `json:"background,omitempty" bson:"background,omitempty"` //背景图
|
||||
Summary *string `json:"summary,omitempty" bson:"summary,omitempty"` //简介
|
||||
HasPrivateZone *bool `json:"hasPrivateZone,omitempty" bson:"hasPrivateZone,omitempty"` // 已关闭私密圈权限
|
||||
Region *string `json:"region,omitempty" bson:"region,omitempty"` //地区
|
||||
Birthday *string `json:"birthday,omitempty" bson:"birthday,omitempty"` //生日
|
||||
VipLevel *int `json:"vipLevel,omitempty" bson:"vipLevel,omitempty"` //vip等级
|
||||
VipExpireDate *time.Time `json:"vipExpireDate,omitempty" bson:"vipExpireDate,omitempty"` //vip过期时间
|
||||
CoinMouthExpireDate *time.Time `json:"coinMouthExpireDate" bson:"coinMouthExpireDate"` //金币月卡过期时间
|
||||
HasLocked *bool `json:"hasLocked,omitempty" bson:"hasLocked,omitempty"` //已禁止登陆
|
||||
HasBanned *bool `json:"hasBanned,omitempty" bson:"hasBanned,omitempty"` //已禁言
|
||||
LockReason *string `json:"lockReason,omitempty" bson:"lockReason,omitempty"` //禁止登录的原因
|
||||
LockImg *string `json:"lockImg,omitempty" bson:"lockImg,omitempty"` //禁止登录的原因截图
|
||||
LockAt *time.Time `json:"lockAt,omitempty" bson:"lockAt,omitempty"` //封禁开始时间
|
||||
ForbidUpload *bool `json:"forbidUpload,omitempty" bson:"forbidUpload,omitempty"` //是否禁止上传文件
|
||||
Token *string `json:"token,omitempty" bson:"token,omitempty"` //用户令牌
|
||||
WatchCount *uint64 `json:"watchCount,omitempty" bson:"watchCount,omitempty"` //观看次数
|
||||
UpdatedAt *time.Time `json:"updatedAt,omitempty" bson:"updatedAt,omitempty"` //更新时间
|
||||
LastVisitAt *time.Time `json:"lastVisitAt,omitempty" bson:"lastVisitAt,omitempty"` //最后登陆时间
|
||||
AppLock *string `json:"appLock,omitempty" bson:"appLock,omitempty"` //设备锁
|
||||
IsDAgent *bool `json:"isDAgent,omitempty" bson:"isDAgent,omitempty"` //是商圈代理
|
||||
LastVer *string `json:"lastVer,omitempty" bson:"lastVer,omitempty"` //最后登陆版本
|
||||
TrueScore *int64 `json:"trueScore,omitempty" bson:"trueScore,omitempty"` //用户真实性得分
|
||||
IsDirect *bool `json:"isDirect,omitempty" bson:"isDirect,omitempty"` //是直推用户
|
||||
DiscCode *string `json:"districtCode,omitempty" bson:"districtCode,omitempty"` //商区码
|
||||
PromSeqe *string `json:"promSeqe,omitempty" bson:"promSeqe,omitempty"` //推广序列
|
||||
SuperUser *bool `json:"superUser" bson:"superUser,omitempty"` //大v
|
||||
OfficialCert *bool `json:"officialCert" bson:"officialCert,omitempty"` //是否官方认证
|
||||
TaxLevel *int64 `json:"taxLevel" bson:"taxLevel,omitempty"` //扣税等级,默认0,3.7;
|
||||
ChatPrice *int64 `json:"chatPrice" bson:"chatPrice,omitempty"` //私信价格
|
||||
LastSysType *string `json:"lastSysType,omitempty" bson:"lastSysType,omitempty"` //最后登陆系统类型
|
||||
SnapVip *int `json:"snapVip,omitempty" bson:"snapVip,omitempty"` //临时vip
|
||||
OriginVipExpire *time.Time `json:"originVipExpire,omitempty" bson:"originVipExpire,omitempty"` //临时vip记录的原始vip时间
|
||||
OriginVipLevel *int `json:"originVipLevel,omitempty" bson:"originVipLevel,omitempty"` //临时vip记录的原始vip等级
|
||||
AutoFollow *bool `json:"autoFollow" bson:"autoFollow,omitempty"` //是否配置被自动关注
|
||||
HasEnteredGame *bool `json:"hasEnteredGame" bson:"hasEnteredGame,omitempty"` //是否进入过游戏
|
||||
BankActName *string `json:"bankActName,omitempty" bson:"bankActName,omitempty"` //银行卡绑定名字
|
||||
GoldVideoFreeExpire *time.Time `json:"goldVideoFreeExpire" bson:"goldVideoFreeExpire,omitempty"` //金币视频免费日期
|
||||
GoldVideoFreeLimit *int64 `json:"goldVideoFreeLimit" bson:"goldVideoFreeLimit,omitempty"` // 金币视频免费限制门槛(包含acg)
|
||||
WeeklyActiveValue *int64 `json:"weeklyActiveValue" bson:"weeklyActiveValue,omitempty"` //每周活跃度
|
||||
OriginalSort *int `json:"originalSort" bson:"originalSort"` // 新版原创排序
|
||||
VideoDeduction *float64 `json:"videoDeduction,omitempty" bson:"videoDeduction,omitempty"` //视频扣量,1:博主10单扣1单, 以此类推
|
||||
VideoDeductionPayCount *int `json:"videoDeductionPayCount,omitempty" bson:"videoDeductionPayCount,omitempty"` //视频扣量购买次数
|
||||
VideoDeductionCount *int `json:"videoDeductionCount,omitempty" bson:"videoDeductionCount,omitempty"` //视频扣量次数
|
||||
MerchantAccount *string `json:"merchantAccount" bson:"merchantAccount,omitempty"` //商家账号
|
||||
HasFirstChargeWaLi *bool `json:"hasFirstChargeWaLi,omitempty" bson:"hasFirstChargeWaLi,omitempty"` //是否首充充值瓦力
|
||||
IsAdvertiser *bool `json:"isAdvertiser" bson:"isAdvertiser"` // 是否是打广告用户
|
||||
HasWhoringCard *bool `json:"hasWhoringCard,omitempty" bson:"hasWhoringCard,omitempty"` // 是否有白嫖卡
|
||||
PayVidDiscount *int `json:"payVidDiscount,omitempty" bson:"payVidDiscount,omitempty"` //支付视频折扣
|
||||
GoldVideoCoupon *[]UserGoldVideoCoupon `json:"goldVideoCoupon,omitempty" bson:"goldVideoCoupon,omitempty"`
|
||||
VideoFreeExpiration *time.Time `json:"videoFreeExpiration,omitempty" bson:"videoFreeExpiration,omitempty"` //视频免费过期时间
|
||||
PassWord *string `json:"passWord,omitempty" bson:"passWord,omitempty"` //密码
|
||||
VipName *string `json:"vipName,omitempty" bson:"vipName,omitempty"` //会员卡名称
|
||||
LoufengBookDiscount *int `json:"loufengBookDiscount" bson:"loufengBookDiscount,omitempty"`
|
||||
LoufengBookDiscountExpiration *time.Time `json:"loufengBookDiscountExpiration" bson:"loufengBookDiscountExpiration,omitempty"`
|
||||
BannedTime *time.Time `json:"bannedTime" bson:"bannedTime,omitempty"` // 禁言时间
|
||||
AllGoldVideoFree *bool `json:"allGoldVideoFree" bson:"allGoldVideoFree,omitempty"` // 是否所有金币视频免费
|
||||
AiMateUid *string `json:"aiMateUid" bson:"aiMateUid,omitempty"` // ai伴侣uid
|
||||
BroadcastExpire *time.Time `json:"broadcastExpire" bson:"broadcastExpire,omitempty"` //直播有效期
|
||||
DramaExpire *time.Time `json:"dramaExpire" bson:"dramaExpire,omitempty"` //短剧权益有效期
|
||||
|
||||
}
|
||||
|
||||
// RenewDramaExpire 从当前有效期顺延短剧权益;已过期时从本次发放时间起算。
|
||||
func RenewDramaExpire(current, now time.Time, days int) time.Time {
|
||||
if current.After(now) {
|
||||
return current.AddDate(0, 0, days)
|
||||
}
|
||||
return now.AddDate(0, 0, days)
|
||||
}
|
||||
|
||||
func (u UserSelector) IsEmpty() bool {
|
||||
return reflect.DeepEqual(u, UserSelector{})
|
||||
}
|
||||
|
||||
// UserSelector 用户修改参数
|
||||
type UserModifyReq struct {
|
||||
Gender *string `json:"gender,omitempty" bson:"gender,omitempty"` //性别
|
||||
Name *string `json:"name,omitempty" bson:"name,omitempty"`
|
||||
Portrait *string `json:"portrait,omitempty" bson:"portrait,omitempty"` //头像
|
||||
Background *[]string `json:"background,omitempty" bson:"background,omitempty"` //背景图
|
||||
Summary *string `json:"summary,omitempty" bson:"summary,omitempty"` //简介
|
||||
Region *string `json:"region,omitempty" bson:"region,omitempty"` //地区
|
||||
Birthday *string `json:"birthday,omitempty" bson:"birthday,omitempty"` //生日
|
||||
AppLock *string `json:"appLock,omitempty" bson:"appLock,omitempty"` //设备锁
|
||||
UpdatedAt *time.Time `json:"updatedAt,omitempty" bson:"updatedAt,omitempty"`
|
||||
}
|
||||
|
||||
type UserOpt struct {
|
||||
//显示全民代理
|
||||
ShowProxy bool `json:"showProxy"`
|
||||
}
|
||||
|
||||
// RechargeLevel 充值等级
|
||||
type RechargeLevel struct {
|
||||
//等级
|
||||
Level int `json:"level"`
|
||||
//当前位置
|
||||
Current int `json:"current"`
|
||||
//当前等级最大值
|
||||
Limit int `json:"limit"`
|
||||
}
|
||||
|
||||
// AwardsExpireResp 奖章返回数据
|
||||
type AwardsExpireResp struct {
|
||||
Number int `json:"number" bson:"number,omitempty"` // 奖章价值
|
||||
IsExpire bool `json:"isExpire" bson:"isExpire,omitempty"` // 奖章是否过期 true有效 false无效
|
||||
}
|
||||
|
||||
type UserRes struct {
|
||||
//年龄
|
||||
Age int `form:"age" json:"age" bson:"age"`
|
||||
//作品总数
|
||||
CollectionCount int64 `form:"collectionCount" json:"collectionCount"`
|
||||
//是否是vip
|
||||
IsVIP bool `json:"isVip" bson:"isVip"`
|
||||
//推广落地页
|
||||
PromoteURL string `json:"promoteURL" bson:"promoteURL"`
|
||||
// 邀请者推广码
|
||||
InviterCode string `json:"inviterCode" bson:"inviterCode"`
|
||||
//用户当前定位城市
|
||||
City string `json:"city"`
|
||||
//用户购买视频总数
|
||||
BuyVidCount int64 `json:"buyVidCount"`
|
||||
//用户访问web携带的Token
|
||||
WebToken string `json:"webToken"`
|
||||
//用户登陆方式
|
||||
LoginType int `json:"loginType"`
|
||||
// 邀请者推广码
|
||||
AppStoreCode string `json:"appStoreCode" bson:"appStoreCode"`
|
||||
// 视频折扣卡到期时间
|
||||
VideoDiscountExpiration time.Time `json:"videoDiscountExpiration"`
|
||||
// 新版金币视频观影券
|
||||
NewGoldVideoCoupon []GoldVideoCoupon `json:"newGoldVideoCoupon"`
|
||||
//我的图片作品总数
|
||||
HappinessPlazaCount int64 `form:"happinessPlazaCount" json:"happinessPlazaCount"`
|
||||
TotalInvite int64 `form:"totalInvite" json:"totalInvite"`
|
||||
IsFollow bool `json:"isFollow"`
|
||||
//是否弹领取框
|
||||
IsPopUps bool `form:"isPopUps" json:"isPopUps"` //是否弹出领取框
|
||||
WhoringCard WhoringCardInfo `json:"whoringCard" bson:"whoringCard"` // 白嫖卡信息
|
||||
AdverAbTestShowType int `json:"adverAbTestShowType"` // 广告ab测展示类型 -1-首次免广告 0-所有广告都可以观看 其他数字N-新人注册N分钟内免广告
|
||||
ImEnabled bool `json:"imEnabled"` // IM 功能是否启用
|
||||
ImToken string `json:"imToken"` // IM 客户端登录 token
|
||||
ImUserID int64 `json:"imUserId"` // IM 平台用户 ID
|
||||
ImDynamicDomain string `json:"dynamicConfigDomain"` // IM SDK 动态配置域名
|
||||
ImSocketURL string `json:"socketURL"` // IM SDK WebSocket 地址
|
||||
User
|
||||
UserOpt
|
||||
RechargeLevel
|
||||
IsUpgrade bool `json:"isUpgrade" bson:"isUpgrade"` // 是否vip升级
|
||||
}
|
||||
type WhoringCardInfo struct {
|
||||
HasWhoringCard bool `json:"hasWhoringCard" bson:"hasWhoringCard"` // 是否有白嫖卡
|
||||
DetailInfo []DetailInfo `json:"detailInfo" bson:"detailInfo"` // 详细信息
|
||||
}
|
||||
|
||||
type DetailInfo struct {
|
||||
ID primitive.ObjectID `json:"id" bson:"id"` // 白嫖卡ID
|
||||
HasReturn bool `json:"hasReturn" bson:"hasReturn"` // 是否返现白嫖卡
|
||||
TotalDays int64 `json:"totalDays" bson:"totalDays"` // 需要打卡天数
|
||||
CurrentSignDays int64 `json:"currentSignDays" bson:"currentSignDays"` // 连续打卡天数
|
||||
ForgetSignDays int64 `json:"forgetSignDays" bson:"forgetSignDays"` // 忘记打卡天数
|
||||
RenewalSignDays int64 `json:"renewalSignDays" bson:"renewalSignDays"` // 补签打卡天数
|
||||
RenewalSignPrice int64 `json:"renewalSignPrice" bson:"renewalSignPrice"` // 补签打卡价格
|
||||
StartTime time.Time `json:"startTime" bson:"startTime"` // 开始时间
|
||||
EndTime time.Time `json:"endTime" bson:"endTime"` // 结束时间
|
||||
RecordTime []Record `json:"recordTime" bson:"recordTime"` // 打卡时间
|
||||
}
|
||||
|
||||
type Record struct {
|
||||
SignTime string `json:"signTime" bson:"signTime"` // 打卡时间
|
||||
IsSign bool `json:"isSign" bson:"isSign"` // 是否打卡
|
||||
}
|
||||
|
||||
// DevLoginP 块设备登陆参数
|
||||
type DevLoginP struct {
|
||||
DevID string `json:"devID"`
|
||||
DevType string `json:"devType" ` //设备型号
|
||||
SysType string `json:"sysType"` //操作系统类型 安卓 IOS
|
||||
Ver string `json:"ver" ` //APP版本号
|
||||
DevToken string `json:"devToken" bson:"devToken"` //设备token ios 推送用
|
||||
CutInfos string `json:"cutInfos"` //剪切板信息
|
||||
Mobile string `json:"mobile"` //手机号
|
||||
QrCnt string `json:"qrCnt"` //二维码内容
|
||||
}
|
||||
|
||||
// BaseInfo 返回的用户信息
|
||||
type BaseInfo struct {
|
||||
UID uint64 `json:"uid" bson:"uid"`
|
||||
Name string `json:"name" bson:"name"`
|
||||
Gender string `json:"gender" bson:"gender"`
|
||||
Portrait string `json:"portrait" bson:"portrait"`
|
||||
HasLocked bool `json:"hasLocked" bson:"hasLocked"` //已禁止登陆
|
||||
HasBanned bool `json:"hasBanned" bson:"hasBanned"` //已禁言
|
||||
}
|
||||
|
||||
// BaseInfoVip 返回的用户信息
|
||||
type BaseInfoVip 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"`
|
||||
//vip登记
|
||||
VipLevel int `json:"vipLevel"`
|
||||
//是否是vip
|
||||
IsVip bool `json:"isVip"`
|
||||
//充值等级
|
||||
RechargeLevel int `json:"rechargeLevel" ` //头像显示的vip等级,累计充值决定
|
||||
//是否是大v
|
||||
SuperUser bool `json:"superUser"` //大v
|
||||
//活跃值
|
||||
ActiveValue int `json:"activeValue"` //活跃度
|
||||
//是否官方认证
|
||||
OfficialCert bool `json:"officialCert"` //是否官方认证
|
||||
//年龄
|
||||
Age int `json:"age"`
|
||||
//关注数
|
||||
Follows int64 `json:"follows"`
|
||||
//粉丝数
|
||||
Fans int64 `json:"fans"`
|
||||
TotalWorks int64 `json:"totalWorks" bson:"totalWorks"` // 总作品数
|
||||
Summary *string `json:"summary,omitempty" bson:"summary,omitempty"` // 简介
|
||||
Awards []int `json:"awards"` // 用户奖章
|
||||
UpTag string `json:"upTag" bson:"upTag"` // 用户标签
|
||||
VipName string `json:"vipName" bson:"vipName"` // 用户VIP名称
|
||||
VipExpireDate time.Time `json:"vipExpireDate" bson:"vipExpireDate"` // VIP过期时间
|
||||
}
|
||||
|
||||
// UserInfo 用户基本信息和状态信息
|
||||
type UserInfo struct {
|
||||
BaseInfo
|
||||
}
|
||||
|
||||
// LoginWithH5 h5登陆参数
|
||||
type LoginWithH5 struct {
|
||||
Mobile string `json:"mobile" ` // 手机号
|
||||
Email string `json:"email"` // email
|
||||
Account string `json:"account"` // 账号
|
||||
Code string `json:"code" ` // 短信码
|
||||
PassWord string `json:"passWord"` // 密码
|
||||
DevID string `json:"devID" binding:"required"` // 设备id
|
||||
SysType string `json:"sysType" binding:"required"` // 操作系统类型 安卓 IOS
|
||||
CutInfos string `json:"cutInfos"` // 剪切板信息
|
||||
IsAppStore bool `json:"isAppStore"` // 是否商店包用户
|
||||
}
|
||||
|
||||
// LoginH5ByQRCode H5用户通过二维码登录
|
||||
type LoginH5ByQRCode struct {
|
||||
Content string `json:"content" binding:"required"` // 二维码内容
|
||||
}
|
||||
|
||||
// GoldVideoCouponDetail 新版观影券详情
|
||||
type GoldVideoCouponDetail struct {
|
||||
Num int `json:"num"` // 观影券面值
|
||||
Count int `json:"count"` // 观影券数量
|
||||
Source videocoupon.GoldVideoCouponSource `json:"source"` // 观影券获得方式
|
||||
}
|
||||
|
||||
// GoldVideoCoupon 观影券
|
||||
type GoldVideoCoupon struct {
|
||||
Position string `json:"position"` // 观影券位置,如“已获得”、“已使用”
|
||||
Coupons []GoldVideoCouponDetail `json:"coupons"` // 观影券
|
||||
}
|
||||
|
||||
type UserRights struct {
|
||||
UID uint64 `json:"uid"` // 用户ID
|
||||
GoldVideoCoupons []GoldVideoCoupon `json:"goldVideoCoupons"` // 观影券
|
||||
Cards []Card `json:"cards"` // 各种会员卡特权卡信息
|
||||
GoldVideoDiscount int `json:"videoDiscount"` // 视频折扣
|
||||
VipExpireDate time.Time `json:"vipExpireDate"` // 会员到期时间
|
||||
GoldVideoFreeExpire time.Time `json:"goldVideoFreeExpire"` // 金币视频免费到期时间
|
||||
}
|
||||
|
||||
type Card struct {
|
||||
Name string `json:"name"` // 卡片名称Name
|
||||
Expiration time.Time `json:"expiration"` // 到期时间
|
||||
}
|
||||
|
||||
type ResetPasswordRequest struct {
|
||||
Email string `json:"email"` // email
|
||||
Mobile string `json:"mobile"` // 电话号码
|
||||
UID uint64 `json:"uid"` // 用户ID
|
||||
TimeStamp int64 `json:"timestamp"` // 时间戳
|
||||
RandNum int64 `json:"randNum"` // 随机数
|
||||
}
|
||||
@@ -0,0 +1,163 @@
|
||||
package usermod
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
"strings"
|
||||
"time"
|
||||
|
||||
"91porn-server/common/log"
|
||||
"91porn-server/common/pageopt"
|
||||
"91porn-server/common/ysinterface/disc"
|
||||
"91porn-server/models/commod"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
)
|
||||
|
||||
// DistrictStatKey
|
||||
type DistrictStatKey struct {
|
||||
DiscSeqe `bson:",inline"` //商区码
|
||||
SysType string `bson:"sysType"` //系统类型 iOS Android
|
||||
}
|
||||
|
||||
func (d DistrictStatKey) GetDiscCode() string {
|
||||
return d.DistrictCode
|
||||
}
|
||||
|
||||
func (d DistrictStatKey) GetPromSeqe() string {
|
||||
return d.PromSeqe
|
||||
}
|
||||
|
||||
func (d DistrictStatKey) GetSysType() string {
|
||||
return d.SysType
|
||||
}
|
||||
|
||||
func (d DistrictStatKey) String() string {
|
||||
if d.DiscSeqe.String() == "" {
|
||||
return ""
|
||||
}
|
||||
return strings.ToUpper(strings.Join([]string{d.DiscSeqe.String(), d.SysType}, "-"))
|
||||
}
|
||||
|
||||
// DistrictStater
|
||||
type DistrictStater = disc.DistrictStater
|
||||
|
||||
var emptyString string
|
||||
|
||||
// DiscSeqeUserCountMap 时间内商区/序列注册数
|
||||
func DiscSeqeUserCountMap(mats ...Matcher) (map[DistrictStater]int64, error) {
|
||||
mats = append(mats, (&DistrictCodeGtMatch{&emptyString}).New())
|
||||
filter := pageopt.MergeM(mats)
|
||||
if len(filter) == 0 {
|
||||
log.Warn("DiscSeqeUserCountMap not have filter")
|
||||
return make(map[DistrictStater]int64), nil
|
||||
}
|
||||
opt := (&options.FindOptions{}).SetProjection(bson.M{
|
||||
"districtCode": 1,
|
||||
"promSeqe": 1,
|
||||
"sysType": 1,
|
||||
})
|
||||
list := []DistrictStatKey{}
|
||||
if err := coll(nil).Find(&list, filter, opt); err != nil {
|
||||
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "DiscNewUserCountByTime", table, "Find", err))
|
||||
return nil, err
|
||||
}
|
||||
m := make(map[DistrictStater]int64)
|
||||
for _, v := range list {
|
||||
if v.String() != "" {
|
||||
m[v] += 1
|
||||
}
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// DiscSeqeNewUserCountByTime 时间内商区/序列注册数
|
||||
func DiscSeqeNewUserCountByTime(start time.Time, end time.Time, mats ...Matcher) (map[DistrictStater]int64, error) {
|
||||
mats = append(mats, (&commod.DiscBindAtGTEAndLTMatch{GTE: &start, LT: &end}).New())
|
||||
return DiscSeqeUserCountMap(mats...)
|
||||
}
|
||||
|
||||
// DiscSeqeNewUIDSMap 时间内商区注册用户
|
||||
func DiscSeqeNewUIDSMap(mats ...Matcher) (map[DistrictStater][]uint64, error) {
|
||||
filter := pageopt.MergeM(mats)
|
||||
opt := (&options.FindOptions{}).SetProjection(bson.M{
|
||||
"districtCode": 1,
|
||||
"promSeqe": 1,
|
||||
"sysType": 1,
|
||||
"uid": 1,
|
||||
})
|
||||
list := []struct {
|
||||
DistrictStatKey `bson:",inline"` //商区码
|
||||
UID uint64 `bson:"uid"`
|
||||
}{}
|
||||
if err := coll(nil).Find(&list, filter, opt); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
m := make(map[DistrictStater][]uint64, len(list))
|
||||
for _, v := range list {
|
||||
if v.String() != "" {
|
||||
m[v.DistrictStatKey] = append(m[v.DistrictStatKey], v.UID)
|
||||
}
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// DiscSeqeNewUIDSMapByTime 时间内商区/序列注册用户
|
||||
func DiscSeqeNewUIDSMapByTime(start time.Time, end time.Time, mats ...Matcher) (map[DistrictStater][]uint64, error) {
|
||||
mats = append(mats, (&commod.DiscBindAtGTEAndLTMatch{GTE: &start, LT: &end}).New())
|
||||
return DiscSeqeNewUIDSMap(mats...)
|
||||
}
|
||||
|
||||
// DiscNewUIDSMap 商区注册用户
|
||||
func DiscNewUIDSMap(mats ...Matcher) (map[DistrictStater][]uint64, error) {
|
||||
filter := pageopt.MergeM(mats)
|
||||
opt := (&options.FindOptions{}).SetProjection(bson.M{
|
||||
"districtCode": 1,
|
||||
"uid": 1,
|
||||
})
|
||||
list := []struct {
|
||||
DistrictCode string `bson:"districtCode"` //商区码
|
||||
UID uint64 `bson:"uid"`
|
||||
}{}
|
||||
if err := coll(nil).Find(&list, filter, opt); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
m := make(map[DistrictStater][]uint64, len(list))
|
||||
for _, v := range list {
|
||||
key := DistrictStatKey{DiscSeqe: DiscSeqe{DistrictCode: v.DistrictCode}}
|
||||
if key.String() != "" {
|
||||
m[key] = append(m[key], v.UID)
|
||||
}
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
|
||||
// DiscNewUIDSMapByTime 时间内商区注册用户
|
||||
func DiscNewUIDSMapByTime(start time.Time, end time.Time, mats ...Matcher) (map[DistrictStater][]uint64, error) {
|
||||
mats = append(mats, (&commod.DiscBindAtGTEAndLTMatch{GTE: &start, LT: &end}).New())
|
||||
return DiscNewUIDSMap(mats...)
|
||||
}
|
||||
|
||||
// DiscNewCountMapByTime 时间内商区/序列注册数
|
||||
func DiscNewCountMapByTime(start time.Time, end time.Time, mats ...Matcher) (map[DistrictStater]int64, error) {
|
||||
mats = append(mats, (&commod.DiscBindAtGTEAndLTMatch{GTE: &start, LT: &end}).New())
|
||||
filter := pageopt.MergeM(mats)
|
||||
opt := (&options.FindOptions{}).SetProjection(bson.M{
|
||||
"districtCode": 1,
|
||||
"uid": 1,
|
||||
})
|
||||
list := []struct {
|
||||
DistrictCode string `bson:"districtCode"` //商区码
|
||||
}{}
|
||||
if err := coll(nil).Find(&list, filter, opt); err != nil {
|
||||
return nil, err
|
||||
}
|
||||
m := make(map[DistrictStater]int64, len(list))
|
||||
for _, v := range list {
|
||||
key := DistrictStatKey{DiscSeqe: DiscSeqe{DistrictCode: v.DistrictCode}}
|
||||
if key.String() != "" {
|
||||
m[key] += 1
|
||||
}
|
||||
}
|
||||
return m, nil
|
||||
}
|
||||
@@ -0,0 +1,27 @@
|
||||
package usermod
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestRenewDramaExpire(t *testing.T) {
|
||||
now := time.Date(2026, 8, 26, 12, 0, 0, 0, time.UTC)
|
||||
tests := []struct {
|
||||
name string
|
||||
current time.Time
|
||||
days int
|
||||
want time.Time
|
||||
}{
|
||||
{name: "starts from now", days: 30, want: now.AddDate(0, 0, 30)},
|
||||
{name: "extends active entitlement", current: now.AddDate(0, 0, 10), days: 30, want: now.AddDate(0, 0, 40)},
|
||||
{name: "refunds active entitlement", current: now.AddDate(0, 0, 30), days: -7, want: now.AddDate(0, 0, 23)},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := RenewDramaExpire(tt.current, now, tt.days); !got.Equal(tt.want) {
|
||||
t.Fatalf("RenewDramaExpire() = %s, want %s", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,13 @@
|
||||
package usermod
|
||||
|
||||
import "fmt"
|
||||
|
||||
// MobileHasBindError 手机已被绑定
|
||||
type MobileHasBindError struct {
|
||||
UID uint64
|
||||
DuplicateMobile string
|
||||
}
|
||||
|
||||
func (m MobileHasBindError) Error() string {
|
||||
return fmt.Sprintf("UID:%d Don't use Duplicate Mobile:%s \n", m.UID, m.DuplicateMobile)
|
||||
}
|
||||
@@ -0,0 +1,63 @@
|
||||
package usermod
|
||||
|
||||
import (
|
||||
"fmt"
|
||||
|
||||
"91porn-server/common/elastic"
|
||||
"91porn-server/common/log"
|
||||
"91porn-server/models"
|
||||
)
|
||||
|
||||
var es *elastic.Client
|
||||
|
||||
const ESTable = models.ESInfoUserTable
|
||||
|
||||
func InitESIndex() {
|
||||
es = elastic.Init()
|
||||
var setting = elastic.M{
|
||||
"settings": elastic.M{
|
||||
"number_of_shards": elastic.NumberOfShards,
|
||||
"number_of_replicas": elastic.NumberOfReplicas,
|
||||
"analysis": elastic.M{
|
||||
"analyzer": elastic.M{
|
||||
"ik": elastic.M{
|
||||
"tokenizer": elastic.AnalyzerIkSmart,
|
||||
},
|
||||
},
|
||||
},
|
||||
},
|
||||
"mappings": elastic.M{
|
||||
"properties": elastic.M{
|
||||
"name": elastic.M{
|
||||
"type": "text",
|
||||
"analyzer": elastic.AnalyzerIkSmart,
|
||||
"search_analyzer": elastic.AnalyzerIkSmart,
|
||||
},
|
||||
},
|
||||
},
|
||||
}
|
||||
if err := es.CreateIndices(ESTable, setting); err != nil {
|
||||
panic(fmt.Sprintf("%s index indeices err ==>[%+v]", ESTable, err))
|
||||
}
|
||||
}
|
||||
|
||||
func Search(keywords string, from int64, size int64) (data []*ESUserSource, err error) {
|
||||
query := elastic.M{
|
||||
"query": elastic.M{
|
||||
"match": elastic.M{
|
||||
"name": keywords,
|
||||
},
|
||||
},
|
||||
"from": from,
|
||||
"size": size,
|
||||
}
|
||||
if err = es.Search(ESTable, &data, query); err != nil {
|
||||
log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "Search", table, "CommonSearch", err),
|
||||
log.Any("keywords", keywords),
|
||||
log.Any("from", from),
|
||||
log.Any("size", size),
|
||||
)
|
||||
return nil, err
|
||||
}
|
||||
return
|
||||
}
|
||||
@@ -0,0 +1,218 @@
|
||||
package usermod
|
||||
|
||||
import (
|
||||
"91porn-server/common/pageopt"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
)
|
||||
|
||||
type Matcher = pageopt.Matcher
|
||||
|
||||
const districtCode = "districtCode"
|
||||
|
||||
// DistrictCodeGtMatch
|
||||
type DistrictCodeGtMatch struct {
|
||||
GT *string
|
||||
}
|
||||
|
||||
func (s *DistrictCodeGtMatch) New() Matcher {
|
||||
return pageopt.NewGTMatch(districtCode, s.GT)
|
||||
}
|
||||
|
||||
// DistrictCodeMatch
|
||||
type DistrictCodeMatch struct {
|
||||
DistrictCode *string
|
||||
}
|
||||
|
||||
func (s *DistrictCodeMatch) New() Matcher {
|
||||
return pageopt.NewAssignMatch(districtCode, s.DistrictCode)
|
||||
}
|
||||
|
||||
// DistrictCodeINMatch
|
||||
type DistrictCodeINMatch struct {
|
||||
DistrictCodeList []string
|
||||
}
|
||||
|
||||
func (d *DistrictCodeINMatch) New() Matcher {
|
||||
return pageopt.NewInMatch(districtCode, d.DistrictCodeList)
|
||||
}
|
||||
|
||||
// PromSeqeMatch
|
||||
type PromSeqeMatch struct {
|
||||
Seqe *string
|
||||
}
|
||||
|
||||
func (d *PromSeqeMatch) New() Matcher {
|
||||
return pageopt.NewAssignMatch("promSeqe", d.Seqe)
|
||||
}
|
||||
|
||||
// SysTypeMatch
|
||||
type SysTypeMatch struct {
|
||||
SysType *string
|
||||
}
|
||||
|
||||
func (s *SysTypeMatch) New() Matcher {
|
||||
return pageopt.NewAssignMatch("sysType", s.SysType)
|
||||
}
|
||||
|
||||
// IsDirectMatch
|
||||
type IsDirectMatch struct {
|
||||
IsDirect *bool
|
||||
}
|
||||
|
||||
func (b *IsDirectMatch) New() Matcher {
|
||||
return pageopt.NewAssignMatch("isDirect", b.IsDirect)
|
||||
}
|
||||
|
||||
// DevIDRegexMatch
|
||||
type DevIDRegexMatch struct {
|
||||
DevID *string
|
||||
}
|
||||
|
||||
func (d *DevIDRegexMatch) New() Matcher {
|
||||
return pageopt.NewRegexMatch("devID", d.DevID, "i")
|
||||
}
|
||||
|
||||
// VipLevelMatch
|
||||
type VipLevelMatch struct {
|
||||
VipLevel *int
|
||||
}
|
||||
|
||||
func (v *VipLevelMatch) New() Matcher {
|
||||
return pageopt.NewAssignMatch("vipLevel", v.VipLevel)
|
||||
}
|
||||
|
||||
// NameRegexMatch
|
||||
type NameRegexMatch struct {
|
||||
Name *string
|
||||
}
|
||||
|
||||
func (n *NameRegexMatch) New() Matcher {
|
||||
return pageopt.NewRegexMatch("name", n.Name, "i")
|
||||
}
|
||||
|
||||
// MobileMatch
|
||||
type MobileMatch struct {
|
||||
Mobile *string
|
||||
}
|
||||
|
||||
func (m *MobileMatch) New() Matcher {
|
||||
return pageopt.NewAssignMatch("mobile", m.Mobile)
|
||||
}
|
||||
|
||||
// PromotionCodeMatch
|
||||
type PromotionCodeMatch struct {
|
||||
PromotionCode *string
|
||||
}
|
||||
|
||||
func (p *PromotionCodeMatch) New() Matcher {
|
||||
return pageopt.NewAssignMatch("promotionCode", p.PromotionCode)
|
||||
}
|
||||
|
||||
// HasPromotionCodeMatch
|
||||
type HasPromotionCodeMatch struct {
|
||||
IsExisted *bool
|
||||
}
|
||||
|
||||
func (h *HasPromotionCodeMatch) New() Matcher {
|
||||
return pageopt.NewExistsMatch("promotionCode", h.IsExisted)
|
||||
}
|
||||
|
||||
// AutoFollowMatch
|
||||
type AutoFollowMatch struct {
|
||||
AutoFollow *bool
|
||||
}
|
||||
|
||||
func (l *AutoFollowMatch) New() Matcher {
|
||||
return pageopt.NewAssignMatch("autoFollow", l.AutoFollow)
|
||||
}
|
||||
|
||||
// LockedMatch
|
||||
type LockedMatch struct {
|
||||
Locked *bool
|
||||
}
|
||||
|
||||
func (l *LockedMatch) New() Matcher {
|
||||
return pageopt.NewAssignMatch("hasLocked", l.Locked)
|
||||
}
|
||||
|
||||
// BannedMatch
|
||||
type BannedMatch struct {
|
||||
Banned *bool
|
||||
}
|
||||
|
||||
func (b *BannedMatch) New() Matcher {
|
||||
return pageopt.NewAssignMatch("hasBanned", b.Banned)
|
||||
}
|
||||
|
||||
// CanUploadMatch
|
||||
type ForbidUploadMatch struct {
|
||||
ForbidUpload *bool
|
||||
}
|
||||
|
||||
func (c *ForbidUploadMatch) New() Matcher {
|
||||
return pageopt.NewAssignMatch("forbidUpload", c.ForbidUpload)
|
||||
}
|
||||
|
||||
// TrueScoreGTEMatch
|
||||
type TrueScoreGTEMatch struct {
|
||||
GTE *int64
|
||||
}
|
||||
|
||||
func (b *TrueScoreGTEMatch) New() Matcher {
|
||||
return pageopt.NewGTEMatch("trueScore", b.GTE)
|
||||
}
|
||||
|
||||
// TrueScoreMatch
|
||||
type TrueScoreMatch struct {
|
||||
TrueScore *int64
|
||||
}
|
||||
|
||||
func (b *TrueScoreMatch) New() Matcher {
|
||||
return pageopt.NewAssignMatch("trueScore", b.TrueScore)
|
||||
}
|
||||
|
||||
type RegisterIpMatch struct {
|
||||
RegisterIp *string
|
||||
}
|
||||
|
||||
func (b *RegisterIpMatch) New() Matcher {
|
||||
return pageopt.NewAssignMatch("registerIP", b.RegisterIp)
|
||||
}
|
||||
|
||||
// CreatedAtGTEAndLTMatch
|
||||
type CreatedAtGTEAndLTMatch = pageopt.CreatedAtGTEAndLTMatch
|
||||
|
||||
// UIDInMatch
|
||||
type UIDInMatch = pageopt.UIDInMatch
|
||||
|
||||
// UIDMatch
|
||||
type UIDMatch = pageopt.UIDMatch
|
||||
|
||||
type Sort = bson.D
|
||||
|
||||
var Sort_CreatedAt_n1 = Sort{{Key: "createdAt", Value: -1}}
|
||||
|
||||
type UserSlice []User
|
||||
|
||||
func List(sort bson.D, skip, limit *int64, matchs ...Matcher) (UserSlice, error) {
|
||||
opt := (&options.FindOptions{})
|
||||
if len(sort) != 0 {
|
||||
opt.SetSort(sort)
|
||||
}
|
||||
if skip != nil {
|
||||
opt.SetSkip(*skip)
|
||||
}
|
||||
if limit != nil {
|
||||
opt.SetLimit(*limit)
|
||||
}
|
||||
filter := pageopt.MergeM(matchs)
|
||||
userList := UserSlice{}
|
||||
return userList, coll(nil).Find(&userList, filter, opt)
|
||||
}
|
||||
|
||||
func Count(matchs ...Matcher) (int64, error) {
|
||||
filter := pageopt.MergeM(matchs)
|
||||
return coll(nil).Count(filter)
|
||||
}
|
||||
@@ -0,0 +1,39 @@
|
||||
package usermod
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestGetPaymentStatusPopupNewUserIgnoresFreeWatchCount(t *testing.T) {
|
||||
now := time.Now()
|
||||
|
||||
tests := []struct {
|
||||
name string
|
||||
watchCount uint64
|
||||
want string
|
||||
}{
|
||||
{
|
||||
name: "remaining free views stays new unpaid",
|
||||
watchCount: 3,
|
||||
want: UserPaymentStatusPopupNewUnpay,
|
||||
},
|
||||
{
|
||||
name: "exhausted free views stays new unpaid",
|
||||
watchCount: 0,
|
||||
want: UserPaymentStatusPopupNewUnpay,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
user := &User{
|
||||
CreatedAt: now.Add(-time.Hour),
|
||||
WatchCount: tt.watchCount,
|
||||
}
|
||||
if got := user.GetPaymentStatusPopup(); got != tt.want {
|
||||
t.Fatalf("GetPaymentStatusPopup() = %q, want %q", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,396 @@
|
||||
package usermod
|
||||
|
||||
import (
|
||||
"encoding/json"
|
||||
"time"
|
||||
|
||||
"91porn-server/common/db"
|
||||
"91porn-server/common/timeutil"
|
||||
"91porn-server/models/commod"
|
||||
|
||||
"github.com/shopspring/decimal"
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
)
|
||||
|
||||
var mdb *db.MongoDB
|
||||
|
||||
const (
|
||||
_ = iota
|
||||
ThreeDayVIP_SnapVip //3天临时永久vip
|
||||
)
|
||||
|
||||
type UserType uint8
|
||||
|
||||
const (
|
||||
UserUnkown UserType = iota
|
||||
UserLoufengAgent //楼风代理 1
|
||||
UserTourists //游客 2
|
||||
)
|
||||
|
||||
// 用户分层弹窗-付费状态分层
|
||||
const (
|
||||
UserPaymentStatusPopupUnkown = "unkown" // 未知
|
||||
UserPaymentStatusPopupNewUnpay = "new_unpay" // 新用户
|
||||
UserPaymentStatusPopupUnder7DayUnpay = "under_7_day_unpay" // 7天内未付费用户
|
||||
UserPaymentStatusPopupUnder7DayUnpayNoCountdown = "under_7_day_unpay_no_countdown" // 7天内未付费用户无倒计时
|
||||
UserPaymentStatusPopupOver7DayUnpay = "over_7_day_unpay" // 7天后未付费用户
|
||||
UserPaymentStatusPopupOver7DayNeedUpgrade = "over_7_day_need_upgrade" // 已付费但未达最高等级,需升级
|
||||
UserPaymentStatusPopupMaxVIPLevel = "max_vip_level" // 达到最大vip等级
|
||||
UserPaymentStatusPopupUnregistered = "unregistered" // 未注册用户
|
||||
UserPaymentStatusPopupNormal = "normal" // 正常用户
|
||||
)
|
||||
|
||||
type DiscSeqe = commod.DiscSeqe
|
||||
|
||||
type DiscDoc = commod.DiscDoc
|
||||
|
||||
// User 用户信息
|
||||
type User struct {
|
||||
ID primitive.ObjectID `json:"id" bson:"_id,omitempty"`
|
||||
//用户id
|
||||
UID uint64 `json:"uid" bson:"uid"`
|
||||
//设备id
|
||||
DevID string `json:"devID" bson:"devID"`
|
||||
//设备类型
|
||||
DevType string `json:"devType" bson:"devType"`
|
||||
//设备token ios 推送用
|
||||
DevToken string `json:"devToken" bson:"devToken"`
|
||||
//注册IP
|
||||
RegisterIP string `json:"registerIP" bson:"registerIP"`
|
||||
//手机号
|
||||
Mobile string `json:"mobile" bson:"mobile"`
|
||||
//性别
|
||||
Gender string `json:"gender" bson:"gender"`
|
||||
//姓名
|
||||
Name string `json:"name" bson:"name"`
|
||||
//头像
|
||||
Portrait string `json:"portrait" bson:"portrait"`
|
||||
//背景图
|
||||
Background []string `json:"background,omitempty" bson:"background,omitempty"`
|
||||
//简介
|
||||
Summary string `json:"summary" bson:"summary"`
|
||||
//地区
|
||||
Region string `json:"region" bson:"region"`
|
||||
//生日
|
||||
Birthday string `json:"birthday" bson:"birthday"`
|
||||
VipName string `json:"vipName" bson:"vipName"`
|
||||
// vip等级 0-非vip会员 1-月卡用户 2-季卡用户 3-年卡用户 4-永久会员
|
||||
VipLevel int `json:"vipLevel" bson:"vipLevel"`
|
||||
//已禁止登陆
|
||||
HasLocked bool `json:"hasLocked" bson:"hasLocked"`
|
||||
//禁止登录的原因
|
||||
LockReason string `json:"lockReason" bson:"lockReason"`
|
||||
//封禁开始时间
|
||||
LockAt time.Time `json:"lockAt" bson:"lockAt"`
|
||||
//禁止登录的原因截图
|
||||
LockImg *string `json:"lockImg,omitempty" bson:"lockImg,omitempty"`
|
||||
//已禁言
|
||||
HasBanned bool `json:"hasBanned" bson:"hasBanned"`
|
||||
//是否禁止上传帖子
|
||||
ForbidUpload bool `json:"forbidUpload" bson:"forbidUpload"`
|
||||
//用户令牌
|
||||
Token string `json:"token" bson:"token"`
|
||||
//观看次数
|
||||
WatchCount uint64 `json:"watchCount" bson:"watchCount"`
|
||||
//应用锁
|
||||
AppLock string `json:"appLock" bson:"appLock"`
|
||||
//用户真实性得分
|
||||
TrueScore int64 `json:"trueScore" bson:"trueScore"`
|
||||
//注册时登陆版本
|
||||
Ver string `json:"ver" bson:"ver"`
|
||||
//最后登陆版本
|
||||
LastVer string `json:"lastVer" bson:"lastVer"`
|
||||
//默认入口已处理版本,仅供后端判断当前版本是否首次进入
|
||||
DefaultEntryHandledVer string `json:"-" bson:"defaultEntryHandledVer,omitempty"`
|
||||
//系统类型
|
||||
SysType string `json:"sysType" bson:"sysType"`
|
||||
//最后登陆时间
|
||||
LastVisitAt time.Time `json:"lastVisitAt" bson:"lastVisitAt"`
|
||||
//最后登陆系统类型
|
||||
LastSysType string `json:"lastSysType" bson:"lastSysType"`
|
||||
//vip过期时间
|
||||
VipExpireDate time.Time `json:"vipExpireDate" bson:"vipExpireDate"`
|
||||
//金币月卡过期时间
|
||||
CoinMouthExpireDate time.Time `json:"coinMouthExpireDate" bson:"coinMouthExpireDate"` //金币月卡过期时间
|
||||
//创建时间
|
||||
CreatedAt time.Time `json:"createdAt" bson:"createdAt"`
|
||||
//修改时间
|
||||
UpdatedAt time.Time `json:"updatedAt" bson:"updatedAt"`
|
||||
//手机绑定时间,缺省参数 不能删除omitempty
|
||||
MobileBindAt *time.Time `json:"mobileBindAt" bson:"mobileBindAt,omitempty"`
|
||||
//手机解绑时间,缺省参数 不能删除omitempty
|
||||
MobileUnBindAt *time.Time `json:"mobileUnBindAt" bson:"mobileUnBindAt,omitempty"`
|
||||
//是商区代理
|
||||
IsDAgent bool `json:"isDAgent" bson:"isDAgent"`
|
||||
//推广码
|
||||
PromCode string `json:"promotionCode" bson:"promotionCode"`
|
||||
//商区
|
||||
DiscDoc `bson:",inline"`
|
||||
//大v
|
||||
SuperUser bool `json:"superUser" bson:"superUser"` // 0不是大v 1大v
|
||||
SuperUserExpire time.Time `json:"superUserExpire" bson:"superUserExpire"` // 大V 持续时间
|
||||
MerchantUser int `json:"merchantUser" bson:"merchantUser"` // 商家认证,0:用户,1商家
|
||||
MerchantUserExpire time.Time `json:"merchantUserExpire" bson:"merchantUserExpire"` // 商家认证持续时间
|
||||
//活跃度
|
||||
ActiveValue int `json:"activeValue" bson:"activeValue"`
|
||||
//是否官方认证
|
||||
OfficialCert bool `json:"officialCert" bson:"officialCert"`
|
||||
//扣税等级,默认0,3.7;
|
||||
TaxLevel int64 `json:"taxLevel" bson:"taxLevel"`
|
||||
//登陆天数
|
||||
LoginDays int64 `json:"loginDays" bson:"loginDays"`
|
||||
//获得打赏的金额
|
||||
Rewarded decimal.Decimal `json:"rewarded" bson:"rewarded"`
|
||||
//临时vip
|
||||
SnapVip bool `json:"snapVip" bson:"snapVip"`
|
||||
//临时vip记录的原始vip时间
|
||||
OriginVipExpire *time.Time `json:"-" bson:"originVipExpire,omitempty"`
|
||||
//临时vip记录的原始vip等级
|
||||
OriginVipLevel *int `json:"-" bson:"originVipLevel,omitempty"`
|
||||
// 是否有白嫖卡
|
||||
HasWhoringCard bool `json:"hasWhoringCard" bson:"hasWhoringCard"`
|
||||
//楼凤全免过期时间
|
||||
LouFengQmExpiration *time.Time `json:"louFengQmExpiration,omitempty" bson:"louFengQmExpiration,omitempty"`
|
||||
//是否配置被自动关注
|
||||
AutoFollow bool `json:"autoFollow" bson:"autoFollow"`
|
||||
//是否进入过游戏
|
||||
HasEnteredGame bool `json:"hasEnteredGame" bson:"hasEnteredGame"`
|
||||
//赠送楼凤解锁次数
|
||||
LouFengUnlockTimes int `json:"louFengUnlockTimes" bson:"louFengUnlockTimes"`
|
||||
//金币视频免费日期
|
||||
GoldVideoFreeExpire time.Time `json:"goldVideoFreeExpire" bson:"goldVideoFreeExpire"`
|
||||
//每周活跃度
|
||||
WeeklyActiveValue int64 `json:"weeklyActiveValue" bson:"weeklyActiveValue"`
|
||||
//银行卡绑定名字
|
||||
BankActName string `json:"bankActName" bson:"bankActName"`
|
||||
// 新版原创排序
|
||||
OriginalSort int `json:"originalSort" bson:"originalSort"`
|
||||
//应用中心下载信息
|
||||
PUC string `json:"puc" bson:"puc"`
|
||||
//视频扣量,1:博主10单扣1单, 以此类推
|
||||
VideoDeduction float64 `json:"videoDeduction" bson:"videoDeduction"`
|
||||
//视频扣量购买次数
|
||||
VideoDeductionPayCount int `json:"videoDeductionPayCount" bson:"videoDeductionPayCount"`
|
||||
//视频扣量次数
|
||||
VideoDeductionCount int `json:"videoDeductionCount" bson:"videoDeductionCount"`
|
||||
//图片被购买数量(作为作者) 此项目暂不对外暴露 因此设置`json:"-"`
|
||||
CoverPayCount int `json:"-" bson:"coverPayCount"`
|
||||
//是否首充充值瓦力
|
||||
HasFirstChargeWaLi bool `json:"hasFirstChargeWaLi" bson:"hasFirstChargeWaLi"`
|
||||
//是否充值棋牌
|
||||
HasFirstChargeVID bool `json:"hasFirstChargeVID" bson:"hasFirstChargeVID"`
|
||||
//商家账号
|
||||
MerchantAccount string `json:"merchantAccount" bson:"merchantAccount"`
|
||||
//支付视频折扣
|
||||
PayVidDiscount int `json:"payVidDiscount" bson:"payVidDiscount"`
|
||||
//金币视频免费券
|
||||
GoldVideoCoupon []UserGoldVideoCoupon `json:"goldVideoCoupon,omitempty" bson:"goldVideoCoupon,omitempty"`
|
||||
//视频免费过期时间--仅对金币数少于特定数目的视频有效
|
||||
VideoFreeExpiration *time.Time `json:"videoFreeExpiration" bson:"videoFreeExpiration,omitempty"`
|
||||
//密码
|
||||
PassWord string `json:"passWord" bson:"passWord"`
|
||||
//邮箱
|
||||
Email string `json:"email" bson:"email"`
|
||||
//通过邮箱验证时间
|
||||
EmailCheckedAt *time.Time `json:"emailCheckedAt" bson:"emailCheckedAt,omitempty"`
|
||||
//用户自己设定的账号 用于找回账号重设密码
|
||||
Account string `json:"account" bson:"account"`
|
||||
//账号绑定时间
|
||||
AccountBindAt *time.Time `json:"accountBindAt" bson:"accountBindAt"`
|
||||
//用户类型
|
||||
Type UserType `json:"userType" bson:"userType"`
|
||||
//天数
|
||||
LoufengBookExpiration time.Time `json:"loufengBookDiscountExpiration" bson:"loufengBookDiscountExpiration"`
|
||||
TotalWorks int64 `json:"totalWorks" bson:"totalWorks"` // 总作品数
|
||||
VidUploadCount int64 `json:"vidUploadCount" bson:"vidUploadCount"` // 视频上传次数
|
||||
CoverUploadCount int64 `json:"coverUploadCount" bson:"coverUploadCount"` // 图片帖子上传次数
|
||||
AiUndressCount int64 `json:"aiUndressCount" bson:"aiUndressCount"` // ai脱衣剩余次数
|
||||
Awards []int `json:"awards" bson:"awards,omitempty"` // 奖励
|
||||
AwardsExpire []AwardsExpire `json:"awardsExpire" bson:"awardsExpire,omitempty"` // 奖章过期时间
|
||||
Follows int64 `json:"follows" bson:"follows"` // 关注数
|
||||
Fans int64 `json:"fans" bson:"fans"` // 粉丝数
|
||||
UpTag string `json:"upTag" bson:"upTag"` // 博主认证
|
||||
LikeCount int `json:"likeCount" bson:"likeCount"` // 点赞数
|
||||
ChatPrice int64 `json:"chatPrice" bson:"chatPrice,omitempty"` // 私信价格
|
||||
IsAdvertiser bool `json:"isAdvertiser" bson:"isAdvertiser"` // 是否是打广告用户
|
||||
AllGoldVideoFree bool `json:"allGoldVideoFree" bson:"allGoldVideoFree"` // 是否所有金币视频免费
|
||||
BannedTime time.Time `json:"bannedTime" bson:"bannedTime"` // 禁言时间
|
||||
AiMateUid string `json:"aiMateUid" bson:"aiMateUid"` // ai伴侣uid,对应第三方服务
|
||||
BroadcastExpire time.Time `json:"broadcastExpire" bson:"broadcastExpire,omitempty"` //直播有效期
|
||||
DramaExpire time.Time `json:"dramaExpire" bson:"dramaExpire,omitempty"` //短剧权益有效期
|
||||
GoldVideoFreeLimit int64 `json:"goldVideoFreeLimit" bson:"goldVideoFreeLimit"`
|
||||
SendMsgPrice int64 `json:"sendMsgPrice"` // 发送私信价格
|
||||
IsRegister bool `json:"isRegister"` // 是否注册
|
||||
Tid string `json:"tid" bson:"tid"` // 粘贴板传过来的tid(traceId)
|
||||
//已开启私密圈
|
||||
HasPrivateZone bool `json:"hasPrivateZone" bson:"hasPrivateZone"`
|
||||
OriVer string `json:"oriVer" bson:"oriVer"` // 原始版本
|
||||
AdGroup commod.AdGroup `json:"adGroup" bson:"adGroup"` // 广告组
|
||||
}
|
||||
|
||||
// AwardsExpire 奖章过期时间
|
||||
type AwardsExpire struct {
|
||||
AwardID primitive.ObjectID `json:"awardID" bson:"awardID,omitempty"` // 奖章
|
||||
Number int `json:"number" bson:"number,omitempty"` // 奖章价值
|
||||
AwardExpire time.Time `json:"awardExpire" bson:"awardExpire,omitempty"` // 奖章过期时间
|
||||
}
|
||||
|
||||
type UploadCountInc struct {
|
||||
TotalWorks *int64 `bson:"totalWorks,omitempty"` //视频上传次数
|
||||
VidUploadCount *int64 `bson:"vidUploadCount,omitempty"` //视频上传次数
|
||||
CoverUploadCount *int64 `bson:"coverUploadCount,omitempty"` //图片帖子上传次数
|
||||
}
|
||||
|
||||
// LoufengAgent 楼凤经纪人
|
||||
type LoufengAgent struct {
|
||||
//楼凤经纪人账号,由统计中心同步过来
|
||||
Account string `json:"agentAccount" bson:"agentAccount"`
|
||||
//是否可赔付
|
||||
Payable bool `json:"payable" bson:"payable"`
|
||||
//保证金
|
||||
Deposit int `json:"deposit" bson:"deposit"`
|
||||
//简介
|
||||
Introduce string `json:"introduce" bson:"introduce"`
|
||||
}
|
||||
|
||||
// 用户金币视频抵用券
|
||||
type UserGoldVideoCoupon struct {
|
||||
//金币
|
||||
Gold int `json:"gold" bson:"gold"`
|
||||
//券数量
|
||||
Count int `json:"count" bson:"count"`
|
||||
}
|
||||
|
||||
type ESUser struct {
|
||||
ID primitive.ObjectID `json:"id"`
|
||||
UID uint64 `json:"uid"` //用户id
|
||||
Gender string `json:"gender"` //性别
|
||||
Name string `json:"name"`
|
||||
Summary string `json:"summary"` //简介
|
||||
Region string `json:"region"` //地区
|
||||
CreatedAt time.Time `json:"createdAt"`
|
||||
UpdatedAt time.Time `json:"updatedAt"`
|
||||
HasLocked bool `json:"hasLocked"` //已禁止登陆
|
||||
HasBanned bool `json:"hasBanned"` //已禁言
|
||||
}
|
||||
|
||||
type ESUserSource struct {
|
||||
ID string `json:"_id"`
|
||||
Source ESUser `json:"_source"`
|
||||
}
|
||||
|
||||
// UserStat 用户信息统计
|
||||
type UserStat struct {
|
||||
ID primitive.ObjectID `json:"id" bson:"_id,omitempty"`
|
||||
CreatedAt time.Time `json:"createdAt" bson:"createdAt"`
|
||||
}
|
||||
|
||||
func (u *User) Age() int {
|
||||
bir := u.Birthday
|
||||
bir = bir + " 00:00:00"
|
||||
btm, _ := time.ParseInLocation("2006-01-02 15:04:05", bir, time.Local)
|
||||
if btm.IsZero() {
|
||||
return 0
|
||||
}
|
||||
return timeutil.Age(btm, time.Now())
|
||||
}
|
||||
|
||||
func Init() {
|
||||
mdb = db.Init(table)
|
||||
initIndex()
|
||||
}
|
||||
|
||||
// IsNewUser reports whether the user registered less than 24 hours ago.
|
||||
func (u *User) IsNewUser(now time.Time) bool {
|
||||
return u != nil && !u.CreatedAt.IsZero() && now.Before(u.CreatedAt.Add(24*time.Hour))
|
||||
}
|
||||
|
||||
func (u User) IsPaidVIP() bool {
|
||||
return u.VipExpireDate.After(time.Now()) && (u.VipLevel >= 1)
|
||||
}
|
||||
|
||||
func (u User) IsVIP(now time.Time) bool {
|
||||
return u.VipExpireDate.After(now)
|
||||
}
|
||||
|
||||
func (u *User) GetSuperUser(now time.Time) bool {
|
||||
if u.SuperUserExpire.Before(now) {
|
||||
return false
|
||||
} else {
|
||||
return u.SuperUser
|
||||
}
|
||||
}
|
||||
|
||||
// VisitValue
|
||||
type VisitValue struct {
|
||||
UID uint64 `json:"uid"`
|
||||
SysType string `json:"sysType"`
|
||||
}
|
||||
|
||||
// RegistValue
|
||||
type RegistValue = VisitValue
|
||||
|
||||
func (v VisitValue) JsonString() string {
|
||||
ct, _ := json.Marshal(v)
|
||||
return string(ct)
|
||||
}
|
||||
|
||||
func GetGoldVideoFreeLimit(u *User) int64 {
|
||||
if u == nil {
|
||||
return 0
|
||||
}
|
||||
// 已经过了金币免费,则只有0
|
||||
if !u.GoldVideoFreeExpire.After(time.Now()) {
|
||||
return 0
|
||||
}
|
||||
var goldVideoFreeLimit int64 = 50
|
||||
if u == nil {
|
||||
return goldVideoFreeLimit
|
||||
}
|
||||
// 按照用户自身的限制门槛来判断
|
||||
if u.GoldVideoFreeLimit > 0 {
|
||||
goldVideoFreeLimit = u.GoldVideoFreeLimit
|
||||
}
|
||||
return goldVideoFreeLimit
|
||||
}
|
||||
|
||||
// GetPaymentStatusPopup 计算用户付费状态分层,用于下发不同的分层弹窗配置。
|
||||
// 注:91porn 的 VipLevel 语义为 0-非会员 1-月卡 2-季卡 3-年卡 4-永久会员,故最高等级为 4。
|
||||
func (u *User) GetPaymentStatusPopup() string {
|
||||
if u == nil {
|
||||
return UserPaymentStatusPopupUnregistered
|
||||
}
|
||||
|
||||
now := time.Now()
|
||||
// 新用户:注册时间在一天以内,且不是付费会员。
|
||||
// 旧版分层只按注册时间和付费状态判断,免费观看次数由新版付费引导单独处理。
|
||||
if u.IsNewUser(now) && !u.IsPaidVIP() {
|
||||
return UserPaymentStatusPopupNewUnpay
|
||||
}
|
||||
|
||||
// 7天内未付费用户
|
||||
if u.CreatedAt.AddDate(0, 0, 7).After(now) && !u.IsPaidVIP() {
|
||||
if u.CreatedAt.AddDate(0, 0, 2).After(now) && !u.IsPaidVIP() { // 两天内未付费用户使用带倒计时图片源
|
||||
return UserPaymentStatusPopupUnder7DayUnpay
|
||||
}
|
||||
return UserPaymentStatusPopupUnder7DayUnpayNoCountdown
|
||||
}
|
||||
|
||||
// 7天后仍未付费用户
|
||||
if u.CreatedAt.AddDate(0, 0, 7).Before(now) && !u.IsPaidVIP() {
|
||||
return UserPaymentStatusPopupOver7DayUnpay
|
||||
}
|
||||
|
||||
if u.IsPaidVIP() {
|
||||
// 已付费,但未达最高等级(永久会员),引导续费升级
|
||||
if !u.VipExpireDate.IsZero() && u.VipLevel < 4 {
|
||||
return UserPaymentStatusPopupOver7DayNeedUpgrade
|
||||
}
|
||||
// 已达最高等级(永久会员)
|
||||
if !u.VipExpireDate.IsZero() && u.VipLevel == 4 {
|
||||
return UserPaymentStatusPopupMaxVIPLevel
|
||||
}
|
||||
}
|
||||
|
||||
return UserPaymentStatusPopupNormal
|
||||
}
|
||||
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,12 @@
|
||||
package usermod
|
||||
|
||||
import "time"
|
||||
|
||||
// RenewVIPLevel returns the level that should remain after extending VIP.
|
||||
// An active higher level must not be downgraded by a lower-level renewal.
|
||||
func RenewVIPLevel(currentExpire, now time.Time, currentLevel, renewedLevel int) int {
|
||||
if currentExpire.After(now) && currentLevel > renewedLevel {
|
||||
return currentLevel
|
||||
}
|
||||
return renewedLevel
|
||||
}
|
||||
@@ -0,0 +1,47 @@
|
||||
package usermod
|
||||
|
||||
import (
|
||||
"testing"
|
||||
"time"
|
||||
)
|
||||
|
||||
func TestRenewVIPLevel(t *testing.T) {
|
||||
now := time.Date(2026, 8, 29, 12, 0, 0, 0, time.UTC)
|
||||
tests := []struct {
|
||||
name string
|
||||
currentExpire time.Time
|
||||
currentLevel int
|
||||
renewedLevel int
|
||||
want int
|
||||
}{
|
||||
{
|
||||
name: "preserves active higher level",
|
||||
currentExpire: now.Add(24 * time.Hour),
|
||||
currentLevel: 3,
|
||||
renewedLevel: 1,
|
||||
want: 3,
|
||||
},
|
||||
{
|
||||
name: "upgrades active lower level",
|
||||
currentExpire: now.Add(24 * time.Hour),
|
||||
currentLevel: 1,
|
||||
renewedLevel: 3,
|
||||
want: 3,
|
||||
},
|
||||
{
|
||||
name: "uses renewed level after expiration",
|
||||
currentExpire: now.Add(-time.Second),
|
||||
currentLevel: 3,
|
||||
renewedLevel: 1,
|
||||
want: 1,
|
||||
},
|
||||
}
|
||||
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
if got := RenewVIPLevel(tt.currentExpire, now, tt.currentLevel, tt.renewedLevel); got != tt.want {
|
||||
t.Fatalf("RenewVIPLevel() = %d, want %d", got, tt.want)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
@@ -0,0 +1,278 @@
|
||||
package usermod
|
||||
|
||||
import (
|
||||
"time"
|
||||
|
||||
"91porn-server/common/log"
|
||||
"91porn-server/models/l/payvidlgmod"
|
||||
"91porn-server/models/v/prdcthsomod"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
)
|
||||
|
||||
type UserListSelector struct {
|
||||
UID *uint64 `form:"uid,omitempty" json:"uid,omitempty" bson:"uid,omitempty"` //用户id
|
||||
DevID *string `form:"devID,omitempty" json:"devID,omitempty" bson:"devID,omitempty"` //设备id
|
||||
DevType *string `form:"devType,omitempty" json:"devType,omitempty" bson:"devType,omitempty"` //设备类型
|
||||
DevToken *string `form:"devToken,omitempty" json:"devToken,omitempty" bson:"devToken,omitempty"` //设备toke`n ios 推送用
|
||||
RegisterIP *string `form:"registerIP,omitempty" json:"registerIP,omitempty" bson:"registerIP,omitempty"` //注册IP
|
||||
Mobile *string `form:"mobile,omitempty" json:"mobile,omitempty" bson:"mobile,omitempty"` //手机号
|
||||
Gender *string `form:"gender,omitempty" json:"gender,omitempty" bson:"gender,omitempty"` //性别
|
||||
Channel *string `form:"channel,omitempty" json:"channel,omitempty" bson:"channel,omitempty"`
|
||||
Name *string `form:"name,omitempty" json:"name,omitempty" bson:"name,omitempty"`
|
||||
PromotionCode *string `form:"promotionCode,omitempty" json:"promotionCode,omitempty" bson:"promotionCode,omitempty"` //推广码
|
||||
Portrait *string `form:"portrait,omitempty" json:"portrait,omitempty" bson:"portrait,omitempty"` //头像
|
||||
Summary *string `form:"summary,omitempty" json:"summary,omitempty" bson:"summary,omitempty"` //简介
|
||||
Region *string `form:"region,omitempty" json:"region,omitempty" bson:"region,omitempty"` //地区
|
||||
Birthday *string `form:"birthday,omitempty" json:"birthday,omitempty" bson:"birthday,omitempty"` //生日
|
||||
VipLevel *int `form:"vipLevel,omitempty" json:"vipLevel,omitempty" bson:"vipLevel,omitempty"` //vip等级
|
||||
HasLocked *bool `form:"hasLocked,omitempty" json:"hasLocked,omitempty" bson:"hasLocked,omitempty"` //已禁止登陆
|
||||
HasBanned *bool `form:"hasBanned,omitempty" json:"hasBanned,omitempty" bson:"hasBanned,omitempty"` //已禁言
|
||||
Token *string `form:"token,omitempty" json:"token,omitempty" bson:"token,omitempty"` //用户令牌
|
||||
WatchCount *uint64 `from:"watchCount,omitempty" json:"watchCount,omitempty" bson:"watchCount,omitempty"` //观看次数
|
||||
BankActName *string `json:"bankActName,omitempty" bson:"bankActName,omitempty"` //银行卡绑定名字
|
||||
UpTag *string `form:"upTag" json:"upTag,omitempty" bson:"upTag,omitempty"` // 博主认证
|
||||
}
|
||||
|
||||
// ExportUser 导出的用户信息
|
||||
type ExportUser struct {
|
||||
UID uint64 `xlsx:"用户id"`
|
||||
//DevID string `xlsx:"设备id"`
|
||||
DevType string `xlsx:"设备类型"`
|
||||
RegisterIP string `xlsx:"注册IP"`
|
||||
Mobile string `xlsx:"手机号"`
|
||||
//Gender string `xlsx:"性别"`
|
||||
Channel string `xlsx:"渠道号"`
|
||||
//Name string `xlsx:"用户名"`
|
||||
PromotionCode string `xlsx:"推广码"`
|
||||
//Summary string `xlsx:"简介"`
|
||||
//Region string `xlsx:"地区"`
|
||||
//Birthday string `xlsx:"生日"`
|
||||
//VipLevel int `xlsx:"vip等级"`
|
||||
VipExpireDate time.Time `xlsx:"vip过期时间"`
|
||||
CreatedAt time.Time `xlsx:"用户创建时间"`
|
||||
LastVisitAt time.Time `xlsx:"最后活跃时间"`
|
||||
//MobileBindAt *time.Time `xlsx:"手机绑定时间"`
|
||||
//HasLocked bool `xlsx:"已禁止登陆"`
|
||||
//HasBanned bool `xlsx:"已禁言"`
|
||||
WatchCount int `xlsx:"七日观看次数"` //七日观看次数,和数据库存的不同
|
||||
//VisitCount int `xlsx:"24小时内访问数"`
|
||||
//TotalVideoCnt int `xlsx:"视频总数"`
|
||||
//UndealVideoCnt int `xlsx:"未审核视频数"`
|
||||
}
|
||||
|
||||
// 用户VIP返回数据
|
||||
type UserVipInfoRes struct {
|
||||
VideoDiscount int `json:"videoDiscount"` //视频折扣率
|
||||
VideoDiscountExpiration time.Time `json:"videoDiscountExpiration"` // 视频折扣卡到期时间
|
||||
VipExpireDate time.Time `json:"vipExpireDate"` //vip过期时间
|
||||
GoldVideoFreeExpire time.Time `json:"goldVideoFreeExpire"` //金币视频免费日期
|
||||
PayVidDiscount int `json:"payVidDiscount"` //支付视频折扣
|
||||
VideoFreeExpiration *time.Time `json:"videoFreeExpiration"` //视频免费过期时间
|
||||
GoldVideoCoupon []UserGoldVideoCoupon `json:"goldVideoCoupon"`
|
||||
}
|
||||
|
||||
func FindAgentByAccount(acc string) (user *User, err error) {
|
||||
if acc == "" {
|
||||
return
|
||||
}
|
||||
err = coll(nil).FindOne(&user, bson.M{"agentAccount": acc})
|
||||
return
|
||||
}
|
||||
|
||||
func FindAllPayableAgents() ([]string, error) {
|
||||
var p []struct {
|
||||
AgentAcc string `bson:"agentAccount"`
|
||||
}
|
||||
if err := coll(nil).Find(&p, bson.M{
|
||||
"agentAccount": bson.M{"$gt": ""},
|
||||
"deposit": bson.M{"$gt": 0},
|
||||
"payable": true,
|
||||
"userType": UserLoufengAgent,
|
||||
}, options.Find().SetProjection(bson.M{"agentAccount": 1})); err != nil {
|
||||
return []string{}, err
|
||||
}
|
||||
agents := make([]string, len(p))
|
||||
for i, agent := range p {
|
||||
agents[i] = agent.AgentAcc
|
||||
}
|
||||
return agents, nil
|
||||
}
|
||||
|
||||
// FindMany 查询所有
|
||||
func FindMany(filter bson.M, _ *options.FindOptions, skip int64, size int64) ([]*User, error) {
|
||||
sort := bson.D{{Key: "createdAt", Value: -1}}
|
||||
opts := options.FindOptions{}
|
||||
opts.SetSort(sort).SetSkip(skip).SetLimit(size)
|
||||
data := make([]*User, 0)
|
||||
if err := coll(nil).Find(&data, filter, &opts); err != nil {
|
||||
log.ZapLog.Warn("proxy FindMany Find fail", log.E(err))
|
||||
return data, err
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
// ExportFindMany 导出的时候查询所有
|
||||
func ExportFindMany(filter bson.M, skip int64, size int64) ([]*User, error) {
|
||||
sort := bson.D{{Key: "createdAt", Value: 1}}
|
||||
filter["userType"] = bson.M{"$in": []UserType{UserUnkown, UserLoufengAgent}}
|
||||
opts := options.FindOptions{}
|
||||
opts.SetSort(sort).SetSkip(skip).SetLimit(size)
|
||||
data := make([]*User, 0)
|
||||
if err := coll(nil).Find(&data, filter, &opts); err != nil {
|
||||
log.ZapLog.Warn(" ExportFindMany Find fail", log.E(err))
|
||||
return data, err
|
||||
}
|
||||
return data, nil
|
||||
}
|
||||
|
||||
// GetTotalCnt 查询数量
|
||||
func GetTotalCnt(filter bson.M, _ *options.FindOptions) (total int64, err error) {
|
||||
total, err = coll(nil).Count(filter)
|
||||
if err != nil {
|
||||
log.ZapLog.Warn("GetTotalCnt fail", log.E(err))
|
||||
}
|
||||
return
|
||||
}
|
||||
|
||||
// PayUIDCountByCreatedTime 消费包括 购买VIP、付费视屏
|
||||
func PayUIDCountByCreatedTime(start time.Time, end time.Time) ([]uint64, error) {
|
||||
//购买VIP /分
|
||||
vUIDList, err := prdcthsomod.PayVipUIDSByCreatedTime(start, end)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
//付费视屏 /金币
|
||||
pUIDList, err := payvidlgmod.GetUIDListByPayTime(start, end)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
payUIDMap := make(map[uint64]byte, len(vUIDList)+len(pUIDList))
|
||||
//转载payUIDMap
|
||||
for _, uid := range vUIDList {
|
||||
payUIDMap[uid] = 1
|
||||
}
|
||||
for _, uid := range pUIDList {
|
||||
payUIDMap[uid] = 1
|
||||
}
|
||||
//取出payUID
|
||||
payUIDList := make([]uint64, len(payUIDMap))
|
||||
i := 0
|
||||
for k := range payUIDMap {
|
||||
payUIDList[i] = k
|
||||
i++
|
||||
}
|
||||
return payUIDList, nil
|
||||
}
|
||||
|
||||
// NewAndPayUIDListByCreatedTime 消费包括 购买VIP、付费视屏
|
||||
func NewAndPayUIDListByCreatedTime(start time.Time, end time.Time) ([]uint64, error) {
|
||||
uidList, err := FindUIDByCreateTime(start, end)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
vUIDList, err := prdcthsomod.PayVipUIDSByCreatedTime(start, end)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
pUIDList, err := payvidlgmod.GetUIDListByPayTime(start, end)
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
payUIDMap := make(map[uint64]bool, len(uidList))
|
||||
//转载payUIDMap
|
||||
for _, uid := range pUIDList {
|
||||
payUIDMap[uid] = false
|
||||
}
|
||||
//标记消费的的UID
|
||||
for _, uid := range vUIDList {
|
||||
if _, ok := payUIDMap[uid]; ok {
|
||||
payUIDMap[uid] = true
|
||||
}
|
||||
}
|
||||
for _, uid := range pUIDList {
|
||||
if _, ok := payUIDMap[uid]; ok {
|
||||
payUIDMap[uid] = true
|
||||
}
|
||||
}
|
||||
//取出payUID
|
||||
payUIDList := make([]uint64, 0, len(payUIDMap))
|
||||
for k, v := range payUIDMap {
|
||||
if v {
|
||||
payUIDList = append(payUIDList, k)
|
||||
}
|
||||
}
|
||||
return payUIDList, nil
|
||||
}
|
||||
|
||||
type UpdateFreeTimesCond struct {
|
||||
UID uint64 `json:"uid" bson:"uid" binding:"required"` // 用户ID
|
||||
FreeTimes *int64 `json:"freeTimes" bson:"freeTimes"` // 免费次数
|
||||
Mark *string `json:"mark" bson:"mark"` // 备注
|
||||
}
|
||||
|
||||
func (receiver *UpdateFreeTimesCond) Filter() bson.M {
|
||||
return bson.M{"uid": receiver.UID, "aiUndressFreeTimes": bson.M{"$gte": receiver.FreeTimes}}
|
||||
}
|
||||
|
||||
func (receiver *UpdateFreeTimesCond) Update() bson.M {
|
||||
var update = bson.M{}
|
||||
if receiver.FreeTimes != nil {
|
||||
update["aiUndressFreeTimes"] = receiver.FreeTimes
|
||||
}
|
||||
return bson.M{"$inc": update}
|
||||
}
|
||||
|
||||
type UpdateDownloadCond struct {
|
||||
UID uint64 `json:"uid" bson:"uid" binding:"required"` // 用户ID
|
||||
Download *int64 `json:"download" bson:"download"` // 下载次数
|
||||
Mark *string `json:"mark" bson:"mark"` // 备注
|
||||
}
|
||||
|
||||
func (receiver *UpdateDownloadCond) Filter() bson.M {
|
||||
return bson.M{"uid": receiver.UID}
|
||||
}
|
||||
|
||||
func (receiver *UpdateDownloadCond) Update() bson.M {
|
||||
var update = bson.M{}
|
||||
if receiver.Download != nil {
|
||||
update["downloadCount"] = receiver.Download
|
||||
}
|
||||
return bson.M{"$inc": update}
|
||||
}
|
||||
|
||||
type SetAdvertiseCond struct {
|
||||
UId []uint64 `form:"uid" json:"uid" binding:"required"` // 用户uid
|
||||
Enable *bool `form:"enable" json:"enable" binding:"required"` // 是否开启
|
||||
}
|
||||
|
||||
type UpdateLotteryTimesCond struct {
|
||||
UID uint64 `json:"uid" bson:"uid" binding:"required"` // 用户ID
|
||||
LotteryTimes *int64 `json:"lotteryTimes" bson:"lotteryTimes"` // 抽空次数
|
||||
Mark *string `json:"mark" bson:"mark"` // 备注
|
||||
}
|
||||
|
||||
func (receiver *UpdateLotteryTimesCond) Filter() bson.M {
|
||||
return bson.M{"uid": receiver.UID}
|
||||
}
|
||||
|
||||
func (receiver *UpdateLotteryTimesCond) Update() bson.M {
|
||||
var update = bson.M{}
|
||||
if receiver.LotteryTimes != nil {
|
||||
update["lotteryTimes"] = receiver.LotteryTimes
|
||||
}
|
||||
return bson.M{"$inc": update}
|
||||
}
|
||||
|
||||
type DeleteCommentCond struct {
|
||||
UID uint64 `json:"uid" bson:"uid" binding:"required"` // 用户ID
|
||||
}
|
||||
|
||||
type QueryGameCodeCond struct {
|
||||
UID uint64 `form:"uid" json:"uid" bson:"uid,omitempty"` //用户ID
|
||||
}
|
||||
|
||||
func (receiver *DeleteCommentCond) Filter() bson.M {
|
||||
return bson.M{"uid": receiver.UID}
|
||||
}
|
||||
Reference in New Issue
Block a user