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 }