using Jellyfin.Plugin.Vanguard.Services; using MediaBrowser.Controller.Entities; using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Providers; using MediaBrowser.Model.Entities; using MediaBrowser.Model.Providers; namespace Jellyfin.Plugin.Vanguard.Providers; /// A show is a streamer/submitter folder: display name and overview from Discord. public sealed class VanguardSeriesProvider : IRemoteMetadataProvider, IHasOrder { private readonly IdentityResolver _identity; private readonly IHttpClientFactory _http; public VanguardSeriesProvider(IdentityResolver identity, IHttpClientFactory http) { _identity = identity; _http = http; } public string Name => "Vanguard Metadata"; public int Order => 0; public async Task> GetMetadata(SeriesInfo info, CancellationToken ct) { var result = new MetadataResult(); var folder = string.IsNullOrEmpty(info.Path) ? info.Name : Path.GetFileName(info.Path.TrimEnd(Path.DirectorySeparatorChar)); if (string.IsNullOrEmpty(folder)) return result; var m = await _identity.ResolveFolderAsync(folder, ct).ConfigureAwait(false); result.Item = new Series { Name = m?.DisplayName ?? folder, Overview = m is null ? $"Recordings from {folder}." : $"Recordings from {m.DisplayName} (@{m.Username} on Discord).", Status = SeriesStatus.Continuing, }; result.HasMetadata = true; return result; } public Task> GetSearchResults(SeriesInfo searchInfo, CancellationToken ct) => Task.FromResult>([]); public Task GetImageResponse(string url, CancellationToken ct) => _http.CreateClient(MediaBrowser.Common.Net.NamedClient.Default).GetAsync(url, ct); } /// Series poster = the Discord avatar (guild-specific if set). public sealed class VanguardSeriesImageProvider : IRemoteImageProvider, IHasOrder { private readonly IdentityResolver _identity; private readonly IHttpClientFactory _http; public VanguardSeriesImageProvider(IdentityResolver identity, IHttpClientFactory http) { _identity = identity; _http = http; } public string Name => "Vanguard Metadata"; public int Order => 0; public bool Supports(BaseItem item) => item is Series; public IEnumerable GetSupportedImages(BaseItem item) => [ImageType.Primary, ImageType.Thumb]; public async Task> GetImages(BaseItem item, CancellationToken ct) { var folder = Path.GetFileName(item.Path?.TrimEnd(Path.DirectorySeparatorChar) ?? string.Empty); if (string.IsNullOrEmpty(folder)) return []; var m = await _identity.ResolveFolderAsync(folder, ct).ConfigureAwait(false); if (m?.AvatarUrl is null) return []; return [ new RemoteImageInfo { ProviderName = Name, Type = ImageType.Primary, Url = m.AvatarUrl, Width = 512, Height = 512 }, new RemoteImageInfo { ProviderName = Name, Type = ImageType.Thumb, Url = m.AvatarUrl, Width = 512, Height = 512 }, ]; } public Task GetImageResponse(string url, CancellationToken ct) => _http.CreateClient(MediaBrowser.Common.Net.NamedClient.Default).GetAsync(url, ct); }