using System; using System.Text.Json.Serialization; using Jellyfin.Plugin.JRay.Configuration; namespace Jellyfin.Plugin.JRay.Models; /// /// Where an item's truth data came from. /// public enum TruthSource { /// A .jray.json file beside the media, written locally. Sidecar = 0, /// Pushed over HTTP by a worker that cannot write beside the media. Pushed = 1, /// Fetched from a manifest server and converted to a truth file. Fetched = 2, } /// /// How an item's truth data was obtained, recorded alongside it. /// /// /// The three sources are not interchangeable. A locally computed sidecar and a /// loose-tier manifest from a third-party server make claims of very /// different strength about the same item, and once stored they are otherwise /// indistinguishable — the truth file itself records nothing about how it /// arrived. /// /// /// This is stored beside the truth file rather than inside it. Injecting /// fields would mean the bytes served back are not the bytes the producer wrote, /// which is the property JR-004 turns on. /// /// // TRACES: JR-010, JR-036 | PR-001 public class TruthProvenance { /// /// Gets or sets which of the three routes delivered this truth data. /// [JsonPropertyName("source")] public TruthSource Source { get; set; } /// /// Gets or sets the server a fetched manifest came from. Empty for the /// local sources, whose origin is this instance. /// [JsonPropertyName("server_url")] public string ServerUrl { get; set; } = string.Empty; /// /// Gets or sets the cut-match tier a fetched manifest reached. /// /// /// Null for local sources: a sidecar or a push is about *this* file, so /// there is no cut to match. The tier is what makes a fetched claim /// interpretable — loose means "probably the same cut", which the UI /// must surface rather than apply silently (JR-036). /// [JsonPropertyName("match_tier")] public MatchTier? MatchTier { get; set; } /// /// Gets or sets the offset, in seconds, applied to every window before /// storage so the stored timings are in this file's own timebase (JR-030). /// /// /// Recorded because it is otherwise unrecoverable: once applied, the stored /// windows look native, and nothing would say they had been shifted. /// [JsonPropertyName("offset_sec")] public double OffsetSec { get; set; } /// /// Gets or sets a human-readable caveat to surface with the overlay, or /// null when the claim needs none. /// [JsonPropertyName("caveat")] public string? Caveat { get; set; } /// /// Gets or sets when this truth data was recorded, UTC. /// [JsonPropertyName("recorded_at")] public DateTime RecordedAt { get; set; } /// /// Creates provenance for truth data produced on this instance. /// /// Either or . /// When it was recorded, UTC. /// The provenance record. public static TruthProvenance Local(TruthSource source, DateTime recordedAt) => new() { Source = source, RecordedAt = recordedAt }; }