add search methods to remote metadata providers

This commit is contained in:
Luke Pulverenti 2014-02-19 23:53:15 -05:00
parent 120c8bcbb9
commit 13e4b2a6a7
45 changed files with 524 additions and 166 deletions

View File

@ -912,32 +912,6 @@ namespace MediaBrowser.Controller.Entities
}
}
/// <summary>
/// Determine if we have changed vs the passed in copy
/// </summary>
/// <param name="copy">The copy.</param>
/// <returns><c>true</c> if the specified copy has changed; otherwise, <c>false</c>.</returns>
/// <exception cref="System.ArgumentNullException"></exception>
public virtual bool HasChanged(BaseItem copy)
{
if (copy == null)
{
throw new ArgumentNullException();
}
if (IsInMixedFolder != copy.IsInMixedFolder)
{
Logger.Debug(Name + " changed due to different value for IsInMixedFolder.");
return true;
}
var changed = copy.DateModified != DateModified;
if (changed)
{
Logger.Debug(Name + " changed - original creation: " + DateCreated + " new creation: " + copy.DateCreated + " original modified: " + DateModified + " new modified: " + copy.DateModified);
}
return changed;
}
public virtual string GetClientTypeName()
{
return GetType().Name;

View File

@ -181,8 +181,6 @@ namespace MediaBrowser.Controller.Entities
item.Parent = null;
LibraryManager.ReportItemRemoved(item);
return ItemRepository.SaveChildren(Id, ActualChildren.Select(i => i.Id).ToList(), cancellationToken);
}
@ -220,7 +218,6 @@ namespace MediaBrowser.Controller.Entities
{LocalizedStrings.Instance.GetString("GenreDispPref")},
{LocalizedStrings.Instance.GetString("DirectorDispPref")},
{LocalizedStrings.Instance.GetString("YearDispPref")},
//{LocalizedStrings.Instance.GetString("OfficialRatingDispPref"), null},
{LocalizedStrings.Instance.GetString("StudioDispPref")}
};

View File

@ -0,0 +1,8 @@

namespace MediaBrowser.Controller.Library
{
public class DeleteOptions
{
public bool DeleteFileLocation { get; set; }
}
}

View File

@ -41,7 +41,7 @@ namespace MediaBrowser.Controller.Library
/// <param name="parent">The parent.</param>
/// <returns>BaseItem.</returns>
BaseItem ResolvePath(FileSystemInfo fileInfo, Folder parent = null);
/// <summary>
/// Resolves a set of files into a list of BaseItem
/// </summary>
@ -335,7 +335,19 @@ namespace MediaBrowser.Controller.Library
/// Deletes the item.
/// </summary>
/// <param name="item">The item.</param>
/// <param name="options">The options.</param>
/// <returns>Task.</returns>
Task DeleteItem(BaseItem item);
Task DeleteItem(BaseItem item, DeleteOptions options);
}
public static class LibraryManagerExtensions
{
public static Task DeleteItem(this ILibraryManager manager, BaseItem item)
{
return manager.DeleteItem(item, new DeleteOptions
{
DeleteFileLocation = true
});
}
}
}

View File

@ -111,6 +111,7 @@
<Compile Include="Entities\IHasAwards.cs" />
<Compile Include="Entities\Photo.cs" />
<Compile Include="FileOrganization\IFileOrganizationService.cs" />
<Compile Include="Library\DeleteOptions.cs" />
<Compile Include="Library\ILibraryPostScanTask.cs" />
<Compile Include="Library\IMetadataSaver.cs" />
<Compile Include="Library\ItemUpdateType.cs" />

View File

@ -95,6 +95,13 @@ namespace MediaBrowser.Controller.Persistence
/// <returns>IEnumerable{ChildDefinition}.</returns>
IEnumerable<Guid> GetChildren(Guid parentId);
/// <summary>
/// Gets the type of the items of.
/// </summary>
/// <param name="type">The type.</param>
/// <returns>IEnumerable{Guid}.</returns>
IEnumerable<BaseItem> GetItemsOfType(Type type);
/// <summary>
/// Saves the children.
/// </summary>

View File

@ -96,5 +96,19 @@ namespace MediaBrowser.Controller.Providers
/// <param name="item">The item.</param>
/// <returns>MetadataOptions.</returns>
MetadataOptions GetMetadataOptions(IHasImages item);
/// <summary>
/// Gets the remote search results.
/// </summary>
/// <typeparam name="TItemType">The type of the t item type.</typeparam>
/// <typeparam name="TLookupType">The type of the t lookup type.</typeparam>
/// <param name="searchInfo">The search information.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{IEnumerable{SearchResult{``1}}}.</returns>
Task<IEnumerable<RemoteSearchResult>> GetRemoteSearchResults<TItemType, TLookupType>(
RemoteSearchQuery<TLookupType> searchInfo,
CancellationToken cancellationToken)
where TItemType : BaseItem, new()
where TLookupType : ItemLookupInfo;
}
}

View File

@ -1,4 +1,6 @@
using MediaBrowser.Controller.Entities;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Model.Providers;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
@ -9,29 +11,27 @@ namespace MediaBrowser.Controller.Providers
{
}
public interface IRemoteMetadataProvider<TItemType, TLookupInfoType> : IMetadataProvider<TItemType>, IRemoteMetadataProvider
public interface IRemoteMetadataProvider<TItemType, in TLookupInfoType> : IMetadataProvider<TItemType>, IRemoteMetadataProvider, IRemoteSearchProvider<TLookupInfoType>
where TItemType : IHasMetadata, IHasLookupInfo<TLookupInfoType>
where TLookupInfoType : ItemLookupInfo, new()
{
Task<MetadataResult<TItemType>> GetMetadata(TLookupInfoType info, CancellationToken cancellationToken);
}
public interface IRemoteSearchProvider<TLookupInfoType>
public interface IRemoteSearchProvider<in TLookupInfoType> : IMetadataProvider
where TLookupInfoType : ItemLookupInfo
{
string Name { get; }
Task<IEnumerable<RemoteSearchResult>> GetSearchResults(TLookupInfoType searchInfo, CancellationToken cancellationToken);
Task<IEnumerable<SearchResult<TLookupInfoType>>> GetSearchResults(TLookupInfoType searchInfo, CancellationToken cancellationToken);
/// <summary>
/// Gets the image response.
/// </summary>
/// <param name="url">The URL.</param>
/// <param name="cancellationToken">The cancellation token.</param>
/// <returns>Task{HttpResponseInfo}.</returns>
Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken);
}
public class SearchResult<T>
where T : ItemLookupInfo
{
public T Item { get; set; }
public string ImageUrl { get; set; }
}
public class RemoteSearchQuery<T>
where T : ItemLookupInfo
{

View File

@ -338,6 +338,9 @@
<Compile Include="..\MediaBrowser.Model\Providers\RemoteImageResult.cs">
<Link>Providers\RemoteImageResult.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Providers\RemoteSearchResult.cs">
<Link>Providers\RemoteSearchResult.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Querying\ArtistsQuery.cs">
<Link>Querying\ArtistsQuery.cs</Link>
</Compile>

View File

@ -325,6 +325,9 @@
<Compile Include="..\MediaBrowser.Model\Providers\RemoteImageResult.cs">
<Link>Providers\RemoteImageResult.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Providers\RemoteSearchResult.cs">
<Link>Providers\RemoteSearchResult.cs</Link>
</Compile>
<Compile Include="..\MediaBrowser.Model\Querying\ArtistsQuery.cs">
<Link>Querying\ArtistsQuery.cs</Link>
</Compile>

View File

@ -112,6 +112,7 @@
<Compile Include="Notifications\NotificationResult.cs" />
<Compile Include="Notifications\NotificationsSummary.cs" />
<Compile Include="Providers\RemoteImageResult.cs" />
<Compile Include="Providers\RemoteSearchResult.cs" />
<Compile Include="Querying\ArtistsQuery.cs" />
<Compile Include="Querying\EpisodeQuery.cs" />
<Compile Include="Querying\ItemCountsQuery.cs" />

View File

@ -0,0 +1,39 @@
using MediaBrowser.Model.Entities;
using System;
using System.Collections.Generic;
namespace MediaBrowser.Model.Providers
{
public class RemoteSearchResult : IHasProviderIds
{
/// <summary>
/// Gets or sets the name.
/// </summary>
/// <value>The name.</value>
public string Name { get; set; }
/// <summary>
/// Gets or sets the provider ids.
/// </summary>
/// <value>The provider ids.</value>
public Dictionary<string, string> ProviderIds { get; set; }
/// <summary>
/// Gets or sets the year.
/// </summary>
/// <value>The year.</value>
public int? ProductionYear { get; set; }
public int? IndexNumber { get; set; }
public int? IndexNumberEnd { get; set; }
public int? ParentIndexNumber { get; set; }
public DateTime? PremiereDate { get; set; }
public string ImageUrl { get; set; }
public string SearchProviderName { get; set; }
public RemoteSearchResult()
{
ProviderIds = new Dictionary<string, string>(StringComparer.OrdinalIgnoreCase);
}
}
}

View File

@ -7,6 +7,7 @@ using MediaBrowser.Controller.Localization;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Providers;
using MediaBrowser.Model.Serialization;
using MediaBrowser.Providers.Movies;
using System;
@ -42,6 +43,11 @@ namespace MediaBrowser.Providers.BoxSets
Current = this;
}
public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(BoxSetInfo searchInfo, CancellationToken cancellationToken)
{
return new List<RemoteSearchResult>();
}
public async Task<MetadataResult<BoxSet>> GetMetadata(BoxSetInfo id, CancellationToken cancellationToken)
{
var tmdbId = id.GetProviderId(MetadataProviders.Tmdb);
@ -282,5 +288,10 @@ namespace MediaBrowser.Providers.BoxSets
public List<Part> parts { get; set; }
public Images images { get; set; }
}
public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
}
}

View File

@ -586,7 +586,7 @@ namespace MediaBrowser.Providers.Manager
}
}
public async Task<IEnumerable<SearchResult<TLookupType>>> GetRemoteSearchResults<TItemType, TLookupType>(RemoteSearchQuery<TLookupType> searchInfo,
public async Task<IEnumerable<RemoteSearchResult>> GetRemoteSearchResults<TItemType, TLookupType>(RemoteSearchQuery<TLookupType> searchInfo,
CancellationToken cancellationToken)
where TItemType : BaseItem, new()
where TLookupType : ItemLookupInfo
@ -623,7 +623,7 @@ namespace MediaBrowser.Providers.Manager
}
// Nothing found
return new List<SearchResult<TLookupType>>();
return new List<RemoteSearchResult>();
}
}
}

View File

@ -1,5 +1,4 @@
using System.Linq;
using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.Configuration;
using MediaBrowser.Common.IO;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Configuration;
@ -9,10 +8,12 @@ using MediaBrowser.Controller.Localization;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Providers;
using MediaBrowser.Model.Serialization;
using System;
using System.Collections.Generic;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
@ -45,6 +46,11 @@ namespace MediaBrowser.Providers.Movies
Current = this;
}
public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(MovieInfo searchInfo, CancellationToken cancellationToken)
{
return new List<RemoteSearchResult>();
}
public Task<MetadataResult<Movie>> GetMetadata(MovieInfo info, CancellationToken cancellationToken)
{
return GetItemMetadata<Movie>(info, cancellationToken);
@ -549,5 +555,10 @@ namespace MediaBrowser.Providers.Movies
return 1;
}
}
public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
}
}

View File

@ -1,6 +1,9 @@
using MediaBrowser.Controller.Entities;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Providers;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
@ -13,6 +16,11 @@ namespace MediaBrowser.Providers.Movies
return MovieDbProvider.Current.GetItemMetadata<Trailer>(info, cancellationToken);
}
public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(TrailerInfo searchInfo, CancellationToken cancellationToken)
{
return new List<RemoteSearchResult>();
}
public string Name
{
get { return MovieDbProvider.Current.Name; }
@ -31,5 +39,10 @@ namespace MediaBrowser.Providers.Movies
return 1;
}
}
public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
}
}

View File

@ -5,6 +5,7 @@ using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Providers;
using MediaBrowser.Model.Serialization;
using System;
using System.Collections.Generic;
@ -15,7 +16,7 @@ using System.Threading.Tasks;
namespace MediaBrowser.Providers.Music
{
public class AudioDbAlbumProvider : IRemoteMetadataProvider<MusicAlbum,AlbumInfo>, IHasOrder
public class AudioDbAlbumProvider : IRemoteMetadataProvider<MusicAlbum, AlbumInfo>, IHasOrder
{
private readonly IServerConfigurationManager _config;
private readonly IFileSystem _fileSystem;
@ -36,6 +37,11 @@ namespace MediaBrowser.Providers.Music
Current = this;
}
public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(AlbumInfo searchInfo, CancellationToken cancellationToken)
{
return new List<RemoteSearchResult>();
}
public async Task<MetadataResult<MusicAlbum>> GetMetadata(AlbumInfo info, CancellationToken cancellationToken)
{
var result = new MetadataResult<MusicAlbum>();
@ -81,7 +87,7 @@ namespace MediaBrowser.Providers.Music
item.SetProviderId(MetadataProviders.MusicBrainzAlbumArtist, result.strMusicBrainzArtistID);
item.SetProviderId(MetadataProviders.MusicBrainzReleaseGroup, result.strMusicBrainzID);
}
public string Name
{
get { return "TheAudioDB"; }
@ -112,7 +118,7 @@ namespace MediaBrowser.Providers.Music
var url = AudioDbArtistProvider.BaseUrl + "/album-mb.php?i=" + musicBrainzReleaseGroupId;
var path = GetAlbumInfoPath(_config.ApplicationPaths, musicBrainzReleaseGroupId);
Directory.CreateDirectory(Path.GetDirectoryName(path));
using (var response = await _httpClient.Get(new HttpRequestOptions
@ -206,5 +212,10 @@ namespace MediaBrowser.Providers.Music
{
public List<Album> album { get; set; }
}
public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
}
}

View File

@ -5,6 +5,7 @@ using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Providers;
using MediaBrowser.Model.Serialization;
using System;
using System.Collections.Generic;
@ -36,6 +37,11 @@ namespace MediaBrowser.Providers.Music
Current = this;
}
public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(ArtistInfo searchInfo, CancellationToken cancellationToken)
{
return new List<RemoteSearchResult>();
}
public async Task<MetadataResult<MusicArtist>> GetMetadata(ArtistInfo info, CancellationToken cancellationToken)
{
var result = new MetadataResult<MusicArtist>();
@ -213,5 +219,10 @@ namespace MediaBrowser.Providers.Music
return 1;
}
}
public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
}
}

View File

@ -4,6 +4,7 @@ using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Providers;
using MediaBrowser.Model.Serialization;
using MoreLinq;
using System;
@ -32,6 +33,11 @@ namespace MediaBrowser.Providers.Music
_logger = logger;
}
public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(AlbumInfo searchInfo, CancellationToken cancellationToken)
{
return new List<RemoteSearchResult>();
}
public async Task<MetadataResult<MusicAlbum>> GetMetadata(AlbumInfo id, CancellationToken cancellationToken)
{
var result = new MetadataResult<MusicAlbum>();
@ -204,6 +210,11 @@ namespace MediaBrowser.Providers.Music
return 2;
}
}
public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
}
#region Result Objects

View File

@ -5,8 +5,10 @@ using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Providers;
using MediaBrowser.Model.Serialization;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
@ -38,6 +40,11 @@ namespace MediaBrowser.Providers.Music
_logger = logger;
}
public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(ArtistInfo searchInfo, CancellationToken cancellationToken)
{
return new List<RemoteSearchResult>();
}
public async Task<MetadataResult<MusicArtist>> GetMetadata(ArtistInfo id, CancellationToken cancellationToken)
{
var result = new MetadataResult<MusicArtist>();
@ -170,5 +177,10 @@ namespace MediaBrowser.Providers.Music
return 2;
}
}
public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
}
}

View File

@ -1,8 +1,10 @@
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Providers;
using MediaBrowser.Providers.Movies;
using System;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
@ -15,6 +17,11 @@ namespace MediaBrowser.Providers.Music
return MovieDbProvider.Current.GetItemMetadata<MusicVideo>(info, cancellationToken);
}
public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(MusicVideoInfo searchInfo, CancellationToken cancellationToken)
{
return new List<RemoteSearchResult>();
}
public string Name
{
get { return MovieDbProvider.Current.Name; }
@ -24,5 +31,10 @@ namespace MediaBrowser.Providers.Music
{
return MovieDbProvider.Current.HasChanged(item, date);
}
public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
}
}

View File

@ -3,7 +3,9 @@ using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Providers;
using System;
using System.Collections.Generic;
using System.IO;
using System.Net;
using System.Text;
@ -27,6 +29,11 @@ namespace MediaBrowser.Providers.Music
Current = this;
}
public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(AlbumInfo searchInfo, CancellationToken cancellationToken)
{
return new List<RemoteSearchResult>();
}
public async Task<MetadataResult<MusicAlbum>> GetMetadata(AlbumInfo id, CancellationToken cancellationToken)
{
var releaseId = id.GetReleaseId();
@ -232,5 +239,10 @@ namespace MediaBrowser.Providers.Music
{
get { return 0; }
}
public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
}
}

View File

@ -1,7 +1,10 @@
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Entities.Audio;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Providers;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.Linq;
using System.Net;
@ -14,6 +17,11 @@ namespace MediaBrowser.Providers.Music
{
public class MusicBrainzArtistProvider : IRemoteMetadataProvider<MusicArtist, ArtistInfo>
{
public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(ArtistInfo searchInfo, CancellationToken cancellationToken)
{
return new List<RemoteSearchResult>();
}
public async Task<MetadataResult<MusicArtist>> GetMetadata(ArtistInfo id, CancellationToken cancellationToken)
{
var result = new MetadataResult<MusicArtist>();
@ -115,5 +123,10 @@ namespace MediaBrowser.Providers.Music
{
get { return "MusicBrainz"; }
}
public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
}
}

View File

@ -5,11 +5,12 @@ using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Providers;
using MediaBrowser.Model.Serialization;
using MediaBrowser.Providers.Movies;
using MediaBrowser.Providers.TV;
using System;
using System.Globalization;
using System.Collections.Generic;
using System.Threading;
using System.Threading.Tasks;
@ -29,6 +30,21 @@ namespace MediaBrowser.Providers.Omdb
_logger = logger;
}
public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(SeriesInfo searchInfo, CancellationToken cancellationToken)
{
return new List<RemoteSearchResult>();
}
public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(TrailerInfo searchInfo, CancellationToken cancellationToken)
{
return new List<RemoteSearchResult>();
}
public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(MovieInfo searchInfo, CancellationToken cancellationToken)
{
return new List<RemoteSearchResult>();
}
public string Name
{
get { return "IMDb via The Open Movie Database"; }
@ -139,5 +155,10 @@ namespace MediaBrowser.Providers.Omdb
return new Tuple<string, string>(imdb, tvdb);
}
public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
}
}

View File

@ -6,6 +6,7 @@ using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Providers;
using MediaBrowser.Model.Serialization;
using MediaBrowser.Providers.Movies;
using System;
@ -42,7 +43,7 @@ namespace MediaBrowser.Providers.People
get { return "TheMovieDb"; }
}
public async Task<IEnumerable<SearchResult<PersonLookupInfo>>> GetSearchResults(PersonLookupInfo searchInfo, CancellationToken cancellationToken)
public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(PersonLookupInfo searchInfo, CancellationToken cancellationToken)
{
var tmdbId = searchInfo.GetProviderId(MetadataProviders.Tmdb);
@ -59,18 +60,15 @@ namespace MediaBrowser.Providers.People
var images = (info.images ?? new Images()).profiles ?? new List<Profile>();
var result = new SearchResult<PersonLookupInfo>
var result = new RemoteSearchResult
{
Item = new PersonLookupInfo
{
Name = info.name
},
Name = info.name,
ImageUrl = images.Count == 0 ? null : (tmdbImageUrl + images[0].file_path)
};
result.Item.SetProviderId(MetadataProviders.Tmdb, info.id.ToString(_usCulture));
result.Item.SetProviderId(MetadataProviders.Imdb, info.imdb_id.ToString(_usCulture));
result.SetProviderId(MetadataProviders.Tmdb, info.id.ToString(_usCulture));
result.SetProviderId(MetadataProviders.Imdb, info.imdb_id.ToString(_usCulture));
return new[] { result };
}
@ -92,19 +90,16 @@ namespace MediaBrowser.Providers.People
}
}
private SearchResult<PersonLookupInfo> GetSearchResult(PersonSearchResult i, string baseImageUrl)
private RemoteSearchResult GetSearchResult(PersonSearchResult i, string baseImageUrl)
{
var result = new SearchResult<PersonLookupInfo>
var result = new RemoteSearchResult
{
Item = new PersonLookupInfo
{
Name = i.Name
},
Name = i.Name,
ImageUrl = string.IsNullOrEmpty(i.Profile_Path) ? null : (baseImageUrl + i.Profile_Path)
};
result.Item.SetProviderId(MetadataProviders.Tmdb, i.Id.ToString(_usCulture));
result.SetProviderId(MetadataProviders.Tmdb, i.Id.ToString(_usCulture));
return result;
}
@ -175,7 +170,7 @@ namespace MediaBrowser.Providers.People
{
var results = await GetSearchResults(info, cancellationToken).ConfigureAwait(false);
return results.Select(i => i.Item.GetProviderId(MetadataProviders.Tmdb)).FirstOrDefault();
return results.Select(i => i.GetProviderId(MetadataProviders.Tmdb)).FirstOrDefault();
}
internal async Task EnsurePersonInfo(string id, CancellationToken cancellationToken)
@ -351,5 +346,10 @@ namespace MediaBrowser.Providers.People
}
#endregion
public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
}
}

View File

@ -367,22 +367,32 @@ namespace MediaBrowser.Providers.TV
return Path.Combine(dataPath, "fanart.xml");
}
private readonly Task _cachedTask = Task.FromResult(true);
internal Task EnsureSeriesXml(string tvdbId, CancellationToken cancellationToken)
private readonly SemaphoreSlim _ensureSemaphore = new SemaphoreSlim(1, 1);
internal async Task EnsureSeriesXml(string tvdbId, CancellationToken cancellationToken)
{
var xmlPath = GetSeriesDataPath(_config.ApplicationPaths, tvdbId);
var xmlPath = GetFanartXmlPath(tvdbId);
var fileInfo = _fileSystem.GetFileSystemInfo(xmlPath);
// Only allow one thread in here at a time since every season will be calling this method, possibly concurrently
await _ensureSemaphore.WaitAsync(cancellationToken).ConfigureAwait(false);
if (fileInfo.Exists)
try
{
if ((DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(fileInfo)).TotalDays <= 7)
{
return _cachedTask;
}
}
var fileInfo = _fileSystem.GetFileSystemInfo(xmlPath);
return DownloadSeriesXml(tvdbId, cancellationToken);
if (fileInfo.Exists)
{
if ((DateTime.UtcNow - _fileSystem.GetLastWriteTimeUtc(fileInfo)).TotalDays <= 7)
{
return;
}
}
await DownloadSeriesXml(tvdbId, cancellationToken).ConfigureAwait(false);
}
finally
{
_ensureSemaphore.Release();
}
}
/// <summary>

View File

@ -1,6 +1,7 @@
using MediaBrowser.Common.Extensions;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
@ -20,13 +21,15 @@ namespace MediaBrowser.Providers.TV
{
private readonly IServerConfigurationManager _config;
private readonly ILogger _logger;
private readonly ILibraryManager _libraryManager;
private static readonly CultureInfo UsCulture = new CultureInfo("en-US");
public MissingEpisodeProvider(ILogger logger, IServerConfigurationManager config)
public MissingEpisodeProvider(ILogger logger, IServerConfigurationManager config, ILibraryManager libraryManager)
{
_logger = logger;
_config = config;
_libraryManager = libraryManager;
}
public async Task Run(IEnumerable<IGrouping<string, Series>> series, CancellationToken cancellationToken)
@ -268,7 +271,7 @@ namespace MediaBrowser.Providers.TV
{
_logger.Info("Removing missing/unaired episode {0} {1}x{2}", episodeToRemove.Series.Name, episodeToRemove.ParentIndexNumber, episodeToRemove.IndexNumber);
await episodeToRemove.Parent.RemoveChild(episodeToRemove, cancellationToken).ConfigureAwait(false);
await _libraryManager.DeleteItem(episodeToRemove).ConfigureAwait(false);
hasChanges = true;
}
@ -327,7 +330,7 @@ namespace MediaBrowser.Providers.TV
{
_logger.Info("Removing virtual season {0} {1}", seasonToRemove.Series.Name, seasonToRemove.IndexNumber);
await seasonToRemove.Parent.RemoveChild(seasonToRemove, cancellationToken).ConfigureAwait(false);
await _libraryManager.DeleteItem(seasonToRemove).ConfigureAwait(false);
hasChanges = true;
}

View File

@ -8,15 +8,16 @@ using MediaBrowser.Controller.Localization;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Providers;
using MediaBrowser.Model.Serialization;
using MediaBrowser.Providers.Movies;
using System;
using System.Collections.Generic;
using System.Globalization;
using System.IO;
using System.Linq;
using System.Threading;
using System.Threading.Tasks;
using System.Linq;
namespace MediaBrowser.Providers.TV
{
@ -48,6 +49,11 @@ namespace MediaBrowser.Providers.TV
get { return "TheMovieDb"; }
}
public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(SeriesInfo searchInfo, CancellationToken cancellationToken)
{
return new List<RemoteSearchResult>();
}
public async Task<MetadataResult<Series>> GetMetadata(SeriesInfo info, CancellationToken cancellationToken)
{
var result = new MetadataResult<Series>();
@ -453,5 +459,10 @@ namespace MediaBrowser.Providers.TV
return 2;
}
}
public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
}
}

View File

@ -45,7 +45,7 @@ namespace MediaBrowser.Providers.TV
group series by tvdbId into g
select g;
await new MissingEpisodeProvider(_logger, _config).Run(seriesGroups, cancellationToken).ConfigureAwait(false);
await new MissingEpisodeProvider(_logger, _config, _libraryManager).Run(seriesGroups, cancellationToken).ConfigureAwait(false);
var numComplete = 0;

View File

@ -1,9 +1,11 @@
using MediaBrowser.Common.IO;
using MediaBrowser.Common.Net;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Providers;
using System;
using System.Collections.Generic;
using System.Globalization;
@ -34,17 +36,54 @@ namespace MediaBrowser.Providers.TV
Current = this;
}
public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(EpisodeInfo searchInfo, CancellationToken cancellationToken)
{
var list = new List<RemoteSearchResult>();
string seriesTvdbId;
searchInfo.SeriesProviderIds.TryGetValue(MetadataProviders.Tvdb.ToString(), out seriesTvdbId);
if (!string.IsNullOrEmpty(seriesTvdbId))
{
var seriesDataPath = TvdbSeriesProvider.GetSeriesDataPath(_config.ApplicationPaths, seriesTvdbId);
try
{
var item = FetchEpisodeData(searchInfo, seriesDataPath, cancellationToken);
if (item != null)
{
list.Add(new RemoteSearchResult
{
IndexNumber = item.IndexNumber,
Name = item.Name,
ParentIndexNumber = item.ParentIndexNumber,
PremiereDate = item.PremiereDate,
ProductionYear = item.ProductionYear,
ProviderIds = item.ProviderIds,
SearchProviderName = Name,
IndexNumberEnd = item.IndexNumberEnd
});
}
}
catch (FileNotFoundException)
{
// Don't fail the provider because this will just keep on going and going.
}
}
return list;
}
public string Name
{
get { return "TheTVDB"; }
}
public Task<MetadataResult<Episode>> GetMetadata(EpisodeInfo id, CancellationToken cancellationToken)
public Task<MetadataResult<Episode>> GetMetadata(EpisodeInfo searchInfo, CancellationToken cancellationToken)
{
var episodeId = id;
string seriesTvdbId;
episodeId.SeriesProviderIds.TryGetValue(MetadataProviders.Tvdb.ToString(), out seriesTvdbId);
searchInfo.SeriesProviderIds.TryGetValue(MetadataProviders.Tvdb.ToString(), out seriesTvdbId);
var result = new MetadataResult<Episode>();
@ -54,7 +93,7 @@ namespace MediaBrowser.Providers.TV
try
{
result.Item = FetchEpisodeData(episodeId, seriesDataPath, cancellationToken);
result.Item = FetchEpisodeData(searchInfo, seriesDataPath, cancellationToken);
result.HasMetadata = result.Item != null;
}
catch (FileNotFoundException)
@ -192,9 +231,9 @@ namespace MediaBrowser.Providers.TV
var episode = new Episode
{
IndexNumber = id.IndexNumber,
ParentIndexNumber = id.ParentIndexNumber,
IndexNumberEnd = id.IndexNumberEnd
IndexNumber = id.IndexNumber,
ParentIndexNumber = id.ParentIndexNumber,
IndexNumberEnd = id.IndexNumberEnd
};
try
@ -674,5 +713,10 @@ namespace MediaBrowser.Providers.TV
}
}
}
public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
}
}

View File

@ -9,6 +9,7 @@ using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.IO;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Providers;
using System;
using System.Collections.Generic;
using System.Globalization;
@ -47,6 +48,11 @@ namespace MediaBrowser.Providers.TV
private const string SeriesQuery = "GetSeries.php?seriesname={0}";
private const string SeriesGetZip = "http://www.thetvdb.com/api/{0}/series/{1}/all/{2}.zip";
public async Task<IEnumerable<RemoteSearchResult>> GetSearchResults(SeriesInfo searchInfo, CancellationToken cancellationToken)
{
return new List<RemoteSearchResult>();
}
public async Task<MetadataResult<Series>> GetMetadata(SeriesInfo itemId, CancellationToken cancellationToken)
{
var result = new MetadataResult<Series>();
@ -1081,5 +1087,10 @@ namespace MediaBrowser.Providers.TV
return 1;
}
}
public Task<HttpResponseInfo> GetImageResponse(string url, CancellationToken cancellationToken)
{
throw new NotImplementedException();
}
}
}

View File

@ -2,7 +2,6 @@
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities.TV;
using MediaBrowser.Controller.FileOrganization;
using MediaBrowser.Controller.IO;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Controller.Resolvers;
@ -28,10 +27,11 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
private readonly IFileSystem _fileSystem;
private readonly IFileOrganizationService _organizationService;
private readonly IServerConfigurationManager _config;
private readonly IProviderManager _providerManager;
private readonly CultureInfo _usCulture = new CultureInfo("en-US");
public EpisodeFileOrganizer(IFileOrganizationService organizationService, IServerConfigurationManager config, IFileSystem fileSystem, ILogger logger, ILibraryManager libraryManager, ILibraryMonitor libraryMonitor)
public EpisodeFileOrganizer(IFileOrganizationService organizationService, IServerConfigurationManager config, IFileSystem fileSystem, ILogger logger, ILibraryManager libraryManager, ILibraryMonitor libraryMonitor, IProviderManager providerManager)
{
_organizationService = organizationService;
_config = config;
@ -39,9 +39,10 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
_logger = logger;
_libraryManager = libraryManager;
_libraryMonitor = libraryMonitor;
_providerManager = providerManager;
}
public async Task<FileOrganizationResult> OrganizeEpisodeFile(string path, TvFileOrganizationOptions options, bool overwriteExisting)
public async Task<FileOrganizationResult> OrganizeEpisodeFile(string path, TvFileOrganizationOptions options, bool overwriteExisting, CancellationToken cancellationToken)
{
_logger.Info("Sorting file {0}", path);
@ -77,7 +78,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
result.ExtractedEndingEpisodeNumber = endingEpisodeNumber;
OrganizeEpisode(path, seriesName, season.Value, episode.Value, endingEpisodeNumber, options, overwriteExisting, result);
await OrganizeEpisode(path, seriesName, season.Value, episode.Value, endingEpisodeNumber, options, overwriteExisting, result, cancellationToken).ConfigureAwait(false);
}
else
{
@ -119,20 +120,20 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
return result;
}
public async Task<FileOrganizationResult> OrganizeWithCorrection(EpisodeFileOrganizationRequest request, TvFileOrganizationOptions options)
public async Task<FileOrganizationResult> OrganizeWithCorrection(EpisodeFileOrganizationRequest request, TvFileOrganizationOptions options, CancellationToken cancellationToken)
{
var result = _organizationService.GetResult(request.ResultId);
var series = (Series)_libraryManager.GetItemById(new Guid(request.SeriesId));
OrganizeEpisode(result.OriginalPath, series, request.SeasonNumber, request.EpisodeNumber, request.EndingEpisodeNumber, _config.Configuration.TvFileOrganizationOptions, true, result);
await OrganizeEpisode(result.OriginalPath, series, request.SeasonNumber, request.EpisodeNumber, request.EndingEpisodeNumber, _config.Configuration.TvFileOrganizationOptions, true, result, cancellationToken).ConfigureAwait(false);
await _organizationService.SaveResult(result, CancellationToken.None).ConfigureAwait(false);
return result;
}
private void OrganizeEpisode(string sourcePath, string seriesName, int seasonNumber, int episodeNumber, int? endingEpiosdeNumber, TvFileOrganizationOptions options, bool overwriteExisting, FileOrganizationResult result)
private Task OrganizeEpisode(string sourcePath, string seriesName, int seasonNumber, int episodeNumber, int? endingEpiosdeNumber, TvFileOrganizationOptions options, bool overwriteExisting, FileOrganizationResult result, CancellationToken cancellationToken)
{
var series = GetMatchingSeries(seriesName, result);
@ -142,18 +143,18 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
result.Status = FileSortingStatus.Failure;
result.StatusMessage = msg;
_logger.Warn(msg);
return;
return Task.FromResult(true);
}
OrganizeEpisode(sourcePath, series, seasonNumber, episodeNumber, endingEpiosdeNumber, options, overwriteExisting, result);
return OrganizeEpisode(sourcePath, series, seasonNumber, episodeNumber, endingEpiosdeNumber, options, overwriteExisting, result, cancellationToken);
}
private void OrganizeEpisode(string sourcePath, Series series, int seasonNumber, int episodeNumber, int? endingEpiosdeNumber, TvFileOrganizationOptions options, bool overwriteExisting, FileOrganizationResult result)
private async Task OrganizeEpisode(string sourcePath, Series series, int seasonNumber, int episodeNumber, int? endingEpiosdeNumber, TvFileOrganizationOptions options, bool overwriteExisting, FileOrganizationResult result, CancellationToken cancellationToken)
{
_logger.Info("Sorting file {0} into series {1}", sourcePath, series.Path);
// Proceed to sort the file
var newPath = GetNewPath(sourcePath, series, seasonNumber, episodeNumber, endingEpiosdeNumber, options);
var newPath = await GetNewPath(sourcePath, series, seasonNumber, episodeNumber, endingEpiosdeNumber, options, cancellationToken).ConfigureAwait(false);
if (string.IsNullOrEmpty(newPath))
{
@ -326,25 +327,33 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
/// <param name="endingEpisodeNumber">The ending episode number.</param>
/// <param name="options">The options.</param>
/// <returns>System.String.</returns>
private string GetNewPath(string sourcePath, Series series, int seasonNumber, int episodeNumber, int? endingEpisodeNumber, TvFileOrganizationOptions options)
private async Task<string> GetNewPath(string sourcePath, Series series, int seasonNumber, int episodeNumber, int? endingEpisodeNumber, TvFileOrganizationOptions options, CancellationToken cancellationToken)
{
// If season and episode numbers match
var currentEpisodes = series.RecursiveChildren.OfType<Episode>()
.Where(i => i.IndexNumber.HasValue &&
i.IndexNumber.Value == episodeNumber &&
i.ParentIndexNumber.HasValue &&
i.ParentIndexNumber.Value == seasonNumber)
.ToList();
var episodeInfo = new EpisodeInfo
{
IndexNumber = episodeNumber,
IndexNumberEnd = endingEpisodeNumber,
MetadataCountryCode = series.GetPreferredMetadataCountryCode(),
MetadataLanguage = series.GetPreferredMetadataLanguage(),
ParentIndexNumber = seasonNumber,
SeriesProviderIds = series.ProviderIds
};
if (currentEpisodes.Count == 0)
var searchResults = await _providerManager.GetRemoteSearchResults<Episode, EpisodeInfo>(new RemoteSearchQuery<EpisodeInfo>
{
SearchInfo = episodeInfo
}, cancellationToken).ConfigureAwait(false);
var episode = searchResults.FirstOrDefault();
if (episode == null)
{
return null;
}
var newPath = GetSeasonFolderPath(series, seasonNumber, options);
var episode = currentEpisodes.First();
var episodeFileName = GetEpisodeFileName(sourcePath, series.Name, seasonNumber, episodeNumber, endingEpisodeNumber, episode.Name, options);
newPath = Path.Combine(newPath, episodeFileName);

View File

@ -3,9 +3,9 @@ using MediaBrowser.Common.IO;
using MediaBrowser.Common.ScheduledTasks;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.FileOrganization;
using MediaBrowser.Controller.IO;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Persistence;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.FileOrganization;
using MediaBrowser.Model.Logging;
using MediaBrowser.Model.Querying;
@ -25,8 +25,9 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
private readonly ILibraryManager _libraryManager;
private readonly IServerConfigurationManager _config;
private readonly IFileSystem _fileSystem;
private readonly IProviderManager _providerManager;
public FileOrganizationService(ITaskManager taskManager, IFileOrganizationRepository repo, ILogger logger, ILibraryMonitor libraryMonitor, ILibraryManager libraryManager, IServerConfigurationManager config, IFileSystem fileSystem)
public FileOrganizationService(ITaskManager taskManager, IFileOrganizationRepository repo, ILogger logger, ILibraryMonitor libraryMonitor, ILibraryManager libraryManager, IServerConfigurationManager config, IFileSystem fileSystem, IProviderManager providerManager)
{
_taskManager = taskManager;
_repo = repo;
@ -35,6 +36,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
_libraryManager = libraryManager;
_config = config;
_fileSystem = fileSystem;
_providerManager = providerManager;
}
public void BeginProcessNewFiles()
@ -103,9 +105,9 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
}
var organizer = new EpisodeFileOrganizer(this, _config, _fileSystem, _logger, _libraryManager,
_libraryMonitor);
_libraryMonitor, _providerManager);
await organizer.OrganizeEpisodeFile(result.OriginalPath, _config.Configuration.TvFileOrganizationOptions, true)
await organizer.OrganizeEpisodeFile(result.OriginalPath, _config.Configuration.TvFileOrganizationOptions, true, CancellationToken.None)
.ConfigureAwait(false);
}
@ -117,9 +119,9 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
public async Task PerformEpisodeOrganization(EpisodeFileOrganizationRequest request)
{
var organizer = new EpisodeFileOrganizer(this, _config, _fileSystem, _logger, _libraryManager,
_libraryMonitor);
_libraryMonitor, _providerManager);
await organizer.OrganizeWithCorrection(request, _config.Configuration.TvFileOrganizationOptions).ConfigureAwait(false);
await organizer.OrganizeWithCorrection(request, _config.Configuration.TvFileOrganizationOptions, CancellationToken.None).ConfigureAwait(false);
}
}
}

View File

@ -2,8 +2,8 @@
using MediaBrowser.Common.ScheduledTasks;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.FileOrganization;
using MediaBrowser.Controller.IO;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Model.Logging;
using System;
using System.Collections.Generic;
@ -20,8 +20,9 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
private readonly IFileSystem _fileSystem;
private readonly IServerConfigurationManager _config;
private readonly IFileOrganizationService _organizationService;
private readonly IProviderManager _providerManager;
public OrganizerScheduledTask(ILibraryMonitor libraryMonitor, ILibraryManager libraryManager, ILogger logger, IFileSystem fileSystem, IServerConfigurationManager config, IFileOrganizationService organizationService)
public OrganizerScheduledTask(ILibraryMonitor libraryMonitor, ILibraryManager libraryManager, ILogger logger, IFileSystem fileSystem, IServerConfigurationManager config, IFileOrganizationService organizationService, IProviderManager providerManager)
{
_libraryMonitor = libraryMonitor;
_libraryManager = libraryManager;
@ -29,6 +30,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
_fileSystem = fileSystem;
_config = config;
_organizationService = organizationService;
_providerManager = providerManager;
}
public string Name
@ -48,7 +50,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
public Task Execute(CancellationToken cancellationToken, IProgress<double> progress)
{
return new TvFolderOrganizer(_libraryManager, _logger, _fileSystem, _libraryMonitor, _organizationService, _config)
return new TvFolderOrganizer(_libraryManager, _logger, _fileSystem, _libraryMonitor, _organizationService, _config, _providerManager)
.Organize(_config.Configuration.TvFileOrganizationOptions, cancellationToken, progress);
}

View File

@ -1,8 +1,8 @@
using MediaBrowser.Common.IO;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.FileOrganization;
using MediaBrowser.Controller.IO;
using MediaBrowser.Controller.Library;
using MediaBrowser.Controller.Providers;
using MediaBrowser.Controller.Resolvers;
using MediaBrowser.Model.Configuration;
using MediaBrowser.Model.FileOrganization;
@ -24,8 +24,9 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
private readonly IFileSystem _fileSystem;
private readonly IFileOrganizationService _organizationService;
private readonly IServerConfigurationManager _config;
private readonly IProviderManager _providerManager;
public TvFolderOrganizer(ILibraryManager libraryManager, ILogger logger, IFileSystem fileSystem, ILibraryMonitor libraryMonitor, IFileOrganizationService organizationService, IServerConfigurationManager config)
public TvFolderOrganizer(ILibraryManager libraryManager, ILogger logger, IFileSystem fileSystem, ILibraryMonitor libraryMonitor, IFileOrganizationService organizationService, IServerConfigurationManager config, IProviderManager providerManager)
{
_libraryManager = libraryManager;
_logger = logger;
@ -33,6 +34,7 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
_libraryMonitor = libraryMonitor;
_organizationService = organizationService;
_config = config;
_providerManager = providerManager;
}
public async Task Organize(TvFileOrganizationOptions options, CancellationToken cancellationToken, IProgress<double> progress)
@ -57,9 +59,9 @@ namespace MediaBrowser.Server.Implementations.FileOrganization
foreach (var file in eligibleFiles)
{
var organizer = new EpisodeFileOrganizer(_organizationService, _config, _fileSystem, _logger, _libraryManager,
_libraryMonitor);
_libraryMonitor, _providerManager);
var result = await organizer.OrganizeEpisodeFile(file.FullName, options, false).ConfigureAwait(false);
var result = await organizer.OrganizeEpisodeFile(file.FullName, options, false, cancellationToken).ConfigureAwait(false);
if (result.Status == FileSortingStatus.Success)
{

View File

@ -1,4 +1,5 @@
using Funq;
using System.Net.Sockets;
using Funq;
using MediaBrowser.Common;
using MediaBrowser.Common.Extensions;
using MediaBrowser.Common.Net;

View File

@ -3,7 +3,6 @@ using MediaBrowser.Common.ScheduledTasks;
using MediaBrowser.Controller.Configuration;
using MediaBrowser.Controller.Entities;
using MediaBrowser.Controller.Library;
using MediaBrowser.Model.Entities;
using MediaBrowser.Model.Logging;
using MediaBrowser.Server.Implementations.ScheduledTasks;
using Microsoft.Win32;

View File

@ -408,8 +408,14 @@ namespace MediaBrowser.Server.Implementations.Library
LibraryItemsCache.AddOrUpdate(item.Id, item, delegate { return item; });
}
public async Task DeleteItem(BaseItem item)
public async Task DeleteItem(BaseItem item, DeleteOptions options)
{
_logger.Debug("Deleting item, Type: {0}, Name: {1}, Path: {2}, Id: {3}",
item.GetType().Name,
item.Name,
item.Path ?? string.Empty,
item.Id);
var parent = item.Parent;
var locationType = item.LocationType;
@ -436,7 +442,7 @@ namespace MediaBrowser.Server.Implementations.Library
}
}
if (locationType == LocationType.FileSystem || locationType == LocationType.Offline)
if (options.DeleteFileLocation && (locationType == LocationType.FileSystem || locationType == LocationType.Offline))
{
foreach (var path in item.GetDeletePaths().ToList())
{
@ -462,15 +468,14 @@ namespace MediaBrowser.Server.Implementations.Library
{
await parent.RemoveChild(item, CancellationToken.None).ConfigureAwait(false);
}
else
{
throw new InvalidOperationException("Don't know how to delete " + item.Name);
}
await ItemRepository.DeleteItem(item.Id, CancellationToken.None).ConfigureAwait(false);
foreach (var child in children)
{
await ItemRepository.DeleteItem(child.Id, CancellationToken.None).ConfigureAwait(false);
}
ReportItemRemoved(item);
}
private IEnumerable<string> GetMetadataPaths(BaseItem item, IEnumerable<BaseItem> children)

View File

@ -726,7 +726,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
foreach (var channelInfo in allChannelsList)
{
cancellationToken.ThrowIfCancellationRequested();
try
{
var item = await GetChannel(channelInfo.Item2, channelInfo.Item1, cancellationToken).ConfigureAwait(false);
@ -764,7 +764,7 @@ namespace MediaBrowser.Server.Implementations.LiveTv
foreach (var item in list)
{
cancellationToken.ThrowIfCancellationRequested();
// Avoid implicitly captured closure
var currentChannel = item;
@ -793,17 +793,44 @@ namespace MediaBrowser.Server.Implementations.LiveTv
double percent = numComplete;
percent /= allChannelsList.Count;
progress.Report(80 * percent + 10);
progress.Report(70 * percent + 10);
}
_programs = programs.ToDictionary(i => i.Id);
progress.Report(80);
// Load these now which will prefetch metadata
await GetRecordings(new RecordingQuery(), cancellationToken).ConfigureAwait(false);
progress.Report(85);
await DeleteOldPrograms(_programs.Keys.ToList(), progress, cancellationToken).ConfigureAwait(false);
progress.Report(100);
}
private async Task DeleteOldPrograms(List<Guid> currentIdList, IProgress<double> progress, CancellationToken cancellationToken)
{
var list = _itemRepo.GetItemsOfType(typeof(LiveTvProgram)).ToList();
var numComplete = 0;
foreach (var program in list)
{
cancellationToken.ThrowIfCancellationRequested();
if (!currentIdList.Contains(program.Id))
{
await _libraryManager.DeleteItem(program).ConfigureAwait(false);
}
numComplete++;
double percent = numComplete;
percent /= list.Count;
progress.Report(15 * percent + 85);
}
}
private double GetGuideDays(int channelCount)
{
if (_config.Configuration.LiveTvOptions.GuideDays.HasValue)

View File

@ -281,27 +281,32 @@ namespace MediaBrowser.Server.Implementations.Persistence
{
if (reader.Read())
{
var typeString = reader.GetString(0);
var type = _typeMapper.GetType(typeString);
if (type == null)
{
_logger.Debug("Unknown type {0}", typeString);
return null;
}
using (var stream = reader.GetMemoryStream(1))
{
return _jsonSerializer.DeserializeFromStream(stream, type) as BaseItem;
}
return GetItem(reader);
}
}
return null;
}
}
private BaseItem GetItem(IDataReader reader)
{
var typeString = reader.GetString(0);
var type = _typeMapper.GetType(typeString);
if (type == null)
{
_logger.Debug("Unknown type {0}", typeString);
return null;
}
using (var stream = reader.GetMemoryStream(1))
{
return _jsonSerializer.DeserializeFromStream(stream, type) as BaseItem;
}
}
/// <summary>
/// Gets the critic reviews.
/// </summary>
@ -468,6 +473,34 @@ namespace MediaBrowser.Server.Implementations.Persistence
}
}
public IEnumerable<BaseItem> GetItemsOfType(Type type)
{
if (type == null)
{
throw new ArgumentNullException("type");
}
using (var cmd = _connection.CreateCommand())
{
cmd.CommandText = "select type,data from TypedBaseItems where type = @type";
cmd.Parameters.Add(cmd, "@type", DbType.String).Value = type.FullName;
using (var reader = cmd.ExecuteReader(CommandBehavior.SequentialAccess | CommandBehavior.SingleResult))
{
while (reader.Read())
{
var item = GetItem(reader);
if (item != null)
{
yield return item;
}
}
}
}
}
public async Task DeleteItem(Guid id, CancellationToken cancellationToken)
{
if (id == Guid.Empty)

View File

@ -363,7 +363,7 @@ namespace MediaBrowser.ServerApplication
var newsService = new Server.Implementations.News.NewsService(ApplicationPaths, JsonSerializer);
RegisterSingleInstance<INewsService>(newsService);
var fileOrganizationService = new FileOrganizationService(TaskManager, FileOrganizationRepository, Logger, LibraryMonitor, LibraryManager, ServerConfigurationManager, FileSystemManager);
var fileOrganizationService = new FileOrganizationService(TaskManager, FileOrganizationRepository, Logger, LibraryMonitor, LibraryManager, ServerConfigurationManager, FileSystemManager, ProviderManager);
RegisterSingleInstance<IFileOrganizationService>(fileOrganizationService);
progress.Report(15);

View File

@ -16,15 +16,17 @@ namespace MediaBrowser.ServerApplication.Native
{
var shortcutPath = Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.StartMenu), "Media Browser 3", "Media Browser Server.lnk");
var startupPath = Environment.GetFolderPath(Environment.SpecialFolder.Startup);
if (autorun)
{
//Copy our shortut into the startup folder for this user
File.Copy(shortcutPath, Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Startup), Path.GetFileName(shortcutPath) ?? "MBstartup.lnk"), true);
File.Copy(shortcutPath, Path.Combine(startupPath, Path.GetFileName(shortcutPath) ?? "MBstartup.lnk"), true);
}
else
{
//Remove our shortcut from the startup folder for this user
File.Delete(Path.Combine(Environment.GetFolderPath(Environment.SpecialFolder.Startup), Path.GetFileName(shortcutPath) ?? "MBstartup.lnk"));
File.Delete(Path.Combine(startupPath, Path.GetFileName(shortcutPath) ?? "MBstartup.lnk"));
}
}
}

View File

@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata>
<id>MediaBrowser.Common.Internal</id>
<version>3.0.329</version>
<version>3.0.330</version>
<title>MediaBrowser.Common.Internal</title>
<authors>Luke</authors>
<owners>ebr,Luke,scottisafool</owners>
@ -12,7 +12,7 @@
<description>Contains common components shared by Media Browser Theater and Media Browser Server. Not intended for plugin developer consumption.</description>
<copyright>Copyright © Media Browser 2013</copyright>
<dependencies>
<dependency id="MediaBrowser.Common" version="3.0.329" />
<dependency id="MediaBrowser.Common" version="3.0.330" />
<dependency id="NLog" version="2.1.0" />
<dependency id="SimpleInjector" version="2.4.1" />
<dependency id="sharpcompress" version="0.10.2" />

View File

@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2011/08/nuspec.xsd">
<metadata>
<id>MediaBrowser.Common</id>
<version>3.0.329</version>
<version>3.0.330</version>
<title>MediaBrowser.Common</title>
<authors>Media Browser Team</authors>
<owners>ebr,Luke,scottisafool</owners>

View File

@ -2,7 +2,7 @@
<package xmlns="http://schemas.microsoft.com/packaging/2010/07/nuspec.xsd">
<metadata>
<id>MediaBrowser.Server.Core</id>
<version>3.0.329</version>
<version>3.0.330</version>
<title>Media Browser.Server.Core</title>
<authors>Media Browser Team</authors>
<owners>ebr,Luke,scottisafool</owners>
@ -12,7 +12,7 @@
<description>Contains core components required to build plugins for Media Browser Server.</description>
<copyright>Copyright © Media Browser 2013</copyright>
<dependencies>
<dependency id="MediaBrowser.Common" version="3.0.329" />
<dependency id="MediaBrowser.Common" version="3.0.330" />
</dependencies>
</metadata>
<files>