diff options
| author | Luke Pulverenti <luke.pulverenti@gmail.com> | 2014-07-08 20:46:11 -0400 |
|---|---|---|
| committer | Luke Pulverenti <luke.pulverenti@gmail.com> | 2014-07-08 20:46:11 -0400 |
| commit | 651d483dec489a84bf93fe900e537cc7be9c4cbd (patch) | |
| tree | 58933f9a84a82e1a1db89c7d7dfa975de7575700 /MediaBrowser.XbmcMetadata | |
| parent | c02e917f5657db4bd76fc6ca17c535fc441c641c (diff) | |
rework nfo savers
Diffstat (limited to 'MediaBrowser.XbmcMetadata')
14 files changed, 844 insertions, 877 deletions
diff --git a/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj b/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj index a3928d7742..972595b94f 100644 --- a/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj +++ b/MediaBrowser.XbmcMetadata/MediaBrowser.XbmcMetadata.csproj @@ -56,13 +56,13 @@ <Compile Include="Providers\MovieNfoProvider.cs" /> <Compile Include="Providers\SeasonNfoProvider.cs" /> <Compile Include="Providers\SeriesNfoProvider.cs" /> - <Compile Include="Savers\AlbumXmlSaver.cs" /> - <Compile Include="Savers\ArtistXmlSaver.cs" /> - <Compile Include="Savers\EpisodeXmlSaver.cs" /> - <Compile Include="Savers\MovieXmlSaver.cs" /> - <Compile Include="Savers\SeasonXmlSaver.cs" /> - <Compile Include="Savers\SeriesXmlSaver.cs" /> - <Compile Include="Savers\XmlSaverHelpers.cs" /> + <Compile Include="Savers\AlbumNfoSaver.cs" /> + <Compile Include="Savers\ArtistNfoSaver.cs" /> + <Compile Include="Savers\BaseNfoSaver.cs" /> + <Compile Include="Savers\EpisodeNfoSaver.cs" /> + <Compile Include="Savers\MovieNfoSaver.cs" /> + <Compile Include="Savers\SeasonNfoSaver.cs" /> + <Compile Include="Savers\SeriesNfoSaver.cs" /> </ItemGroup> <ItemGroup> <ProjectReference Include="..\MediaBrowser.Common\MediaBrowser.Common.csproj"> diff --git a/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs index 49851f42a7..6e31b01783 100644 --- a/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs +++ b/MediaBrowser.XbmcMetadata/Parsers/BaseNfoParser.cs @@ -11,6 +11,7 @@ using System.Linq; using System.Text; using System.Threading; using System.Xml; +using MediaBrowser.XbmcMetadata.Savers; namespace MediaBrowser.XbmcMetadata.Parsers { @@ -63,8 +64,7 @@ namespace MediaBrowser.XbmcMetadata.Parsers ValidationType = ValidationType.None }; - //Fetch(item, metadataFile, settings, Encoding.GetEncoding("ISO-8859-1"), cancellationToken); - Fetch(item, metadataFile, settings, Encoding.UTF8, cancellationToken); + Fetch(item, metadataFile, settings, cancellationToken); } /// <summary> @@ -73,11 +73,10 @@ namespace MediaBrowser.XbmcMetadata.Parsers /// <param name="item">The item.</param> /// <param name="metadataFile">The metadata file.</param> /// <param name="settings">The settings.</param> - /// <param name="encoding">The encoding.</param> /// <param name="cancellationToken">The cancellation token.</param> - private void Fetch(T item, string metadataFile, XmlReaderSettings settings, Encoding encoding, CancellationToken cancellationToken) + private void Fetch(T item, string metadataFile, XmlReaderSettings settings, CancellationToken cancellationToken) { - using (var streamReader = new StreamReader(metadataFile)) + using (var streamReader = BaseNfoSaver.GetStreamReader(metadataFile)) { // Use XmlReader for best performance using (var reader = XmlReader.Create(streamReader, settings)) diff --git a/MediaBrowser.XbmcMetadata/Savers/AlbumNfoSaver.cs b/MediaBrowser.XbmcMetadata/Savers/AlbumNfoSaver.cs new file mode 100644 index 0000000000..800cb8e108 --- /dev/null +++ b/MediaBrowser.XbmcMetadata/Savers/AlbumNfoSaver.cs @@ -0,0 +1,112 @@ +using MediaBrowser.Common.IO; +using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.Audio; +using MediaBrowser.Controller.Library; +using System; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Xml; + +namespace MediaBrowser.XbmcMetadata.Savers +{ + public class AlbumNfoSaver : BaseNfoSaver + { + public AlbumNfoSaver(IFileSystem fileSystem, IServerConfigurationManager configurationManager, ILibraryManager libraryManager, IUserManager userManager, IUserDataManager userDataManager) + : base(fileSystem, configurationManager, libraryManager, userManager, userDataManager) + { + } + + public override string GetSavePath(IHasMetadata item) + { + return Path.Combine(item.Path, "album.nfo"); + } + + protected override string GetRootElementName(IHasMetadata item) + { + return "album"; + } + + public override bool IsEnabledFor(IHasMetadata item, ItemUpdateType updateType) + { + if (!item.SupportsLocalMetadata) + { + return false; + } + + return item is MusicAlbum && updateType >= ItemUpdateType.MetadataDownload; + } + + protected override void WriteCustomElements(IHasMetadata item, XmlWriter writer) + { + var album = (MusicAlbum)item; + + var tracks = album.Tracks + .ToList(); + + var artists = tracks + .SelectMany(i => + { + var list = new List<string>(); + + if (!string.IsNullOrEmpty(i.AlbumArtist)) + { + list.Add(i.AlbumArtist); + } + list.AddRange(i.Artists); + + return list; + }) + .Distinct(StringComparer.OrdinalIgnoreCase); + + foreach (var artist in artists) + { + writer.WriteElementString("artist", artist); + } + + AddTracks(tracks, writer); + } + + private static readonly CultureInfo UsCulture = new CultureInfo("en-US"); + + private void AddTracks(IEnumerable<Audio> tracks, XmlWriter writer) + { + foreach (var track in tracks.OrderBy(i => i.ParentIndexNumber ?? 0).ThenBy(i => i.IndexNumber ?? 0)) + { + writer.WriteStartElement("track"); + + if (track.IndexNumber.HasValue) + { + writer.WriteElementString("position", track.IndexNumber.Value.ToString(UsCulture)); + } + + if (!string.IsNullOrEmpty(track.Name)) + { + writer.WriteElementString("title", track.Name); + } + + if (track.RunTimeTicks.HasValue) + { + var time = TimeSpan.FromTicks(track.RunTimeTicks.Value).ToString(@"mm\:ss"); + + writer.WriteElementString("duration", time); + } + + writer.WriteEndElement(); + } + } + + protected override List<string> GetTagsUsed() + { + var list = new List<string> + { + "track", + "artist" + }; + + return list; + } + } +} diff --git a/MediaBrowser.XbmcMetadata/Savers/AlbumXmlSaver.cs b/MediaBrowser.XbmcMetadata/Savers/AlbumXmlSaver.cs deleted file mode 100644 index 252ca62f23..0000000000 --- a/MediaBrowser.XbmcMetadata/Savers/AlbumXmlSaver.cs +++ /dev/null @@ -1,134 +0,0 @@ -using MediaBrowser.Common.IO; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Entities.Audio; -using MediaBrowser.Controller.Library; -using MediaBrowser.Model.Entities; -using System; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Security; -using System.Text; -using System.Threading; - -namespace MediaBrowser.XbmcMetadata.Savers -{ - public class AlbumXmlSaver : IMetadataFileSaver - { - private readonly ILibraryManager _libraryManager; - private readonly IUserManager _userManager; - private readonly IUserDataManager _userDataRepo; - - private readonly IFileSystem _fileSystem; - private readonly IServerConfigurationManager _config; - - public AlbumXmlSaver(ILibraryManager libraryManager, IUserManager userManager, IUserDataManager userDataRepo, IFileSystem fileSystem, IServerConfigurationManager config) - { - _libraryManager = libraryManager; - _userManager = userManager; - _userDataRepo = userDataRepo; - _fileSystem = fileSystem; - _config = config; - } - - public string Name - { - get - { - return "Xbmc Nfo"; - } - } - - public string GetSavePath(IHasMetadata item) - { - return Path.Combine(item.Path, "album.nfo"); - } - - public void Save(IHasMetadata item, CancellationToken cancellationToken) - { - var album = (MusicAlbum)item; - - var builder = new StringBuilder(); - - builder.Append("<album>"); - - XmlSaverHelpers.AddCommonNodes(album, builder, _libraryManager, _userManager, _userDataRepo, _fileSystem, _config); - - var tracks = album.Tracks - .ToList(); - - var artists = tracks - .SelectMany(i => - { - var list = new List<string>(); - - if (!string.IsNullOrEmpty(i.AlbumArtist)) - { - list.Add(i.AlbumArtist); - } - list.AddRange(i.Artists); - - return list; - }) - .Distinct(StringComparer.OrdinalIgnoreCase); - - foreach (var artist in artists) - { - builder.Append("<artist>" + SecurityElement.Escape(artist) + "</artist>"); - } - - AddTracks(tracks, builder); - - builder.Append("</album>"); - - var xmlFilePath = GetSavePath(item); - - XmlSaverHelpers.Save(builder, xmlFilePath, new List<string> - { - "track", - "artist" - }); - } - - public bool IsEnabledFor(IHasMetadata item, ItemUpdateType updateType) - { - if (!item.SupportsLocalMetadata) - { - return false; - } - - return item is MusicAlbum && updateType >= ItemUpdateType.MetadataDownload; - } - - private static readonly CultureInfo UsCulture = new CultureInfo("en-US"); - - private void AddTracks(IEnumerable<Audio> tracks, StringBuilder builder) - { - foreach (var track in tracks.OrderBy(i => i.ParentIndexNumber ?? 0).ThenBy(i => i.IndexNumber ?? 0)) - { - builder.Append("<track>"); - - if (track.IndexNumber.HasValue) - { - builder.Append("<position>" + SecurityElement.Escape(track.IndexNumber.Value.ToString(UsCulture)) + "</position>"); - } - - if (!string.IsNullOrEmpty(track.Name)) - { - builder.Append("<title>" + SecurityElement.Escape(track.Name) + "</title>"); - } - - if (track.RunTimeTicks.HasValue) - { - var time = TimeSpan.FromTicks(track.RunTimeTicks.Value).ToString(@"mm\:ss"); - - builder.Append("<duration>" + SecurityElement.Escape(time) + "</duration>"); - } - - builder.Append("</track>"); - } - } - } -} diff --git a/MediaBrowser.XbmcMetadata/Savers/ArtistNfoSaver.cs b/MediaBrowser.XbmcMetadata/Savers/ArtistNfoSaver.cs new file mode 100644 index 0000000000..a76eaef839 --- /dev/null +++ b/MediaBrowser.XbmcMetadata/Savers/ArtistNfoSaver.cs @@ -0,0 +1,94 @@ +using MediaBrowser.Common.IO; +using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.Audio; +using MediaBrowser.Controller.Library; +using MediaBrowser.XbmcMetadata.Configuration; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Linq; +using System.Xml; + +namespace MediaBrowser.XbmcMetadata.Savers +{ + public class ArtistNfoSaver : BaseNfoSaver + { + public ArtistNfoSaver(IFileSystem fileSystem, IServerConfigurationManager configurationManager, ILibraryManager libraryManager, IUserManager userManager, IUserDataManager userDataManager) + : base(fileSystem, configurationManager, libraryManager, userManager, userDataManager) + { + } + + public override string GetSavePath(IHasMetadata item) + { + return Path.Combine(item.Path, "artist.nfo"); + } + + protected override string GetRootElementName(IHasMetadata item) + { + return "artist"; + } + + public override bool IsEnabledFor(IHasMetadata item, ItemUpdateType updateType) + { + if (!item.SupportsLocalMetadata) + { + return false; + } + + return item is MusicArtist && updateType >= ItemUpdateType.MetadataDownload; + } + + protected override void WriteCustomElements(IHasMetadata item, XmlWriter writer) + { + var artist = (MusicArtist)item; + + if (artist.EndDate.HasValue) + { + var formatString = ConfigurationManager.GetNfoConfiguration().ReleaseDateFormat; + + writer.WriteElementString("disbanded", artist.EndDate.Value.ToString(formatString)); + } + + var albums = artist + .RecursiveChildren + .OfType<MusicAlbum>() + .ToList(); + + AddAlbums(albums, writer); + } + + private static readonly CultureInfo UsCulture = new CultureInfo("en-US"); + + private void AddAlbums(IEnumerable<MusicAlbum> albums, XmlWriter writer) + { + foreach (var album in albums) + { + writer.WriteStartElement("album"); + + if (!string.IsNullOrEmpty(album.Name)) + { + writer.WriteElementString("title", album.Name); + } + + if (album.ProductionYear.HasValue) + { + writer.WriteElementString("year", album.ProductionYear.Value.ToString(UsCulture)); + } + + writer.WriteEndElement(); + } + } + + protected override List<string> GetTagsUsed() + { + var list = new List<string> + { + "album", + "disbanded" + }; + + return list; + } + } +}
\ No newline at end of file diff --git a/MediaBrowser.XbmcMetadata/Savers/ArtistXmlSaver.cs b/MediaBrowser.XbmcMetadata/Savers/ArtistXmlSaver.cs deleted file mode 100644 index 937d702d34..0000000000 --- a/MediaBrowser.XbmcMetadata/Savers/ArtistXmlSaver.cs +++ /dev/null @@ -1,116 +0,0 @@ -using MediaBrowser.Common.IO; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Entities.Audio; -using MediaBrowser.Controller.Library; -using MediaBrowser.Model.Entities; -using MediaBrowser.XbmcMetadata.Configuration; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Linq; -using System.Security; -using System.Text; -using System.Threading; - -namespace MediaBrowser.XbmcMetadata.Savers -{ - public class ArtistXmlSaver : IMetadataFileSaver - { - private readonly ILibraryManager _libraryManager; - private readonly IUserManager _userManager; - private readonly IUserDataManager _userDataRepo; - - private readonly IFileSystem _fileSystem; - private readonly IServerConfigurationManager _config; - - private static readonly CultureInfo UsCulture = new CultureInfo("en-US"); - - public ArtistXmlSaver(ILibraryManager libraryManager, IUserManager userManager, IUserDataManager userDataRepo, IFileSystem fileSystem, IServerConfigurationManager config) - { - _libraryManager = libraryManager; - _userManager = userManager; - _userDataRepo = userDataRepo; - _fileSystem = fileSystem; - _config = config; - } - - public string GetSavePath(IHasMetadata item) - { - return Path.Combine(item.Path, "artist.nfo"); - } - - public string Name - { - get - { - return "Xbmc Nfo"; - } - } - - public void Save(IHasMetadata item, CancellationToken cancellationToken) - { - var artist = (MusicArtist)item; - - var builder = new StringBuilder(); - - builder.Append("<artist>"); - - XmlSaverHelpers.AddCommonNodes(artist, builder, _libraryManager, _userManager, _userDataRepo, _fileSystem, _config); - - if (artist.EndDate.HasValue) - { - var formatString = _config.GetNfoConfiguration().ReleaseDateFormat; - - builder.Append("<disbanded>" + SecurityElement.Escape(artist.EndDate.Value.ToString(formatString)) + "</disbanded>"); - } - - var albums = artist - .RecursiveChildren - .OfType<MusicAlbum>() - .ToList(); - - AddAlbums(albums, builder); - - builder.Append("</artist>"); - - var xmlFilePath = GetSavePath(item); - - XmlSaverHelpers.Save(builder, xmlFilePath, new List<string> - { - "album", - "disbanded" - }); - } - - public bool IsEnabledFor(IHasMetadata item, ItemUpdateType updateType) - { - if (!item.SupportsLocalMetadata) - { - return false; - } - - return item is MusicArtist && updateType >= ItemUpdateType.MetadataDownload; - } - - private void AddAlbums(IEnumerable<MusicAlbum> albums, StringBuilder builder) - { - foreach (var album in albums) - { - builder.Append("<album>"); - - if (!string.IsNullOrEmpty(album.Name)) - { - builder.Append("<title>" + SecurityElement.Escape(album.Name) + "</title>"); - } - - if (album.ProductionYear.HasValue) - { - builder.Append("<year>" + SecurityElement.Escape(album.ProductionYear.Value.ToString(UsCulture)) + "</year>"); - } - - builder.Append("</album>"); - } - } - } -} diff --git a/MediaBrowser.XbmcMetadata/Savers/XmlSaverHelpers.cs b/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs index 7111a429ab..cb9137ad09 100644 --- a/MediaBrowser.XbmcMetadata/Savers/XmlSaverHelpers.cs +++ b/MediaBrowser.XbmcMetadata/Savers/BaseNfoSaver.cs @@ -15,13 +15,13 @@ using System.Collections.Generic; using System.Globalization; using System.IO; using System.Linq; -using System.Security; using System.Text; +using System.Threading; using System.Xml; namespace MediaBrowser.XbmcMetadata.Savers { - public static class XmlSaverHelpers + public abstract class BaseNfoSaver : IMetadataFileSaver { private static readonly CultureInfo UsCulture = new CultureInfo("en-US"); @@ -98,34 +98,78 @@ namespace MediaBrowser.XbmcMetadata.Savers }.ToDictionary(i => i, StringComparer.OrdinalIgnoreCase); + protected BaseNfoSaver(IFileSystem fileSystem, IServerConfigurationManager configurationManager, ILibraryManager libraryManager, IUserManager userManager, IUserDataManager userDataManager) + { + UserDataManager = userDataManager; + UserManager = userManager; + LibraryManager = libraryManager; + ConfigurationManager = configurationManager; + FileSystem = fileSystem; + } + + protected IFileSystem FileSystem { get; private set; } + protected IServerConfigurationManager ConfigurationManager { get; private set; } + protected ILibraryManager LibraryManager { get; private set; } + protected IUserManager UserManager { get; private set; } + protected IUserDataManager UserDataManager { get; private set; } + + public string Name + { + get + { + return "Xbmc Nfo"; + } + } + + /// <summary> + /// Gets the save path. + /// </summary> + /// <param name="item">The item.</param> + /// <returns>System.String.</returns> + public abstract string GetSavePath(IHasMetadata item); + + /// <summary> + /// Gets the name of the root element. + /// </summary> + /// <param name="item">The item.</param> + /// <returns>System.String.</returns> + protected abstract string GetRootElementName(IHasMetadata item); + /// <summary> - /// Saves the specified XML. + /// Determines whether [is enabled for] [the specified item]. /// </summary> - /// <param name="xml">The XML.</param> - /// <param name="path">The path.</param> - /// <param name="xmlTagsUsed">The XML tags used.</param> - public static void Save(StringBuilder xml, string path, List<string> xmlTagsUsed) + /// <param name="item">The item.</param> + /// <param name="updateType">Type of the update.</param> + /// <returns><c>true</c> if [is enabled for] [the specified item]; otherwise, <c>false</c>.</returns> + public abstract bool IsEnabledFor(IHasMetadata item, ItemUpdateType updateType); + + protected virtual List<string> GetTagsUsed() + { + return new List<string>(); + } + + public void Save(IHasMetadata item, CancellationToken cancellationToken) { - if (File.Exists(path)) + var path = GetSavePath(item); + + using (var memoryStream = new MemoryStream()) { - var tags = xmlTagsUsed.ToList(); + Save(item, memoryStream, path); - var position = xml.ToString().LastIndexOf("</", StringComparison.OrdinalIgnoreCase); - xml.Insert(position, GetCustomTags(path, tags)); - } + memoryStream.Position = 0; - var xmlDocument = new XmlDocument(); - xmlDocument.LoadXml(xml.ToString()); + cancellationToken.ThrowIfCancellationRequested(); - //Add the new node to the document. - xmlDocument.InsertBefore(xmlDocument.CreateXmlDeclaration("1.0", "UTF-8", "yes"), xmlDocument.DocumentElement); + SaveToFile(memoryStream, path); + } + } - Directory.CreateDirectory(Path.GetDirectoryName(path)); + private void SaveToFile(Stream stream, string path) + { + var file = new FileInfo(path); var wasHidden = false; - var file = new FileInfo(path); - // This will fail if the file is hidden if (file.Exists) { @@ -139,10 +183,7 @@ namespace MediaBrowser.XbmcMetadata.Savers using (var filestream = new FileStream(path, FileMode.Create, FileAccess.Write, FileShare.Read)) { - using (var streamWriter = new StreamWriter(filestream, Encoding.UTF8)) - { - xmlDocument.Save(streamWriter); - } + stream.CopyTo(filestream); } if (wasHidden) @@ -154,130 +195,136 @@ namespace MediaBrowser.XbmcMetadata.Savers } } - /// <summary> - /// Gets the custom tags. - /// </summary> - /// <param name="path">The path.</param> - /// <param name="xmlTagsUsed">The XML tags used.</param> - /// <returns>System.String.</returns> - private static string GetCustomTags(string path, List<string> xmlTagsUsed) + private void Save(IHasMetadata item, Stream stream, string xmlPath) { - var settings = new XmlReaderSettings + var settings = new XmlWriterSettings { - CheckCharacters = false, - IgnoreProcessingInstructions = true, - IgnoreComments = true, - ValidationType = ValidationType.None + Indent = true, + Encoding = Encoding.UTF8, + CloseOutput = false }; - var builder = new StringBuilder(); - - using (var streamReader = new StreamReader(path, Encoding.UTF8)) + using (XmlWriter writer = XmlWriter.Create(stream, settings)) { - // Use XmlReader for best performance - using (var reader = XmlReader.Create(streamReader, settings)) + var root = GetRootElementName(item); + + writer.WriteStartDocument(true); + + writer.WriteStartElement(root); + + var baseItem = item as BaseItem; + + if (baseItem != null) { - reader.MoveToContent(); + AddCommonNodes(baseItem, writer, LibraryManager, UserManager, UserDataManager, FileSystem, ConfigurationManager); + } - // Loop through each element - while (reader.Read()) - { - if (reader.NodeType == XmlNodeType.Element) - { - var name = reader.Name; + WriteCustomElements(item, writer); - if (!CommonTags.ContainsKey(name) && !xmlTagsUsed.Contains(name, StringComparer.OrdinalIgnoreCase)) - { - builder.AppendLine(reader.ReadOuterXml()); - } - else - { - reader.Skip(); - } - } - } + var hasMediaSources = baseItem as IHasMediaSources; + + if (hasMediaSources != null) + { + AddMediaInfo(hasMediaSources, writer); } - } - return builder.ToString(); + var tagsUsed = GetTagsUsed(); + + try + { + AddCustomTags(xmlPath, tagsUsed, writer); + } + catch (FileNotFoundException) + { + + } + + writer.WriteEndElement(); + + writer.WriteEndDocument(); + } } - public static void AddMediaInfo<T>(T item, StringBuilder builder) - where T : BaseItem, IHasMediaSources + protected abstract void WriteCustomElements(IHasMetadata item, XmlWriter writer); + + public static void AddMediaInfo<T>(T item, XmlWriter writer) + where T : IHasMediaSources { - builder.Append("<fileinfo>"); - builder.Append("<streamdetails>"); + writer.WriteStartElement("fileinfo"); + writer.WriteStartElement("streamdetails"); - foreach (var stream in item.GetMediaSources(false).First().MediaStreams) + var mediaSource = item.GetMediaSources(false).First(); + + foreach (var stream in mediaSource.MediaStreams) { - builder.Append("<" + stream.Type.ToString().ToLower() + ">"); + writer.WriteStartElement(stream.Type.ToString().ToLower()); if (!string.IsNullOrEmpty(stream.Codec)) { - builder.Append("<codec>" + SecurityElement.Escape(stream.Codec) + "</codec>"); - builder.Append("<micodec>" + SecurityElement.Escape(stream.Codec) + "</micodec>"); + writer.WriteElementString("codec", stream.Codec); + writer.WriteElementString("micodec", stream.Codec); } if (stream.BitRate.HasValue) { - builder.Append("<bitrate>" + stream.BitRate.Value.ToString(UsCulture) + "</bitrate>"); + writer.WriteElementString("bitrate", stream.BitRate.Value.ToString(UsCulture)); } if (stream.Width.HasValue) { - builder.Append("<width>" + stream.Width.Value.ToString(UsCulture) + "</width>"); + writer.WriteElementString("width", stream.Width.Value.ToString(UsCulture)); } if (stream.Height.HasValue) { - builder.Append("<height>" + stream.Height.Value.ToString(UsCulture) + "</height>"); + writer.WriteElementString("height", stream.Height.Value.ToString(UsCulture)); } if (!string.IsNullOrEmpty(stream.AspectRatio)) { - builder.Append("<aspect>" + SecurityElement.Escape(stream.AspectRatio) + "</aspect>"); - builder.Append("<aspectratio>" + SecurityElement.Escape(stream.AspectRatio) + "</aspectratio>"); + writer.WriteElementString("aspect", stream.AspectRatio); + writer.WriteElementString("aspectratio", stream.AspectRatio); } var framerate = stream.AverageFrameRate ?? stream.RealFrameRate; if (framerate.HasValue) { - builder.Append("<framerate>" + framerate.Value.ToString(UsCulture) + "</framerate>"); + writer.WriteElementString("framerate", framerate.Value.ToString(UsCulture)); } if (!string.IsNullOrEmpty(stream.Language)) { - builder.Append("<language>" + SecurityElement.Escape(stream.Language) + "</language>"); + writer.WriteElementString("language", stream.Language); } var scanType = stream.IsInterlaced ? "interlaced" : "progressive"; if (!string.IsNullOrEmpty(scanType)) { - builder.Append("<scantype>" + SecurityElement.Escape(scanType) + "</scantype>"); + writer.WriteElementString("scantype", scanType); } if (stream.Channels.HasValue) { - builder.Append("<channels>" + stream.Channels.Value.ToString(UsCulture) + "</channels>"); + writer.WriteElementString("channels", stream.Channels.Value.ToString(UsCulture)); } if (stream.SampleRate.HasValue) { - builder.Append("<samplingrate>" + stream.SampleRate.Value.ToString(UsCulture) + "</samplingrate>"); + writer.WriteElementString("samplingrate", stream.SampleRate.Value.ToString(UsCulture)); } - builder.Append("<default>" + SecurityElement.Escape(stream.IsDefault.ToString()) + "</default>"); - builder.Append("<forced>" + SecurityElement.Escape(stream.IsForced.ToString()) + "</forced>"); + writer.WriteElementString("default", stream.IsDefault.ToString()); + writer.WriteElementString("forced", stream.IsForced.ToString()); if (stream.Type == MediaStreamType.Video) { - if (item.RunTimeTicks.HasValue) + if (mediaSource.RunTimeTicks.HasValue) { - var timespan = TimeSpan.FromTicks(item.RunTimeTicks.Value); + var timespan = TimeSpan.FromTicks(mediaSource.RunTimeTicks.Value); - builder.Append("<duration>" + Convert.ToInt32(timespan.TotalMinutes).ToString(UsCulture) + "</duration>"); - builder.Append("<durationinseconds>" + Convert.ToInt32(timespan.TotalSeconds).ToString(UsCulture) + "</durationinseconds>"); + writer.WriteElementString("duration", Convert.ToInt32(timespan.TotalMinutes).ToString(UsCulture)); + writer.WriteElementString("durationinseconds", Convert.ToInt32(timespan.TotalSeconds).ToString(UsCulture)); } var video = item as Video; @@ -291,34 +338,34 @@ namespace MediaBrowser.XbmcMetadata.Savers switch (video.Video3DFormat.Value) { case Video3DFormat.FullSideBySide: - builder.Append("<format3d>FSBS</format3d>"); + writer.WriteElementString("format3d", "FSBS"); break; case Video3DFormat.FullTopAndBottom: - builder.Append("<format3d>FTAB</format3d>"); + writer.WriteElementString("format3d", "FTAB"); break; case Video3DFormat.HalfSideBySide: - builder.Append("<format3d>HSBS</format3d>"); + writer.WriteElementString("format3d", "HSBS"); break; case Video3DFormat.HalfTopAndBottom: - builder.Append("<format3d>HTAB</format3d>"); + writer.WriteElementString("format3d", "HTAB"); break; } } } } - builder.Append("</" + stream.Type.ToString().ToLower() + ">"); + writer.WriteEndElement(); } - builder.Append("</streamdetails>"); - builder.Append("</fileinfo>"); + writer.WriteEndElement(); + writer.WriteEndElement(); } /// <summary> /// Adds the common nodes. /// </summary> /// <returns>Task.</returns> - public static void AddCommonNodes(BaseItem item, StringBuilder builder, ILibraryManager libraryManager, IUserManager userManager, IUserDataManager userDataRepo, IFileSystem fileSystem, IServerConfigurationManager config) + public static void AddCommonNodes(BaseItem item, XmlWriter writer, ILibraryManager libraryManager, IUserManager userManager, IUserDataManager userDataRepo, IFileSystem fileSystem, IServerConfigurationManager config) { var overview = (item.Overview ?? string.Empty) .StripHtml() @@ -328,15 +375,15 @@ namespace MediaBrowser.XbmcMetadata.Savers if (item is MusicArtist) { - builder.Append("<biography><![CDATA[" + overview + "]]></biography>"); + writer.WriteElementString("biography", overview); } else if (item is MusicAlbum) { - builder.Append("<review><![CDATA[" + overview + "]]></review>"); + writer.WriteElementString("review", overview); } else { - builder.Append("<plot><![CDATA[" + overview + "]]></plot>"); + writer.WriteElementString("plot", overview); } var hasShortOverview = item as IHasShortOverview; @@ -346,30 +393,34 @@ namespace MediaBrowser.XbmcMetadata.Savers .StripHtml() .Replace(""", "'"); - builder.Append("<outline><![CDATA[" + outline + "]]></outline>"); + writer.WriteElementString("outline", outline); } else { - builder.Append("<outline><![CDATA[" + overview + "]]></outline>"); + writer.WriteElementString("outline", overview); + } + + if (!string.IsNullOrWhiteSpace(item.CustomRating)) + { + writer.WriteElementString("customrating", item.CustomRating); } - builder.Append("<customrating>" + SecurityElement.Escape(item.CustomRating ?? string.Empty) + "</customrating>"); - builder.Append("<lockdata>" + item.IsLocked.ToString().ToLower() + "</lockdata>"); + writer.WriteElementString("lockdata", item.IsLocked.ToString().ToLower()); if (item.LockedFields.Count > 0) { - builder.Append("<lockedfields>" + string.Join("|", item.LockedFields.Select(i => i.ToString()).ToArray()) + "</lockedfields>"); + writer.WriteElementString("lockedfields", string.Join("|", item.LockedFields.Select(i => i.ToString()).ToArray())); } - + if (!string.IsNullOrEmpty(item.DisplayMediaType)) { - builder.Append("<type>" + SecurityElement.Escape(item.DisplayMediaType) + "</type>"); + writer.WriteElementString("type", item.DisplayMediaType); } - builder.Append("<dateadded>" + SecurityElement.Escape(item.DateCreated.ToString("yyyy-MM-dd HH:mm:ss")) + "</dateadded>"); + writer.WriteElementString("dateadded", item.DateCreated.ToString("yyyy-MM-dd HH:mm:ss")); - builder.Append("<title>" + SecurityElement.Escape(item.Name ?? string.Empty) + "</title>"); - builder.Append("<originaltitle>" + SecurityElement.Escape(item.Name ?? string.Empty) + "</originaltitle>"); + writer.WriteElementString("title", item.Name ?? string.Empty); + writer.WriteElementString("originaltitle", item.Name ?? string.Empty); var directors = item.People .Where(i => IsPersonType(i, PersonType.Director)) @@ -378,7 +429,7 @@ namespace MediaBrowser.XbmcMetadata.Savers foreach (var person in directors) { - builder.Append("<director>" + SecurityElement.Escape(person) + "</director>"); + writer.WriteElementString("director", person); } var writers = item.People @@ -389,12 +440,12 @@ namespace MediaBrowser.XbmcMetadata.Savers foreach (var person in writers) { - builder.Append("<writer>" + SecurityElement.Escape(person) + "</writer>"); + writer.WriteElementString("writer", person); } foreach (var person in writers) { - builder.Append("<credits>" + SecurityElement.Escape(person) + "</credits>"); + writer.WriteElementString("credits", person); } var hasTrailer = item as IHasTrailers; @@ -402,33 +453,33 @@ namespace MediaBrowser.XbmcMetadata.Savers { foreach (var trailer in hasTrailer.RemoteTrailers) { - builder.Append("<trailer>" + SecurityElement.Escape(GetOutputTrailerUrl(trailer.Url)) + "</trailer>"); + writer.WriteElementString("trailer", GetOutputTrailerUrl(trailer.Url)); } } if (item.CommunityRating.HasValue) { - builder.Append("<rating>" + SecurityElement.Escape(item.CommunityRating.Value.ToString(UsCulture)) + "</rating>"); + writer.WriteElementString("rating", item.CommunityRating.Value.ToString(UsCulture)); } if (item.ProductionYear.HasValue) { - builder.Append("<year>" + SecurityElement.Escape(item.ProductionYear.Value.ToString(UsCulture)) + "</year>"); + writer.WriteElementString("year", item.ProductionYear.Value.ToString(UsCulture)); } if (!string.IsNullOrEmpty(item.ForcedSortName)) { - builder.Append("<sorttitle>" + SecurityElement.Escape(item.ForcedSortName) + "</sorttitle>"); + writer.WriteElementString("sorttitle", item.ForcedSortName); } if (!string.IsNullOrEmpty(item.OfficialRating)) { - builder.Append("<mpaa>" + SecurityElement.Escape(item.OfficialRating) + "</mpaa>"); + writer.WriteElementString("mpaa", item.OfficialRating); } if (!string.IsNullOrEmpty(item.OfficialRatingDescription)) { - builder.Append("<mpaadescription>" + SecurityElement.Escape(item.OfficialRatingDescription) + "</mpaadescription>"); + writer.WriteElementString("mpaadescription", item.OfficialRatingDescription); } var hasAspectRatio = item as IHasAspectRatio; @@ -436,27 +487,27 @@ namespace MediaBrowser.XbmcMetadata.Savers { if (!string.IsNullOrEmpty(hasAspectRatio.AspectRatio)) { - builder.Append("<aspectratio>" + SecurityElement.Escape(hasAspectRatio.AspectRatio) + "</aspectratio>"); + writer.WriteElementString("aspectratio", hasAspectRatio.AspectRatio); } } if (!string.IsNullOrEmpty(item.HomePageUrl)) { - builder.Append("<website>" + SecurityElement.Escape(item.HomePageUrl) + "</website>"); + writer.WriteElementString("website", item.HomePageUrl); } var rt = item.GetProviderId(MetadataProviders.RottenTomatoes); if (!string.IsNullOrEmpty(rt)) { - builder.Append("<rottentomatoesid>" + SecurityElement.Escape(rt) + "</rottentomatoesid>"); + writer.WriteElementString("rottentomatoesid", rt); } var tmdbCollection = item.GetProviderId(MetadataProviders.TmdbCollection); if (!string.IsNullOrEmpty(tmdbCollection)) { - builder.Append("<collectionnumber>" + SecurityElement.Escape(tmdbCollection) + "</collectionnumber>"); + writer.WriteElementString("collectionnumber", tmdbCollection); } var imdb = item.GetProviderId(MetadataProviders.Imdb); @@ -464,11 +515,11 @@ namespace MediaBrowser.XbmcMetadata.Savers { if (item is Series) { - builder.Append("<imdb_id>" + SecurityElement.Escape(imdb) + "</imdb_id>"); + writer.WriteElementString("imdb_id", imdb); } else { - builder.Append("<imdbid>" + SecurityElement.Escape(imdb) + "</imdbid>"); + writer.WriteElementString("imdbid", imdb); } } @@ -478,20 +529,20 @@ namespace MediaBrowser.XbmcMetadata.Savers var tvdb = item.GetProviderId(MetadataProviders.Tvdb); if (!string.IsNullOrEmpty(tvdb)) { - builder.Append("<tvdbid>" + SecurityElement.Escape(tvdb) + "</tvdbid>"); + writer.WriteElementString("tvdbid", tvdb); } } var tmdb = item.GetProviderId(MetadataProviders.Tmdb); if (!string.IsNullOrEmpty(tmdb)) { - builder.Append("<tmdbid>" + SecurityElement.Escape(tmdb) + "</tmdbid>"); + writer.WriteElementString("tmdbid", tmdb); } var tvcom = item.GetProviderId(MetadataProviders.Tvcom); if (!string.IsNullOrEmpty(tvcom)) { - builder.Append("<tvcomid>" + SecurityElement.Escape(tvcom) + "</tvcomid>"); + writer.WriteElementString("tvcomid", tvcom); } var hasLanguage = item as IHasPreferredMetadataLanguage; @@ -499,7 +550,7 @@ namespace MediaBrowser.XbmcMetadata.Savers { if (!string.IsNullOrEmpty(hasLanguage.PreferredMetadataLanguage)) { - builder.Append("<language>" + SecurityElement.Escape(hasLanguage.PreferredMetadataLanguage) + "</language>"); + writer.WriteElementString("language", hasLanguage.PreferredMetadataLanguage); } } @@ -509,12 +560,12 @@ namespace MediaBrowser.XbmcMetadata.Savers if (item is MusicArtist) { - builder.Append("<formed>" + SecurityElement.Escape(item.PremiereDate.Value.ToString(formatString)) + "</formed>"); + writer.WriteElementString("formed", item.PremiereDate.Value.ToString(formatString)); } else { - builder.Append("<premiered>" + SecurityElement.Escape(item.PremiereDate.Value.ToString(formatString)) + "</premiered>"); - builder.Append("<releasedate>" + SecurityElement.Escape(item.PremiereDate.Value.ToString(formatString)) + "</releasedate>"); + writer.WriteElementString("premiered", item.PremiereDate.Value.ToString(formatString)); + writer.WriteElementString("releasedate", item.PremiereDate.Value.ToString(formatString)); } } @@ -524,7 +575,7 @@ namespace MediaBrowser.XbmcMetadata.Savers { var formatString = options.ReleaseDateFormat; - builder.Append("<enddate>" + SecurityElement.Escape(item.EndDate.Value.ToString(formatString)) + "</enddate>"); + writer.WriteElementString("enddate", item.EndDate.Value.ToString(formatString)); } } @@ -534,12 +585,12 @@ namespace MediaBrowser.XbmcMetadata.Savers { if (hasCriticRating.CriticRating.HasValue) { - builder.Append("<criticrating>" + SecurityElement.Escape(hasCriticRating.CriticRating.Value.ToString(UsCulture)) + "</criticrating>"); + writer.WriteElementString("criticrating", hasCriticRating.CriticRating.Value.ToString(UsCulture)); } if (!string.IsNullOrEmpty(hasCriticRating.CriticRatingSummary)) { - builder.Append("<criticratingsummary><![CDATA[" + hasCriticRating.CriticRatingSummary + "]]></criticratingsummary>"); + writer.WriteElementString("criticratingsummary", hasCriticRating.CriticRatingSummary); } } @@ -549,13 +600,13 @@ namespace MediaBrowser.XbmcMetadata.Savers { if (!string.IsNullOrEmpty(hasDisplayOrder.DisplayOrder)) { - builder.Append("<displayorder>" + SecurityElement.Escape(hasDisplayOrder.DisplayOrder) + "</displayorder>"); + writer.WriteElementString("displayorder", hasDisplayOrder.DisplayOrder); } } if (item.VoteCount.HasValue) { - builder.Append("<votes>" + SecurityElement.Escape(item.VoteCount.Value.ToString(UsCulture)) + "</votes>"); + writer.WriteElementString("votes", item.VoteCount.Value.ToString(UsCulture)); } var hasBudget = item as IHasBudget; @@ -563,19 +614,19 @@ namespace MediaBrowser.XbmcMetadata.Savers { if (hasBudget.Budget.HasValue) { - builder.Append("<budget>" + SecurityElement.Escape(hasBudget.Budget.Value.ToString(UsCulture)) + "</budget>"); + writer.WriteElementString("budget", hasBudget.Budget.Value.ToString(UsCulture)); } if (hasBudget.Revenue.HasValue) { - builder.Append("<revenue>" + SecurityElement.Escape(hasBudget.Revenue.Value.ToString(UsCulture)) + "</revenue>"); + writer.WriteElementString("revenue", hasBudget.Revenue.Value.ToString(UsCulture)); } } var hasMetascore = item as IHasMetascore; if (hasMetascore != null && hasMetascore.Metascore.HasValue) { - builder.Append("<metascore>" + SecurityElement.Escape(hasMetascore.Metascore.Value.ToString(UsCulture)) + "</metascore>"); + writer.WriteElementString("metascore", hasMetascore.Metascore.Value.ToString(UsCulture)); } // Use original runtime here, actual file runtime later in MediaInfo @@ -585,7 +636,7 @@ namespace MediaBrowser.XbmcMetadata.Savers { var timespan = TimeSpan.FromTicks(runTimeTicks.Value); - builder.Append("<runtime>" + Convert.ToInt32(timespan.TotalMinutes).ToString(UsCulture) + "</runtime>"); + writer.WriteElementString("runtime", Convert.ToInt32(timespan.TotalMinutes).ToString(UsCulture)); } var hasTaglines = item as IHasTaglines; @@ -593,7 +644,7 @@ namespace MediaBrowser.XbmcMetadata.Savers { foreach (var tagline in hasTaglines.Taglines) { - builder.Append("<tagline>" + SecurityElement.Escape(tagline) + "</tagline>"); + writer.WriteElementString("tagline", tagline); } } @@ -602,18 +653,18 @@ namespace MediaBrowser.XbmcMetadata.Savers { foreach (var country in hasProductionLocations.ProductionLocations) { - builder.Append("<country>" + SecurityElement.Escape(country) + "</country>"); + writer.WriteElementString("country", country); } } foreach (var genre in item.Genres) { - builder.Append("<genre>" + SecurityElement.Escape(genre) + "</genre>"); + writer.WriteElementString("genre", genre); } foreach (var studio in item.Studios) { - builder.Append("<studio>" + SecurityElement.Escape(studio) + "</studio>"); + writer.WriteElementString("studio", studio); } var hasTags = item as IHasTags; @@ -623,11 +674,11 @@ namespace MediaBrowser.XbmcMetadata.Savers { if (item is MusicAlbum || item is MusicArtist) { - builder.Append("<style>" + SecurityElement.Escape(tag) + "</style>"); + writer.WriteElementString("style", tag); } else { - builder.Append("<tag>" + SecurityElement.Escape(tag) + "</tag>"); + writer.WriteElementString("tag", tag); } } } @@ -637,111 +688,111 @@ namespace MediaBrowser.XbmcMetadata.Savers { foreach (var tag in hasKeywords.Keywords) { - builder.Append("<plotkeyword>" + SecurityElement.Escape(tag) + "</plotkeyword>"); + writer.WriteElementString("plotkeyword", tag); } } var hasAwards = item as IHasAwards; if (hasAwards != null && !string.IsNullOrEmpty(hasAwards.AwardSummary)) { - builder.Append("<awardsummary>" + SecurityElement.Escape(hasAwards.AwardSummary) + "</awardsummary>"); + writer.WriteElementString("awardsummary", hasAwards.AwardSummary); } var externalId = item.GetProviderId(MetadataProviders.AudioDbArtist); if (!string.IsNullOrEmpty(externalId)) { - builder.Append("<audiodbartistid>" + SecurityElement.Escape(externalId) + "</audiodbartistid>"); + writer.WriteElementString("audiodbartistid", externalId); } externalId = item.GetProviderId(MetadataProviders.AudioDbAlbum); if (!string.IsNullOrEmpty(externalId)) { - builder.Append("<audiodbalbumid>" + SecurityElement.Escape(externalId) + "</audiodbalbumid>"); + writer.WriteElementString("audiodbalbumid", externalId); } externalId = item.GetProviderId(MetadataProviders.Zap2It); if (!string.IsNullOrEmpty(externalId)) { - builder.Append("<zap2itid>" + SecurityElement.Escape(externalId) + "</zap2itid>"); + writer.WriteElementString("zap2itid", externalId); } externalId = item.GetProviderId(MetadataProviders.MusicBrainzAlbum); if (!string.IsNullOrEmpty(externalId)) { - builder.Append("<musicbrainzalbumid>" + SecurityElement.Escape(externalId) + "</musicbrainzalbumid>"); + writer.WriteElementString("musicbrainzalbumid", externalId); } externalId = item.GetProviderId(MetadataProviders.MusicBrainzAlbumArtist); if (!string.IsNullOrEmpty(externalId)) { - builder.Append("<musicbrainzalbumartistid>" + SecurityElement.Escape(externalId) + "</musicbrainzalbumartistid>"); + writer.WriteElementString("musicbrainzalbumartistid", externalId); } externalId = item.GetProviderId(MetadataProviders.MusicBrainzArtist); if (!string.IsNullOrEmpty(externalId)) { - builder.Append("<musicbrainzartistid>" + SecurityElement.Escape(externalId) + "</musicbrainzartistid>"); + writer.WriteElementString("musicbrainzartistid", externalId); } externalId = item.GetProviderId(MetadataProviders.MusicBrainzReleaseGroup); if (!string.IsNullOrEmpty(externalId)) { - builder.Append("<musicbrainzreleasegroupid>" + SecurityElement.Escape(externalId) + "</musicbrainzreleasegroupid>"); + writer.WriteElementString("musicbrainzreleasegroupid", externalId); } externalId = item.GetProviderId(MetadataProviders.Gamesdb); if (!string.IsNullOrEmpty(externalId)) { - builder.Append("<gamesdbid>" + SecurityElement.Escape(externalId) + "</gamesdbid>"); + writer.WriteElementString("gamesdbid", externalId); } externalId = item.GetProviderId(MetadataProviders.TvRage); if (!string.IsNullOrEmpty(externalId)) { - builder.Append("<tvrageid>" + SecurityElement.Escape(externalId) + "</tvrageid>"); + writer.WriteElementString("tvrageid", externalId); } if (options.SaveImagePathsInNfo) { - AddImages(item, builder, fileSystem, config); + AddImages(item, writer, fileSystem, config); } - AddUserData(item, builder, userManager, userDataRepo, options); + AddUserData(item, writer, userManager, userDataRepo, options); - AddActors(item, builder, libraryManager, fileSystem, config); + AddActors(item, writer, libraryManager, fileSystem, config); var folder = item as BoxSet; if (folder != null) { - AddCollectionItems(folder, builder); + AddCollectionItems(folder, writer); } } - public static void AddChapters(Video item, StringBuilder builder, IItemRepository repository) + public static void AddChapters(Video item, XmlWriter writer, IItemRepository repository) { var chapters = repository.GetChapters(item.Id); foreach (var chapter in chapters) { - builder.Append("<chapter>"); - builder.Append("<name>" + SecurityElement.Escape(chapter.Name) + "</name>"); + writer.WriteStartElement("chapter"); + writer.WriteElementString("name", chapter.Name); var time = TimeSpan.FromTicks(chapter.StartPositionTicks); var ms = Convert.ToInt64(time.TotalMilliseconds); - builder.Append("<startpositionms>" + SecurityElement.Escape(ms.ToString(UsCulture)) + "</startpositionms>"); - builder.Append("</chapter>"); + writer.WriteElementString("startpositionms", ms.ToString(UsCulture)); + writer.WriteEndElement(); } } - public static void AddCollectionItems(Folder item, StringBuilder builder) + private static void AddCollectionItems(Folder item, XmlWriter writer) { var items = item.LinkedChildren .Where(i => i.Type == LinkedChildType.Manual && !string.IsNullOrWhiteSpace(i.ItemName)) @@ -749,17 +800,17 @@ namespace MediaBrowser.XbmcMetadata.Savers foreach (var link in items) { - builder.Append("<collectionitem>"); + writer.WriteStartElement("collectionitem"); - builder.Append("<name>" + SecurityElement.Escape(link.ItemName) + "</name>"); - builder.Append("<type>" + SecurityElement.Escape(link.ItemType) + "</type>"); + writer.WriteElementString("name", link.ItemName); + writer.WriteElementString("type", link.ItemType); if (link.ItemYear.HasValue) { - builder.Append("<year>" + SecurityElement.Escape(link.ItemYear.Value.ToString(UsCulture)) + "</year>"); + writer.WriteElementString("year", link.ItemYear.Value.ToString(UsCulture)); } - builder.Append("</collectionitem>"); + writer.WriteEndElement(); } } @@ -777,26 +828,26 @@ namespace MediaBrowser.XbmcMetadata.Savers StringComparison.OrdinalIgnoreCase); } - private static void AddImages(BaseItem item, StringBuilder builder, IFileSystem fileSystem, IServerConfigurationManager config) + private static void AddImages(BaseItem item, XmlWriter writer, IFileSystem fileSystem, IServerConfigurationManager config) { - builder.Append("<art>"); + writer.WriteStartElement("art"); var poster = item.PrimaryImagePath; if (!string.IsNullOrEmpty(poster)) { - builder.Append("<poster>" + SecurityElement.Escape(GetPathToSave(item.PrimaryImagePath, fileSystem, config)) + "</poster>"); + writer.WriteElementString("poster", GetPathToSave(item.PrimaryImagePath, fileSystem, config)); } foreach (var backdrop in item.GetImages(ImageType.Backdrop)) { - builder.Append("<fanart>" + SecurityElement.Escape(GetPathToSave(backdrop.Path, fileSystem, config)) + "</fanart>"); + writer.WriteElementString("fanart", GetPathToSave(backdrop.Path, fileSystem, config)); } - builder.Append("</art>"); + writer.WriteEndElement(); } - private static void AddUserData(BaseItem item, StringBuilder builder, IUserManager userManager, IUserDataManager userDataRepo, XbmcMetadataOptions options) + private static void AddUserData(BaseItem item, XmlWriter writer, IUserManager userManager, IUserDataManager userDataRepo, XbmcMetadataOptions options) { var userId = options.UserId; if (string.IsNullOrWhiteSpace(userId)) @@ -818,25 +869,25 @@ namespace MediaBrowser.XbmcMetadata.Savers var userdata = userDataRepo.GetUserData(user.Id, item.GetUserDataKey()); - builder.Append("<playcount>" + userdata.PlayCount.ToString(UsCulture) + "</playcount>"); - builder.Append("<watched>" + userdata.Played.ToString().ToLower() + "</watched>"); + writer.WriteElementString("playcount", userdata.PlayCount.ToString(UsCulture)); + writer.WriteElementString("watched", userdata.Played.ToString().ToLower()); if (userdata.LastPlayedDate.HasValue) { - builder.Append("<lastplayed>" + SecurityElement.Escape(userdata.LastPlayedDate.Value.ToString("yyyy-MM-dd HH:mm:ss")) + "</lastplayed>"); + writer.WriteElementString("lastplayed", userdata.LastPlayedDate.Value.ToString("yyyy-MM-dd HH:mm:ss").ToLower()); } - builder.Append("<resume>"); + writer.WriteStartElement("resume"); var runTimeTicks = item.RunTimeTicks ?? 0; - builder.Append("<position>" + TimeSpan.FromTicks(userdata.PlaybackPositionTicks).TotalSeconds.ToString(UsCulture) + "</position>"); - builder.Append("<total>" + TimeSpan.FromTicks(runTimeTicks).TotalSeconds.ToString(UsCulture) + "</total>"); + writer.WriteElementString("position", TimeSpan.FromTicks(userdata.PlaybackPositionTicks).TotalSeconds.ToString(UsCulture)); + writer.WriteElementString("total", TimeSpan.FromTicks(runTimeTicks).TotalSeconds.ToString(UsCulture)); - builder.Append("</resume>"); + writer.WriteEndElement(); } - public static void AddActors(BaseItem item, StringBuilder builder, ILibraryManager libraryManager, IFileSystem fileSystem, IServerConfigurationManager config) + private static void AddActors(BaseItem item, XmlWriter writer, ILibraryManager libraryManager, IFileSystem fileSystem, IServerConfigurationManager config) { var actors = item.People .Where(i => !IsPersonType(i, PersonType.Director) && !IsPersonType(i, PersonType.Writer)) @@ -844,14 +895,26 @@ namespace MediaBrowser.XbmcMetadata.Savers foreach (var person in actors) { - builder.Append("<actor>"); - builder.Append("<name>" + SecurityElement.Escape(person.Name ?? string.Empty) + "</name>"); - builder.Append("<role>" + SecurityElement.Escape(person.Role ?? string.Empty) + "</role>"); - builder.Append("<type>" + SecurityElement.Escape(person.Type ?? string.Empty) + "</type>"); + writer.WriteStartElement("actor"); + + if (!string.IsNullOrWhiteSpace(person.Name)) + { + writer.WriteElementString("name", person.Name); + } + + if (!string.IsNullOrWhiteSpace(person.Role)) + { + writer.WriteElementString("role", person.Role); + } + if (!string.IsNullOrWhiteSpace(person.Type)) + { + writer.WriteElementString("type", person.Type); + } + if (person.SortOrder.HasValue) { - builder.Append("<sortorder>" + SecurityElement.Escape(person.SortOrder.Value.ToString(UsCulture)) + "</sortorder>"); + writer.WriteElementString("sortorder", person.SortOrder.Value.ToString(UsCulture)); } try @@ -860,7 +923,7 @@ namespace MediaBrowser.XbmcMetadata.Savers if (!string.IsNullOrEmpty(personEntity.PrimaryImagePath)) { - builder.Append("<thumb>" + SecurityElement.Escape(GetPathToSave(personEntity.PrimaryImagePath, fileSystem, config)) + "</thumb>"); + writer.WriteElementString("thumb", GetPathToSave(personEntity.PrimaryImagePath, fileSystem, config)); } } catch (Exception) @@ -868,15 +931,10 @@ namespace MediaBrowser.XbmcMetadata.Savers // Already logged in core } - builder.Append("</actor>"); + writer.WriteEndElement(); } } - private static bool IsPersonType(PersonInfo person, string type) - { - return string.Equals(person.Type, type, StringComparison.OrdinalIgnoreCase) || string.Equals(person.Role, type, StringComparison.OrdinalIgnoreCase); - } - private static string GetPathToSave(string path, IFileSystem fileSystem, IServerConfigurationManager config) { foreach (var map in config.Configuration.PathSubstitutions) @@ -887,24 +945,53 @@ namespace MediaBrowser.XbmcMetadata.Savers return path; } - public static string ReplaceString(string str, string oldValue, string newValue, StringComparison comparison) + private static bool IsPersonType(PersonInfo person, string type) + { + return string.Equals(person.Type, type, StringComparison.OrdinalIgnoreCase) || string.Equals(person.Role, type, StringComparison.OrdinalIgnoreCase); + } + + private static void AddCustomTags(string path, List<string> xmlTagsUsed, XmlWriter writer) { - var sb = new StringBuilder(); + var settings = new XmlReaderSettings + { + CheckCharacters = false, + IgnoreProcessingInstructions = true, + IgnoreComments = true, + ValidationType = ValidationType.None + }; - int previousIndex = 0; - int index = str.IndexOf(oldValue, comparison); - while (index != -1) + using (var streamReader = GetStreamReader(path)) { - sb.Append(str.Substring(previousIndex, index - previousIndex)); - sb.Append(newValue); - index += oldValue.Length; + // Use XmlReader for best performance + using (var reader = XmlReader.Create(streamReader, settings)) + { + reader.MoveToContent(); + + // Loop through each element + while (reader.Read()) + { + if (reader.NodeType == XmlNodeType.Element) + { + var name = reader.Name; - previousIndex = index; - index = str.IndexOf(oldValue, index, comparison); + if (!CommonTags.ContainsKey(name) && !xmlTagsUsed.Contains(name, StringComparer.OrdinalIgnoreCase)) + { + writer.WriteNode(reader, false); + } + else + { + reader.Skip(); + } + } + } + } } - sb.Append(str.Substring(previousIndex)); - return sb.ToString(); + } + + public static StreamReader GetStreamReader(string path) + { + return new StreamReader(path, Encoding.UTF8); } } } diff --git a/MediaBrowser.XbmcMetadata/Savers/EpisodeNfoSaver.cs b/MediaBrowser.XbmcMetadata/Savers/EpisodeNfoSaver.cs new file mode 100644 index 0000000000..381faedf4a --- /dev/null +++ b/MediaBrowser.XbmcMetadata/Savers/EpisodeNfoSaver.cs @@ -0,0 +1,122 @@ +using MediaBrowser.Common.IO; +using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.TV; +using MediaBrowser.Controller.Library; +using MediaBrowser.XbmcMetadata.Configuration; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Xml; + +namespace MediaBrowser.XbmcMetadata.Savers +{ + public class EpisodeNfoSaver : BaseNfoSaver + { + public EpisodeNfoSaver(IFileSystem fileSystem, IServerConfigurationManager configurationManager, ILibraryManager libraryManager, IUserManager userManager, IUserDataManager userDataManager) + : base(fileSystem, configurationManager, libraryManager, userManager, userDataManager) + { + } + + public override string GetSavePath(IHasMetadata item) + { + return GetMovieSavePath(item); + } + + public static string GetMovieSavePath(IHasMetadata item) + { + return Path.ChangeExtension(item.Path, ".nfo"); + } + + protected override string GetRootElementName(IHasMetadata item) + { + return "episodedetails"; + } + + public override bool IsEnabledFor(IHasMetadata item, ItemUpdateType updateType) + { + if (!item.SupportsLocalMetadata) + { + return false; + } + + return item is Episode && updateType >= ItemUpdateType.MetadataDownload; + } + + protected override void WriteCustomElements(IHasMetadata item, XmlWriter writer) + { + var episode = (Episode)item; + + if (episode.IndexNumber.HasValue) + { + writer.WriteElementString("episode", episode.IndexNumber.Value.ToString(UsCulture)); + } + + if (episode.IndexNumberEnd.HasValue) + { + writer.WriteElementString("episodenumberend", episode.IndexNumberEnd.Value.ToString(UsCulture)); + } + + if (episode.ParentIndexNumber.HasValue) + { + writer.WriteElementString("season", episode.ParentIndexNumber.Value.ToString(UsCulture)); + } + + if (episode.PremiereDate.HasValue) + { + var formatString = ConfigurationManager.GetNfoConfiguration().ReleaseDateFormat; + + writer.WriteElementString("aired", episode.PremiereDate.Value.ToString(formatString)); + } + + if (episode.AirsAfterSeasonNumber.HasValue) + { + writer.WriteElementString("airsafter_season", episode.AirsAfterSeasonNumber.Value.ToString(UsCulture)); + } + if (episode.AirsBeforeEpisodeNumber.HasValue) + { + writer.WriteElementString("airsbefore_episode", episode.AirsBeforeEpisodeNumber.Value.ToString(UsCulture)); + } + if (episode.AirsBeforeSeasonNumber.HasValue) + { + writer.WriteElementString("airsbefore_season", episode.AirsBeforeSeasonNumber.Value.ToString(UsCulture)); + } + + if (episode.DvdEpisodeNumber.HasValue) + { + writer.WriteElementString("DVD_episodenumber", episode.DvdEpisodeNumber.Value.ToString(UsCulture)); + } + + if (episode.DvdSeasonNumber.HasValue) + { + writer.WriteElementString("DVD_season", episode.DvdSeasonNumber.Value.ToString(UsCulture)); + } + + if (episode.AbsoluteEpisodeNumber.HasValue) + { + writer.WriteElementString("absolute_number", episode.AbsoluteEpisodeNumber.Value.ToString(UsCulture)); + } + } + + private static readonly CultureInfo UsCulture = new CultureInfo("en-US"); + + protected override List<string> GetTagsUsed() + { + var list = new List<string> + { + "aired", + "season", + "episode", + "episodenumberend", + "airsafter_season", + "airsbefore_episode", + "airsbefore_season", + "DVD_episodenumber", + "DVD_season", + "absolute_number" + }; + + return list; + } + } +} diff --git a/MediaBrowser.XbmcMetadata/Savers/EpisodeXmlSaver.cs b/MediaBrowser.XbmcMetadata/Savers/EpisodeXmlSaver.cs deleted file mode 100644 index 1b5c24aad5..0000000000 --- a/MediaBrowser.XbmcMetadata/Savers/EpisodeXmlSaver.cs +++ /dev/null @@ -1,141 +0,0 @@ -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Security; -using System.Text; -using System.Threading; -using MediaBrowser.Common.IO; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Entities.TV; -using MediaBrowser.Controller.Library; -using MediaBrowser.Model.Entities; -using MediaBrowser.XbmcMetadata.Configuration; - -namespace MediaBrowser.XbmcMetadata.Savers -{ - public class EpisodeXmlSaver : IMetadataFileSaver - { - private readonly ILibraryManager _libraryManager; - private readonly IUserManager _userManager; - private readonly IUserDataManager _userDataRepo; - - private readonly CultureInfo _usCulture = new CultureInfo("en-US"); - - private readonly IFileSystem _fileSystem; - private readonly IServerConfigurationManager _config; - - public EpisodeXmlSaver(ILibraryManager libraryManager, IUserManager userManager, IUserDataManager userDataRepo, IFileSystem fileSystem, IServerConfigurationManager config) - { - _libraryManager = libraryManager; - _userManager = userManager; - _userDataRepo = userDataRepo; - _fileSystem = fileSystem; - _config = config; - } - - public string Name - { - get - { - return "Xbmc Nfo"; - } - } - - public string GetSavePath(IHasMetadata item) - { - return Path.ChangeExtension(item.Path, ".nfo"); - } - - public void Save(IHasMetadata item, CancellationToken cancellationToken) - { - var episode = (Episode)item; - - var builder = new StringBuilder(); - - builder.Append("<episodedetails>"); - - XmlSaverHelpers.AddCommonNodes(episode, builder, _libraryManager, _userManager, _userDataRepo, _fileSystem, _config); - - if (episode.IndexNumber.HasValue) - { - builder.Append("<episode>" + episode.IndexNumber.Value.ToString(_usCulture) + "</episode>"); - } - - if (episode.IndexNumberEnd.HasValue) - { - builder.Append("<episodenumberend>" + SecurityElement.Escape(episode.IndexNumberEnd.Value.ToString(_usCulture)) + "</episodenumberend>"); - } - - if (episode.ParentIndexNumber.HasValue) - { - builder.Append("<season>" + episode.ParentIndexNumber.Value.ToString(_usCulture) + "</season>"); - } - - if (episode.PremiereDate.HasValue) - { - var formatString = _config.GetNfoConfiguration().ReleaseDateFormat; - - builder.Append("<aired>" + SecurityElement.Escape(episode.PremiereDate.Value.ToString(formatString)) + "</aired>"); - } - - if (episode.AirsAfterSeasonNumber.HasValue) - { - builder.Append("<airsafter_season>" + SecurityElement.Escape(episode.AirsAfterSeasonNumber.Value.ToString(_usCulture)) + "</airsafter_season>"); - } - if (episode.AirsBeforeEpisodeNumber.HasValue) - { - builder.Append("<airsbefore_episode>" + SecurityElement.Escape(episode.AirsBeforeEpisodeNumber.Value.ToString(_usCulture)) + "</airsbefore_episode>"); - } - if (episode.AirsBeforeSeasonNumber.HasValue) - { - builder.Append("<airsbefore_season>" + SecurityElement.Escape(episode.AirsBeforeSeasonNumber.Value.ToString(_usCulture)) + "</airsbefore_season>"); - } - - if (episode.DvdEpisodeNumber.HasValue) - { - builder.Append("<DVD_episodenumber>" + SecurityElement.Escape(episode.DvdEpisodeNumber.Value.ToString(_usCulture)) + "</DVD_episodenumber>"); - } - - if (episode.DvdSeasonNumber.HasValue) - { - builder.Append("<DVD_season>" + SecurityElement.Escape(episode.DvdSeasonNumber.Value.ToString(_usCulture)) + "</DVD_season>"); - } - - if (episode.AbsoluteEpisodeNumber.HasValue) - { - builder.Append("<absolute_number>" + SecurityElement.Escape(episode.AbsoluteEpisodeNumber.Value.ToString(_usCulture)) + "</absolute_number>"); - } - - XmlSaverHelpers.AddMediaInfo((Episode)item, builder); - - builder.Append("</episodedetails>"); - - var xmlFilePath = GetSavePath(item); - - XmlSaverHelpers.Save(builder, xmlFilePath, new List<string> - { - "aired", - "season", - "episode", - "episodenumberend", - "airsafter_season", - "airsbefore_episode", - "airsbefore_season", - "DVD_episodenumber", - "DVD_season", - "absolute_number" - }); - } - - public bool IsEnabledFor(IHasMetadata item, ItemUpdateType updateType) - { - if (!item.SupportsLocalMetadata) - { - return false; - } - - return item is Episode && updateType >= ItemUpdateType.MetadataDownload; - } - } -} diff --git a/MediaBrowser.XbmcMetadata/Savers/MovieXmlSaver.cs b/MediaBrowser.XbmcMetadata/Savers/MovieNfoSaver.cs index fa2155e30a..9c8442e167 100644 --- a/MediaBrowser.XbmcMetadata/Savers/MovieXmlSaver.cs +++ b/MediaBrowser.XbmcMetadata/Savers/MovieNfoSaver.cs @@ -6,40 +6,20 @@ using MediaBrowser.Controller.Entities.TV; using MediaBrowser.Controller.Library; using MediaBrowser.Model.Entities; using System.Collections.Generic; +using System.Globalization; using System.IO; -using System.Security; -using System.Text; -using System.Threading; +using System.Xml; namespace MediaBrowser.XbmcMetadata.Savers { - public class MovieXmlSaver : IMetadataFileSaver + public class MovieNfoSaver : BaseNfoSaver { - private readonly ILibraryManager _libraryManager; - private readonly IUserManager _userManager; - private readonly IUserDataManager _userDataRepo; - - private readonly IFileSystem _fileSystem; - private readonly IServerConfigurationManager _config; - - public MovieXmlSaver(ILibraryManager libraryManager, IUserManager userManager, IUserDataManager userDataRepo, IFileSystem fileSystem, IServerConfigurationManager config) + public MovieNfoSaver(IFileSystem fileSystem, IServerConfigurationManager configurationManager, ILibraryManager libraryManager, IUserManager userManager, IUserDataManager userDataManager) + : base(fileSystem, configurationManager, libraryManager, userManager, userDataManager) { - _libraryManager = libraryManager; - _userManager = userManager; - _userDataRepo = userDataRepo; - _fileSystem = fileSystem; - _config = config; } - public string Name - { - get - { - return "Xbmc Nfo"; - } - } - - public string GetSavePath(IHasMetadata item) + public override string GetSavePath(IHasMetadata item) { return GetMovieSavePath(item); } @@ -58,23 +38,36 @@ namespace MediaBrowser.XbmcMetadata.Savers return Path.ChangeExtension(item.Path, ".nfo"); } - public void Save(IHasMetadata item, CancellationToken cancellationToken) + protected override string GetRootElementName(IHasMetadata item) { - var video = (Video)item; + return item is MusicVideo ? "musicvideo" : "movie"; + } - var builder = new StringBuilder(); + public override bool IsEnabledFor(IHasMetadata item, ItemUpdateType updateType) + { + if (!item.SupportsLocalMetadata) + { + return false; + } - var tag = item is MusicVideo ? "musicvideo" : "movie"; + var video = item as Video; - builder.Append("<" + tag + ">"); + // Check parent for null to avoid running this against things like video backdrops + if (video != null && !(item is Episode) && !video.IsOwnedItem) + { + return updateType >= ItemUpdateType.MetadataDownload; + } - XmlSaverHelpers.AddCommonNodes(video, builder, _libraryManager, _userManager, _userDataRepo, _fileSystem, _config); + return false; + } + protected override void WriteCustomElements(IHasMetadata item, XmlWriter writer) + { var imdb = item.GetProviderId(MetadataProviders.Imdb); if (!string.IsNullOrEmpty(imdb)) { - builder.Append("<id>" + SecurityElement.Escape(imdb) + "</id>"); + writer.WriteElementString("id", imdb); } var musicVideo = item as MusicVideo; @@ -83,11 +76,11 @@ namespace MediaBrowser.XbmcMetadata.Savers { if (!string.IsNullOrEmpty(musicVideo.Artist)) { - builder.Append("<artist>" + SecurityElement.Escape(musicVideo.Artist) + "</artist>"); + writer.WriteElementString("artist", musicVideo.Artist); } if (!string.IsNullOrEmpty(musicVideo.Album)) { - builder.Append("<album>" + SecurityElement.Escape(musicVideo.Album) + "</album>"); + writer.WriteElementString("album", musicVideo.Album); } } @@ -97,41 +90,24 @@ namespace MediaBrowser.XbmcMetadata.Savers { if (!string.IsNullOrEmpty(movie.TmdbCollectionName)) { - builder.Append("<set>" + SecurityElement.Escape(movie.TmdbCollectionName) + "</set>"); + writer.WriteElementString("set", movie.TmdbCollectionName); } } + } - XmlSaverHelpers.AddMediaInfo((Video)item, builder); - - builder.Append("</" + tag + ">"); - - var xmlFilePath = GetSavePath(item); + private static readonly CultureInfo UsCulture = new CultureInfo("en-US"); - XmlSaverHelpers.Save(builder, xmlFilePath, new List<string> - { + protected override List<string> GetTagsUsed() + { + var list = new List<string> + { "album", "artist", "set", "id" - }); - } + }; - public bool IsEnabledFor(IHasMetadata item, ItemUpdateType updateType) - { - if (!item.SupportsLocalMetadata) - { - return false; - } - - var video = item as Video; - - // Check parent for null to avoid running this against things like video backdrops - if (video != null && !(item is Episode) && !video.IsOwnedItem) - { - return updateType >= ItemUpdateType.MetadataDownload; - } - - return false; + return list; } } } diff --git a/MediaBrowser.XbmcMetadata/Savers/SeasonNfoSaver.cs b/MediaBrowser.XbmcMetadata/Savers/SeasonNfoSaver.cs new file mode 100644 index 0000000000..fd5819b3d2 --- /dev/null +++ b/MediaBrowser.XbmcMetadata/Savers/SeasonNfoSaver.cs @@ -0,0 +1,63 @@ +using MediaBrowser.Common.IO; +using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.TV; +using MediaBrowser.Controller.Library; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Xml; + +namespace MediaBrowser.XbmcMetadata.Savers +{ + public class SeasonNfoSaver : BaseNfoSaver + { + public SeasonNfoSaver(IFileSystem fileSystem, IServerConfigurationManager configurationManager, ILibraryManager libraryManager, IUserManager userManager, IUserDataManager userDataManager) : base(fileSystem, configurationManager, libraryManager, userManager, userDataManager) + { + } + + public override string GetSavePath(IHasMetadata item) + { + return Path.Combine(item.Path, "season.nfo"); + } + + protected override string GetRootElementName(IHasMetadata item) + { + return "season"; + } + + public override bool IsEnabledFor(IHasMetadata item, ItemUpdateType updateType) + { + if (!item.SupportsLocalMetadata) + { + return false; + } + + if (!(item is Season)) + { + return false; + } + + return updateType >= ItemUpdateType.MetadataDownload || (updateType >= ItemUpdateType.MetadataImport && File.Exists(GetSavePath(item))); + } + + protected override void WriteCustomElements(IHasMetadata item, XmlWriter writer) + { + var season = (Season)item; + + if (season.IndexNumber.HasValue) + { + writer.WriteElementString("seasonnumber", season.IndexNumber.Value.ToString(CultureInfo.InvariantCulture)); + } + } + + protected override List<string> GetTagsUsed() + { + var list = base.GetTagsUsed(); + + list.Add("seasonnumber"); + + return list; + } + } +} diff --git a/MediaBrowser.XbmcMetadata/Savers/SeasonXmlSaver.cs b/MediaBrowser.XbmcMetadata/Savers/SeasonXmlSaver.cs deleted file mode 100644 index a96b0636f2..0000000000 --- a/MediaBrowser.XbmcMetadata/Savers/SeasonXmlSaver.cs +++ /dev/null @@ -1,86 +0,0 @@ -using MediaBrowser.Common.IO; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Entities.TV; -using MediaBrowser.Controller.Library; -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Security; -using System.Text; -using System.Threading; - -namespace MediaBrowser.XbmcMetadata.Savers -{ - public class SeasonXmlSaver : IMetadataFileSaver - { - private readonly ILibraryManager _libraryManager; - private readonly IUserManager _userManager; - private readonly IUserDataManager _userDataRepo; - - private readonly IFileSystem _fileSystem; - private readonly IServerConfigurationManager _config; - - public SeasonXmlSaver(ILibraryManager libraryManager, IUserManager userManager, IUserDataManager userDataRepo, IFileSystem fileSystem, IServerConfigurationManager config) - { - _libraryManager = libraryManager; - _userManager = userManager; - _userDataRepo = userDataRepo; - _fileSystem = fileSystem; - _config = config; - } - - public string Name - { - get - { - return "Xbmc Nfo"; - } - } - - public string GetSavePath(IHasMetadata item) - { - return Path.Combine(item.Path, "season.nfo"); - } - - public void Save(IHasMetadata item, CancellationToken cancellationToken) - { - var builder = new StringBuilder(); - - builder.Append("<season>"); - - var season = (Season)item; - - if (season.IndexNumber.HasValue) - { - builder.Append("<seasonnumber>" + SecurityElement.Escape(season.IndexNumber.Value.ToString(CultureInfo.InvariantCulture)) + "</seasonnumber>"); - } - - XmlSaverHelpers.AddCommonNodes((Season)item, builder, _libraryManager, _userManager, _userDataRepo, _fileSystem, _config); - - builder.Append("</season>"); - - var xmlFilePath = GetSavePath(item); - - XmlSaverHelpers.Save(builder, xmlFilePath, new List<string> - { - "seasonnumber" - }); - } - - public bool IsEnabledFor(IHasMetadata item, ItemUpdateType updateType) - { - if (!item.SupportsLocalMetadata) - { - return false; - } - - if (!(item is Season)) - { - return false; - } - - return updateType >= ItemUpdateType.MetadataDownload || (updateType >= ItemUpdateType.MetadataImport && File.Exists(GetSavePath(item))); - } - } -} diff --git a/MediaBrowser.XbmcMetadata/Savers/SeriesNfoSaver.cs b/MediaBrowser.XbmcMetadata/Savers/SeriesNfoSaver.cs new file mode 100644 index 0000000000..473b5f46bb --- /dev/null +++ b/MediaBrowser.XbmcMetadata/Savers/SeriesNfoSaver.cs @@ -0,0 +1,113 @@ +using MediaBrowser.Common.IO; +using MediaBrowser.Controller.Configuration; +using MediaBrowser.Controller.Entities; +using MediaBrowser.Controller.Entities.TV; +using MediaBrowser.Controller.Library; +using MediaBrowser.Model.Entities; +using System.Collections.Generic; +using System.Globalization; +using System.IO; +using System.Xml; + +namespace MediaBrowser.XbmcMetadata.Savers +{ + public class SeriesNfoSaver : BaseNfoSaver + { + public SeriesNfoSaver(IFileSystem fileSystem, IServerConfigurationManager configurationManager, ILibraryManager libraryManager, IUserManager userManager, IUserDataManager userDataManager) + : base(fileSystem, configurationManager, libraryManager, userManager, userDataManager) + { + } + + public override string GetSavePath(IHasMetadata item) + { + return Path.Combine(item.Path, "tvshow.nfo"); + } + + protected override string GetRootElementName(IHasMetadata item) + { + return "tvshow"; + } + + public override bool IsEnabledFor(IHasMetadata item, ItemUpdateType updateType) + { + if (!item.SupportsLocalMetadata) + { + return false; + } + + return item is Series && updateType >= ItemUpdateType.MetadataDownload; + } + + protected override void WriteCustomElements(IHasMetadata item, XmlWriter writer) + { + var series = (Series)item; + + var tvdb = item.GetProviderId(MetadataProviders.Tvdb); + + if (!string.IsNullOrEmpty(tvdb)) + { + writer.WriteElementString("id", tvdb); + + writer.WriteStartElement("episodeguide"); + + var language = item.GetPreferredMetadataLanguage(); + language = string.IsNullOrEmpty(language) + ? "en" + : language; + + writer.WriteStartElement("url"); + writer.WriteAttributeString("cache", string.Format("{0}.xml", tvdb)); + writer.WriteString(string.Format("http://www.thetvdb.com/api/1D62F2F90030C444/series/{0}/all/{1}.zip", tvdb, language)); + writer.WriteEndElement(); + + writer.WriteEndElement(); + } + + writer.WriteElementString("season", "-1"); + writer.WriteElementString("episode", "-1"); + + if (series.Status.HasValue) + { + writer.WriteElementString("status", series.Status.Value.ToString()); + } + + if (!string.IsNullOrEmpty(series.AirTime)) + { + writer.WriteElementString("airs_time", series.AirTime); + } + + if (series.AirDays.Count == 7) + { + writer.WriteElementString("airs_dayofweek", "Daily"); + } + else if (series.AirDays.Count > 0) + { + writer.WriteElementString("airs_dayofweek", series.AirDays[0].ToString()); + } + + if (series.AnimeSeriesIndex.HasValue) + { + writer.WriteElementString("animeseriesindex", series.AnimeSeriesIndex.Value.ToString(CultureInfo.InvariantCulture)); + } + } + + private static readonly CultureInfo UsCulture = new CultureInfo("en-US"); + + protected override List<string> GetTagsUsed() + { + var list = new List<string> + { + "id", + "episodeguide", + "season", + "episode", + "status", + "airs_time", + "airs_dayofweek", + "animeseriesindex" + }; + + return list; + } + } +} diff --git a/MediaBrowser.XbmcMetadata/Savers/SeriesXmlSaver.cs b/MediaBrowser.XbmcMetadata/Savers/SeriesXmlSaver.cs deleted file mode 100644 index 94d46f61d3..0000000000 --- a/MediaBrowser.XbmcMetadata/Savers/SeriesXmlSaver.cs +++ /dev/null @@ -1,122 +0,0 @@ -using System.Collections.Generic; -using System.Globalization; -using System.IO; -using System.Security; -using System.Text; -using System.Threading; -using MediaBrowser.Common.IO; -using MediaBrowser.Controller.Configuration; -using MediaBrowser.Controller.Entities; -using MediaBrowser.Controller.Entities.TV; -using MediaBrowser.Controller.Library; -using MediaBrowser.Model.Entities; - -namespace MediaBrowser.XbmcMetadata.Savers -{ - public class SeriesXmlSaver : IMetadataFileSaver - { - private readonly ILibraryManager _libraryManager; - private readonly IUserManager _userManager; - private readonly IUserDataManager _userDataRepo; - - private readonly IFileSystem _fileSystem; - private readonly IServerConfigurationManager _config; - - public SeriesXmlSaver(IServerConfigurationManager config, ILibraryManager libraryManager, IUserManager userManager, IUserDataManager userDataRepo, IFileSystem fileSystem) - { - _config = config; - _libraryManager = libraryManager; - _userManager = userManager; - _userDataRepo = userDataRepo; - _fileSystem = fileSystem; - } - - public string Name - { - get - { - return "Xbmc Nfo"; - } - } - - public string GetSavePath(IHasMetadata item) - { - return Path.Combine(item.Path, "tvshow.nfo"); - } - - public void Save(IHasMetadata item, CancellationToken cancellationToken) - { - var series = (Series)item; - - var builder = new StringBuilder(); - - builder.Append("<tvshow>"); - - XmlSaverHelpers.AddCommonNodes(series, builder, _libraryManager, _userManager, _userDataRepo, _fileSystem, _config); - - var tvdb = item.GetProviderId(MetadataProviders.Tvdb); - - if (!string.IsNullOrEmpty(tvdb)) - { - builder.Append("<id>" + SecurityElement.Escape(tvdb) + "</id>"); - - builder.AppendFormat("<episodeguide><url cache=\"{0}.xml\">http://www.thetvdb.com/api/1D62F2F90030C444/series/{0}/all/{1}.zip</url></episodeguide>", - tvdb, - string.IsNullOrEmpty(_config.Configuration.PreferredMetadataLanguage) ? "en" : _config.Configuration.PreferredMetadataLanguage); - } - - builder.Append("<season>-1</season>"); - builder.Append("<episode>-1</episode>"); - - if (series.Status.HasValue) - { - builder.Append("<status>" + SecurityElement.Escape(series.Status.Value.ToString()) + "</status>"); - } - - if (!string.IsNullOrEmpty(series.AirTime)) - { - builder.Append("<airs_time>" + SecurityElement.Escape(series.AirTime) + "</airs_time>"); - } - - if (series.AirDays.Count == 7) - { - builder.Append("<airs_dayofweek>" + SecurityElement.Escape("Daily") + "</airs_dayofweek>"); - } - else if (series.AirDays.Count > 0) - { - builder.Append("<airs_dayofweek>" + SecurityElement.Escape(series.AirDays[0].ToString()) + "</airs_dayofweek>"); - } - - if (series.AnimeSeriesIndex.HasValue) - { - builder.Append("<animeseriesindex>" + SecurityElement.Escape(series.AnimeSeriesIndex.Value.ToString(CultureInfo.InvariantCulture)) + "</animeseriesindex>"); - } - - builder.Append("</tvshow>"); - - var xmlFilePath = GetSavePath(item); - - XmlSaverHelpers.Save(builder, xmlFilePath, new List<string> - { - "id", - "episodeguide", - "season", - "episode", - "status", - "airs_time", - "airs_dayofweek", - "animeseriesindex" - }); - } - - public bool IsEnabledFor(IHasMetadata item, ItemUpdateType updateType) - { - if (!item.SupportsLocalMetadata) - { - return false; - } - - return item is Series && updateType >= ItemUpdateType.MetadataDownload; - } - } -} |
