package laosijiser import ( "91porn-server/common" "91porn-server/common/constant/redisconst" "91porn-server/common/laosiji" "91porn-server/common/log" "91porn-server/models/v/mediamod" "91porn-server/models/v/tagmod" "91porn-server/models/v/usermod" "91porn-server/models/v/vidmod" "91porn-server/web/service/vidser" "91porn-server/web/webg" "context" "errors" "fmt" "math/rand" "strconv" "strings" "time" "go.mongodb.org/mongo-driver/bson" "go.mongodb.org/mongo-driver/bson/primitive" "go.mongodb.org/mongo-driver/mongo/options" ) func MovieSearch(ctx context.Context, param laosiji.MovieSearchReq) (resp laosiji.MovieSearchResp, err error) { var yuanresp laosiji.MovieSearchResp yuanresp, err = laosiji.MovieSearch(ctx, param) if err != nil { log.Error("MovieSearch", log.E(err)) return } //是否导入 taskIds := make([]string, 0) for _, v := range yuanresp.Data { taskIds = append(taskIds, v.Id) } resp = laosiji.MovieSearchResp{ Data: make([]laosiji.MovieInfo, 0), Total: yuanresp.Total, Current_page: yuanresp.Current_page, Page_size: yuanresp.Page_size, Last_page: yuanresp.Last_page, } if param.Position == "guochan" || param.Position == "av" || param.Position == "douyin" || param.Position == "dark" { videoList, _ := vidmod.GetList(bson.M{"sourceID": bson.M{"$in": taskIds}}) // 处理域名 for _, movieInfo := range yuanresp.Data { //movieInfo.Img_x = common.JoinUrlPath(laosiji.IMAGEYUAN, movieInfo.Img_x) //movieInfo.Img_y = common.JoinUrlPath(laosiji.IMAGEYUAN, movieInfo.Img_y) movieInfo.Img_x = common.JoinUrlPath("laosiji", movieInfo.Img_x) movieInfo.Img_y = common.JoinUrlPath("laosiji", movieInfo.Img_y) for _, videoInfo := range videoList { if videoInfo.SourceID == movieInfo.Id { movieInfo.IsAdd = true continue } } resp.Data = append(resp.Data, movieInfo) } } else if param.Position == "cartoon" { mediaList, _ := mediamod.GetListByLsjIds(taskIds) for _, movieInfo := range yuanresp.Data { //movieInfo.Img_x = common.JoinUrlPath(laosiji.IMAGEYUAN, movieInfo.Img_x) //movieInfo.Img_y = common.JoinUrlPath(laosiji.IMAGEYUAN, movieInfo.Img_y) movieInfo.Img_x = common.JoinUrlPath("laosiji", movieInfo.Img_x) movieInfo.Img_y = common.JoinUrlPath("laosiji", movieInfo.Img_y) for _, videoInfo := range mediaList { if videoInfo.LsjId == movieInfo.Id { movieInfo.IsAdd = true continue } } resp.Data = append(resp.Data, movieInfo) } } else { err = errors.New("该资源暂不支持") } return resp, nil } func MovieDetail(ctx context.Context, param laosiji.MovieDetailReq) (resp laosiji.MovieDetailResp, err error) { resp, err = laosiji.MovieDetail(ctx, param) if err != nil { log.Error("MovieSearch", log.E(err)) return } // 处理域名 //resp.Img_x = common.JoinUrlPath(laosiji.IMAGEYUAN, resp.Img_x) //resp.Img_y = common.JoinUrlPath(laosiji.IMAGEYUAN, resp.Img_y) resp.Img_x = common.JoinUrlPath("laosiji", resp.Img_x) resp.Img_y = common.JoinUrlPath("laosiji", resp.Img_y) for key, value := range resp.Preview_images { //resp.Preview_images[key] = common.JoinUrlPath(laosiji.IMAGEYUAN, value) resp.Preview_images[key] = common.JoinUrlPath("laosiji", value) } for key, value := range resp.Links { resp.Links[key].M3u8_url = laosiji.MovieM3u8OriginURL(value.M3u8_url) resp.Links[key].Preview_m3u8_url = laosiji.MovieM3u8OriginURL(value.Preview_m3u8_url) resp.Links[key].Hevc_m3u8_url = laosiji.MovieM3u8OriginURL(value.Hevc_m3u8_url) } return resp, nil } func MovieAddList(ctx context.Context, param laosiji.MovieAddListReq, manager string) ([]vidser.SensitiveHit, error) { if param.Ids == nil || len(param.Ids) <= 0 { return nil, nil } movieDetails := make([]laosiji.MovieDetailResp, 0) for _, id := range param.Ids { var movieDetail laosiji.MovieDetailResp req := laosiji.MovieDetailReq{ Id: id, } movieDetail, err := laosiji.MovieDetail(ctx, req) if err != nil { log.Warn("MovieAddList laosiji.MovieDetail failed", log.Any("id", id), log.E(err)) continue } for i, linkInfo := range movieDetail.Links { linkInfo.M3u8_url = laosiji.MovieM3u8SourcePath(linkInfo.M3u8_url) linkInfo.Preview_m3u8_url = laosiji.MovieM3u8SourcePath(linkInfo.Preview_m3u8_url) linkInfo.Hevc_m3u8_url = laosiji.MovieM3u8SourcePath(linkInfo.Hevc_m3u8_url) movieDetail.Links[i] = linkInfo } if len(movieDetail.Img_y) > 0 { movieDetail.Img_y = common.JoinUrlPath("laosiji/", movieDetail.Img_y) } if len(movieDetail.Img_x) > 0 { movieDetail.Img_x = common.JoinUrlPath("laosiji/", movieDetail.Img_x) } movieDetails = append(movieDetails, movieDetail) } if len(movieDetails) <= 0 { log.Warn("MovieAddList laosiji.MovieDetailResp len is 0") return nil, errors.New("laosiji.MovieDetailResp len is 0") } // 批量处理标签 tags := make(map[string]struct{}) for _, comicsDetail := range movieDetails { if comicsDetail.Tags != nil && len(comicsDetail.Tags) > 0 { for _, tag := range comicsDetail.Tags { tags[tag.Name] = struct{}{} } } } terms := vidser.LoadEnabledSensitiveTerms() hits := make([]vidser.SensitiveHit, 0) if param.Position == "cartoon" { return syncCartoonList(movieDetails, tags, manager, terms) } else if param.Position == "av" || param.Position == "guochan" || param.Position == "douyin" || param.Position == "dark" { 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 = checkInsertVidTags(tagList) if err != nil { log.Error("MovieAddList checkInsertVidTags failed", log.E(err)) return hits, err } } users, err := usermod.FindMany(bson.M{"uid": bson.M{"$gt": 300000}}, &options.FindOptions{}, 0, 300) if err != nil { log.Warn("PostAddList FindManyUser failed", log.E(err)) return hits, err } failedIds := make([]string, 0) for _, comicsDetail := range movieDetails { hit, oneErr := syncOneMovie(comicsDetail, tagMaps, users, manager, terms) if oneErr != nil { log.Warn("MovieAddList syncOneMovie failed", log.Any("id", comicsDetail.Id), log.E(oneErr)) failedIds = append(failedIds, comicsDetail.Id) continue } if hit != nil { hits = append(hits, *hit) } } if len(failedIds) > 0 { return hits, errors.New(fmt.Sprintf("需要同步%d部资源,失败%d,失败Id[%s]", len(param.Ids), len(failedIds), strings.Join(failedIds, ","))) } return hits, nil } return hits, errors.New("该资源暂不支持") } func syncOneMovie(movieDetail laosiji.MovieDetailResp, tags map[string]primitive.ObjectID, upUsers []*usermod.User, manager string, terms []string) (*vidser.SensitiveHit, error) { now := time.Now() postList, err := vidmod.GetList(bson.M{"sourceID": bson.M{"$in": []string{movieDetail.Id}}}) if err != nil { log.Warn("syncOneMovie GetList failed", log.Any("id", movieDetail.Id), log.E(err)) return nil, err } if postList != nil && len(postList) > 0 { h265URL := movieH265SourceURL(movieDetail.Links) if h265URL == "" { return nil, nil } video := postList[0] if err = vidmod.MarkH265Success(video.ID, h265URL); err != nil { return nil, err } if webg.Redis != nil { cacheKey := fmt.Sprintf(redisconst.VideoInfoKey(), video.ID.Hex()) if _, err = webg.Redis.Del(cacheKey); err != nil { log.Warn("syncOneMovie clear video cache failed", log.Any("id", video.ID), log.Any("cacheKey", cacheKey), log.E(err)) return nil, err } } return nil, nil } vidInfo := vidmod.VideoModel{ ID: primitive.NewObjectID(), Title: movieDetail.Name, Content: movieDetail.Description, Tags: make([]primitive.ObjectID, 0), MimeType: "video/mp4", SeriesCover: make([]string, 0), Via: "laosiji", Status: vidmod.CheckPass, Location: primitive.ObjectID{}, Actor: movieDetail.Actor, NewUpdatedAt: "laosiji", ReviewAt: now, CreatedAt: now, UpdatedAt: now, ReviewAccount: manager, VerticalCover: movieDetail.Img_y, } if movieDetail.Img_type == "short" && len(movieDetail.Img_y) > 0 { vidInfo.NewsType = vidmod.SHORT vidInfo.Cover = movieDetail.Img_y vidInfo.CoverThumb = movieDetail.Img_y vidInfo.Direction = "vertical" } else { vidInfo.NewsType = vidmod.SP vidInfo.Cover = movieDetail.Img_x vidInfo.CoverThumb = movieDetail.Img_x vidInfo.Direction = "horizontal" } playTime, _ := strconv.Atoi(movieDetail.Duration) vidInfo.PlayTime = uint(playTime) uIndex := rand.Intn(len(upUsers)) u := upUsers[uIndex] vidInfo.PublisherID = u.UID if movieDetail.Links != nil && len(movieDetail.Links) > 0 { vidInfo.SourceURL = movieDetail.Links[0].M3u8_url vidInfo.Filename = movieDetail.Links[0].Name vidInfo.PreviewURL = movieDetail.Links[0].Preview_m3u8_url vidInfo.H265Url = movieH265SourceURL(movieDetail.Links) if vidInfo.H265Url != "" { vidInfo.H265Status = vidmod.H265StatusSuccess } } vidInfo.SourceID = movieDetail.Id if movieDetail.Tags != nil && len(movieDetail.Tags) > 0 { for _, tag := range movieDetail.Tags { if k, ok := tags[tag.Name]; ok { vidInfo.Tags = append(vidInfo.Tags, k) } } } // 敏感词命中 → 强制为待审核(WaitingCheck=0) hit := vidser.CheckTextHits(terms, movieDetail.Id, vidInfo.Title, vidInfo.Content, "") if hit != nil { vidInfo.Status = vidmod.WaitingCheck log.Warn("syncOneMovie sensitive hit, forced offline", log.Any("sourceId", hit.SourceID), log.Any("title", hit.Title), log.Any("detail", hit.Detail)) } if vidInfo.H265Url == "" && vidInfo.SourceURL != "" && vidInfo.Status == vidmod.CheckPass && vidInfo.NewsType == vidmod.SP { vidInfo.H265Status = vidmod.H265StatusQueued vidInfo.H265QueuedAt = now } if _, err = vidmod.InsertBase(vidInfo); err != nil { return nil, err } return hit, nil } // movieH265SourceURL 返回首个播放链接对应的 H.265 地址。 // syncOneMovie 的 H.264 也固定使用 links[0],不能拿后续分集的 H.265 与首集混用。 func movieH265SourceURL(links []laosiji.LinkInfo) string { if len(links) == 0 { return "" } return laosiji.MovieM3u8SourcePath(links[0].Hevc_m3u8_url) } func checkInsertVidTags(names []string) (data map[string]vidmod.ObjectID, err error) { data = make(map[string]vidmod.ObjectID) tags, err := tagmod.FindOneTagByNames(names) if err != nil { log.Warn("checkInsertVidTags tagmod.FindOneTagByNames", log.E(err), log.Any("name", names)) return } for _, tag := range tags { data[tag.TagName] = tag.ID } insertTags := make([]tagmod.Tag, 0) for _, tag := range tags { if _, ok := data[tag.TagName]; !ok { insertTag := tagmod.Tag{ ID: primitive.NewObjectID(), TagName: tag.TagName, IsActive: true, CreatedAt: time.Now(), UpdatedAt: time.Now(), } insertTags = append(insertTags, insertTag) data[tag.TagName] = insertTag.ID } } if len(insertTags) > 0 { err = tagmod.InsertMany(insertTags) if err != nil { log.Warn("checkInsertVidTags InsertMany failed", log.Any("tags", insertTags), log.E(err)) return } } return }