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
+423
View File
@@ -0,0 +1,423 @@
package Init
import (
"91porn-server/models/s/dailyretentionmod"
"91porn-server/models/s/useradverstatmod"
"91porn-server/models/v/advanceconfigmod"
"91porn-server/models/v/advanceordermod"
"91porn-server/models/v/aichangefaceimgmod"
"91porn-server/models/v/aichangefacemod"
"91porn-server/models/v/aichangefacevidmod"
"91porn-server/models/v/aiimagetovideomod"
"91porn-server/models/v/aiplazamod"
"91porn-server/models/v/aitemplatemodulemod"
"91porn-server/models/v/aitexttoimagemod"
"91porn-server/models/v/aitexttonovelmod"
"91porn-server/models/v/bannerjumpmod"
"91porn-server/models/v/checkinconfigmod"
"91porn-server/models/v/checkinprizemod"
"91porn-server/models/v/cmtmod"
"91porn-server/models/v/collectmod"
"91porn-server/models/v/coupon_record_mod"
"91porn-server/models/v/discount_area_mod"
"91porn-server/models/v/discount_area_video_mod"
"91porn-server/models/v/eventmod"
"91porn-server/models/v/export_task_mod"
"91porn-server/models/v/followmod"
"91porn-server/models/v/fundtransferlogmod"
"91porn-server/models/v/imgroupmembermod"
"91porn-server/models/v/imgroupmod"
"91porn-server/models/v/immessagemod"
"91porn-server/models/v/integralconfigmod"
"91porn-server/models/v/integralexcangemod"
"91porn-server/models/v/jingangmod"
"91porn-server/models/v/likemod"
"91porn-server/models/v/media_buy_record_mod"
"91porn-server/models/v/mediabookshelfmod"
"91porn-server/models/v/mediacontentmod"
"91porn-server/models/v/mediamod"
"91porn-server/models/v/mediatagdimensionmod"
"91porn-server/models/v/mediatagmod"
"91porn-server/models/v/messagemod"
"91porn-server/models/v/nakedchatmod"
"91porn-server/models/v/nakedchatordermod"
"91porn-server/models/v/officialWebsitemod"
"91porn-server/models/v/officialmod"
"91porn-server/models/v/paymentguidemod"
"91porn-server/models/v/sessionmod"
"91porn-server/models/v/signrecordmod"
"91porn-server/models/v/signtaskmod"
"91porn-server/models/v/sysconfmod"
"91porn-server/models/v/taskrecordmod"
"91porn-server/models/v/userResourcemod"
"91porn-server/models/v/usercheckinmod"
"91porn-server/models/v/videogoldcoinmod"
"91porn-server/models/v/vidtimeonlinemod"
"91porn-server/models/v/vipcardexperimentmod"
"os"
"time"
"91porn-server/common/log"
"91porn-server/models/l/adsclicklogmod"
"91porn-server/models/l/exchlogmod"
"91porn-server/models/l/loginlgmod"
"91porn-server/models/l/lotterylgmod"
"91porn-server/models/l/operatorlgmod"
"91porn-server/models/l/payvidlgmod"
"91porn-server/models/l/playlgmod"
"91porn-server/models/l/pullgmod"
"91porn-server/models/l/registermod"
"91porn-server/models/l/searchlogmod"
"91porn-server/models/l/synccdnmod"
"91porn-server/models/l/userdailytasklogmod"
"91porn-server/models/l/visitlogmod"
"91porn-server/models/l/welfarelgmod"
"91porn-server/models/s/hotstatmod"
"91porn-server/models/s/kwrankmod"
"91porn-server/models/s/kwstatmod"
"91porn-server/models/s/sectionstatmod"
"91porn-server/models/s/statordermod"
"91porn-server/models/s/statrecordmod"
"91porn-server/models/s/stattagplaymod"
"91porn-server/models/s/statusermod"
"91porn-server/models/s/statvidmod"
"91porn-server/models/s/statvidtotalmod"
"91porn-server/models/v/active2023mod"
"91porn-server/models/v/activitymod"
"91porn-server/models/v/actmod"
"91porn-server/models/v/adminmod"
"91porn-server/models/v/adreviewmod"
"91porn-server/models/v/adsmod"
"91porn-server/models/v/aiUnDressmod"
"91porn-server/models/v/annoumod"
"91porn-server/models/v/audioanchormod"
"91porn-server/models/v/audiobookmod"
"91porn-server/models/v/authoritymod"
"91porn-server/models/v/backpackmod"
"91porn-server/models/v/chatrobotmod"
"91porn-server/models/v/contentlibmod"
"91porn-server/models/v/contentreviewmod"
"91porn-server/models/v/currencymod"
"91porn-server/models/v/dailytaskmod"
"91porn-server/models/v/errfedbkmod"
"91porn-server/models/v/exchcodemod"
"91porn-server/models/v/faqmod"
"91porn-server/models/v/feedbackmod"
"91porn-server/models/v/fictionmod"
"91porn-server/models/v/filtermod"
"91porn-server/models/v/freeVidmod"
"91porn-server/models/v/fsuidmod"
"91porn-server/models/v/goldcfgmod"
"91porn-server/models/v/goldextramod"
"91porn-server/models/v/hevctaskmod"
"91porn-server/models/v/idmod"
"91porn-server/models/v/imagetopmod"
"91porn-server/models/v/immod"
"91porn-server/models/v/imusermod"
"91porn-server/models/v/ipblockmod"
"91porn-server/models/v/ipwhitemod"
"91porn-server/models/v/ldycfgmod"
"91porn-server/models/v/locmod"
"91porn-server/models/v/marqueemod"
"91porn-server/models/v/moduleconfmod"
"91porn-server/models/v/modulesectionmod"
"91porn-server/models/v/modulevidmod"
"91porn-server/models/v/newactivity"
"91porn-server/models/v/noticefmtmod"
"91porn-server/models/v/noticerecdmod"
"91porn-server/models/v/oncetaskmod"
"91porn-server/models/v/operationlogmod"
"91porn-server/models/v/payaudiobookmod"
"91porn-server/models/v/prdcthsomod"
"91porn-server/models/v/prizemod"
"91porn-server/models/v/productbenefitmod"
"91porn-server/models/v/productmod"
"91porn-server/models/v/productposimod"
"91porn-server/models/v/proxyincomemod"
"91porn-server/models/v/proxymod"
"91porn-server/models/v/proxyrecordmod"
"91porn-server/models/v/pushmod"
"91porn-server/models/v/questionnremod"
"91porn-server/models/v/quicksearchmod"
"91porn-server/models/v/rchgamegoldmod"
"91porn-server/models/v/rchgamtmod"
"91porn-server/models/v/rchgchanmod"
"91porn-server/models/v/rchgordmod"
"91porn-server/models/v/recmdtag"
"91porn-server/models/v/recommod"
"91porn-server/models/v/reptmod"
"91porn-server/models/v/repttypemod"
"91porn-server/models/v/rjctmpltmod"
"91porn-server/models/v/rolemod"
"91porn-server/models/v/scenebannermod"
"91porn-server/models/v/sensitivewordmod"
"91porn-server/models/v/settingmod"
"91porn-server/models/v/sourcemod"
"91porn-server/models/v/systemmod"
"91porn-server/models/v/tagconfmod"
"91porn-server/models/v/tagmod"
"91porn-server/models/v/taskmod"
"91porn-server/models/v/tonemod"
"91porn-server/models/v/tonerecomod"
"91porn-server/models/v/txnactmod"
"91porn-server/models/v/txnmod"
"91porn-server/models/v/useractmod"
"91porn-server/models/v/usermod"
"91porn-server/models/v/userrecomod"
"91porn-server/models/v/usertagmod"
"91porn-server/models/v/userwatchrecordmod"
"91porn-server/models/v/verifyreportmod"
"91porn-server/models/v/versionmod"
"91porn-server/models/v/videoactivitymod"
"91porn-server/models/v/videocoupon"
"91porn-server/models/v/videodiscountmod"
"91porn-server/models/v/vidmod"
"91porn-server/models/v/vidpopmod"
"91porn-server/models/v/vipconfigmod"
"91porn-server/models/v/walletmod"
"91porn-server/models/v/wdchannmod"
"91porn-server/models/v/wdordmod"
"91porn-server/models/v/wdtaxmod"
)
// initVideoDB 初始化主业务数据库
func initVideoDB() {
defer func() {
if r := recover(); r != nil {
log.Warn("[Init Index Error]===>", log.Any("Detail ", r))
os.Exit(-1)
}
}()
log.Info("【DB-Video】init start..")
filtermod.Init()
repttypemod.Init()
reptmod.Init()
tagmod.Init()
tonemod.Init()
tonerecomod.Init()
locmod.Init()
vidmod.Init()
hevctaskmod.Init()
adminmod.Init()
adsmod.Init()
adreviewmod.Init()
annoumod.Init()
pushmod.Init()
activitymod.Init()
sourcemod.Init()
productmod.Init()
productposimod.Init()
proxyincomemod.Init()
proxymod.Init()
proxyrecordmod.Init()
idmod.Init()
usermod.Init()
rchgamtmod.Init()
rchgamegoldmod.Init()
goldcfgmod.Init()
rchgchanmod.Init()
rchgordmod.Init()
prdcthsomod.Init()
settingmod.Init()
versionmod.Init()
walletmod.Init()
fundtransferlogmod.Init()
wdchannmod.Init()
wdordmod.Init()
wdtaxmod.Init()
authoritymod.Init()
rolemod.Init()
faqmod.Init()
feedbackmod.Init()
txnactmod.Init()
txnmod.Init()
useractmod.Init()
usertagmod.Init()
immod.Init()
imusermod.Init()
ipblockmod.Init()
ipwhitemod.Init()
noticefmtmod.Init()
noticerecdmod.Init()
officialmod.Init()
userrecomod.Init()
exchcodemod.Init()
chatrobotmod.Init()
contentlibmod.Init()
fsuidmod.Init()
recmdtag.Init()
freeVidmod.Init()
newactivity.Init()
ldycfgmod.Init()
questionnremod.Init()
verifyreportmod.Init()
fictionmod.Init()
audiobookmod.Init()
audioanchormod.Init()
errfedbkmod.Init()
payaudiobookmod.Init()
vipconfigmod.Init()
taskmod.Init()
taskrecordmod.Init()
backpackmod.Init()
prizemod.Init()
currencymod.Init()
systemmod.Init()
videodiscountmod.Init()
moduleconfmod.Init()
modulesectionmod.Init()
recommod.Init()
modulevidmod.Init()
tagconfmod.Init()
operationlogmod.Init()
videocoupon.Init()
marqueemod.Init()
videoactivitymod.Init()
vidpopmod.Init()
userwatchrecordmod.Index()
productbenefitmod.Init()
imagetopmod.Init()
active2023mod.Init()
goldextramod.Init()
actmod.Init()
dailytaskmod.Init()
oncetaskmod.Init()
rjctmpltmod.Init()
aiUnDressmod.Init()
likemod.Init()
integralconfigmod.Init()
integralexcangemod.Init()
followmod.Init()
cmtmod.Init()
collectmod.Init()
userResourcemod.Init()
aichangefacevidmod.Init()
aichangefacemod.Init()
sessionmod.Init()
messagemod.Init()
aichangefaceimgmod.Init()
advanceordermod.Init()
videogoldcoinmod.Init()
advanceconfigmod.Init()
coupon_record_mod.Init()
signrecordmod.Init()
vidtimeonlinemod.Init()
discount_area_mod.Init()
discount_area_video_mod.Init()
export_task_mod.Init()
quicksearchmod.Init()
sysconfmod.Init()
bannerjumpmod.Init()
paymentguidemod.Init()
scenebannermod.Init()
vipcardexperimentmod.Init()
mediamod.Init()
mediacontentmod.Init()
mediatagmod.Init()
mediatagdimensionmod.Init()
mediabookshelfmod.Init()
media_buy_record_mod.Init()
imgroupmod.Init()
imgroupmembermod.Init()
immessagemod.Init()
nakedchatmod.Init()
nakedchatordermod.Init()
aitexttoimagemod.Init()
aiimagetovideomod.Init()
aitemplatemodulemod.Init()
aiplazamod.Init()
signtaskmod.Init()
aitexttonovelmod.Init()
eventmod.Init()
checkinprizemod.Init()
usercheckinmod.Init()
checkinconfigmod.Init()
sensitivewordmod.Init()
contentreviewmod.Init()
officialWebsitemod.Init()
log.Info("【DB-Video】init end")
}
// initStatDB 初始化统计数据库
func initStatDB() {
defer func() {
if r := recover(); r != nil {
log.Warn("[Init Index Error]===>", log.Any("Detail ", r))
os.Exit(-1)
}
}()
log.Info("【DB-Stat】init start..")
statrecordmod.Init()
sectionstatmod.Init()
statvidmod.Init()
statordermod.Init()
kwstatmod.Init()
kwrankmod.Init()
stattagplaymod.Init()
statvidtotalmod.Init()
statusermod.Init()
hotstatmod.Init()
dailyretentionmod.Init()
useradverstatmod.Init()
log.Info("【DB-Stat】init end")
}
// initLogDB 初始化日志数据库
func initLogDB() {
defer func() {
if r := recover(); r != nil {
log.Warn("[Init Index Error]===>", log.Any("Detail ", r))
os.Exit(-1)
}
}()
log.Info("【DB-Log】 db init start..")
loginlgmod.Init()
payvidlgmod.Init()
playlgmod.Init()
pullgmod.Init()
searchlogmod.Init()
visitlogmod.Init()
welfarelgmod.Init()
synccdnmod.Init()
operatorlgmod.Init()
registermod.Init()
exchlogmod.Init()
lotterylgmod.Init()
adsclicklogmod.Init()
userdailytasklogmod.Init()
jingangmod.Init()
log.Info("【DB-Log】db init end")
}
// Init 设置索引//
func InitMongo() {
log.Info("DB init start..")
initLogDB()
initVideoDB()
initStatDB()
log.Info("DB init end")
}
func ESInit() {
log.Info("ES init start...")
initESIndex()
log.Info("ES init end")
}
// 初始化ES index
func initESIndex() {
vidmod.InitESIndex()
tagmod.InitESIndex()
usermod.InitESIndex()
audiobookmod.InitESIndex()
}
func InitCache() {
go func() {
ticker := time.NewTicker(29 * time.Minute)
for {
<-ticker.C
vidmod.SetAllVidWithPopCache()
}
}()
}
+88
View File
@@ -0,0 +1,88 @@
package aiimagetovideodata
import (
"91porn-server/common/cachev2"
"91porn-server/common/db"
"91porn-server/models"
"91porn-server/models/v/aiimagetovideomod"
"time"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
)
type ListRes struct {
List []aiimagetovideomod.AiImageToVideo
Count int64
HasNext bool
}
// GetListFromCache 从缓存获取列表数据
func GetListFromCache(cond bson.M, skip, limit int64, sort bson.D) ([]aiimagetovideomod.AiImageToVideo, int64, bool, error) {
var data ListRes
_, err := cachev2.Classes().CacheTime(10*time.Minute).AutoListKey(models.AiImageToVideo).ResBind(&data).Cache(GetListData, cond, skip, limit, sort)
return data.List, data.Count, data.HasNext, err
}
// GetListData 获取列表数据并组装适合缓存格式返回
func GetListData(cond bson.M, skip, limit int64, sort bson.D) (res ListRes, err error) {
res.List, res.Count, res.HasNext, err = aiimagetovideomod.GetList(cond, skip, limit, sort)
return
}
// GetInfoFromCache 获取数据详情
func GetInfoFromCache(id primitive.ObjectID) (res aiimagetovideomod.AiImageToVideo, err error) {
_, err = cachev2.Classes().CacheTime(30*time.Minute).AutoInfoKey(models.AiImageToVideo, id.Hex()).ResBind(&res).Cache(aiimagetovideomod.GetInfo, id)
return
}
// GetAllFromCache 获取所有数据
func GetAllFromCache(cond bson.M, sort bson.D) (res []aiimagetovideomod.AiImageToVideo, err error) {
_, err = cachev2.Classes().CacheTime(30*time.Minute).AutoListKey(models.AiImageToVideo+"-all").ResBind(&res).Cache(aiimagetovideomod.GetAll, cond, sort)
return
}
// InsertData 插入数据
func InsertData(t *db.MongoTool, data aiimagetovideomod.AiImageToVideo) (primitive.ObjectID, error) {
newID, err := aiimagetovideomod.Insert(t, data)
if err != nil {
return newID, err
}
// 清除缓存数据
_, err = cachev2.Classes().Table(models.AiImageToVideo).AutoClear(true, nil)
if err != nil {
return newID, err
}
return newID, nil
}
// UpdateData 更新数据
func UpdateData(t *db.MongoTool, id string, data map[string]interface{}) (int64, error) {
objID, err := primitive.ObjectIDFromHex(id)
if err != nil {
return 0, err
}
affect, err := aiimagetovideomod.UpdateByID(t, objID, data)
if err != nil {
return 0, err
}
// 清理缓存
_, _ = cachev2.Classes().Table(models.AiImageToVideo).AutoClear(true, &id)
return affect, err
}
// DeleteData 删除数据
func DeleteData(t *db.MongoTool, id primitive.ObjectID) (err error) {
err = aiimagetovideomod.DeleteByID(t, id)
if err != nil {
return
}
// 清理缓存
all := "*"
_, _ = cachev2.Classes().Table(models.AiImageToVideo).AutoClear(true, &all)
return
}
+43
View File
@@ -0,0 +1,43 @@
package aiimagetovideodata
import "91porn-server/models/v/aiimagetovideomod"
// FormatAppDataList 格式化app列表数据
func FormatAppDataList(origin []aiimagetovideomod.AiImageToVideo) (res []*aiimagetovideomod.AiImageToVideoInfo) {
res = make([]*aiimagetovideomod.AiImageToVideoInfo, len(origin))
if len(origin) == 0 {
return
}
// 组装返回数据
for i, item := range origin {
res[i] = FormatAppData(item)
}
return
}
// FormatAppData 格式化app数据
func FormatAppData(item aiimagetovideomod.AiImageToVideo) (res *aiimagetovideomod.AiImageToVideoInfo) {
if item.ID.IsZero() {
return
}
// 组装返回数据
res = &aiimagetovideomod.AiImageToVideoInfo{
ID: item.ID,
UID: item.UID,
ImgUrl: item.ImgUrl,
NewImgUrl: item.NewImgUrl,
Status: item.Status,
Coin: item.Coin,
IsFreeTimes: item.IsFreeTimes,
IsHide: item.IsHide,
Remark: item.Remark,
IsDelete: item.IsDelete,
CreatedAt: item.CreatedAt,
UpdatedAt: item.UpdatedAt,
}
return
}
+89
View File
@@ -0,0 +1,89 @@
package aiplazadata
import (
"time"
"91porn-server/common/cachev2"
"91porn-server/common/db"
"91porn-server/models"
"91porn-server/models/v/aiplazamod"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
)
type ListRes struct {
List []aiplazamod.AiPlaza
Count int64
HasNext bool
}
// GetListFromCache 从缓存获取列表数据
func GetListFromCache(cond bson.M, skip, limit int64, sort bson.D) ([]aiplazamod.AiPlaza, int64, bool, error) {
var data ListRes
_, err := cachev2.Classes().CacheTime(10*time.Minute).AutoListKey(models.AiPlaza).ResBind(&data).Cache(GetListData, cond, skip, limit, sort)
return data.List, data.Count, data.HasNext, err
}
// GetListData 获取列表数据并组装适合缓存格式返回
func GetListData(cond bson.M, skip, limit int64, sort bson.D) (res ListRes, err error) {
res.List, res.Count, res.HasNext, err = aiplazamod.GetList(cond, skip, limit, sort)
return
}
// GetInfoFromCache 获取数据详情
func GetInfoFromCache(id primitive.ObjectID) (res aiplazamod.AiPlaza, err error) {
_, err = cachev2.Classes().CacheTime(30*time.Minute).AutoInfoKey(models.AiPlaza, id.Hex()).ResBind(&res).Cache(aiplazamod.GetInfo, id)
return
}
// GetAllFromCache 获取所有数据
func GetAllFromCache(cond bson.M, sort bson.D) (res []aiplazamod.AiPlaza, err error) {
_, err = cachev2.Classes().CacheTime(30*time.Minute).AutoListKey(models.AiPlaza+"-all").ResBind(&res).Cache(aiplazamod.GetAll, cond, sort)
return
}
// InsertData 插入数据
func InsertData(t *db.MongoTool, data aiplazamod.AiPlaza) (primitive.ObjectID, error) {
newID, err := aiplazamod.Insert(t, data)
if err != nil {
return newID, err
}
// 清除缓存数据
_, err = cachev2.Classes().Table(models.AiPlaza).AutoClear(true, nil)
if err != nil {
return newID, err
}
return newID, nil
}
// UpdateData 更新数据
func UpdateData(t *db.MongoTool, id string, data map[string]interface{}) (int64, error) {
objID, err := primitive.ObjectIDFromHex(id)
if err != nil {
return 0, err
}
affect, err := aiplazamod.UpdateByID(t, objID, data)
if err != nil {
return 0, err
}
// 清理缓存
_, _ = cachev2.Classes().Table(models.AiPlaza).AutoClear(true, &id)
return affect, err
}
// DeleteData 删除数据
func DeleteData(t *db.MongoTool, id ...primitive.ObjectID) (err error) {
err = aiplazamod.DeleteByID(t, id...)
if err != nil {
return
}
// 清理缓存
all := "*"
_, _ = cachev2.Classes().Table(models.AiPlaza).AutoClear(true, &all)
return
}
+153
View File
@@ -0,0 +1,153 @@
package aiplazadata
import (
"91porn-server/app/service/vidhelpser"
"91porn-server/common"
"91porn-server/models/v/aiplazamod"
"91porn-server/models/v/collectmod"
"91porn-server/models/v/likemod"
"91porn-server/models/v/vidmod"
"go.mongodb.org/mongo-driver/bson/primitive"
"sync"
)
// FormatAppDataList 格式化app列表数据
func FormatAppDataList(origin []aiplazamod.AiPlaza) (res []*aiplazamod.AiPlazaInfo) {
res = make([]*aiplazamod.AiPlazaInfo, len(origin))
if len(origin) == 0 {
return
}
// 获取用户数据
uids := []uint64{}
for _, item := range origin {
uids = append(uids, item.Uid)
}
userMap := vidhelpser.GetSimpleUserMapNoUID(uids)
// 组装返回数据
for i, item := range origin {
res[i] = FormatAppSimpleData(item, userMap)
}
return
}
// FormatAppSimpleData 格式化app数据
func FormatAppSimpleData(item aiplazamod.AiPlaza, userMap map[uint64]*vidmod.Publisher) (res *aiplazamod.AiPlazaInfo) {
if item.ID.IsZero() {
return
}
// 组装返回数据
res = &aiplazamod.AiPlazaInfo{
ID: item.ID,
Type: item.Type,
Template: item.Template,
Uid: item.Uid,
Title: item.Title,
OriginalImage: item.OriginalImage,
OriginalVideo: item.OriginalVideo,
OriginalVideoCover: item.OriginalVideoCover,
OriginContent: item.OriginContent,
GenerateImage: item.GenerateImage,
GenerateVideo: item.GenerateVideo,
GenerateVideoCover: item.GenerateVideoCover,
Status: item.Status,
Reason: item.Reason,
SortCode: item.SortCode,
LikeCount: item.LikeCount,
CollectCount: item.CollectCount,
CommentCount: item.CommentCount,
ViewCount: item.ViewCount,
ReviewAt: item.ReviewAt,
CreatedAt: item.CreatedAt,
UpdatedAt: item.UpdatedAt,
}
if userMap != nil {
user, ok := userMap[item.Uid]
if ok && user != nil {
res.Name = user.Name
res.Gender = user.Gender
res.Portrait = user.Portrait
}
}
return
}
// FormatAppData 格式化app列表数据
func FormatAppData(uid uint64, item aiplazamod.AiPlaza) (res *aiplazamod.AiPlazaInfo) {
if item.ID.IsZero() {
return
}
userMap := vidhelpser.GetSimpleUserMapNoUID([]uint64{item.Uid})
// 获取是否点赞,收藏数据
dataStatus := GetDataStatus(uid, []primitive.ObjectID{item.ID})
// 组装返回数据
res = &aiplazamod.AiPlazaInfo{
ID: item.ID,
Type: item.Type,
Template: item.Template,
Uid: item.Uid,
Title: item.Title,
OriginalImage: item.OriginalImage,
OriginalVideo: item.OriginalVideo,
OriginalVideoCover: item.OriginalVideoCover,
OriginContent: item.OriginContent,
GenerateImage: item.GenerateImage,
GenerateVideo: item.GenerateVideo,
GenerateVideoCover: item.GenerateVideoCover,
Status: item.Status,
Reason: item.Reason,
SortCode: item.SortCode,
ReviewAt: item.ReviewAt,
CreatedAt: item.CreatedAt,
UpdatedAt: item.UpdatedAt,
}
if userMap != nil {
user, ok := userMap[item.Uid]
if ok && user != nil {
res.Name = user.Name
res.Gender = user.Gender
res.Portrait = user.Portrait
}
}
if dataStatus != nil {
res.HasLiked = dataStatus[item.ID].HasLiked
res.HasCollected = dataStatus[item.ID].HasCollected
}
return
}
// DataStatus 数据状态
type DataStatus struct {
//已点赞
HasLiked bool `json:"hasLiked" bson:"hasLiked"`
//已收藏
HasCollected bool `json:"hasCollected" bson:"hasCollected"`
}
// GetDataStatus 获取数据状态信息
func GetDataStatus(uid uint64, objIds []primitive.ObjectID) map[primitive.ObjectID]DataStatus {
mLike := make(map[primitive.ObjectID]bool)
mCollect := make(map[primitive.ObjectID]bool)
var wg sync.WaitGroup
wg.Add(2)
common.Go(func() {
defer wg.Done()
mLike, _ = likemod.IsLikeVideos(uid, objIds)
})
common.Go(func() {
defer wg.Done()
mCollect, _ = collectmod.IsCollectVideos(uid, objIds)
})
wg.Wait()
m := make(map[primitive.ObjectID]DataStatus)
for _, v := range objIds {
info := DataStatus{
HasLiked: mLike[v],
HasCollected: mCollect[v],
}
m[v] = info
}
return m
}
+89
View File
@@ -0,0 +1,89 @@
package aitemplatemoduledata
import (
"time"
"91porn-server/common/cachev2"
"91porn-server/common/db"
"91porn-server/models"
"91porn-server/models/v/aitemplatemodulemod"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
)
type ListRes struct {
List []aitemplatemodulemod.AiTemplateModule
Count int64
HasNext bool
}
// GetListFromCache 从缓存获取列表数据
func GetListFromCache(cond bson.M, skip, limit int64, sort bson.D) ([]aitemplatemodulemod.AiTemplateModule, int64, bool, error) {
var data ListRes
_, err := cachev2.Classes().CacheTime(3*time.Minute).AutoListKey(models.AiTemplateModule).ResBind(&data).Cache(GetListData, cond, skip, limit, sort)
return data.List, data.Count, data.HasNext, err
}
// GetListData 获取列表数据并组装适合缓存格式返回
func GetListData(cond bson.M, skip, limit int64, sort bson.D) (res ListRes, err error) {
res.List, res.Count, res.HasNext, err = aitemplatemodulemod.GetList(cond, skip, limit, sort)
return
}
// GetInfoFromCache 获取数据详情
func GetInfoFromCache(id primitive.ObjectID) (res aitemplatemodulemod.AiTemplateModule, err error) {
_, err = cachev2.Classes().CacheTime(5*time.Minute).AutoInfoKey(models.AiTemplateModule, id.Hex()).ResBind(&res).Cache(aitemplatemodulemod.GetInfo, id)
return
}
// GetAllFromCache 获取所有数据
func GetAllFromCache(cond bson.M, sort bson.D) (res []aitemplatemodulemod.AiTemplateModule, err error) {
_, err = cachev2.Classes().CacheTime(8*time.Minute).AutoListKey(models.AiTemplateModule+"-all").ResBind(&res).Cache(aitemplatemodulemod.GetAll, cond, sort)
return
}
// InsertData 插入数据
func InsertData(t *db.MongoTool, data aitemplatemodulemod.AiTemplateModule) (primitive.ObjectID, error) {
newID, err := aitemplatemodulemod.Insert(t, data)
if err != nil {
return newID, err
}
// 清除缓存数据
_, err = cachev2.Classes().Table(models.AiTemplateModule).AutoClear(true, nil)
if err != nil {
return newID, err
}
return newID, nil
}
// UpdateData 更新数据
func UpdateData(t *db.MongoTool, id string, data map[string]interface{}) (int64, error) {
objID, err := primitive.ObjectIDFromHex(id)
if err != nil {
return 0, err
}
affect, err := aitemplatemodulemod.UpdateByID(t, objID, data)
if err != nil {
return 0, err
}
// 清理缓存
_, _ = cachev2.Classes().Table(models.AiTemplateModule).AutoClear(true, &id)
return affect, err
}
// DeleteData 删除数据
func DeleteData(t *db.MongoTool, id primitive.ObjectID) (err error) {
err = aitemplatemodulemod.DeleteByID(t, id)
if err != nil {
return
}
// 清理缓存
all := "*"
_, _ = cachev2.Classes().Table(models.AiTemplateModule).AutoClear(true, &all)
return
}
+36
View File
@@ -0,0 +1,36 @@
package aitemplatemoduledata
import (
"91porn-server/models/v/aitemplatemodulemod"
)
// FormatAppDataList 格式化app列表数据
func FormatAppDataList(origin []aitemplatemodulemod.AiTemplateModule) (res []*aitemplatemodulemod.AiTemplateModuleInfo) {
res = make([]*aitemplatemodulemod.AiTemplateModuleInfo, len(origin))
if len(origin) == 0 {
return
}
// 组装返回数据
for i, item := range origin {
res[i] = FormatAppData(item)
}
return
}
// FormatAppData 格式化app数据
func FormatAppData(item aitemplatemodulemod.AiTemplateModule) (res *aitemplatemodulemod.AiTemplateModuleInfo) {
if item.ID.IsZero() {
return
}
// 组装返回数据
res = &aitemplatemodulemod.AiTemplateModuleInfo{
ID: item.ID,
Type: item.Type,
Name: item.Name,
}
return
}
+89
View File
@@ -0,0 +1,89 @@
package aitexttoimagedata
import (
"time"
"91porn-server/common/cachev2"
"91porn-server/common/db"
"91porn-server/models"
"91porn-server/models/v/aitexttoimagemod"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
)
type ListRes struct {
List []aitexttoimagemod.AiTextToImage
Count int64
HasNext bool
}
// GetListFromCache 从缓存获取列表数据
func GetListFromCache(cond bson.M, skip, limit int64, sort bson.D) ([]aitexttoimagemod.AiTextToImage, int64, bool, error) {
var data ListRes
_, err := cachev2.Classes().CacheTime(3*time.Minute).AutoListKey(models.AiTextToImage).ResBind(&data).Cache(GetListData, cond, skip, limit, sort)
return data.List, data.Count, data.HasNext, err
}
// GetListData 获取列表数据并组装适合缓存格式返回
func GetListData(cond bson.M, skip, limit int64, sort bson.D) (res ListRes, err error) {
res.List, res.Count, res.HasNext, err = aitexttoimagemod.GetList(cond, skip, limit, sort)
return
}
// GetInfoFromCache 获取数据详情
func GetInfoFromCache(id primitive.ObjectID) (res aitexttoimagemod.AiTextToImage, err error) {
_, err = cachev2.Classes().CacheTime(5*time.Minute).AutoInfoKey(models.AiTextToImage, id.Hex()).ResBind(&res).Cache(aitexttoimagemod.GetInfo, id)
return
}
// GetAllFromCache 获取所有数据
func GetAllFromCache(cond bson.M, sort bson.D) (res []aitexttoimagemod.AiTextToImage, err error) {
_, err = cachev2.Classes().CacheTime(8*time.Minute).AutoListKey(models.AiTextToImage+"-all").ResBind(&res).Cache(aitexttoimagemod.GetAll, cond, sort)
return
}
// InsertData 插入数据
func InsertData(t *db.MongoTool, data aitexttoimagemod.AiTextToImage) (primitive.ObjectID, error) {
newID, err := aitexttoimagemod.Insert(t, data)
if err != nil {
return newID, err
}
// 清除缓存数据
_, err = cachev2.Classes().Table(models.AiTextToImage).AutoClear(true, nil)
if err != nil {
return newID, err
}
return newID, nil
}
// UpdateData 更新数据
func UpdateData(t *db.MongoTool, id string, data map[string]interface{}) (int64, error) {
objID, err := primitive.ObjectIDFromHex(id)
if err != nil {
return 0, err
}
affect, err := aitexttoimagemod.UpdateByID(t, objID, data)
if err != nil {
return 0, err
}
// 清理缓存
_, _ = cachev2.Classes().Table(models.AiTextToImage).AutoClear(true, &id)
return affect, err
}
// DeleteData 删除数据
func DeleteData(t *db.MongoTool, id primitive.ObjectID) (err error) {
err = aitexttoimagemod.DeleteByID(t, id)
if err != nil {
return
}
// 清理缓存
all := "*"
_, _ = cachev2.Classes().Table(models.AiTextToImage).AutoClear(true, &all)
return
}
+49
View File
@@ -0,0 +1,49 @@
package aitexttoimagedata
import (
"91porn-server/models/v/aitexttoimagemod"
)
// FormatAppDataList 格式化app列表数据
func FormatAppDataList(origin []aitexttoimagemod.AiTextToImage) (res []*aitexttoimagemod.AiTextToImageInfo) {
res = make([]*aitexttoimagemod.AiTextToImageInfo, len(origin))
if len(origin) == 0 {
return
}
// 组装返回数据
for i, item := range origin {
res[i] = FormatAppData(item)
}
return
}
// FormatAppData 格式化app数据
func FormatAppData(item aitexttoimagemod.AiTextToImage) (res *aitexttoimagemod.AiTextToImageInfo) {
if item.ID.IsZero() {
return
}
// 组装返回数据
res = &aitexttoimagemod.AiTextToImageInfo{
ID: item.ID,
UID: item.UID,
Text: item.Text,
NewImgUrl: item.NewImgUrl,
Status: item.Status,
AspectRatio: item.AspectRatio,
StyleType: item.StyleType,
Coin: item.Coin,
DebitAmountCoin: item.DebitAmountCoin,
DebitIncomeCoin: item.DebitIncomeCoin,
IsFreeTimes: item.IsFreeTimes,
IsHide: item.IsHide,
Remark: item.Remark,
IsDelete: item.IsDelete,
CreatedAt: item.CreatedAt,
UpdatedAt: item.UpdatedAt,
}
return
}
+88
View File
@@ -0,0 +1,88 @@
package aitexttonoveldata
import (
"91porn-server/common/cachev2"
"91porn-server/common/db"
"91porn-server/models"
"91porn-server/models/v/aitexttonovelmod"
"time"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
)
type ListRes struct {
List []aitexttonovelmod.AiTextToNovel
Count int64
HasNext bool
}
// GetListFromCache 从缓存获取列表数据
func GetListFromCache(cond bson.M, skip, limit int64, sort bson.D) ([]aitexttonovelmod.AiTextToNovel, int64, bool, error) {
var data ListRes
_, err := cachev2.Classes().CacheTime(10*time.Minute).AutoListKey(models.AiTextToNovel).ResBind(&data).Cache(GetListData, cond, skip, limit, sort)
return data.List, data.Count, data.HasNext, err
}
// GetListData 获取列表数据并组装适合缓存格式返回
func GetListData(cond bson.M, skip, limit int64, sort bson.D) (res ListRes, err error) {
res.List, res.Count, res.HasNext, err = aitexttonovelmod.GetList(cond, skip, limit, sort)
return
}
// GetInfoFromCache 获取数据详情
func GetInfoFromCache(id primitive.ObjectID) (res aitexttonovelmod.AiTextToNovel, err error) {
_, err = cachev2.Classes().CacheTime(30*time.Minute).AutoInfoKey(models.AiTextToNovel, id.Hex()).ResBind(&res).Cache(aitexttonovelmod.GetInfo, id)
return
}
// GetAllFromCache 获取所有数据
func GetAllFromCache(cond bson.M, sort bson.D) (res []aitexttonovelmod.AiTextToNovel, err error) {
_, err = cachev2.Classes().CacheTime(30*time.Minute).AutoListKey(models.AiTextToNovel+"-all").ResBind(&res).Cache(aitexttonovelmod.GetAll, cond, sort)
return
}
// InsertData 插入数据
func InsertData(t *db.MongoTool, data aitexttonovelmod.AiTextToNovel) (primitive.ObjectID, error) {
newID, err := aitexttonovelmod.Insert(t, data)
if err != nil {
return newID, err
}
// 清除缓存数据
_, err = cachev2.Classes().Table(models.AiTextToNovel).AutoClear(true, nil)
if err != nil {
return newID, err
}
return newID, nil
}
// UpdateData 更新数据
func UpdateData(t *db.MongoTool, id string, data map[string]interface{}) (int64, error) {
objID, err := primitive.ObjectIDFromHex(id)
if err != nil {
return 0, err
}
affect, err := aitexttonovelmod.UpdateByID(t, objID, data)
if err != nil {
return 0, err
}
// 清理缓存
_, _ = cachev2.Classes().Table(models.AiTextToNovel).AutoClear(true, &id)
return affect, err
}
// DeleteData 删除数据
func DeleteData(t *db.MongoTool, id primitive.ObjectID) (err error) {
err = aitexttonovelmod.DeleteByID(t, id)
if err != nil {
return
}
// 清理缓存
all := "*"
_, _ = cachev2.Classes().Table(models.AiTextToNovel).AutoClear(true, &all)
return
}
+49
View File
@@ -0,0 +1,49 @@
package aitexttonoveldata
import "91porn-server/models/v/aitexttonovelmod"
// FormatAppDataList 格式化app列表数据
func FormatAppDataList(origin []aitexttonovelmod.AiTextToNovel) (res []*aitexttonovelmod.AiTextToNovel) {
res = make([]*aitexttonovelmod.AiTextToNovel, len(origin))
if len(origin) == 0 {
return
}
// 组装返回数据
for i, item := range origin {
res[i] = FormatAppData(item)
}
return
}
// FormatAppData 格式化app数据
func FormatAppData(item aitexttonovelmod.AiTextToNovel) (res *aitexttonovelmod.AiTextToNovel) {
if item.ID.IsZero() {
return
}
// 组装返回数据
res = &aitexttonovelmod.AiTextToNovel{
ID: item.ID,
UID: item.UID,
Description: item.Description,
Content: item.Content,
Status: item.Status,
CharacterSetting: item.CharacterSetting,
LocationScene: item.LocationScene,
Details: item.Details,
ModelType: item.ModelType,
Coin: item.Coin,
DebitAmountCoin: item.DebitAmountCoin,
DebitIncomeCoin: item.DebitIncomeCoin,
IsFreeTimes: item.IsFreeTimes,
IsHide: item.IsHide,
Remark: item.Remark,
IsDelete: item.IsDelete,
CreatedAt: item.CreatedAt,
UpdatedAt: item.UpdatedAt,
}
return
}
+73
View File
@@ -0,0 +1,73 @@
package bannerjumpdata
import (
"time"
"91porn-server/common/cachev2"
"91porn-server/common/db"
"91porn-server/models"
"91porn-server/models/v/bannerjumpmod"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
)
type ListRes struct {
List []bannerjumpmod.BannerJump
Count int64
HasNext bool
}
// GetAllFromCache 获取所有数据
func GetAllFromCache() (res []bannerjumpmod.BannerJump, err error) {
t := time.Now()
cond := bson.M{"enable": true, "startAt": bson.M{"$lte": t}, "endAt": bson.M{"$gt": t}}
sort := bson.D{{"weight", -1}, {"createdAt", -1}}
_, err = cachev2.Classes().CacheTime(8*time.Minute).AutoListKey(models.BannerJump+"-all").ResBind(&res).Cache(bannerjumpmod.GetAll, cond, sort)
return
}
// InsertData 插入数据
func InsertData(t *db.MongoTool, data bannerjumpmod.BannerJump) (primitive.ObjectID, error) {
newID, err := bannerjumpmod.Insert(t, data)
if err != nil {
return newID, err
}
// 清除缓存数据
_, err = cachev2.Classes().Table(models.BannerJump).AutoClear(true, nil)
if err != nil {
return newID, err
}
return newID, nil
}
// UpdateData 更新数据
func UpdateData(t *db.MongoTool, id string, data map[string]interface{}) (int64, error) {
objID, err := primitive.ObjectIDFromHex(id)
if err != nil {
return 0, err
}
affect, err := bannerjumpmod.UpdateByID(t, objID, data)
if err != nil {
return 0, err
}
// 清理缓存
_, _ = cachev2.Classes().Table(models.BannerJump).AutoClear(true, &id)
return affect, err
}
// DeleteData 删除数据
func DeleteData(t *db.MongoTool, id primitive.ObjectID) (err error) {
err = bannerjumpmod.DeleteByID(t, id)
if err != nil {
return
}
// 清理缓存
all := "*"
_, _ = cachev2.Classes().Table(models.BannerJump).AutoClear(true, &all)
return
}
+43
View File
@@ -0,0 +1,43 @@
package imgroupdata
import (
"91porn-server/models/v/imgroupmod"
)
// FormatAppDataList 格式化app列表数据
func FormatAppDataList(origin []imgroupmod.ImGroup) (res []*imgroupmod.ImGroupInfo) {
res = make([]*imgroupmod.ImGroupInfo, len(origin))
if len(origin) == 0 {
return
}
// 组装返回数据
for i, item := range origin {
res[i] = FormatAppData(item)
}
return
}
// FormatAppData 格式化app数据
func FormatAppData(item imgroupmod.ImGroup) (res *imgroupmod.ImGroupInfo) {
if item.ID.IsZero() {
return
}
// 组装返回数据
res = &imgroupmod.ImGroupInfo{
ID: item.ID,
GroupId: item.GroupId,
Name: item.Name,
Cover: item.Cover,
Summary: item.Summary,
MemberNum: item.MemberNum,
FakeMemberNum: item.FakeMemberNum,
Price: item.Price,
CreatedAt: item.CreatedAt,
UpdatedAt: item.UpdatedAt,
}
return
}
+89
View File
@@ -0,0 +1,89 @@
package imgroupdata
import (
"time"
"91porn-server/common/cachev2"
"91porn-server/common/db"
"91porn-server/models"
"91porn-server/models/v/imgroupmod"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
)
type ListRes struct {
List []imgroupmod.ImGroup
Count int64
HasNext bool
}
// GetListFromCache 从缓存获取列表数据
func GetListFromCache(cond bson.M, skip, limit int64, sort bson.D) ([]imgroupmod.ImGroup, int64, bool, error) {
var data ListRes
_, err := cachev2.Classes().CacheTime(10*time.Minute).AutoListKey(models.ImGroup).ResBind(&data).Cache(GetListData, cond, skip, limit, sort)
return data.List, data.Count, data.HasNext, err
}
// GetListData 获取列表数据并组装适合缓存格式返回
func GetListData(cond bson.M, skip, limit int64, sort bson.D) (res ListRes, err error) {
res.List, res.Count, res.HasNext, err = imgroupmod.GetList(cond, skip, limit, sort)
return
}
// GetInfoFromCache 获取数据详情
func GetInfoFromCache(id primitive.ObjectID) (res imgroupmod.ImGroup, err error) {
_, err = cachev2.Classes().CacheTime(30*time.Minute).AutoInfoKey(models.ImGroup, id.Hex()).ResBind(&res).Cache(imgroupmod.GetInfo, id)
return
}
// GetAllFromCache 获取所有数据
func GetAllFromCache(cond bson.M, sort bson.D) (res []imgroupmod.ImGroup, err error) {
_, err = cachev2.Classes().CacheTime(30*time.Minute).AutoListKey(models.ImGroup+"-all").ResBind(&res).Cache(imgroupmod.GetAll, cond, sort)
return
}
// InsertData 插入数据
func InsertData(t *db.MongoTool, data imgroupmod.ImGroup) (primitive.ObjectID, error) {
newID, err := imgroupmod.Insert(t, data)
if err != nil {
return newID, err
}
// 清除缓存数据
_, err = cachev2.Classes().Table(models.ImGroup).AutoClear(true, nil)
if err != nil {
return newID, err
}
return newID, nil
}
// UpdateData 更新数据
func UpdateData(t *db.MongoTool, id string, data map[string]interface{}) (int64, error) {
objID, err := primitive.ObjectIDFromHex(id)
if err != nil {
return 0, err
}
affect, err := imgroupmod.UpdateByID(t, objID, data)
if err != nil {
return 0, err
}
// 清理缓存
_, _ = cachev2.Classes().Table(models.ImGroup).AutoClear(true, &id)
return affect, err
}
// DeleteData 删除数据
func DeleteData(t *db.MongoTool, id primitive.ObjectID) (err error) {
err = imgroupmod.DeleteByID(t, id)
if err != nil {
return
}
// 清理缓存
all := "*"
_, _ = cachev2.Classes().Table(models.ImGroup).AutoClear(true, &all)
return
}
+37
View File
@@ -0,0 +1,37 @@
package imgroupmemberdata
import (
"91porn-server/models/v/imgroupmembermod"
)
// FormatAppDataList 格式化app列表数据
func FormatAppDataList(origin []imgroupmembermod.ImGroupMember) (res []*imgroupmembermod.ImGroupMemberInfo) {
res = make([]*imgroupmembermod.ImGroupMemberInfo, len(origin))
if len(origin) == 0 {
return
}
// 组装返回数据
for i, item := range origin {
res[i] = FormatAppData(item)
}
return
}
// FormatAppData 格式化app数据
func FormatAppData(item imgroupmembermod.ImGroupMember) (res *imgroupmembermod.ImGroupMemberInfo) {
if item.ID.IsZero() {
return
}
// 组装返回数据
res = &imgroupmembermod.ImGroupMemberInfo{
ID: item.ID,
Uid: item.Uid,
Price: item.Price,
CreatedAt: item.CreatedAt,
}
return
}
+89
View File
@@ -0,0 +1,89 @@
package imgroupmemberdata
import (
"time"
"91porn-server/common/cachev2"
"91porn-server/common/db"
"91porn-server/models"
"91porn-server/models/v/imgroupmembermod"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
)
type ListRes struct {
List []imgroupmembermod.ImGroupMember
Count int64
HasNext bool
}
// GetListFromCache 从缓存获取列表数据
func GetListFromCache(cond bson.M, skip, limit int64, sort bson.D) ([]imgroupmembermod.ImGroupMember, int64, bool, error) {
var data ListRes
_, err := cachev2.Classes().CacheTime(10*time.Minute).AutoListKey(models.ImGroupMember).ResBind(&data).Cache(GetListData, cond, skip, limit, sort)
return data.List, data.Count, data.HasNext, err
}
// GetListData 获取列表数据并组装适合缓存格式返回
func GetListData(cond bson.M, skip, limit int64, sort bson.D) (res ListRes, err error) {
res.List, res.Count, res.HasNext, err = imgroupmembermod.GetList(cond, skip, limit, sort)
return
}
// GetInfoFromCache 获取数据详情
func GetInfoFromCache(id primitive.ObjectID) (res imgroupmembermod.ImGroupMember, err error) {
_, err = cachev2.Classes().CacheTime(30*time.Minute).AutoInfoKey(models.ImGroupMember, id.Hex()).ResBind(&res).Cache(imgroupmembermod.GetInfo, id)
return
}
// GetAllFromCache 获取所有数据
func GetAllFromCache(cond bson.M, sort bson.D) (res []imgroupmembermod.ImGroupMember, err error) {
_, err = cachev2.Classes().CacheTime(30*time.Minute).AutoListKey(models.ImGroupMember+"-all").ResBind(&res).Cache(imgroupmembermod.GetAll, cond, sort)
return
}
// InsertData 插入数据
func InsertData(t *db.MongoTool, data imgroupmembermod.ImGroupMember) (primitive.ObjectID, error) {
newID, err := imgroupmembermod.Insert(t, data)
if err != nil {
return newID, err
}
// 清除缓存数据
_, err = cachev2.Classes().Table(models.ImGroupMember).AutoClear(true, nil)
if err != nil {
return newID, err
}
return newID, nil
}
// UpdateData 更新数据
func UpdateData(t *db.MongoTool, id string, data map[string]interface{}) (int64, error) {
objID, err := primitive.ObjectIDFromHex(id)
if err != nil {
return 0, err
}
affect, err := imgroupmembermod.UpdateByID(t, objID, data)
if err != nil {
return 0, err
}
// 清理缓存
_, _ = cachev2.Classes().Table(models.ImGroupMember).AutoClear(true, &id)
return affect, err
}
// DeleteData 删除数据
func DeleteData(t *db.MongoTool, id primitive.ObjectID) (err error) {
err = imgroupmembermod.DeleteByID(t, id)
if err != nil {
return
}
// 清理缓存
all := "*"
_, _ = cachev2.Classes().Table(models.ImGroupMember).AutoClear(true, &all)
return
}
+52
View File
@@ -0,0 +1,52 @@
package immessagedata
import (
"91porn-server/app/service/vidhelpser"
"91porn-server/models/v/immessagemod"
"91porn-server/models/v/vidmod"
)
// FormatAppDataList 格式化app列表数据
func FormatAppDataList(origin []immessagemod.ImMessage) (res []*immessagemod.ImMessageInfo) {
res = make([]*immessagemod.ImMessageInfo, len(origin))
if len(origin) == 0 {
return
}
// 获取用户数据
uids := []uint64{}
for _, item := range origin {
uids = append(uids, item.Uid)
}
userMap := vidhelpser.GetSimpleUserMapNoUID(uids)
// 组装返回数据
for i, item := range origin {
res[i] = FormatAppData(item, userMap)
}
return
}
// FormatAppData 格式化app数据
func FormatAppData(item immessagemod.ImMessage, userMap map[uint64]*vidmod.Publisher) (res *immessagemod.ImMessageInfo) {
if item.ID.IsZero() {
return
}
// 组装返回数据
res = &immessagemod.ImMessageInfo{
ID: item.ID,
GroupId: item.GroupId,
Uid: item.Uid,
Content: item.Content,
Image: item.Image,
CreatedAt: item.CreatedAt,
}
if userMap != nil {
user, ok := userMap[item.Uid]
if ok && user != nil {
res.Name = user.Name
res.Gender = user.Gender
res.Portrait = user.Portrait
}
}
return
}
+89
View File
@@ -0,0 +1,89 @@
package immessagedata
import (
"time"
"91porn-server/common/cachev2"
"91porn-server/common/db"
"91porn-server/models"
"91porn-server/models/v/immessagemod"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
)
type ListRes struct {
List []immessagemod.ImMessage
Count int64
HasNext bool
}
// GetListFromCache 从缓存获取列表数据
func GetListFromCache(cond bson.M, skip, limit int64, sort bson.D) ([]immessagemod.ImMessage, int64, bool, error) {
var data ListRes
_, err := cachev2.Classes().CacheTime(10*time.Minute).AutoListKey(models.ImMessage).ResBind(&data).Cache(GetListData, cond, skip, limit, sort)
return data.List, data.Count, data.HasNext, err
}
// GetListData 获取列表数据并组装适合缓存格式返回
func GetListData(cond bson.M, skip, limit int64, sort bson.D) (res ListRes, err error) {
res.List, res.Count, res.HasNext, err = immessagemod.GetList(cond, skip, limit, sort)
return
}
// GetInfoFromCache 获取数据详情
func GetInfoFromCache(id primitive.ObjectID) (res immessagemod.ImMessage, err error) {
_, err = cachev2.Classes().CacheTime(30*time.Minute).AutoInfoKey(models.ImMessage, id.Hex()).ResBind(&res).Cache(immessagemod.GetInfo, id)
return
}
// GetAllFromCache 获取所有数据
func GetAllFromCache(cond bson.M, sort bson.D) (res []immessagemod.ImMessage, err error) {
_, err = cachev2.Classes().CacheTime(30*time.Minute).AutoListKey(models.ImMessage+"-all").ResBind(&res).Cache(immessagemod.GetAll, cond, sort)
return
}
// InsertData 插入数据
func InsertData(t *db.MongoTool, data immessagemod.ImMessage) (primitive.ObjectID, error) {
newID, err := immessagemod.Insert(t, data)
if err != nil {
return newID, err
}
// 清除缓存数据
_, err = cachev2.Classes().Table(models.ImMessage).AutoClear(true, nil)
if err != nil {
return newID, err
}
return newID, nil
}
// UpdateData 更新数据
func UpdateData(t *db.MongoTool, id string, data map[string]interface{}) (int64, error) {
objID, err := primitive.ObjectIDFromHex(id)
if err != nil {
return 0, err
}
affect, err := immessagemod.UpdateByID(t, objID, data)
if err != nil {
return 0, err
}
// 清理缓存
_, _ = cachev2.Classes().Table(models.ImMessage).AutoClear(true, &id)
return affect, err
}
// DeleteData 删除数据
func DeleteData(t *db.MongoTool, id primitive.ObjectID) (err error) {
err = immessagemod.DeleteByID(t, id)
if err != nil {
return
}
// 清理缓存
all := "*"
_, _ = cachev2.Classes().Table(models.ImMessage).AutoClear(true, &all)
return
}
+116
View File
@@ -0,0 +1,116 @@
package mediabookshelfdata
import (
"91porn-server/models/v/mediabookshelfmod"
"91porn-server/models/v/mediamod"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/mongo/options"
"time"
)
// AppData 需要组装返回的数据
type AppData struct {
BaseInfo *mediabookshelfmod.MediaBookshelfInfo `json:"baseInfo"` // 基础信息
}
// FormatAppDataList 格式化app列表数据
func FormatAppDataList(origin []mediabookshelfmod.MediaBookshelf) (res []AppData) {
res = make([]AppData, len(origin))
if len(origin) == 0 {
return
}
// 组装返回数据
for i, item := range origin {
res[i] = FormatAppData(item)
}
return
}
// FormatAppData 格式化app数据
func FormatAppData(item mediabookshelfmod.MediaBookshelf) (res AppData) {
if item.ID.IsZero() {
return
}
// 组装返回数据
res.BaseInfo = &mediabookshelfmod.MediaBookshelfInfo{
ID: item.ID,
Name: item.Name,
UID: item.UID,
ReadAt: item.ReadAt,
CreatedAt: item.CreatedAt,
UpdateTime: item.UpdateTime,
}
return
}
// AppSimpleData 仅返回基础数据
type AppSimpleData *mediabookshelfmod.MediaBookshelfInfo
// FormatAppSimpleDataList 格式化app列表数据
func FormatAppSimpleDataList(origin []mediabookshelfmod.MediaBookshelf, skip, limit int64, sort bson.D) (res []AppSimpleData) {
res = make([]AppSimpleData, len(origin))
if len(origin) == 0 {
return
}
var mids []primitive.ObjectID
for i := range origin {
mids = append(mids, origin[i].MID)
}
filter := bson.M{"_id": bson.M{"$in": mids}}
opts := options.Find().SetSkip(skip).SetLimit(limit)
if len(sort) > 0 {
opts = opts.SetSort(sort)
}
media, err := mediamod.QueryMediaByCond(filter, opts)
if err != nil {
return
}
m := make(map[primitive.ObjectID]*mediamod.Media)
for i := range media {
m[media[i].ID] = media[i]
}
// 组装返回数据
for i, item := range origin {
res[i] = FormatAppSimpleData(item, m[item.MID])
}
return
}
// FormatAppSimpleData 格式化app数据
func FormatAppSimpleData(item mediabookshelfmod.MediaBookshelf, media *mediamod.Media) (res AppSimpleData) {
if item.ID.IsZero() {
return
}
// 组装返回数据
res = &mediabookshelfmod.MediaBookshelfInfo{
ID: item.MID,
//MID: item.MID,
Name: media.Title,
VerticalCover: media.VerticalCover,
TotalEpisode: media.TotalEpisode,
CurrentEpisode: media.CurrentEpisode,
MediaType: media.MediaType,
MediaSubType: int(media.MediaSubType),
UpdateStatus: media.UpdateStatus,
CountBrowse: media.CountBrowse,
Permission: media.Permission,
Price: media.Price,
UID: item.UID,
ReadAt: item.ReadAt,
CreatedAt: item.CreatedAt,
UpdateTime: item.UpdateTime,
}
if time.Now().Add(-time.Hour*24*7).Unix() < media.ContentUpdateTime.Unix() {
res.IsNew = true
}
return
}
+110
View File
@@ -0,0 +1,110 @@
package mediabookshelfdata
import (
"fmt"
"time"
"91porn-server/common/cachev2"
"91porn-server/common/db"
"91porn-server/models"
"91porn-server/models/v/mediabookshelfmod"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
)
func getKey(uid uint64) string {
return fmt.Sprintf("%s-%d", models.MediaBookshelf, uid)
}
type ListRes struct {
List []mediabookshelfmod.MediaBookshelf
Count int64
HasNext bool
}
// GetListFromCache 从缓存获取列表数据
func GetListFromCache(uid uint64, cond bson.M, skip, limit int64, sort bson.D) ([]mediabookshelfmod.MediaBookshelf, int64, bool, error) {
var data ListRes
_, err := cachev2.Classes().CacheTime(10*time.Minute).AutoListKey(getKey(uid)).ResBind(&data).Cache(GetListData, cond, skip, limit, sort)
return data.List, data.Count, data.HasNext, err
}
// GetListData 获取列表数据并组装适合缓存格式返回
func GetListData(cond bson.M, skip, limit int64, sort bson.D) (res ListRes, err error) {
res.List, res.Count, res.HasNext, err = mediabookshelfmod.GetList(cond, skip, limit, sort)
return
}
func GetInfoByCond(cond bson.M) (mediabookshelfmod.MediaBookshelf, error) {
return mediabookshelfmod.GetInfoByCond(cond)
}
// InsertData 插入数据
func InsertData(t *db.MongoTool, uid uint64, data mediabookshelfmod.MediaBookshelf) (primitive.ObjectID, error) {
newID, err := mediabookshelfmod.Insert(t, data)
if err != nil {
return newID, err
}
// 清除缓存数据
_, err = cachev2.Classes().Table(getKey(uid)).AutoClear(true, nil)
if err != nil {
return newID, err
}
return newID, nil
}
// UpdateData 更新数据
func UpdateData(t *db.MongoTool, id string, data map[string]interface{}) (int64, error) {
objID, err := primitive.ObjectIDFromHex(id)
if err != nil {
return 0, err
}
affect, err := mediabookshelfmod.UpdateByID(t, objID, data)
if err != nil {
return 0, err
}
// 清理缓存
_, _ = cachev2.Classes().Table(models.MediaBookshelf).AutoClear(true, nil)
return affect, err
}
// DeleteDataByCond 删除数据
func DeleteDataByCond(t *db.MongoTool, uid uint64, cond bson.M) (err error) {
err = mediabookshelfmod.DeleteByCond(t, cond)
if err != nil {
return
}
// 清理缓存
_, _ = cachev2.Classes().Table(getKey(uid)).AutoClear(true, nil)
return
}
// DeleteDataByIds 删除数据
func DeleteDataByIds(t *db.MongoTool, uid uint64, ids []primitive.ObjectID) (err error) {
err = mediabookshelfmod.DeleteByIDS(t, uid, ids)
if err != nil {
return
}
// 清理缓存
_, _ = cachev2.Classes().Table(getKey(uid)).AutoClear(true, nil)
return
}
// DeleteData 删除数据
func DeleteData(t *db.MongoTool, id primitive.ObjectID) (err error) {
err = mediabookshelfmod.DeleteByID(t, id)
if err != nil {
return
}
// 清理缓存
all := "*"
_, _ = cachev2.Classes().Table(models.MediaBookshelf).AutoClear(true, &all)
return
}
+37
View File
@@ -0,0 +1,37 @@
package mediacontentdata
import (
"time"
"91porn-server/common/cachev2"
"91porn-server/models"
"91porn-server/models/v/mediacontentmod"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
)
type ListRes struct {
List []mediacontentmod.MediaContent
Count int64
HasNext bool
}
// GetListFromCache 从缓存获取列表数据
func GetListFromCache(cond bson.M, skip, limit int64, sort bson.D) ([]mediacontentmod.MediaContent, int64, bool, error) {
var data ListRes
_, err := cachev2.Classes().CacheTime(10*time.Minute).AutoListKey(models.MediaContent).ResBind(&data).Cache(GetListData, cond, skip, limit, sort)
return data.List, data.Count, data.HasNext, err
}
// GetListData 获取列表数据并组装适合缓存格式返回
func GetListData(cond bson.M, skip, limit int64, sort bson.D) (res ListRes, err error) {
res.List, res.Count, res.HasNext, err = mediacontentmod.GetList(cond, skip, limit, sort)
return
}
// GetInfoFromCache 获取数据详情
func GetInfoFromCache(id primitive.ObjectID) (res mediacontentmod.MediaContent, err error) {
_, err = cachev2.Classes().CacheTime(10*time.Minute).AutoInfoKey(models.MediaContent, id.Hex()).ResBind(&res).Cache(mediacontentmod.GetInfo, id, true)
return
}
+37
View File
@@ -0,0 +1,37 @@
package mediadata
import (
"time"
"91porn-server/common/cachev2"
"91porn-server/models"
"91porn-server/models/v/mediamod"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
)
type ListRes struct {
List []*mediamod.Media
Count int64
HasNext bool
}
// GetListFromCache 从缓存获取列表数据
func GetListFromCache(cond bson.M, skip, limit int64, sort bson.D) ([]*mediamod.Media, bool, error) {
var data ListRes
_, err := cachev2.Classes().CacheTime(10*time.Minute).AutoListKey(models.Media).ResBind(&data).Cache(GetListData, cond, skip, limit, sort)
return data.List, data.HasNext, err
}
// GetListData 获取列表数据并组装适合缓存格式返回
func GetListData(cond bson.M, skip, limit int64, sort bson.D) (res ListRes, err error) {
res.List, res.HasNext, err = mediamod.GetList(cond, skip, limit, sort)
return
}
// GetInfoFromCache 获取数据详情
func GetInfoFromCache(id primitive.ObjectID) (res mediamod.Media, err error) {
_, err = cachev2.Classes().CacheTime(5*time.Minute).AutoInfoKey(models.Media, id.Hex()).ResBind(&res).Cache(mediamod.GetInfo, id)
return
}
+94
View File
@@ -0,0 +1,94 @@
package mediatagdata
import (
"time"
"91porn-server/common/cachev2"
"91porn-server/common/db"
"91porn-server/models"
"91porn-server/models/v/mediatagmod"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
)
type ListRes struct {
List []mediatagmod.MediaTag
Count int64
HasNext bool
}
// GetTagIdsByNameFromCache 通过名字获取标签id
func GetTagIdsByNameFromCache(name string) (ids []primitive.ObjectID, err error) {
_, err = cachev2.Classes().CacheTime(300*time.Second).AutoListKey(models.MediaTag).ResBind(&ids).Cache(mediatagmod.FindTagIdsByName, name)
return
}
// GetTagByNameFromCache 通过名字获取标签id
func GetTagByNameFromCache(name string) (tag mediatagmod.MediaTag, err error) {
_, err = cachev2.Classes().CacheTime(300*time.Second).AutoListKey(models.MediaTag).ResBind(&tag).Cache(mediatagmod.FindOneTagByName, name)
return tag, err
}
// GetListFromCache 从缓存获取列表数据
func GetListFromCache(cond bson.M, skip, limit int64, sort bson.D) ([]mediatagmod.MediaTag, int64, bool, error) {
var data ListRes
_, err := cachev2.Classes().CacheTime(3600*time.Second).AutoListKey(models.MediaTag).ResBind(&data).Cache(GetListData, cond, skip, limit, sort)
return data.List, data.Count, data.HasNext, err
}
// GetListData 获取列表数据并组装适合缓存格式返回
func GetListData(cond bson.M, skip, limit int64, sort bson.D) (res ListRes, err error) {
res.List, res.Count, res.HasNext, err = mediatagmod.GetList(cond, skip, limit, sort)
return
}
// GetInfoFromCache 获取数据详情
func GetInfoFromCache(id primitive.ObjectID) (res mediatagmod.MediaTag, err error) {
_, err = cachev2.Classes().CacheTime(7200*time.Second).AutoInfoKey(models.MediaTag, id.Hex()).ResBind(&res).Cache(mediatagmod.GetInfo, id)
return
}
// InsertData 插入数据
func InsertData(t *db.MongoTool, data mediatagmod.MediaTag) (primitive.ObjectID, error) {
newID, err := mediatagmod.Insert(t, data)
if err != nil {
return newID, err
}
// 清除缓存数据
_, err = cachev2.Classes().Table(models.MediaTag).AutoClear(true, nil)
if err != nil {
return newID, err
}
return newID, nil
}
// UpdateData 更新数据
func UpdateData(t *db.MongoTool, id string, data map[string]interface{}) (int64, error) {
objID, err := primitive.ObjectIDFromHex(id)
if err != nil {
return 0, err
}
affect, err := mediatagmod.UpdateByID(t, objID, data)
if err != nil {
return 0, err
}
// 清理缓存
_, _ = cachev2.Classes().Table(models.MediaTag).AutoClear(true, &id)
return affect, err
}
// DeleteData 删除数据
func DeleteData(t *db.MongoTool, id primitive.ObjectID) (err error) {
err = mediatagmod.DeleteByID(t, id)
if err != nil {
return
}
// 清理缓存
all := "*"
_, _ = cachev2.Classes().Table(models.MediaTag).AutoClear(true, &all)
return
}
+82
View File
@@ -0,0 +1,82 @@
package mediatagdimensiondata
import (
"time"
"91porn-server/common/cachev2"
"91porn-server/common/db"
"91porn-server/models"
"91porn-server/models/v/mediatagdimensionmod"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
)
type ListRes struct {
List []mediatagdimensionmod.MediaTagDimension
Count int64
HasNext bool
}
// GetListFromCache 从缓存获取列表数据
func GetListFromCache(cond bson.M, skip, limit int64, sort bson.D) ([]mediatagdimensionmod.MediaTagDimension, int64, bool, error) {
var data ListRes
_, err := cachev2.Classes().CacheTime(3600*time.Second).AutoListKey(models.MediaTagDimension).ResBind(&data).Cache(GetListData, cond, skip, limit, sort)
return data.List, data.Count, data.HasNext, err
}
// GetListData 获取列表数据并组装适合缓存格式返回
func GetListData(cond bson.M, skip, limit int64, sort bson.D) (res ListRes, err error) {
res.List, res.Count, res.HasNext, err = mediatagdimensionmod.GetList(cond, skip, limit, sort)
return
}
// GetInfoFromCache 获取数据详情
func GetInfoFromCache(id primitive.ObjectID) (res mediatagdimensionmod.MediaTagDimension, err error) {
_, err = cachev2.Classes().CacheTime(7200*time.Second).AutoInfoKey(models.MediaTagDimension, id.Hex()).ResBind(&res).Cache(mediatagdimensionmod.GetInfo, id)
return
}
// InsertData 插入数据
func InsertData(t *db.MongoTool, data mediatagdimensionmod.MediaTagDimension) (primitive.ObjectID, error) {
newID, err := mediatagdimensionmod.Insert(t, data)
if err != nil {
return newID, err
}
// 清除缓存数据
_, err = cachev2.Classes().Table(models.MediaTagDimension).AutoClear(true, nil)
if err != nil {
return newID, err
}
return newID, nil
}
// UpdateData 更新数据
func UpdateData(t *db.MongoTool, id string, data map[string]interface{}) (int64, error) {
objID, err := primitive.ObjectIDFromHex(id)
if err != nil {
return 0, err
}
affect, err := mediatagdimensionmod.UpdateByID(t, objID, data)
if err != nil {
return 0, err
}
// 清理缓存
_, _ = cachev2.Classes().Table(models.MediaTagDimension).AutoClear(true, &id)
return affect, err
}
// DeleteData 删除数据
func DeleteData(t *db.MongoTool, id primitive.ObjectID) (err error) {
err = mediatagdimensionmod.DeleteByID(t, id)
if err != nil {
return
}
// 清理缓存
all := "*"
_, _ = cachev2.Classes().Table(models.MediaTagDimension).AutoClear(true, &all)
return
}
+74
View File
@@ -0,0 +1,74 @@
package nakedchatdata
import (
"91porn-server/models/v/nakedchatmod"
)
// FormatAppDataList 格式化app列表数据
func FormatAppDataList(origin []nakedchatmod.NakedChat) (res []*nakedchatmod.NakedChatSimple) {
res = make([]*nakedchatmod.NakedChatSimple, len(origin))
if len(origin) == 0 {
return
}
// 组装返回数据
for i, item := range origin {
res[i] = FormatAppSimpleData(item)
}
return
}
// FormatAppSimpleData 格式化app数据
func FormatAppSimpleData(item nakedchatmod.NakedChat) (res *nakedchatmod.NakedChatSimple) {
if item.ID.IsZero() {
return
}
// 组装返回数据
res = &nakedchatmod.NakedChatSimple{
ID: item.ID,
Title: item.Title,
Cover: item.Cover,
Price: item.Price,
Age: item.Age,
Weight: item.Weight,
Height: item.Height,
Cup: item.Cup,
SaleNum: item.SaleNum + item.FakeSaleNum,
CreatedAt: item.CreatedAt,
UpdatedAt: item.UpdatedAt,
}
return
}
// FormatAppData 格式化app数据
func FormatAppData(item nakedchatmod.NakedChat) (res *nakedchatmod.NakedChatInfo) {
if item.ID.IsZero() {
return
}
// 组装返回数据
res = &nakedchatmod.NakedChatInfo{
ID: item.ID,
Title: item.Title,
Cover: item.Cover,
Price: item.Price,
Options: item.Options,
Images: item.Images,
Video: item.Video,
Contact: item.Contact,
Age: item.Age,
Weight: item.Weight,
Height: item.Height,
Cup: item.Cup,
SaleNum: item.SaleNum + item.FakeSaleNum,
BusinessHours: item.BusinessHours,
Summary: item.Summary,
CreatedAt: item.CreatedAt,
UpdatedAt: item.UpdatedAt,
}
return
}
+89
View File
@@ -0,0 +1,89 @@
package nakedchatdata
import (
"time"
"91porn-server/common/cachev2"
"91porn-server/common/db"
"91porn-server/models"
"91porn-server/models/v/nakedchatmod"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
)
type ListRes struct {
List []nakedchatmod.NakedChat
Count int64
HasNext bool
}
// GetListFromCache 从缓存获取列表数据
func GetListFromCache(cond bson.M, skip, limit int64, sort bson.D) ([]nakedchatmod.NakedChat, int64, bool, error) {
var data ListRes
_, err := cachev2.Classes().CacheTime(10*time.Minute).AutoListKey(models.NakedChat).ResBind(&data).Cache(GetListData, cond, skip, limit, sort)
return data.List, data.Count, data.HasNext, err
}
// GetListData 获取列表数据并组装适合缓存格式返回
func GetListData(cond bson.M, skip, limit int64, sort bson.D) (res ListRes, err error) {
res.List, res.Count, res.HasNext, err = nakedchatmod.GetList(cond, skip, limit, sort)
return
}
// GetInfoFromCache 获取数据详情
func GetInfoFromCache(id primitive.ObjectID) (res nakedchatmod.NakedChat, err error) {
_, err = cachev2.Classes().CacheTime(30*time.Minute).AutoInfoKey(models.NakedChat, id.Hex()).ResBind(&res).Cache(nakedchatmod.GetInfo, id)
return
}
// GetAllFromCache 获取所有数据
func GetAllFromCache(cond bson.M, sort bson.D) (res []nakedchatmod.NakedChat, err error) {
_, err = cachev2.Classes().CacheTime(30*time.Minute).AutoListKey(models.NakedChat+"-all").ResBind(&res).Cache(nakedchatmod.GetAll, cond, sort)
return
}
// InsertData 插入数据
func InsertData(t *db.MongoTool, data nakedchatmod.NakedChat) (primitive.ObjectID, error) {
newID, err := nakedchatmod.Insert(t, data)
if err != nil {
return newID, err
}
// 清除缓存数据
_, err = cachev2.Classes().Table(models.NakedChat).AutoClear(true, nil)
if err != nil {
return newID, err
}
return newID, nil
}
// UpdateData 更新数据
func UpdateData(t *db.MongoTool, id string, data map[string]interface{}) (int64, error) {
objID, err := primitive.ObjectIDFromHex(id)
if err != nil {
return 0, err
}
affect, err := nakedchatmod.UpdateByID(t, objID, data)
if err != nil {
return 0, err
}
// 清理缓存
_, _ = cachev2.Classes().Table(models.NakedChat).AutoClear(true, &id)
return affect, err
}
// DeleteData 删除数据
func DeleteData(t *db.MongoTool, id primitive.ObjectID) (err error) {
err = nakedchatmod.DeleteByID(t, id)
if err != nil {
return
}
// 清理缓存
all := "*"
_, _ = cachev2.Classes().Table(models.NakedChat).AutoClear(true, &all)
return
}
+44
View File
@@ -0,0 +1,44 @@
package nakedchatorderdata
import (
"91porn-server/models/v/nakedchatordermod"
)
// FormatAppDataList 格式化app列表数据
func FormatAppDataList(origin []nakedchatordermod.NakedChatOrder) (res []*nakedchatordermod.NakedChatOrderInfo) {
res = make([]*nakedchatordermod.NakedChatOrderInfo, len(origin))
if len(origin) == 0 {
return
}
// 组装返回数据
for i, item := range origin {
res[i] = FormatAppData(item)
}
return
}
// FormatAppData 格式化app数据
func FormatAppData(item nakedchatordermod.NakedChatOrder) (res *nakedchatordermod.NakedChatOrderInfo) {
if item.ID.IsZero() {
return
}
// 组装返回数据
res = &nakedchatordermod.NakedChatOrderInfo{
ID: item.ID,
Nid: item.Nid,
Uid: item.Uid,
UserContact: item.UserContact,
Num: item.Num,
Price: item.Price,
Amount: item.Amount,
Remark: item.Remark,
Status: item.Status,
CreatedAt: item.CreatedAt,
UpdatedAt: item.UpdatedAt,
}
return
}
+89
View File
@@ -0,0 +1,89 @@
package nakedchatorderdata
import (
"time"
"91porn-server/common/cachev2"
"91porn-server/common/db"
"91porn-server/models"
"91porn-server/models/v/nakedchatordermod"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
)
type ListRes struct {
List []nakedchatordermod.NakedChatOrder
Count int64
HasNext bool
}
// GetListFromCache 从缓存获取列表数据
func GetListFromCache(cond bson.M, skip, limit int64, sort bson.D) ([]nakedchatordermod.NakedChatOrder, int64, bool, error) {
var data ListRes
_, err := cachev2.Classes().CacheTime(10*time.Minute).AutoListKey(models.NakedChatOrder).ResBind(&data).Cache(GetListData, cond, skip, limit, sort)
return data.List, data.Count, data.HasNext, err
}
// GetListData 获取列表数据并组装适合缓存格式返回
func GetListData(cond bson.M, skip, limit int64, sort bson.D) (res ListRes, err error) {
res.List, res.Count, res.HasNext, err = nakedchatordermod.GetList(cond, skip, limit, sort)
return
}
// GetInfoFromCache 获取数据详情
func GetInfoFromCache(id primitive.ObjectID) (res nakedchatordermod.NakedChatOrder, err error) {
_, err = cachev2.Classes().CacheTime(30*time.Minute).AutoInfoKey(models.NakedChatOrder, id.Hex()).ResBind(&res).Cache(nakedchatordermod.GetInfo, id)
return
}
// GetAllFromCache 获取所有数据
func GetAllFromCache(cond bson.M, sort bson.D) (res []nakedchatordermod.NakedChatOrder, err error) {
_, err = cachev2.Classes().CacheTime(30*time.Minute).AutoListKey(models.NakedChatOrder+"-all").ResBind(&res).Cache(nakedchatordermod.GetAll, cond, sort)
return
}
// InsertData 插入数据
func InsertData(t *db.MongoTool, data nakedchatordermod.NakedChatOrder) (primitive.ObjectID, error) {
newID, err := nakedchatordermod.Insert(t, data)
if err != nil {
return newID, err
}
// 清除缓存数据
_, err = cachev2.Classes().Table(models.NakedChatOrder).AutoClear(true, nil)
if err != nil {
return newID, err
}
return newID, nil
}
// UpdateData 更新数据
func UpdateData(t *db.MongoTool, id string, data map[string]interface{}) (int64, error) {
objID, err := primitive.ObjectIDFromHex(id)
if err != nil {
return 0, err
}
affect, err := nakedchatordermod.UpdateByID(t, objID, data)
if err != nil {
return 0, err
}
// 清理缓存
_, _ = cachev2.Classes().Table(models.NakedChatOrder).AutoClear(true, &id)
return affect, err
}
// DeleteData 删除数据
func DeleteData(t *db.MongoTool, id primitive.ObjectID) (err error) {
err = nakedchatordermod.DeleteByID(t, id)
if err != nil {
return
}
// 清理缓存
all := "*"
_, _ = cachev2.Classes().Table(models.NakedChatOrder).AutoClear(true, &all)
return
}
+85
View File
@@ -0,0 +1,85 @@
package quicksearchdata
import (
"91porn-server/models/v/quicksearchmod"
)
// AppData 需要组装返回的数据
type AppData struct {
BaseInfo *quicksearchmod.QuickSearchInfo `json:"baseInfo"` // 基础信息
}
// FormatAppDataList 格式化app列表数据
func FormatAppDataList(origin []quicksearchmod.QuickSearch) (res []AppData) {
res = make([]AppData, len(origin))
if len(origin) == 0 {
return
}
// 组装返回数据
for i, item := range origin {
res[i] = FormatAppData(item)
}
return
}
// FormatAppData 格式化app数据
func FormatAppData(item quicksearchmod.QuickSearch) (res AppData) {
if item.ID.IsZero() {
return
}
// 组装返回数据
res.BaseInfo = &quicksearchmod.QuickSearchInfo{
ID: item.ID,
Enabled: item.Enabled,
Title: item.Title,
SearchKeyword: item.SearchKeyword,
Link: item.Link,
Type: item.Type,
CreatedAt: item.CreatedAt,
UpdatedAt: item.UpdatedAt,
}
return
}
// AppSimpleData 仅返回基础数据
type AppSimpleData *quicksearchmod.QuickSearchInfo
// FormatAppSimpleDataList 格式化app列表数据
func FormatAppSimpleDataList(origin []quicksearchmod.QuickSearch) (res []AppSimpleData) {
res = make([]AppSimpleData, len(origin))
if len(origin) == 0 {
return
}
// 组装返回数据
for i, item := range origin {
res[i] = FormatAppSimpleData(item)
}
return
}
// FormatAppSimpleData 格式化app数据
func FormatAppSimpleData(item quicksearchmod.QuickSearch) (res AppSimpleData) {
if item.ID.IsZero() {
return
}
// 组装返回数据
res = &quicksearchmod.QuickSearchInfo{
ID: item.ID,
Enabled: item.Enabled,
Title: item.Title,
SearchKeyword: item.SearchKeyword,
Link: item.Link,
Type: item.Type,
CreatedAt: item.CreatedAt,
UpdatedAt: item.UpdatedAt,
}
return
}
+89
View File
@@ -0,0 +1,89 @@
package quicksearchdata
import (
"time"
"91porn-server/common/cachev2"
"91porn-server/common/db"
"91porn-server/models"
"91porn-server/models/v/quicksearchmod"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
)
type ListRes struct {
List []quicksearchmod.QuickSearch
Count int64
HasNext bool
}
// GetListFromCache 从缓存获取列表数据
func GetListFromCache(cond bson.M, skip, limit int64, sort bson.D) ([]quicksearchmod.QuickSearch, int64, bool, error) {
var data ListRes
_, err := cachev2.Classes().CacheTime(10*time.Minute).AutoListKey(models.QuickSearch).ResBind(&data).Cache(GetListData, cond, skip, limit, sort)
return data.List, data.Count, data.HasNext, err
}
// GetListData 获取列表数据并组装适合缓存格式返回
func GetListData(cond bson.M, skip, limit int64, sort bson.D) (res ListRes, err error) {
res.List, res.Count, res.HasNext, err = quicksearchmod.GetList(cond, skip, limit, sort)
return
}
// GetInfoFromCache 获取数据详情
func GetInfoFromCache(id primitive.ObjectID) (res quicksearchmod.QuickSearch, err error) {
_, err = cachev2.Classes().CacheTime(30*time.Minute).AutoInfoKey(models.QuickSearch, id.Hex()).ResBind(&res).Cache(quicksearchmod.GetInfo, id)
return
}
// GetAllFromCache 获取所有数据
func GetAllFromCache(cond bson.M) (res []quicksearchmod.QuickSearch, err error) {
_, err = cachev2.Classes().CacheTime(3*time.Minute).AutoListKey(models.QuickSearch+"-all").ResBind(&res).Cache(quicksearchmod.GetAll, cond)
return
}
// InsertData 插入数据
func InsertData(t *db.MongoTool, data quicksearchmod.QuickSearch) (primitive.ObjectID, error) {
newID, err := quicksearchmod.Insert(t, data)
if err != nil {
return newID, err
}
// 清除缓存数据
_, err = cachev2.Classes().Table(models.QuickSearch).AutoClear(true, nil)
if err != nil {
return newID, err
}
return newID, nil
}
// UpdateData 更新数据
func UpdateData(t *db.MongoTool, id string, data map[string]interface{}) (int64, error) {
objID, err := primitive.ObjectIDFromHex(id)
if err != nil {
return 0, err
}
affect, err := quicksearchmod.UpdateByID(t, objID, data)
if err != nil {
return 0, err
}
// 清理缓存
_, _ = cachev2.Classes().Table(models.QuickSearch).AutoClear(true, &id)
return affect, err
}
// DeleteData 删除数据
func DeleteData(t *db.MongoTool, id primitive.ObjectID) (err error) {
err = quicksearchmod.DeleteByID(t, id)
if err != nil {
return
}
// 清理缓存
all := "*"
_, _ = cachev2.Classes().Table(models.QuickSearch).AutoClear(true, &all)
return
}
+89
View File
@@ -0,0 +1,89 @@
package signrecorddata
import (
"91porn-server/models/v/signrecordmod"
)
// AppData 需要组装返回的数据
type AppData struct {
BaseInfo *signrecordmod.SignRecordInfo `json:"baseInfo"` // 基础信息
}
// FormatAppDataList 格式化app列表数据
func FormatAppDataList(origin []signrecordmod.SignRecord) (res []AppData) {
res = make([]AppData, len(origin))
if len(origin) == 0 {
return
}
// 组装返回数据
for i, item := range origin {
res[i] = FormatAppData(item)
}
return
}
// FormatAppData 格式化app数据
func FormatAppData(item signrecordmod.SignRecord) (res AppData) {
if item.ID.IsZero() {
return
}
// 组装返回数据
res.BaseInfo = &signrecordmod.SignRecordInfo{
ID: item.ID,
PID: item.PID,
UID: item.UID,
TotalDays: item.TotalDays,
CurrentSignDays: item.CurrentSignDays,
ForgetSignDays: item.ForgetSignDays,
RenewalSignDays: item.RenewalSignDays,
SignTime: item.SignTime,
CreatedAt: item.CreatedAt,
UpdateTime: item.UpdateTime,
}
return
}
// AppSimpleData 仅返回基础数据
type AppSimpleData *signrecordmod.SignRecordInfo
// FormatAppSimpleDataList 格式化app列表数据
func FormatAppSimpleDataList(origin []signrecordmod.SignRecord) (res []AppSimpleData) {
res = make([]AppSimpleData, len(origin))
if len(origin) == 0 {
return
}
// 组装返回数据
for i, item := range origin {
res[i] = FormatAppSimpleData(item)
}
return
}
// FormatAppSimpleData 格式化app数据
func FormatAppSimpleData(item signrecordmod.SignRecord) (res AppSimpleData) {
if item.ID.IsZero() {
return
}
// 组装返回数据
res = &signrecordmod.SignRecordInfo{
ID: item.ID,
PID: item.PID,
UID: item.UID,
TotalDays: item.TotalDays,
CurrentSignDays: item.CurrentSignDays,
ForgetSignDays: item.ForgetSignDays,
RenewalSignDays: item.RenewalSignDays,
SignTime: item.SignTime,
CreatedAt: item.CreatedAt,
UpdateTime: item.UpdateTime,
}
return
}
+88
View File
@@ -0,0 +1,88 @@
package signrecorddata
import (
"91porn-server/common/cachev2"
"91porn-server/common/db"
"91porn-server/models"
"91porn-server/models/v/signrecordmod"
"time"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
)
type ListRes struct {
List []signrecordmod.SignRecord
Count int64
HasNext bool
}
// GetListFromCache 从缓存获取列表数据
func GetListFromCache(cond bson.M, skip, limit int64, sort bson.D) ([]signrecordmod.SignRecord, int64, bool, error) {
var data ListRes
_, err := cachev2.Classes().CacheTime(10*time.Minute).AutoListKey(models.SignRecord).ResBind(&data).Cache(GetListData, cond, skip, limit, sort)
return data.List, data.Count, data.HasNext, err
}
// GetListData 获取列表数据并组装适合缓存格式返回
func GetListData(cond bson.M, skip, limit int64, sort bson.D) (res ListRes, err error) {
res.List, res.Count, res.HasNext, err = signrecordmod.GetList(cond, skip, limit, sort)
return
}
// GetInfoFromCache 获取数据详情
func GetInfoFromCache(id primitive.ObjectID) (res signrecordmod.SignRecord, err error) {
_, err = cachev2.Classes().CacheTime(30*time.Minute).AutoInfoKey(models.SignRecord, id.Hex()).ResBind(&res).Cache(signrecordmod.GetInfo, id)
return
}
// GetAllFromCache 获取所有数据
func GetAllFromCache(cond bson.M, sort bson.D) (res []signrecordmod.SignRecord, err error) {
_, err = cachev2.Classes().CacheTime(30*time.Minute).AutoListKey(models.SignRecord+"-all").ResBind(&res).Cache(signrecordmod.GetAll, cond, sort)
return
}
// InsertData 插入数据
func InsertData(t *db.MongoTool, data signrecordmod.SignRecord) (primitive.ObjectID, error) {
newID, err := signrecordmod.Insert(t, data)
if err != nil {
return newID, err
}
// 清除缓存数据
_, err = cachev2.Classes().Table(models.SignRecord).AutoClear(true, nil)
if err != nil {
return newID, err
}
return newID, nil
}
// UpdateData 更新数据
func UpdateData(t *db.MongoTool, id string, data map[string]interface{}) (int64, error) {
objID, err := primitive.ObjectIDFromHex(id)
if err != nil {
return 0, err
}
affect, err := signrecordmod.UpdateByID(t, objID, data)
if err != nil {
return 0, err
}
// 清理缓存
_, _ = cachev2.Classes().Table(models.SignRecord).AutoClear(true, &id)
return affect, err
}
// DeleteData 删除数据
func DeleteData(t *db.MongoTool, id primitive.ObjectID) (err error) {
err = signrecordmod.DeleteByID(t, id)
if err != nil {
return
}
// 清理缓存
all := "*"
_, _ = cachev2.Classes().Table(models.SignRecord).AutoClear(true, &all)
return
}
+161
View File
@@ -0,0 +1,161 @@
package sysconfdata
import (
"strconv"
"time"
"91porn-server/common/cachev2"
"91porn-server/common/db"
"91porn-server/common/localcache"
"91porn-server/models"
"91porn-server/models/v/sysconfmod"
"go.mongodb.org/mongo-driver/bson/primitive"
)
// GetIntsFromSharedCache reads integer settings from the shared cache without
// the process-local one-minute layer, so management changes take effect at once.
func GetIntsFromSharedCache(defaults map[sysconfmod.VCode]int) (map[sysconfmod.VCode]int, error) {
configure, err := getAllFromSharedCache()
if err != nil {
return nil, err
}
values := make(map[sysconfmod.VCode]int, len(defaults))
for code, fallback := range defaults {
values[code] = fallback
if raw, ok := configure[string(code)]; ok {
if parsed, parseErr := strconv.Atoi(raw); parseErr == nil {
values[code] = parsed
}
}
}
return values, nil
}
const (
tmpLocalCacheKey = "AllSysConfTmpKey"
// DefaultTotalWatchCount preserves the legacy free-trial behavior when the
// shared configuration is absent or temporarily unavailable.
DefaultTotalWatchCount uint64 = 3
)
// GetAllFromCache 获取全部配置项
func GetAllFromCache() (res sysconfmod.ConfMap, err error) {
// 频繁访问 从本地进程内缓存中获取,对象不存在则从redis中获取
r, _ := localcache.C.Get(tmpLocalCacheKey)
if r != nil {
return r.(sysconfmod.ConfMap), nil
}
defer func() {
localcache.C.Set(tmpLocalCacheKey, res, 1*time.Minute)
}()
return getAllFromSharedCache()
}
// GetTotalWatchCount returns the configured non-VIP free-trial count from the
// existing bounded configuration cache and falls back to the legacy default.
func GetTotalWatchCount() uint64 {
configure, err := GetAllFromCache()
if err != nil {
return DefaultTotalWatchCount
}
return totalWatchCount(configure)
}
func totalWatchCount(configure sysconfmod.ConfMap) uint64 {
raw, ok := configure[string(sysconfmod.VCodeTotalWatchCount)]
if !ok {
return DefaultTotalWatchCount
}
value, err := strconv.ParseUint(raw, 10, 64)
if err != nil {
return DefaultTotalWatchCount
}
return value
}
func getAllFromSharedCache() (res sysconfmod.ConfMap, err error) {
_, err = cachev2.Classes().CacheTime(5 * time.Minute).AutoListKey(models.SysConf).ResBind(&res).Cache(sysconfmod.GetAllConfig)
return
}
// GetBoolFromSharedCache 绕过进程内缓存读取布尔配置,后台修改并清理 Redis 后可立即生效。
func GetBoolFromSharedCache(code sysconfmod.VCode) (bool, error) {
values, err := GetBoolsFromSharedCache(code)
if err != nil {
return false, err
}
return values[code], nil
}
// GetBoolsFromSharedCache reads several switches from one shared-cache
// snapshot. This keeps request paths that need related switches from fetching
// and decoding the same configuration map repeatedly.
func GetBoolsFromSharedCache(codes ...sysconfmod.VCode) (map[sysconfmod.VCode]bool, error) {
configure, err := getAllFromSharedCache()
if err != nil {
return nil, err
}
values := make(map[sysconfmod.VCode]bool, len(codes))
for _, code := range codes {
if _, exists := configure[string(code)]; !exists {
continue
}
values[code] = configure.GetBool(code)
}
return values, nil
}
func clearAllCache() error {
localcache.C.Delete(tmpLocalCacheKey)
_, err := cachev2.Classes().AutoListKey(models.SysConf).DeleteCurrent()
return err
}
// GetByGpCodeFromCache 获取分组配置数据
func GetByGpCodeFromCache(code sysconfmod.GPCode) (res sysconfmod.ConfMap, err error) {
_, err = cachev2.Classes().CacheTime(30*time.Minute).AutoListKey(models.SysConf).ResBind(&res).Cache(sysconfmod.GetByGpCode, code)
return
}
// InsertData 插入数据
func InsertData(t *db.MongoTool, data sysconfmod.SysConf) (primitive.ObjectID, error) {
newID, err := sysconfmod.Insert(t, data)
if err != nil {
return newID, err
}
// 清除缓存数据
if err = clearAllCache(); err != nil {
return newID, err
}
return newID, nil
}
// UpdateData 更新数据
func UpdateData(t *db.MongoTool, id string, data map[string]interface{}) (int64, error) {
objID, err := primitive.ObjectIDFromHex(id)
if err != nil {
return 0, err
}
affect, err := sysconfmod.UpdateByID(t, objID, data)
if err != nil {
return 0, err
}
if err = clearAllCache(); err != nil {
return affect, err
}
return affect, nil
}
// DeleteData 删除数据
func DeleteData(t *db.MongoTool, id primitive.ObjectID) (err error) {
err = sysconfmod.DeleteByID(t, id)
if err != nil {
return
}
// 清理缓存
return clearAllCache()
}
+27
View File
@@ -0,0 +1,27 @@
package sysconfdata
import (
"testing"
"91porn-server/models/v/sysconfmod"
)
func TestTotalWatchCount(t *testing.T) {
tests := []struct {
name string
config sysconfmod.ConfMap
want uint64
}{
{name: "configured", config: sysconfmod.ConfMap{string(sysconfmod.VCodeTotalWatchCount): "5"}, want: 5},
{name: "zero is allowed", config: sysconfmod.ConfMap{string(sysconfmod.VCodeTotalWatchCount): "0"}, want: 0},
{name: "missing", config: sysconfmod.ConfMap{}, want: DefaultTotalWatchCount},
{name: "invalid", config: sysconfmod.ConfMap{string(sysconfmod.VCodeTotalWatchCount): "invalid"}, want: DefaultTotalWatchCount},
}
for _, tt := range tests {
t.Run(tt.name, func(t *testing.T) {
if got := totalWatchCount(tt.config); got != tt.want {
t.Fatalf("totalWatchCount() = %d, want %d", got, tt.want)
}
})
}
}
Vendored Executable
+36
View File
@@ -0,0 +1,36 @@
package viddata
import (
"91porn-server/common/cachev2"
"91porn-server/models"
"91porn-server/models/v/vidmod"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/mongo/options"
"time"
"go.mongodb.org/mongo-driver/bson"
)
type ListRes struct {
List []*vidmod.VideoModel
HasNext bool
}
func GetListFromCache(cond bson.M, skip, limit int64, sort bson.D) ([]*vidmod.VideoModel, bool, error) {
var data ListRes
_, err := cachev2.Classes().CacheTime(10*time.Minute).AutoListKey(models.VideoInfo).ResBind(&data).Cache(getListData, cond, skip, limit, sort)
return data.List, data.HasNext, err
}
// getListData 获取列表数据并组装适合缓存格式返回
func getListData(cond bson.M, skip, limit int64, sort bson.D) (res ListRes, err error) {
opt := options.Find().SetLimit(limit).SetSkip(skip).SetSort(sort)
res.List, res.HasNext, err = vidmod.FindList(cond, opt)
return
}
// GetInfoFromCache 获取数据详情
func GetInfoFromCache(id primitive.ObjectID) (res vidmod.VideoModel, err error) {
_, err = cachev2.Classes().CacheTime(5*time.Minute).AutoInfoKey(models.VideoInfo, id.Hex()).ResBind(&res).Cache(vidmod.GetVideoInfo, id.Hex())
return
}
+156
View File
@@ -0,0 +1,156 @@
package commod
import (
"reflect"
"91porn-server/common/stderr"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/mongo/options"
)
// Page 客户端传低过来的分页信息 对外暴露
type Page struct {
PageNumber uint64 `form:"pageNumber" json:"pageNumber" binding:"required,min=1"` // 当前页
PageSize uint64 `form:"pageSize" json:"pageSize" binding:"required,min=1,max=100"` // 每页条数
Sort []Sorts `form:"sort" json:"sort"`
}
type Sorts struct {
SortKey string `json:"sortKey"`
SortVal int `json:"sortVal"`
}
func (p Page) Skip() uint64 {
return (p.PageNumber - 1) * p.PageSize
}
func (p Page) Skip64() int64 {
return int64((p.PageNumber - 1) * p.PageSize)
}
func (p Page) Limit64() int64 {
return int64(p.PageSize)
}
func (p Page) Limit() uint64 {
return p.PageSize
}
// 注意:Page.Sort内元素顺序决定排序顺序
func (p Page) GetSort() bson.D {
sorts := make(bson.D, len(p.Sort))
for i, v := range p.Sort {
sorts[i] = bson.E{Key: v.SortKey, Value: v.SortVal}
}
return sorts
}
// Sig 签名结构体
type Sig struct {
AccessKey string `form:"accessKey" json:"accessKey" binding:"required"`
BucketName string `form:"bucketName" json:"bucketName" binding:"required"`
}
// Resp 返回结构体
type Resp struct {
Code stderr.Code `json:"code"`
Msg string `json:"msg"`
Data interface{} `json:"data"`
}
// ListResp 分页列表 公共返回结构体
type ListResp struct {
Total int64 `json:"total"`
HasNext bool `json:"hasNext"`
List interface{} `json:"list"`
}
// Page 客户端传低过来的分页信息 内部使用
type PageBy struct {
CheckNext bool
Num uint64
Size uint64
}
// OrderBy 排序
type OrderBy struct {
Key string // 排序的字段
Desc bool // 排序方式 是否倒序
}
// StdQuery 客户端传过来的时间条件信息
type StdQuery struct {
Page *PageBy
Order *[]OrderBy
}
// ConvertToListQuery 分页列表 通用条件查询条件组装
func ConvertToListQuery(s StdQuery) (opts *options.FindOptions) {
opts = &options.FindOptions{}
if s.Page != nil {
skip := int64((s.Page.Num - 1) * s.Page.Size)
limit := int64(s.Page.Size)
if s.Page.CheckNext {
limit++
}
opts.Skip = &skip
opts.Limit = &limit
}
if s.Order != nil && len(*s.Order) > 0 {
sort := bson.D{}
for _, v := range *s.Order {
e := bson.E{}
if v.Desc {
e.Key = v.Key
e.Value = -1
} else {
e.Key = v.Key
e.Value = 1
}
sort = append(sort, e)
}
opts.Sort = sort
}
return
}
// StructToMap2 对象转map,去掉无效值
func StructToMap3(u interface{}) map[string]interface{} {
t := reflect.TypeOf(u)
v := reflect.ValueOf(u)
m := make(map[string]interface{})
for i := 0; i < t.NumField(); i++ {
fv := v.Field(i).Type()
vv := v.Field(i)
k, _ := t.Field(i).Tag.Lookup("bson")
switch fv.Kind() {
case reflect.String:
if vv.String() != "" {
if k == "_id" {
idv, _ := primitive.ObjectIDFromHex(vv.String())
m["_id"] = idv
} else {
m[k] = vv.String()
}
}
case reflect.Int, reflect.Int8, reflect.Int16, reflect.Int32, reflect.Int64:
if vv.Int() != 0 {
m[k] = vv.Interface()
}
case reflect.Uint, reflect.Uint8, reflect.Uint16, reflect.Uint32, reflect.Uint64, reflect.Uintptr:
if vv.Uint() != 0 {
m[k] = vv.Interface()
}
case reflect.Interface, reflect.Ptr:
if vv.Interface() != nil {
m[k] = vv.Interface()
}
}
}
return m
}
+44
View File
@@ -0,0 +1,44 @@
package commod
const (
LouFengCostNotify = "LouFengCostNotify:%d" //用户楼凤消费通知
GameRechargePoliteNotify = "GameRechargePoliteNotify:%d" //用户游戏充值有礼通知
)
// SystemConfigType 系统配置类型
type SystemConfigType int
const (
NudeChatSpecialArea SystemConfigType = iota // 裸聊专区
)
// SystemLocationCode 系统位置编号
type SystemLocationCode int
const (
OfficialBulletin SystemLocationCode = iota // 官方公告
)
// BuyType 充值购买类型
type BuyType int
const (
BuyGold BuyType = iota + 1 // 购买金币
BuyGameCoin // 购买游戏币
BuyFruitCoin // 购买果币
BuyProduct // 购买商品
//BuyNudeChatService // 购买裸聊服务
)
type AdGroup string
const (
AdGroupNone AdGroup = "" // 无组
AdGroupA AdGroup = "A" // A组
AdGroupB AdGroup = "B" // B组
AdGroupC AdGroup = "C" // C组
)
func (ag AdGroup) InABC() bool {
return ag == AdGroupA || ag == AdGroupB || ag == AdGroupC
}
+52
View File
@@ -0,0 +1,52 @@
package commod
import (
"errors"
"math"
)
// 扣量类型
type DeductType int
const (
NotDed DeductType = iota
)
const (
DedConsume DeductType = 1 << iota
DedNewUser
DedBooker
DedRecharge
)
func (d DeductType) Has(t DeductType) bool {
return int(t)&int(d) == int(t)
}
// BitSet 位集合
func (d DeductType) BitSet() []int {
return []int{int(math.Log2(float64(d)))}
}
func (d DeductType) String() string {
switch d {
case DedConsume:
return "dedConsume"
case DedNewUser:
return "dedNewUser"
case DedBooker:
return "dedBooker"
case DedConsume | DedNewUser:
return "dedConsumeAndNewUser"
default:
return "unknow"
}
}
func ToDeductType(v int) (DeductType, error) {
all := DedConsume | DedNewUser | DedBooker
if all.Has(DeductType(v)) {
return DeductType(v), nil
}
return NotDed, errors.New(NotDed.String())
}
+93
View File
@@ -0,0 +1,93 @@
package commod
import (
"strings"
"time"
"91porn-server/common/pageopt"
)
type DiscSeqe struct {
DistrictCode string `json:"districtCode" bson:"districtCode"` //商区码
PromSeqe string `json:"promSeqe" bson:"promSeqe"` //推广序列
}
func (d *DiscSeqe) String() string {
if d.PromSeqe == "" {
return d.DistrictCode
}
return strings.ToUpper(strings.Join([]string{d.DistrictCode, d.PromSeqe}, "-"))
}
func (p *DiscSeqe) From(s string) *DiscSeqe {
p.Clean()
list := strings.Split(s, "-")
if len(list) > 0 {
p.DistrictCode = list[0]
}
if len(list) > 1 {
p.PromSeqe = list[1]
}
return p
}
func (p *DiscSeqe) Clean() {
p.DistrictCode = ""
p.PromSeqe = ""
}
type DiscDoc struct {
//商区码和推广序列
DiscSeqe `bson:",inline"`
//true:是直推用户
IsDirect bool `json:"isDirect" bson:"isDirect"`
//商区绑定时间
DiscBindAt time.Time `bson:"discBindAt"`
}
func NewDiscDoc(discSeqe DiscSeqe, isDirect bool, discBindAt time.Time) DiscDoc {
return DiscDoc{
discSeqe,
isDirect, //直推:推广链接没有推广码, 否则是分裂,
discBindAt,
}
}
type Matcher = pageopt.Matcher
// IsDirectMatch
type IsDirectMatch struct {
IsDirect *bool
}
func (b *IsDirectMatch) New() Matcher {
return pageopt.NewAssignMatch("isDirect", b.IsDirect)
}
// DistrictCodeMatch
type DistrictCodeMatch struct {
DistrictCode *string
}
func (s *DistrictCodeMatch) New() Matcher {
return pageopt.NewAssignMatch("districtCode", s.DistrictCode)
}
// DistrictCodeInMatch
type DistrictCodeInMatch struct {
Codes []string
}
func (s *DistrictCodeInMatch) New() Matcher {
return pageopt.NewInMatch("districtCode", s.Codes)
}
// DiscBindAtGTEAndLTMatch
type DiscBindAtGTEAndLTMatch struct {
GTE *time.Time
LT *time.Time
}
func (c *DiscBindAtGTEAndLTMatch) New() Matcher {
return pageopt.NewGTEAndLTMatch("discBindAt", c.GTE, c.LT)
}
+14
View File
@@ -0,0 +1,14 @@
package commod
import "91porn-server/common/constant"
type ButtonProp struct {
Style constant.SwitchStyle `form:"style" json:"style" bson:"style"` //开关样式
Enable bool `form:"enable" json:"enable" bson:"enable"` //true:显示按钮
}
type LdyButton struct {
Name string `form:"name" json:"name" bson:"name"` //开关名
Type constant.SwitchAct `form:"type" json:"type" bson:"type"` //开关类型
ButtonProp `bson:",inline"`
}
+34
View File
@@ -0,0 +1,34 @@
package commod
type ProductType int
const (
VIP ProductType = 0 // product 0
VIDEO ProductType = 1 // VIDEO视频1
MODEL ProductType = 2 // MODEL嫩模2
MeetingCard ProductType = 3 // 约会卡 3
GAME ProductType = 4 // 游戏币 4
NEWUSERCard ProductType = 5 // 新手卡 5
PhysicalGoods ProductType = 6 // 实体商品 6
AudioBook ProductType = 8 // 语音小说 8
VideoDiscount ProductType = 13 // 视频折扣卡 13
VideoFreeCard ProductType = 14 // 视频免费卡 14
CoinMonthCard ProductType = 18 // 金币月卡 18
Media ProductType = 19 // 动漫整本 19
AdvanceCard ProductType = 21 // 预售卡 21
GameAdvanceCard ProductType = 22 // 游戏预售卡 22
WhoringCard ProductType = 24 // 白嫖卡 24
ImGroup ProductType = 101 // 加入群 101
NakedChat ProductType = 102 // 裸聊 102
)
const OTHER = 20 //OTHER 20
// CurrencyType 货币类型
type CurrencyType int
const (
Gold CurrencyType = iota + 1 // 金币
GameCoin // 游戏币
FruitCoin // 果币
AiMateCoin // AI伴侣币
)
+65
View File
@@ -0,0 +1,65 @@
package commod
type SortType int
// 1、最新,2、最热/推荐,3、最多播放,4、十分钟以上视频, 5、精华/精选,6、视频 7-最多收藏 8、解锁次数 9、最新热评
const (
New SortType = 1 // 最新上架
MostHot SortType = 2 // 热门推荐
MostWatch SortType = 3 // 最多观看
MostCollect SortType = 7 // 最多收藏
HotComment SortType = 9 // 最新热评
)
var nameMap = map[SortType]string{
New: "最新上架",
MostHot: "热门推荐",
MostWatch: "最多观看",
HotComment: "最新热评",
MostCollect: "最多收藏",
}
func (s SortType) Name() string {
name, ok := nameMap[s]
if !ok {
return "未知排序"
}
return name
}
func (s SortType) Item() SortItemData {
item := SortItemData{
Value: s,
Name: "未知排序",
}
name, ok := nameMap[s]
if !ok {
return item
}
item.Name = name
return item
}
type SortItemData struct {
Value SortType `json:"value"`
Name string `json:"name"`
}
// WebSortRules 后台支持修改的排序规则
var WebSortRules = map[string][]SortItemData{
"acgSort": {
New.Item(),
MostHot.Item(),
MostWatch.Item(),
MostCollect.Item(),
HotComment.Item(),
},
"videoSort": {
New.Item(),
MostHot.Item(),
MostWatch.Item(),
MostCollect.Item(),
HotComment.Item(),
},
}
+165
View File
@@ -0,0 +1,165 @@
package commod
import (
"time"
"github.com/shopspring/decimal"
"go.mongodb.org/mongo-driver/bson/primitive"
)
//统计中心Model
type KFKTopic string
const (
KFK_APPID int32 = 204 // 20591PORN
KFK_APP_NAME = "91PORN" // app名字
USER_REG KFKTopic = "user_register" // 用户注册
USER_RECH KFKTopic = "user_recharge" // 用户充值
USER_RECH_ALL KFKTopic = "user_recharge_all" // 全部订单
USER_ACCE KFKTopic = "user_access" // 用户访问
USER_WOTHDRAW KFKTopic = "user_withdraw" // 用户提现
USER_BINDING KFKTopic = "user_binding" // 用户绑定
USER_INVITE KFKTopic = "user_invite" // 用户邀请
ConsumeRecordJob = "consume_record" // 产品消费流水
CardSellJob KFKTopic = "card_sell" // 会员卡特权卡销售流水
AiSellJob = "ai_sell" // AI销售流水
AdsTimeLongVideo = 15 // 长视频广告时间(单位: 秒)
)
type AiSellMsg struct {
AppID int32 `json:"appID" bson:"appID"` // AppID
UID uint64 `json:"uid" bson:"uid"` // UID
UniqID string `json:"uniqID" bson:"uniqID"` // 唯一ID,各个app内部交易ID
Amount int64 `json:"amount" bson:"amount"` // 金币数
TranType string `json:"tranType" bson:"tranType"` // 交易类型
SysType string `json:"sysType" bson:"sysType"` // 系统类型
CurrencyType string `json:"currencyType" bson:"currencyType"` // 交易类型,pay、free
TranCreatedAt time.Time `json:"tranCreatedAt" bson:"tranCreatedAt"` // 交易完成时间
IsRepurchase string `json:"isRepurchase" bson:"isRepurchase"` // 是否复购,yes、no
}
// UserRegisterMsg 用户注册
type UserRegisterMsg struct {
UserId uint64 `json:"userId"`
AppId int32 `json:"appId"`
PlatformId string `json:"platformId"` // 原始平台流水Id
SysType string `json:"sysType"`
DevType string `json:"devType"`
Mobile string `json:"mobile"`
Name string `json:"name"`
IP string `json:"ip"`
IsDirect bool `json:"isDirect"`
DistrictCode string `json:"districtCode"` // 渠道推广 dc
PromSeqe string `json:"promSeqe"` // 代理推广 pc
PUC string `json:"puc" bson:"puc"` //
PromCode string `json:"promCode"` // 用户推广序列(全名代理)
RegisterTime time.Time `json:"registerTime"`
}
// UserAccessMsg 用户访问 用户每天第一访问
type UserAccessMsg struct {
UserId uint64 `json:"userId"`
PlatformId string `json:"platformId"` // 原始平台流水Id
AppId int32 `json:"appId"`
SysType string `json:"sysType"`
DevType string `json:"devType"`
IP string `json:"ip"`
Version string `json:"version"`
DevID string `json:"devID"`
VisitAt time.Time `json:"visitAt"`
IsDirect bool `json:"isDirect,omitempty"` // true:是直推用户
DistrictCode string `json:"districtCode,omitempty"` // 渠道码
RegisterTime time.Time `json:"registerTime,omitempty"` //用户注册时间
IsDeduction bool `json:"isDeduction,omitempty"` // true:CPA扣量用户
}
// UserBindingMsg 用户绑定
type UserBindingMsg struct {
UserId uint64 `json:"userId"` // 用户ID
AppId int32 `json:"appId"` // appID
PlatformId string `json:"platformId"` // 原始平台流水Id
SysType string `json:"sysType"` // 操作系统类型 安卓 IOS
DevType string `json:"devType"` // 设备类型
Mobile string `json:"mobile"` // 手机号
BindingTime *time.Time `json:"bindingTime"` // 绑定时间
}
type UserInviteBindMsg struct {
UserId uint64 `json:"userId" bson:"userId" binding:"required"` // 用户ID
AppId int32 `json:"appId" bson:"appId" binding:"required"` // appID
ParentPromCode string `json:"parentPromCode,omitempty" bson:"promSeqe"` // 邀请人推广码
InviteTime time.Time `json:"inviteTime,omitempty" bson:"inviteTime" binding:"required"` // 邀请码绑定时间
}
const (
StatVipCard = iota //会员卡
StatLouFeng //楼凤
StatValueAddSer //增值服务
)
const (
CurrencyTypeGold = iota //金币
CurrencyTypeCash //现金
)
type ConsumeRecordMsg struct {
AppID int32 `json:"appID" bson:"appID"`
UID uint64 `json:"uid" bson:"uid"` //
Type int `json:"type" bson:"type"` //消费类型
CurrencyType int `json:"currencyType" bson:"currencyType"` //货币类型 0金币 1人民币
Money decimal.Decimal `json:"money" bson:"money"` //人民币 元
Amount decimal.Decimal `json:"amount" bson:"amount"` //金币(角)
Uniq string `json:"uniq" bson:"uniq"` //唯一号码
CreatedAt time.Time `json:"createdAt" bson:"createdAt"` //记录创建时间
}
// 用户充值消息
type UserRechargeMsg struct {
UserId uint64 `json:"userId" bson:"userId" binding:"required"` // 用户ID
AppId int32 `json:"appId" bson:"appId" binding:"required"` // appID
PlatformId string `json:"platformId" bson:"platformId"` // 原始平台流水Id
SysType string `json:"sysType" bson:"sysType" binding:"required"` // 操作系统类型 安卓 IOS
DevType string `json:"devType" bson:"devType"` // 设备类型
ChannelName string `json:"channelName" bson:"channelName"` // 支付渠道名字
CID string `json:"cid" bson:"cid"` // 渠道id
Type string `bson:"type" json:"type"` // 充值方式
OrderId string `json:"orderId" bson:"orderId" binding:"required"` // 流水id
OID string `json:"oid" bson:"oid"` //第三方支付流水id
Money int64 `json:"money" bson:"money" binding:"required"` // 充值金额 订单金额
PayMoney int64 `json:"payMoney" bson:"payMoney" binding:"required"` // 实际到账金额 用户实际支付金额
Status int `json:"status" bson:"status"` // 2付款失败 3付款成功(目前只有成功才发送)
Rate string `json:"rate"` //渠道费率
SuccessAt time.Time `json:"successAt,omitempty" bson:"successAt"` // 成功时间
ProductType int `json:"productType" bson:"productType"`
ChanShareMod int `json:"chanShareMod" bson:"chanShareMod"` //渠道分成 0消费分成 1金币分成 2不分成
/*......*/
}
type CardSellMsg struct {
AppID int32 `json:"appID" bson:"appID"` // AppID
UID uint64 `json:"uid" bson:"uid"` // UID
UniqID string `json:"uniqID" bson:"uniqID"` // 唯一ID,各个app内部交易ID
Amount int64 `json:"amount" bson:"amount"` // 金币数
TranTypeInt int64 `json:"tranTypeInt" bson:"tranTypeInt"` // 交易类型码
TranType string `json:"tranType" bson:"tranType"` // 交易类型文字描述
SysType string `json:"sysType" bson:"sysType"` // 系统类型
CurrencyType int `json:"currencyType" bson:"currencyType"` // 交易类型(0 金币 1 现金)
TranCreatedAt time.Time `json:"tranCreatedAt" bson:"tranCreatedAt"` // 交易完成时间
Product Product `json:"product" bson:"product"` // 产品信息
}
type Position struct {
ID primitive.ObjectID `json:"id" bson:"id"` // 位置ID
Name string `json:"name" bson:"name"` // 位置名称
}
type Product struct {
ID string `json:"id"` // ID
Name string `json:"name"` // 产品名称
DiscountedPrice int64 `bson:"discountedPrice" json:"discountedPrice"` // 现价 单位角(金币)
ProductType ProductType `bson:"productType" json:"productType"` // 产品类型
Position Position `json:"position"` // 产品位置
}
+18
View File
@@ -0,0 +1,18 @@
package daichongmod
// 获取订单信息
type GetOrderReq struct {
TraderId int64 `form:"traderId" json:"traderId"`
PlayerId int64 `form:"playerId" json:"playerId"`
Proof string `form:"proof" json:"proof"` //玩家上传的图片名称
SessionId string `form:"sessionId" json:"sessionId"` //当前会话的sessionId
ProT int `form:"productType" json:"productType" ` //0 站群 1棋牌
}
// 聊天信息请求
type PayInfoReq struct {
TraderId int64 `form:"traderId" json:"traderId" binding:"required"`
PlayerId int64 `form:"playerId" json:"playerId" binding:"required"`
SessionId string `form:"sessionId" json:"sessionId" binding:"required"` //当前会话的sessionId
ProT int `form:"productType" json:"productType" ` //0 站群 1棋牌
}
+34
View File
@@ -0,0 +1,34 @@
package daichongmod
import "time"
// 代充回调公用请求结构体
type CommnReq struct {
AppId string `json:"appId" binding:"required"` //代充平台提供的appId
Data string `json:"data" binding:"required"` //加密字符串
}
// 商人登陆 加密结构体
type LoginSign struct {
Uid string `json:"uid"`
Password string `json:"password"`
}
// 商人余额 加密结构体
type BalanceSign struct {
Uids string `json:"uids"`
Time int64 `json:"time"` //时间戳
}
// 上分 通知新订单生成 加密结构体
type NewOrderSign struct {
FromId string `json:"fromId"` //商人uid
ToId string `json:"toId"` //用户uid
Amount int64 `json:"amount"` //上分数量
OrderId string `json:"orderId"` //订单号
ProductInfo string `json:"productInfo"` //商品信息
Time int64 `json:"time"` //本次通知发起的时间
TransNo string `json:"transNo"` //请求订单
ProT int `json:"productType"` //0站群 1棋牌
SuccessAt time.Time `json:"successAt"` //回调成功时间
}
+41
View File
@@ -0,0 +1,41 @@
package sharemod
import "91porn-server/models/v/vidmod"
// VShareReq 内容分享请求
type VShareReq struct {
Content string `form:"content" json:"content"`
VideoID string `form:"videoID" json:"videoID"` // 可选;视频分享成功时用于累计真实推荐分
EventID string `form:"eventId" json:"eventId"` // 可选;同一次真实分享事件重试时保持不变,用于推荐分幂等
ObjType string `form:"objType" json:"objType"` // drama 表示短剧分享
MediaID string `form:"mediaID" json:"mediaID"`
ContentID string `form:"contentID" json:"contentID"`
}
// VShareCntReq 视频分享次数
type VShareCntReq struct {
VideoID string `form:"videoID" json:"videoID"`
}
// VShareResp 内容分享应答
type VShareResp struct {
QrCode []byte `json:"qrCode"`
}
// VShareCntResp 分享次数应答
type VShareCntResp struct {
VidelID string `json:"videoID"`
Cnt int `json:"cnt"`
}
// List 分享推荐列表
type List struct {
Title string `json:"title"`
Cover string `json:"cover"`
SourceUrl string `json:"sourceUrl"`
LandUrl string `json:"landUrl"`
PicUrl string `json:"picUrl"`
Tags []string `json:"tags"`
DownloadUrl string `json:"downloadUrl"`
List []vidmod.ShareInfo `json:"list"`
}
+9
View File
@@ -0,0 +1,9 @@
package sharemod
// VShareModel 分享统计
type VShareModel struct {
UID int64 `json:"uid" bson:"uid"`
Title int `json:"title" bson:"title"`
ClickCnt int64 `json:"clickCnt" bson:"clickCnt"`
ShareTime int64 `json:"shareTime" bson:"shareTime"`
}
+15
View File
@@ -0,0 +1,15 @@
package models
const (
ESInfoVideoTable = "91porn_video_info"
ESMediaTable = "91porn_media_info"
ESInfoTagTable = "91porn_tag_info"
ESInfoUserTable = "91porn_user_info"
ESInfoLouFengTable = "91porn_loufeng_info"
ESInfoFictionTable = "91porn_fiction_info"
ESInfoAudioBookTable = "91porn_audiobook"
ESLogSearchLogTable = "91porn_search_log"
ESStatKeywordTable = "91porn_keyword_stat"
)
+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()
}
@@ -0,0 +1,121 @@
package dailyretentionmod
import (
"91porn-server/common/db"
"91porn-server/common/log"
"91porn-server/models"
"errors"
"fmt"
"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.DailyRetention
func coll(t *db.MongoTool) *db.MongoTool {
if t == nil {
return mdb.Coll(table)
}
return t.Coll(table)
}
func initIndex() {
many := []mongo.IndexModel{
{
Keys: bson.D{
{Key: "date", Value: -1},
},
},
{
Keys: bson.D{
{Key: "createdAt", Value: -1},
},
},
{
Keys: bson.D{
{Key: "adGroup", Value: 1},
{Key: "date", 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))
}
}
// Init 初始化索引
func Init() {
mdb = db.Init(table)
initIndex()
}
// QueryAllList 分页查询文档
func QueryAllList(filter primitive.M, opts ...*options.FindOptions) (out []*DailyRetention, err error) {
if err = coll(nil).Find(&out, filter, opts...); err != nil {
log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "QueryAllList", table, "Find", err),
log.Any("filter", filter),
log.Any("opts", opts),
)
return nil, err
}
return
}
// QueryOne
func QueryOne(filter bson.M) (*DailyRetention, error) {
v := DailyRetention{}
if err := coll(nil).FindOne(&v, filter); err != nil {
log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "QueryOne", table, "FindOne", err),
log.Any("filter", filter),
)
return &v, err
}
if v.Id.IsZero() {
return nil, errors.New("record not found")
}
return &v, nil
}
// UpsertOne
func UpsertOne(filter bson.M, updateData bson.M) (err error) {
if _, err = coll(nil).UpsertOne(filter, updateData); err != nil {
log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "UpsertOne", table, "UpdateOne", err),
log.Any("filter", filter),
log.Any("updateData", updateData),
)
return
}
return
}
func BulkWrite(models []mongo.WriteModel, opts ...*options.BulkWriteOptions) (err error) {
if len(models) == 0 {
return nil
}
if _, err = coll(nil).Bulk(models, opts...); err != nil {
log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "BulkWrite", table, "BulkWrite", err),
log.Any("modelsCount", len(models)),
)
return
}
return
}
func Distinct(filter bson.M, fieldName string, opts ...*options.DistinctOptions) (out []*DailyRetention, err error) {
raw, err := coll(nil).Distinct(fieldName, filter, opts...)
if err != nil {
log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "Distinct", table, "UpdateOne", err),
log.Any("fieldName", fieldName),
log.Any("filter", filter),
)
return
}
out = make([]*DailyRetention, len(raw))
return
}
+33
View File
@@ -0,0 +1,33 @@
package dailyretentionmod
import (
"91porn-server/common/db"
"91porn-server/models/commod"
"time"
"go.mongodb.org/mongo-driver/bson/primitive"
)
var mdb *db.MongoDB
const (
MaxRetentionDays = 30 // 最大留存天数
)
// DailyRetention 每日用户留存统计
// @table:daily_retention
// @model:DailyRetentionModel
type DailyRetention struct {
Id primitive.ObjectID `json:"id" bson:"_id"` // 自增ID
Date time.Time `json:"date" bson:"date" index:"date_idx, date_adgroup_idx:unique"` // 日期,当日0点
AdGroup commod.AdGroup `json:"adGroup" bson:"adGroup" index:"adgroup_idx, date_adgroup_idx:unique"` // 广告组
NewUsers int64 `json:"newUsers" bson:"newUsers"` // 当天新增用户
UserRetained map[int]int64 `json:"userRetained" bson:"userRetained"` // key = 第几天, value = 日活留存人数
UserRates map[int]float64 `json:"userRates" bson:"userRates"` // key = 第几天, value = 日活留存率
AdClickAcc map[int]int64 `json:"adClickAcc" bson:"adClickAcc"` // key = 第几天, value = 广告点击累计
TotalClickAcc map[int]int64 `json:"totalClickAcc" bson:"totalClickAcc"` // key = 第几天, value = 总点击累计
PayCountAcc map[int]int64 `json:"payCountAcc" bson:"payCountAcc"` // key = 第几天, value = 充值次数累计
PayTotalAcc map[int]int64 `json:"payTotalAcc" bson:"payTotalAcc"` // key = 第几天, value = 充值总金额累计
UpdatedAt time.Time `json:"updatedAt" bson:"updatedAt"` // 更新时间
CreatedAt time.Time `json:"createdAt" bson:"createdAt" index:"-created_at_idx"` // 创建时间
}
+203
View File
@@ -0,0 +1,203 @@
package hotstatmod
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/bson/primitive"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
var mdb *db.MongoDB
const table = models.NewsHot
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{
{
Keys: bson.D{{Key: "sumDate", Value: 1}, {Key: "videoID", Value: 1}},
Options: options.Index(),
},
{
Keys: bson.D{{Key: "sumDate", Value: 1}, {Key: "todayHot", Value: -1}},
Options: options.Index(),
},
{
Keys: bson.D{{Key: "sumDate", Value: 1}, {Key: "weekHot", Value: -1}},
Options: options.Index(),
},
{
Keys: bson.D{{Key: "sumDate", Value: 1}, {Key: "monthHot", Value: -1}},
Options: options.Index(),
},
{
Keys: bson.D{{Key: "createdAt", Value: 1}},
Options: options.Index(),
},
}
if _, err := coll(nil).CreateIndex(many); err != nil {
panic(fmt.Sprintf("%s model set index err ==>[%+v]", table, err))
}
}
// UpdateInsertHotValue 更新热度数值,没有就插入
func UpdateInsertHotValue(sumDate time.Time, mDayli map[primitive.ObjectID]int, mWeek map[primitive.ObjectID]int, mMonth map[primitive.ObjectID]int, mNow map[primitive.ObjectID]int) error {
writes := make([]mongo.WriteModel, len(mNow))
i := 0
for vid, v := range mNow {
filter := bson.M{
"sumDate": sumDate,
"videoID": vid,
}
update := bson.M{
"$setOnInsert": bson.M{
"sumDate": sumDate,
"videoID": vid,
"createdAt": time.Now(),
},
"$set": bson.M{
"todayHot": mDayli[vid],
"weekHot": mWeek[vid],
"monthHot": mMonth[vid],
"totalHot": v,
"updatedAt": time.Now(),
},
}
writes[i] = mongo.NewUpdateOneModel().SetFilter(filter).SetUpdate(update).SetUpsert(true)
i++
log.Debug(fmt.Sprintf("sumDate:%s table:%s [filter:%+v update:%+v ]\n", sumDate, table, filter, update))
}
if len(writes) == 0 {
return nil
}
//bulkWrite 不是原子操作 不具备事务性
opt := (&options.BulkWriteOptions{}).SetOrdered(false) //设为无序,触发并行写,提升写效率
_, err := coll(nil).Bulk(writes, opt)
return err
}
func getHotValue(page, size uint64, cond bson.M, sort bson.D) ([]*HotStat, bool, error) {
hasNext := false
skip := (page - 1) * size
opts := options.FindOptions{}
if sort != nil {
opts.SetSort(sort)
}
opts.SetSkip(int64(skip)).SetLimit(int64(size + 1))
var back []*HotStat
if err := coll(nil).Find(&back, cond, &opts); err != nil {
log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "getHotValue", table, "Find", err),
log.Any("page", page),
log.Any("size", size),
log.Any("cond", cond),
log.Any("sort", sort),
)
return nil, hasNext, err
}
if uint64(len(back)) > size {
hasNext = true
back = back[:size]
}
return back, hasNext, nil
}
func getSortedVideoID(page, size uint64, cond bson.M, sort bson.D) ([]primitive.ObjectID, bool, error) {
ids := []primitive.ObjectID{}
infos, hasNext, err := getHotValue(page, size, cond, sort)
if err != nil {
return ids, false, err
}
ids = make([]primitive.ObjectID, len(infos))
for i, v := range infos {
ids[i] = v.VideoID
}
return ids, hasNext, err
}
// GetHotValueToday 查找热度值
func GetHotValueToday(page, size uint64) ([]primitive.ObjectID, bool, error) {
sumDate := timerange.LocDayRange(time.Now()).Head
cond := bson.M{"sumDate": sumDate}
sort := bson.D{{Key: "todayHot", Value: -1}}
return getSortedVideoID(page, size, cond, sort)
}
// GetHotValueWeek 查找热度值
func GetHotValueWeek(page, size uint64) ([]primitive.ObjectID, bool, error) {
sumDate := timerange.LocDayRange(time.Now()).Head
cond := bson.M{"sumDate": sumDate}
sort := bson.D{{Key: "weekHot", Value: -1}}
return getSortedVideoID(page, size, cond, sort)
}
// GetHotValueMonth 查找热度值
func GetHotValueMonth(page, size uint64) ([]primitive.ObjectID, bool, error) {
sumDate := timerange.LocDayRange(time.Now()).Head
cond := bson.M{"sumDate": sumDate}
sort := bson.D{{Key: "monthHot", Value: -1}}
return getSortedVideoID(page, size, cond, sort)
}
func getHotValueByDate(dt time.Time) (map[primitive.ObjectID]int, error) {
var infos []*HotStat
mValue := make(map[primitive.ObjectID]int)
if err := coll(nil).Find(&infos, bson.M{"sumDate": dt}); err != nil {
log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "getHotValue", table, "Find", err))
return mValue, err
}
for _, v := range infos {
mValue[v.VideoID] = v.TotalHot
}
return mValue, nil
}
// GetYesterdayHotValue 获取昨日热度值
func GetYesterdayHotValue(dt time.Time) (map[primitive.ObjectID]int, error) {
return getHotValueByDate(dt.AddDate(0, 0, -1))
}
// GetLastWeekHotValue 获取上个周日热度值
func GetLastWeekHotValue(dt time.Time) (map[primitive.ObjectID]int, error) {
offset := 0
wk := dt.Weekday()
switch wk {
case time.Monday:
offset = -1
case time.Tuesday:
offset = -2
case time.Wednesday:
offset = -3
case time.Thursday:
offset = -4
case time.Friday:
offset = -5
case time.Saturday:
offset = -6
}
return getHotValueByDate(dt.AddDate(0, 0, offset))
}
// GetLastMonthHotValue 获取上个月末热度值
func GetLastMonthHotValue(dt time.Time) (map[primitive.ObjectID]int, error) {
return getHotValueByDate(dt.AddDate(0, 0, -dt.Day()))
}
func DeleteBeforeCreatedAt(t *db.MongoTool, tm time.Time) error {
_, err := coll(t).DeleteMany(bson.M{"createdAt": bson.M{"$lt": tm}})
return err
}
+27
View File
@@ -0,0 +1,27 @@
package hotstatmod
import (
"time"
"91porn-server/common/db"
"go.mongodb.org/mongo-driver/bson/primitive"
)
func Init() {
mdb = db.Init(table)
initIndex()
}
// HotStat 帖子热度统计表
type HotStat struct {
ID primitive.ObjectID `json:"_id" bson:"_id,omitempty"`
SumDate time.Time `json:"sumDate" bson:"sumDate"`
VideoID primitive.ObjectID `json:"videoID" bson:"videoID"`
TodayHot int `json:"todayHot" bson:"todayHot"` //今日热度
WeekHot int `json:"weekHot" bson:"weekHot"` //本周热度
MonthHot int `json:"monthHot" bson:"monthHot"` //本月热度
TotalHot int `json:"totalHot" bson:"totalHot"` //目前为止总热度
CreatedAt time.Time `json:"createdAt" bson:"createdAt"` // 创建时间
UpdatedAt time.Time `json:"updatedAt" bson:"updatedAt"` // 更新时间
}
+176
View File
@@ -0,0 +1,176 @@
package kwrankmod
import (
"fmt"
"math/rand"
"time"
"91porn-server/common"
"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"
)
var mdb *db.MongoDB
const table = models.KWRankStat
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{
{
Keys: bson.D{{Key: "word", Value: 1}},
},
{
Keys: bson.D{{Key: "sumDate", Value: -1}},
},
{
Keys: bson.D{{Key: "sumDate", Value: -1}, {Key: "word", Value: 1}},
Options: options.Index().SetUnique(true),
},
{
Keys: bson.D{{Key: "count", Value: -1}},
},
{
Keys: bson.D{{Key: "sortKey", Value: -1}}, //大的排前面
},
{
Keys: bson.D{{Key: "sumDate", Value: -1}, {Key: "sortKey", Value: -1}, {Key: "count", Value: -1}}, //大的排前面
},
{
Keys: bson.D{{Key: "recordAt", Value: -1}},
},
}
if _, err := coll(nil).CreateIndex(many); err != nil {
panic(fmt.Sprintf("%s model set index err ==>[%+v]", table, err))
}
}
func Insert(kw Word) error {
now := time.Now()
kw.CreatedAt = now
kw.UpdatedAt = now
if _, err := coll(nil).InsertOne(kw); err != nil {
log.ZapLog.Error(fmt.Sprintf("coll:%s Insert fail error:%+v:", table, err))
return err
}
return nil
}
func Update(id ObjectID, doc RankDoc) error {
update, err := common.ToBsonM(doc)
if err != nil {
return fmt.Errorf("coll:%s update ToBsonM fail, error:%+v ", table, err)
}
update["updatedAt"] = time.Now()
if _, err := coll(nil).UpdateOne(M{"_id": id}, M{"$set": update}); err != nil {
log.ZapLog.Error(fmt.Sprintf("coll:%s update fail error:%+v:", table, err))
return err
}
return nil
}
// DeleteOne DeleteOne
func Delete(id ObjectID) error {
_, err := coll(nil).DeleteOne(M{"_id": id})
if err != nil {
log.ZapLog.Error(fmt.Sprintf("coll:%s DeleteOne fail error:%+v:", table, err))
return err
}
return nil
}
var rankSort = bson.D{
{Key: "sumDate", Value: -1},
{Key: "sortKey", Value: -1},
{Key: "count", Value: -1},
}
var enableIsTrue = true
// RecentRanking RecentRanking
func RecentRanking(limit int64) ([]Keyword, error) {
kws, err := KwsList(rankSort, 0, limit, (&EnableMatch{&enableIsTrue}).New())
if err != nil {
log.ZapLog.Error(fmt.Sprintf("coll:%s RecentRanking fail error:%+v:", table, err))
}
return kws, err
}
func ChangeStatTrans(trans *db.MongoTool, position time.Time, recordTime time.Time, setList []RankSetDoc) error {
if len(setList) == 0 {
return nil
}
sumDate := timerange.LocDayRange(position).Head
// create the slice of write models
writes := make([]mongo.WriteModel, len(setList))
for i, doc := range setList {
filter := M{
"sumDate": sumDate,
"word": doc.Word,
}
update := M{
"$setOnInsert": M{
"sumDate": sumDate,
"word": doc.Word,
"enable": true, //首次插入时使能
"createdAt": time.Now(),
},
"$set": M{
"count": doc.Count, //设计为统计表keywordStat聚合word得到
"sortKey": doc.Count, //控制app端排序
"recordAt": recordTime,
"updatedAt": time.Now(),
},
}
writes[i] = mongo.NewUpdateOneModel().
SetFilter(filter).
SetUpdate(update).
SetUpsert(true)
log.Debug(fmt.Sprintf("sumDate:%s table:%s [ word:%+v filter:%+v update:%+v ]\n", sumDate, table, doc.Word, filter, update))
}
//bulkWrite 不是原子操作 不具备事务性
opt := (&options.BulkWriteOptions{}).SetOrdered(false) //设为无序,触发并行写,提升写效率
_, err := coll(trans).Bulk(writes, opt)
return err
}
func GetListNewest(limit int64) (WordArray, error) {
sort := bson.D{{Key: "createdAt", Value: -1}}
enable := true
enableMatch := EnableMatch{&enable}
return List(sort, 0, limit, enableMatch.New())
}
func GetListRandom(limit int64) (WordArray, error) {
enable := true
enableMatch := EnableMatch{&enable}
count, err := Count(enableMatch.New())
if err != nil {
return nil, err
}
maxSkip := count - limit
if maxSkip < 0 {
maxSkip = 0
}
randSkip := rand.Int63n(maxSkip)
sort := bson.D{{Key: "count", Value: -1}}
return List(sort, randSkip, limit)
}
func DeleteBeforeSumDate(t *db.MongoTool, tm time.Time) error {
_, err := coll(t).DeleteMany(bson.M{"sumDate": bson.M{"$lt": tm}})
return err
}
+78
View File
@@ -0,0 +1,78 @@
package kwrankmod
import (
"fmt"
"time"
"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
// SumDateMatch
type SumDateMatch struct {
SumDate *time.Time
}
func (i *SumDateMatch) New() Matcher {
return pageopt.NewAssignMatch("sumDate", i.SumDate)
}
// EnableMatch
type EnableMatch struct {
Enable *bool
}
func (i *EnableMatch) New() Matcher {
return pageopt.NewAssignMatch("enable", i.Enable)
}
func List(sort bson.D, skip, limit int64, matchers ...Matcher) (WordArray, error) {
filter := pageopt.MergeM(matchers)
opt := &options.FindOptions{}
if len(sort) != 0 {
opt.SetSort(sort)
}
opt.SetSkip(skip)
opt.SetLimit(limit)
wordArray := make(WordArray, 0, limit)
if err := coll(nil).Find(&wordArray, filter, opt); err != nil {
log.ZapLog.Error(fmt.Sprintf("coll:%s List fail error:%+v:", table, err))
return wordArray, err
}
return wordArray, nil
}
type Keyword struct {
KeyWord string `bson:"word" json:"keyWord"` //关键字
Count int64 `bson:"count" json:"count"` //关键字搜索次数
}
func KwsList(sort bson.D, skip, limit int64, matchers ...Matcher) ([]Keyword, error) {
filter := pageopt.MergeM(matchers)
opt := &options.FindOptions{}
if len(sort) != 0 {
opt.SetSort(sort)
}
opt.SetSkip(skip)
opt.SetLimit(limit)
opt.SetProjection(M{
"word": 1,
"count": 1,
})
list := make([]Keyword, 0, limit)
if err := coll(nil).Find(&list, filter, opt); err != nil {
log.ZapLog.Error(fmt.Sprintf("coll:%s List fail error:%+v:", table, err))
return list, err
}
return list, nil
}
func Count(matchers ...Matcher) (int64, error) {
filter := pageopt.MergeM(matchers)
return coll(nil).Count(filter)
}
+66
View File
@@ -0,0 +1,66 @@
package kwrankmod
import (
"time"
"91porn-server/common/db"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
)
type ObjectID = primitive.ObjectID
type M = bson.M
type Word struct {
ID primitive.ObjectID `bson:"_id,omitempty"` // ID
SumDate time.Time `bson:"sumDate"`
ComplexProportion float64 `bson:"complexProportion"` //综合搜索占比
VideoProportion float64 `bson:"videoProportion"` //视屏搜索占比
UserProportion float64 `bson:"userProportion"` //用户搜索占比
TagProportion float64 `bson:"tagProportion"` //标签(话题)搜索占比
LocationProportion float64 `bson:"locationProportion"` //地点搜索占比
Word string `bson:"word"` //词
Count int64 `bson:"count"` //搜索量
SortKey int64 `bson:"sortKey"` //排序量
Enable bool `bson:"enable"` //使能
RecordAt time.Time `bson:"recordAt"` //数据记录时间
CreatedAt time.Time `bson:"createdAt"` // 创建时间
UpdatedAt time.Time `bson:"updatedAt"` // 更新时间
}
type RankDoc struct {
Word *string `bson:"word,omitempty"`
SortKey *int64 `bson:"sortKey,omitempty"`
Enable *bool `bson:"enable,omitempty"`
}
type RankSetDoc struct {
Word *string `bson:"word,omitempty"`
Count *int64 `bson:"count,omitempty"`
ComplexProportion *float64 `bson:"complexProportion"`
VideoProportion *float64 `bson:"videoProportion"`
UserProportion *float64 `bson:"userProportion"`
TagProportion *float64 `bson:"tagProportion"`
LocationProportion *float64 `bson:"locationProportion"`
}
func Init() {
mdb = db.Init(table)
initIndex()
}
type WordArray []Word
func (k WordArray) Len() int {
return len(k)
}
func (k WordArray) Less(i, j int) bool {
return k[i].Count < k[j].Count
}
func (k WordArray) Swap(i, j int) {
k[i], k[j] = k[j], k[i]
}
+234
View File
@@ -0,0 +1,234 @@
package kwstatmod
import (
"fmt"
"time"
"91porn-server/common/constant"
"91porn-server/common/db"
"91porn-server/common/log"
"91porn-server/common/timeutil/timerange"
"91porn-server/models"
"github.com/jinzhu/now"
"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.KeywordStat
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{
{
Keys: bson.D{{Key: "word", Value: 1}},
},
{
Keys: bson.D{{Key: "realm", Value: 1}, {Key: "word", Value: 1}},
},
{
Keys: bson.D{{Key: "sumDate", Value: -1}, {Key: "realm", Value: 1}},
},
{
Keys: bson.D{{Key: "sumDate", Value: -1}, {Key: "realm", Value: 1}, {Key: "word", Value: 1}},
Options: options.Index().SetUnique(true),
},
{
Keys: bson.D{{Key: "count", Value: -1}},
},
{
Keys: bson.D{{Key: "createdAt", Value: -1}},
},
{
Keys: bson.D{{Key: "updatedAt", Value: -1}},
},
}
if _, err := coll(nil).CreateIndex(many); err != nil {
panic(fmt.Sprintf("%s model set index err ==>[%+v]", table, err))
}
}
func ChangeStatTrans(trans *db.MongoTool, position time.Time, recordTime time.Time, docList []KeywordIncDoc) error {
sumDate := timerange.LocDayRange(position).Head
// create the slice of write models
writes := make([]mongo.WriteModel, len(docList))
for i, doc := range docList {
filter := M{
"sumDate": sumDate,
"realm": doc.Realm,
"word": doc.Word,
}
update := M{
"$setOnInsert": M{
"sumDate": sumDate,
"realm": doc.Realm,
"word": doc.Word,
"createdAt": time.Now(),
},
"$set": M{
"recordAt": recordTime,
"updatedAt": time.Now(),
},
"$inc": M{
"count": doc.Count,
},
}
writes[i] = mongo.NewUpdateOneModel().
SetFilter(filter).
SetUpdate(update).
SetUpsert(true)
log.Debug(fmt.Sprintf("sumDate:%s table:%s [ realm:%+v word:%+v filter:%+v update:%+v ]\n", sumDate, table, doc.Realm, doc.Word, filter, update))
}
if len(writes) == 0 {
return nil
}
//bulkWrite 不是原子操作 不具备事务性
opt := (&options.BulkWriteOptions{}).SetOrdered(false) //设为无序,触发并行写,提升写效率
_, err := coll(trans).Bulk(writes, opt)
return err
}
func list(sumDate time.Time, realms []constant.RealmType, enable bool, sort bson.D, skip, limit int64) ([]Keyword, error) {
filter := M{
"sumDate": sumDate,
"realm": M{"$in": realms},
}
realmCount := len(realms)
if realmCount == 0 {
return []Keyword{}, nil
}
if realmCount == 1 { //只有一个元素 不使用$in 提升效率
filter["realm"] = realms[0]
}
opt := (&options.FindOptions{}).
SetSort(sort).
SetSkip(skip).
SetLimit(limit)
keywords := make([]Keyword, 0, limit)
if err := coll(nil).Find(&keywords, filter, opt); err != nil {
log.ZapLog.Error(fmt.Sprintf("coll:%s list fail error:%+v:", table, err))
return nil, err
}
return keywords, nil
}
// RealmRanking RealmRanking
func RealmRanking(sumDate time.Time, realm constant.RealmType, skip int64, limit int64) ([]Keyword, error) {
sort := bson.D{
{Key: "sortKey", Value: -1},
{Key: "count", Value: -1},
}
keywords, err := list(sumDate, []constant.RealmType{realm}, true, sort, skip, limit)
if err != nil {
log.ZapLog.Error(fmt.Sprintf("coll:%s RealmRanking fail error:%+v:", table, err))
return nil, err
}
return keywords, nil
}
// KeywordCountMapBySumDate
func KeywordCountMapBySumDate(sumDate time.Time) (map[string]int64, error) {
pipeline := []M{
{
"$match": M{
"sumDate": sumDate,
},
},
{
"$group": M{
"_id": "$word",
"count": M{"$sum": "$count"},
},
},
{
"$sort": M{
"count": -1,
},
},
}
var list []struct {
Word string `bson:"_id"`
Count int64 `bson:"count"`
}
if err := coll(nil).Aggregate(&list, pipeline); err != nil {
return nil, err
}
m := make(map[string]int64, len(list))
for _, v := range list {
m[v.Word] = v.Count
}
return m, nil
}
// HotSearchWordsToday 获取今日搜索较高的关键词 视频关键字
func HotSearchWordsToday(top int) ([]string, error) {
var kw []Keyword
var words []string
opts := options.FindOptions{}
sort := bson.D{{Key: "count", Value: -1}}
opts.SetSort(sort).SetLimit(int64(top))
if err := coll(nil).Find(&kw, M{"realm": "video", "sumDate": now.BeginningOfDay()}, &opts); err != nil {
log.Error("keywordStat model HotSearchWordsToday error", log.E(err), log.Any("top", top))
return words, err
}
words = make([]string, len(kw))
for i, k := range kw {
words[i] = k.Word
}
return words, nil
}
func GetKeywordsExcludeWords(sumDate time.Time, realm string, words []string, skip int64, limit int64) (data []Keyword, err error) {
if words == nil {
words = []string{}
}
query := bson.M{"word": bson.M{"$nin": words}}
opts := options.Find()
sort := bson.D{
{Key: "sortKey", Value: -1},
{Key: "count", Value: -1},
}
opts.SetSort(sort).SetSkip(skip).SetLimit(limit)
if err = coll(nil).Find(&data, query, opts); err != nil {
log.Error("keywordStat model GetKeywordsExcludeWords error", log.E(err), log.Any("sumDate", sumDate), log.Any("words", words))
return
}
return
}
// 根据时间获取今日加昨日的关键字
func GetKeywordsBySumDate(sumDate time.Time, realm string, skip int64, limit int64) (data []Keyword, err error) {
var query = bson.M{"sumDate": bson.M{"$gte": sumDate}, "realm": realm}
var opts = options.Find()
opts.SetSort(bson.D{{Key: "sortKey", Value: -1}, {Key: "count", Value: -1}}).SetSkip(skip).SetLimit(limit)
if err = coll(nil).Find(&data, query, opts); err != nil {
log.Error("keywordStat model GetKeywordsBySumDate error", log.E(err), log.Any("sumDate", sumDate), log.Any("realm", realm))
return
}
return
}
// 根据时间段获取关键字
func GetKeywordsByTimeRange(start time.Time, end time.Time) (data []Keyword, err error) {
var query = bson.M{"updatedAt": bson.M{"$gte": start, "$lt": end}}
if err = coll(nil).Find(&data, query); err != nil {
log.Error("keywordStat model GetKeywordsByTimeRange error", log.E(err))
return
}
return
}
func DeleteBeforeSumDate(t *db.MongoTool, tm time.Time) error {
_, err := coll(t).DeleteMany(bson.M{"sumDate": bson.M{"$lt": tm}})
return err
}
+51
View File
@@ -0,0 +1,51 @@
package kwstatmod
import (
"time"
"91porn-server/common/constant"
"91porn-server/common/db"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
)
type (
ObjectID = primitive.ObjectID
M = bson.M
KeywordSetDoc = KeywordIncDoc
)
type Keyword struct {
ID primitive.ObjectID `bson:"_id,omitempty"` // ID
SumDate time.Time `bson:"sumDate"`
Realm constant.RealmType `bson:"realm"`
Word string `bson:"word"`
Count int64 `bson:"count"`
RecordAt time.Time `bson:"recordAt"` //数据记录时间
CreatedAt time.Time `bson:"createdAt"` // 创建时间
UpdatedAt time.Time `bson:"updatedAt"` // 更新时间
}
type ESKeywordSrc struct {
ID primitive.ObjectID `json:"id"` // ID
SumDate time.Time `json:"sumDate"`
Realm constant.RealmType `json:"realm"`
Word string `json:"word"`
Count int64 `json:"count"`
RecordAt time.Time `json:"recordAt"` //数据记录时间
CreatedAt time.Time `json:"createdAt"` // 创建时间
UpdatedAt time.Time `json:"updatedAt"` // 更新时间
}
type KeywordIncDoc struct {
Realm constant.RealmType `bson:"realm,omitempty"`
Word string `bson:"word,omitempty"`
Count int64 `bson:"count,omitempty"`
}
func Init() {
mdb = db.Init(table)
initIndex()
}
+43
View File
@@ -0,0 +1,43 @@
package sectionstatmod
import (
"time"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
"go.mongodb.org/mongo-driver/mongo/options"
)
// IncSectionHits 增加专题每日点击量
func IncSectionHits(sectionID primitive.ObjectID, date string) error {
filter := bson.M{"sectionID": sectionID, "date": date}
_, err := coll(nil).UpdateOne(filter, bson.M{"$inc": bson.M{"hitsPerDay": 1}})
return err
}
// UpsertSectionHits upsert某一天专题点击量
func UpsertSectionHits(sectionID primitive.ObjectID, date string) error {
filter := bson.M{"sectionID": sectionID, "date": date}
now := time.Now()
update := bson.M{
"$set": bson.M{"sectionID": sectionID, "date": date, "updatedAt": now},
"$setOnInsert": bson.M{"createdAt": now},
"$inc": bson.M{"hitsPerDay": 1},
}
_, err := coll(nil).UpsertOne(filter, update)
return err
}
// ListSectionHits 按页检索专题统计数据
func ListSectionHits(req ListRequest) (resp ListResponse, err error) {
opts := options.Find().SetSkip(int64(req.PageSize * (req.PageNumber - 1))).SetLimit(int64(req.PageSize + 1)).
SetSort(bson.D{{Key: "date", Value: -1}})
if err = coll(nil).Find(&resp.List, bson.M{"sectionID": req.SectionID}, opts); err != nil {
return
}
if uint64(len(resp.List)) > req.PageSize {
resp.HasNext = true
resp.List = resp.List[:req.PageSize]
}
return
}
+63
View File
@@ -0,0 +1,63 @@
package sectionstatmod
import (
"fmt"
"time"
"91porn-server/common/db"
"91porn-server/models"
"91porn-server/models/commod"
"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"
)
type SectionStat struct {
ID primitive.ObjectID `json:"id" bson:"_id,omitempty"` // id
SectionID primitive.ObjectID `json:"sectionID" bson:"sectionID"` // 专题ID
HitsPerday int64 `json:"hitsPerDay" bson:"hitsPerDay"` // 每日点击量
Date string `json:"date" bson:"date"` // 统计日期
CreatedAt time.Time `json:"createdAt" bson:"createdAt,omitempty"` // 创建时间
UpdatedAt time.Time `json:"updatedAt" bson:"updatedAt,omitempty"` // 刷新时间
}
var mdb *db.MongoDB
const table = models.SectionClick
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()
}
// initIndex 初始化索引
func initIndex() {
many := []mongo.IndexModel{
{
Keys: bson.D{{Key: "sectionID", Value: 1}, {Key: "date", 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))
}
}
type ListRequest struct {
SectionID primitive.ObjectID `json:"sectionID" swaggertype:"string" binding:"required"` // 专题ID
commod.Page
}
type ListResponse struct {
List []SectionStat // 统计列表
HasNext bool // 下一页
}
+95
View File
@@ -0,0 +1,95 @@
package statordermod
import (
"time"
"91porn-server/common/log"
"91porn-server/common/pageopt"
"go.mongodb.org/mongo-driver/mongo/options"
)
type (
Matcher = pageopt.Matcher
// ChannelMatch
ChannelMatch struct {
Type *string
}
)
func (t *ChannelMatch) New() Matcher {
return pageopt.NewAssignMatch("channel", t.Type)
}
// TypeMatch
type TypeMatch struct {
Type *OrderType
}
func (t *TypeMatch) New() Matcher {
return pageopt.NewAssignMatch("type", t.Type)
}
// SumDateGTEAndLTMatch
type SumDateGTEAndLTMatch struct {
GTE *time.Time
LT *time.Time
}
func (s *SumDateGTEAndLTMatch) New() Matcher {
return pageopt.NewGTEAndLTMatch("sumDate", s.GTE, s.LT)
}
var Sort_SumDate_n1 = Sort{{Key: "sumDate", Value: -1}}
func List(sort Sort, skip, limit *int64, matchers ...Matcher) ([]OrderState, 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 := []OrderState{}
if err := coll(nil).Find(&list, filter, opt); err != nil {
log.Error("statordermod 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("statordermod Count error", log.E(err))
return 0, err
}
return count, nil
}
// Sum
func Sum(matchers ...Matcher) (Items, error) {
filter := pageopt.MergeM(matchers)
pipeline := []M{}
pipeline = append(pipeline, M{"$match": filter})
pipeline = append(pipeline, M{"$group": M{"_id": nil,
"orderCount": M{"$sum": "$orderCount"},
"completeOrderCount": M{"$sum": "$completeOrderCount"},
"orderAmount": M{"$sum": "$orderAmount"},
"completeOrderAmount": M{"$sum": "$completeOrderAmount"},
"paidOrderCount": M{"$sum": "$paidOrderCount"},
"paidAmount": M{"$sum": "$paidAmount"},
}})
items := Items{}
if err := coll(nil).AggregateDecode(&items, pipeline); err != nil {
log.Error("statordermod Sum error", log.E(err))
return Items{}, err
}
return items, nil
}
+123
View File
@@ -0,0 +1,123 @@
package statordermod
import (
"fmt"
"time"
"91porn-server/common"
"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.OrderStat
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: "sumDate", Value: -1}},
},
{
Keys: bson.D{{Key: "channel", Value: 1}, {Key: "type", Value: 1}},
},
{
Keys: bson.D{{Key: "sumDate", Value: -1}, {Key: "channel", Value: 1}, {Key: "type", 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 ChangeRechargeStatTrans(trans *db.MongoTool, sumDate, recordTime time.Time, stateMap RecOrderStateMap) error {
writes := make([]mongo.WriteModel, len(stateMap))
i := 0
for channel, statDoc := range stateMap {
model, err := toMgoModel(sumDate, recordTime, channel, Recharge, statDoc.RechargeOrderStateIncDoc, statDoc.RechargeOrderStateSetDoc)
if err != nil {
return err
}
writes[i] = model
i++
}
if len(writes) == 0 {
return nil
}
//bulkWrite 不是原子操作 不具备事务性
opt := (&options.BulkWriteOptions{}).SetOrdered(false) //设为无序,触发并行写,提升写效率
_, err := coll(trans).Bulk(writes, opt)
return err
}
func ChangeWithDrawStatTrans(trans *db.MongoTool, sumDate, recordTime time.Time, stateMap WitOrderStateMap) error {
writes := make([]mongo.WriteModel, len(stateMap))
i := 0
for channel, statDoc := range stateMap {
model, err := toMgoModel(sumDate, recordTime, channel, WithDraw, statDoc.WithDrawOrderStateIncDoc, statDoc.WithDrawOrderStateSetDoc)
if err != nil {
return err
}
writes[i] = model
i++
}
if len(writes) == 0 {
return nil
}
//bulkWrite 不是原子操作 不具备事务性
opt := (&options.BulkWriteOptions{}).SetOrdered(false) //设为无序,触发并行写,提升写效率
_, err := coll(trans).Bulk(writes, opt)
return err
}
func toMgoModel(sumDate, recordTime time.Time, channel string, typ OrderType, inc orderStateIncDoc, set orderStateSetDoc) (mongo.WriteModel, error) {
filter := M{
"sumDate": sumDate,
"channel": channel,
"type": typ,
}
setM, err := common.ToBsonM(set)
if err != nil {
return nil, err
}
setM["recordAt"] = recordTime
setM["updatedAt"] = time.Now()
incM, err := common.ToBsonM(inc)
if err != nil {
return nil, err
}
update := M{
"$setOnInsert": M{
"sumDate": sumDate,
"channel": channel,
"type": typ,
"createdAt": time.Now(),
},
}
if len(incM) != 0 {
update["$inc"] = incM
}
if len(setM) != 0 {
update["$set"] = setM
}
model := mongo.NewUpdateOneModel().
SetFilter(filter).
SetUpdate(update).
SetUpsert(true)
log.Debug(fmt.Sprintf("sumDate:%s table:%s [ typ:%s channel:%s filter:%+v update:%+v ]\n", sumDate, table, typ.String(), channel, filter, update))
return model, nil
}
+90
View File
@@ -0,0 +1,90 @@
package statordermod
import (
"time"
"91porn-server/common/db"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
)
type (
OrderType int
M = bson.M
Sort = bson.D
)
const (
Recharge OrderType = 1
WithDraw OrderType = 2
)
func (o *OrderType) String() string {
switch *o {
case Recharge:
return "recharge"
case WithDraw:
return "withDraw"
default:
return "unknow"
}
}
type Items struct {
OrderCount int64 `json:"orderCount" bson:"orderCount"` //生产订单数
CompleteOrderCount int64 `json:"completeOrderCount" bson:"completeOrderCount"` //完成订单数
OrderAmount int64 `json:"orderAmount" bson:"orderAmount"` //生产订单金额
CompleteOrderAmount int64 `json:"completeOrderAmount" bson:"completeOrderAmount"` //完成订单的实际支付金额
PaidOrderCount int64 `json:"paidOrderCount" bson:"paidOrderCount"` //用户已支付金额/三方已出款金额
PaidAmount int64 `json:"paidAmount" bson:"paidAmount"` //用户已支付订单数/三方已出款订单数
}
// OrderState 充值提现统计
type OrderState struct {
ID primitive.ObjectID `json:"id" bson:"_id,omitempty"` // ID
SumDate time.Time `json:"sumDate" bson:"sumDate"`
Items `bson:",inline"`
Channel string `json:"channel" bson:"channel"` //充值渠道
Type OrderType `json:"type" bson:"type"` //订单类型, 1,充值;2,提现
RecordAt time.Time `json:"recordAt" bson:"recordAt"` //数据记录时间
CreatedAt time.Time `json:"createdAt" bson:"createdAt"` //文档创建时间
UpdatedAt time.Time `json:"updatedAt" bson:"updatedAt"` //文档更新时间
}
func Init() {
mdb = db.Init(table)
initIndex()
}
type orderStateSetDoc struct {
}
type orderStateIncDoc struct {
OrderCount *int64 `bson:"orderCount,omitempty"` //订单数
CompleteOrderCount *int64 `bson:"completeOrderCount,omitempty"` //完成订单数
OrderAmount *int64 `bson:"orderAmount,omitempty"` //订单金额
CompleteOrderAmount *int64 `bson:"completeOrderAmount,omitempty"` //实际支付金额
PaidOrderCount *int64 `bson:"paidOrderCount,omitempty"` //用户已支付订单数/三方已出款订单数
PaidAmount *int64 `bson:"paidAmount,omitempty"` //用户已支付金额/三方已出款金额
}
type RechargeOrderStateIncDoc = orderStateIncDoc
type RechargeOrderStateSetDoc = orderStateSetDoc
type RechargeOrderStateDoc struct {
RechargeOrderStateIncDoc
RechargeOrderStateSetDoc
}
type RecOrderStateMap = map[string]*RechargeOrderStateDoc
type WithDrawOrderStateIncDoc = orderStateIncDoc
type WithDrawOrderStateSetDoc = orderStateSetDoc
type WithDrawOrderStateDoc struct {
WithDrawOrderStateIncDoc
WithDrawOrderStateSetDoc
}
type WitOrderStateMap = map[string]*WithDrawOrderStateDoc
+182
View File
@@ -0,0 +1,182 @@
package statrecordmod
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.StatRecord
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: "name", Value: 1}},
Options: options.Index().SetUnique(true),
},
{
Keys: bson.D{{Key: "job", Value: 1}, {Key: "item", Value: 1}},
Options: options.Index().SetSparse(true).SetUnique(true),
},
{
Keys: bson.D{{Key: "createdAt", Value: -1}},
},
{
Keys: bson.D{{Key: "updatedAt", Value: -1}},
},
}
if _, err := coll(nil).CreateIndex(many); err != nil {
panic(fmt.Sprintf("%s model set index err ==>[%+v]", table, err))
}
}
// ChangeStatTrans ChangeStatTrans
func UpsertOneTrans(trans *db.MongoTool, name string, recordTime time.Time) error {
filter := bson.M{
"name": name,
}
update := bson.M{
"$set": bson.M{
"recordTime": recordTime,
"updatedAt": time.Now(),
},
"$setOnInsert": bson.M{
"name": name,
"fristRecordTime": recordTime,
"createdAt": time.Now(),
},
}
if _, err := coll(trans).UpsertOne(filter, update); err != nil {
log.Error("statrecordmod UpsertOneTrans error:%v\n", log.E(err))
return err
}
return nil
}
type ItemRecordAt struct {
Job string
Item string
RecordTime time.Time
}
func MergeName(job string, item string) string {
return fmt.Sprintf("%s.%s", job, item)
}
func UpsertOneItemTrans(trans *db.MongoTool, job string, item string, recordTime time.Time) error {
filter := bson.M{
"job": job,
"item": item,
}
update := bson.M{
"$set": bson.M{
"recordTime": recordTime,
"updatedAt": time.Now(),
},
"$setOnInsert": bson.M{
"name": MergeName(job, item),
"job": job,
"item": item,
"fristRecordTime": recordTime,
"createdAt": time.Now(),
},
}
if _, err := coll(trans).UpsertOne(filter, update); err != nil {
log.Error("statrecordmod UpsertOneItemTrans error:%v\n", log.E(err))
return err
}
return nil
}
// FindOne FindOne
func findOneByName(Name string) (Record, error) {
filter := bson.M{
"name": Name,
}
doc := Record{}
return doc, coll(nil).FindOne(&doc, filter)
}
// LastRecordTime 最后的记录时间,服务器的时区
func LastRecordTime(name string, defaultTime time.Time) (time.Time, error) {
//获取上次记录时间
doc, err := findOneByName(name)
if err != nil {
return time.Time{}, fmt.Errorf("LastRecordTime err:%+v\n", err)
}
//设定为服务器的时区
var tim = defaultTime
if !doc.RecordTime.IsZero() {
tim = doc.RecordTime
}
//不依赖数据库 保证时间是服务器时间
localTime := tim.In(time.Local)
log.Debug("LastRecordTime local Info", log.Any("Local", time.Local), log.Any("time", tim), log.Any("returnTime", localTime))
return localTime, nil
}
func FristRecordTimeByName(name string) (time.Time, error) {
doc, err := findOneByName(name)
if err != nil {
return time.Time{}, fmt.Errorf("FristRecordTimeByName err:%+v\n", err)
}
return doc.FristRecordTime, nil
}
func findOneByJob(job string, item string) (Record, error) {
filter := bson.M{
"job": job,
"item": item,
}
doc := Record{}
return doc, coll(nil).FindOne(&doc, filter)
}
func FristRecordTimeByJob(job string, item string) (time.Time, error) {
doc, err := findOneByJob(job, item)
if err != nil {
return time.Time{}, fmt.Errorf("FristRecordTimeByName err:%+v\n", err)
}
return doc.FristRecordTime, nil
}
func findManyByJob(job string) ([]Record, error) {
filter := bson.M{
"job": job,
}
list := []Record{}
return list, coll(nil).Find(&list, filter)
}
func LastRecordTimeMap(job string, defaultTimeMap map[string]time.Time) (map[string]time.Time, error) {
list, err := findManyByJob(job)
if err != nil {
return nil, err
}
for _, v := range list {
defaultTimeMap[v.Item] = v.RecordTime
}
return defaultTimeMap, nil
}
func DeleteStatRecordByName(name string) error {
_, err := coll(nil).DeleteOne(bson.M{"name": name})
return err
}
+84
View File
@@ -0,0 +1,84 @@
package statrecordmod
import (
"time"
"91porn-server/common/db"
"go.mongodb.org/mongo-driver/bson/primitive"
)
type Record struct {
ID primitive.ObjectID `bson:"_id,omitempty"`
Name string `bson:"name"` //任务名
Job string `bson:"job"` //工作
Item string `bson:"item"` //项目
RecordTime time.Time `bson:"recordTime"` //提交时间
FristRecordTime time.Time `bson:"fristRecordTime"` //第一次提交时间
CreatedAt time.Time `bson:"createdAt"` //创建时间
UpdatedAt time.Time `bson:"updatedAt"` //更新时间
}
const (
OneMinuteScale = 1 //对齐时间(分钟)
FiveMinuteScale = 5 //对齐时间(分钟)
FifteenMinuteScale = 15 //对齐时间(分钟)
ThirtyMinuteScale = 30 //对齐时间(分钟)
OneDayScale = 1440 //对齐时间(分钟)
)
const (
//stat 基本统计
DailyStatJob1 = "dailyStatJob1"
ChannelStatJob = "channelStatJob"
VideoStatJob = "videoStatJob"
VideoTotalStatJob = "videoTotalStatJob"
ChannelRetainStatJob = "channelRetainStatJob"
KeywordStatJob = "keywordStatJob"
KeywordRankStatJob = "keywordRankStatJob"
RechargeOrderStatJob = "rechargeOrderStatJob"
WithdrawOrderStatJob = "withdrawOrderStatJob"
TagPlayStatJob = "tagPlayStatJob"
ADSStatJob = "adsStatJob"
TotalJob = "totalJob"
ChTotalJob = "chTotalJob"
InvitStatJob = "InvitStatJob"
DataPointJob = "dataPointJob"
UserStatJob = "userStatJob"
DiscStatJob = "discStatJob"
DiscTotalStatJob = "discTotalStatJob"
Retain1StatJob = "retainStatJob1"
DicsZoomStatJob = "dicsZoomStatJob"
//act 活动统计,生命周期等于活动时间
ActInvitCountJob_01_17 = "ActInvitCountJob_01_17"
ActInvitCoinsJob_01_17 = "ActInvitCoinsJob_01_17"
LotteryActID = "LotteryActID"
// 数据同步
ElasticSyncVideoJob = "esVideoJob"
ElasticSyncMediaJob = "esMediaJob"
ElasticSyncTagJob = "esTagJob"
ElasticSyncUserJob = "esUserJob"
ElasticSyncKeywordJob = "esKeywordJob"
ElasticSyncSearchLogJob = "esSearchLogJob"
ElasticSyncLoufengJob = "esLouFengJob"
ElasticSyncAudioBookJob = "esAudioBookJob"
SpiderSyncLoufengJob = "spiderLouFengJob"
SpiderSyncfictionJob = "spiderFictionJob"
SpiderSyncAudiobookJob = "spiderAudiobookJob"
SpiderSyncLoufengAgentJob = "spiderSyncLoufengAgentJob"
RedisSyncShortVideoJob = "rdShortVideoJob"
//sql折叠
SqlCollasperVidPageView = "sqlCollasperVidPageView"
SqlCollasperUserTotalWork = "sqlCollasperUserTotalWorks"
)
func Init() {
mdb = db.Init(table)
initIndex()
}
+90
View File
@@ -0,0 +1,90 @@
package stattagplaymod
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.TagPlayStat
func coll(t *db.MongoTool) *db.MongoTool {
if t == nil {
return mdb.Coll(table)
}
return t.Coll(table)
}
func initIndex() {
many := []mongo.IndexModel{
{
Keys: bson.D{{Key: "tagID", Value: 1}, {Key: "videoID", Value: 1}},
Options: options.Index().SetUnique(true),
},
{
Keys: bson.D{{Key: "playCount", Value: 1}, {Key: "updatedAt", Value: 1}},
},
{
Keys: bson.D{{Key: "updatedAt", Value: -1}},
},
}
if _, err := coll(nil).CreateIndex(many); err != nil {
panic(fmt.Sprintf("%s model set index err ==>[%+v]", table, err))
}
}
func GetTagPlayCount(tagID ObjectID, videoID ObjectID) (TagPlay, error) {
tagPlay := TagPlay{}
if err := coll(nil).FindOne(&tagPlay, bson.M{"tagID": tagID, "videoID": videoID}); err != nil {
log.Error("stat tag play model GetTagPlayCount error", log.E(err), log.Any("tagID", tagID), log.Any("videoID", videoID))
return tagPlay, err
}
return tagPlay, nil
}
func ChangeStatTrans(trans *db.MongoTool, incDoc []IncDoc) error {
incDocLen := len(incDoc)
if incDocLen == 0 {
return nil
}
// create the slice of write models
writes := make([]mongo.WriteModel, incDocLen)
for i, tagPlay := range incDoc {
filter := bson.M{
"tagID": tagPlay.TagID,
"videoID": tagPlay.VideoID,
}
update := bson.M{
"$setOnInsert": bson.M{
"tagID": tagPlay.TagID,
"videoID": tagPlay.VideoID,
},
"$inc": bson.M{
"playCount": tagPlay.PlayCount,
},
"$set": bson.M{
"updatedAt": time.Now(),
},
}
writes[i] = mongo.NewUpdateOneModel().
SetFilter(filter).
SetUpdate(update).
SetUpsert(true)
}
//bulkWrite 不是原子操作 不具备事务性
opt := (&options.BulkWriteOptions{}).SetOrdered(false) //设为无序,触发并行写,提升写效率
if _, err := coll(trans).Bulk(writes, opt); err != nil {
log.Warn("stat tag play model Bulk error", log.E(err))
return err
}
return nil
}
+30
View File
@@ -0,0 +1,30 @@
package stattagplaymod
import (
"time"
"91porn-server/common/db"
"go.mongodb.org/mongo-driver/bson/primitive"
)
type ObjectID = primitive.ObjectID
type TagPlay struct {
ID ObjectID `bson:"_id,omitempty"`
TagID ObjectID `bson:"tagID"`
VideoID ObjectID `bson:"videoID"`
PlayCount int64 `bson:"playCount"`
UpdatedAt time.Time `bson:"updatedAt"`
}
type IncDoc struct {
TagID ObjectID `bson:"tagID"`
VideoID ObjectID `bson:"videoID"`
PlayCount int64 `bson:"playCount"`
}
func Init() {
mdb = db.Init(table)
initIndex()
}

Some files were not shown because too many files have changed in this diff Show More