Initial commit
Co-Authored-By: Claude Opus 5.5 (1M context) <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,576 @@
|
||||
package configser
|
||||
|
||||
import (
|
||||
"context"
|
||||
"regexp"
|
||||
"strconv"
|
||||
"strings"
|
||||
"sync"
|
||||
"videoweb/app/api/proto"
|
||||
"videoweb/app/service/translationser"
|
||||
"videoweb/pub/adcenter"
|
||||
"videoweb/pub/common/log"
|
||||
"videoweb/pub/common/netutil"
|
||||
"videoweb/pub/common/srvdef"
|
||||
"videoweb/pub/dataReport"
|
||||
"videoweb/pub/models/announcementmod"
|
||||
"videoweb/pub/models/cfg"
|
||||
"videoweb/pub/models/ipblackmod"
|
||||
"videoweb/pub/models/richtextcontentmod"
|
||||
"videoweb/pub/models/videotagmod"
|
||||
|
||||
"github.com/robfig/cron/v3"
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
)
|
||||
|
||||
var (
|
||||
CacheMgr CacheInfo //
|
||||
skdCron *cron.Cron
|
||||
)
|
||||
|
||||
// richTextImgSrcRe 匹配富文本HTML里 img 标签的 src 图片地址,兼容单引号、双引号和JSON转义后的双引号。
|
||||
var richTextImgSrcRe = regexp.MustCompile(`(?i)(<img\b[^>]*?\s*)src\s*=\s*(\\?"([^"\\]*)\\?"|'([^']*)')`)
|
||||
|
||||
type CacheInfo struct {
|
||||
Lock sync.RWMutex // 读写锁
|
||||
Config proto.ConfigInfo // 系统配置缓存
|
||||
Advitise proto.AdvitiseData
|
||||
AdvitiseMap map[string]adcenter.AdCacheInfo
|
||||
TagCategoryList []proto.VideoTagCategoryData
|
||||
TotalHistory int64
|
||||
IpBlackMaps map[string]struct{}
|
||||
TagMaps map[int64]proto.TagsInfoData
|
||||
NewAddressInfo proto.NewAddressInfo
|
||||
AppRichTexts []proto.AppRichTextItemResp
|
||||
Announcements []*proto.AnnouncementItem
|
||||
}
|
||||
|
||||
type appRichTextCacheItem struct {
|
||||
Id int64 `bson:"_id,omitempty"`
|
||||
Title string `bson:"title"`
|
||||
Content string `bson:"content"`
|
||||
Desc string `bson:"desc"`
|
||||
}
|
||||
|
||||
func init() {
|
||||
skdCron = cron.New(cron.WithSeconds()) // 秒级定时任务
|
||||
CacheMgr.Config = proto.ConfigInfo{}
|
||||
CacheMgr.IpBlackMaps = make(map[string]struct{})
|
||||
}
|
||||
|
||||
func Start() {
|
||||
ctx := context.Background()
|
||||
dataReport.StartSDKConfigCron()
|
||||
UpdateConfigInfo(ctx)
|
||||
UpdateAdvitiseDataFromJt()
|
||||
updateIpBlack()
|
||||
updateTagsCache()
|
||||
updateAppRichTexts()
|
||||
updateAnnouncements()
|
||||
_, _ = skdCron.AddFunc("0 */5 * * * ?", func() {
|
||||
UpdateConfigInfo(ctx)
|
||||
UpdateAdvitiseDataFromJt()
|
||||
updateIpBlack()
|
||||
updateTagsCache()
|
||||
updateAppRichTexts()
|
||||
})
|
||||
_, _ = skdCron.AddFunc("0 */10 * * * ?", func() {
|
||||
updateAnnouncements()
|
||||
})
|
||||
|
||||
skdCron.Start()
|
||||
}
|
||||
|
||||
func updateTagsCache() {
|
||||
filter := bson.M{videotagmod.FN.VideoTagInfo.Status: true}
|
||||
opts := &options.FindOptions{}
|
||||
opts.SetLimit(5000)
|
||||
opts.SetSort(bson.M{videotagmod.FN.VideoTagInfo.Sort: -1})
|
||||
list, err := videotagmod.FindManyVideoTagInfos(context.Background(), filter, opts)
|
||||
if err != nil {
|
||||
log.Warn("updateTaggCache.FFindManyVideoTagInfos", log.Any("err", err))
|
||||
return
|
||||
}
|
||||
tempMaps := make(map[int64]proto.TagsInfoData)
|
||||
for _, v := range list {
|
||||
tempMaps[v.Id] = proto.TagsInfoData{
|
||||
Id: v.Id,
|
||||
Name: v.Title,
|
||||
SeoInfo: v.SeoInfo,
|
||||
}
|
||||
}
|
||||
CacheMgr.Lock.Lock()
|
||||
defer CacheMgr.Lock.Unlock()
|
||||
CacheMgr.TagMaps = tempMaps
|
||||
}
|
||||
|
||||
func UpdateConfigInfo(ctx context.Context) {
|
||||
config := proto.ConfigInfo{}
|
||||
newAddressInfo := proto.NewAddressInfo{}
|
||||
|
||||
filter := bson.M{cfg.FN.SysCfg.Id: 1}
|
||||
sysCfg, _ := cfg.FindOneSysCfg(context.Background(), filter)
|
||||
if sysCfg == nil {
|
||||
return
|
||||
}
|
||||
|
||||
config.NewUrlAddr = sysCfg.NewUrlAddr
|
||||
config.NewUrlAddr1 = sysCfg.NewUrlAddr1
|
||||
config.NewUrlAddr2 = sysCfg.NewUrlAddr2
|
||||
config.ForeverUrlAddr = sysCfg.ForeverUrlAddr
|
||||
config.GmailAddr = sysCfg.GmailAddr
|
||||
config.AppAddr = sysCfg.AppAddr
|
||||
config.OfficialAppAddr = sysCfg.OfficialAppAddr
|
||||
config.WeiChart = sysCfg.WeiChart
|
||||
config.QQ = sysCfg.QQ
|
||||
config.TgGroup = sysCfg.TgGroup
|
||||
config.PotaoGroup = sysCfg.PotaoGroup
|
||||
config.GitAddr = sysCfg.GitAddr
|
||||
config.TwitterAddr = sysCfg.TwitterAddr
|
||||
config.Telegram = sysCfg.Telegram
|
||||
config.TelegramAdd = sysCfg.TelegramAdd
|
||||
config.TranslationAddr = sysCfg.TranslationAddr
|
||||
config.ImgCdn = sysCfg.ImgAppCdn
|
||||
config.TsCdn = sysCfg.MediaAppCdn
|
||||
config.ImgAppUsCdn = sysCfg.ImgAppUsCdn
|
||||
config.MediaAppUsCdn = sysCfg.MediaAppUsCdn
|
||||
config.PdfAddr = sysCfg.PdfAddr
|
||||
|
||||
config.WebTitle = sysCfg.WebTitle
|
||||
config.WebKeyworld = sysCfg.WebKeyworld
|
||||
config.WebDescription = sysCfg.WebDescription
|
||||
config.WebSiteName = sysCfg.WebSiteName
|
||||
config.WebAddr = sysCfg.WebAddr
|
||||
config.DHNewUrlAddr1 = sysCfg.DHNewUrlAddr1
|
||||
config.DHNewUrlAddr2 = sysCfg.DHNewUrlAddr2
|
||||
config.DHNewUrlAddr3 = sysCfg.DHNewUrlAddr3
|
||||
config.UseIngAddress = sysCfg.UseAddress
|
||||
config.FreeVPN = sysCfg.FreeVPN
|
||||
config.AdvitiesTopicNum = sysCfg.AdvitiesTopicNum
|
||||
|
||||
config.DHKeyworld = sysCfg.DHKeyworld
|
||||
config.DHDescription = sysCfg.DHDescription
|
||||
config.DHSiteName = sysCfg.DHSiteName
|
||||
config.DHTitle = sysCfg.DHTitle
|
||||
config.ActressBackGround = netutil.MergeURL(sysCfg.ImgAppCdn, sysCfg.ActressBackGround)
|
||||
config.ReportSDKConfig = dataReport.GetSDKDomainConfig()
|
||||
config.WatermarkImage = sysCfg.WatermarkImage
|
||||
config.CustomerServiceHost = sysCfg.CustomerServiceHost
|
||||
config.ChannelCode = sysCfg.ChannelCode
|
||||
config.EnableH265 = sysCfg.EnableH265
|
||||
|
||||
// NewAddressInfo 来源于系统配置 sys_cfg,用于只返回前端需要展示的最新地址信息。
|
||||
newAddressInfo.NewUrlAddr = sysCfg.NewUrlAddr
|
||||
newAddressInfo.NewUrlAddr1 = sysCfg.NewUrlAddr1
|
||||
newAddressInfo.NewUrlAddr2 = sysCfg.NewUrlAddr2
|
||||
newAddressInfo.ForeverUrlAddr = sysCfg.ForeverUrlAddr
|
||||
newAddressInfo.GmailAddr = sysCfg.GmailAddr
|
||||
newAddressInfo.TgGroup = sysCfg.TgGroup
|
||||
newAddressInfo.Telegram = sysCfg.Telegram
|
||||
newAddressInfo.CustomerServiceHost = sysCfg.CustomerServiceHost
|
||||
newAddressInfo.TwitterAddr = sysCfg.TwitterAddr
|
||||
newAddressInfo.PdfAddr = sysCfg.PdfAddr
|
||||
newAddressInfo.AppAddr = sysCfg.AppAddr
|
||||
newAddressInfo.OfficialAppAddr = sysCfg.OfficialAppAddr
|
||||
|
||||
CacheMgr.Lock.Lock()
|
||||
defer CacheMgr.Lock.Unlock()
|
||||
CacheMgr.Config = config
|
||||
CacheMgr.NewAddressInfo = newAddressInfo
|
||||
|
||||
}
|
||||
func GetConfigInfo() proto.ConfigInfo {
|
||||
CacheMgr.Lock.RLock()
|
||||
defer CacheMgr.Lock.RUnlock()
|
||||
|
||||
return CacheMgr.Config
|
||||
}
|
||||
func GetAdvitise() proto.AdvitiseData {
|
||||
CacheMgr.Lock.RLock()
|
||||
defer CacheMgr.Lock.RUnlock()
|
||||
|
||||
return CacheMgr.Advitise
|
||||
}
|
||||
|
||||
func GetNewAddress() proto.NewAddressInfo {
|
||||
CacheMgr.Lock.RLock()
|
||||
defer CacheMgr.Lock.RUnlock()
|
||||
return CacheMgr.NewAddressInfo
|
||||
}
|
||||
|
||||
// GetFooterInfo 查询APP底部信息
|
||||
func GetFooterInfo() proto.FooterInfo {
|
||||
// 底部富文本和系统配置都来自缓存,接口请求不直接访问Mongo。
|
||||
config := GetConfigInfo()
|
||||
return proto.FooterInfo{
|
||||
Brand: buildFooterBrand(config),
|
||||
NavList: buildFooterNavList(),
|
||||
ContactList: buildFooterContactList(config),
|
||||
}
|
||||
}
|
||||
|
||||
func getFooterRichTextMap() map[string]proto.AppRichTextItemResp {
|
||||
data := getCachedAppRichTexts()
|
||||
if len(data) == 0 {
|
||||
updateAppRichTexts()
|
||||
data = getCachedAppRichTexts()
|
||||
}
|
||||
result := make(map[string]proto.AppRichTextItemResp, len(data))
|
||||
for _, item := range data {
|
||||
title := strings.TrimSpace(item.Title)
|
||||
if title == "" {
|
||||
continue
|
||||
}
|
||||
result[title] = item
|
||||
}
|
||||
return result
|
||||
}
|
||||
|
||||
func buildFooterBrand(config proto.ConfigInfo) proto.FooterBrand {
|
||||
return proto.FooterBrand{
|
||||
Title: config.WebSiteName,
|
||||
Content: config.WebDescription,
|
||||
}
|
||||
}
|
||||
|
||||
func buildFooterNavList() []proto.TranslationCategory {
|
||||
bottom := translationser.GetTranslationBottomList()
|
||||
return append([]proto.TranslationCategory{}, bottom.CategoryList...)
|
||||
}
|
||||
|
||||
func buildFooterContactList(config proto.ConfigInfo) []proto.FooterContact {
|
||||
// 联系方式名称按页面截图固定返回,右侧只包含 E-mail、商务合作、官方群 三项。
|
||||
return []proto.FooterContact{
|
||||
{Name: "E-mail", Value: config.GmailAddr},
|
||||
{Name: "商务合作:立即联系", Value: config.Telegram},
|
||||
{Name: "官方群:立即加入", Value: firstNotEmpty(config.TgGroup, config.TelegramAdd)},
|
||||
}
|
||||
}
|
||||
|
||||
func firstNotEmpty(values ...string) string {
|
||||
for _, value := range values {
|
||||
value = strings.TrimSpace(value)
|
||||
if value != "" {
|
||||
return value
|
||||
}
|
||||
}
|
||||
return ""
|
||||
}
|
||||
|
||||
// GetAppRichTextList 查询APP富文本内容列表
|
||||
func GetAppRichTextList(rawIds string, rawTitles string) proto.AppRichTextListResp {
|
||||
ids := parseInt64Set(rawIds)
|
||||
titles := parseStringSet(rawTitles)
|
||||
data := getCachedAppRichTexts()
|
||||
if len(data) == 0 {
|
||||
updateAppRichTexts()
|
||||
data = getCachedAppRichTexts()
|
||||
}
|
||||
return proto.AppRichTextListResp{List: filterAppRichTexts(data, ids, titles)}
|
||||
}
|
||||
|
||||
func getCachedAppRichTexts() []proto.AppRichTextItemResp {
|
||||
CacheMgr.Lock.RLock()
|
||||
defer CacheMgr.Lock.RUnlock()
|
||||
return append([]proto.AppRichTextItemResp{}, CacheMgr.AppRichTexts...)
|
||||
}
|
||||
|
||||
func filterAppRichTexts(data []proto.AppRichTextItemResp, ids map[int64]struct{}, titles map[string]struct{}) []proto.AppRichTextItemResp {
|
||||
list := make([]proto.AppRichTextItemResp, 0, len(data))
|
||||
for _, item := range data {
|
||||
if len(ids) > 0 {
|
||||
if _, ok := ids[item.Id]; !ok {
|
||||
continue
|
||||
}
|
||||
}
|
||||
if len(titles) > 0 {
|
||||
if _, ok := titles[item.Title]; !ok {
|
||||
continue
|
||||
}
|
||||
}
|
||||
list = append(list, item)
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
func parseInt64Set(raw string) map[int64]struct{} {
|
||||
raw = strings.TrimSpace(raw)
|
||||
if raw == "" {
|
||||
return nil
|
||||
}
|
||||
resp := make(map[int64]struct{})
|
||||
for _, item := range strings.Split(raw, ",") {
|
||||
id, err := strconv.ParseInt(strings.TrimSpace(item), 10, 64)
|
||||
if err != nil || id <= 0 {
|
||||
continue
|
||||
}
|
||||
resp[id] = struct{}{}
|
||||
}
|
||||
return resp
|
||||
}
|
||||
|
||||
func parseStringSet(raw string) map[string]struct{} {
|
||||
raw = strings.TrimSpace(raw)
|
||||
if raw == "" {
|
||||
return nil
|
||||
}
|
||||
resp := make(map[string]struct{})
|
||||
for _, item := range strings.Split(raw, ",") {
|
||||
item = strings.TrimSpace(item)
|
||||
if item == "" {
|
||||
continue
|
||||
}
|
||||
resp[item] = struct{}{}
|
||||
}
|
||||
return resp
|
||||
}
|
||||
|
||||
// GetSiteSeoInfo 返回全站SEO配置,供统一渲染 title、meta keywords、description 和 canonical。
|
||||
func GetSiteSeoInfo() proto.SeoInfo {
|
||||
CacheMgr.Lock.RLock()
|
||||
defer CacheMgr.Lock.RUnlock()
|
||||
webAddr := normalizeWebAddr(CacheMgr.Config.WebAddr)
|
||||
return proto.SeoInfo{
|
||||
Title: CacheMgr.Config.WebTitle,
|
||||
Keywords: append([]string{}, CacheMgr.Config.WebKeyworld...),
|
||||
Description: CacheMgr.Config.WebDescription,
|
||||
WebSiteName: CacheMgr.Config.WebSiteName,
|
||||
CanonicalURL: webAddr,
|
||||
}
|
||||
}
|
||||
|
||||
// GetNavSeoInfo 返回导航页SEO配置
|
||||
func GetNavSeoInfo() proto.SeoNavInfo {
|
||||
CacheMgr.Lock.RLock()
|
||||
defer CacheMgr.Lock.RUnlock()
|
||||
return proto.SeoNavInfo{
|
||||
DHTitle: CacheMgr.Config.DHTitle,
|
||||
DHKeyworld: append([]string{}, CacheMgr.Config.DHKeyworld...),
|
||||
DHDescription: CacheMgr.Config.DHDescription,
|
||||
DHSiteName: CacheMgr.Config.DHSiteName,
|
||||
}
|
||||
}
|
||||
|
||||
// GetNavPageList 返回导航页线路集合。
|
||||
func GetNavPageList() []proto.NavPageItem {
|
||||
CacheMgr.Lock.RLock()
|
||||
defer CacheMgr.Lock.RUnlock()
|
||||
list := make([]proto.NavPageItem, 0, 3)
|
||||
for _, item := range []proto.NavPageItem{
|
||||
{Line: 1, Url: strings.TrimSpace(CacheMgr.Config.DHNewUrlAddr1)},
|
||||
{Line: 2, Url: strings.TrimSpace(CacheMgr.Config.DHNewUrlAddr2)},
|
||||
{Line: 3, Url: strings.TrimSpace(CacheMgr.Config.DHNewUrlAddr3)},
|
||||
} {
|
||||
if item.Url == "" {
|
||||
continue
|
||||
}
|
||||
list = append(list, item)
|
||||
}
|
||||
return list
|
||||
}
|
||||
|
||||
func normalizeWebAddr(webAddr string) string {
|
||||
webAddr = strings.TrimSpace(webAddr)
|
||||
webAddr = strings.TrimRight(webAddr, "/")
|
||||
if webAddr == "" {
|
||||
return ""
|
||||
}
|
||||
if !strings.HasPrefix(webAddr, "http://") && !strings.HasPrefix(webAddr, "https://") {
|
||||
return "https://" + webAddr
|
||||
}
|
||||
return webAddr
|
||||
}
|
||||
|
||||
func GetRandCDN() string {
|
||||
config := GetConfigInfo()
|
||||
return config.TsCdn
|
||||
}
|
||||
|
||||
func updateIpBlack() {
|
||||
ctx := context.Background()
|
||||
list, err := ipblackmod.FindManyIPBlackModel(ctx, bson.M{})
|
||||
if err != nil {
|
||||
log.Error("updateIpBlack FindManyIPBlackModel error", log.E(err))
|
||||
return
|
||||
}
|
||||
tempMaps := make(map[string]struct{})
|
||||
for _, v := range list {
|
||||
tempMaps[v.Ip] = struct{}{}
|
||||
}
|
||||
CacheMgr.Lock.Lock()
|
||||
defer CacheMgr.Lock.Unlock()
|
||||
CacheMgr.IpBlackMaps = tempMaps
|
||||
}
|
||||
|
||||
func updateAppRichTexts() {
|
||||
resp, err := queryAppRichTexts(context.Background())
|
||||
if err != nil {
|
||||
log.Warn("查询APP富文本内容失败", log.E(err))
|
||||
return
|
||||
}
|
||||
CacheMgr.Lock.Lock()
|
||||
defer CacheMgr.Lock.Unlock()
|
||||
CacheMgr.AppRichTexts = resp
|
||||
}
|
||||
|
||||
// queryAppRichTexts 查询启用状态的APP富文本内容,统一供定时缓存和接口兜底加载使用。
|
||||
func queryAppRichTexts(ctx context.Context) ([]proto.AppRichTextItemResp, *srvdef.SrvErr) {
|
||||
filter := bson.M{
|
||||
richtextcontentmod.FN.RichTextContentModel.Status: true,
|
||||
}
|
||||
opts := options.Find().
|
||||
SetProjection(bson.M{
|
||||
richtextcontentmod.FN.RichTextContentModel.Id: 1,
|
||||
richtextcontentmod.FN.RichTextContentModel.Title: 1,
|
||||
richtextcontentmod.FN.RichTextContentModel.Content: 1,
|
||||
richtextcontentmod.FN.RichTextContentModel.Desc: 1,
|
||||
}).
|
||||
SetSort(bson.D{
|
||||
{Key: richtextcontentmod.FN.RichTextContentModel.Sort, Value: -1},
|
||||
{Key: richtextcontentmod.FN.RichTextContentModel.UpdatedAt, Value: -1},
|
||||
}).
|
||||
SetLimit(100)
|
||||
list := make([]appRichTextCacheItem, 0)
|
||||
err := richtextcontentmod.FindManyRichTextContentModelModelWithBind(ctx, &list, filter, opts)
|
||||
if err != nil {
|
||||
log.Warn("查询APP富文本内容失败", log.Any("filter", filter), log.E(err))
|
||||
return nil, err
|
||||
}
|
||||
imgCdn := GetConfigInfo().ImgCdn
|
||||
resp := make([]proto.AppRichTextItemResp, 0, len(list))
|
||||
for _, item := range list {
|
||||
resp = append(resp, proto.AppRichTextItemResp{
|
||||
Id: item.Id,
|
||||
Title: item.Title,
|
||||
Content: applyRichTextImgSrcCdn(imgCdn, item.Content),
|
||||
Desc: item.Desc,
|
||||
})
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// applyRichTextImgSrcCdn 给富文本 content 中 img 标签的 src 相对图片地址拼接图片CDN
|
||||
func applyRichTextImgSrcCdn(imgCdn string, content string) string {
|
||||
if imgCdn == "" || content == "" {
|
||||
return content
|
||||
}
|
||||
return richTextImgSrcRe.ReplaceAllStringFunc(content, func(match string) string {
|
||||
parts := richTextImgSrcRe.FindStringSubmatch(match)
|
||||
if len(parts) < 5 {
|
||||
return match
|
||||
}
|
||||
prefix := parts[1]
|
||||
quote := `"`
|
||||
src := parts[3]
|
||||
if src == "" {
|
||||
quote = `'`
|
||||
src = parts[4]
|
||||
} else if strings.HasPrefix(parts[2], `\"`) {
|
||||
quote = `\"`
|
||||
}
|
||||
src = strings.TrimSpace(src)
|
||||
if src == "" || isAbsoluteRichTextSrc(src) {
|
||||
return match
|
||||
}
|
||||
return prefix + "src=" + quote + netutil.MergeURL(imgCdn, src) + quote
|
||||
})
|
||||
}
|
||||
|
||||
// isAbsoluteRichTextSrc 判断图片地址是否已经是完整地址或特殊协议,避免重复拼接CDN。
|
||||
func isAbsoluteRichTextSrc(src string) bool {
|
||||
lowerSrc := strings.ToLower(src)
|
||||
return strings.HasPrefix(lowerSrc, "http://") ||
|
||||
strings.HasPrefix(lowerSrc, "https://") ||
|
||||
strings.HasPrefix(lowerSrc, "data:") ||
|
||||
strings.HasPrefix(lowerSrc, "blob:") ||
|
||||
strings.HasPrefix(src, "//")
|
||||
}
|
||||
|
||||
func updateAnnouncements() {
|
||||
list, err := queryAnnouncements(context.Background())
|
||||
if err != nil {
|
||||
log.Warn("查询公告失败", log.E(err))
|
||||
return
|
||||
}
|
||||
CacheMgr.Lock.Lock()
|
||||
defer CacheMgr.Lock.Unlock()
|
||||
CacheMgr.Announcements = list
|
||||
}
|
||||
|
||||
func queryAnnouncements(ctx context.Context) ([]*proto.AnnouncementItem, *srvdef.SrvErr) {
|
||||
filter := bson.M{announcementmod.FN.Announcement.Status: true}
|
||||
opts := options.Find().
|
||||
SetProjection(bson.M{
|
||||
announcementmod.FN.Announcement.Id: 1,
|
||||
announcementmod.FN.Announcement.Title: 1,
|
||||
announcementmod.FN.Announcement.Content: 1,
|
||||
}).
|
||||
SetSort(bson.D{
|
||||
{Key: announcementmod.FN.Announcement.Sort, Value: -1},
|
||||
{Key: announcementmod.FN.Announcement.UpdatedAt, Value: -1},
|
||||
}).
|
||||
SetLimit(50)
|
||||
list, err := announcementmod.FindManyAnnouncement(ctx, filter, opts)
|
||||
if err != nil {
|
||||
log.Warn("查询公告失败", log.Any("filter", filter), log.E(err))
|
||||
return nil, err
|
||||
}
|
||||
resp := make([]*proto.AnnouncementItem, 0, len(list))
|
||||
for _, item := range list {
|
||||
if item == nil {
|
||||
continue
|
||||
}
|
||||
resp = append(resp, &proto.AnnouncementItem{
|
||||
Id: item.Id,
|
||||
Title: item.Title,
|
||||
Content: item.Content,
|
||||
})
|
||||
}
|
||||
return resp, nil
|
||||
}
|
||||
|
||||
// GetAnnouncements 返回启用中的公告缓存,每10分钟刷新。
|
||||
func GetAnnouncements() []*proto.AnnouncementItem {
|
||||
CacheMgr.Lock.RLock()
|
||||
defer CacheMgr.Lock.RUnlock()
|
||||
if len(CacheMgr.Announcements) == 0 {
|
||||
return make([]*proto.AnnouncementItem, 0)
|
||||
}
|
||||
resp := make([]*proto.AnnouncementItem, len(CacheMgr.Announcements))
|
||||
copy(resp, CacheMgr.Announcements)
|
||||
return resp
|
||||
}
|
||||
|
||||
func CheckIpBlack(ip string) bool {
|
||||
CacheMgr.Lock.RLock()
|
||||
defer CacheMgr.Lock.RUnlock()
|
||||
if _, ok := CacheMgr.IpBlackMaps[ip]; ok {
|
||||
return true
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func GetVideoTagCategoryDataList() []proto.VideoTagCategoryData {
|
||||
CacheMgr.Lock.RLock()
|
||||
defer CacheMgr.Lock.RUnlock()
|
||||
rsl := make([]proto.VideoTagCategoryData, 0)
|
||||
for _, v := range CacheMgr.TagCategoryList {
|
||||
rsl = append(rsl, v)
|
||||
}
|
||||
return rsl
|
||||
}
|
||||
func Stop() {
|
||||
dataReport.StopSDKConfigCron()
|
||||
skdCron.Stop()
|
||||
}
|
||||
|
||||
func GetTag(tagId int64) *proto.TagsInfoData {
|
||||
CacheMgr.Lock.RLock()
|
||||
defer CacheMgr.Lock.RUnlock()
|
||||
tag, ok := CacheMgr.TagMaps[tagId]
|
||||
if !ok {
|
||||
return nil
|
||||
}
|
||||
return &tag
|
||||
}
|
||||
Reference in New Issue
Block a user