Initial commit

Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
This commit is contained in:
2026-09-15 13:57:10 +08:00
co-authored by Claude Opus 5
commit 8679200f41
1897 changed files with 257900 additions and 0 deletions
+74
View File
@@ -0,0 +1,74 @@
package adsclicklogmod
import (
"fmt"
"time"
"91porn-server/common/db"
"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"
)
var mdb *db.MongoDB
const table = models.AdsClickLog
func Init() {
mdb = db.Init(table)
initIndex()
}
// InitIndex 初始化索引
func initIndex() {
many := []mongo.IndexModel{
{
Keys: bson.D{{Key: "uid", Value: 1}, {Key: "adsType", Value: 1}, {Key: "createdAt", Value: 1}},
Options: options.Index().SetUnique(true),
},
}
if _, err := coll(nil).CreateIndex(many); err != nil {
panic(fmt.Sprintf("%s model set index err ==>[%+v]", table, err))
}
}
func coll(t *db.MongoTool) *db.MongoTool {
if t == nil {
return mdb.Coll(table)
}
return t.Coll(table)
}
type AdsClick struct {
ID primitive.ObjectID `json:"-" bson:"_id,omitempty"`
UID uint64 `json:"uid" bson:"uid"`
ClickId primitive.ObjectID `json:"clickId" bson:"clickId"`
ObjType string `json:"objType" bson:"objType"`
AdsType int64 `json:"adsType" bson:"adsType"` // 0 默认; 1 金主楼凤广告
CreatedAt time.Time `json:"createdAt" bson:"createdAt"`
UpdatedAt time.Time `json:"updatedAt" bson:"updatedAt"`
}
func AddClick(uid uint64, clickId primitive.ObjectID, objType string, adsType int64) error {
now := time.Now()
_, err := coll(nil).InsertOne(AdsClick{
UID: uid,
ClickId: clickId,
ObjType: objType,
AdsType: adsType,
CreatedAt: now,
UpdatedAt: now,
})
return err
}
func GetDailyClickCount(uid uint64) (uint64, error) {
year, month, day := time.Now().Date()
start := time.Date(year, month, day, 0, 0, 0, 0, time.Local)
end := time.Date(year, month, day+1, 0, 0, 0, 0, time.Local)
res, err := coll(nil).Distinct("clickId", bson.M{"uid": uid, "adsType": 1, "createdAt": bson.M{"$gte": start, "$lt": end}})
return uint64(len(res)), err
}
+121
View File
@@ -0,0 +1,121 @@
package exchlogmod
import (
"fmt"
"91porn-server/common"
"91porn-server/common/db"
"91porn-server/common/log"
"91porn-server/models"
"91porn-server/models/commod"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
var mdb *db.MongoDB
const table = models.ExchLog
func coll(t *db.MongoTool) *db.MongoTool {
if t == nil {
return mdb.Coll(table)
}
return t.Coll(table)
}
func initIndex() {
many := []mongo.IndexModel{ //batch set indexes //value is the type 1 or -1
{
Keys: bson.D{{Key: "code", Value: 1}, {Key: "createdAt", Value: 1}},
},
{
Keys: bson.D{{Key: "userID", Value: 1}, {Key: "createdAt", Value: 1}},
},
{
Keys: bson.D{{Key: "userID", Value: 1}, {Key: "batchNum", Value: 1}},
},
{
Keys: bson.D{{Key: "channel", Value: 1}, {Key: "createdAt", Value: 1}},
},
{
Keys: bson.D{{Key: "authority", Value: 1}, {Key: "createdAt", Value: 1}},
},
{
Keys: bson.D{{Key: "createdAt", Value: 1}},
},
}
if _, err := coll(nil).CreateIndex(many); err != nil {
panic(fmt.Sprintf("%s model set index err ==>[%+v]", table, err))
}
}
func Insert(doc ExchangeLog) error {
if _, err := coll(nil).InsertOne(doc); err != nil {
log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "Insert", table, "InsertOne", err),
log.Any("doc", doc),
)
return err
}
return nil
}
func GetExchangeLogList(filterParams FilterDoc, page commod.Page) (total int64, data []ExchangeLog, err error) {
filter, _ := common.ToBsonM(filterParams)
var skip = int64((page.PageNumber - 1) * page.PageSize)
var limit = int64(page.PageSize)
var opts = options.Find()
opts.SetSort(bson.D{{Key: "createdAt", Value: -1}}).SetSkip(skip).SetLimit(limit)
if err = coll(nil).Find(&data, filter, opts); err != nil {
log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "GetExchangeLogList", table, "Find", err),
log.Any("filterParams", filterParams),
log.Any("page", page),
)
return
}
if total, err = coll(nil).Count(filter); err != nil {
log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "GetExchangeLogList", table, "Count", err),
log.Any("filterParams", filterParams),
log.Any("page", page),
)
return
}
return
}
// 获取用户兑换日志
func GetLogByUIDAndBatchNum(uid uint64, batchNum string) (data ExchangeLog, err error) {
if err = coll(nil).FindOne(&data, bson.M{"userID": uid, "batchNum": batchNum}); err != nil {
log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "GetExchangeLogList", table, "Find", err),
log.Any("uid", uid),
log.Any("batchNum", batchNum),
)
return
}
return
}
// 获取用户兑换日志
func GetLogByUIDAndAuthority(uid uint64, authority string) (data ExchangeLog, err error) {
if err = coll(nil).FindOne(&data, bson.M{"userID": uid, "authority": authority}); err != nil {
log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "GetExchangeLogList", table, "Find", err),
log.Any("uid", uid),
log.Any("authority", authority),
)
return
}
return
}
// 获取用户兑换
func GetLogByUIDAndCode(uid uint64, code string) (data ExchangeLog, err error) {
if err = coll(nil).FindOne(&data, bson.M{"userID": uid, "code": code}); err != nil {
log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "GetLogByUIDAndCode", table, "Find", err),
log.Any("uid", uid),
log.Any("code", code),
)
return
}
return
}
+37
View File
@@ -0,0 +1,37 @@
package exchlogmod
import (
"time"
"91porn-server/common/db"
"go.mongodb.org/mongo-driver/bson/primitive"
)
type ObjectID = primitive.ObjectID
// Init 初始化索引
func Init() {
mdb = db.Init(table)
initIndex()
}
type ExchangeLog struct {
ID ObjectID `json:"id" bson:"_id,omitempty"`
Code string `json:"code" bson:"code"` // 兑换码
UserID uint64 `json:"userID" bson:"userID"` // 兑换者
BatchNum string `json:"batchNum" bson:"batchNum"` // 批次号
Channel string `json:"channel" bson:"channel"` // 所属渠道
Authority string `json:"authority" bson:"authority"` // 兑换权限
Desc string `json:"desc" bson:"-"` // 说明
Reward int `json:"reward" bson:"reward"` // 奖励值
RewardCount int `json:"rewardCount" bson:"rewardCount"` // 奖励量
CreatedAt time.Time `json:"createdAt" bson:"createdAt"` // 创建时间/兑换时间
}
type FilterDoc struct {
Code *string `bson:"code,omitempty"` // 兑换码
UserID *uint64 `bson:"userID,omitempty"` // 兑换者
Channel *string `bson:"channel,omitempty"` // 所属渠道
Authority *string `bson:"authority,omitempty"` // 兑换权限
}
+25
View File
@@ -0,0 +1,25 @@
package exchlogmod
import (
"time"
"91porn-server/models/commod"
)
type ListReqParam struct {
Code *string `form:"code" json:"code"` // 兑换码
UserID *uint64 `form:"userID" json:"userID"` // 兑换者
Channel *string `form:"channel" json:"channel"` // 所属渠道
Authority *string `form:"authority" json:"authority"` // 兑换权限
Page commod.Page
}
type ListResp struct {
Code string `json:"code"` // 兑换码
UserID uint64 `json:"userID"` // 兑换者
Channel string `json:"channel"` // 所属渠道
Authority string `json:"authority"` // 兑换权限
Reward int `json:"reward"` // 奖励值
RewardCount int `json:"rewardCount"` // 奖励量
CreatedAt time.Time `json:"createdAt"` // 创建时间/兑换时间
}
+127
View File
@@ -0,0 +1,127 @@
package loginlgmod
import (
"fmt"
"math"
"time"
"91porn-server/common/db"
"91porn-server/common/log"
"91porn-server/models"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
)
var mdb *db.MongoDB
const table = models.LoginLog
func coll(t *db.MongoTool) *db.MongoTool {
if t == nil {
return mdb.Coll(table)
}
return t.Coll(table)
}
// initIndex 设置index
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: "devID", Value: 1}},
},
{
Keys: bson.D{{Key: "loginTime", Value: 1}},
},
}
if _, err := coll(nil).CreateIndex(many); err != nil {
panic(fmt.Sprintf("%s model set index err ==>[%+v]", table, err))
}
}
func InsertLoginLog(l *LoginLog) error {
if _, err := coll(nil).InsertOne(l); err != nil {
log.Error("loginlog insert err", log.E(err))
return err
}
return nil
}
func WebGetDayActivity(uids []uint64, start time.Time, end time.Time) (data []LoginLog, err error) {
if err = coll(nil).Find(
&data,
bson.M{
"loginTime": bson.M{
"$and": []bson.M{
bson.M{"$gte": start},
bson.M{"$lte": end},
},
},
"uid": bson.M{
"$in": uids,
},
},
); err != nil {
log.ZapLog.Error(fmt.Sprintf("model record login WebGetDayActivity fail error:%+v:", err))
return
}
return
}
// GetTotalCnt 获取查询总数总数
func getLoginLogTotalCnt(cond bson.M) (int64, error) {
total, err := coll(nil).Count(cond)
if err != nil {
e := fmt.Sprintf("get total Cnt error: %+v\n", err)
log.ZapLog.Error(e)
return 0, err
}
return total, nil
}
// GetSkipSize 计算跳转
func getLoginLogSkipSize(page int, size int, cond bson.M) (int, int, int64, error) {
total, err := getLoginLogTotalCnt(cond)
if err != nil {
return 0, 0, 0, err
}
totalpages := int(math.Ceil(float64(total) / float64(size)))
if page > totalpages {
page = totalpages
}
if page < 1 {
page = 1
}
return (page - 1) * size, totalpages, total, nil
}
// FindLoginLog 查找登陆日志
func FindLoginLogList(page int, size int, cond bson.M, sort bson.D) ([]*LoginLog, int, int64, error) {
skip, totalPages, total, err := getLoginLogSkipSize(page, size, cond)
if err != nil {
return nil, 0, 0, err
}
var back []*LoginLog
if err = coll(nil).Aggregate(
&back,
[]bson.M{
bson.M{"$match": cond},
bson.M{"$sort": sort},
bson.M{"$skip": skip},
bson.M{"$limit": size},
},
); err != nil {
e := fmt.Sprintf("get login logs error: %+v\n", err)
log.ZapLog.Error(e)
return nil, totalPages, total, err
}
return back, totalPages, total, nil
}
func DeleteBeforeLoginTime(t *db.MongoTool, tm time.Time) error {
_, err := coll(t).DeleteMany(bson.M{"loginTime": bson.M{"$lt": tm}})
return err
}
+43
View File
@@ -0,0 +1,43 @@
package loginlgmod
import (
"time"
"91porn-server/common/db"
"91porn-server/models/commod"
)
// LoginLog 登陆记录
type LoginLog struct {
UID uint64 `json:"uid" bson:"uid"`
IP string `json:"ip" bson:"ip"`
SysType string `json:"sysType" bson:"sysType"` //操作系统类型 安卓 IOS
Ver string `json:"ver" bson:"ver"` //APP版本号
DevType string `json:"devType" bson:"devType"` //设备型号
DevID string `json:"devID" bson:"devID"`
BuildID string `json:"buildID" bson:"buildID"` //app构建ID(包ID)
LoginTime time.Time `json:"loginTime" bson:"loginTime,omitempty"`
LogoutTime time.Time `json:"logoutTime" bson:"logoutTime,omitempty"`
Logout bool `json:"logout" bson:"logout"` //是否退出登陆
}
// LogListResp 登陆日志查询列表
type LogListResp struct {
Logs []*LoginLog `json:"logs"`
Total int64 `json:"total"`
}
// QueryReq 登陆日志查询请求参数
type QueryReq struct {
commod.Page
UID uint64 `form:"uid" json:"uid"`
Start time.Time `form:"start" json:"start"`
End time.Time `form:"end" json:"end"`
Sort string `form:"sort" json:"sort"`
Desc int `form:"desc" json:"desc"`
}
func Init() {
mdb = db.Init(table)
initIndex()
}
+108
View File
@@ -0,0 +1,108 @@
package lotterylgmod
import (
"fmt"
"time"
"91porn-server/common/db"
"91porn-server/common/log"
"91porn-server/common/timeutil/timerange"
"91porn-server/models"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
const table = models.LotteryLog
var mdb *db.MongoDB
func coll(t *db.MongoTool) *db.MongoTool {
if t == nil {
return mdb.Coll(table)
}
return t.Coll(table)
}
// initIndexAds 初始化索引
func initIndex() {
many := []mongo.IndexModel{
{
Keys: bson.D{{Key: "uid", Value: 1}, {Key: "createdAt", Value: 1}},
},
{
Keys: bson.D{{Key: "code", Value: 1}},
},
{
Keys: bson.D{{Key: "createdAt", Value: 1}},
},
}
if _, err := coll(nil).CreateIndex(many); err != nil {
panic(fmt.Sprintf("%s model set index err ==>[%+v]", table, err))
}
}
// InsertLog 记录一个抽奖号行为
func InsertLog(uid uint64, code int, gateName string) error {
ll := LotteryLog{
UID: uid,
Code: code,
GateName: gateName,
CreatedAt: time.Now(),
}
if _, err := coll(nil).InsertOne(ll); err != nil {
log.Error("InsertClickLog error", log.Any("ll", ll), log.E(err))
return err
}
return nil
}
// UserTodayChances 获取用户当日抽奖号数量
func UserTodayChances(uid uint64) (int, error) {
sumDate := timerange.LocDayRange(time.Now()).Head
ll := []LotteryLog{}
cond := bson.M{"uid": uid, "createdAt": bson.M{"$gte": sumDate}}
if err := coll(nil).Find(&ll, cond); err != nil {
log.Error("UserTodayChances error", log.Any("uid", uid), log.E(err))
return 0, err
}
return len(ll), nil
}
// LottnumList 获取摇号列表
func LottnumList(page, size uint64, start *time.Time, end *time.Time, uid *uint64, code *int) ([]LotteryLog, int64, error) {
back := []LotteryLog{}
cond := bson.M{}
if uid != nil {
cond["uid"] = *uid
}
if code != nil {
cond["code"] = *code
}
if start != nil && end != nil {
cond["createdAt"] = bson.M{"$gte": *start, "$lt": *end}
}
sort := bson.D{{Key: "createdAt", Value: -1}}
skip := (page - 1) * size
opts := options.FindOptions{}
opts.SetSort(sort).SetSkip(int64(skip)).SetLimit(int64(size))
if err := coll(nil).Find(&back, bson.M(cond), &opts); err != nil {
log.Error("LottnumList error", log.Any("page", page), log.Any("size", size), log.Any("cond", cond), log.E(err))
return back, 0, err
}
total, _ := coll(nil).Count(cond)
return back, total, nil
}
// UserTodayNum 获取用户当日抽奖号
func UserTodayNum(uid uint64) ([]LotteryLog, error) {
sumDate := timerange.LocDayRange(time.Now()).Head
ll := []LotteryLog{}
cond := bson.M{"uid": uid, "createdAt": bson.M{"$gte": sumDate}}
if err := coll(nil).Find(&ll, cond); err != nil {
log.Error("UserTodayChances error", log.Any("uid", uid), log.E(err))
return ll, err
}
return ll, nil
}
+20
View File
@@ -0,0 +1,20 @@
package lotterylgmod
import (
"time"
"91porn-server/common/db"
)
// LotteryLog 活动摇号日志
type LotteryLog struct {
UID uint64 `json:"uid" bson:"uid"`
Code int `json:"code" bson:"code"`
GateName string `json:"gateName" bson:"gateName"`
CreatedAt time.Time `json:"createdAt" bson:"createdAt"`
}
func Init() {
mdb = db.Init(table)
initIndex()
}
+50
View File
@@ -0,0 +1,50 @@
package lotterylgmod
import (
"time"
"91porn-server/models/commod"
"go.mongodb.org/mongo-driver/bson/primitive"
)
// AdsClickResp 广告点击日志应答
type AdsClickResp struct {
Logs int `json:"logs"`
Total int64 `json:"total"`
}
// AdsCountResp 广告点击统计应答
type AdsCountResp struct {
ID string `json:"id"`
TodayCnt int64 `json:"todayCnt"`
YesterdayCnt int64 `json:"yesterdayCnt"`
WeekCnt int64 `json:"weekCnt"`
MonthCnt int64 `json:"monthCnt"`
TotalCnt int64 `json:"totalCnt"`
}
type AdsClickReq struct {
UID uint64 `form:"uid" json:"uid"`
Start time.Time `form:"start" json:"start"`
End time.Time `form:"end" json:"end"`
Sort string `form:"sort" json:"sort"`
Desc int `form:"desc" json:"desc"`
commod.Page
}
// AdsClickInfo
type AdsClickInfo struct {
AID primitive.ObjectID `json:"aid"` //广告id
TodayCount int64 `json:"todayCount"` //今日点击数
YesterdayCount int64 `json:"yesterdayCount"` //昨日点击数
WeekCount int64 `json:"weekCount"` //本周点击数
MonthCount int64 `json:"monthCount"` //本月点击数
TotalCount int64 `json:"totalCount"` //总点击数
}
// AdsStatisticResp 广告点击统计应答
type AdsStatisticResp struct {
Logs []AdsClickInfo `json:"logs"`
Total int64 `json:"total"`
}
+148
View File
@@ -0,0 +1,148 @@
package operatorlgmod
import (
"fmt"
"math"
"strings"
"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.WebOperatorLog
var mdb *db.MongoDB
func coll(t *db.MongoTool) *db.MongoTool {
if t == nil {
return mdb.Coll(table)
}
return t.Coll(table)
}
// initIndexAds 初始化索引
func initIndex() {
many := []mongo.IndexModel{
{
Keys: bson.D{{Key: "createdAt", Value: 1}},
},
{
Keys: bson.D{{Key: "manager", Value: 1}},
},
{
Keys: bson.D{{Key: "uri", Value: 1}},
},
{
Keys: bson.D{{Key: "position", Value: 1}},
},
}
if _, err := coll(nil).CreateIndex(many); err != nil {
panic(fmt.Sprintf("%s model set index err ==>[%+v]", table, err))
}
}
// RecordOperation 记录操作日志
func RecordOperation(manager string, position string, operator string, content string, uri string) error {
record := WebOperatorLog{
Manager: manager,
Position: position,
Operator: operator,
Content: content,
URI: uri,
CreatedAt: time.Now(),
}
if _, err := coll(nil).InsertOne(&record); err != nil {
log.Error("RecordOperation error", log.Any("manager", manager), log.Any("position", position),
log.Any("operator", operator), log.Any("content", content), log.Any("url", uri), log.E(err))
return err
}
return nil
}
func backOperatorParam(param OperatorListReq) map[string]interface{} {
m := make(map[string]interface{})
if len(param.Manager) != 0 {
m["manager"] = param.Manager
}
if len(param.Position) != 0 {
m["position"] = param.Position
}
if len(param.URI) != 0 {
m["uri"] = param.URI
}
if param.Content != "" {
param.Content = strings.Trim(param.Content, " ")
m["content"] = bson.M{"$regex": primitive.Regex{
Pattern: param.Content,
Options: "i",
}}
}
if !param.End.IsZero() {
i := make(map[string]time.Time)
i["$gte"] = param.Start
i["$lt"] = param.End
m["createdAt"] = i
}
return m
}
// getTotalCnt 获取后台操作日志总数
func getTotalCnt(cond bson.M) (int64, error) {
total, err := coll(nil).Count(cond)
if err != nil {
log.Error("getTotalCnt", log.Any("cond", cond), log.E(err))
return 0, err
}
return total, nil
}
// getSkipSize 计算跳转
func getSkipSize(page, size uint64, cond bson.M) (uint64, uint64, int64, error) {
total, err := getTotalCnt(cond)
if err != nil {
return 0, 0, 0, err
}
totalpages := uint64(math.Ceil(float64(total) / float64(size)))
if page > totalpages {
page = totalpages
}
if page < 1 {
page = 1
}
return (page - 1) * size, totalpages, total, nil
}
// GetOperatorLog 获取操作日志
func GetOperatorLog(req OperatorListReq) ([]*WebOperatorLog, int64, error) {
cond := backOperatorParam(req)
sort := bson.D{{Key: "createdAt", Value: -1}}
skip, _, total, err := getSkipSize(req.PageNumber, req.PageSize, bson.M(cond))
if err != nil {
return nil, 0, err
}
opts := options.FindOptions{}
opts.SetSort(sort).SetSkip(int64(skip)).SetLimit(int64(req.PageSize))
var back []*WebOperatorLog
if err = coll(nil).Find(&back, bson.M(cond), &opts); err != nil {
log.Error("GetOperatorLog error", log.Any("req", req), log.E(err))
}
return back, total, err
}
// EditRemarks 更新备注
func EditRemarks(id primitive.ObjectID, remarks string) error {
cond := bson.M{"_id": id}
update := bson.M{"$set": bson.M{"remarks": remarks}}
if _, err := coll(nil).UpdateOne(cond, update); err != nil {
log.Error("EditRemarks error", log.Any("id", id), log.Any("remarks", remarks), log.E(err))
return err
}
return nil
}
+27
View File
@@ -0,0 +1,27 @@
package operatorlgmod
import (
"time"
"91porn-server/common/db"
"go.mongodb.org/mongo-driver/bson/primitive"
)
// WebOperatorLog 后台操作日志
type WebOperatorLog struct {
ID primitive.ObjectID `json:"id" bson:"_id,omitempty"`
Manager string `json:"manager" bson:"manager"` //管理员账号
Position string `json:"position" bson:"position"` //操作位置
Operator string `json:"operator" bson:"operator"` //操作动作
Content string `json:"content" bson:"content"` //操作内容
URI string `json:"uri" bson:"uri"` //操作uri
Remarks string `json:"remarks" bson:"remarks"` //备注
CreatedAt time.Time `json:"createdAt" bson:"createdAt"`
}
// Init 初始化索引
func Init() {
mdb = db.Init(table)
initIndex()
}
+32
View File
@@ -0,0 +1,32 @@
package operatorlgmod
import (
"time"
"91porn-server/models/commod"
"go.mongodb.org/mongo-driver/bson/primitive"
)
// OperatorListReq 操作日志查询
type OperatorListReq struct {
Manager string `form:"manager" json:"manager"`
Position string `form:"position" json:"position"`
Content string `form:"content" json:"content" binding:"omitempty,min=2,max=100"`
URI string `form:"uri" json:"uri"`
Start time.Time `form:"start" json:"start"`
End time.Time `form:"end" json:"end"`
commod.Page
}
// OperatorListResp 操作日志查询应答
type OperatorListResp struct {
Infos []*WebOperatorLog `json:"infos"`
Total int64 `json:"total"`
}
// OperatorModifyReq 操作日志修改
type OperatorModifyReq struct {
ID primitive.ObjectID `json:"id"`
Remarks string `json:"remarks"`
}
+6
View File
@@ -0,0 +1,6 @@
package payvidlgmod
// Pay4VidLogQueryReq Pay4VidLogQueryReq
type Pay4VidLogQueryReq struct {
PublisherID *uint64 `json:"publisherID,omitempty" bson:"publisherID"` //上传者ID
}
+114
View File
@@ -0,0 +1,114 @@
package payvidlgmod
import (
"fmt"
"strings"
"time"
"91porn-server/common/log"
"91porn-server/common/pageopt"
"91porn-server/common/ysinterface/disc"
"go.mongodb.org/mongo-driver/mongo/options"
)
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}, "-"))
}
type DistrictStater = disc.DistrictStater
// DiscSeqeTransCount
func DiscSeqeBuyVidCount(start, end time.Time, mats ...Matcher) (map[DistrictStater]int64, error) {
mats = append(mats, (&CreatedAtGTEAndLTMatch{GTE: &start, LT: &end}).New())
filter := pageopt.MergeM(mats)
list := []DistrictStatKey{}
opt := (&options.FindOptions{}).SetProjection(M{
"districtCode": 1,
"promSeqe": 1,
"sysType": 1,
})
if err := coll(nil).Find(&list, filter, opt); err != nil {
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "DiscSeqeTransCount", table, "Find", err))
return nil, err
}
m := make(map[DistrictStater]int64)
for _, v := range list {
if v.String() != "" {
m[v] += 1
}
}
return m, nil
}
// DiscSeqeBuyVidCoins
func DiscSeqeBuyVidCoins(start, end time.Time, mats ...Matcher) (map[DistrictStater]int64, error) {
mats = append(mats, (&CreatedAtGTEAndLTMatch{GTE: &start, LT: &end}).New())
filter := pageopt.MergeM(mats)
list := []struct {
DistrictStatKey `bson:",inline"` //商区码
Coins int64 `bson:"coins"`
}{}
opt := (&options.FindOptions{}).SetProjection(M{
"districtCode": 1,
"promSeqe": 1,
"sysType": 1,
"coins": 1,
})
if err := coll(nil).Find(&list, filter, opt); err != nil {
return nil, err
}
m := make(map[DistrictStater]int64, len(list))
for _, v := range list {
if v.String() != "" {
m[v.DistrictStatKey] += v.Coins
}
}
return m, nil
}
// DiscSeqeTaxAmount
func DiscSeqeTaxAmount(start, end time.Time, mats ...Matcher) (map[DistrictStater]float64, error) {
mats = append(mats, (&CreatedAtGTEAndLTMatch{GTE: &start, LT: &end}).New())
filter := pageopt.MergeM(mats)
list := []struct {
DistrictStatKey `bson:",inline"` //商区码
TaxAmount float64 `bson:"taxAmount"` //税额
}{}
opt := (&options.FindOptions{}).SetProjection(M{
"districtCode": 1,
"promSeqe": 1,
"sysType": 1,
"taxAmount": 1,
})
if err := coll(nil).Find(&list, filter, opt); err != nil {
return nil, err
}
m := make(map[DistrictStater]float64, len(list))
for _, v := range list {
if v.String() != "" {
m[v.DistrictStatKey] += v.TaxAmount
}
}
return m, nil
}
+84
View File
@@ -0,0 +1,84 @@
package payvidlgmod
import (
"91porn-server/common/log"
"91porn-server/common/pageopt"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo/options"
)
type Matcher = pageopt.Matcher
// DistrictCodeMatch
type DistrictCodeMatch struct {
DistrictCode *string
}
func (s *DistrictCodeMatch) New() Matcher {
return pageopt.NewAssignMatch("districtCode", s.DistrictCode)
}
// IsDirectMatch
type IsDirectMatch struct {
IsDirect *bool
}
func (b *IsDirectMatch) New() Matcher {
return pageopt.NewAssignMatch("isDirect", b.IsDirect)
}
// PromSeqeMatch
type PromSeqeMatch struct {
Seqe *string
}
func (d *PromSeqeMatch) New() Matcher {
return pageopt.NewAssignMatch("promSeqe", d.Seqe)
}
// SysTypeMatch
type SysTypeMatch struct {
SysType *string
}
func (d *SysTypeMatch) New() Matcher {
return pageopt.NewAssignMatch("sysType", d.SysType)
}
// CreatedAtGTEAndLTMatch
type CreatedAtGTEAndLTMatch = pageopt.CreatedAtGTEAndLTMatch
type Sort = bson.D
var Sort_CreatedAt_n1 = Sort{{Key: "createdAt", Value: -1}}
func List(sort Sort, skip, limit *int64, matchers ...Matcher) ([]Pay4VidLog, error) {
filter := pageopt.MergeM(matchers)
opt := (&options.FindOptions{})
if len(sort) != 0 {
opt.SetSort(sort)
}
if skip != nil {
opt.SetSkip(*skip)
}
if limit != nil {
opt.SetLimit(*limit)
}
list := []Pay4VidLog{}
if err := coll(nil).Find(&list, filter, opt); err != nil {
log.Error("payvidlgmod List error", log.E(err))
return nil, err
}
return list, nil
}
func Count(matchers ...Matcher) (int64, error) {
filter := pageopt.MergeM(matchers)
count, err := coll(nil).Count(filter)
if err != nil {
log.Error("payvidlgmod Count error", log.E(err))
return 0, err
}
return count, nil
}
+602
View File
@@ -0,0 +1,602 @@
package payvidlgmod
import (
"91porn-server/models/commod"
"fmt"
"math"
"time"
"91porn-server/common/db"
"91porn-server/common/log"
"91porn-server/common/pageopt"
"91porn-server/common/timeutil"
"91porn-server/models"
"github.com/pkg/errors"
"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"
)
var mdb *db.MongoDB
const table = models.PayVideoLog
// initIndex 初始化索引
func initIndex() {
many := []mongo.IndexModel{
{
Keys: bson.D{{Key: "uid", Value: 1}, {Key: "videoID", Value: 1}},
Options: options.Index().SetUnique(true),
},
{
Keys: bson.D{{Key: "createdAt", Value: -1}},
},
{
Keys: bson.D{{Key: "uniq", Value: 1}},
Options: options.Index().SetUnique(true),
},
{
Keys: bson.D{{Key: "deductType", Value: 1}, {Key: "createdAt", Value: -1}},
Options: options.Index().SetSparse(true),
},
{
Keys: bson.D{{Key: "videoID", Value: 1}},
},
{
Keys: bson.D{{Key: "publisherID", Value: 1}},
},
}
if _, err := coll(nil).CreateIndex(many); err != nil {
panic(fmt.Sprintf("%s model set index err ==>[%+v]", table, err))
}
}
func coll(t *db.MongoTool) *db.MongoTool {
if t == nil {
return mdb.Coll(table)
}
return t.Coll(table)
}
// InsertVideoPayRecord 插入一条购买记录
func InsertVideoPayRecord(t *db.MongoTool, p Pay4VidLog) error {
p.Uniq = Unique(p.UID, p.VideoID)
p.CreatedAt = time.Now()
res, err := coll(t).InsertOne(&p)
if err != nil {
log.Error("InsertVideoPayRecord error", log.Any("p", p), log.E(err))
return err
}
p.ID = res.InsertedID.(ObjectID)
return nil
}
// IsPay4Video 用户是否购买了视频
func IsPay4Video(uid uint64, videoID ObjectID) (bool, error) {
cnt, err := coll(nil).Count(bson.M{"uid": uid, "videoID": videoID})
if err != nil {
log.Error("IsPay4Video error", log.Any("uid", uid), log.Any("videoID", videoID), log.E(err))
return false, err
}
return cnt != 0, nil
}
func FindManyPay4VidLogByUID(uid uint64, newsType string) ([]*Pay4VidLog, error) {
vl := make([]*Pay4VidLog, 0)
err := coll(nil).Find(&vl, bson.M{"uid": uid, "newsType": newsType})
if err != nil {
log.Error("FindManyPay4VidLogByUID error", log.Any("uid", uid), log.Any("err", err.Error()))
return nil, err
}
return vl, nil
}
// IsPay4Videos 用户是否购买了视频
func IsPay4Videos(uid uint64, videoIDs []ObjectID) (map[ObjectID]bool, error) {
if videoIDs == nil {
videoIDs = []ObjectID{}
}
m := make(map[ObjectID]bool)
var infos []Pay4VidLog
query := bson.M{"uid": uid, "videoID": bson.M{"$in": videoIDs}}
if err := coll(nil).Find(&infos, query); err != nil {
log.Error("IsPay4Videos error", log.Any("uid", uid), log.Any("videoIDs", videoIDs), log.E(err))
return m, err
}
for _, i := range infos {
m[i.VideoID] = true
}
return m, nil
}
// 判断当前视频是否有人购买过
func IsVidIfBePay(id primitive.ObjectID) bool {
var pay *Pay4VidLog
if err := coll(nil).FindOne(&pay, bson.M{"videoID": id}); err != nil {
log.Error("IsVidIfBePay error", log.Any("videoID", id), log.E(err))
return false
}
return pay != nil
}
// DelVideoPayRecord 删除一条购买记录
func DelVideoPayRecord(videoID primitive.ObjectID, uid uint64) error {
if _, err := coll(nil).DeleteOne(bson.M{"videoID": videoID, "uid": uid}); err != nil {
log.Error("DelVideoPayRecord DeleteOne error", log.Any("videoID", videoID), log.Any("uid", uid))
return err
}
return nil
}
// 从给定的hash列表中获取购买状态映射:uniq->Statue
// uniq通过Unique()获取
func PayStatueMap(uniqList []string) (map[string]bool, error) {
filter := bson.M{
"uniq": bson.M{"$in": uniqList},
}
payLogList := make([]Pay4VidLog, 0, len(uniqList))
if err := coll(nil).Find(&payLogList, filter); err != nil {
return nil, err
}
m := make(map[string]bool, len(payLogList))
//初始化
for _, uniq := range uniqList {
m[uniq] = false
}
//已经收藏的
for _, v := range payLogList {
uniq := v.Uniq
m[uniq] = true
}
return m, nil
}
func GetUIDListByPayTime(start time.Time, end time.Time) ([]uint64, error) {
filter := bson.M{
"createdAt": bson.M{
"$gte": start,
"$lt": end,
},
}
list := make([]struct {
UID uint64 `bson:"uid"`
}, 0)
if err := coll(nil).Find(&list, filter); err != nil {
return nil, err
}
uidList := make([]uint64, len(list))
for i, v := range list {
uidList[i] = v.UID
}
return uidList, nil
}
func GetPayMoneyByTime(start time.Time, end time.Time) (int64, error) {
filter := bson.M{
"createdAt": bson.M{
"$gte": start,
"$lt": end,
},
}
logs := make([]Pay4VidLog, 0)
if err := coll(nil).Find(&logs, filter); err != nil {
return 0, fmt.Errorf("table:%s GetPayMoneyByTime err: %s", table, err.Error())
}
total := int64(0)
for _, v := range logs {
total += v.PayMoney
}
return total, nil
}
// FindManyVideoPayRecord 查询所有
func FindThreeMonthVideoPayRecord(publisherID uint64, pageNumber, pageSize uint64) (total int64, totalAmount int64, data []*Pay4VidLog, hasNext bool, err error) {
data = make([]*Pay4VidLog, 0)
startTime := timeutil.NearMonth(time.Now(), 2)
f := bson.M{"publisherID": publisherID, "createdAt": bson.M{"$gte": startTime}}
skip := int64(pageSize * (pageNumber - 1))
limit := int64(pageSize + 1)
opts := options.FindOptions{
Skip: &skip,
Limit: &limit,
Sort: bson.D{{Key: "createdAt", Value: -1}},
}
if err = coll(nil).Find(&data, f, &opts); err != nil {
log.Error("FindManyVideoPayRecord error", log.Any("filter", f), log.E(err))
}
type Res struct {
TotalAmount float64 `json:"totalAmount" bson:"totalAmount"`
}
totalIncome := []bson.M{
{"$match": f},
{
"$group": bson.M{
"_id": nil,
"totalAmount": bson.M{
"$sum": "$publisherIncome",
},
},
},
}
ress := make([]Res, 0)
if err = coll(nil).Aggregate(&ress, totalIncome); err != nil {
log.Error("FindManyVideoPayRecord error", log.Any("filter", f), log.E(err))
}
if len(ress) > 0 {
totalAmount = int64(math.Floor(ress[0].TotalAmount))
}
total, err = coll(nil).Count(f)
if err != nil {
log.Error("FindManyVideoPayRecord Count error", log.Any("filter", f), log.E(err))
}
if len(data) > int(pageSize) {
hasNext = true
data = data[:pageSize]
}
return
}
// GetWorksIncomeList 查询收益列表
func GetWorksIncomeList(publisherID uint64, page commod.Page) (data []*Pay4VidLog, hasNext bool, err error) {
data = make([]*Pay4VidLog, 0)
opt := options.Find().
SetLimit(page.Limit64() + 1).
SetSkip(page.Skip64()).
SetSort(bson.D{{"createdAt", -1}})
filter := bson.M{
"publisherID": publisherID,
}
if err = coll(nil).Find(&data, filter, opt); err != nil {
log.Error("FindManyVideoPayRecord error", log.Any("filter", filter), log.E(err))
return nil, false, err
}
hasNext = len(data) > int(page.Limit64())
if hasNext {
data = data[:page.Limit64()]
}
return
}
// PayCoinByCreatedTime 金币
func PayCoinByCreatedTime(start time.Time, end time.Time) (int64, error) {
pipeline := []bson.M{
{
"$match": bson.M{
// createdAt ∈ [startTime, endTime)
"createdAt": bson.M{
"$gte": start,
"$lt": end,
},
},
},
{
"$group": bson.M{
"_id": nil,
"totalAmount": bson.M{"$sum": "$payMoney"},
},
},
}
var ret struct {
TotalAmount int64 `bson:"totalAmount"`
}
if err := coll(nil).AggregateDecode(&ret, pipeline); err != nil {
return 0, fmt.Errorf("table:%s PayCoinByCreatedTime err: %s", table, err.Error())
}
return ret.TotalAmount, nil
}
// PayCoinMapByTime vid->金币 map
func PayCoinMapByTime(start time.Time, end time.Time) (map[ObjectID]int64, error) {
pipeline := []bson.M{
{
"$match": bson.M{
"createdAt": bson.M{
"$gte": start,
"$lt": end,
},
},
},
{
"$group": bson.M{
"_id": "$videoID",
"income": bson.M{
"$sum": "$payMoney",
},
},
},
}
var docList []struct {
VID ObjectID `bson:"_id"`
Income int64 `bson:"income"`
}
if err := coll(nil).Aggregate(&docList, pipeline); err != nil {
return nil, fmt.Errorf("table:%s PayCoinMapByTime err: %s", table, err.Error())
}
ret := make(map[ObjectID]int64)
for _, doc := range docList {
ret[doc.VID] = doc.Income
}
return ret, nil
}
func VideoCoinIncomeGross(start, end time.Time) (int64, error) {
matchStage := bson.M{
"$match": bson.M{
"createdAt": bson.M{
"$gte": start,
"$lt": end,
},
},
}
groupStage := bson.M{
"$group": bson.M{
"_id": nil,
"gross": bson.M{
"$sum": "$payMoney",
},
},
}
var gross struct {
Gross int64 `bson:"gross"`
}
pipeline := []bson.M{matchStage, groupStage}
// opts := options.Aggregate()
if err := coll(nil).AggregateDecode(&gross, pipeline); err != nil {
log.Error("VideoCoinIncomeGross err: " + err.Error())
return 0, errors.Wrapf(err, "table:%s VideoCoinIncomeGross", table)
}
return gross.Gross, nil
}
// VideoCoinIncomeAggregateByVideoIDs 根据视频ID统计视频的售卖总数以及总金币数
func VideoCoinIncomeAggregateByVideoIDs(ids []primitive.ObjectID) (list []VideoCoinIncome, err error) {
if len(ids) == 0 {
return
}
matchStage := bson.M{
"$match": bson.M{
"videoID": bson.M{"$in": ids},
},
}
groupStage := bson.M{
"$group": bson.M{
"_id": "$videoID",
"total": bson.M{
"$sum": "$payMoney",
},
"count": bson.M{
"$sum": 1,
},
},
}
pipeline := []bson.M{matchStage, groupStage}
opts := options.Aggregate().SetMaxTime(10 * time.Second)
if err := coll(nil).Aggregate(&list, pipeline, opts); err != nil {
return nil, errors.Wrapf(err, "table:%s VideoCoinIncomeAggregateByVideoIDs", table)
}
return
}
// VideoCoinIncomeAggregate 聚合统计在给定时间段内视频收入排名前N的视频
func VideoCoinIncomeAggregateTopN(topN int, start, end time.Time) (list []VideoCoinIncome, err error) {
matchStage := bson.M{
"$match": bson.M{
"createdAt": bson.M{
"$gte": start,
"$lt": end,
},
},
}
groupStage := bson.M{
"$group": bson.M{
"_id": "$videoID",
"total": bson.M{
"$sum": "$payMoney",
},
"count": bson.M{
"$sum": 1,
},
},
}
sortStage := bson.M{
"$sort": bson.M{
"total": -1,
"count": -1,
},
}
limitStage := bson.M{
"$limit": topN,
}
pipeline := []bson.M{matchStage, groupStage, sortStage, limitStage}
opts := options.Aggregate().SetMaxTime(10 * time.Second)
if err := coll(nil).Aggregate(&list, pipeline, opts); err != nil {
return nil, errors.Wrapf(err, "table:%s VideoCoinIncomeAggregateTopN", table)
}
return
}
// PayCountMapByTime vid->金币 map
func PayCountMapByTime(start time.Time, end time.Time) (map[ObjectID]int64, error) {
pipeline := []bson.M{
{
"$match": bson.M{
"createdAt": bson.M{
"$gte": start,
"$lt": end,
},
},
},
{
"$group": bson.M{
"_id": "$videoID",
"count": bson.M{
"$sum": 1,
},
},
},
}
var docList []struct {
VID ObjectID `bson:"_id"`
Count int64 `bson:"count"`
}
if err := coll(nil).Aggregate(&docList, pipeline); err != nil {
return nil, fmt.Errorf("table:%s PayCoinMapByTime err: %s", table, err.Error())
}
ret := make(map[ObjectID]int64)
for _, doc := range docList {
ret[doc.VID] = doc.Count
}
return ret, nil
}
// TaxAmountMapByTime vid->TaxAmount map
func TaxAmountMapByTime(start time.Time, end time.Time) (map[ObjectID]float64, error) {
pipeline := []bson.M{
{
"$match": bson.M{
"createdAt": bson.M{
"$gte": start,
"$lt": end,
},
},
},
{
"$group": bson.M{
"_id": "$videoID",
"taxAmount": bson.M{
"$sum": "$taxAmount",
},
},
},
}
var docList []struct {
VID ObjectID `bson:"_id"`
TaxAmount float64 `bson:"taxAmount"`
}
if err := coll(nil).Aggregate(&docList, pipeline); err != nil {
return nil, fmt.Errorf("table:%s PayCoinMapByTime err: %s", table, err.Error())
}
ret := make(map[ObjectID]float64)
for _, doc := range docList {
ret[doc.VID] += doc.TaxAmount
}
return ret, nil
}
func PublisherIncomeMapByTime(start time.Time, end time.Time) (map[uint64]int64, error) {
pipeline := []bson.M{
{
"$match": bson.M{
"createdAt": bson.M{
"$gte": start,
"$lt": end,
},
},
},
{
"$group": bson.M{
"_id": "$publisherID",
"income": bson.M{
"$sum": "$payMoney",
},
},
},
}
var docList []struct {
PublisherID uint64 `bson:"_id"`
Income int64 `bson:"income"`
}
if err := coll(nil).Aggregate(&docList, pipeline); err != nil {
return nil, fmt.Errorf("table:%s PublisherIncomeMapByTime err: %s", table, err.Error())
}
ret := make(map[uint64]int64)
for _, doc := range docList {
ret[doc.PublisherID] = doc.Income
}
return ret, nil
}
// TaxAmountByTime
func TaxAmountByTime(start, end time.Time, mats ...Matcher) (float64, error) {
mats = append(mats, (&CreatedAtGTEAndLTMatch{GTE: &start, LT: &end}).New())
filter := pageopt.MergeM(mats)
var list []struct {
TaxAmount float64 `bson:"taxAmount"` //税额
}
opt := (&options.FindOptions{}).SetProjection(M{
"taxAmount": 1,
})
if err := coll(nil).Find(&list, filter, opt); err != nil {
return 0, err
}
var taxAmount float64
for _, v := range list {
taxAmount += v.TaxAmount
}
return taxAmount, nil
}
func FindByUID(uid uint64, newsType string, pageNumber int64, pageSize int64) (data []*Pay4VidLog, hasNext bool, err error) {
data = make([]*Pay4VidLog, 0)
opt := options.Find().
SetLimit(pageSize + 1).
SetSkip((pageNumber - 1) * pageSize).
SetSort(bson.D{{"createdAt", -1}})
filter := bson.M{
"uid": uid,
"newsType": newsType,
}
err = coll(nil).Find(&data, filter, opt)
if err != nil {
log.Error("FindByUID error", log.Any("uid", uid), log.Any("err", err.Error()))
return nil, false, err
}
if len(data) > int(pageSize) {
hasNext = true
data = data[:pageSize]
}
return
}
func PublisherVideoDeductionRange(uid uint64, start, end time.Time) ([]PublisherDeductionStat, error) {
pipeline := []bson.M{
{
"$match": bson.M{
// createdAt ∈ [startTime, endTime)
"createdAt": bson.M{
"$gte": start,
"$lt": end,
},
"publisherID": uid,
},
},
{
"$group": bson.M{
"_id": "$isVideoDeduction",
"totalAmount": bson.M{"$sum": "$coins"},
"videoCount": bson.M{"$sum": 1},
},
},
}
docList := []PublisherDeductionStat{}
return docList, coll(nil).Aggregate(&docList, pipeline)
}
func GetPayVidLogsByTime(start time.Time, end time.Time) ([]Pay4VidLogShort, error) {
filter := bson.M{
"createdAt": bson.M{
"$gte": start,
"$lt": end,
},
}
logs := make([]Pay4VidLogShort, 0)
if err := coll(nil).Find(&logs, filter); err != nil {
return logs, fmt.Errorf("table:%s GetPayMoneyByTime err: %s", table, err.Error())
}
return logs, nil
}
+78
View File
@@ -0,0 +1,78 @@
package payvidlgmod
import (
"strconv"
"strings"
"time"
"91porn-server/common/db"
"91porn-server/models/commod"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
)
type (
ObjectID = primitive.ObjectID
M = bson.M
DiscSeqe = commod.DiscSeqe
DiscDoc = commod.DiscDoc
)
// Pay4VidLog 购买影片记录
type Pay4VidLog struct {
ID primitive.ObjectID `json:"id" bson:"_id,omitempty"` // ID
UID uint64 `json:"uid" bson:"uid"` // 用户ID
Title string `json:"title" bson:"title,required"` // 视频标题
NewsType string `json:"newsType" bson:"newsType"` // 类型
VideoID primitive.ObjectID `json:"videoID" bson:"videoID"` // 视频id
PlayTime uint `json:"playTime" bson:"playTime"` // 影片长度
Coins int64 `json:"coins" bson:"coins"` // 定价
Tax int64 `json:"tax" bson:"tax"` // 税率
TaxAmount float64 `json:"taxAmount" bson:"taxAmount"` // 系统收取的税额 税率*定价
PayMoney int64 `json:"payMoney" bson:"payMoney"` // 金币
PublisherIncome float64 `json:"publisherIncome" bson:"publisherIncome"` // 上传者实际收益 定价-系统收取的税额
PublisherID uint64 `json:"publisherID" bson:"publisherID"` // 上传者ID
Uniq string `json:"uniq" bson:"uniq"` // UID.VideoID
CreatedAt time.Time `json:"createdAt" bson:"createdAt"` // 创建时间
SysType string `json:"sysType" bson:"sysType"` // 系统类型
IsVideoDeduction bool `json:"isVideoDeduction" bson:"isVideoDeduction"` // 是否扣量
DiscDoc `bson:",inline"`
}
func Init() {
mdb = db.Init(table)
initIndex()
}
func Unique(uid uint64, videoID primitive.ObjectID) string {
list := []string{
strconv.FormatInt(int64(uid), 10),
videoID.Hex(),
}
s := strings.Join(list, ".")
return s
}
type VideoCoinIncome struct {
VID ObjectID `bson:"_id" json:"videoID"` //video id
Total int64 `bson:"total" json:"total"` //视频总金币
Count int64 `bson:"count" json:"count"` //视频购买总次数
}
type PublisherDeductionStat struct {
IsVideoDeduction bool `bson:"_id"` // 是否扣量
TotalAmount int64 `bson:"totalAmount"` // 视频总售卖(金币)
VideoCount int64 `bson:"videoCount"` // 总计视频数
}
// Pay4VidLogShort 购买影片短结构
type Pay4VidLogShort struct {
ID primitive.ObjectID `json:"id" bson:"_id,omitempty"`
VideoID primitive.ObjectID `json:"videoID" bson:"videoID"`
PayMoney int64 `json:"payMoney" bson:"payMoney"` //金币
CreatedAt time.Time `json:"createdAt" bson:"createdAt"`
}
+426
View File
@@ -0,0 +1,426 @@
package playlgmod
import (
"fmt"
"math"
"time"
"91porn-server/common/db"
"91porn-server/common/log"
"91porn-server/models"
"github.com/jinzhu/now"
"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.PlayLog
const maxReadVideos = 200
// initIndex 初始化索引
func initIndex() {
many := []mongo.IndexModel{
{
Keys: bson.D{{Key: "uid", Value: 1}},
},
{
Keys: bson.D{{Key: "videoID", Value: 1}},
},
{
Keys: bson.D{{Key: "createdAt", Value: -1}},
},
}
if _, err := coll(nil).CreateIndex(many); err != nil {
panic(fmt.Sprintf("%s model set index err ==>[%+v]", table, err))
}
}
func coll(t *db.MongoTool) *db.MongoTool {
if t == nil {
return mdb.Coll(table)
}
return t.Coll(table)
}
// InsertPlayRecord 记录一个播放行为
func InsertPlayRecord(p PlayLog) error {
if _, err := coll(nil).InsertOne(&p); err != nil {
log.Error("InsertPlayRecord error", log.Any("p", p), log.E(err))
return err
}
return nil
}
// HasWatchedVideo 已经观看的视频
func HasWatchedVideo(uid uint64) ([]primitive.ObjectID, error) {
now := time.Now()
begin := now.AddDate(0, 0, -7)
var logs []*PlayLog
opts := options.FindOptions{}
opts.SetSort(bson.D{{Key: "createdAt", Value: -1}}).SetLimit(maxReadVideos)
if err := coll(nil).Find(&logs, bson.M{"uid": uid, "createdAt": bson.M{"$gt": begin}}, &opts); err != nil {
log.Error("HasWatchedVideo error", log.Any("uid", uid), log.E(err))
return nil, err
}
vids := make([]primitive.ObjectID, len(logs))
for i, l := range logs {
vids[i] = l.VideoID
}
return vids, nil
}
// HasWatchedVideoCnt 已经观看的视频数
func HasWatchedVideoCnt(uids []uint64) ([]UIDCount, error) {
now := time.Now()
begin := now.AddDate(0, 0, -4)
var datas []UIDCount
cond := bson.M{"uid": bson.M{"$in": uids}, "createdAt": bson.M{"$gt": begin}}
if err := coll(nil).Aggregate(&datas, []bson.M{
bson.M{"$match": cond},
bson.M{"$group": bson.M{"_id": "$uid", "count": bson.M{"$sum": 1}}},
}); err != nil {
log.Error("HasWatchedVideoCnt error", log.Any("uids", uids), log.E(err))
}
return datas, nil
}
// HasWatchedTags 当天已经观看过的标签id
func HasWatchedTags(uid uint64, top int) ([]string, error) {
tagIDs := []string{}
var data []TagIDCount
if err := coll(nil).Aggregate(&data, []bson.M{
bson.M{"$match": bson.M{"uid": uid, "tagID": bson.M{"$exists": true}, "createdAt": bson.M{"$gte": now.BeginningOfDay()}}},
bson.M{"$group": bson.M{"_id": "$tagID", "count": bson.M{"$sum": 1}}},
bson.M{"$sort": bson.D{{Key: "count", Value: -1}}},
bson.M{"$limit": top},
}); err != nil {
log.Error("HasWatchedTags error", log.Any("uid", uid), log.Any("top", top), log.E(err))
return tagIDs, err
}
tagIDs = make([]string, len(data))
for i, d := range data {
tagIDs[i] = d.TagID.Hex()
}
return tagIDs, nil
}
// getPlayRecordSkipSize 计算跳转
func getPlayRecordSkipSize(page, size uint64, cond bson.M) (uint64, uint64, uint64, error) {
var total uint64 = 10000
totalpages := uint64(math.Ceil(float64(total) / float64(size)))
if page > totalpages {
page = totalpages
}
if page < 1 {
page = 1
}
return (page - 1) * size, totalpages, total, nil
}
// GetPlayRecordList 获取播放记录
func getPlayRecordList(page, size uint64, cond bson.M, sort bson.D) ([]*PlayLog, uint64, uint64, error) {
skip, totalPages, total, err := getPlayRecordSkipSize(page, size, cond)
if err != nil {
return nil, 0, 0, err
}
opts := options.FindOptions{}
if sort != nil {
opts.SetSort(sort)
}
opts.SetSkip(int64(skip)).SetLimit(int64(size))
var back []*PlayLog
if err = coll(nil).Find(&back, cond, &opts); err != nil {
log.Error("GetPlayRecordList error", log.Any("page", page), log.Any("size", size),
log.Any("cond", cond), log.Any("sort", sort), log.E(err))
return nil, totalPages, total, err
}
return back, totalPages, total, nil
}
// GetNearPlayLog 获取用户最近的观影记录
func GetNearPlayLog(uid uint64) error {
var p PlayLog
opts := options.FindOne().SetSort(bson.D{{Key: "createdAt", Value: -1}})
return coll(nil).FindOne(&p, bson.M{"uid": uid}, opts)
}
// GetViewLogToday 当天是否看过此视频
func GetViewLogToday(uid uint64, vid primitive.ObjectID) bool {
cond := bson.M{"uid": uid, "videoID": vid, "createdAt": bson.M{"$gte": now.BeginningOfDay(), "$lte": now.EndOfDay()}}
cnt, _ := coll(nil).Count(cond)
return cnt > 0
}
// 当天是否观看过视频
func IsViewToday(uid uint64) bool {
cond := bson.M{"uid": uid, "createdAt": bson.M{"$gte": now.BeginningOfDay(), "$lte": now.EndOfDay()}}
cnt, _ := coll(nil).Count(cond)
return cnt > 0
}
// PlayCountMapByTime PlayCountMapByTime playWays 0免费 1付费 2.试看
func PlayCountMapByTime(start time.Time, end time.Time, playWays []int) (map[primitive.ObjectID]int64, error) {
if len(playWays) == 0 {
return make(map[primitive.ObjectID]int64), nil
}
filter := bson.M{
"createdAt": bson.M{
"$gte": start,
"$lt": end,
},
"playWay": bson.M{"$in": playWays}, //0免费 1付费 2.试看
}
pipeline := []bson.M{
{
"$match": filter,
},
{
"$group": bson.M{
"_id": "$videoID",
"count": bson.M{
"$sum": 1,
},
},
},
}
list := make([]struct {
VID primitive.ObjectID `bson:"_id"`
Count int64 `bson:"count"`
}, 0)
if err := coll(nil).Aggregate(&list, pipeline); err != nil {
return nil, fmt.Errorf("PlayLog PlayCountMapByTime err: %s", err.Error())
}
ret := make(map[primitive.ObjectID]int64)
for _, v := range list {
ret[v.VID] = v.Count
}
return ret, nil
}
func GetPayUserCount(vid []primitive.ObjectID) (int64, error) {
if len(vid) == 0 {
return 0, nil
}
pipeline := []bson.M{
{
"$match": bson.M{
"videoID": bson.M{
"$in": vid,
},
},
},
{
"$group": bson.M{
"_id": "$uid",
},
},
}
count, err := coll(nil).Count(pipeline)
if err != nil {
return 0, fmt.Errorf("GetPatUserCount err: %s", err.Error())
}
return count, nil
}
// PlayUIDListByTime
// playWay 0,免费 1付费 2.试看 ,nil All
func PlayUIDListByTime(start time.Time, end time.Time, playWay *int) ([]uint64, error) {
match := bson.M{
"$match": bson.M{
"createdAt": bson.M{
"$gte": start,
"$lt": end,
},
},
}
if playWay != nil {
match["playWay"] = *playWay //0,免费 1付费 2.试看
}
pipeline := []bson.M{match}
pipeline = append(pipeline,
bson.M{
"$group": bson.M{
"_id": "$uid",
},
})
list := []struct {
UID uint64 `bson:"_id"`
}{}
if err := coll(nil).Aggregate(&list, pipeline); err != nil {
return nil, fmt.Errorf("PlayUIDListByTime err: %s", err.Error())
}
uidList := make([]uint64, len(list))
for i, v := range list {
uidList[i] = v.UID
}
return uidList, nil
}
func backWatchParam(param WatchReq) map[string]interface{} {
m := make(map[string]interface{})
if param.UID > 0 {
m["uid"] = param.UID
}
if param.PlayWay == 1 {
m["playWay"] = 0
}
if param.PlayWay == 2 {
m["playWay"] = 1
}
if param.PlayWay == 3 {
m["playWay"] = 2
}
if !param.End.IsZero() {
i := make(map[string]time.Time)
i["$gte"] = param.Start
i["$lt"] = param.End
m["createdAt"] = i
}
return m
}
// GetPlayLog 获取播放日志
func GetPlayLog(param WatchReq) ([]*PlayLog, uint64, error) {
cond := backWatchParam(param)
sort := bson.D{{Key: "createdAt", Value: -1}}
infos, _, total, err := getPlayRecordList(param.PageNumber, param.PageSize, bson.M(cond), sort)
return infos, total, err
}
// GetUIDPlaySecondMap 用户播放时长(秒)map
func GetUIDPlaySecondMap(uidList []uint64) (map[uint64]int64, error) {
pipeline := []bson.M{
{
"$match": bson.M{
"uid": bson.M{
"$in": uidList,
},
},
},
{
"$group": bson.M{
"_id": "$uid",
"playSecond": bson.M{
"$sum": "$longer",
},
},
},
}
list := []struct {
UID uint64 `bson:"_id"`
PlaySecond int64 `bson:"playSecond"`
}{}
if err := coll(nil).Aggregate(&list, pipeline); err != nil {
return nil, fmt.Errorf("GetUIDPlayTimeMap err: %s", err.Error())
}
playSecondMap := make(map[uint64]int64, len(list))
for _, v := range list {
playSecondMap[v.UID] = v.PlaySecond
}
return playSecondMap, nil
}
// 根据时间范围获取标签下的视频的播放次数
func GetTagPlayByTimeRange(start time.Time, end time.Time) ([]TagPlayCount, error) {
list := make([]TagPlayCount, 0)
pipeline := []bson.M{
{
"$match": bson.M{
"tagID": bson.M{"$exists": true},
"createdAt": bson.M{"$gte": start, "$lt": end},
},
},
{
"$group": bson.M{
"_id": bson.M{"videoID": "$videoID", "tagID": "$tagID"},
"playCount": bson.M{"$sum": 1},
},
},
}
if err := coll(nil).Aggregate(&list, pipeline); err != nil {
log.Error("models log play log model GetTagPlayByTimeRange error", log.E(err), log.Any("start", start), log.Any("end", end))
return nil, err
}
return list, nil
}
// 获取播放量最多的视频
func GetHotVid(start time.Time, end time.Time) ([]TagPlayCount, error) {
list := make([]TagPlayCount, 0)
pipeline := []bson.M{
{
"$match": bson.M{
"tagID": bson.M{"$exists": true},
"createdAt": bson.M{"$gte": start, "$lt": end},
},
},
{
"$group": bson.M{
"_id": bson.M{"videoID": "$videoID", "tagID": "$tagID"},
"playCount": bson.M{"$sum": 1},
},
},
}
if err := coll(nil).Aggregate(&list, pipeline); err != nil {
log.Error("models log play log model GetTagPlayByTimeRange error", log.E(err), log.Any("start", start), log.Any("end", end))
return nil, err
}
return list, nil
}
// 获取播放量最多的视频
func GetHotVidIDs() ([]VidCount, error) {
list := make([]VidCount, 0)
pipeline := []bson.M{
{
"$match": bson.M{
"createdAt": bson.M{
"$gte": time.Now().AddDate(0, 0, -1),
},
},
},
{
"$group": bson.M{
"_id": "$videoID",
"count": bson.M{"$sum": 1},
},
},
{"$sort": bson.M{
"count": -1,
}},
{
"$limit": 20,
},
}
return list, coll(nil).Aggregate(&list, pipeline)
}
// 获取播放量最多的视频
func GetHotPublishesr() ([]PublisherCount, error) {
list := make([]PublisherCount, 0)
pipeline := []bson.M{
{
"$group": bson.M{
"_id": "$publisher",
"count": bson.M{"$sum": 1},
},
},
{"$match": bson.M{
"_id": bson.M{"$gt": 0},
}},
{"$sort": bson.M{
"count": -1,
}},
{
"$limit": 20,
},
}
return list, coll(nil).Aggregate(&list, pipeline)
}
func DeleteBeforeCreatedAt(t *db.MongoTool, tm time.Time) error {
_, err := coll(t).DeleteMany(bson.M{"createdAt": bson.M{"$lt": tm}})
return err
}
+73
View File
@@ -0,0 +1,73 @@
package playlgmod
import (
"time"
"91porn-server/common/db"
"go.mongodb.org/mongo-driver/bson/primitive"
)
var mdb *db.MongoDB
// PlayLog 观看记录
type PlayLog struct {
UID uint64 `json:"uid" bson:"uid"`
VideoID primitive.ObjectID `json:"videoID" bson:"videoID"`
Longer int `json:"longer" bson:"longer"` //播放时长 单位:秒
Progress int `json:"progress" bson:"progress"`
Via int `json:"via" bson:"via"`
PlayWay int `json:"playWay" bson:"playWay"` //0,免费 1付费 2.试看
TagID primitive.ObjectID `json:"tagID" bson:"tagID,omitempty"`
Publisher uint64 `json:"publisher" bson:"publisher,omitempty"`
CreatedAt time.Time `json:"createdAt" bson:"createdAt"`
}
type GroupKey struct {
VideoID primitive.ObjectID `bson:"videoID"`
TagID primitive.ObjectID `bson:"tagID"`
}
type TagPlayCount struct {
GroupID GroupKey `bson:"_id"`
PlayCount int64 `bson:"playCount"`
}
type TagPlayInfo struct {
VideoID primitive.ObjectID
TagID primitive.ObjectID
PlayCount int64
}
// TagIDCount 观看过的tagID统计
type TagIDCount struct {
TagID primitive.ObjectID `bson:"_id"`
Count int `bson:"count"`
}
// UIDCount 用户观看次数
type UIDCount struct {
UID uint64 `bson:"_id"`
Count int `bson:"count"`
}
// VidCount 视频观看次数
type VidCount struct {
//视频id
VideoID primitive.ObjectID `json:"videoID" bson:"_id"`
//次数
Count int `bson:"count"`
}
// PublisherCount 博主被观看次数
type PublisherCount struct {
//上传者id
Publisher uint64 `json:"publisher" bson:"_id,omitempty"`
//次数
Count int `bson:"count"`
}
func Init() {
mdb = db.Init(table)
initIndex()
}
+37
View File
@@ -0,0 +1,37 @@
package playlgmod
import (
"time"
"91porn-server/models/commod"
"go.mongodb.org/mongo-driver/bson/primitive"
)
// WatchReq 观看日志查询请求参数
type WatchReq struct {
PlayWay int `form:"playWay" json:"playWay"`
UID uint64 `form:"uid" json:"uid"`
Start time.Time `form:"start" json:"start"`
End time.Time `form:"end" json:"end"`
commod.Page
}
// LogInfo 返回数据
type LogInfo struct {
UID uint64 `json:"uid"`
VideoID primitive.ObjectID `json:"videoID"`
Title string `json:"title"`
PlayTime uint `json:"playTime"`
Longer int `json:"longer" `
Progress int `json:"progress"`
Via int `json:"via"`
PlayWay int `json:"playWay"` //0,免费 1付费 2.试看
CreatedAt time.Time `json:"createdAt"`
}
// WatchResp 观看日志查询请求应答
type WatchResp struct {
Logs []*LogInfo `json:"logs"`
Total uint64 `json:"total"`
}
+62
View File
@@ -0,0 +1,62 @@
package pullgmod
import (
"fmt"
"91porn-server/common/db"
"91porn-server/common/log"
"91porn-server/models"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
var mdb *db.MongoDB
const table = models.PullLog
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{{Key: "createdAt", Value: -1}},
},
{
Keys: bson.D{{Key: "newUpdatedAt", Value: -1}},
},
}
if _, err := coll(nil).CreateIndex(many); err != nil {
panic(fmt.Sprintf("%s model set index err ==>[%+v]", table, err))
}
}
// InsertPullLog InsertPullLog
func InsertPullLog(p PullLog) error {
_, err := coll(nil).InsertOne(&p)
return err
}
// FindPullRecord 查询
func FindPullRecord(vidType, newUpdateAt string) (pr *PullLog, err error) {
opts := options.FindOne().SetSort(bson.D{{Key: "createdAt", Value: -1}})
cond := bson.M{}
if vidType != "" {
cond["vidType"] = vidType
}
if newUpdateAt != "" {
cond["newUpdatedAt"] = newUpdateAt
}
if err = coll(nil).FindOne(&pr, cond, opts); err != nil {
log.Error("FindPullRecord error", log.E(err))
return
}
return
}
+23
View File
@@ -0,0 +1,23 @@
package pullgmod
import (
"time"
"91porn-server/common/db"
)
// PullLog 从aws同步视频记录
type PullLog struct {
LastID string `json:"lastId" bson:"lastId"`
Count int `json:"count" bson:"count"`
FailCount int `json:"failCount" bson:"failCount"`
CreatedAt time.Time `json:"createdAt" bson:"createdAt"`
FailIDs []string `json:"failIDs" bson:"failIDs,omitempty"`
VidType string `json:"vidType" bson:"vidType"`
NewUpdatedAt string `json:"newUpdatedAt" bson:"newUpdatedAt"`
}
func Init() {
mdb = db.Init(table)
initIndex()
}
+57
View File
@@ -0,0 +1,57 @@
package registermod
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/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
var mdb *db.MongoDB
const table = models.NewRegister
func coll(t *db.MongoTool) *db.MongoTool {
if t == nil {
return mdb.Coll(table)
}
return t.Coll(table)
}
// initIndex 设置index
func initIndex() {
many := []mongo.IndexModel{ //batch set indexes //value is the type 1 or -1
{
Keys: bson.D{{Key: "uid", Value: 1}},
Options: options.Index().SetUnique(true),
},
{
Keys: bson.D{{Key: "ip", Value: 1}},
},
{
Keys: bson.D{{Key: "createdAt", Value: 1}},
},
}
if _, err := coll(nil).CreateIndex(many); err != nil {
panic(fmt.Sprintf("%s model set index err ==>[%+v]", table, err))
}
}
func InsertRegisterLog(l *NewRegisterLog) error {
if _, err := coll(nil).InsertOne(l); err != nil {
log.Error("loginlog insert err", log.E(err))
return err
}
return nil
}
func DeleteBeforeCreatedAt(t *db.MongoTool, tm time.Time) error {
_, err := coll(t).DeleteMany(bson.M{"createdAt": bson.M{"$lt": tm}})
return err
}
+25
View File
@@ -0,0 +1,25 @@
package registermod
import (
"time"
"91porn-server/common/db"
)
// 新注册用户Log 接口调用记录
type NewRegisterLog struct {
UID uint64 `json:"uid" bson:"uid"`
IP string `json:"ip" bson:"ip"`
Query []QueryStat `json:"query" bson:"query"` //接口调用次数记录表
CreatedAt time.Time `json:"createdAt" bson:"createdAt"`
}
type QueryStat struct {
QueryUrl string `json:"key" bson:"key"`
Count int64 `json:"count" bson:"count"`
}
func Init() {
mdb = db.Init(table)
initIndex()
}
+148
View File
@@ -0,0 +1,148 @@
package searchlogmod
import (
"fmt"
"time"
"91porn-server/common/constant"
"91porn-server/common/db"
"91porn-server/common/log"
"91porn-server/models"
"91porn-server/models/commod"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
)
var mdb *db.MongoDB
const table = models.SearchLog
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{{Key: "createdAt", Value: -1}},
},
{
Keys: bson.D{{Key: "uid", Value: 1}},
},
{
Keys: bson.D{{Key: "realm", Value: 1}}, //不会新建 realm 索引
},
{
Keys: bson.D{{Key: "realm", Value: 1}, {Key: "keyword", Value: 1}}, //不会新建 realm 索引
},
}
if _, err := coll(nil).CreateIndex(many); err != nil {
panic(fmt.Sprintf("%s model set index err ==>[%+v]", table, err))
}
}
// FindHotSearch 根据搜索量获取热搜排行榜
func FindHotSearch(realm constant.RealmType, page commod.Page) ([]SearchCount, error) {
p := []M{
{
"$match": M{"realm": realm},
},
{
"$group": M{"_id": "$keyword", "count": M{"$sum": 1}},
},
{
"$match": M{"_id": M{"$ne": ""}},
},
{
"$sort": bson.D{{Key: "count", Value: -1}},
},
{
"$skip": (page.PageNumber - 1) * page.PageSize,
},
{
"$limit": page.PageSize,
},
}
data := make([]SearchCount, 0, page.PageSize)
if err := coll(nil).Aggregate(&data, p); err != nil {
log.ZapLog.Error(fmt.Sprintf("models record SearchLog FindSearchCountVid fail error:%+v:", err))
return nil, err
}
return data, nil
}
// InsertMany InsertMany
func InsertMany(uid uint64, realm constant.RealmType, keyWords []string) error {
now := time.Now()
searchLogDoc := make([]SearchLogDoc, 0, len(keyWords))
for _, keyword := range keyWords {
if keyword == "" {
continue
}
searchLogDoc = append(searchLogDoc, SearchLogDoc{
Realm: realm,
UID: uid,
Keyword: keyword,
CreatedAt: now,
})
}
if len(searchLogDoc) == 0 {
return nil
}
if _, err := coll(nil).InsertMany(&searchLogDoc); err != nil {
log.ZapLog.Error("SearchLog InsertMany error", log.E(err))
return err
}
return nil
}
func GetKeywordCountMapByTime(start time.Time, end time.Time, realm constant.RealmType) (map[string]int64, error) {
pipeline := []M{
{
"$match": M{
"createdAt": M{
"$gte": start,
"$lt": end,
},
"realm": realm,
},
},
{
"$sortByCount": "$keyword",
},
}
list := []struct {
Keyword string `bson:"_id"`
Count int64 `bson:"count"`
}{}
if err := coll(nil).Aggregate(&list, pipeline); err != nil {
return nil, fmt.Errorf("GetKeywordCountMapByTime err: %s", err.Error())
}
m := make(map[string]int64, len(list))
for _, v := range list {
m[v.Keyword] = v.Count
}
return m, nil
}
// 根据时间段获取搜索日志
func GetSearchLogByTimeRange(start time.Time, end time.Time) (data []SearchLog, err error) {
var query = bson.M{
"createdAt": bson.M{"$gte": start, "$lt": end},
}
if err = coll(nil).Find(&data, query); err != nil {
log.Error("models SearchLog model GetSearchLogByTimeRange error", log.E(err))
return
}
return
}
func DeleteBeforeCreatedAt(t *db.MongoTool, tm time.Time) error {
_, err := coll(t).DeleteMany(bson.M{"createdAt": bson.M{"$lt": tm}})
return err
}
+54
View File
@@ -0,0 +1,54 @@
package searchlogmod
import (
"time"
"91porn-server/common/constant"
"91porn-server/common/db"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
)
type (
SearchLogDoc = SearchLog
ObjectID = primitive.ObjectID
M = bson.M
)
// SearchLog 搜索记录
type SearchLog struct {
ID ObjectID `json:"id" bson:"_id,omitempty"`
Realm constant.RealmType `json:"realm" bson:"realm"` //搜索区域 综合:complex 视频:video 用户:user 话题:tag 地点:site
UID uint64 `json:"uid" bson:"uid"` //搜索人ID
Keyword string `json:"keyword" bson:"keyword"` //搜索的关键字
CreatedAt time.Time `json:"createdAt" bson:"createdAt"` //搜索的时间
}
// SearchLog 搜索记录
type ESSearchLogSource struct {
ID ObjectID `json:"id"`
Realm constant.RealmType `json:"realm"` //搜索区域 综合:complex 视频:video 用户:user 话题:tag 地点:site
UID uint64 `json:"uid"` //搜索人ID
Keyword string `json:"keyword"` //搜索的关键字
CreatedAt time.Time `json:"createdAt"` //搜索的时间
}
// SearchCount 热搜视频统计最高多搜索次数的视频
type SearchCount struct {
KeyWord string `json:"keyWord" bson:"_id"` //关键字
Count int `json:"count" bson:"count"` //关键字搜索次数
}
// SearchResp SearchResp
type SearchResp struct {
TagName string `json:"id" bson:"_id,omitempty"`
Count int `json:"count" bson:"count,omitempty"`
}
func Init() {
mdb = db.Init(table)
initIndex()
}
+57
View File
@@ -0,0 +1,57 @@
package synccdnmod
import (
"fmt"
"91porn-server/common/db"
"91porn-server/common/log"
"91porn-server/models"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
)
var mdb *db.MongoDB
const table = models.SyncCdnLog
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{{Key: "createdAt", Value: -1}},
},
}
if _, err := coll(nil).CreateIndex(many); err != nil {
panic(fmt.Sprintf("%s model set index err ==>[%+v]", table, err))
}
}
// InsertSyncCdnLog InsertSyncCdnLog
func InsertSyncCdnLog(p SyncCdnLog) error {
_, err := coll(nil).InsertOne(&p)
return err
}
// FindSyncRecord 查询
func FindSyncRecord() (pr []SyncCdnLog, err error) {
pr = []SyncCdnLog{}
cond := []bson.M{
bson.M{
"$sort": bson.M{"createdAt": -1},
},
bson.M{
"$limit": 1}}
if err = coll(nil).Aggregate(&pr, cond); err != nil {
log.Error("FindSyncRecord error", log.E(err))
return
}
return
}
+51
View File
@@ -0,0 +1,51 @@
package synccdnmod
import (
"91porn-server/common/db"
"91porn-server/common/stderr"
"time"
)
const (
AccessKey = "4qQTNUrg9MloxqtykJbkf9BTeJ3liBo5fS7Qg6Nu"
SecretKey = "axcamr082kQaJx87ebqkGHNPy-9EBeoTT2XbU6A2"
//AccessKey = "MY_ACCESS_KEY"
//SecretKey = "MY_SECRET_KEY"
URl = "http://rs.qiniu.com/move/bmV3ZG9jczpmaW5kX21hbi50eHQ=/bmV3ZG9jczpmaW5kLm1hbi50eHQ="
Host string = "http://fusion.qiniuapi.com" //域名
FetchUrl string = "/v2/tune/prefetch" //预取接口
PreFetchUrl string = "/v2/tune/prefetch/list" //预期查询接口地址
)
// SyncHttpResp 返回结构体
type SyncHttpResp struct {
Code stderr.Code `json:"code"`
Error string `json:"error"`
RequestId string `json:"requestId"`
InvalidUrls []string `json:"invalidUrls"`
QuotaDay int `json:"quotaDay"`
SurplusDay int `json:"surplusDay"`
}
type SyncCdnLog struct {
RequestIds []string `json:"requestIds" bson:"requestIds"`
LastID string `json:"lastId" bson:"lastId"`
Count int `json:"count" bson:"count"`
FailCount int `json:"failCount" bson:"failCount"`
CreatedAt time.Time `json:"createdAt" bson:"createdAt"`
FailIDs []string `json:"failIDs" bson:"failIDs,omitempty"`
}
// SyncReq 前端参数传递
type SyncReq struct {
Token string `json:"token" binding:"required"`
Cdn string `json:"cdn"`
FilePath string `json:"filePath"`
}
func Init() {
mdb = db.Init(table)
initIndex()
}
+71
View File
@@ -0,0 +1,71 @@
package userdailytasklogmod
import (
"fmt"
"time"
"91porn-server/common/db"
"91porn-server/models"
"91porn-server/models/v/dailytaskmod"
"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"
)
var mdb *db.MongoDB
const table = models.UserDailyTaskLog
// InitIndex 设置index
func initIndex() {
coll := coll(nil)
many := []mongo.IndexModel{
{
Keys: bson.D{{Key: "uid", Value: 1}, {Key: "type", Value: 1}, {Key: "date", Value: 1}},
Options: options.Index().SetUnique(true),
},
}
if _, err := coll.CreateIndex(many); err != nil {
panic(fmt.Sprintf("%s model set index err ==>[%+v]", table, err))
}
}
func coll(t *db.MongoTool) *db.MongoTool {
if t == nil {
return mdb.Coll(table)
}
return t.Coll(table)
}
func Init() {
mdb = db.Init(table)
initIndex()
}
type UserDailyTask struct {
ID primitive.ObjectID `json:"_id" bson:"_id"`
UID uint64 `json:"uid" bson:"uid"`
Type int `json:"type" bson:"type"` // 0 每日广告点击; 1 每日任务
Date string `json:"date" bson:"date"` // 日期. 格式 2006-01-02
FinishCount uint64 `json:"finishCount" bson:"finishCount"` // 当日完成次数
CreatedAt time.Time `json:"createdAt" bson:"createdAt"`
UpdatedAt time.Time `json:"updatedAt" bson:"updatedAt"`
}
func CompleteDailyTask(uid uint64, taskType int64, completeTime uint64) error {
_, err := coll(nil).UpsertOne(bson.M{"uid": uid, "type": taskType, "date": time.Now().Format("2006-01-02")}, bson.M{"$inc": bson.M{"finishCount": completeTime}})
return err
}
func GetUserFinishCount(uid uint64, taskType dailytaskmod.DailyTaskTypeEnum) (uint64, error) {
var udk UserDailyTask
if err := coll(nil).FindOne(&udk, bson.M{"uid": uid, "type": taskType, "date": time.Now().Format("2006-01-02")}); err != nil {
return 0, err
}
if udk.ID.IsZero() {
return 0, nil
}
return udk.FinishCount, nil
}
+44
View File
@@ -0,0 +1,44 @@
package visitlogmod
import (
"91porn-server/common/pageopt"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo/options"
)
type VisitLogSlice []VisitLog
func (v VisitLogSlice) ToUIDs() []uint64 {
uids := make([]uint64, len(v))
for i, l := range v {
uids[i] = l.UID
}
return uids
}
type Matcher = pageopt.Matcher
// CreatedAtGTEAndLTMatch
type CreatedAtGTEAndLTMatch = pageopt.CreatedAtGTEAndLTMatch
func List(sort bson.D, skip, limit *int64, mats ...Matcher) (VisitLogSlice, 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(mats)
list := VisitLogSlice{}
return list, coll(nil).Find(&list, filter, opt)
}
func Count(matchs ...pageopt.Matcher) (int64, error) {
filter := pageopt.MergeM(matchs)
return coll(nil).Count(filter)
}
+38
View File
@@ -0,0 +1,38 @@
package visitlogmod
import (
"time"
"91porn-server/common/db"
"go.mongodb.org/mongo-driver/bson/primitive"
)
// 以天为单位,统计用户的首次访问的日志
type VisitLog struct {
ID *primitive.ObjectID `json:"id" bson:"_id,omitempty"` //记录Id
SumDate time.Time `json:"sumDate" bson:"sumDate"` //每日零点
UID uint64 `json:"uid" bson:"uid"` //用户ID
IP string `json:"ip" bson:"ip"` //IP
SysType string `json:"sysType" bson:"sysType"` //操作系统类型 安卓 IOS
Ver string `json:"ver" bson:"ver"` //APP版本号
DevType string `json:"devType" bson:"devType"` //设备型号
DevID string `json:"devID" bson:"devID"` //设备ID
BuildID string `json:"buildID" bson:"buildID"` //app构建ID(包ID)
CreatedAt time.Time `json:"createdAt" bson:"createdAt"` //创建时间
IsDirect bool `json:"isDirect" bson:"isDirect"` // true:是直推用户
DistrictCode string `json:"districtCode" bson:"districtCode"` // 渠道码
RegisterTime time.Time `json:"registerTime" bson:"registerTime"` //用户注册时间
IsDeduction bool `json:"isDeduction" bson:"isDeduction"` // true:CPA扣量用户
}
type FilterDoc struct {
SumDate time.Time `bson:"sumDate"` //每日零点
UID uint64 `bson:"uid"` //用户ID
}
func Init() {
mdb = db.Init(table)
initIndex()
}
+187
View File
@@ -0,0 +1,187 @@
package visitlogmod
import (
"fmt"
"time"
"91porn-server/common/db"
"91porn-server/common/log"
"91porn-server/common/pageopt"
"91porn-server/models"
"91porn-server/models/v/usermod"
"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"
)
var mdb *db.MongoDB
const table = models.VisitLog
func coll(t *db.MongoTool) *db.MongoTool {
if t == nil {
return mdb.Coll(table)
}
return t.Coll(table)
}
// InitIndex 设置index
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: "sumDate", Value: -1}, {Key: "uid", Value: 1}},
},
{
Keys: bson.D{{Key: "createdAt", Value: -1}},
},
}
if _, err := coll(nil).CreateIndex(many); err != nil {
panic(fmt.Sprintf("%s model set index err ==>[%+v]", table, err))
}
}
func DataClean(deleteAt time.Time) (int64, error) {
res, err := coll(nil).DeleteMany(bson.M{"createdAt": bson.M{"$lt": deleteAt}})
if err != nil {
return 0, err
}
return res.DeletedCount, nil
}
func UpsertUserVisit(l *VisitLog) (*mongo.UpdateResult, error) {
l.CreatedAt = time.Now()
b, _ := bson.Marshal(l)
m := bson.M{}
_ = bson.Unmarshal(b, &m)
return coll(nil).UpsertOne(bson.M{"sumDate": l.SumDate, "uid": l.UID}, bson.M{"$setOnInsert": m})
}
func UIDListByCreatedTime(start time.Time, end time.Time, mats ...Matcher) ([]uint64, error) {
list := []struct {
UID uint64 `bson:"uid"` //用户ID
}{}
mats = append(mats, (&CreatedAtGTEAndLTMatch{GTE: &start, LT: &end}).New())
filter := pageopt.MergeM(mats)
opt := (&options.FindOptions{}).SetProjection(bson.M{
"uid": 1,
})
if err := coll(nil).Find(&list, filter, opt); err != nil {
log.Error("UIDListByCreatedTime failed", log.Any("filter", filter), log.E(err))
return nil, err
}
uids := make([]uint64, len(list))
for i, v := range list {
uids[i] = v.UID
}
return uids, nil
}
func GetSumDateCountMap(uidList []uint64) (map[uint64]int64, error) {
if len(uidList) == 0 {
return make(map[uint64]int64), nil
}
pipeLine := []bson.M{
{
"$match": bson.M{
"uid": bson.M{
"$in": uidList,
},
},
},
{
"$group": bson.M{
"_id": "$uid",
"count": bson.M{
"$sum": 1,
},
},
},
}
list := make([]struct {
UID uint64 `bson:"_id"`
Count int64 `bson:"count"`
}, 0, len(uidList))
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
}
// RetainUserListByTime 存留user
func RetainUserListByTime(createUserStart, createUserEnd, visitStart, visitEnd time.Time, mats ...usermod.Matcher) ([]usermod.User, error) {
visitFilter := (&CreatedAtGTEAndLTMatch{GTE: &visitStart, LT: &visitEnd}).New().Filter()
visitList := make([]struct {
UID uint64 `bson:"uid"`
}, 0)
visitOpt := (&options.FindOptions{}).SetProjection(bson.M{
"uid": 1,
})
if err := coll(nil).Find(&visitList, visitFilter, visitOpt); err != nil {
return nil, err
}
visitUIDList := make([]uint64, len(visitList))
for i, v := range visitList {
visitUIDList[i] = v.UID
}
return usermod.UserListByCreateTimeAndUIDS(createUserStart, createUserEnd, visitUIDList, mats...)
}
// RetainUIDListByTime 存留UID
func RetainUIDListByTime(createStart, createEnd, visitStart, visitEnd time.Time, mats ...usermod.Matcher) ([]uint64, error) {
visitList := make([]struct {
UID uint64 `bson:"uid"`
}, 0)
visitFilter := (&CreatedAtGTEAndLTMatch{GTE: &visitStart, LT: &visitEnd}).New().Filter()
visitOpt := (&options.FindOptions{}).SetProjection(bson.M{
"uid": 1,
})
if err := coll(nil).Find(&visitList, visitFilter, visitOpt); err != nil {
return nil, err
}
visitUIDList := make([]uint64, len(visitList))
for i, v := range visitList {
visitUIDList[i] = v.UID
}
return usermod.UIDListByCreateTimeAndUIDS(createStart, createEnd, visitUIDList, mats...)
}
// AccessSyncById 每日访问数据同步
func AccessSyncById(Id string, size int64) (data []VisitLog, err error) {
id, err := primitive.ObjectIDFromHex(Id)
if err != nil {
return
}
endTime := time.Now().Add(-time.Minute * 5)
visitFilter := bson.M{"_id": bson.M{"$gt": id}, "createdAt": bson.M{"$lt": endTime}}
visitOpt := (&options.FindOptions{}).SetLimit(size).SetSort(bson.M{"_id": 1})
err = coll(nil).Find(&data, visitFilter, visitOpt)
return
}
func AccessSyncByTime(visitTime time.Time, size int64) (data []VisitLog, err error) {
endTime := time.Now().Add(-time.Minute * 5)
visitFilter := bson.M{"createdAt": bson.M{"$gt": visitTime, "$lt": endTime}}
visitOpt := (&options.FindOptions{}).SetLimit(size).SetSort(bson.M{"createdAt": 1})
err = coll(nil).Find(&data, visitFilter, visitOpt)
return
}
func GetInfoByCond(cond bson.M, opts ...*options.FindOneOptions) (VisitLog, error) {
v := VisitLog{}
if err := coll(nil).FindOne(&v, cond, opts...); err != nil {
log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "GetInfo", table, "FindOne", err),
log.Any("cond", cond),
)
return v, err
}
return v, nil
}
+54
View File
@@ -0,0 +1,54 @@
package welfarelgmod
import (
"fmt"
"91porn-server/common/db"
"91porn-server/common/log"
"91porn-server/models"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
var mdb *db.MongoDB
const table = models.WelfareLog
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{{Key: "uid", Value: -1}, {Key: "fareType", Value: -1}},
Options: options.Index().SetUnique(true),
}, {
Keys: bson.D{{Key: "createdAt", Value: -1}},
},
}
if _, err := coll(nil).CreateIndex(many); err != nil {
panic(fmt.Sprintf("%s model set index err ==>[%+v]", table, err))
}
}
// InsertWelFareLog InsertWelFareLog
func InsertWelFareLog(p WelfareLog) error {
_, err := coll(nil).InsertOne(&p)
return err
}
// FindWelFareByUid 查询
func FindWelFareByUid(uid uint64) (pr *WelfareLog, err error) {
if err = coll(nil).FindOne(&pr, bson.M{"uid": uid}); err != nil {
log.Error("FindWelFareByUid error", log.E(err))
return
}
return
}
+31
View File
@@ -0,0 +1,31 @@
package welfarelgmod
import (
"time"
"91porn-server/common/db"
"go.mongodb.org/mongo-driver/bson/primitive"
)
type WelFareType int64
const (
Fare_Vip WelFareType = iota //vip
Fare_Coin //金币
)
// 福利添加记录
type WelfareLog struct {
Id primitive.ObjectID `json:"id,omitempty" bson:"_id,omitempty"`
Uid uint64 `json:"uid" bson:"uid"`
FareType WelFareType `json:"fareType" bson:"fareType"`
FareNum int64 `json:"fareNum" bson:"fareNum"`
DailyDate time.Time `json:"dailyDate" bson:"dailyDate"`
CreatedAt time.Time `json:"createdAt" bson:"createdAt"`
}
func Init() {
mdb = db.Init(table)
initIndex()
}