Files
huangguo_server/web/service/laosijiser/media.go
T
rootandClaude Opus 5 8679200f41 Initial commit
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-15 13:57:10 +08:00

208 lines
6.4 KiB
Go

package laosijiser
import (
"91porn-server/common/laosiji"
"91porn-server/common/log"
"91porn-server/models/v/mediacontentmod"
"91porn-server/models/v/mediamod"
"91porn-server/models/v/mediatagmod"
"91porn-server/web/service/vidser"
"errors"
"fmt"
"strconv"
"strings"
"time"
"go.mongodb.org/mongo-driver/bson/primitive"
)
func checkInsertMediaTag(names []string, typ int) (data map[string]primitive.ObjectID, err error) {
data, err = mediatagmod.FindOneTagByNames(names, typ)
if err != nil {
log.Error("checkInsertMediaTag FindOneTagByiNames failed", log.Any("tags", names), log.E(err))
return
}
insertTags := make([]mediatagmod.MediaTag, 0)
for _, tag := range names {
if _, ok := data[tag]; !ok {
insertTag := mediatagmod.MediaTag{
ID: primitive.NewObjectID(),
Type: typ,
Name: tag,
Active: true,
Sort: 0,
IsDiscovery: false,
CreatedAt: time.Now(),
}
insertTags = append(insertTags, insertTag)
data[tag] = insertTag.ID
}
}
if len(insertTags) > 0 {
err = mediatagmod.InsertMany(nil, insertTags)
if err != nil {
log.Warn("checkInsertMediaTag InsertMany failed", log.Any("tags", insertTags), log.E(err))
return
}
}
return
}
func syncCartoonList(movieDetails []laosiji.MovieDetailResp, tags map[string]struct{}, manager string, terms []string) ([]vidser.SensitiveHit, error) {
hits := make([]vidser.SensitiveHit, 0)
tagMaps := make(map[string]primitive.ObjectID)
var err error
if len(tags) > 0 {
tagList := make([]string, 0)
for k, _ := range tags {
tagList = append(tagList, k)
}
tagMaps, err = checkInsertMediaTag(tagList, 1)
if err != nil {
log.Error("syncCartoonList checkInsertVidTags failed", log.E(err))
return hits, err
}
}
failedIds := make([]string, 0)
for _, movieDetail := range movieDetails {
hit, oneErr := syncOneCartoon(movieDetail, tagMaps, manager, terms)
if oneErr != nil {
log.Warn("syncCartoonList syncOneCartoon failed", log.Any("id", movieDetail.Id), log.E(oneErr))
failedIds = append(failedIds, movieDetail.Id)
continue
}
if hit != nil {
hits = append(hits, *hit)
}
}
if len(failedIds) > 0 {
return hits, errors.New(fmt.Sprintf("需要同步%d部动漫,失败%d,失败Id[%s]", len(movieDetails), len(failedIds), strings.Join(failedIds, ",")))
}
return hits, nil
}
func syncOneCartoon(movieDetail laosiji.MovieDetailResp, tagMaps map[string]primitive.ObjectID, manager string, terms []string) (*vidser.SensitiveHit, error) {
now := time.Now()
mediaTemp, err := mediamod.GetListByLsjId(movieDetail.Id)
if err != nil {
log.Warn("syncOneCartoon GetListByLsjId failed", log.Any("id", movieDetail.Id), log.Any("err", err))
return nil, err
}
if !mediaTemp.ID.IsZero() {
return nil, syncExistingCartoonH265(mediaTemp.ID, movieDetail.Links, manager)
}
mediaTemp = mediamod.Media{
ID: primitive.NewObjectID(),
LsjId: movieDetail.Id,
Title: movieDetail.Name,
HorizontalCover: movieDetail.Img_x,
VerticalCover: movieDetail.Img_y,
Tags: make([]primitive.ObjectID, 0),
TagDetails: make([]mediamod.TagDetail, 0),
Summary: movieDetail.Description,
MediaType: mediamod.MediaTypeVideo,
Kind: 1,
PermissionIconHide: false,
Permission: 2,
Status: 1,
CreatedAt: now,
UpdateTime: now,
UpdatedAct: manager,
Anchor: movieDetail.Director,
}
mediaTemp.UpdateStatus, _ = strconv.Atoi(movieDetail.Update_status)
//if mediaTemp.UpdateStatus == 1 {
// mediaTemp.UpdatedDesc = fmt.Sprintf("已完结%d话", mediaTemp.TotalEpisode)
//} else {
// mediaTemp.UpdatedDesc = fmt.Sprintf("更新至%d话", mediaTemp.TotalEpisode)
//}
for _, tag := range movieDetail.Tags {
if v, ok := tagMaps[tag.Name]; ok {
mediaTemp.TagDetails = append(mediaTemp.TagDetails, mediamod.TagDetail{
Id: v,
Name: tag.Name,
})
mediaTemp.Tags = append(mediaTemp.Tags, v)
}
}
contents := make([]mediacontentmod.MediaContent, 0)
if len(movieDetail.Links) > 0 {
for i, chapter := range movieDetail.Links {
mediaContent := mediacontentmod.MediaContent{
ID: primitive.NewObjectID(),
MediaID: mediaTemp.ID,
EpisodeNumber: i + 1,
ListenPermission: mediaTemp.Permission,
Price: mediaTemp.Price,
Name: chapter.Name,
VideoUrl: chapter.M3u8_url,
H265Url: strings.TrimSpace(chapter.Hevc_m3u8_url),
UrlSet: make([]string, 0),
Status: 1,
IsActive: true,
UpdatedAct: manager,
CreatedAt: now,
UpdateTime: now,
HashId: chapter.Id,
}
contents = append(contents, mediaContent)
}
}
mediaTemp.CurrentEpisode = len(contents)
mediaTemp.TotalEpisode = mediaTemp.CurrentEpisode
// 敏感词命中 → 强制下架(Status=0)
hit := vidser.CheckTextHits(terms, movieDetail.Id, mediaTemp.Title, mediaTemp.Summary, "")
if hit != nil {
mediaTemp.Status = 0
log.Warn("syncOneCartoon sensitive hit, forced offline",
log.Any("sourceId", hit.SourceID),
log.Any("title", hit.Title),
log.Any("detail", hit.Detail))
}
_, err = mediamod.Insert(nil, mediaTemp)
if err != nil {
log.Warn("syncOneCartoon InsertMedia failed", log.Any("media", mediaTemp.ID), log.E(err))
return nil, err
}
if len(contents) > 0 {
_ = mediacontentmod.InsetBatch(nil, contents)
}
return hit, nil
}
// syncExistingCartoonH265 允许重复导入老司机动漫时回填历史章节的 H.265 地址。
// 只接受上游非空地址,不改动现有 H.264 地址,也不会用空值覆盖已入库资源。
func syncExistingCartoonH265(mediaID primitive.ObjectID, links []laosiji.LinkInfo, manager string) error {
updatedIDs := make([]primitive.ObjectID, 0)
for _, chapter := range links {
h265URL := strings.TrimSpace(chapter.Hevc_m3u8_url)
if h265URL == "" || strings.TrimSpace(chapter.Id) == "" {
continue
}
content, err := mediacontentmod.GetInfoByHashId(mediaID, chapter.Id)
if err == mediacontentmod.MediaContentNotFound {
continue
}
if err != nil {
return err
}
if strings.TrimSpace(content.H265Url) == h265URL {
continue
}
if _, err = mediacontentmod.UpdateByID(nil, content.ID, map[string]interface{}{
"h265Url": h265URL,
"updatedAct": manager,
"updateTime": time.Now(),
}); err != nil {
return err
}
updatedIDs = append(updatedIDs, content.ID)
}
return nil
}