mirror of
https://github.com/truewhile/MeBox.git
synced 2026-10-06 21:36:37 +08:00
default exclude incompatible subscription releases
This commit is contained in:
@@ -13,10 +13,16 @@ var (
|
|||||||
seasonOnlyRE = regexp.MustCompile(`(?i)(?:^|[\s._-])(?:s|season)\s*\d{1,2}(?:[\s._-]|$)|第\s*\d+\s*季`)
|
seasonOnlyRE = regexp.MustCompile(`(?i)(?:^|[\s._-])(?:s|season)\s*\d{1,2}(?:[\s._-]|$)|第\s*\d+\s*季`)
|
||||||
)
|
)
|
||||||
|
|
||||||
// defaultExcludeWords 是默认过滤的「垃圾版本」排除清单,对所有订阅生效,
|
// defaultExcludeWords 是默认过滤的「垃圾版本」排除清单,对所有订阅生效。
|
||||||
// 与用户自定义排除词合并。拉丁词在 containsAnyExcludeToken 里按词边界匹配以避免子串误伤。
|
// 拉丁词在 containsAnyExcludeToken 里按词边界匹配以避免子串误伤。
|
||||||
const defaultExcludeWords = "cam,ts,tc,telesync,telecine,hdcam,hdts,枪版,抢先,抢鲜,预告,trailer,sample"
|
const defaultExcludeWords = "cam,ts,tc,telesync,telecine,hdcam,hdts,枪版,抢先,抢鲜,预告,trailer,sample"
|
||||||
|
|
||||||
|
// defaultCompatibilityExcludeWords 是面向自动订阅的兼容性默认排除清单。
|
||||||
|
// 仅在用户未真正自定义排除词时启用,避免默认命中 DoVi/H.265/10bit/杜比音轨等版本。
|
||||||
|
const defaultCompatibilityExcludeWords = "dovi,dv,dolby vision,dolby,杜比视界,杜比,h265,h.265,h-265,h_265,h 265,hevc,x265,10bit,10-bit,10 bit,hi10p,atmos,truehd,ddp,dd+,eac3"
|
||||||
|
|
||||||
|
const legacyFrontendExcludeWords = "cam,ts,tc,枪版"
|
||||||
|
|
||||||
func matchesSubscriptionRules(sub *model.Subscription, title string) bool {
|
func matchesSubscriptionRules(sub *model.Subscription, title string) bool {
|
||||||
titleFold := strings.ToLower(title)
|
titleFold := strings.ToLower(title)
|
||||||
if containsAnyExcludeToken(titleFold, defaultExcludeWords) {
|
if containsAnyExcludeToken(titleFold, defaultExcludeWords) {
|
||||||
@@ -25,6 +31,9 @@ func matchesSubscriptionRules(sub *model.Subscription, title string) bool {
|
|||||||
if sub == nil {
|
if sub == nil {
|
||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
if shouldApplyDefaultCompatibilityExcludes(sub.ExcludeWords) && containsAnyExcludeToken(titleFold, defaultCompatibilityExcludeWords) {
|
||||||
|
return false
|
||||||
|
}
|
||||||
if sub.ExcludeWords != "" && containsAnyExcludeToken(titleFold, sub.ExcludeWords) {
|
if sub.ExcludeWords != "" && containsAnyExcludeToken(titleFold, sub.ExcludeWords) {
|
||||||
return false
|
return false
|
||||||
}
|
}
|
||||||
@@ -43,6 +52,24 @@ func matchesSubscriptionRules(sub *model.Subscription, title string) bool {
|
|||||||
return true
|
return true
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func shouldApplyDefaultCompatibilityExcludes(excludeWords string) bool {
|
||||||
|
normalized := normalizeExcludeWords(excludeWords)
|
||||||
|
return normalized == "" || normalized == normalizeExcludeWords(legacyFrontendExcludeWords)
|
||||||
|
}
|
||||||
|
|
||||||
|
func normalizeExcludeWords(csv string) string {
|
||||||
|
parts := make([]string, 0)
|
||||||
|
for _, token := range strings.FieldsFunc(strings.ToLower(csv), func(r rune) bool {
|
||||||
|
return r == ',' || r == '/' || r == '|' || r == ';' || r == ','
|
||||||
|
}) {
|
||||||
|
token = strings.TrimSpace(token)
|
||||||
|
if token != "" {
|
||||||
|
parts = append(parts, token)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
return strings.Join(parts, ",")
|
||||||
|
}
|
||||||
|
|
||||||
func subscriptionCandidateScore(sub *model.Subscription, item SearchResult) int {
|
func subscriptionCandidateScore(sub *model.Subscription, item SearchResult) int {
|
||||||
title := strings.ToLower(subscriptionSearchResultText(item))
|
title := strings.ToLower(subscriptionSearchResultText(item))
|
||||||
score := item.Seeders
|
score := item.Seeders
|
||||||
|
|||||||
@@ -39,6 +39,45 @@ func TestMatchesSubscriptionRulesDefaultExcludesJunkReleases(t *testing.T) {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
func TestMatchesSubscriptionRulesDefaultExcludesCompatibilityReleases(t *testing.T) {
|
||||||
|
cases := []struct {
|
||||||
|
name string
|
||||||
|
sub *model.Subscription
|
||||||
|
}{
|
||||||
|
{name: "empty exclude words", sub: &model.Subscription{}},
|
||||||
|
{name: "legacy frontend defaults", sub: &model.Subscription{ExcludeWords: "cam,ts,tc,枪版"}},
|
||||||
|
}
|
||||||
|
|
||||||
|
for _, c := range cases {
|
||||||
|
t.Run(c.name, func(t *testing.T) {
|
||||||
|
for _, title := range []string{
|
||||||
|
"Some Movie 2024 2160p DoVi H.265 10bit",
|
||||||
|
"Some Movie 2024 2160p H-265",
|
||||||
|
"Some Movie 2024 1080p HEVC",
|
||||||
|
"Some Movie 2024 1080p x265",
|
||||||
|
"Some Movie 2024 2160p Dolby Vision Atmos",
|
||||||
|
"某电影 2024 1080p 杜比全景声",
|
||||||
|
"Some Anime 2024 1080p Hi10P",
|
||||||
|
} {
|
||||||
|
if matchesSubscriptionRules(c.sub, title) {
|
||||||
|
t.Errorf("expected default compatibility rules to exclude %q", title)
|
||||||
|
}
|
||||||
|
}
|
||||||
|
})
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
|
func TestMatchesSubscriptionRulesCustomExcludeWordsCanOptOutOfCompatibilityDefaults(t *testing.T) {
|
||||||
|
sub := &model.Subscription{ExcludeWords: "sample"}
|
||||||
|
title := "Some Movie 2024 2160p DoVi HEVC 10bit"
|
||||||
|
if !matchesSubscriptionRules(sub, title) {
|
||||||
|
t.Fatalf("custom exclude words should not force default compatibility excludes for %q", title)
|
||||||
|
}
|
||||||
|
if matchesSubscriptionRules(sub, "Some Movie 2024 1080p SAMPLE") {
|
||||||
|
t.Fatal("custom exclude words should still apply")
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|
||||||
func TestMatchesSubscriptionRulesWordBoundaryAvoidsFalsePositives(t *testing.T) {
|
func TestMatchesSubscriptionRulesWordBoundaryAvoidsFalsePositives(t *testing.T) {
|
||||||
sub := &model.Subscription{}
|
sub := &model.Subscription{}
|
||||||
// "ts" / "cam" / "tc" 作为子串出现在合法标题里时不应被默认排除误伤。
|
// "ts" / "cam" / "tc" 作为子串出现在合法标题里时不应被默认排除误伤。
|
||||||
|
|||||||
@@ -110,7 +110,7 @@ export function SubscriptionForm({ values, editing, onSubmit, onCancelEdit, onCh
|
|||||||
/>
|
/>
|
||||||
<input
|
<input
|
||||||
className="input-base"
|
className="input-base"
|
||||||
placeholder="排除词,如 cam,ts,tc"
|
placeholder="排除词,如 cam,ts,dovi,h265,10bit,杜比"
|
||||||
value={values.excludeWords}
|
value={values.excludeWords}
|
||||||
onChange={(e) => onChange('excludeWords', e.target.value)}
|
onChange={(e) => onChange('excludeWords', e.target.value)}
|
||||||
/>
|
/>
|
||||||
|
|||||||
@@ -1,6 +1,7 @@
|
|||||||
import type { DiscoverItem } from '../api/discover'
|
import type { DiscoverItem } from '../api/discover'
|
||||||
import { buildSiteSearchFeedURL, buildSubscriptionAliases } from '../api/subscriptions'
|
import { buildSiteSearchFeedURL, buildSubscriptionAliases } from '../api/subscriptions'
|
||||||
import { buildSubscribeKeyword } from './discoverPageModel'
|
import { buildSubscribeKeyword } from './discoverPageModel'
|
||||||
|
import { defaultSubscriptionExcludeWords } from './subscriptionFormModel'
|
||||||
|
|
||||||
export type DiscoverSubscriptionForm = {
|
export type DiscoverSubscriptionForm = {
|
||||||
keyword: string
|
keyword: string
|
||||||
@@ -34,7 +35,7 @@ export function initialDiscoverSubscriptionForm(item: DiscoverItem): DiscoverSub
|
|||||||
quality: '',
|
quality: '',
|
||||||
effects: '',
|
effects: '',
|
||||||
release_groups: '',
|
release_groups: '',
|
||||||
exclude_words: 'cam,ts,tc,枪版',
|
exclude_words: defaultSubscriptionExcludeWords,
|
||||||
wash_enabled: false,
|
wash_enabled: false,
|
||||||
wash_priority: 'balanced',
|
wash_priority: 'balanced',
|
||||||
save_path: '',
|
save_path: '',
|
||||||
|
|||||||
@@ -16,6 +16,9 @@ export interface SubscriptionFormValues {
|
|||||||
washPriority: string
|
washPriority: string
|
||||||
}
|
}
|
||||||
|
|
||||||
|
export const defaultSubscriptionExcludeWords =
|
||||||
|
'cam,ts,tc,枪版,dovi,dv,dolby vision,dolby,杜比视界,杜比,h265,h.265,h-265,h_265,hevc,x265,10bit,10-bit,hi10p,atmos,truehd,ddp,dd+,eac3'
|
||||||
|
|
||||||
export const defaultSubscriptionFormValues: SubscriptionFormValues = {
|
export const defaultSubscriptionFormValues: SubscriptionFormValues = {
|
||||||
name: '',
|
name: '',
|
||||||
feed: '',
|
feed: '',
|
||||||
@@ -29,7 +32,7 @@ export const defaultSubscriptionFormValues: SubscriptionFormValues = {
|
|||||||
quality: '',
|
quality: '',
|
||||||
effects: '',
|
effects: '',
|
||||||
releaseGroups: '',
|
releaseGroups: '',
|
||||||
excludeWords: 'cam,ts,tc,枪版',
|
excludeWords: defaultSubscriptionExcludeWords,
|
||||||
washEnabled: false,
|
washEnabled: false,
|
||||||
washPriority: 'balanced',
|
washPriority: 'balanced',
|
||||||
}
|
}
|
||||||
|
|||||||
Reference in New Issue
Block a user