package mediaser import ( "fmt" "strings" "91porn-server/models/v/mediamod" "91porn-server/models/v/sensitivewordmod" "go.mongodb.org/mongo-driver/bson/primitive" ) // CheckSensitive 单条媒资编辑的上架敏感词校验,规则对齐 vid/update: // // 1. status 被切到上架(1) —— 上架转换 // 2. 当前已上架(status==1) 且本次更新涉及 Title/Summary —— 已上架内容改动 // // 校验文本以请求字段为准(提供则用新值,否则用 DB 现值)。 // 返回 (命中详情, true) 时调用方应拒绝本次更新;未命中或与上架无关返回 ("", false)。 func (p *WebUpdateReq) CheckSensitive() (string, bool) { media, err := mediamod.GetInfo(p.ID) if err != nil { // 查不到交给后续 Update 流程报错,这里不拦 return "", false } // mediamod.Media.Status: 1 上架 / 0 下架 const statusUp = 1 shelvingTransition := p.Status != nil && *p.Status == statusUp currentlyShelved := media.Status == statusUp touchesText := p.Title != nil || p.Summary != nil if !shelvingTransition && !(currentlyShelved && touchesText) { return "", false } title := media.Title summary := media.Summary if p.Title != nil { title = *p.Title } if p.Summary != nil { summary = *p.Summary } terms := sensitivewordmod.LoadEnabledTerms() if len(terms) == 0 { return "", false } titleHits := sensitivewordmod.MatchHits(title, terms) summaryHits := sensitivewordmod.MatchHits(summary, terms) if len(titleHits) == 0 && len(summaryHits) == 0 { return "", false } return formatMediaHitLine(p.ID, title, titleHits, summaryHits), true } // CheckSensitive 批量媒资更新的上架敏感词校验。 // 批量请求体不含文本字段,因此仅当 IsActive=true(批量上架)时, // 对每个 id 的 DB 现值 Title/Summary 做命中检测。任一命中即拒绝,多条按行聚合。 func (p *WebBatchUpdateReq) CheckSensitive() (string, bool) { if p.IsActive == nil || !*p.IsActive { return "", false } terms := sensitivewordmod.LoadEnabledTerms() if len(terms) == 0 { return "", false } lines := make([]string, 0) for _, id := range p.Filter() { if id.IsZero() { continue } media, err := mediamod.GetInfo(id) if err != nil { continue } titleHits := sensitivewordmod.MatchHits(media.Title, terms) summaryHits := sensitivewordmod.MatchHits(media.Summary, terms) if len(titleHits) == 0 && len(summaryHits) == 0 { continue } lines = append(lines, formatMediaHitLine(media.ID, media.Title, titleHits, summaryHits)) } if len(lines) == 0 { return "", false } return strings.Join(lines, "\n"), true } // formatMediaHitLine 媒资命中描述: // "id:xxxx 对象标题 XXXXXX。 标题命中 XX 简介命中 YY,不予上架成功" func formatMediaHitLine(id primitive.ObjectID, title string, titleHits, summaryHits []string) string { parts := make([]string, 0, 2) if len(titleHits) > 0 { parts = append(parts, "标题命中 "+strings.Join(titleHits, "、")) } if len(summaryHits) > 0 { parts = append(parts, "简介命中 "+strings.Join(summaryHits, "、")) } return fmt.Sprintf("id:%s 对象标题 %s。 %s,不予上架成功", id.Hex(), title, strings.Join(parts, " ")) }