Files
rootandClaude Opus 5 8679200f41 Initial commit
Co-Authored-By: Claude Opus 5 <noreply@anthropic.com>
2026-09-15 13:57:10 +08:00

69 lines
2.0 KiB
Go

package contentreviewser
import (
"91porn-server/common/log"
"91porn-server/models/v/contentreviewmod"
"91porn-server/models/v/mediacontentmod"
"91porn-server/models/v/mediamod"
"go.mongodb.org/mongo-driver/bson"
"go.mongodb.org/mongo-driver/bson/primitive"
)
// acgScanner ACG 扫描策略:每个 Media 可能产生 1 个 ACG_MEDIA + N 个 ACG_CONTENT 命中
// 仅匹配 title / summary / 章节名 / 章节内容(不检测 tag)
type acgScanner struct{}
func (s *acgScanner) CountTotal() (int64, error) {
return mediamod.CountForReview()
}
func (s *acgScanner) ScanBatch(taskID, lastID primitive.ObjectID, terms []string) (*ScanResult, error) {
batch, err := mediamod.FindForReviewBatch(lastID, scanBatchSize)
if err != nil {
return nil, err
}
if len(batch) == 0 {
return &ScanResult{Done: true}, nil
}
issues := make([]*contentreviewmod.ReviewIssue, 0)
for _, m := range batch {
issues = append(issues, collectMediaIssues(taskID, m, terms)...)
}
return &ScanResult{
Issues: issues,
Checked: int64(len(batch)),
NextID: batch[len(batch)-1].ID,
}, nil
}
// collectMediaIssues 检测一个 Media 自身及其全部 MediaContent
func collectMediaIssues(taskID primitive.ObjectID, m *mediamod.Media, terms []string) []*contentreviewmod.ReviewIssue {
out := make([]*contentreviewmod.ReviewIssue, 0)
mb := newIssueBuilder(taskID, contentreviewmod.IssueTargetACGMedia, m.ID).
MatchTitle("标题", m.Title, terms).
MatchContent("内容", m.Summary, terms)
if mb.HasHits() {
out = append(out, mb.Build())
}
contents, err := mediacontentmod.QueryAllList(bson.M{"mediaId": m.ID, "isActive": true})
if err != nil {
log.Warn("query media contents fail", log.Any("mid", m.ID), log.E(err))
return out
}
for _, c := range contents {
cb := newIssueBuilder(taskID, contentreviewmod.IssueTargetACGContent, c.ID).
WithMediaID(m.ID).
MatchTitle("章节名", c.Name, terms).
MatchContent("章节内容", c.Text, terms)
if cb.HasHits() {
out = append(out, cb.Build())
}
}
return out
}