134 lines
3.4 KiB
Go
134 lines
3.4 KiB
Go
package metadata
|
|
|
|
import (
|
|
"strings"
|
|
"time"
|
|
|
|
"github.com/Silo-Server/silo-server/internal/models"
|
|
)
|
|
|
|
const (
|
|
RefreshDebtReasonEpisodeIncomplete int64 = 1
|
|
RefreshDebtReasonStaleProviderID int64 = 2
|
|
RefreshDebtReasonRefreshFailure int64 = 4
|
|
RefreshDebtReasonCoreMetadataIncomplete int64 = 8
|
|
RefreshDebtReasonProviderIDIncomplete int64 = 16
|
|
)
|
|
|
|
const (
|
|
RefreshTargetItem = "item"
|
|
RefreshTargetSeason = "season"
|
|
RefreshTargetEpisode = "episode"
|
|
)
|
|
|
|
func NormalizeRefreshTargetType(targetType string) string {
|
|
switch strings.ToLower(strings.TrimSpace(targetType)) {
|
|
case "", RefreshTargetItem:
|
|
return RefreshTargetItem
|
|
case RefreshTargetSeason:
|
|
return RefreshTargetSeason
|
|
case RefreshTargetEpisode:
|
|
return RefreshTargetEpisode
|
|
default:
|
|
return ""
|
|
}
|
|
}
|
|
|
|
func hasRefreshDebtReason(mask, reason int64) bool {
|
|
return mask&reason != 0
|
|
}
|
|
|
|
func refreshDebtPriority(reasonMask int64) int {
|
|
switch {
|
|
case hasRefreshDebtReason(reasonMask, RefreshDebtReasonEpisodeIncomplete):
|
|
return 300
|
|
case hasRefreshDebtReason(reasonMask, RefreshDebtReasonStaleProviderID):
|
|
return 250
|
|
case hasRefreshDebtReason(reasonMask, RefreshDebtReasonProviderIDIncomplete):
|
|
return 240
|
|
case hasRefreshDebtReason(reasonMask, RefreshDebtReasonRefreshFailure):
|
|
return 200
|
|
case hasRefreshDebtReason(reasonMask, RefreshDebtReasonCoreMetadataIncomplete):
|
|
return 150
|
|
default:
|
|
return 100
|
|
}
|
|
}
|
|
|
|
func nextRefreshDelay(reasonMask int64, attemptCount int) time.Duration {
|
|
if hasRefreshDebtReason(reasonMask, RefreshDebtReasonEpisodeIncomplete) {
|
|
switch {
|
|
case attemptCount <= 1:
|
|
return 24 * time.Hour
|
|
case attemptCount == 2:
|
|
return 3 * 24 * time.Hour
|
|
case attemptCount == 3:
|
|
return 7 * 24 * time.Hour
|
|
case attemptCount == 4:
|
|
return 14 * 24 * time.Hour
|
|
default:
|
|
return 30 * 24 * time.Hour
|
|
}
|
|
}
|
|
|
|
switch {
|
|
case attemptCount <= 1:
|
|
return 24 * time.Hour
|
|
case attemptCount == 2:
|
|
return 3 * 24 * time.Hour
|
|
case attemptCount == 3:
|
|
return 7 * 24 * time.Hour
|
|
case attemptCount == 4:
|
|
return 14 * 24 * time.Hour
|
|
default:
|
|
return 30 * 24 * time.Hour
|
|
}
|
|
}
|
|
|
|
func nextRefreshAtForDebt(reasonMask int64, attemptCount int, now time.Time) time.Time {
|
|
return now.Add(nextRefreshDelay(reasonMask, attemptCount))
|
|
}
|
|
|
|
func refreshDebtReasonsForItem(item *models.MediaItem) int64 {
|
|
if item == nil {
|
|
return 0
|
|
}
|
|
|
|
var reasonMask int64
|
|
if hasCoreMetadataRefreshDebt(item) {
|
|
reasonMask |= RefreshDebtReasonCoreMetadataIncomplete
|
|
}
|
|
if hasProviderIDRefreshDebt(item) {
|
|
reasonMask |= RefreshDebtReasonProviderIDIncomplete
|
|
}
|
|
if item.RefreshFailures > 0 && strings.EqualFold(strings.TrimSpace(item.Status), "matched") {
|
|
reasonMask |= RefreshDebtReasonRefreshFailure
|
|
}
|
|
return reasonMask
|
|
}
|
|
|
|
func hasProviderIDRefreshDebt(item *models.MediaItem) bool {
|
|
if item == nil || !strings.EqualFold(strings.TrimSpace(item.Status), "matched") {
|
|
return false
|
|
}
|
|
if strings.TrimSpace(item.TmdbID) != "" {
|
|
return false
|
|
}
|
|
return strings.TrimSpace(item.TvdbID) != "" || strings.TrimSpace(item.ImdbID) != ""
|
|
}
|
|
|
|
func hasCoreMetadataRefreshDebt(item *models.MediaItem) bool {
|
|
if item == nil || !strings.EqualFold(strings.TrimSpace(item.Status), "matched") {
|
|
return false
|
|
}
|
|
hasRatings := item.RatingIMDB != nil ||
|
|
item.RatingTMDB != nil ||
|
|
item.RatingRTCritic != nil ||
|
|
item.RatingRTAudience != nil
|
|
|
|
return strings.TrimSpace(item.Overview) == "" ||
|
|
strings.TrimSpace(item.PosterPath) == "" ||
|
|
strings.TrimSpace(item.BackdropPath) == "" ||
|
|
!hasRatings
|
|
}
|