UserData bound to ExternalId, Resume play seems still not working. Rename music to concerts.
All checks were successful
continuous-integration/drone/push Build is passing
All checks were successful
continuous-integration/drone/push Build is passing
This commit is contained in:
1
.vscode/settings.json
vendored
Normal file
1
.vscode/settings.json
vendored
Normal file
@@ -0,0 +1 @@
|
||||
{}
|
||||
@@ -11,13 +11,13 @@ public sealed class CinemaConcertFolder : CinemaRootFolder
|
||||
{
|
||||
}
|
||||
|
||||
public override CollectionType? CollectionType => Data.Enums.CollectionType.music;
|
||||
public override CollectionType? CollectionType => Data.Enums.CollectionType.musicvideos;
|
||||
|
||||
public override BaseItemKind ClientType => BaseItemKind.MusicAlbum;
|
||||
public override BaseItemKind ClientType => BaseItemKind.MusicVideo;
|
||||
|
||||
public override ItemType ItemType => ItemType.Concert;
|
||||
|
||||
internal override string ImageName => "music.png";
|
||||
internal override string ImageName => "concert.png";
|
||||
|
||||
protected override IEnumerable<BaseItem> GetFilterItems()
|
||||
{
|
||||
@@ -28,6 +28,6 @@ public sealed class CinemaConcertFolder : CinemaRootFolder
|
||||
|
||||
public override bool TryCreateMediaItem(MediaSource? media, string csId, BaseItem parentFolder, [NotNullWhen(true)] out BaseItem? item)
|
||||
{
|
||||
return media.TryCreateMediaItem<CinemaMusicAlbum>(csId, parentFolder, true, out item);
|
||||
return media.TryCreateMediaItem<Folder>(csId, parentFolder, true, out item);
|
||||
}
|
||||
}
|
||||
@@ -12,6 +12,11 @@ public class CinemaEpisode : Episode
|
||||
{
|
||||
public sealed override string GetClientTypeName() => BaseItemKind.Episode.ToString();
|
||||
|
||||
public override List<string> GetUserDataKeys()
|
||||
{
|
||||
return new List<string>() { ExternalId };
|
||||
}
|
||||
|
||||
protected override IEnumerable<(BaseItem Item, MediaSourceType MediaSourceType)> GetAllItemsForMediaSources()
|
||||
{
|
||||
var result = this.VideoGetAllItemsForMediaSources();
|
||||
|
||||
@@ -172,9 +172,6 @@ public abstract class CinemaFilterFolder : Folder
|
||||
{
|
||||
Folder parentItem = LibraryManager.GetUserRootFolder();
|
||||
folder.ParentId = parentItem.Id;
|
||||
//folder.IsRoot = true;
|
||||
//if (!CinemaHost.LibraryManager.RootFolder.VirtualChildren.Contains(folder))
|
||||
// CinemaHost.LibraryManager.RootFolder.AddVirtualChild(folder);
|
||||
if (!parentItem.Children.Contains(folder))
|
||||
parentItem.AddChild(folder);
|
||||
}
|
||||
|
||||
@@ -86,8 +86,8 @@ sealed class CinemaHost : IHostedService
|
||||
.Hide = config.HideSeriesFolder;
|
||||
CinemaFilterFolder.CreateRootFilterFolder<CinemaAnimeFolder>(string.IsNullOrWhiteSpace(config.AnimeFolderName) ? "Anime" : config.AnimeFolderName)
|
||||
.Hide = config.HideAnimeFolder;
|
||||
CinemaFilterFolder.CreateRootFilterFolder<CinemaConcertFolder>(string.IsNullOrWhiteSpace(config.MusicFolderName) ? "Music" : config.MusicFolderName)
|
||||
.Hide = config.HideMusicFolder;
|
||||
CinemaFilterFolder.CreateRootFilterFolder<CinemaConcertFolder>(string.IsNullOrWhiteSpace(config.ConcertFolderName) ? "Concerts" : config.ConcertFolderName)
|
||||
.Hide = config.HideConcertFolder;
|
||||
}
|
||||
|
||||
private void EnsureWebshareSession(CinemaPluginConfiguration config)
|
||||
|
||||
@@ -1,3 +1,4 @@
|
||||
using CinemaLib.API;
|
||||
using Jellyfin.Data.Entities;
|
||||
using Jellyfin.Data.Enums;
|
||||
using MediaBrowser.Controller.Dto;
|
||||
@@ -5,6 +6,7 @@ using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Entities.Audio;
|
||||
using MediaBrowser.Controller.Entities.TV;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Controller.Persistence;
|
||||
using MediaBrowser.Controller.Providers;
|
||||
using MediaBrowser.Controller.Resolvers;
|
||||
using MediaBrowser.Controller.Sorting;
|
||||
@@ -19,8 +21,9 @@ namespace Jellyfin.Plugin.Cinema;
|
||||
sealed class CinemaLibraryManager : ILibraryManager
|
||||
{
|
||||
private readonly ILibraryManager _inner;
|
||||
private readonly IUserDataRepository _userData;
|
||||
|
||||
public CinemaLibraryManager(CinemaInnerLibraryManager innerLibraryManager, IServiceProvider svc)
|
||||
public CinemaLibraryManager(CinemaInnerLibraryManager innerLibraryManager, IUserDataRepository userData, IServiceProvider svc)
|
||||
{
|
||||
if (innerLibraryManager == null || svc == null)
|
||||
throw new ArgumentNullException();
|
||||
@@ -29,7 +32,7 @@ sealed class CinemaLibraryManager : ILibraryManager
|
||||
if (inner == null)
|
||||
throw new InvalidOperationException("Original LibraryManager service not found.");
|
||||
this._inner = inner;
|
||||
|
||||
this._userData = userData;
|
||||
}
|
||||
|
||||
#region ILibraryManager Members
|
||||
@@ -265,20 +268,46 @@ sealed class CinemaLibraryManager : ILibraryManager
|
||||
public QueryResult<BaseItem> GetItemsResult(InternalItemsQuery query)
|
||||
{
|
||||
QueryResult<BaseItem> result = _inner.GetItemsResult(query);
|
||||
if (query.ParentId != Guid.Empty || query.OrderBy.FirstOrDefault().OrderBy == ItemSortBy.DatePlayed)
|
||||
if (query.ParentId != Guid.Empty)
|
||||
// Not a search at the root so do not involve our root folders
|
||||
return result;
|
||||
|
||||
List<BaseItem> resultL = new List<BaseItem>(result.Items);
|
||||
|
||||
List<BaseItem> a = new List<BaseItem>(result.Items);
|
||||
if (query.OrderBy.FirstOrDefault().OrderBy == ItemSortBy.DatePlayed && query.User != null)
|
||||
{
|
||||
// Get Resume play items
|
||||
// PERF: This may quickly become very slow
|
||||
var resumePlay = _userData.GetAllUserData(query.User.InternalId)
|
||||
.OrderByDescending(x => x.Played)
|
||||
.Skip(query.StartIndex ?? 0)
|
||||
.Take(query.Limit ?? 20);
|
||||
foreach (var i in resumePlay)
|
||||
{
|
||||
// Note: All Cinema items override GetUserDataKeys and return ExternalId
|
||||
string? csId;
|
||||
if (!CinemaQueryExtensions.TryGetCinemaIdFromExternalId(i.Key, out csId))
|
||||
continue;
|
||||
|
||||
MediaSource? ms = Metadata.DetailAsync(csId, default).GetAwaiter().GetResult();
|
||||
if (CinemaQueryExtensions.TryCreateMediaItem<Folder>(ms, csId, null, false, out BaseItem? a))
|
||||
resultL.Add(a);
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
// Add our root folders to the search
|
||||
foreach (BaseItem i in GetUserRootFolder().Children)
|
||||
if (i is CinemaRootFolder root)
|
||||
// Prevent duplicates as content in Anime is also elsewhere
|
||||
if (i is CinemaRootFolder root && i is not CinemaAnimeFolder)
|
||||
{
|
||||
var b = root.GetItemList(query);
|
||||
if (b != null)
|
||||
a.AddRange(b);
|
||||
resultL.AddRange(b);
|
||||
}
|
||||
}
|
||||
|
||||
return new QueryResult<BaseItem>() { Items = a };
|
||||
return new QueryResult<BaseItem>() { Items = resultL };
|
||||
}
|
||||
|
||||
public LibraryOptions GetLibraryOptions(BaseItem item)
|
||||
|
||||
@@ -12,6 +12,11 @@ public class CinemaMovie : Movie
|
||||
{
|
||||
public sealed override string GetClientTypeName() => BaseItemKind.Movie.ToString();
|
||||
|
||||
public override List<string> GetUserDataKeys()
|
||||
{
|
||||
return new List<string>() { ExternalId };
|
||||
}
|
||||
|
||||
protected override IEnumerable<(BaseItem Item, MediaSourceType MediaSourceType)> GetAllItemsForMediaSources()
|
||||
{
|
||||
var result = this.VideoGetAllItemsForMediaSources();
|
||||
|
||||
@@ -1,68 +0,0 @@
|
||||
using CinemaLib.API;
|
||||
using Jellyfin.Data.Entities;
|
||||
using Jellyfin.Data.Enums;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Controller.Entities.Audio;
|
||||
using MediaBrowser.Model.Querying;
|
||||
|
||||
namespace Jellyfin.Plugin.Cinema;
|
||||
|
||||
/// <summary>
|
||||
/// Music album folder item from Cinema.
|
||||
/// </summary>
|
||||
public sealed class CinemaMusicAlbum : MusicAlbum
|
||||
{
|
||||
public sealed override string GetClientTypeName() => BaseItemKind.Series.ToString();
|
||||
|
||||
public override int GetChildCount(User user)
|
||||
{
|
||||
return base.GetChildCount(user);
|
||||
}
|
||||
|
||||
public override int GetRecursiveChildCount(User user)
|
||||
{
|
||||
return base.GetRecursiveChildCount(user);
|
||||
}
|
||||
|
||||
public override List<BaseItem> GetChildren(User user, bool includeLinkedChildren, InternalItemsQuery query)
|
||||
{
|
||||
return (List<BaseItem>)GetItemsInternal(query).Items;
|
||||
}
|
||||
|
||||
protected override QueryResult<BaseItem> GetItemsInternal(InternalItemsQuery query)
|
||||
{
|
||||
int offset = query.StartIndex ?? 0;
|
||||
int limit = query.Limit ?? 0;
|
||||
|
||||
List<BaseItem> items = new List<BaseItem>();
|
||||
QueryResult<BaseItem> result = new QueryResult<BaseItem>() { Items = items, StartIndex = offset };
|
||||
|
||||
FilterSortBy sortBy;
|
||||
ItemOrder sortDir;
|
||||
if (query.OrderBy.Count == 0)
|
||||
{
|
||||
sortBy = FilterSortBy.Episode;
|
||||
sortDir = ItemOrder.Ascending;
|
||||
}
|
||||
else
|
||||
{
|
||||
(ItemSortBy sortByJ, SortOrder sortDirJ) = query.OrderBy.First();
|
||||
sortBy = sortByJ.ToCinema();
|
||||
sortDir = sortDirJ == SortOrder.Ascending ? ItemOrder.Ascending : ItemOrder.Descending;
|
||||
}
|
||||
|
||||
FilterResponse? filterRes = Metadata.ChildrenAsync(query.SearchTerm ?? "", order: sortDir, sort: sortBy, offset: offset, limit: limit).GetAwaiter().GetResult();
|
||||
if (filterRes != null && filterRes.hits != null && filterRes.hits.hits != null)
|
||||
{
|
||||
if (filterRes.hits.total != null)
|
||||
result.TotalRecordCount = (int)filterRes.hits.total.value;
|
||||
foreach (var i in filterRes.hits.hits)
|
||||
{
|
||||
if (i._source.TryCreateMediaItem<Folder>(i._id, this, false, out BaseItem? a))
|
||||
items.Add(a);
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
}
|
||||
36
CinemaJellyfin/CinemaMusicVideo.cs
Normal file
36
CinemaJellyfin/CinemaMusicVideo.cs
Normal file
@@ -0,0 +1,36 @@
|
||||
using Jellyfin.Data.Enums;
|
||||
using MediaBrowser.Controller.Entities;
|
||||
using MediaBrowser.Model.Dto;
|
||||
|
||||
namespace Jellyfin.Plugin.Cinema;
|
||||
|
||||
/// <summary>
|
||||
/// Concerts folder item from Cinema.
|
||||
/// </summary>
|
||||
public sealed class CinemaMusicVideo : MusicVideo
|
||||
{
|
||||
public sealed override string GetClientTypeName() => BaseItemKind.MusicVideo.ToString();
|
||||
|
||||
public override List<string> GetUserDataKeys()
|
||||
{
|
||||
return new List<string>() { ExternalId };
|
||||
}
|
||||
|
||||
protected override IEnumerable<(BaseItem Item, MediaSourceType MediaSourceType)> GetAllItemsForMediaSources()
|
||||
{
|
||||
var result = this.VideoGetAllItemsForMediaSources();
|
||||
if (result == null)
|
||||
return base.GetAllItemsForMediaSources();
|
||||
else
|
||||
return result;
|
||||
}
|
||||
|
||||
public override List<MediaSourceInfo> GetMediaSources(bool enablePathSubstitution)
|
||||
{
|
||||
var result = this.VideoGetMediaSources(enablePathSubstitution);
|
||||
if (result == null)
|
||||
return base.GetMediaSources(enablePathSubstitution);
|
||||
else
|
||||
return result;
|
||||
}
|
||||
}
|
||||
@@ -61,7 +61,7 @@ static class CinemaQueryExtensions
|
||||
/// <param name="parentFolder">Jellyfin parent folder.</param>
|
||||
/// <param name="item">On success the created item.</param>
|
||||
/// <returns>True on success, false otherwise.</returns>
|
||||
public static bool TryCreateMediaItem<TContainerType>(this MediaSource? media, string csId, BaseItem parentFolder, bool allowContainer, [NotNullWhen(true)] out BaseItem? item)
|
||||
public static bool TryCreateMediaItem<TContainerType>(this MediaSource? media, string csId, BaseItem? parentFolder, bool allowContainer, [NotNullWhen(true)] out BaseItem? item)
|
||||
where TContainerType : Folder, new()
|
||||
{
|
||||
if (media == null)
|
||||
@@ -70,12 +70,10 @@ static class CinemaQueryExtensions
|
||||
return false;
|
||||
}
|
||||
|
||||
var parentFolderId = parentFolder.Id;
|
||||
|
||||
bool isNew;
|
||||
bool forceUpdate = false;
|
||||
|
||||
bool isAudio = media.is_concert ?? false;
|
||||
bool isConcert = media.is_concert ?? false;
|
||||
if (media.children_count != 0)
|
||||
{
|
||||
// Container
|
||||
@@ -87,10 +85,9 @@ static class CinemaQueryExtensions
|
||||
item = GetMediaItemById<TContainerType>(csId, null, out isNew);
|
||||
|
||||
}
|
||||
else if (isAudio)
|
||||
else if (isConcert)
|
||||
{
|
||||
// TODO determine if this is an AudioBook od Audio
|
||||
item = GetMediaItemById<MediaBrowser.Controller.Entities.Audio.Audio>(csId, null, out isNew);
|
||||
item = GetMediaItemById<CinemaMusicVideo>(csId, null, out isNew);
|
||||
|
||||
}
|
||||
else if (media.info_labels?.mediatype == "episode")
|
||||
@@ -164,7 +161,8 @@ static class CinemaQueryExtensions
|
||||
hasAlbumArtists.AlbumArtists = media.info_labels?.director;
|
||||
}
|
||||
|
||||
item.ParentId = parentFolderId;
|
||||
if (parentFolder != null)
|
||||
item.ParentId = parentFolder.Id;
|
||||
|
||||
/*
|
||||
if (item is IHasSeries hasSeries)
|
||||
|
||||
@@ -15,10 +15,16 @@ public sealed class CinemaSeason : Season, ICinemaChildrenCount
|
||||
{
|
||||
private CinemaSubfolderHelper _helper;
|
||||
|
||||
public CinemaSeason() {
|
||||
public CinemaSeason()
|
||||
{
|
||||
this._helper = new CinemaSubfolderHelper(this, FilterSortBy.Episode);
|
||||
}
|
||||
|
||||
public override List<string> GetUserDataKeys()
|
||||
{
|
||||
return new List<string>() { ExternalId };
|
||||
}
|
||||
|
||||
#region ICinemaChildrenCountMembers
|
||||
|
||||
public int ChildrenCount
|
||||
@@ -27,7 +33,8 @@ public sealed class CinemaSeason : Season, ICinemaChildrenCount
|
||||
set => _helper.ChildrenCount = value;
|
||||
}
|
||||
|
||||
public int TotalChildrenCount {
|
||||
public int TotalChildrenCount
|
||||
{
|
||||
get => _helper.TotalChildrenCount;
|
||||
set => _helper.TotalChildrenCount = value;
|
||||
}
|
||||
|
||||
@@ -15,10 +15,16 @@ public sealed class CinemaTvSeries : Series, ICinemaChildrenCount
|
||||
{
|
||||
private CinemaSubfolderHelper _helper;
|
||||
|
||||
public CinemaTvSeries() {
|
||||
public CinemaTvSeries()
|
||||
{
|
||||
this._helper = new CinemaSubfolderHelper(this, FilterSortBy.Episode);
|
||||
}
|
||||
|
||||
public override List<string> GetUserDataKeys()
|
||||
{
|
||||
return new List<string>() { ExternalId };
|
||||
}
|
||||
|
||||
#region ICinemaChildrenCountMembers
|
||||
|
||||
public int ChildrenCount
|
||||
@@ -27,7 +33,8 @@ public sealed class CinemaTvSeries : Series, ICinemaChildrenCount
|
||||
set => _helper.ChildrenCount = value;
|
||||
}
|
||||
|
||||
public int TotalChildrenCount {
|
||||
public int TotalChildrenCount
|
||||
{
|
||||
get => _helper.TotalChildrenCount;
|
||||
set => _helper.TotalChildrenCount = value;
|
||||
}
|
||||
@@ -68,7 +75,8 @@ public sealed class CinemaTvSeries : Series, ICinemaChildrenCount
|
||||
|
||||
// Set series identifier on all seasons
|
||||
foreach (var i in result.Items)
|
||||
if (i is CinemaSeason season) {
|
||||
if (i is CinemaSeason season)
|
||||
{
|
||||
season.SeriesId = Id;
|
||||
season.SeriesName = Name;
|
||||
}
|
||||
|
||||
@@ -20,8 +20,8 @@ public class CinemaPluginConfiguration : BasePluginConfiguration
|
||||
public string AnimeFolderName { get; set; }
|
||||
public bool HideAnimeFolder { get; set; }
|
||||
|
||||
public string MusicFolderName { get; set; }
|
||||
public bool HideMusicFolder { get; set; }
|
||||
public string ConcertFolderName { get; set; }
|
||||
public bool HideConcertFolder { get; set; }
|
||||
|
||||
public string? WebshareUser { get; set; }
|
||||
public string? WebsharePassword { get; set; }
|
||||
|
||||
@@ -40,12 +40,12 @@
|
||||
<br />
|
||||
|
||||
<div class="inputContainer">
|
||||
<input is="emby-input" type="text" id="musicFolderName" label="Music Folder Name" />
|
||||
<div class="fieldDescription">Custom name for the Cinema Music root folder.</div>
|
||||
<input is="emby-input" type="text" id="concertFolderName" label="Concerts Folder Name" />
|
||||
<div class="fieldDescription">Custom name for the Cinema Concerts root folder.</div>
|
||||
</div>
|
||||
<label class="checkboxContainer">
|
||||
<input is="emby-checkbox" type="checkbox" id="hideMusicFolder" />
|
||||
<span>Hide the Cinema Music root folder.</span>
|
||||
<input is="emby-checkbox" type="checkbox" id="hideConcertFolder" />
|
||||
<span>Hide the Cinema Concerts root folder.</span>
|
||||
</label>
|
||||
<div class="verticalSection verticalSection-extrabottompadding">
|
||||
<h2>Webshare Account</h2>
|
||||
@@ -101,14 +101,14 @@
|
||||
}));
|
||||
document.querySelector('#hideAnimeFolder').checked = config.HideAnimeFolder;
|
||||
|
||||
var musicFolderName = document.querySelector('#musicFolderName');
|
||||
if (config.MusicFolderName)
|
||||
musicFolderName.value = config.MusicFolderName;
|
||||
musicFolderName.dispatchEvent(new Event('change', {
|
||||
var concertFolderName = document.querySelector('#concertFolderName');
|
||||
if (config.ConcertFolderName)
|
||||
concertFolderName.value = config.ConcertFolderName;
|
||||
concertFolderName.dispatchEvent(new Event('change', {
|
||||
bubbles: true,
|
||||
cancelable: false
|
||||
}));
|
||||
document.querySelector('#hideMusicFolder').checked = config.HideMusicFolder;
|
||||
document.querySelector('#hideConcertFolder').checked = config.HideConcertFolder;
|
||||
|
||||
var webshareUser = document.querySelector('#webshareUser');
|
||||
if (config.WebshareUser)
|
||||
@@ -140,8 +140,8 @@
|
||||
config.HideSeriesFolder = document.querySelector('#hideSeriesFolder').checked;
|
||||
config.AnimeFolderName = document.querySelector('#animeFolderName').value;
|
||||
config.HideAnimeFolder = document.querySelector('#hideAnimeFolder').checked;
|
||||
config.MusicFolderName = document.querySelector('#musicFolderName').value;
|
||||
config.HideMusicFolder = document.querySelector('#hideMusicFolder').checked;
|
||||
config.ConcertFolderName = document.querySelector('#concertFolderName').value;
|
||||
config.HideConcertFolder = document.querySelector('#hideConcertFolder').checked;
|
||||
|
||||
config.WebshareUser = document.querySelector('#webshareUser').value;
|
||||
config.WebsharePassword = document.querySelector('#websharePassword').value;
|
||||
|
||||
@@ -40,12 +40,17 @@ public class Metadata
|
||||
bool noSearchTerms = expression.Trim().Length == 0;
|
||||
string filterName;
|
||||
string sortS = ToString(sort);
|
||||
if (sort == FilterSortBy.Title) {
|
||||
if (sort == FilterSortBy.Title)
|
||||
{
|
||||
filterName = "startsWithSimple";
|
||||
sortS = "";
|
||||
} else if (noSearchTerms) {
|
||||
}
|
||||
else if (noSearchTerms)
|
||||
{
|
||||
filterName = "all";
|
||||
} else {
|
||||
}
|
||||
else
|
||||
{
|
||||
filterName = "search";
|
||||
}
|
||||
|
||||
@@ -81,6 +86,24 @@ public class Metadata
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets detail info about in item.
|
||||
/// </summary>
|
||||
/// <param name="id">Item identifier.</param>
|
||||
/// <param name="cancel">Asynchronous cancellation.</param>
|
||||
/// <returns>Media info.</returns>
|
||||
public async static Task<MediaSource?> DetailAsync(string id, CancellationToken cancel)
|
||||
{
|
||||
if (id == null || id.Length == 0)
|
||||
throw new ArgumentNullException();
|
||||
|
||||
Uri uri = new Uri(new Uri(ApiRoot, "media/"), id);
|
||||
MediaSource? result = await Program._http.GetFromJsonAsync<MediaSource>(uri, CreateFilterJsonOptions(), cancel);
|
||||
if (result != null)
|
||||
result = FixDetailResponse(result);
|
||||
return result;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets available streams for the given media.
|
||||
/// </summary>
|
||||
@@ -160,25 +183,35 @@ public class Metadata
|
||||
if (i._source == null)
|
||||
continue;
|
||||
|
||||
if (i._source.cast != null)
|
||||
foreach (Cast j in i._source.cast)
|
||||
FixDetailResponse(i._source);
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
private static MediaSource FixDetailResponse(MediaSource res)
|
||||
{
|
||||
if (res.cast != null)
|
||||
foreach (Cast j in res.cast)
|
||||
j.thumbnail = FixImageUrl(j.thumbnail);
|
||||
|
||||
if (i._source.i18n_info_labels != null)
|
||||
foreach (InfoLabelI18n j in i._source.i18n_info_labels) {
|
||||
if (j.art != null) {
|
||||
if (res.i18n_info_labels != null)
|
||||
foreach (InfoLabelI18n j in res.i18n_info_labels)
|
||||
{
|
||||
if (j.art != null)
|
||||
{
|
||||
j.art.poster = FixImageUrl(j.art.poster);
|
||||
j.art.fanart = FixImageUrl(j.art.fanart);
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return res;
|
||||
}
|
||||
|
||||
private static string FixImageUrl(string url)
|
||||
{
|
||||
if (url != null && !url.StartsWith("http")) {
|
||||
if (url != null && !url.StartsWith("http"))
|
||||
{
|
||||
if (url.StartsWith("//"))
|
||||
url = "https:" + url;
|
||||
else
|
||||
|
||||
Reference in New Issue
Block a user