begin work on daily episodes
This commit is contained in:
parent
fef1d16cec
commit
42b1416602
|
@ -3,6 +3,7 @@ using MediaBrowser.Controller.Entities;
|
|||
using MediaBrowser.Controller.Entities.Audio;
|
||||
using MediaBrowser.Controller.Entities.TV;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Controller.LiveTv;
|
||||
using MediaBrowser.Controller.Localization;
|
||||
using MediaBrowser.Controller.Net;
|
||||
using MediaBrowser.Controller.Providers;
|
||||
|
@ -73,7 +74,7 @@ namespace MediaBrowser.Api
|
|||
if (locationType == LocationType.FileSystem ||
|
||||
locationType == LocationType.Offline)
|
||||
{
|
||||
if (!(item is ICollectionFolder) && !(item is UserView) && !(item is AggregateFolder))
|
||||
if (!(item is ICollectionFolder) && !(item is UserView) && !(item is AggregateFolder) && !(item is LiveTvChannel) && !(item is IItemByName))
|
||||
{
|
||||
var collectionType = _libraryManager.GetInheritedContentType(item);
|
||||
if (string.IsNullOrWhiteSpace(collectionType))
|
||||
|
|
|
@ -223,6 +223,10 @@ namespace MediaBrowser.Common.Implementations.Configuration
|
|||
{
|
||||
return Activator.CreateInstance(configurationType);
|
||||
}
|
||||
catch (DirectoryNotFoundException)
|
||||
{
|
||||
return Activator.CreateInstance(configurationType);
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
Logger.ErrorException("Error loading configuration file: {0}", ex, path);
|
||||
|
|
|
@ -38,7 +38,10 @@ namespace MediaBrowser.Common.Implementations.Devices
|
|||
_logger.Error("Invalid value found in device id file");
|
||||
}
|
||||
}
|
||||
catch (FileNotFoundException ex)
|
||||
catch (DirectoryNotFoundException)
|
||||
{
|
||||
}
|
||||
catch (FileNotFoundException)
|
||||
{
|
||||
}
|
||||
catch (Exception ex)
|
||||
|
|
|
@ -101,6 +101,10 @@ namespace MediaBrowser.Common.Implementations.Security
|
|||
{
|
||||
contents = File.ReadAllLines(licenseFile);
|
||||
}
|
||||
catch (DirectoryNotFoundException)
|
||||
{
|
||||
(File.Create(licenseFile)).Close();
|
||||
}
|
||||
catch (FileNotFoundException)
|
||||
{
|
||||
(File.Create(licenseFile)).Close();
|
||||
|
|
|
@ -1,4 +1,6 @@
|
|||
using System;
|
||||
using System.Globalization;
|
||||
using System.Linq;
|
||||
using System.Security.Cryptography;
|
||||
using System.Text;
|
||||
using System.Text.RegularExpressions;
|
||||
|
@ -54,6 +56,15 @@ namespace MediaBrowser.Common.Extensions
|
|||
return sb.ToString();
|
||||
}
|
||||
|
||||
public static string RemoveDiacritics(this string text)
|
||||
{
|
||||
return String.Concat(
|
||||
text.Normalize(NormalizationForm.FormD)
|
||||
.Where(ch => CharUnicodeInfo.GetUnicodeCategory(ch) !=
|
||||
UnicodeCategory.NonSpacingMark)
|
||||
).Normalize(NormalizationForm.FormC);
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Gets the M d5.
|
||||
/// </summary>
|
||||
|
|
|
@ -204,6 +204,10 @@ namespace MediaBrowser.Common.Plugins
|
|||
{
|
||||
return (TConfigurationType)XmlSerializer.DeserializeFromFile(typeof(TConfigurationType), path);
|
||||
}
|
||||
catch (DirectoryNotFoundException)
|
||||
{
|
||||
return (TConfigurationType)Activator.CreateInstance(typeof(TConfigurationType));
|
||||
}
|
||||
catch (FileNotFoundException)
|
||||
{
|
||||
return (TConfigurationType)Activator.CreateInstance(typeof(TConfigurationType));
|
||||
|
|
|
@ -1,11 +1,11 @@
|
|||
using MediaBrowser.Controller.Providers;
|
||||
using MediaBrowser.Model.Configuration;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Model.Users;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.Serialization;
|
||||
using MediaBrowser.Model.Users;
|
||||
|
||||
namespace MediaBrowser.Controller.Entities.TV
|
||||
{
|
||||
|
@ -178,6 +178,15 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||
}
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public bool IsInSeasonFolder
|
||||
{
|
||||
get
|
||||
{
|
||||
return FindParent<Season>() != null;
|
||||
}
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public string SeriesName
|
||||
{
|
||||
|
|
|
@ -1,13 +1,12 @@
|
|||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Controller.Localization;
|
||||
using MediaBrowser.Controller.Localization;
|
||||
using MediaBrowser.Controller.Providers;
|
||||
using MediaBrowser.Model.Configuration;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Model.Querying;
|
||||
using MediaBrowser.Model.Users;
|
||||
using MoreLinq;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Runtime.Serialization;
|
||||
using MediaBrowser.Model.Users;
|
||||
|
||||
namespace MediaBrowser.Controller.Entities.TV
|
||||
{
|
||||
|
@ -156,24 +155,6 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||
return IndexNumber != null ? IndexNumber.Value.ToString("0000") : Name;
|
||||
}
|
||||
|
||||
private IEnumerable<Episode> GetEpisodes()
|
||||
{
|
||||
var series = Series;
|
||||
|
||||
if (series != null && series.ContainsEpisodesWithoutSeasonFolders)
|
||||
{
|
||||
var seasonNumber = IndexNumber;
|
||||
|
||||
if (seasonNumber.HasValue)
|
||||
{
|
||||
return series.RecursiveChildren.OfType<Episode>()
|
||||
.Where(i => i.ParentIndexNumber.HasValue && i.ParentIndexNumber.Value == seasonNumber.Value);
|
||||
}
|
||||
}
|
||||
|
||||
return Children.OfType<Episode>();
|
||||
}
|
||||
|
||||
[IgnoreDataMember]
|
||||
public bool IsMissingSeason
|
||||
{
|
||||
|
@ -221,16 +202,32 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||
var episodes = GetRecursiveChildren(user)
|
||||
.OfType<Episode>();
|
||||
|
||||
if (IndexNumber.HasValue)
|
||||
{
|
||||
var series = Series;
|
||||
var series = Series;
|
||||
|
||||
if (series != null)
|
||||
{
|
||||
return series.GetEpisodes(user, IndexNumber.Value, includeMissingEpisodes, includeVirtualUnairedEpisodes, episodes);
|
||||
}
|
||||
if (IndexNumber.HasValue && series != null)
|
||||
{
|
||||
return series.GetEpisodes(user, IndexNumber.Value, includeMissingEpisodes, includeVirtualUnairedEpisodes, episodes);
|
||||
}
|
||||
|
||||
if (series != null && series.ContainsEpisodesWithoutSeasonFolders)
|
||||
{
|
||||
var seasonNumber = IndexNumber;
|
||||
var list = episodes.ToList();
|
||||
|
||||
if (seasonNumber.HasValue)
|
||||
{
|
||||
list.AddRange(series.GetRecursiveChildren(user).OfType<Episode>()
|
||||
.Where(i => i.ParentIndexNumber.HasValue && i.ParentIndexNumber.Value == seasonNumber.Value));
|
||||
}
|
||||
else
|
||||
{
|
||||
list.AddRange(series.GetRecursiveChildren(user).OfType<Episode>()
|
||||
.Where(i => !i.ParentIndexNumber.HasValue));
|
||||
}
|
||||
|
||||
episodes = list.DistinctBy(i => i.Id);
|
||||
}
|
||||
|
||||
if (!includeMissingEpisodes)
|
||||
{
|
||||
episodes = episodes.Where(i => !i.IsMissingEpisode);
|
||||
|
@ -245,6 +242,33 @@ namespace MediaBrowser.Controller.Entities.TV
|
|||
.Cast<Episode>();
|
||||
}
|
||||
|
||||
private IEnumerable<Episode> GetEpisodes()
|
||||
{
|
||||
var episodes = RecursiveChildren.OfType<Episode>();
|
||||
var series = Series;
|
||||
|
||||
if (series != null && series.ContainsEpisodesWithoutSeasonFolders)
|
||||
{
|
||||
var seasonNumber = IndexNumber;
|
||||
var list = episodes.ToList();
|
||||
|
||||
if (seasonNumber.HasValue)
|
||||
{
|
||||
list.AddRange(series.RecursiveChildren.OfType<Episode>()
|
||||
.Where(i => i.ParentIndexNumber.HasValue && i.ParentIndexNumber.Value == seasonNumber.Value));
|
||||
}
|
||||
else
|
||||
{
|
||||
list.AddRange(series.RecursiveChildren.OfType<Episode>()
|
||||
.Where(i => !i.ParentIndexNumber.HasValue));
|
||||
}
|
||||
|
||||
episodes = list.DistinctBy(i => i.Id);
|
||||
}
|
||||
|
||||
return episodes;
|
||||
}
|
||||
|
||||
public override IEnumerable<BaseItem> GetChildren(User user, bool includeLinkedChildren)
|
||||
{
|
||||
return GetEpisodes(user);
|
||||
|
|
|
@ -186,5 +186,12 @@ namespace MediaBrowser.Controller.Library
|
|||
/// <param name="userId">The user identifier.</param>
|
||||
/// <param name="userPolicy">The user policy.</param>
|
||||
Task UpdateUserPolicy(string userId, UserPolicy userPolicy);
|
||||
|
||||
/// <summary>
|
||||
/// Makes the valid username.
|
||||
/// </summary>
|
||||
/// <param name="username">The username.</param>
|
||||
/// <returns>System.String.</returns>
|
||||
string MakeValidUsername(string username);
|
||||
}
|
||||
}
|
||||
|
|
|
@ -28,8 +28,6 @@ namespace MediaBrowser.LocalMetadata
|
|||
|
||||
var path = file.FullName;
|
||||
|
||||
//await XmlProviderUtils.XmlParsingResourcePool.WaitAsync(cancellationToken).ConfigureAwait(false);
|
||||
|
||||
try
|
||||
{
|
||||
result.Item = new T();
|
||||
|
@ -45,10 +43,6 @@ namespace MediaBrowser.LocalMetadata
|
|||
{
|
||||
result.HasMetadata = false;
|
||||
}
|
||||
finally
|
||||
{
|
||||
//XmlProviderUtils.XmlParsingResourcePool.Release();
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
|
|
@ -612,6 +612,10 @@ namespace MediaBrowser.MediaEncoding.Subtitles
|
|||
catch (FileNotFoundException)
|
||||
{
|
||||
|
||||
}
|
||||
catch (DirectoryNotFoundException)
|
||||
{
|
||||
|
||||
}
|
||||
catch (IOException ex)
|
||||
{
|
||||
|
|
|
@ -505,15 +505,6 @@ namespace MediaBrowser.Model.ApiClient
|
|||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task<PublicSystemInfo>.</returns>
|
||||
Task<PublicSystemInfo> GetPublicSystemInfoAsync(CancellationToken cancellationToken = default(CancellationToken));
|
||||
|
||||
/// <summary>
|
||||
/// Gets a person
|
||||
/// </summary>
|
||||
/// <param name="name">The name.</param>
|
||||
/// <param name="userId">The user id.</param>
|
||||
/// <returns>Task{BaseItemDto}.</returns>
|
||||
/// <exception cref="ArgumentNullException">userId</exception>
|
||||
Task<BaseItemDto> GetPersonAsync(string name, string userId);
|
||||
|
||||
/// <summary>
|
||||
/// Gets a list of plugins installed on the server
|
||||
|
@ -967,15 +958,6 @@ namespace MediaBrowser.Model.ApiClient
|
|||
/// <exception cref="ArgumentNullException">item</exception>
|
||||
string GetPersonImageUrl(BaseItemPerson item, ImageOptions options);
|
||||
|
||||
/// <summary>
|
||||
/// Gets an image url that can be used to download an image from the api
|
||||
/// </summary>
|
||||
/// <param name="name">The name of the person</param>
|
||||
/// <param name="options">The options.</param>
|
||||
/// <returns>System.String.</returns>
|
||||
/// <exception cref="ArgumentNullException">name</exception>
|
||||
string GetPersonImageUrl(string name, ImageOptions options);
|
||||
|
||||
/// <summary>
|
||||
/// Gets an image url that can be used to download an image from the api
|
||||
/// </summary>
|
||||
|
|
|
@ -106,6 +106,10 @@ namespace MediaBrowser.Providers.Movies
|
|||
{
|
||||
// No biggie. Don't blow up
|
||||
}
|
||||
catch (DirectoryNotFoundException)
|
||||
{
|
||||
// No biggie. Don't blow up
|
||||
}
|
||||
}
|
||||
|
||||
var language = item.GetPreferredMetadataLanguage();
|
||||
|
|
|
@ -82,6 +82,10 @@ namespace MediaBrowser.Providers.Music
|
|||
catch (FileNotFoundException)
|
||||
{
|
||||
|
||||
}
|
||||
catch (DirectoryNotFoundException)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -90,6 +90,10 @@ namespace MediaBrowser.Providers.Music
|
|||
catch (FileNotFoundException)
|
||||
{
|
||||
|
||||
}
|
||||
catch (DirectoryNotFoundException)
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -83,6 +83,10 @@ namespace MediaBrowser.Providers.People
|
|||
{
|
||||
return null;
|
||||
}
|
||||
catch (DirectoryNotFoundException)
|
||||
{
|
||||
return null;
|
||||
}
|
||||
}
|
||||
|
||||
private RemoteImageInfo GetImageInfo(string xmlFile, string personName, CancellationToken cancellationToken)
|
||||
|
|
|
@ -98,6 +98,10 @@ namespace MediaBrowser.Providers.TV
|
|||
{
|
||||
// No biggie. Don't blow up
|
||||
}
|
||||
catch (DirectoryNotFoundException)
|
||||
{
|
||||
// No biggie. Don't blow up
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -106,6 +106,10 @@ namespace MediaBrowser.Providers.TV
|
|||
{
|
||||
// No biggie. Don't blow up
|
||||
}
|
||||
catch (DirectoryNotFoundException)
|
||||
{
|
||||
// No biggie. Don't blow up
|
||||
}
|
||||
}
|
||||
|
||||
var language = item.GetPreferredMetadataLanguage();
|
||||
|
|
|
@ -2,6 +2,7 @@
|
|||
using MediaBrowser.Controller.Configuration;
|
||||
using MediaBrowser.Controller.Entities.TV;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Controller.Localization;
|
||||
using MediaBrowser.Controller.Providers;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Model.Logging;
|
||||
|
@ -22,14 +23,16 @@ namespace MediaBrowser.Providers.TV
|
|||
private readonly IServerConfigurationManager _config;
|
||||
private readonly ILogger _logger;
|
||||
private readonly ILibraryManager _libraryManager;
|
||||
private readonly ILocalizationManager _localization;
|
||||
|
||||
private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
|
||||
|
||||
public MissingEpisodeProvider(ILogger logger, IServerConfigurationManager config, ILibraryManager libraryManager)
|
||||
public MissingEpisodeProvider(ILogger logger, IServerConfigurationManager config, ILibraryManager libraryManager, ILocalizationManager localization)
|
||||
{
|
||||
_logger = logger;
|
||||
_config = config;
|
||||
_libraryManager = libraryManager;
|
||||
_localization = localization;
|
||||
}
|
||||
|
||||
public async Task Run(IEnumerable<IGrouping<string, Series>> series, CancellationToken cancellationToken)
|
||||
|
@ -93,16 +96,16 @@ namespace MediaBrowser.Providers.TV
|
|||
|
||||
var hasBadData = HasInvalidContent(group);
|
||||
|
||||
var anySeasonsRemoved = await RemoveObsoleteOrMissingSeasons(group, episodeLookup, false)
|
||||
var anySeasonsRemoved = await RemoveObsoleteOrMissingSeasons(group, episodeLookup)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
var anyEpisodesRemoved = await RemoveObsoleteOrMissingEpisodes(group, episodeLookup, false)
|
||||
var anyEpisodesRemoved = await RemoveObsoleteOrMissingEpisodes(group, episodeLookup)
|
||||
.ConfigureAwait(false);
|
||||
|
||||
var hasNewEpisodes = false;
|
||||
var hasNewSeasons = false;
|
||||
|
||||
foreach (var series in group.Where(s => s.ContainsEpisodesWithoutSeasonFolders))
|
||||
foreach (var series in group)
|
||||
{
|
||||
hasNewSeasons = await AddDummySeasonFolders(series, cancellationToken).ConfigureAwait(false);
|
||||
}
|
||||
|
@ -165,14 +168,15 @@ namespace MediaBrowser.Providers.TV
|
|||
/// <returns></returns>
|
||||
private async Task<bool> AddDummySeasonFolders(Series series, CancellationToken cancellationToken)
|
||||
{
|
||||
var existingEpisodes = series.RecursiveChildren
|
||||
var episodesInSeriesFolder = series.RecursiveChildren
|
||||
.OfType<Episode>()
|
||||
.Where(i => !i.IsInSeasonFolder)
|
||||
.ToList();
|
||||
|
||||
var hasChanges = false;
|
||||
|
||||
// Loop through the unique season numbers
|
||||
foreach (var seasonNumber in existingEpisodes.Select(i => i.ParentIndexNumber ?? -1)
|
||||
foreach (var seasonNumber in episodesInSeriesFolder.Select(i => i.ParentIndexNumber ?? -1)
|
||||
.Where(i => i >= 0)
|
||||
.Distinct()
|
||||
.ToList())
|
||||
|
@ -188,6 +192,20 @@ namespace MediaBrowser.Providers.TV
|
|||
}
|
||||
}
|
||||
|
||||
// Unknown season - create a dummy season to put these under
|
||||
if (episodesInSeriesFolder.Any(i => !i.ParentIndexNumber.HasValue))
|
||||
{
|
||||
var hasSeason = series.Children.OfType<Season>()
|
||||
.Any(i => !i.IndexNumber.HasValue);
|
||||
|
||||
if (!hasSeason)
|
||||
{
|
||||
await AddSeason(series, null, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
hasChanges = true;
|
||||
}
|
||||
}
|
||||
|
||||
return hasChanges;
|
||||
}
|
||||
|
||||
|
@ -292,8 +310,7 @@ namespace MediaBrowser.Providers.TV
|
|||
/// Removes the virtual entry after a corresponding physical version has been added
|
||||
/// </summary>
|
||||
private async Task<bool> RemoveObsoleteOrMissingEpisodes(IEnumerable<Series> series,
|
||||
IEnumerable<Tuple<int, int>> episodeLookup,
|
||||
bool forceRemoveAll)
|
||||
IEnumerable<Tuple<int, int>> episodeLookup)
|
||||
{
|
||||
var existingEpisodes = (from s in series
|
||||
let seasonOffset = TvdbSeriesProvider.GetSeriesOffset(s.ProviderIds) ?? ((s.AnimeSeriesIndex ?? 1) - 1)
|
||||
|
@ -312,11 +329,6 @@ namespace MediaBrowser.Providers.TV
|
|||
var episodesToRemove = virtualEpisodes
|
||||
.Where(i =>
|
||||
{
|
||||
if (forceRemoveAll)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (i.Episode.IndexNumber.HasValue && i.Episode.ParentIndexNumber.HasValue)
|
||||
{
|
||||
var seasonNumber = i.Episode.ParentIndexNumber.Value + i.SeasonOffset;
|
||||
|
@ -362,11 +374,9 @@ namespace MediaBrowser.Providers.TV
|
|||
/// </summary>
|
||||
/// <param name="series">The series.</param>
|
||||
/// <param name="episodeLookup">The episode lookup.</param>
|
||||
/// <param name="forceRemoveAll">if set to <c>true</c> [force remove all].</param>
|
||||
/// <returns>Task{System.Boolean}.</returns>
|
||||
private async Task<bool> RemoveObsoleteOrMissingSeasons(IEnumerable<Series> series,
|
||||
IEnumerable<Tuple<int, int>> episodeLookup,
|
||||
bool forceRemoveAll)
|
||||
IEnumerable<Tuple<int, int>> episodeLookup)
|
||||
{
|
||||
var existingSeasons = (from s in series
|
||||
let seasonOffset = TvdbSeriesProvider.GetSeriesOffset(s.ProviderIds) ?? ((s.AnimeSeriesIndex ?? 1) - 1)
|
||||
|
@ -385,11 +395,6 @@ namespace MediaBrowser.Providers.TV
|
|||
var seasonsToRemove = virtualSeasons
|
||||
.Where(i =>
|
||||
{
|
||||
if (forceRemoveAll)
|
||||
{
|
||||
return true;
|
||||
}
|
||||
|
||||
if (i.Season.IndexNumber.HasValue)
|
||||
{
|
||||
var seasonNumber = i.Season.IndexNumber.Value + i.SeasonOffset;
|
||||
|
@ -409,7 +414,9 @@ namespace MediaBrowser.Providers.TV
|
|||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
// Season does not have a number
|
||||
// Remove if there are no episodes directly in series without a season number
|
||||
return i.Season.Series.RecursiveChildren.OfType<Episode>().All(s => s.ParentIndexNumber.HasValue || s.IsInSeasonFolder);
|
||||
})
|
||||
.ToList();
|
||||
|
||||
|
@ -472,20 +479,22 @@ namespace MediaBrowser.Providers.TV
|
|||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task{Season}.</returns>
|
||||
private async Task<Season> AddSeason(Series series,
|
||||
int seasonNumber,
|
||||
int? seasonNumber,
|
||||
CancellationToken cancellationToken)
|
||||
{
|
||||
_logger.Info("Creating Season {0} entry for {1}", seasonNumber, series.Name);
|
||||
var seasonName = seasonNumber == 0 ?
|
||||
_config.Configuration.SeasonZeroDisplayName :
|
||||
(seasonNumber.HasValue ? string.Format(_localization.GetLocalizedString("NameSeasonNumber"), seasonNumber.Value.ToString(UsCulture)) : _localization.GetLocalizedString("NameSeasonUnknown"));
|
||||
|
||||
var name = seasonNumber == 0 ? _config.Configuration.SeasonZeroDisplayName : string.Format("Season {0}", seasonNumber.ToString(UsCulture));
|
||||
_logger.Info("Creating Season {0} entry for {1}", seasonName, series.Name);
|
||||
|
||||
var season = new Season
|
||||
{
|
||||
Name = name,
|
||||
Name = seasonName,
|
||||
IndexNumber = seasonNumber,
|
||||
Parent = series,
|
||||
DisplayMediaType = typeof(Season).Name,
|
||||
Id = (series.Id + seasonNumber.ToString(UsCulture) + name).GetMBId(typeof(Season))
|
||||
Id = (series.Id + (seasonNumber ?? -1).ToString(UsCulture) + seasonName).GetMBId(typeof(Season))
|
||||
};
|
||||
|
||||
await series.AddChild(season, cancellationToken).ConfigureAwait(false);
|
||||
|
|
|
@ -1,11 +1,12 @@
|
|||
using System.Collections.Generic;
|
||||
using MediaBrowser.Controller.Configuration;
|
||||
using MediaBrowser.Controller.Configuration;
|
||||
using MediaBrowser.Controller.Entities.TV;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Controller.Localization;
|
||||
using MediaBrowser.Controller.Providers;
|
||||
using MediaBrowser.Model.Entities;
|
||||
using MediaBrowser.Model.Logging;
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Threading;
|
||||
using System.Threading.Tasks;
|
||||
|
@ -25,12 +26,14 @@ namespace MediaBrowser.Providers.TV
|
|||
private readonly ILibraryManager _libraryManager;
|
||||
private readonly IServerConfigurationManager _config;
|
||||
private readonly ILogger _logger;
|
||||
private readonly ILocalizationManager _localization;
|
||||
|
||||
public SeriesPostScanTask(ILibraryManager libraryManager, ILogger logger, IServerConfigurationManager config)
|
||||
public SeriesPostScanTask(ILibraryManager libraryManager, ILogger logger, IServerConfigurationManager config, ILocalizationManager localization)
|
||||
{
|
||||
_libraryManager = libraryManager;
|
||||
_logger = logger;
|
||||
_config = config;
|
||||
_localization = localization;
|
||||
}
|
||||
|
||||
public Task Run(IProgress<double> progress, CancellationToken cancellationToken)
|
||||
|
@ -47,7 +50,7 @@ namespace MediaBrowser.Providers.TV
|
|||
|
||||
var seriesGroups = FindSeriesGroups(seriesList).Where(g => !string.IsNullOrEmpty(g.Key)).ToList();
|
||||
|
||||
await new MissingEpisodeProvider(_logger, _config, _libraryManager).Run(seriesGroups, cancellationToken).ConfigureAwait(false);
|
||||
await new MissingEpisodeProvider(_logger, _config, _libraryManager, _localization).Run(seriesGroups, cancellationToken).ConfigureAwait(false);
|
||||
|
||||
var numComplete = 0;
|
||||
|
||||
|
|
|
@ -72,6 +72,10 @@ namespace MediaBrowser.Providers.TV
|
|||
{
|
||||
// Don't fail the provider because this will just keep on going and going.
|
||||
}
|
||||
catch (DirectoryNotFoundException)
|
||||
{
|
||||
// Don't fail the provider because this will just keep on going and going.
|
||||
}
|
||||
}
|
||||
|
||||
return list;
|
||||
|
@ -101,6 +105,10 @@ namespace MediaBrowser.Providers.TV
|
|||
{
|
||||
// Don't fail the provider because this will just keep on going and going.
|
||||
}
|
||||
catch (DirectoryNotFoundException)
|
||||
{
|
||||
// Don't fail the provider because this will just keep on going and going.
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
|
@ -208,8 +216,9 @@ namespace MediaBrowser.Providers.TV
|
|||
/// Fetches the episode data.
|
||||
/// </summary>
|
||||
/// <param name="id">The identifier.</param>
|
||||
/// <param name="identity">The identity.</param>
|
||||
/// <param name="seriesDataPath">The series data path.</param>
|
||||
/// <param name="seriesProviderIds"></param>
|
||||
/// <param name="seriesProviderIds">The series provider ids.</param>
|
||||
/// <param name="cancellationToken">The cancellation token.</param>
|
||||
/// <returns>Task{System.Boolean}.</returns>
|
||||
private Episode FetchEpisodeData(EpisodeInfo id, EpisodeIdentity identity, string seriesDataPath, Dictionary<string, string> seriesProviderIds, CancellationToken cancellationToken)
|
||||
|
@ -279,6 +288,10 @@ namespace MediaBrowser.Providers.TV
|
|||
{
|
||||
break;
|
||||
}
|
||||
catch (DirectoryNotFoundException)
|
||||
{
|
||||
break;
|
||||
}
|
||||
|
||||
episodeNumber++;
|
||||
}
|
||||
|
|
|
@ -94,6 +94,10 @@ namespace MediaBrowser.Providers.TV
|
|||
{
|
||||
// No tvdb data yet. Don't blow up
|
||||
}
|
||||
catch (DirectoryNotFoundException)
|
||||
{
|
||||
// No tvdb data yet. Don't blow up
|
||||
}
|
||||
}
|
||||
|
||||
return new RemoteImageInfo[] { };
|
||||
|
|
|
@ -87,6 +87,10 @@ namespace MediaBrowser.Providers.TV
|
|||
{
|
||||
// No tvdb data yet. Don't blow up
|
||||
}
|
||||
catch (DirectoryNotFoundException)
|
||||
{
|
||||
// No tvdb data yet. Don't blow up
|
||||
}
|
||||
}
|
||||
|
||||
return new RemoteImageInfo[] { };
|
||||
|
|
|
@ -1,4 +1,5 @@
|
|||
using MediaBrowser.Common.Configuration;
|
||||
using MediaBrowser.Common.Extensions;
|
||||
using MediaBrowser.Common.Net;
|
||||
using MediaBrowser.Controller;
|
||||
using MediaBrowser.Controller.Configuration;
|
||||
|
@ -789,7 +790,7 @@ namespace MediaBrowser.Server.Implementations.Connect
|
|||
if (user == null)
|
||||
{
|
||||
// Add user
|
||||
user = await _userManager.CreateUser(connectEntry.UserName).ConfigureAwait(false);
|
||||
user = await _userManager.CreateUser(_userManager.MakeValidUsername(connectEntry.UserName)).ConfigureAwait(false);
|
||||
|
||||
user.ConnectUserName = connectEntry.UserName;
|
||||
user.ConnectUserId = connectEntry.UserId;
|
||||
|
|
|
@ -78,6 +78,11 @@ namespace MediaBrowser.Server.Implementations.Drawing
|
|||
// No biggie
|
||||
sizeDictionary = new Dictionary<Guid, ImageSize>();
|
||||
}
|
||||
catch (DirectoryNotFoundException)
|
||||
{
|
||||
// No biggie
|
||||
sizeDictionary = new Dictionary<Guid, ImageSize>();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
logger.ErrorException("Error parsing image size cache file", ex);
|
||||
|
|
|
@ -459,11 +459,11 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
|
|||
|
||||
private bool IsSameEpisode(string sourcePath, string newPath)
|
||||
{
|
||||
var sourceFileInfo = new FileInfo(sourcePath);
|
||||
var destinationFileInfo = new FileInfo(newPath);
|
||||
|
||||
try
|
||||
{
|
||||
var sourceFileInfo = new FileInfo(sourcePath);
|
||||
var destinationFileInfo = new FileInfo(newPath);
|
||||
|
||||
if (sourceFileInfo.Length == destinationFileInfo.Length)
|
||||
{
|
||||
return true;
|
||||
|
@ -473,6 +473,10 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
|
|||
{
|
||||
return false;
|
||||
}
|
||||
catch (DirectoryNotFoundException)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
return false;
|
||||
}
|
||||
|
|
|
@ -1755,9 +1755,12 @@ namespace MediaBrowser.Server.Implementations.Library
|
|||
var resolver = new EpisodeResolver(new ExtendedNamingOptions(),
|
||||
new Naming.Logging.NullLogger());
|
||||
|
||||
var fileType = episode.VideoType == VideoType.BluRay || episode.VideoType == VideoType.Dvd || episode.VideoType == VideoType.HdDvd ?
|
||||
FileInfoType.Directory :
|
||||
FileInfoType.File;
|
||||
|
||||
var locationType = episode.LocationType;
|
||||
|
||||
var fileType = /*args.IsDirectory ? FileInfoType.Directory :*/ FileInfoType.File;
|
||||
var episodeInfo = locationType == LocationType.FileSystem || locationType == LocationType.Offline ?
|
||||
resolver.Resolve(episode.Path, fileType) :
|
||||
new Naming.TV.EpisodeInfo();
|
||||
|
@ -1769,29 +1772,42 @@ namespace MediaBrowser.Server.Implementations.Library
|
|||
|
||||
var changed = false;
|
||||
|
||||
if (!episode.IndexNumber.HasValue)
|
||||
if (episodeInfo.IsByDate)
|
||||
{
|
||||
episode.IndexNumber = episodeInfo.EpisodeNumber;
|
||||
|
||||
if (episode.IndexNumber.HasValue)
|
||||
{
|
||||
episode.IndexNumber = null;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!episode.IndexNumberEnd.HasValue)
|
||||
{
|
||||
episode.IndexNumberEnd = episodeInfo.EndingEpsiodeNumber;
|
||||
|
||||
if (episode.IndexNumberEnd.HasValue)
|
||||
{
|
||||
episode.IndexNumberEnd = null;
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!episode.ParentIndexNumber.HasValue)
|
||||
{
|
||||
episode.ParentIndexNumber = episodeInfo.SeasonNumber;
|
||||
if (!episode.PremiereDate.HasValue)
|
||||
{
|
||||
if (episodeInfo.Year.HasValue && episodeInfo.Month.HasValue && episodeInfo.Day.HasValue)
|
||||
{
|
||||
episode.PremiereDate = new DateTime(episodeInfo.Year.Value, episodeInfo.Month.Value, episodeInfo.Day.Value).ToUniversalTime();
|
||||
}
|
||||
|
||||
if (episode.PremiereDate.HasValue)
|
||||
{
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!episode.ProductionYear.HasValue)
|
||||
{
|
||||
episode.ProductionYear = episodeInfo.Year;
|
||||
|
||||
if (episode.ProductionYear.HasValue)
|
||||
{
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!episode.ParentIndexNumber.HasValue)
|
||||
{
|
||||
|
@ -1801,11 +1817,53 @@ namespace MediaBrowser.Server.Implementations.Library
|
|||
{
|
||||
episode.ParentIndexNumber = season.IndexNumber;
|
||||
}
|
||||
|
||||
if (episode.ParentIndexNumber.HasValue)
|
||||
{
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
else
|
||||
{
|
||||
if (!episode.IndexNumber.HasValue)
|
||||
{
|
||||
episode.IndexNumber = episodeInfo.EpisodeNumber;
|
||||
|
||||
if (episode.IndexNumber.HasValue)
|
||||
{
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (episode.ParentIndexNumber.HasValue)
|
||||
if (!episode.IndexNumberEnd.HasValue)
|
||||
{
|
||||
changed = true;
|
||||
episode.IndexNumberEnd = episodeInfo.EndingEpsiodeNumber;
|
||||
|
||||
if (episode.IndexNumberEnd.HasValue)
|
||||
{
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
|
||||
if (!episode.ParentIndexNumber.HasValue)
|
||||
{
|
||||
episode.ParentIndexNumber = episodeInfo.SeasonNumber;
|
||||
|
||||
if (!episode.ParentIndexNumber.HasValue)
|
||||
{
|
||||
var season = episode.Season;
|
||||
|
||||
if (season != null)
|
||||
{
|
||||
episode.ParentIndexNumber = season.IndexNumber;
|
||||
}
|
||||
}
|
||||
|
||||
if (episode.ParentIndexNumber.HasValue)
|
||||
{
|
||||
changed = true;
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
|
|
|
@ -1,7 +1,5 @@
|
|||
using MediaBrowser.Controller.Entities.TV;
|
||||
using MediaBrowser.Controller.Library;
|
||||
using MediaBrowser.Naming.Common;
|
||||
using MediaBrowser.Naming.IO;
|
||||
using System.Linq;
|
||||
|
||||
namespace MediaBrowser.Server.Implementations.Library.Resolvers.TV
|
||||
|
|
|
@ -171,6 +171,38 @@ namespace MediaBrowser.Server.Implementations.Library
|
|||
return AuthenticateUser(username, passwordSha1, null, remoteEndPoint);
|
||||
}
|
||||
|
||||
public bool IsValidUsername(string username)
|
||||
{
|
||||
// Usernames can contain letters (a-z), numbers (0-9), dashes (-), underscores (_), apostrophes ('), and periods (.)
|
||||
return username.All(IsValidCharacter);
|
||||
}
|
||||
|
||||
private bool IsValidCharacter(char i)
|
||||
{
|
||||
return char.IsLetterOrDigit(i) || char.Equals(i, '-') || char.Equals(i, '_') || char.Equals(i, '\'') ||
|
||||
char.Equals(i, '.');
|
||||
}
|
||||
|
||||
public string MakeValidUsername(string username)
|
||||
{
|
||||
if (IsValidUsername(username))
|
||||
{
|
||||
return username;
|
||||
}
|
||||
|
||||
// Usernames can contain letters (a-z), numbers (0-9), dashes (-), underscores (_), apostrophes ('), and periods (.)
|
||||
var builder = new StringBuilder();
|
||||
|
||||
foreach (var c in username)
|
||||
{
|
||||
if (IsValidCharacter(c))
|
||||
{
|
||||
builder.Append(c);
|
||||
}
|
||||
}
|
||||
return builder.ToString();
|
||||
}
|
||||
|
||||
public async Task<bool> AuthenticateUser(string username, string passwordSha1, string passwordMd5, string remoteEndPoint)
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(username))
|
||||
|
@ -178,7 +210,8 @@ namespace MediaBrowser.Server.Implementations.Library
|
|||
throw new ArgumentNullException("username");
|
||||
}
|
||||
|
||||
var user = Users.FirstOrDefault(i => string.Equals(username, i.Name, StringComparison.OrdinalIgnoreCase));
|
||||
var user = Users
|
||||
.FirstOrDefault(i => string.Equals(username, i.Name, StringComparison.OrdinalIgnoreCase));
|
||||
|
||||
if (user == null)
|
||||
{
|
||||
|
@ -203,20 +236,6 @@ namespace MediaBrowser.Server.Implementations.Library
|
|||
}
|
||||
}
|
||||
|
||||
// Maybe user accidently entered connect credentials. let's be flexible
|
||||
if (!success && user.ConnectLinkType.HasValue && !string.IsNullOrWhiteSpace(passwordMd5))
|
||||
{
|
||||
try
|
||||
{
|
||||
await _connectFactory().Authenticate(user.ConnectUserName, passwordMd5).ConfigureAwait(false);
|
||||
success = true;
|
||||
}
|
||||
catch
|
||||
{
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
// Update LastActivityDate and LastLoginDate, then save
|
||||
if (success)
|
||||
{
|
||||
|
@ -273,7 +292,7 @@ namespace MediaBrowser.Server.Implementations.Library
|
|||
// There always has to be at least one user.
|
||||
if (users.Count == 0)
|
||||
{
|
||||
var name = Environment.UserName;
|
||||
var name = MakeValidUsername(Environment.UserName);
|
||||
|
||||
var user = InstantiateNewUser(name, false);
|
||||
|
||||
|
@ -477,6 +496,11 @@ namespace MediaBrowser.Server.Implementations.Library
|
|||
throw new ArgumentNullException("name");
|
||||
}
|
||||
|
||||
if (!IsValidUsername(name))
|
||||
{
|
||||
throw new ArgumentException("Only alphanumeric characters are allowed.");
|
||||
}
|
||||
|
||||
if (Users.Any(u => u.Name.Equals(name, StringComparison.OrdinalIgnoreCase)))
|
||||
{
|
||||
throw new ArgumentException(string.Format("A user with the name '{0}' already exists.", name));
|
||||
|
@ -803,6 +827,10 @@ namespace MediaBrowser.Server.Implementations.Library
|
|||
return (UserPolicy)_xmlSerializer.DeserializeFromFile(typeof(UserPolicy), path);
|
||||
}
|
||||
}
|
||||
catch (DirectoryNotFoundException)
|
||||
{
|
||||
return GetDefaultPolicy(user);
|
||||
}
|
||||
catch (FileNotFoundException)
|
||||
{
|
||||
return GetDefaultPolicy(user);
|
||||
|
@ -840,6 +868,8 @@ namespace MediaBrowser.Server.Implementations.Library
|
|||
|
||||
var path = GetPolifyFilePath(user);
|
||||
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(path));
|
||||
|
||||
lock (_policySyncLock)
|
||||
{
|
||||
_xmlSerializer.SerializeToFile(userPolicy, path);
|
||||
|
@ -900,6 +930,10 @@ namespace MediaBrowser.Server.Implementations.Library
|
|||
return (UserConfiguration)_xmlSerializer.DeserializeFromFile(typeof(UserConfiguration), path);
|
||||
}
|
||||
}
|
||||
catch (DirectoryNotFoundException)
|
||||
{
|
||||
return new UserConfiguration();
|
||||
}
|
||||
catch (FileNotFoundException)
|
||||
{
|
||||
return new UserConfiguration();
|
||||
|
@ -930,6 +964,8 @@ namespace MediaBrowser.Server.Implementations.Library
|
|||
config = _jsonSerializer.DeserializeFromString<UserConfiguration>(json);
|
||||
}
|
||||
|
||||
Directory.CreateDirectory(Path.GetDirectoryName(path));
|
||||
|
||||
lock (_configSyncLock)
|
||||
{
|
||||
_xmlSerializer.SerializeToFile(config, path);
|
||||
|
|
|
@ -419,7 +419,7 @@
|
|||
"HeaderMediaLocations": "Media Locations",
|
||||
"LabelFolderTypeValue": "Folder type: {0}",
|
||||
"LabelPathSubstitutionHelp": "Optional: Path substitution can map server paths to network shares that clients can access for direct playback.",
|
||||
"FolderTypeMixed": "Mixed videos",
|
||||
"FolderTypeMixed": "Mixed content",
|
||||
"FolderTypeMovies": "Movies",
|
||||
"FolderTypeMusic": "Music",
|
||||
"FolderTypeAdultVideos": "Adult videos",
|
||||
|
@ -658,5 +658,5 @@
|
|||
"LabelItemLimitHelp": "Optional. Set a limit to the number of items that will be synced.",
|
||||
"MessageBookPluginRequired": "Requires installation of the Bookshelf plugin",
|
||||
"MessageGamePluginRequired": "Requires installation of the GameBrowser plugin",
|
||||
"MessageMixedContentHelp": "Content will be displayed with as a plain folder structure"
|
||||
"MessageMixedContentHelp": "Content will be displayed as a plain folder structure"
|
||||
}
|
||||
|
|
|
@ -37,7 +37,7 @@
|
|||
"ButtonOk": "Ok",
|
||||
"ButtonCancel": "Cancel",
|
||||
"ButtonNew": "New",
|
||||
"FolderTypeMixed": "Mixed videos",
|
||||
"FolderTypeMixed": "Mixed content",
|
||||
"FolderTypeMovies": "Movies",
|
||||
"FolderTypeMusic": "Music",
|
||||
"FolderTypeAdultVideos": "Adult videos",
|
||||
|
@ -48,7 +48,7 @@
|
|||
"FolderTypeBooks": "Books",
|
||||
"FolderTypeTvShows": "TV",
|
||||
"FolderTypeInherit": "Inherit",
|
||||
"LabelContentType": "Content type:",
|
||||
"LabelContentType": "Content type:",
|
||||
"HeaderSetupLibrary": "Setup your media library",
|
||||
"ButtonAddMediaFolder": "Add media folder",
|
||||
"LabelFolderType": "Folder type:",
|
||||
|
@ -1307,5 +1307,8 @@
|
|||
"LabelEnableSingleImageInDidlLimitHelp": "Some devices will not render properly if multiple images are embedded within Didl.",
|
||||
"TabActivity": "Activity",
|
||||
"TitleSync": "Sync",
|
||||
"OptionAllowSyncContent": "Allow syncing media to devices"
|
||||
"OptionAllowSyncContent": "Allow syncing media to devices",
|
||||
"NameSeasonUnknown": "Season Unknown",
|
||||
"NameSeasonNumber": "Season {0}",
|
||||
"LabelNewUserNameHelp": "Usernames can contain letters (a-z), numbers (0-9), dashes (-), underscores (_), apostrophes ('), and periods (.)"
|
||||
}
|
||||
|
|
|
@ -26,6 +26,14 @@ namespace MediaBrowser.Server.Implementations.News
|
|||
{
|
||||
return GetProductNewsInternal(query);
|
||||
}
|
||||
catch (DirectoryNotFoundException)
|
||||
{
|
||||
// No biggie
|
||||
return new QueryResult<NewsItem>
|
||||
{
|
||||
Items = new NewsItem[] { }
|
||||
};
|
||||
}
|
||||
catch (FileNotFoundException)
|
||||
{
|
||||
// No biggie
|
||||
|
|
|
@ -256,6 +256,10 @@ namespace MediaBrowser.XbmcMetadata.Savers
|
|||
catch (FileNotFoundException)
|
||||
{
|
||||
|
||||
}
|
||||
catch (DirectoryNotFoundException)
|
||||
{
|
||||
|
||||
}
|
||||
|
||||
writer.WriteEndElement();
|
||||
|
|
Loading…
Reference in New Issue
Block a user