326 lines
8.2 KiB
Go
326 lines
8.2 KiB
Go
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
|
|
}
|