first commit
🏗️ Build Plugin / call (push) Failing after 0s
📝 Create/Update Release Draft & Release Bump PR / call (push) Failing after 0s
🧪 Test Plugin / call (push) Failing after 0s
🔬 Run CodeQL / call (push) Failing after 0s

This commit is contained in:
2025-11-12 22:05:36 +01:00
parent d544b71939
commit ac6a3842dd
46 changed files with 5891 additions and 499 deletions
@@ -0,0 +1,96 @@
using System;
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Text.Json.Serialization;
namespace Jellyfin.Plugin.SRFPlay.Api.Models;
/// <summary>
/// Represents a chapter (video/episode) in the SRF API response.
/// </summary>
public class Chapter
{
/// <summary>
/// Gets or sets the unique identifier.
/// </summary>
[JsonPropertyName("id")]
public string Id { get; set; } = string.Empty;
/// <summary>
/// Gets or sets the URN (Uniform Resource Name).
/// </summary>
[JsonPropertyName("urn")]
public string Urn { get; set; } = string.Empty;
/// <summary>
/// Gets or sets the title.
/// </summary>
[JsonPropertyName("title")]
public string Title { get; set; } = string.Empty;
/// <summary>
/// Gets or sets the lead/description.
/// </summary>
[JsonPropertyName("lead")]
public string? Lead { get; set; }
/// <summary>
/// Gets or sets the description.
/// </summary>
[JsonPropertyName("description")]
public string? Description { get; set; }
/// <summary>
/// Gets or sets the image URL.
/// </summary>
[JsonPropertyName("imageUrl")]
public string? ImageUrl { get; set; }
/// <summary>
/// Gets or sets the duration in milliseconds.
/// </summary>
[JsonPropertyName("duration")]
public long Duration { get; set; }
/// <summary>
/// Gets or sets the publication date.
/// </summary>
[JsonPropertyName("date")]
public DateTime? Date { get; set; }
/// <summary>
/// Gets or sets the valid from date.
/// </summary>
[JsonPropertyName("validFrom")]
public DateTime? ValidFrom { get; set; }
/// <summary>
/// Gets or sets the valid to date (expiration).
/// </summary>
[JsonPropertyName("validTo")]
public DateTime? ValidTo { get; set; }
/// <summary>
/// Gets or sets the list of available resources (streams).
/// </summary>
[JsonPropertyName("resourceList")]
public IReadOnlyList<Resource> ResourceList { get; set; } = new List<Resource>();
/// <summary>
/// Gets or sets the episode number.
/// </summary>
[JsonPropertyName("episodeNumber")]
public int? EpisodeNumber { get; set; }
/// <summary>
/// Gets or sets the season number.
/// </summary>
[JsonPropertyName("seasonNumber")]
public int? SeasonNumber { get; set; }
/// <summary>
/// Gets or sets the media type.
/// </summary>
[JsonPropertyName("mediaType")]
public string? MediaType { get; set; }
}
@@ -0,0 +1,64 @@
using System;
using System.Text.Json.Serialization;
namespace Jellyfin.Plugin.SRFPlay.Api.Models;
/// <summary>
/// Represents an episode in the SRF API response.
/// </summary>
public class Episode
{
/// <summary>
/// Gets or sets the unique identifier.
/// </summary>
[JsonPropertyName("id")]
public string Id { get; set; } = string.Empty;
/// <summary>
/// Gets or sets the URN.
/// </summary>
[JsonPropertyName("urn")]
public string? Urn { get; set; }
/// <summary>
/// Gets or sets the title.
/// </summary>
[JsonPropertyName("title")]
public string Title { get; set; } = string.Empty;
/// <summary>
/// Gets or sets the lead/description.
/// </summary>
[JsonPropertyName("lead")]
public string? Lead { get; set; }
/// <summary>
/// Gets or sets the description.
/// </summary>
[JsonPropertyName("description")]
public string? Description { get; set; }
/// <summary>
/// Gets or sets the image URL.
/// </summary>
[JsonPropertyName("imageUrl")]
public string? ImageUrl { get; set; }
/// <summary>
/// Gets or sets the episode number.
/// </summary>
[JsonPropertyName("episodeNumber")]
public int? EpisodeNumber { get; set; }
/// <summary>
/// Gets or sets the season number.
/// </summary>
[JsonPropertyName("seasonNumber")]
public int? SeasonNumber { get; set; }
/// <summary>
/// Gets or sets the publication date.
/// </summary>
[JsonPropertyName("publishedDate")]
public DateTime? PublishedDate { get; set; }
}
@@ -0,0 +1,29 @@
using System.Collections.Generic;
using System.Collections.ObjectModel;
using System.Text.Json.Serialization;
namespace Jellyfin.Plugin.SRFPlay.Api.Models;
/// <summary>
/// Represents the root media composition response from SRF API.
/// </summary>
public class MediaComposition
{
/// <summary>
/// Gets or sets the list of chapters (videos/episodes).
/// </summary>
[JsonPropertyName("chapterList")]
public IReadOnlyList<Chapter> ChapterList { get; set; } = new List<Chapter>();
/// <summary>
/// Gets or sets the episode information.
/// </summary>
[JsonPropertyName("episode")]
public Episode? Episode { get; set; }
/// <summary>
/// Gets or sets the show information.
/// </summary>
[JsonPropertyName("show")]
public Show? Show { get; set; }
}
@@ -0,0 +1,26 @@
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Text.Json.Serialization;
namespace Jellyfin.Plugin.SRFPlay.Api.Models;
/// <summary>
/// Represents the data container in a Play v3 response.
/// </summary>
/// <typeparam name="T">The type of data items.</typeparam>
public class PlayV3DataContainer<T>
{
/// <summary>
/// Gets or sets the list of data items.
/// </summary>
[JsonPropertyName("data")]
[SuppressMessage("Usage", "CA2227:Collection properties should be read only", Justification = "Required for JSON deserialization")]
[SuppressMessage("Design", "CA1002:Do not expose generic lists", Justification = "DTO for JSON deserialization")]
public List<T>? Data { get; set; }
/// <summary>
/// Gets or sets the next page cursor.
/// </summary>
[JsonPropertyName("next")]
public string? Next { get; set; }
}
@@ -0,0 +1,20 @@
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Text.Json.Serialization;
namespace Jellyfin.Plugin.SRFPlay.Api.Models;
/// <summary>
/// Represents a direct data response (for shows list).
/// </summary>
/// <typeparam name="T">The type of data items.</typeparam>
public class PlayV3DirectResponse<T>
{
/// <summary>
/// Gets or sets the list of data items.
/// </summary>
[JsonPropertyName("data")]
[SuppressMessage("Usage", "CA2227:Collection properties should be read only", Justification = "Required for JSON deserialization")]
[SuppressMessage("Design", "CA1002:Do not expose generic lists", Justification = "DTO for JSON deserialization")]
public List<T>? Data { get; set; }
}
@@ -0,0 +1,16 @@
using System.Text.Json.Serialization;
namespace Jellyfin.Plugin.SRFPlay.Api.Models;
/// <summary>
/// Represents a paginated response from the Play v3 API.
/// </summary>
/// <typeparam name="T">The type of data items.</typeparam>
public class PlayV3Response<T>
{
/// <summary>
/// Gets or sets the data container.
/// </summary>
[JsonPropertyName("data")]
public PlayV3DataContainer<T>? Data { get; set; }
}
@@ -0,0 +1,79 @@
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Text.Json.Serialization;
namespace Jellyfin.Plugin.SRFPlay.Api.Models;
/// <summary>
/// Represents a show from the Play v3 API.
/// </summary>
public class PlayV3Show
{
/// <summary>
/// Gets or sets the show ID.
/// </summary>
[JsonPropertyName("id")]
public string? Id { get; set; }
/// <summary>
/// Gets or sets the show URN.
/// </summary>
[JsonPropertyName("urn")]
public string? Urn { get; set; }
/// <summary>
/// Gets or sets the show title.
/// </summary>
[JsonPropertyName("title")]
public string? Title { get; set; }
/// <summary>
/// Gets or sets the image URL.
/// </summary>
[JsonPropertyName("imageUrl")]
public string? ImageUrl { get; set; }
/// <summary>
/// Gets or sets the transmission type (TV or Radio).
/// </summary>
[JsonPropertyName("transmission")]
public string? Transmission { get; set; }
/// <summary>
/// Gets or sets the vendor/business unit.
/// </summary>
[JsonPropertyName("vendor")]
public string? Vendor { get; set; }
/// <summary>
/// Gets or sets the lead description.
/// </summary>
[JsonPropertyName("lead")]
public string? Lead { get; set; }
/// <summary>
/// Gets or sets the full description.
/// </summary>
[JsonPropertyName("description")]
public string? Description { get; set; }
/// <summary>
/// Gets or sets the poster image URL.
/// </summary>
[JsonPropertyName("posterImageUrl")]
public string? PosterImageUrl { get; set; }
/// <summary>
/// Gets or sets the number of episodes.
/// </summary>
[JsonPropertyName("numberOfEpisodes")]
public int NumberOfEpisodes { get; set; }
/// <summary>
/// Gets or sets the list of topic IDs.
/// </summary>
[JsonPropertyName("topicList")]
[SuppressMessage("Usage", "CA2227:Collection properties should be read only", Justification = "Required for JSON deserialization")]
[SuppressMessage("Design", "CA1002:Do not expose generic lists", Justification = "DTO for JSON deserialization")]
public List<string>? TopicList { get; set; }
}
@@ -0,0 +1,33 @@
using System.Text.Json.Serialization;
namespace Jellyfin.Plugin.SRFPlay.Api.Models;
/// <summary>
/// Represents a topic/category from the Play v3 API.
/// </summary>
public class PlayV3Topic
{
/// <summary>
/// Gets or sets the topic ID (UUID).
/// </summary>
[JsonPropertyName("id")]
public string? Id { get; set; }
/// <summary>
/// Gets or sets the topic title.
/// </summary>
[JsonPropertyName("title")]
public string? Title { get; set; }
/// <summary>
/// Gets or sets the topic description/lead.
/// </summary>
[JsonPropertyName("lead")]
public string? Lead { get; set; }
/// <summary>
/// Gets or sets the transmission type (TV or Radio).
/// </summary>
[JsonPropertyName("transmission")]
public string? Transmission { get; set; }
}
@@ -0,0 +1,116 @@
using System;
using System.Collections.Generic;
using System.Diagnostics.CodeAnalysis;
using System.Text.Json.Serialization;
namespace Jellyfin.Plugin.SRFPlay.Api.Models;
/// <summary>
/// Represents a video/episode from the Play v3 API.
/// </summary>
public class PlayV3Video
{
/// <summary>
/// Gets or sets the video ID.
/// </summary>
[JsonPropertyName("id")]
public string? Id { get; set; }
/// <summary>
/// Gets or sets the video URN.
/// </summary>
[JsonPropertyName("urn")]
public string? Urn { get; set; }
/// <summary>
/// Gets or sets the video title.
/// </summary>
[JsonPropertyName("title")]
public string? Title { get; set; }
/// <summary>
/// Gets or sets the episode ID.
/// </summary>
[JsonPropertyName("episodeId")]
public string? EpisodeId { get; set; }
/// <summary>
/// Gets or sets the lead description.
/// </summary>
[JsonPropertyName("lead")]
public string? Lead { get; set; }
/// <summary>
/// Gets or sets the full description.
/// </summary>
[JsonPropertyName("description")]
public string? Description { get; set; }
/// <summary>
/// Gets or sets the image URL.
/// </summary>
[JsonPropertyName("imageUrl")]
public string? ImageUrl { get; set; }
/// <summary>
/// Gets or sets the duration in milliseconds.
/// </summary>
[JsonPropertyName("duration")]
public long Duration { get; set; }
/// <summary>
/// Gets or sets the publication date.
/// </summary>
[JsonPropertyName("date")]
public DateTime Date { get; set; }
/// <summary>
/// Gets or sets the valid from date.
/// </summary>
[JsonPropertyName("validFrom")]
public DateTime? ValidFrom { get; set; }
/// <summary>
/// Gets or sets the valid to date (expiration).
/// </summary>
[JsonPropertyName("validTo")]
public DateTime? ValidTo { get; set; }
/// <summary>
/// Gets or sets the media type (VIDEO or AUDIO).
/// </summary>
[JsonPropertyName("mediaType")]
public string? MediaType { get; set; }
/// <summary>
/// Gets or sets a value indicating whether subtitles are available.
/// </summary>
[JsonPropertyName("subtitlesAvailable")]
public bool SubtitlesAvailable { get; set; }
/// <summary>
/// Gets or sets a value indicating whether the content is playable abroad.
/// </summary>
[JsonPropertyName("playableAbroad")]
public bool PlayableAbroad { get; set; }
/// <summary>
/// Gets or sets the list of possible block reasons.
/// </summary>
[JsonPropertyName("possibleBlockReasons")]
[SuppressMessage("Usage", "CA2227:Collection properties should be read only", Justification = "Required for JSON deserialization")]
[SuppressMessage("Design", "CA1002:Do not expose generic lists", Justification = "DTO for JSON deserialization")]
public List<string>? PossibleBlockReasons { get; set; }
/// <summary>
/// Gets or sets the content type (EPISODE, CLIP, etc.).
/// </summary>
[JsonPropertyName("type")]
public string? Type { get; set; }
/// <summary>
/// Gets or sets the associated show information.
/// </summary>
[JsonPropertyName("show")]
public PlayV3Show? Show { get; set; }
}
@@ -0,0 +1,51 @@
using System.Text.Json.Serialization;
namespace Jellyfin.Plugin.SRFPlay.Api.Models;
/// <summary>
/// Represents a streaming resource (URL) in the SRF API response.
/// </summary>
public class Resource
{
/// <summary>
/// Gets or sets the stream URL.
/// </summary>
[JsonPropertyName("url")]
public string Url { get; set; } = string.Empty;
/// <summary>
/// Gets or sets the streaming protocol (e.g., HLS, DASH).
/// </summary>
[JsonPropertyName("protocol")]
public string? Protocol { get; set; }
/// <summary>
/// Gets or sets the quality level (e.g., HD, SD).
/// </summary>
[JsonPropertyName("quality")]
public string? Quality { get; set; }
/// <summary>
/// Gets or sets the streaming method.
/// </summary>
[JsonPropertyName("streaming")]
public string? Streaming { get; set; }
/// <summary>
/// Gets or sets the MIME type.
/// </summary>
[JsonPropertyName("mimeType")]
public string? MimeType { get; set; }
/// <summary>
/// Gets or sets the encoding.
/// </summary>
[JsonPropertyName("encoding")]
public string? Encoding { get; set; }
/// <summary>
/// Gets or sets whether DRM is required.
/// </summary>
[JsonPropertyName("drmList")]
public object? DrmList { get; set; }
}
@@ -0,0 +1,63 @@
using System.Text.Json.Serialization;
namespace Jellyfin.Plugin.SRFPlay.Api.Models;
/// <summary>
/// Represents a show/program in the SRF API response.
/// </summary>
public class Show
{
/// <summary>
/// Gets or sets the unique identifier.
/// </summary>
[JsonPropertyName("id")]
public string Id { get; set; } = string.Empty;
/// <summary>
/// Gets or sets the URN.
/// </summary>
[JsonPropertyName("urn")]
public string? Urn { get; set; }
/// <summary>
/// Gets or sets the title.
/// </summary>
[JsonPropertyName("title")]
public string Title { get; set; } = string.Empty;
/// <summary>
/// Gets or sets the lead/description.
/// </summary>
[JsonPropertyName("lead")]
public string? Lead { get; set; }
/// <summary>
/// Gets or sets the description.
/// </summary>
[JsonPropertyName("description")]
public string? Description { get; set; }
/// <summary>
/// Gets or sets the image URL.
/// </summary>
[JsonPropertyName("imageUrl")]
public string? ImageUrl { get; set; }
/// <summary>
/// Gets or sets the banner image URL.
/// </summary>
[JsonPropertyName("bannerImageUrl")]
public string? BannerImageUrl { get; set; }
/// <summary>
/// Gets or sets the vendor (business unit).
/// </summary>
[JsonPropertyName("vendor")]
public string? Vendor { get; set; }
/// <summary>
/// Gets or sets the transmission type.
/// </summary>
[JsonPropertyName("transmission")]
public string? Transmission { get; set; }
}