82 lines
3.0 KiB
Go
82 lines
3.0 KiB
Go
package models
|
|||
|
|
|
||
|
|
import "time"
|
||
|
|
|
||
|
|
// ExtraKind classifies supplemental video content. It is the shared vocabulary
|
||
|
|
// between remote provider videos (item_videos.kind) and scanner-discovered
|
||
|
|
// local extras (media_extras.kind). Values are lowercase snake_case strings
|
||
|
|
// rather than integer enums so plugins and future providers can emit kinds the
|
||
|
|
// server does not know yet; NormalizeExtraKind folds those to ExtraKindOther.
|
||
|
|
type ExtraKind string
|
||
|
|
|
||
|
|
const (
|
||
|
|
ExtraKindTrailer ExtraKind = "trailer"
|
||
|
|
ExtraKindTeaser ExtraKind = "teaser"
|
||
|
|
ExtraKindFeaturette ExtraKind = "featurette"
|
||
|
|
ExtraKindClip ExtraKind = "clip"
|
||
|
|
ExtraKindBehindTheScenes ExtraKind = "behind_the_scenes"
|
||
|
|
ExtraKindBloopers ExtraKind = "bloopers"
|
||
|
|
// ExtraKindDeletedScene is local-only: TMDB has no matching video type,
|
||
|
|
// but Jellyfin/Plex folder conventions do.
|
||
|
|
ExtraKindDeletedScene ExtraKind = "deleted_scene"
|
||
|
|
ExtraKindOther ExtraKind = "other"
|
||
|
|
)
|
||
|
|
|
||
|
|
// AllExtraKinds lists every known kind, in display order. This is the source
|
||
|
|
// of truth mirrored by the media_folders.trailer_kinds column default.
|
||
|
|
var AllExtraKinds = []ExtraKind{
|
||
|
|
ExtraKindTrailer,
|
||
|
|
ExtraKindTeaser,
|
||
|
|
ExtraKindFeaturette,
|
||
|
|
ExtraKindClip,
|
||
|
|
ExtraKindBehindTheScenes,
|
||
|
|
ExtraKindBloopers,
|
||
|
|
ExtraKindDeletedScene,
|
||
|
|
ExtraKindOther,
|
||
|
|
}
|
||
|
|
|
||
|
|
// NormalizeExtraKind maps an arbitrary kind string onto the known vocabulary,
|
||
|
|
// folding unknown values to ExtraKindOther so newer providers degrade safely.
|
||
|
|
func NormalizeExtraKind(raw string) ExtraKind {
|
||
|
|
switch ExtraKind(raw) {
|
||
|
|
case ExtraKindTrailer, ExtraKindTeaser, ExtraKindFeaturette, ExtraKindClip,
|
||
|
|
ExtraKindBehindTheScenes, ExtraKindBloopers, ExtraKindDeletedScene:
|
||
|
|
return ExtraKind(raw)
|
||
|
|
default:
|
||
|
|
return ExtraKindOther
|
||
|
|
}
|
||
|
|
}
|
||
|
|
|
||
|
|
// ItemVideo is a row in item_videos: a remote promotional/supplemental video
|
||
|
|
// (YouTube trailer, teaser, ...) attached to a media item by a metadata
|
||
|
|
// provider. Rows are replaced wholesale on refresh, keyed for dedup by
|
||
|
|
// (ContentID, Provider, ProviderKey).
|
||
|
|
type ItemVideo struct {
|
||
|
|
ID int64
|
||
|
|
ContentID string
|
||
|
|
Provider string // provider capability slug, e.g. "tmdb"
|
||
|
|
ProviderKey string // provider-native video id (dedup key)
|
||
|
|
Kind ExtraKind
|
||
|
|
Site string // hosting site, e.g. "youtube"
|
||
|
|
SiteKey string // site-native video key (YouTube video id)
|
||
|
|
Name string
|
||
|
|
Language string // ISO 639-1, empty when unknown
|
||
|
|
IsOfficial bool
|
||
|
|
SizeHint int // vertical resolution hint (e.g. 1080), 0 when unknown
|
||
|
|
PublishedAt *time.Time
|
||
|
|
SortOrder int
|
||
|
|
}
|
||
|
|
|
||
|
|
// MediaExtra is a row in media_extras: a scanner-discovered local extra
|
||
|
|
// (featurette, deleted scene, local trailer file, ...) belonging to a parent
|
||
|
|
// movie or series. Its ContentID is minted with contentid.ForLocal on the
|
||
|
|
// backing file path, making it a playable watch target through
|
||
|
|
// GetWatchDetail's fallback chain; access control is the parent's.
|
||
|
|
type MediaExtra struct {
|
||
|
|
ContentID string
|
||
|
|
ParentID string // media_items.content_id of the owning movie/series
|
||
|
|
Kind ExtraKind
|
||
|
|
Title string
|
||
|
|
SortOrder int
|
||
|
|
}
|