mirror of
https://github.com/truewhile/MeBox.git
synced 2026-10-07 22:06:38 +08:00
split subscription availability helpers
This commit is contained in:
@@ -0,0 +1,182 @@
|
||||
package service
|
||||
|
||||
import (
|
||||
"context"
|
||||
"strings"
|
||||
|
||||
"github.com/ShukeBta/MediaStationGo/internal/model"
|
||||
)
|
||||
|
||||
func addAvailabilityTitle(title, query string, out *LocalAvailability) {
|
||||
if out == nil || strings.TrimSpace(title) == "" || strings.TrimSpace(query) == "" {
|
||||
return
|
||||
}
|
||||
if !availabilityTitleMatchesAny(title, []string{query}) {
|
||||
return
|
||||
}
|
||||
out.LocalMediaCount++
|
||||
if refs := episodeRefsFromTitle(title); len(refs) > 0 {
|
||||
if out.ExistingEpisodeKeys == nil {
|
||||
out.ExistingEpisodeKeys = map[string]struct{}{}
|
||||
}
|
||||
for _, ref := range refs {
|
||||
out.ExistingEpisodeKeys[episodeKey(ref.Season, ref.Episode)] = struct{}{}
|
||||
}
|
||||
return
|
||||
}
|
||||
if isSeriesPackTitle(title) {
|
||||
out.HasSeriesPack = true
|
||||
}
|
||||
}
|
||||
|
||||
func addAvailabilityTitleAny(title string, queries []string, out *LocalAvailability) {
|
||||
if !availabilityTitleMatchesAny(title, queries) {
|
||||
return
|
||||
}
|
||||
addTrustedAvailabilityTitle(title, 0, 0, false, out)
|
||||
}
|
||||
|
||||
func availabilityTitleMatchesAny(title string, queries []string) bool {
|
||||
titleKey := normalizeAvailabilityComparable(title)
|
||||
if titleKey == "" {
|
||||
return false
|
||||
}
|
||||
for _, query := range queries {
|
||||
queryKey := normalizeAvailabilityComparable(query)
|
||||
if queryKey == "" {
|
||||
continue
|
||||
}
|
||||
if strings.Contains(titleKey, queryKey) {
|
||||
return true
|
||||
}
|
||||
}
|
||||
return false
|
||||
}
|
||||
|
||||
func addSiteSearchCandidateAvailability(candidate siteSearchCandidate, out *LocalAvailability) {
|
||||
addTrustedAvailabilityTitle(subscriptionSearchResultText(candidate.Item), candidate.Season, candidate.Episode, candidate.Pack, out)
|
||||
}
|
||||
|
||||
func (s *SubscriptionService) subscriptionCandidateConfirmedAvailable(ctx context.Context, sub *model.Subscription, candidate siteSearchCandidate) bool {
|
||||
availability := mergeLocalAvailability(
|
||||
SubscriptionLocalAvailability(ctx, s.repo, sub),
|
||||
s.pendingDownloadAvailability(ctx, sub),
|
||||
)
|
||||
return candidateAvailableInAvailability(sub, candidate, availability)
|
||||
}
|
||||
|
||||
func candidateAvailableInAvailability(sub *model.Subscription, candidate siteSearchCandidate, availability LocalAvailability) bool {
|
||||
mediaType := normalizeMediaType(subscriptionMediaType(sub), subscriptionName(sub)+" "+subscriptionFilter(sub), "")
|
||||
if !isSubscriptionSeriesType(mediaType) {
|
||||
return availability.LocalMediaCount > 0 || availability.InLibrary
|
||||
}
|
||||
episodes := candidateEpisodeNumbers(candidate)
|
||||
if len(episodes) == 0 {
|
||||
return availability.HasSeriesPack
|
||||
}
|
||||
season := candidate.Season
|
||||
if season <= 0 {
|
||||
season = 1
|
||||
}
|
||||
for _, episode := range episodes {
|
||||
if _, ok := availability.ExistingEpisodeKeys[episodeKey(season, episode)]; !ok {
|
||||
return false
|
||||
}
|
||||
}
|
||||
return true
|
||||
}
|
||||
|
||||
func addTrustedAvailabilityTitle(title string, season, episode int, pack bool, out *LocalAvailability) {
|
||||
if out == nil {
|
||||
return
|
||||
}
|
||||
if strings.TrimSpace(title) == "" && episode <= 0 && !pack {
|
||||
return
|
||||
}
|
||||
out.LocalMediaCount++
|
||||
refs := episodeRefsFromTitle(title)
|
||||
if len(refs) == 0 && episode > 0 {
|
||||
if season <= 0 {
|
||||
season = 1
|
||||
}
|
||||
refs = []episodeRef{{Season: season, Episode: episode}}
|
||||
}
|
||||
if len(refs) > 0 {
|
||||
if out.ExistingEpisodeKeys == nil {
|
||||
out.ExistingEpisodeKeys = map[string]struct{}{}
|
||||
}
|
||||
for _, ref := range refs {
|
||||
out.ExistingEpisodeKeys[episodeKey(ref.Season, ref.Episode)] = struct{}{}
|
||||
}
|
||||
return
|
||||
}
|
||||
if episode <= 0 {
|
||||
season, episode = ParseEpisode(title)
|
||||
}
|
||||
if episode > 0 {
|
||||
if out.ExistingEpisodeKeys == nil {
|
||||
out.ExistingEpisodeKeys = map[string]struct{}{}
|
||||
}
|
||||
out.ExistingEpisodeKeys[episodeKey(season, episode)] = struct{}{}
|
||||
return
|
||||
}
|
||||
if pack || isSeriesPackTitle(title) {
|
||||
out.HasSeriesPack = true
|
||||
}
|
||||
}
|
||||
|
||||
func mergeLocalAvailability(values ...LocalAvailability) LocalAvailability {
|
||||
out := LocalAvailability{
|
||||
ExistingEpisodeKeys: map[string]struct{}{},
|
||||
MissingEpisodeKeys: map[string]struct{}{},
|
||||
}
|
||||
for _, value := range values {
|
||||
if value.TotalEpisodes > out.TotalEpisodes {
|
||||
out.TotalEpisodes = value.TotalEpisodes
|
||||
}
|
||||
out.LocalMediaCount += value.LocalMediaCount
|
||||
out.InLibrary = out.InLibrary || value.InLibrary
|
||||
out.HasSeriesPack = out.HasSeriesPack || value.HasSeriesPack
|
||||
for key := range value.ExistingEpisodeKeys {
|
||||
out.ExistingEpisodeKeys[key] = struct{}{}
|
||||
}
|
||||
}
|
||||
out.DownloadedEpisodes = len(out.ExistingEpisodeKeys)
|
||||
if out.TotalEpisodes > 0 {
|
||||
out.MissingEpisodes = missingEpisodes(out.ExistingEpisodeKeys, out.TotalEpisodes)
|
||||
for _, episode := range out.MissingEpisodes {
|
||||
out.MissingEpisodeKeys[episodeKey(1, episode)] = struct{}{}
|
||||
}
|
||||
}
|
||||
if out.DownloadedEpisodes == 0 && out.LocalMediaCount > 0 {
|
||||
out.DownloadedEpisodes = out.LocalMediaCount
|
||||
if out.TotalEpisodes == 0 {
|
||||
out.TotalEpisodes = 1
|
||||
}
|
||||
}
|
||||
return out
|
||||
}
|
||||
|
||||
// subscriptionItemAlreadyAvailable 判断某个订阅条目(按其标题解析出的季/集)是否已在媒体库存在。
|
||||
// 电影/无集号条目:媒体库已有该片即视为已存在;剧集条目:对应季集已入库即视为已存在。
|
||||
func subscriptionItemAlreadyAvailable(sub *model.Subscription, avail LocalAvailability, title string) bool {
|
||||
if avail.LocalMediaCount == 0 && !avail.HasSeriesPack {
|
||||
return false
|
||||
}
|
||||
if !isSubscriptionSeriesType(subscriptionMediaType(sub)) {
|
||||
return true
|
||||
}
|
||||
if avail.HasSeriesPack {
|
||||
return true
|
||||
}
|
||||
wantSeason, wantEpisode := ParseEpisode(title)
|
||||
if wantEpisode <= 0 {
|
||||
// 整季合集 / 无法解析集号:库里已有内容时保守跳过,避免重复整季下载。
|
||||
return true
|
||||
}
|
||||
if wantSeason <= 0 {
|
||||
wantSeason = 1
|
||||
}
|
||||
_, exists := avail.ExistingEpisodeKeys[episodeKey(wantSeason, wantEpisode)]
|
||||
return exists
|
||||
}
|
||||
Reference in New Issue
Block a user