@@ -0,0 +1,325 @@
|
||||
package moduleconfmod
|
||||
|
||||
import (
|
||||
"91porn-server/common/log"
|
||||
"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"
|
||||
)
|
||||
|
||||
var mdb *db.MongoDB
|
||||
|
||||
const table = models.ModuleConf
|
||||
|
||||
var moduleMetadataCache = newModuleSnapshotCache(loadModuleMetadata, time.Now, moduleSnapshotTTL, moduleSnapshotRetryDelay)
|
||||
|
||||
func loadModuleMetadata() (modules []ModuleConf, err error) {
|
||||
err = coll(nil).Find(&modules, bson.M{})
|
||||
return
|
||||
}
|
||||
|
||||
// InitIndex 设置index
|
||||
func initIndex() {
|
||||
coll := coll(nil)
|
||||
many := []mongo.IndexModel{
|
||||
{
|
||||
Keys: bson.D{{Key: "moduleName", Value: 1}, {Key: "subModuleName", 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)
|
||||
}
|
||||
|
||||
// InsertOne 插入一条数据
|
||||
func InsertOne(p *ModuleConf) error {
|
||||
p.HaiJiaoStyle.NormalizeRefreshConfig()
|
||||
if err := p.HaiJiaoStyle.ValidateRefreshConfig(); err != nil {
|
||||
return err
|
||||
}
|
||||
if err := p.ValidateSchedule(); err != nil {
|
||||
return err
|
||||
}
|
||||
p.CreatedAt = time.Now()
|
||||
_, err := coll(nil).InsertOne(p)
|
||||
if err == nil {
|
||||
moduleMetadataCache.invalidate()
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
// UpdateOne 更新一条数据
|
||||
func UpdateOne(set EditSelector) error {
|
||||
current, err := getByIDFromDB(set.ID)
|
||||
if err != nil {
|
||||
return err
|
||||
}
|
||||
if set.HaiJiaoStyle != nil {
|
||||
set.HaiJiaoStyle.NormalizeRefreshConfig()
|
||||
if err = set.HaiJiaoStyle.ValidateRefreshConfig(); err != nil {
|
||||
return err
|
||||
}
|
||||
}
|
||||
if set.ClearOnlineAt && set.OnlineAt != nil {
|
||||
return fmt.Errorf("onlineAt and clearOnlineAt cannot be set together")
|
||||
}
|
||||
if set.ClearOfflineAt && set.OfflineAt != nil {
|
||||
return fmt.Errorf("offlineAt and clearOfflineAt cannot be set together")
|
||||
}
|
||||
if set.OnlineAt != nil {
|
||||
current.OnlineAt = set.OnlineAt
|
||||
}
|
||||
if set.OfflineAt != nil {
|
||||
current.OfflineAt = set.OfflineAt
|
||||
}
|
||||
if set.ClearOnlineAt {
|
||||
current.OnlineAt = nil
|
||||
}
|
||||
if set.ClearOfflineAt {
|
||||
current.OfflineAt = nil
|
||||
}
|
||||
if err = current.ValidateSchedule(); err != nil {
|
||||
return err
|
||||
}
|
||||
set.UpdatedAt = time.Now()
|
||||
update := bson.M{"$set": set}
|
||||
unset := bson.M{}
|
||||
if set.ClearOnlineAt {
|
||||
unset["onlineAt"] = ""
|
||||
}
|
||||
if set.ClearOfflineAt {
|
||||
unset["offlineAt"] = ""
|
||||
}
|
||||
if len(unset) > 0 {
|
||||
update["$unset"] = unset
|
||||
}
|
||||
_, err = coll(nil).UpdateOne(bson.M{"_id": set.ID}, update)
|
||||
if err == nil {
|
||||
moduleMetadataCache.invalidate()
|
||||
}
|
||||
return err
|
||||
}
|
||||
|
||||
func (p ModuleConf) ValidateSchedule() error {
|
||||
if p.OnlineAt != nil && p.OfflineAt != nil && !p.OfflineAt.After(*p.OnlineAt) {
|
||||
return fmt.Errorf("offlineAt must be later than onlineAt")
|
||||
}
|
||||
return nil
|
||||
}
|
||||
|
||||
func (p ModuleConf) IsActiveAt(now time.Time) bool {
|
||||
if p.Status != 1 || p.DeletedAt != nil {
|
||||
return false
|
||||
}
|
||||
if p.OnlineAt != nil && p.OnlineAt.After(now) {
|
||||
return false
|
||||
}
|
||||
return p.OfflineAt == nil || p.OfflineAt.After(now)
|
||||
}
|
||||
|
||||
// DeleteOne 删除一条数据
|
||||
func DeleteOne(id primitive.ObjectID) (err error) {
|
||||
now := time.Now()
|
||||
status := uint8(0)
|
||||
set := EditSelector{ID: id, DeletedAt: &now, Status: &status}
|
||||
return UpdateOne(set)
|
||||
}
|
||||
|
||||
// GetByID 根据id获取一条记录
|
||||
func GetByID(id primitive.ObjectID) (conf ModuleConf, err error) {
|
||||
snapshot, err := moduleMetadataCache.get()
|
||||
if err != nil {
|
||||
return ModuleConf{}, err
|
||||
}
|
||||
conf, ok := snapshot.findByID(id)
|
||||
if !ok {
|
||||
return ModuleConf{}, mongo.ErrNoDocuments
|
||||
}
|
||||
return conf, nil
|
||||
}
|
||||
|
||||
func getByIDFromDB(id primitive.ObjectID) (conf ModuleConf, err error) {
|
||||
err = coll(nil).FindOne(&conf, bson.M{"_id": id})
|
||||
return
|
||||
}
|
||||
|
||||
// GetModuleConf 获取一个模块下的所有配置
|
||||
func GetModuleConf(moduleName string) (ret []ModuleConf, err error) {
|
||||
snapshot, err := moduleMetadataCache.get()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return snapshot.findByModuleName(moduleName), nil
|
||||
}
|
||||
|
||||
// GetModuleConfByType 根据类型获取配置
|
||||
func GetModuleConfByType(moduleType int) (ret []ModuleConf, err error) {
|
||||
snapshot, err := moduleMetadataCache.get()
|
||||
if err != nil {
|
||||
log.Error(fmt.Sprintf("[METHOD-%s]==> Model %s %s fail error:%+v:", "GetModuleConfByType", table, "snapshot", err))
|
||||
return nil, err
|
||||
}
|
||||
return snapshot.findByType(moduleType), nil
|
||||
}
|
||||
|
||||
// GetAllModule 获取所有开启(status=1)的模块配置
|
||||
func GetAllModule() (ret []ModuleConf, err error) {
|
||||
snapshot, err := moduleMetadataCache.get()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return snapshot.enabled(), nil
|
||||
}
|
||||
|
||||
// GetAllActiveModule 获取当前处于有效展示时间内的亚模块。
|
||||
func GetAllActiveModule(now time.Time) (ret []ModuleConf, err error) {
|
||||
snapshot, err := moduleMetadataCache.get()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return snapshot.activeAt(now), nil
|
||||
}
|
||||
|
||||
// ExcludedVideoModuleIDs 返回指定场景需要从聚合列表排除的亚模块 ID。
|
||||
func ExcludedVideoModuleIDs(now time.Time, recommend bool) ([]string, error) {
|
||||
snapshot, err := moduleMetadataCache.get()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return snapshot.excludedVideoModuleIDs(now, recommend), nil
|
||||
}
|
||||
|
||||
// ExcludedSearchModuleIDs 返回配置为不进入搜索列表的亚模块 ID。
|
||||
func ExcludedSearchModuleIDs() ([]string, error) {
|
||||
snapshot, err := moduleMetadataCache.get()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return snapshot.excludedSearchModuleIDs(), nil
|
||||
}
|
||||
|
||||
// BlockedOutsideSearchModuleIDs 返回当前仅允许通过搜索入口访问的亚模块 ID 集合。
|
||||
func BlockedOutsideSearchModuleIDs(moduleIDs []string, now time.Time) (map[string]struct{}, error) {
|
||||
objectIDs := make([]primitive.ObjectID, 0, len(moduleIDs))
|
||||
seen := make(map[primitive.ObjectID]struct{}, len(moduleIDs))
|
||||
for _, moduleID := range moduleIDs {
|
||||
id, parseErr := primitive.ObjectIDFromHex(moduleID)
|
||||
if parseErr != nil || id.IsZero() {
|
||||
continue
|
||||
}
|
||||
if _, ok := seen[id]; ok {
|
||||
continue
|
||||
}
|
||||
seen[id] = struct{}{}
|
||||
objectIDs = append(objectIDs, id)
|
||||
}
|
||||
if len(objectIDs) == 0 {
|
||||
return map[string]struct{}{}, nil
|
||||
}
|
||||
snapshot, err := moduleMetadataCache.get()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return snapshot.blockedOutsideSearchModuleIDs(objectIDs, now), nil
|
||||
}
|
||||
|
||||
// CanBrowseModule 判断亚模块是否能从搜索以外的普通入口访问。
|
||||
func CanBrowseModule(moduleID primitive.ObjectID, now time.Time) (bool, error) {
|
||||
module, err := GetByID(moduleID)
|
||||
if err != nil {
|
||||
return false, err
|
||||
}
|
||||
return module.IsActiveAt(now), nil
|
||||
}
|
||||
|
||||
// Search 根据搜索条件检索
|
||||
func Search(q QuerySelector, page commod.Page) (resp ListResp, err error) {
|
||||
skip := int64(page.Skip())
|
||||
limit := int64(page.Limit() + 1)
|
||||
opts := options.FindOptions{
|
||||
Skip: &skip,
|
||||
Limit: &limit,
|
||||
Sort: bson.D{{Key: "sortNum", Value: 1}},
|
||||
}
|
||||
filter := bson.M{}
|
||||
if err != nil {
|
||||
return
|
||||
}
|
||||
if q.ModuleName != nil {
|
||||
filter["moduleName"] = primitive.Regex{
|
||||
Pattern: *q.ModuleName,
|
||||
}
|
||||
}
|
||||
if q.SubModuleName != nil {
|
||||
filter["subModuleName"] = primitive.Regex{
|
||||
Pattern: *q.SubModuleName,
|
||||
}
|
||||
}
|
||||
if q.Type != nil {
|
||||
filter["type"] = *q.Type
|
||||
}
|
||||
if q.ShowType != nil {
|
||||
filter["showType"] = q.ShowType
|
||||
}
|
||||
data := []ModuleConf{}
|
||||
if err = coll(nil).Find(&data, filter, &opts); err != nil {
|
||||
return
|
||||
}
|
||||
total := int64(0)
|
||||
if total, err = coll(nil).Count(filter); err != nil {
|
||||
return
|
||||
}
|
||||
hasNext := false
|
||||
if uint64(len(data)) > page.Limit() {
|
||||
hasNext = true
|
||||
data = data[:page.Limit()]
|
||||
}
|
||||
resp.List = data
|
||||
resp.Total = total
|
||||
resp.HasNext = hasNext
|
||||
return
|
||||
}
|
||||
|
||||
// FindByIDs 根据section id批量获取section详情
|
||||
func FindByIDs(ids []primitive.ObjectID) (list []ModuleConf, err error) {
|
||||
if len(ids) == 0 {
|
||||
return nil, nil
|
||||
}
|
||||
snapshot, err := moduleMetadataCache.get()
|
||||
if err != nil {
|
||||
return nil, err
|
||||
}
|
||||
return snapshot.findByIDs(ids), nil
|
||||
}
|
||||
|
||||
func FindOneById(id primitive.ObjectID) (ModuleConf, error) {
|
||||
return GetByID(id)
|
||||
}
|
||||
|
||||
// QueryAllList 分页查询文档
|
||||
func QueryAllList(filter primitive.M, opts ...*options.FindOptions) (out []*ModuleConf, 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
|
||||
}
|
||||
Reference in New Issue
Block a user