init: 初始化 web_hgdjb_server 项目
Co-Authored-By: Claude Opus 4.7 <noreply@anthropic.com>
This commit is contained in:
@@ -0,0 +1,232 @@
|
||||
package srv_videoinfo
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
"time"
|
||||
"videoweb/pub/common/log"
|
||||
"videoweb/pub/common/srvdef"
|
||||
"videoweb/pub/models/playletchaptermod"
|
||||
"videoweb/pub/models/videocreatermod"
|
||||
"videoweb/pub/models/videoinformationmod"
|
||||
"videoweb/pub/mongos"
|
||||
"videoweb/pub/storage/proxy"
|
||||
"videoweb/web/service/srv_videoslug"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson"
|
||||
"go.mongodb.org/mongo-driver/mongo/options"
|
||||
)
|
||||
|
||||
func IsPlayletMedia(ctx context.Context, media proxy.MediaResp) bool {
|
||||
return playletchaptermod.IsLinkedMedia(ctx, media.IsPlaylet, media.PlayletKeys()...)
|
||||
}
|
||||
|
||||
func SyncOneVideo(ctx context.Context, media proxy.MediaResp) *srvdef.SrvErr {
|
||||
if IsPlayletMedia(ctx, media) {
|
||||
log.Info("VideoSync skip playlet media", log.Any("mediaId", media.Id.Hex()), log.Any("mediaSourceId", media.MediaSourceId.Hex()))
|
||||
return nil
|
||||
}
|
||||
filter := bson.M{
|
||||
"$or": []bson.M{
|
||||
{videoinformationmod.FN.VideoInformation.Video.FileId: media.Id.Hex()},
|
||||
{videoinformationmod.FN.VideoInformation.SyncId: media.Id.Hex()},
|
||||
},
|
||||
}
|
||||
videoInfo, serr := videoinformationmod.FindOneVideoInformation(ctx, filter)
|
||||
if serr != nil {
|
||||
// 新加入的视频
|
||||
if serr.Code == srvdef.ErrNoData {
|
||||
videoInfo = media.ToVideoInfo()
|
||||
if videoInfo == nil {
|
||||
log.Error("VideoSync FindOneVideoInformation", log.Any("MediaId", media.Id))
|
||||
return srvdef.New(srvdef.ErrNoData, "videoInfo is nil")
|
||||
}
|
||||
videoInfo.IndexNow = 0
|
||||
if len(media.Publish) > 0 {
|
||||
creater, serr := videocreatermod.FindOneVideoCreaterInfo(ctx, bson.M{
|
||||
videocreatermod.FN.VideoCreaterInfo.Name: media.Publish,
|
||||
})
|
||||
if serr != nil && serr.Code != srvdef.ErrNoData {
|
||||
log.Error("VideoSync.FindOneVideoCreaterInfo", log.Any("media", media), log.E(serr))
|
||||
return serr
|
||||
}
|
||||
if creater == nil {
|
||||
createrId := mongos.Lid.VideoCreator.Get()
|
||||
creater = &videocreatermod.VideoCreaterInfo{
|
||||
Id: createrId,
|
||||
Name: media.Publish,
|
||||
Status: true,
|
||||
Sort: 0,
|
||||
UpdatedAt: time.Now(),
|
||||
CreatedAt: time.Now(),
|
||||
}
|
||||
if slugErr := srv_videoslug.EnsureCreater(ctx, creater, 0); slugErr != nil {
|
||||
return slugErr
|
||||
}
|
||||
serr = videocreatermod.InsertOneVideoCreaterInfo(ctx, creater)
|
||||
if serr != nil {
|
||||
log.Error("VideoSync.InsertOneVideoCreaterInfo", log.Any("media", media), log.E(serr))
|
||||
return serr
|
||||
}
|
||||
}
|
||||
videoInfo.CreatorId = creater.Id
|
||||
videoInfo.CreatorName = creater.Name
|
||||
}
|
||||
if slugErr := srv_videoslug.EnsureVideo(ctx, videoInfo, 0); slugErr != nil {
|
||||
return slugErr
|
||||
}
|
||||
serr = videoinformationmod.InsertOneVideoInformation(ctx, videoInfo)
|
||||
if serr != nil {
|
||||
log.Error("VideoSync InsertOneVideoInformation", log.Any("videoInfo", videoInfo), log.E(serr))
|
||||
return serr
|
||||
}
|
||||
} else {
|
||||
log.Error("VideoSync FindOneVideoInformation", log.Any("filter", filter), log.E(serr))
|
||||
return serr
|
||||
}
|
||||
} else {
|
||||
// 更新资源
|
||||
nodes := make([]videoinformationmod.Node, 0)
|
||||
if videoInfo != nil {
|
||||
// 更新节点里面图片水印 以本地视频列表的节点为主
|
||||
for _, node := range videoInfo.Nodes {
|
||||
isFind := false
|
||||
if len(node.NodeId) > 0 {
|
||||
for _, v := range media.Nodes {
|
||||
if node.NodeId == v.NodeId {
|
||||
isFind = true
|
||||
node.Images = v.Images
|
||||
nodes = append(nodes, node)
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if !isFind {
|
||||
nodes = append(nodes, node)
|
||||
}
|
||||
}
|
||||
} else {
|
||||
nodes = media.Nodes
|
||||
}
|
||||
setDoc := bson.M{
|
||||
videoinformationmod.FN.VideoInformation.Nodes: nodes,
|
||||
videoinformationmod.FN.VideoInformation.Keyworld: media.Keyworld,
|
||||
videoinformationmod.FN.VideoInformation.FirstTag: media.FirstTag,
|
||||
videoinformationmod.FN.VideoInformation.SecondTags: media.SecondTags,
|
||||
videoinformationmod.FN.VideoInformation.CoverImg: media.CoverImg,
|
||||
videoinformationmod.FN.VideoInformation.UnencryptedImage: media.UnencryptedImage,
|
||||
}
|
||||
if len(media.FieldNameFs) > 0 {
|
||||
video := videoinformationmod.VideoInfo{
|
||||
TaskId: media.TaskID,
|
||||
FileId: media.Id.Hex(),
|
||||
Url: media.FieldNameFs,
|
||||
Cover: media.CoverImg,
|
||||
Height: media.Height,
|
||||
Width: media.Width,
|
||||
VideoTime: media.VideoTime,
|
||||
UnencryptedPreMp4: media.UnencryptedPreMp4,
|
||||
PreMp4FileNameFs: media.PreMp4FileNameFs,
|
||||
}
|
||||
if !strings.HasSuffix(video.Url, ".m3u8") {
|
||||
video.Url += ".m3u8"
|
||||
}
|
||||
setDoc[videoinformationmod.FN.VideoInformation.Video.TaskId] = video.TaskId
|
||||
setDoc[videoinformationmod.FN.VideoInformation.Video.FileId] = video.FileId
|
||||
setDoc[videoinformationmod.FN.VideoInformation.Video.Url] = video.Url
|
||||
setDoc[videoinformationmod.FN.VideoInformation.Video.Cover] = video.Cover
|
||||
setDoc[videoinformationmod.FN.VideoInformation.Video.Height] = video.Height
|
||||
setDoc[videoinformationmod.FN.VideoInformation.Video.Width] = video.Width
|
||||
setDoc[videoinformationmod.FN.VideoInformation.Video.VideoTime] = video.VideoTime
|
||||
setDoc[videoinformationmod.FN.VideoInformation.Video.UnencryptedPreMp4] = video.UnencryptedPreMp4
|
||||
}
|
||||
if strings.TrimSpace(videoInfo.Slug) == "" {
|
||||
if slugErr := srv_videoslug.EnsureVideo(ctx, videoInfo, videoInfo.Id); slugErr == nil && strings.TrimSpace(videoInfo.Slug) != "" {
|
||||
setDoc[videoinformationmod.FN.VideoInformation.Slug] = videoInfo.Slug
|
||||
}
|
||||
}
|
||||
serr = videoinformationmod.UpdateOneVideoInformation(ctx, bson.M{videoinformationmod.FN.VideoInformation.Id: videoInfo.Id}, bson.M{"$set": setDoc})
|
||||
if serr != nil {
|
||||
return serr
|
||||
}
|
||||
}
|
||||
_ = syncNodeVideo(ctx, media)
|
||||
return nil
|
||||
}
|
||||
|
||||
// SyncUnencryptedOne 仅补齐单条资源的 UnencryptedImage / UnencryptedPreMp4 字段。
|
||||
// 源数据对应字段为空时跳过该字段(避免覆盖本地已有值);本地无对应资源时直接返回。
|
||||
// 幂等:可重复执行,用于历史数据补齐。
|
||||
func SyncUnencryptedOne(ctx context.Context, media proxy.MediaResp) *srvdef.SrvErr {
|
||||
if media.UnencryptedImage == "" && media.UnencryptedPreMp4 == "" {
|
||||
return nil
|
||||
}
|
||||
filter := bson.M{videoinformationmod.FN.VideoInformation.Video.FileId: media.Id.Hex()}
|
||||
videoInfo, serr := videoinformationmod.FindOneVideoInformation(ctx, filter)
|
||||
if serr != nil {
|
||||
return serr
|
||||
}
|
||||
setDoc := bson.M{}
|
||||
if media.UnencryptedImage != "" {
|
||||
setDoc[videoinformationmod.FN.VideoInformation.UnencryptedImage] = media.UnencryptedImage
|
||||
}
|
||||
// 仅当源端有主视频文件时,才补 Video.UnencryptedPreMp4(避免向空的 Video 子结构写字段)
|
||||
if media.UnencryptedPreMp4 != "" && len(media.FieldNameFs) > 0 {
|
||||
setDoc[videoinformationmod.FN.VideoInformation.Video.UnencryptedPreMp4] = media.UnencryptedPreMp4
|
||||
}
|
||||
if len(setDoc) == 0 {
|
||||
return nil
|
||||
}
|
||||
return videoinformationmod.UpdateOneVideoInformation(ctx,
|
||||
bson.M{videoinformationmod.FN.VideoInformation.Id: videoInfo.Id},
|
||||
bson.M{"$set": setDoc})
|
||||
}
|
||||
|
||||
// syncNodeVideo 同步节点里的视频
|
||||
func syncNodeVideo(ctx context.Context, media proxy.MediaResp) *srvdef.SrvErr {
|
||||
filter := bson.M{"nodes.nodeId": media.Id.Hex()}
|
||||
opts := &options.FindOptions{}
|
||||
opts.SetLimit(100)
|
||||
videoInfo, serr := videoinformationmod.FindManyVideoInformations(ctx, filter, opts)
|
||||
if serr != nil {
|
||||
log.Warn("syncNodeVideo", log.Any("filter", filter), log.E(serr))
|
||||
return serr
|
||||
}
|
||||
if !strings.HasSuffix(media.FieldNameFs, ".m3u8") {
|
||||
media.FieldNameFs += ".m3u8"
|
||||
}
|
||||
if len(videoInfo) > 0 {
|
||||
// 更新视频路径
|
||||
for _, video := range videoInfo {
|
||||
if video.Nodes != nil && len(video.Nodes) > 0 {
|
||||
isFind := false
|
||||
for i, node := range video.Nodes {
|
||||
if node.Videos != nil && len(node.Videos) > 0 {
|
||||
for j, v := range node.Videos {
|
||||
if v.FileId == media.Id.Hex() {
|
||||
node.Videos[j].Url = media.FieldNameFs
|
||||
isFind = true
|
||||
break
|
||||
}
|
||||
}
|
||||
}
|
||||
if isFind {
|
||||
video.Nodes[i] = node
|
||||
break
|
||||
}
|
||||
}
|
||||
if isFind {
|
||||
serr = videoinformationmod.UpdateOneVideoInformation(ctx, bson.M{videoinformationmod.FN.VideoInformation.Id: video.Id}, bson.M{"$set": bson.M{
|
||||
videoinformationmod.FN.VideoInformation.UpdatedAt: time.Now(),
|
||||
videoinformationmod.FN.VideoInformation.Nodes: video.Nodes,
|
||||
}})
|
||||
if serr != nil {
|
||||
log.Warn("syncNodeVideo UpdateOneVideoInformation failed", log.Any("filter", filter), log.E(serr))
|
||||
continue
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
||||
return nil
|
||||
}
|
||||
Reference in New Issue
Block a user