Files
rootandClaude Opus 5 acb9a34520 [AI] fix: 修复短剧剧集重复显示
两处原因,分别处理:

1. contentsync 只按 _id 水位线插新增,源库事后打上的 isDelete 传不过来,
   源站删掉的重复集在目标库一直留着。每轮同步后补扫一次 media /
   media_content / video_info,把源库的软删除标记同步过去,并按
   web/service/mediacontentser 的同一口径重算父级 currentEpisode /
   freeEpisode。只做「源库删了→目标也删」一个方向,不与本地下架保护冲突。

2. 各站 skd 的媒资库同步会为同一集(mediaId+hashId 相同)另插一条自己的 _id,
   与 contentsync 带过来的源库那条并存。媒资库那条在 SaleCoin=0 时
   listenPermission=2,本该收费的集可以白看。插入时若发现本地已有同一集,
   把本地那条 isActive:false 下架;并新增 skd 配置开关
   switch.mediaSyncDisabled,非源站可直接关掉这条同步链。

Co-Authored-By: Claude Opus 5 (1M context) <noreply@anthropic.com>
2026-10-29 20:18:36 +08:00

167 lines
5.6 KiB
Go
Raw Permalink Blame History

This file contains ambiguous Unicode characters
This file contains Unicode characters that might be confused with other characters. If you think that this is intentional, you can safely ignore this warning. Use the Escape button to reveal them.
package job
import (
"91porn-server/common"
"91porn-server/common/aiService"
"91porn-server/common/log"
mediaService "91porn-server/common/media"
"91porn-server/common/mediaCenter"
"91porn-server/models/commod"
"91porn-server/skd/job/checkin"
"91porn-server/skd/job/dailyAdverCalc"
"91porn-server/skd/job/dataclean"
"91porn-server/skd/job/hotvalue"
"91porn-server/skd/job/shortrecommend"
"91porn-server/skd/job/user"
"91porn-server/skd/service"
"91porn-server/skd/service/contentreviewser"
"91porn-server/skd/service/export_task"
"91porn-server/skd/skdg"
"context"
"time"
)
// start 定时任务 开启
func start() {
_, _ = statCron.AddFunc("0 0 0 * * ?", func() { //每天0点执行一次
// 重置预售卡预付权益
user.ResetLimit()
})
if skdg.Conf.ShortRecommendEnabled() {
// 定时检查队列完整性;当天健康时只做一次Redis脚本,异常时自动重建。
if _, err := statCron.AddFunc(skdg.Conf.ShortRecommendCron(), shortrecommend.Run); err != nil {
log.Error("register short recommend cron failed",
log.E(err), log.Any("cron", skdg.Conf.ShortRecommendCron()))
}
// 启动时补建当日队列;分布式锁保证多实例只执行一次。
common.Go(shortrecommend.Run)
}
_, _ = statCron.AddFunc("0 0/5 * * * ?", func() { //每5分钟执行一次统计任务
runStat()
})
_, _ = statCron.AddFunc("@every 5m", func() { //每5分钟执行一次数据同步任务
runSync()
})
_, _ = statCron.AddFunc("0 0/5 * * * ?", func() { //每5分钟执行一次sql折叠任务
runSyncSqlcollaspe()
})
// _, _ = statCron.AddFunc("0 0/5 * * * ?", func() { //每5分钟刷新一下排行榜
// runRankStat()
// })
// _, _ = statCron.AddFunc("0 0/1 * * * ?", func() { //每1分钟执行一次统计任务
// runPromoteStat()
// })
// _, _ = statCron.AddFunc("0 0 0/1 * * ?", func() { //每1个小时增加内部人员推广人数
// runInnerFakePromote()
// })
// _, _ = statCron.AddFunc("0 0/2 * * * ?", func() { //每2分钟生成备用推广码
// runMakePromotionCode()
// })
// _, _ = statCron.AddFunc("0 0 0,1,3,6,7,9,10,12,15,20,21,23 * * ?", func() { //每天11,15,18,23点执行一次消息任务
// service.GoldEggLuckyRunSync()
// })
_, _ = statCron.AddFunc("0 0 4 * * ?", func() { //每天凌晨4点执行一次
dataclean.RunSync()
})
_, _ = statCron.AddFunc("0/10 * * * * ?", func() { //每10秒执行一次
service.VidTimeOnline()
})
common.Go(func() {
hotvalue.ResetHot()
})
_, _ = statCron.AddFunc("0 0 6 * * ?", func() { //每天凌晨6点执行一次
hotvalue.ResetHot()
})
// 每10秒检测需要导出的任务列表
_, _ = statCron.AddFunc("0/10 * * * * ?", func() { //每10秒执行一次
export_task.ExecExportTask()
})
// 每3秒检测有无待执行的内容审查任务(同一时刻仅 1 个任务运行)
_, _ = statCron.AddFunc("0/3 * * * * ?", func() {
contentreviewser.TryRunPendingTask()
})
_, _ = statCron.AddFunc("0 * * * * ?", func() { // 每分钟检查是否需要发送 IM 广告通知
IMAdNotifyOnline()
})
// 每 5 秒检查 web 端是否发起了 IM 用户同步请求
_, _ = statCron.AddFunc("0/5 * * * * ?", func() {
RunPendingSyncIMUsers()
})
// 同步acg订阅的动漫
if skdg.Conf.Switch.MediaSyncDisabled {
log.Info("【ACG同步任务】已按配置关闭(switch.mediaSyncDisabled),内容改由 contentsync 从源站同步")
} else {
_, _ = statCron.AddFunc("0 0/30 * * * ?", func() { //每30分钟执行一次
ms := mediaService.NewMediaSync(skdg.Redis, mediaCenter.NewMediaCenterService(mediaCenter.Config{
Url: skdg.Conf.MediaResourcesCfg.UploadMediaUrl,
ProId: skdg.Conf.MediaResourcesCfg.ProId,
Secret: skdg.Conf.MediaResourcesCfg.AppSecret,
}))
ms.SyncAll("系统")
})
}
common.Go(func() {
err := aiService.NewAiService(
aiService.AppId(int(commod.KFK_APPID)),
aiService.Url(skdg.Conf.Url.AiServer),
aiService.Redis(skdg.Redis),
).Sync()
if err != nil {
log.Error("Sync AI Template fail")
}
})
// 定期同步ai服务里的模版
_, _ = statCron.AddFunc("0 0/10 * * * ?", func() { //每10分钟执行一次
err := aiService.NewAiService(
aiService.AppId(int(commod.KFK_APPID)),
aiService.Url(skdg.Conf.Url.AiServer),
aiService.Redis(skdg.Redis),
).Sync()
if err != nil {
log.Error("Sync AI Template fail")
}
})
_, _ = statCron.AddFunc("0/2 * * * * ?", func() { //每2秒检查签到奖励视频切片状态
checkin.VideoCheckRS()
})
_, _ = statCron.AddFunc("0 0/1 * * * ?", func() { // 每分钟提交 H265 等待队列
SubmitH265TranscodingQueue()
})
_, _ = statCron.AddFunc("0 0/1 * * * ?", func() { // 每分钟轮询 H265 转码结果
CheckH265TranscodingResults()
})
_, _ = statCron.AddFunc("0 0 0/1 * * ?", func() { // 每小时保障首页重点视频的 H265 资源
ScanHomeH265TranscodingQueue()
})
common.Go(func() {
ScanHomeH265TranscodingQueue()
SubmitH265TranscodingQueue()
CheckH265TranscodingResults()
})
spec := "0 0/30 * * * ?"
if skdg.Conf.Base.Env == "test" {
spec = "0 0/1 * * * ?" // 测试环境3分钟刷新一次
}
_, _ = statCron.AddFunc(spec, func() { //每30分钟执行一次
now := time.Now()
if now.Hour() == 0 || now.Hour() == 1 || now.Hour() == 2 {
yesterday := now.AddDate(0, 0, -1)
if err := dailyAdverCalc.CalcRetention(context.Background(), yesterday); err != nil {
log.Error("CalcRetention failed", log.Any("error", err))
}
}
// 当天的数据,每小时计算一次,确保及时更新看板
if err := dailyAdverCalc.CalcRetention(context.Background(), now); err != nil {
log.Error("CalcRetention failed", log.Any("error", err))
}
})
statCron.Start()
}