Merge branch 'master' into sort-nfo-data

This commit is contained in:
Marc Brooks
2025-02-03 19:48:59 -06:00
committed by GitHub
468 changed files with 25086 additions and 9927 deletions

View File

@@ -15,7 +15,7 @@
</ItemGroup>
<PropertyGroup>
<TargetFramework>net8.0</TargetFramework>
<TargetFramework>net9.0</TargetFramework>
<GenerateAssemblyInfo>false</GenerateAssemblyInfo>
<GenerateDocumentationFile>true</GenerateDocumentationFile>
</PropertyGroup>

View File

@@ -73,7 +73,7 @@ namespace MediaBrowser.XbmcMetadata.Parsers
protected IProviderManager ProviderManager { get; }
/// <summary>
/// Gets a value indicating whether URLs after a closing XML tag are supporrted.
/// Gets a value indicating whether URLs after a closing XML tag are supported.
/// </summary>
protected virtual bool SupportsUrlAfterClosingXmlTag => false;
@@ -312,8 +312,11 @@ namespace MediaBrowser.XbmcMetadata.Parsers
if (user is not null)
{
userData = _userDataManager.GetUserData(user, item);
userData.Played = played;
_userDataManager.SaveUserData(user, item, userData, UserDataSaveReason.Import, CancellationToken.None);
if (userData is not null)
{
userData.Played = played;
_userDataManager.SaveUserData(user, item, userData, UserDataSaveReason.Import, CancellationToken.None);
}
}
}
@@ -326,8 +329,11 @@ namespace MediaBrowser.XbmcMetadata.Parsers
if (user is not null)
{
userData = _userDataManager.GetUserData(user, item);
userData.PlayCount = count;
_userDataManager.SaveUserData(user, item, userData, UserDataSaveReason.Import, CancellationToken.None);
if (userData is not null)
{
userData.PlayCount = count;
_userDataManager.SaveUserData(user, item, userData, UserDataSaveReason.Import, CancellationToken.None);
}
}
}
@@ -340,8 +346,11 @@ namespace MediaBrowser.XbmcMetadata.Parsers
if (user is not null)
{
userData = _userDataManager.GetUserData(user, item);
userData.LastPlayedDate = lastPlayed;
_userDataManager.SaveUserData(user, item, userData, UserDataSaveReason.Import, CancellationToken.None);
if (userData is not null)
{
userData.LastPlayedDate = lastPlayed;
_userDataManager.SaveUserData(user, item, userData, UserDataSaveReason.Import, CancellationToken.None);
}
}
}
@@ -663,7 +672,7 @@ namespace MediaBrowser.XbmcMetadata.Parsers
}
var fileSystemMetadata = _directoryService.GetFile(val);
// non existing file returns null
// nonexistent file returns null
if (fileSystemMetadata is null || !fileSystemMetadata.Exists)
{
Logger.LogWarning("Artwork file {Path} specified in nfo file for {ItemName} does not exist.", uri, itemResult.Item.Name);

View File

@@ -50,23 +50,20 @@ namespace MediaBrowser.XbmcMetadata.Parsers
{
case "id":
{
// get ids from attributes
// Get ids from attributes
item.TrySetProviderId(MetadataProvider.Tmdb, reader.GetAttribute("TMDB"));
item.TrySetProviderId(MetadataProvider.Tvdb, reader.GetAttribute("TVDB"));
string? imdbId = reader.GetAttribute("IMDB");
string? tmdbId = reader.GetAttribute("TMDB");
// read id from content
// Read id from content
// Content can be arbitrary according to Kodi wiki, so only parse if we are sure it matches a provider-specific schema
var contentId = reader.ReadElementContentAsString();
if (contentId.Contains("tt", StringComparison.Ordinal) && string.IsNullOrEmpty(imdbId))
if (string.IsNullOrEmpty(imdbId) && contentId.StartsWith("tt", StringComparison.Ordinal))
{
imdbId = contentId;
}
else if (string.IsNullOrEmpty(tmdbId))
{
tmdbId = contentId;
}
item.TrySetProviderId(MetadataProvider.Imdb, imdbId);
item.TrySetProviderId(MetadataProvider.Tmdb, tmdbId);
break;
}
@@ -82,21 +79,13 @@ namespace MediaBrowser.XbmcMetadata.Parsers
if (!string.IsNullOrWhiteSpace(val) && movie is not null)
{
// TODO Handle this better later
if (!val.Contains('<', StringComparison.Ordinal))
try
{
movie.CollectionName = val;
ParseSetXml(val, movie);
}
else
catch (Exception ex)
{
try
{
ParseSetXml(val, movie);
}
catch (Exception ex)
{
Logger.LogError(ex, "Error parsing set node");
}
Logger.LogError(ex, "Error parsing set node");
}
}
@@ -139,7 +128,12 @@ namespace MediaBrowser.XbmcMetadata.Parsers
// Loop through each element
while (!reader.EOF && reader.ReadState == ReadState.Interactive)
{
if (reader.NodeType == XmlNodeType.Element)
if (reader.NodeType == XmlNodeType.Text && reader.Depth == 1)
{
movie.CollectionName = reader.Value;
break;
}
else if (reader.NodeType == XmlNodeType.Element)
{
switch (reader.Name)
{

View File

@@ -1,3 +1,4 @@
using System;
using System.Globalization;
using System.Xml;
using Emby.Naming.TV;
@@ -48,16 +49,20 @@ namespace MediaBrowser.XbmcMetadata.Parsers
{
case "id":
{
item.TrySetProviderId(MetadataProvider.Imdb, reader.GetAttribute("IMDB"));
// Get ids from attributes
item.TrySetProviderId(MetadataProvider.Tmdb, reader.GetAttribute("TMDB"));
item.TrySetProviderId(MetadataProvider.Tvdb, reader.GetAttribute("TVDB"));
string? imdbId = reader.GetAttribute("IMDB");
string? tvdbId = reader.GetAttribute("TVDB");
if (string.IsNullOrWhiteSpace(tvdbId))
// Read id from content
// Content can be arbitrary according to Kodi wiki, so only parse if we are sure it matches a provider-specific schema
var contentId = reader.ReadElementContentAsString();
if (string.IsNullOrEmpty(imdbId) && contentId.StartsWith("tt", StringComparison.Ordinal))
{
tvdbId = reader.ReadElementContentAsString();
imdbId = contentId;
}
item.TrySetProviderId(MetadataProvider.Tvdb, tvdbId);
item.TrySetProviderId(MetadataProvider.Imdb, imdbId);
break;
}

View File

@@ -15,7 +15,7 @@ using Microsoft.Extensions.Logging;
namespace MediaBrowser.XbmcMetadata.Savers
{
/// <summary>
/// Nfo saver for artsist.
/// Nfo saver for artist.
/// </summary>
public class ArtistNfoSaver : BaseNfoSaver
{
@@ -69,7 +69,7 @@ namespace MediaBrowser.XbmcMetadata.Savers
AddAlbums(albums, writer);
}
private void AddAlbums(IList<BaseItem> albums, XmlWriter writer)
private void AddAlbums(IReadOnlyList<BaseItem> albums, XmlWriter writer)
{
foreach (var album in albums
.OrderBy(album => album.ProductionYear ?? 0)

View File

@@ -878,49 +878,52 @@ namespace MediaBrowser.XbmcMetadata.Savers
var userdata = userDataRepo.GetUserData(user, item);
writer.WriteElementString(
if (userdata is not null)
{
writer.WriteElementString(
"isuserfavorite",
userdata.IsFavorite.ToString(CultureInfo.InvariantCulture).ToLowerInvariant());
if (userdata.Rating.HasValue)
{
writer.WriteElementString(
"userrating",
userdata.Rating.Value.ToString(CultureInfo.InvariantCulture).ToLowerInvariant());
}
if (!item.IsFolder)
{
writer.WriteElementString(
"playcount",
userdata.PlayCount.ToString(CultureInfo.InvariantCulture));
writer.WriteElementString(
"watched",
userdata.Played.ToString(CultureInfo.InvariantCulture).ToLowerInvariant());
if (userdata.LastPlayedDate.HasValue)
if (userdata.Rating.HasValue)
{
writer.WriteElementString(
"lastplayed",
userdata.LastPlayedDate.Value.ToString("yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture).ToLowerInvariant());
"userrating",
userdata.Rating.Value.ToString(CultureInfo.InvariantCulture).ToLowerInvariant());
}
writer.WriteStartElement("resume");
if (!item.IsFolder)
{
writer.WriteElementString(
"playcount",
userdata.PlayCount.ToString(CultureInfo.InvariantCulture));
writer.WriteElementString(
"watched",
userdata.Played.ToString(CultureInfo.InvariantCulture).ToLowerInvariant());
var runTimeTicks = item.RunTimeTicks ?? 0;
if (userdata.LastPlayedDate.HasValue)
{
writer.WriteElementString(
"lastplayed",
userdata.LastPlayedDate.Value.ToString("yyyy-MM-dd HH:mm:ss", CultureInfo.InvariantCulture).ToLowerInvariant());
}
writer.WriteElementString(
"position",
TimeSpan.FromTicks(userdata.PlaybackPositionTicks).TotalSeconds.ToString(CultureInfo.InvariantCulture));
writer.WriteElementString(
"total",
TimeSpan.FromTicks(runTimeTicks).TotalSeconds.ToString(CultureInfo.InvariantCulture));
writer.WriteStartElement("resume");
var runTimeTicks = item.RunTimeTicks ?? 0;
writer.WriteElementString(
"position",
TimeSpan.FromTicks(userdata.PlaybackPositionTicks).TotalSeconds.ToString(CultureInfo.InvariantCulture));
writer.WriteElementString(
"total",
TimeSpan.FromTicks(runTimeTicks).TotalSeconds.ToString(CultureInfo.InvariantCulture));
}
}
writer.WriteEndElement();
}
private void AddActors(List<PersonInfo> people, XmlWriter writer, ILibraryManager libraryManager, bool saveImagePath)
private void AddActors(IReadOnlyList<PersonInfo> people, XmlWriter writer, ILibraryManager libraryManager, bool saveImagePath)
{
foreach (var person in people
.OrderBy(person => person.SortOrder ?? 0)

View File

@@ -116,7 +116,9 @@ namespace MediaBrowser.XbmcMetadata.Savers
{
if (!string.IsNullOrEmpty(movie.CollectionName))
{
writer.WriteElementString("set", movie.CollectionName);
writer.WriteStartElement("set");
writer.WriteElementString("name", movie.CollectionName);
writer.WriteEndElement();
}
}
}