Use TV guide for livestreams
🏗️ Build Plugin / build (push) Successful in 2m53s
🧪 Test Plugin / test (push) Successful in 1m21s

This commit is contained in:
2025-12-07 17:41:48 +01:00
parent 198fc4c58d
commit 0548fe7dec
17 changed files with 650 additions and 299 deletions
@@ -0,0 +1,41 @@
using Jellyfin.Plugin.SRFPlay.Configuration;
using MediaBrowser.Controller.Entities;
namespace Jellyfin.Plugin.SRFPlay.Utilities;
/// <summary>
/// Extension methods for common plugin operations.
/// </summary>
public static class Extensions
{
/// <summary>
/// Gets the SRF URN from the item's provider IDs.
/// </summary>
/// <param name="item">The base item.</param>
/// <returns>The SRF URN, or null if not found or empty.</returns>
public static string? GetSrfUrn(this BaseItem item)
{
return item.ProviderIds.TryGetValue("SRF", out var urn) && !string.IsNullOrEmpty(urn)
? urn
: null;
}
/// <summary>
/// Converts the BusinessUnit enum to its lowercase string representation.
/// </summary>
/// <param name="businessUnit">The business unit.</param>
/// <returns>The lowercase string representation.</returns>
public static string ToLowerString(this BusinessUnit businessUnit)
{
return businessUnit.ToString().ToLowerInvariant();
}
/// <summary>
/// Gets the plugin configuration safely, returning null if not available.
/// </summary>
/// <returns>The plugin configuration, or null if not available.</returns>
public static PluginConfiguration? GetPluginConfig()
{
return Plugin.Instance?.Configuration;
}
}
@@ -0,0 +1,74 @@
using System;
namespace Jellyfin.Plugin.SRFPlay.Utilities;
/// <summary>
/// Helper class for determining MIME content types.
/// </summary>
public static class MimeTypeHelper
{
/// <summary>
/// Gets the MIME content type for an image based on URL or file extension.
/// </summary>
/// <param name="url">The image URL.</param>
/// <returns>The MIME content type, defaulting to "image/jpeg" for SRF images.</returns>
public static string GetImageContentType(string? url)
{
if (string.IsNullOrEmpty(url))
{
return "image/jpeg";
}
var uri = new Uri(url);
var path = uri.AbsolutePath.ToLowerInvariant();
if (path.EndsWith(".png", StringComparison.Ordinal))
{
return "image/png";
}
if (path.EndsWith(".gif", StringComparison.Ordinal))
{
return "image/gif";
}
if (path.EndsWith(".webp", StringComparison.Ordinal))
{
return "image/webp";
}
if (path.EndsWith(".jpg", StringComparison.Ordinal) || path.EndsWith(".jpeg", StringComparison.Ordinal))
{
return "image/jpeg";
}
// Default to JPEG for SRF images (most common)
return "image/jpeg";
}
/// <summary>
/// Gets the MIME content type for a media segment based on file extension.
/// </summary>
/// <param name="path">The segment path or filename.</param>
/// <returns>The MIME content type.</returns>
public static string GetSegmentContentType(string path)
{
if (path.EndsWith(".ts", StringComparison.OrdinalIgnoreCase))
{
return "video/MP2T";
}
if (path.EndsWith(".mp4", StringComparison.OrdinalIgnoreCase) ||
path.EndsWith(".m4s", StringComparison.OrdinalIgnoreCase))
{
return "video/mp4";
}
if (path.EndsWith(".aac", StringComparison.OrdinalIgnoreCase))
{
return "audio/aac";
}
return "application/octet-stream";
}
}
@@ -0,0 +1,27 @@
using System;
using System.Security.Cryptography;
using System.Text;
namespace Jellyfin.Plugin.SRFPlay.Utilities;
/// <summary>
/// Helper class for URN-related operations.
/// </summary>
public static class UrnHelper
{
/// <summary>
/// Generates a deterministic GUID from a URN.
/// This ensures the same URN always produces the same GUID.
/// MD5 is used for non-cryptographic purposes only (generating stable IDs).
/// </summary>
/// <param name="urn">The URN to convert.</param>
/// <returns>A deterministic GUID string.</returns>
#pragma warning disable CA5351 // MD5 is used for non-cryptographic purposes (ID generation)
public static string ToGuid(string urn)
{
var hash = MD5.HashData(Encoding.UTF8.GetBytes(urn));
var guid = new Guid(hash);
return guid.ToString();
}
#pragma warning restore CA5351
}