mirror of
https://github.com/truewhile/MeBox.git
synced 2026-09-29 19:36:36 +08:00
85 lines
3.0 KiB
Go
85 lines
3.0 KiB
Go
// Package service — subscription planning and release candidate selection.
|
|
package service
|
|
|
|
import "github.com/ShukeBta/MediaStationGo/internal/model"
|
|
|
|
type siteSearchCandidate struct {
|
|
Item SearchResult
|
|
Download string
|
|
GUID string
|
|
Season int
|
|
Episode int
|
|
Pack bool
|
|
Score int
|
|
}
|
|
|
|
type siteSearchSelectionStats struct {
|
|
Total int
|
|
QueryMismatch int
|
|
QueryMismatchExamples []string
|
|
RelaxedQueryMatch int
|
|
RuleMismatch int
|
|
MissingDownload int
|
|
Seen int
|
|
Prepared int
|
|
Selected int
|
|
LocalAlreadySatisfied bool
|
|
LocalSeriesPackPresent bool
|
|
SeriesComplete bool
|
|
ExistingEpisodeSkipped int
|
|
NotMissingEpisodeSkipped int
|
|
NoEpisodeSkipped int
|
|
PackFallbackAvailable bool
|
|
PackFallbackUsed bool
|
|
}
|
|
|
|
// SubscriptionPlanner owns release selection decisions for subscriptions:
|
|
// rule matching, candidate scoring, and filtering against known availability.
|
|
type SubscriptionPlanner struct{}
|
|
|
|
func selectSiteSearchCandidates(results []SearchResult, sub *model.Subscription, seenSet map[string]struct{}, availability ...LocalAvailability) []siteSearchCandidate {
|
|
return SubscriptionPlanner{}.SelectSiteSearchCandidates(results, sub, seenSet, availability...)
|
|
}
|
|
|
|
func (SubscriptionPlanner) SelectSiteSearchCandidates(results []SearchResult, sub *model.Subscription, seenSet map[string]struct{}, availability ...LocalAvailability) []siteSearchCandidate {
|
|
if sub == nil {
|
|
return nil
|
|
}
|
|
if seenSet == nil {
|
|
seenSet = map[string]struct{}{}
|
|
}
|
|
local := LocalAvailability{}
|
|
if len(availability) > 0 {
|
|
local = availability[0]
|
|
}
|
|
candidates, _ := selectSiteSearchCandidatesWithStats(results, sub, seenSet, local)
|
|
return candidates
|
|
}
|
|
|
|
func selectSiteSearchCandidatesWithAvailability(results []SearchResult, sub *model.Subscription, seenSet map[string]struct{}, local LocalAvailability) []siteSearchCandidate {
|
|
candidates, _ := selectSiteSearchCandidatesWithStats(results, sub, seenSet, local)
|
|
return candidates
|
|
}
|
|
|
|
func selectSiteSearchCandidatesWithStats(results []SearchResult, sub *model.Subscription, seenSet map[string]struct{}, local LocalAvailability) ([]siteSearchCandidate, siteSearchSelectionStats) {
|
|
stats := siteSearchSelectionStats{Total: len(results)}
|
|
if sub == nil {
|
|
return nil, stats
|
|
}
|
|
if seenSet == nil {
|
|
seenSet = map[string]struct{}{}
|
|
}
|
|
candidates := collectSiteSearchCandidates(results, sub, seenSet, false, &stats)
|
|
if len(candidates) == 0 && shouldRelaxSiteSearchQueryMatch(sub, local) && stats.QueryMismatch > 0 {
|
|
relaxedStats := siteSearchSelectionStats{Total: len(results)}
|
|
candidates = collectSiteSearchCandidates(results, sub, seenSet, true, &relaxedStats)
|
|
stats.RuleMismatch = relaxedStats.RuleMismatch
|
|
stats.MissingDownload = relaxedStats.MissingDownload
|
|
stats.Seen = relaxedStats.Seen
|
|
stats.Prepared = relaxedStats.Prepared
|
|
stats.RelaxedQueryMatch = relaxedStats.RelaxedQueryMatch
|
|
}
|
|
selected := selectPreparedSubscriptionCandidatesWithStats(candidates, sub, local, &stats)
|
|
return selected, stats
|
|
}
|