@@ -0,0 +1,106 @@
|
||||
package mediaser
|
||||
|
||||
import (
|
||||
"testing"
|
||||
|
||||
"91porn-server/models/v/mediacontentmod"
|
||||
"91porn-server/models/v/mediamod"
|
||||
|
||||
"go.mongodb.org/mongo-driver/bson/primitive"
|
||||
)
|
||||
|
||||
func validDramaCreateReq() WebCreateReq {
|
||||
return WebCreateReq{
|
||||
Title: "测试短剧",
|
||||
HorizontalCover: "https://example.com/h.jpg",
|
||||
VerticalCover: "https://example.com/v.jpg",
|
||||
TotalEpisode: 10,
|
||||
UpdateStatus: mediamod.Update,
|
||||
MediaType: mediamod.MediaTypeDrama,
|
||||
Kind: mediamod.Theater,
|
||||
Permission: 1,
|
||||
}
|
||||
}
|
||||
|
||||
func TestWebCreateReqValidateDrama(t *testing.T) {
|
||||
tests := []struct {
|
||||
name string
|
||||
mutate func(*WebCreateReq)
|
||||
wantErr bool
|
||||
}{
|
||||
{name: "valid"},
|
||||
{name: "missing cover", mutate: func(req *WebCreateReq) { req.VerticalCover = "" }, wantErr: true},
|
||||
{name: "published before first episode", mutate: func(req *WebCreateReq) { req.Status = 1 }, wantErr: true},
|
||||
{name: "wrong kind", mutate: func(req *WebCreateReq) { req.Kind = 1 }, wantErr: true},
|
||||
{name: "wrong permission", mutate: func(req *WebCreateReq) { req.Permission = 2 }, wantErr: true},
|
||||
}
|
||||
for _, tt := range tests {
|
||||
t.Run(tt.name, func(t *testing.T) {
|
||||
req := validDramaCreateReq()
|
||||
if tt.mutate != nil {
|
||||
tt.mutate(&req)
|
||||
}
|
||||
if gotErr := req.Validate() != nil; gotErr != tt.wantErr {
|
||||
t.Fatalf("Validate() error = %v, wantErr %v", gotErr, tt.wantErr)
|
||||
}
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
func TestValidateDramaMediaForPublish(t *testing.T) {
|
||||
media := mediamod.Media{
|
||||
ID: primitive.NewObjectID(),
|
||||
MediaType: mediamod.MediaTypeDrama,
|
||||
Title: "测试短剧",
|
||||
HorizontalCover: "h.jpg",
|
||||
VerticalCover: "v.jpg",
|
||||
TotalEpisode: 10,
|
||||
UpdateStatus: mediamod.Update,
|
||||
Kind: mediamod.Theater,
|
||||
Permission: 1,
|
||||
}
|
||||
first := mediacontentmod.MediaContent{
|
||||
ID: primitive.NewObjectID(),
|
||||
MediaID: media.ID,
|
||||
MediaType: mediamod.MediaTypeDrama,
|
||||
EpisodeNumber: 1,
|
||||
Name: "第1集",
|
||||
Status: 1,
|
||||
IsActive: true,
|
||||
VideoUrl: "https://example.com/1.m3u8",
|
||||
}
|
||||
if err := validateDramaMediaForPublish(media, first); err != nil {
|
||||
t.Fatalf("valid drama cannot publish: %v", err)
|
||||
}
|
||||
first.Status = 0
|
||||
if err := validateDramaMediaForPublish(media, first); err == nil {
|
||||
t.Fatal("transcoding first episode unexpectedly allowed to publish")
|
||||
}
|
||||
first.Status = 1
|
||||
first.VideoUrl = ""
|
||||
if err := validateDramaMediaForPublish(media, first); err == nil {
|
||||
t.Fatal("first episode without play URL unexpectedly allowed to publish")
|
||||
}
|
||||
}
|
||||
|
||||
func TestWebListReqFilterUsesScalarValues(t *testing.T) {
|
||||
status, kind, mediaCenterID := 1, mediamod.Theater, uint(123)
|
||||
req := WebListReq{Status: &status, Kind: &kind, MediaCenterID: &mediaCenterID}
|
||||
filter := req.Filter()
|
||||
if filter["status"] != status || filter["kind"] != kind || filter["mediaCenterId"] != mediaCenterID {
|
||||
t.Fatalf("unexpected filter: %#v", filter)
|
||||
}
|
||||
}
|
||||
|
||||
func TestWebBatchUpdateReqRejectsDramaParentPricing(t *testing.T) {
|
||||
price := int64(30)
|
||||
req := WebBatchUpdateReq{Price: &price}
|
||||
medias := []*mediamod.Media{{MediaType: mediamod.MediaTypeDrama}}
|
||||
if err := req.validateDramaBatchFields(medias); err == nil {
|
||||
t.Fatal("drama parent pricing unexpectedly accepted")
|
||||
}
|
||||
req.Price = nil
|
||||
if err := req.validateDramaBatchFields(medias); err != nil {
|
||||
t.Fatalf("drama batch without parent pricing rejected: %v", err)
|
||||
}
|
||||
}
|
||||
Executable
+1095
File diff suppressed because it is too large
Load Diff
@@ -0,0 +1,100 @@
|
||||
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, " "))
|
||||
}
|
||||
Reference in New Issue
Block a user