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
+631
View File
@@ -0,0 +1,631 @@
package audiobookmod
import (
"encoding/json"
"errors"
"fmt"
"math/rand"
"time"
"91porn-server/app/appg"
"91porn-server/app/service/searcher"
"91porn-server/common"
"91porn-server/common/constant/redisconst"
"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/bson/primitive"
"go.mongodb.org/mongo-driver/mongo"
"go.mongodb.org/mongo-driver/mongo/options"
)
const table = models.AudioBook
// InitIndex 设置index
func initIndex() {
coll := coll(nil)
many := []mongo.IndexModel{
{
Keys: bson.D{{Key: "number", Value: 1}},
Options: options.Index().SetUnique(true),
},
{
Keys: bson.D{{Key: "isActive", Value: 1}},
},
{
Keys: bson.D{{Key: "fType", Value: 1}},
},
{
Keys: bson.D{{Key: "anchor", Value: 1}},
},
}
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 GetByID(id primitive.ObjectID) (ab AudioBookAppRes, err error) {
redisKey := redisconst.DataCachKey(table, id.Hex())
redisc := appg.Redis
if redisc == nil || !redisc.Exists(redisKey) {
if err = coll(nil).FindOne(&ab, bson.M{"_id": id}); err != nil {
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "GetByID", table, "FindOne", err), log.Any("id", id.Hex()))
return
}
if redisc == nil {
return
}
var jsonBytes []byte
jsonBytes, err = json.Marshal(&ab)
if err != nil {
return
}
err = redisc.Set(redisKey, string(jsonBytes), redisconst.DataCachExpire)
return
}
str, err := redisc.Get(redisKey)
if err != nil {
return
}
if str == nil {
err = errors.New("redis key is null")
return
}
if err = json.Unmarshal([]byte(*str), &ab); err != nil {
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "GetByID", table, "FindOne", err), log.Any("id", id.Hex()))
return
}
return
}
// todo app
func GetByIds(ids []primitive.ObjectID) (res []AudioBookAppRes, err error) {
data := make([]AudioBookAppRes, 0)
f := bson.M{}
if ids != nil {
f["_id"] = bson.M{"$in": ids}
}
if err = coll(nil).Find(&data, f); err != nil {
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "GetByBusinessDateAndCityInIds", table, "Find", err), log.Any("cond", f))
return
}
tempM := make(map[primitive.ObjectID]AudioBookAppRes)
for i := range data {
tempM[data[i].ID] = data[i]
}
res = make([]AudioBookAppRes, len(ids))
for i := range ids {
res[i] = tempM[ids[i]]
}
return
}
func GetByFType(fType string, page commod.Page) (data []AudioBookBase, hasNext bool, err error) {
data = make([]AudioBookBase, 0)
skip := int64(page.Skip())
limit := int64(page.Limit() + 1)
sortWord := "createdAt"
opts := options.FindOptions{
Skip: &skip,
Limit: &limit,
Sort: bson.D{{Key: sortWord, Value: -1}},
}
f := bson.M{"isActive": true}
if fType != "" {
if fType == ListenPermissionBuyZone {
f["contentSet.listenPermission"] = ListenPermissionBuy
} else {
f["fType"] = fType
}
}
if err = coll(nil).Find(&data, f, &opts); err != nil {
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "GetByFType", table, "Find", err), log.Any("cond", f))
return
}
if uint64(len(data)) > page.PageSize {
hasNext = true
data = data[:page.PageSize]
}
for i := range data {
for j := range data[i].ContentSet {
data[i].ContentSet[j].ListenPermission = 3
data[i].ContentSet[j].Price = 0
}
}
return
}
func GetByAnchor(anchor string, page commod.Page) (data []AudioBookBase, hasNext bool, err error) {
data = make([]AudioBookBase, 0)
skip := int64(page.Skip())
limit := int64(page.Limit() + 1)
sortWord := "createdAt"
opts := options.FindOptions{
Skip: &skip,
Limit: &limit,
Sort: bson.D{{Key: sortWord, Value: -1}},
}
f := bson.M{"isActive": true}
if anchor != "" {
f["anchor"] = anchor
}
if err = coll(nil).Find(&data, f, &opts); err != nil {
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "GetByFType", table, "Find", err), log.Any("cond", f))
return
}
if uint64(len(data)) > page.PageSize {
hasNext = true
data = data[:page.PageSize]
}
return
}
// 获取热门
func GetHots(page commod.Page) (data []AudioBookBase, hasNext bool, err error) {
data = make([]AudioBookBase, 0)
skip := int64(page.Skip())
limit := int64(page.Limit() + 1)
sortWord := "countPurchases"
opts := options.FindOptions{
Skip: &skip,
Limit: &limit,
Sort: bson.D{{Key: sortWord, Value: -1}},
}
f := bson.M{"isActive": true}
if err = coll(nil).Find(&data, f, &opts); err != nil {
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "GetByFType", table, "Find", err), log.Any("cond", f))
return
}
if uint64(len(data)) > page.PageSize {
hasNext = true
data = data[:page.PageSize]
}
return
}
func GetRandomPush(size int) (data []AudioBookBase, err error) {
data = make([]AudioBookBase, 0)
redisK := "tempSet:" + RedisSetKey + ":randomData"
redisc := appg.Redis
if redisc == nil || !redisc.Exists(redisK) {
f := bson.M{"isActive": true}
var total int64
total, err = randomCount(f)
if err != nil {
return
}
var limit int64 = 100
var skip int64 = 0
if total-limit > limit {
skip = rand.Int63n(total - limit)
}
opts := options.FindOptions{
Skip: &skip,
Limit: &limit,
}
if err = coll(nil).Find(&data, f, &opts); err != nil {
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "GetRandomPush", table, "Find", err), log.Any("filter", f))
return
}
if len(data) < 1 {
return
}
if redisc == nil {
return
}
tempd := make([]string, len(data))
for i := range data {
var strB []byte
strB, err = json.Marshal(data[i])
if err != nil {
return
}
tempd[i] = string(strB)
}
if _, err = redisc.SAdd(redisK, tempd); err != nil {
return
}
_, _ = redisc.ExpireKey(redisK, time.Minute*10)
}
tempd, err := redisc.SRandMemberN(redisK, int64(size))
if len(tempd) < 1 {
return data, errors.New("redis key is null")
}
data = make([]AudioBookBase, len(tempd))
for i := range data {
_ = json.Unmarshal([]byte(tempd[i]), &data[i])
}
return
}
func GetRandomPush_PermissionBuy(size int) (data []AudioBookBase, err error) {
data = make([]AudioBookBase, 0)
redisK := "tempSet:" + RedisSetKey + ":randomData:permissionBuy"
redisc := appg.Redis
if redisc == nil || !redisc.Exists(redisK) {
f := bson.M{"isActive": true, "contentSet.listenPermission": ListenPermissionBuy}
var total int64
total, err = randomCount(f)
if err != nil {
return
}
var limit int64 = 100
var skip int64 = 0
if total-limit > limit {
skip = rand.Int63n(total - limit)
}
opts := options.FindOptions{
Skip: &skip,
Limit: &limit,
}
if err = coll(nil).Find(&data, f, &opts); err != nil {
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "GetRandomPush_PermissionBuy", table, "Find", err), log.Any("filter", f))
return
}
if len(data) < 1 {
return
}
if redisc == nil {
return
}
tempd := make([]string, len(data))
for i := range data {
var strB []byte
strB, err = json.Marshal(data[i])
if err != nil {
return
}
tempd[i] = string(strB)
}
if _, err = redisc.SAdd(redisK, tempd); err != nil {
return
}
_, _ = redisc.ExpireKey(redisK, time.Minute*10)
}
tempd, err := redisc.SRandMemberN(redisK, int64(size))
if len(tempd) < 1 {
return data, errors.New("redis key is null")
}
data = make([]AudioBookBase, len(tempd))
for i := range data {
_ = json.Unmarshal([]byte(tempd[i]), &data[i])
}
return
}
func GetRandomPush_PermissionVIP(size int) (data []AudioBookBase, err error) {
data = make([]AudioBookBase, 0)
redisK := "tempSet:" + RedisSetKey + ":randomData:PermissionVIP"
redisc := appg.Redis
if redisc == nil || !redisc.Exists(redisK) {
f := bson.M{"isActive": true, "contentSet.listenPermission": ListenPermissionVIP}
var total int64
total, err = randomCount(f)
if err != nil {
return
}
var limit int64 = 100
var skip int64 = 0
if total-limit > limit {
skip = rand.Int63n(total - limit)
}
opts := options.FindOptions{
Skip: &skip,
Limit: &limit,
}
if err = coll(nil).Find(&data, f, &opts); err != nil {
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "GetRandomPush_PermissionVIP", table, "Find", err), log.Any("filter", f))
return
}
if len(data) < 1 {
return
}
if redisc == nil {
return
}
tempd := make([]string, len(data))
for i := range data {
var strB []byte
strB, err = json.Marshal(data[i])
if err != nil {
return
}
tempd[i] = string(strB)
}
if _, err = redisc.SAdd(redisK, tempd); err != nil {
return
}
_, _ = redisc.ExpireKey(redisK, time.Minute*10)
}
tempd, err := redisc.SRandMemberN(redisK, int64(size))
if len(tempd) < 1 {
return data, errors.New("redis key is null")
}
data = make([]AudioBookBase, len(tempd))
for i := range data {
_ = json.Unmarshal([]byte(tempd[i]), &data[i])
}
return
}
func GetFTypes() (data []interface{}, err error) {
data = make([]interface{}, 0)
redisKey := RedisSetKey + ":fType"
redisc := appg.Redis
if redisc == nil || !redisc.Exists(redisKey) {
data, err = coll(nil).Distinct("fType", bson.M{})
if err != nil {
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "GetCitys", table, "Distinct", err))
return nil, err
}
if redisc == nil {
return data, err
}
jsonBytes, err := json.Marshal(data)
if err != nil {
return data, err
}
_ = redisc.Set(redisKey, string(jsonBytes), time.Minute*10)
return data, err
}
str, err := redisc.Get(redisKey)
if err != nil {
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "GetFTypes", table, "Find", err))
return nil, err
}
if str == nil {
return data, errors.New("redis key is null")
}
err = json.Unmarshal([]byte(*str), &data)
return
}
func SearchTitle(title string, page commod.Page) (data []AudioBookBase, hasNext bool, err error) {
data = make([]AudioBookBase, 0)
skip := int64(page.Skip())
limit := int64(page.Limit() + 1)
opts := options.FindOptions{
Skip: &skip,
Limit: &limit,
Sort: bson.D{{Key: "createdAt", Value: 1}},
}
f := bson.M{"isActive": true}
f["$or"] = bson.A{
bson.M{"title": primitive.Regex{
Pattern: title,
Options: "",
}},
}
if err = coll(nil).Find(&data, f, &opts); err != nil {
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "SearchTitle", table, "Find", err), log.Any("cond", f))
return
}
if uint64(len(data)) > page.PageSize {
hasNext = true
data = data[:page.PageSize]
}
return
}
func IncCount(id primitive.ObjectID, inc CountInc) (err error) {
res, err := coll(nil).UpdateOne(bson.M{"_id": id}, bson.M{"$inc": inc})
if err != nil {
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "IncCount", table, "UpdateOne", err), log.Any("id", id), log.Any("inc", inc))
return
}
if res.ModifiedCount <= 0 {
if err != nil {
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "IncCount", table, "UpdateOne", err), log.Any("id", id), log.Any("inc", inc), log.Any("res", res))
return
}
}
return
}
func GetNew(opt searcher.Opter) (data []AudioBookAppRes, hasNext bool, err error) {
data = make([]AudioBookAppRes, 0)
skip := opt.Skip()
limit := opt.Limit() + 1
opts := options.FindOptions{
Skip: &skip,
Limit: &limit,
Sort: bson.D{{Key: "createdAt", Value: -1}},
}
f := bson.M{"isActive": true}
if err = coll(nil).Find(&data, f, &opts); err != nil {
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "GetNew", table, "Find", err), log.Any("cond", f))
return
}
if int64(len(data)) > opt.Limit() {
hasNext = true
data = data[:opt.Limit()]
}
return
}
func randomCount(f bson.M) (count int64, err error) {
count, err = coll(nil).Count(f)
if err != nil {
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "GetCitys", table, "Distinct", err))
return
}
return
}
// todo web
// StdFind 通用查询
func StdFind(q QuerySelector, page commod.Page) (data []AudioBook, total int64, err error) {
data = make([]AudioBook, 0)
skip := int64(page.Skip())
limit := int64(page.Limit())
opts := options.FindOptions{
Skip: &skip,
Limit: &limit,
}
f, err := common.ToBsonM(q)
if err != nil {
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "StdFind", table, "ToBsonM", err), log.Any("cond", f))
return
}
if q.Title != nil {
f["title"] = primitive.Regex{
Pattern: *q.Title,
Options: "",
}
}
if err = coll(nil).Find(&data, f, &opts); err != nil {
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "StdFind", table, "Find", err), log.Any("cond", f))
return
}
total, err = coll(nil).Count(f)
if err != nil {
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "StdFind", table, "Count", err), log.Any("cond", f))
}
return
}
// IsExisted 查询
func IsExisted(id primitive.ObjectID) (ok bool, err error) {
ok, err = coll(nil).Exists(bson.M{"_id": id})
if err != nil {
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "IsExisted", table, "Exists", err), log.Any("id", id))
return
}
return
}
// InsertAudioBook 插入一条数据
func InsertAudioBook(p *AudioBook) (err error) {
p.CreatedAt = time.Now()
if _, err = coll(nil).InsertOne(p); err != nil {
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "InsertAudioBook", table, "InsertOne", err))
}
return
}
// InsertBulket 插入一条数据
func InsertBulket(p []AudioBookUpsertEdit) (err error) {
fmt.Println("------------", len(p))
now := time.Now()
wm := make([]mongo.WriteModel, len(p))
for k := range p {
filter := bson.M{"number": p[k].Number}
update := bson.M{"$set": p[k], "$setOnInsert": bson.M{"createdAt": now, "contentSet": p[k].ContentSet}}
model := mongo.NewUpdateOneModel().
SetFilter(filter).
SetUpdate(update).
SetUpsert(true)
wm[k] = model
}
ordered := false
opts := options.BulkWriteOptions{
Ordered: &ordered,
}
if _, err = coll(nil).Bulk(wm, &opts); err != nil {
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "InsertMany", table, "InsertMany", err))
}
return
}
// InsertAudioBook 插入一条数据
func InsertMany(p []AudioBook) (err error) {
if _, err = coll(nil).InsertMany(p); err != nil {
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "InsertMany", table, "InsertMany", err))
}
return
}
// UpdateAudioBook 修改AudioBook类型
func UpdateAudioBookBatch(sets []EditSelector) (err error) {
now := time.Now()
wm := make([]mongo.WriteModel, len(sets))
for k := range sets {
sets[k].UpdatedAt = now
filter := bson.M{"_id": sets[k].ID}
update := bson.M{"$set": sets[k]}
model := mongo.NewUpdateOneModel().
SetFilter(filter).
SetUpdate(update).
SetUpsert(false)
wm[k] = model
}
ordered := false
opts := options.BulkWriteOptions{
Ordered: &ordered,
}
if _, err = coll(nil).Bulk(wm, &opts); err != nil {
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "InsertMany", table, "InsertMany", err))
}
return
}
// UpdateAudioBook 修改AudioBook类型
func UpdateAudioBook(set EditSelector) error {
set.UpdatedAt = time.Now()
setM, err := common.ToBsonM(set)
if err != nil {
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "ToBsonM", table, "UpdateOne", err),
log.Any("set", set))
return err
}
if _, err = coll(nil).UpdateOne(bson.M{"_id": set.ID}, bson.M{"$set": setM}); err != nil {
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "UpdateAudioBook", table, "UpdateOne", err),
log.Any("set", set),
)
return err
}
return nil
}
// RemoveAudioBook 删除AudioBook类型
func RemoveAudioBook(id string) error {
OID, err := primitive.ObjectIDFromHex(id)
if err != nil {
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "RemoveAudioBook", table, "ObjectIDFromHex", err),
log.Any("id", id),
)
return err
}
if _, err = coll(nil).DeleteOne(bson.M{"_id": OID}); err != nil {
log.Warn(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "RemoveAudioBook", table, "DeleteOne", err),
log.Any("OID", OID),
)
return err
}
return nil
}
// todo skd
// 获取ES同步数据
func GetListByUpdateTimeRange(start time.Time, end time.Time) (data []AudioBookBase, err error) {
var query = bson.M{
"updatedAt": bson.M{"$gte": start, "$lt": end},
}
if err = coll(nil).Find(&data, query); err != nil {
log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "GetListByUpdateTimeRange", table, "Find", err),
log.Any("start", start),
log.Any("end", end),
)
return
}
return
}
func GetListByCond(cond bson.M, opts *options.FindOptions) ([]AudioBook, error) {
var data []AudioBook
if err := coll(nil).Find(&data, cond, opts); err != nil {
return nil, err
}
return data, nil
}
+69
View File
@@ -0,0 +1,69 @@
package audiobookmod
import (
"fmt"
"91porn-server/common/elastic"
"91porn-server/common/log"
"91porn-server/models"
)
var es *elastic.Client
const ESTable = models.ESInfoAudioBookTable
func InitESIndex() {
es = elastic.Init()
var setting = elastic.M{
"settings": elastic.M{
"number_of_shards": elastic.NumberOfShards,
"number_of_replicas": elastic.NumberOfReplicas,
"analysis": elastic.M{
"analyzer": elastic.M{
"ik": elastic.M{
"tokenizer": elastic.AnalyzerIkMaxWord,
},
},
},
},
"mappings": elastic.M{
"properties": elastic.M{
"title": elastic.M{
"type": "text",
"analyzer": elastic.AnalyzerIkMaxWord,
"search_analyzer": elastic.AnalyzerIkSmart,
},
},
},
}
if err := es.CreateIndices(ESTable, setting); err != nil {
panic(fmt.Sprintf("%s index indeices err ==>[%+v]", ESTable, err))
}
}
func Search(keywords string, from int64, size int64) (data []ESAudioBookSource, err error) {
query := elastic.M{
"query": elastic.M{
"bool": elastic.M{
"must": elastic.A{
{"multi_match": elastic.M{
"query": keywords,
"fields": []string{"title"}},
},
{"term": elastic.M{"isActive": true}},
},
},
},
"from": from,
"size": size,
}
if err = elastic.Init().Search(ESTable, &data, query); err != nil {
log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "Search", table, "CommonSearch", err),
log.Any("keywords", keywords),
log.Any("from", from),
log.Any("size", size),
)
return
}
return
}
+145
View File
@@ -0,0 +1,145 @@
package audiobookmod
import (
"time"
"91porn-server/common/db"
"go.mongodb.org/mongo-driver/bson/primitive"
)
var mdb *db.MongoDB
const (
ListenPermissionVIP = 0
ListenPermissionBuy = 1
ListenPermissionBuyZone = "付费专区"
)
type Content struct {
EpisodeNumber int `json:"episodeNumber" bson:"episodeNumber" ` //第几集
ListenPermission int `json:"listenPermission" bson:"listenPermission"` //收听权限 0:会员 1:金币购买 3:试听
Price int64 `json:"price" bson:"price"` //购买价格
Name string `json:"name" bson:"name"` //章节名
URL string `json:"contentUrl" bson:"contentUrl"` //资源地址
MediaSize int64 `json:"mediaSize" bson:"mediaSize"` //资源大小
IsBrought bool `json:"isBrought" bson:"-"` //是否购买
}
type AudioBook struct {
ID primitive.ObjectID `json:"id" bson:"_id,omitempty"`
Title string `json:"title" bson:"title,omitempty"` //标题
Anchor string `json:"anchor" bson:"anchor"` //作者
Cover string `json:"cover" bson:"cover"` //封面
ContentSet []Content `json:"contentSet" bson:"contentSet"` //内容集
TotalEpisode int `json:"totalEpisode" bson:"totalEpisode"` //总集数
TrialSet []Content `json:"trialSet" bson:"trialSet"` //试听集
FType string `json:"fType" bson:"fType"` //小说类型
Summary string `json:"summary" bson:"summary"` //简介
IsActive bool `json:"isActive" bson:"isActive"` //是否激活
CountPurchases int64 `json:"countPurchases" bson:"countPurchases"` //购买数
CountBrowse int64 `json:"countBrowse" bson:"countBrowse"` //浏览数
CountCollect int64 `json:"countCollect" bson:"countCollect"` //收藏数
Number int64 `json:"number" bson:"number,omitempty"` //编号
CreatedAt time.Time `json:"createdAt" bson:"createdAt,omitempty"` //创建时间
UpdatedAt time.Time `json:"updatedAt" bson:"updatedAt,omitempty"` //修改时间
}
func Init() {
mdb = db.Init(table)
initIndex()
}
type QuerySelector struct {
ID *primitive.ObjectID `json:"id,omitempty" bson:"_id,omitempty"`
Title *string `json:"title,omitempty" bson:"title,omitempty"` //标题
Anchor *string `json:"anchor,omitempty" bson:"anchor,omitempty"` //作者
FType *string `json:"fType,omitempty" bson:"fType,omitempty"` //小说类型
IsActive *bool `json:"isActive,omitempty" bson:"isActive,omitempty"` //是否激活
Number *int `json:"number,omitempty" bson:"number,omitempty"` //编号
}
type EditSelector struct {
ID primitive.ObjectID `json:"id" bson:"_id,omitempty"`
Title string `json:"title" bson:"title,omitempty"` //标题
Anchor string `json:"anchor" bson:"anchor"` //作者
Cover string `json:"cover" bson:"cover"` //封面
ContentSet []Content `json:"contentSet" bson:"contentSet"` //内容集
TotalEpisode int `json:"totalEpisode" bson:"totalEpisode"` //总集数
TrialSet []Content `json:"trialSet" bson:"trialSet"` //试听集
FType string `json:"fType" bson:"fType"` //小说类型
Summary string `json:"summary" bson:"summary"` //简介
IsActive bool `json:"isActive" bson:"isActive"` //是否激活
CountPurchases int64 `json:"countPurchases" bson:"countPurchases"` //购买数
CountBrowse int64 `json:"countBrowse" bson:"countBrowse"` //浏览数
CountCollect int64 `json:"countCollect" bson:"countCollect"` //收藏数
Number int `json:"number" bson:"number,omitempty"` //编号
UpdatedAt time.Time `json:"updatedAt" bson:"updatedAt,omitempty"` //修改时间
}
const RedisSetKey = "audiobook"
// todo app
type AudioBookAppRes struct {
ID primitive.ObjectID `json:"id" bson:"_id,omitempty"`
Title string `json:"title" bson:"title,omitempty"` //标题
Anchor string `json:"-" bson:"anchor"` //作者
Cover string `json:"cover" bson:"cover"` //封面
ContentSet []Content `json:"contentSet" bson:"contentSet"` //内容集
TrialSet []Content `json:"trialSet" bson:"trialSet"` //试听集
FType string `json:"fType" bson:"fType"` //小说类型
Summary string `json:"summary" bson:"summary"` //简介
IsActive bool `json:"isActive" bson:"isActive"` //是否激活
TotalEpisode int `json:"totalEpisode" bson:"totalEpisode"` //总集数
CountPurchases int64 `json:"countPurchases" bson:"countPurchases"` //购买数
CountBrowse int64 `json:"countBrowse" bson:"countBrowse"` //浏览数
OriginalPrice int64 `json:"originalPrice" bson:"-"` //原价
DiscountPrice int64 `json:"discountPrice" bson:"-"` //优惠价(用户实际需要支付的价格)
}
type AudioBookBase struct {
ID primitive.ObjectID `json:"id" bson:"_id,omitempty"`
Title string `json:"title" bson:"title,omitempty"` //标题
Anchor string `json:"anchor" bson:"anchor"` //作者
Cover string `json:"cover" bson:"cover"` //封面
TotalEpisode int `json:"totalEpisode" bson:"totalEpisode"` //总集数
TrialSet []Content `json:"trialSet" bson:"trialSet"` //试听集
FType string `json:"fType" bson:"fType"` //小说类型
Summary string `json:"summary" bson:"summary"` //简介
CountPurchases int64 `json:"countPurchases" bson:"countPurchases"` //购买数
CountBrowse int64 `json:"countBrowse" bson:"countBrowse"` //浏览数
ContentSet []struct {
EpisodeNumber int `json:"episodeNumber" bson:"episodeNumber" ` //第几集
ListenPermission int `json:"listenPermission" bson:"listenPermission"` //收听权限 0:会员 1:金币购买 3:试听
Price int64 `json:"price" bson:"price"` //购买价格
Name string `json:"name" bson:"name"` //章节名
MediaSize int64 `json:"mediaSize" bson:"mediaSize"` //资源大小
} `json:"contentSet" bson:"contentSet"`
}
type AudioBookUpsertEdit struct {
Title string `json:"title" bson:"title,omitempty"` //标题
Anchor string `json:"anchor" bson:"anchor"` //作者
Cover string `json:"cover" bson:"cover"` //封面
ContentSet []Content `json:"contentSet" bson:"-"` //内容集
TotalEpisode int `json:"totalEpisode" bson:"totalEpisode"` //总集数
TrialSet []Content `json:"trialSet" bson:"trialSet"` //试听集
FType string `json:"fType" bson:"fType"` //小说类型
Summary string `json:"summary" bson:"summary"` //简介
IsActive bool `json:"isActive" bson:"isActive"` //是否激活
Number int64 `json:"number" bson:"number,omitempty"` //编号
CreatedAt time.Time `json:"createdAt" bson:"createdAt,omitempty"` //创建时间
UpdatedAt time.Time `json:"updatedAt" bson:"updatedAt,omitempty"` //修改时间
}
type CountInc struct {
CountPurchases *int `json:"countPurchases" bson:"countPurchases,omitempty"` //购买数
CountBrowse *int `json:"countBrowse" bson:"countBrowse,omitempty"` //浏览数
CountCollect *int `json:"countCollect" bson:"countCollect,omitempty"` //收藏数
}
type ESAudioBookSource struct {
ID string `json:"_id"`
Source AudioBookBase `json:"_source"`
}