mirror of
https://github.com/Readarr/Readarr.git
synced 2026-04-23 22:25:09 -04:00
Anime!
New: Anime support New: pull alternate names from thexem.de New: Search using all alternate names (if rage ID is unavailable) New: Show scene mapping information when hovering over episode number New: Full season searching for anime (searches for each episode) New: animezb.com anime indexer New: Treat BD as bluray Fixed: Parsing of 2 digit absolute episode numbers Fixed: Loading series details page for series that start with period Fixed: Return 0 results when manual search fails, instead of an error Fixed: animezb URL
This commit is contained in:
@@ -0,0 +1,9 @@
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace NzbDrone.Core.DataAugmentation.Scene
|
||||
{
|
||||
public interface ISceneMappingProvider
|
||||
{
|
||||
List<SceneMapping> GetSceneMappings();
|
||||
}
|
||||
}
|
||||
@@ -16,5 +16,7 @@ namespace NzbDrone.Core.DataAugmentation.Scene
|
||||
|
||||
[JsonProperty("season")]
|
||||
public int SeasonNumber { get; set; }
|
||||
|
||||
public string Type { get; set; }
|
||||
}
|
||||
}
|
||||
@@ -1,3 +1,4 @@
|
||||
using System;
|
||||
using NzbDrone.Core.Datastore;
|
||||
using NzbDrone.Core.Messaging.Events;
|
||||
using System.Collections.Generic;
|
||||
@@ -8,6 +9,7 @@ namespace NzbDrone.Core.DataAugmentation.Scene
|
||||
public interface ISceneMappingRepository : IBasicRepository<SceneMapping>
|
||||
{
|
||||
List<SceneMapping> FindByTvdbid(int tvdbId);
|
||||
void Clear(string type);
|
||||
}
|
||||
|
||||
public class SceneMappingRepository : BasicRepository<SceneMapping>, ISceneMappingRepository
|
||||
@@ -21,5 +23,10 @@ namespace NzbDrone.Core.DataAugmentation.Scene
|
||||
{
|
||||
return Query.Where(x => x.TvdbId == tvdbId);
|
||||
}
|
||||
|
||||
public void Clear(string type)
|
||||
{
|
||||
Delete(s => s.Type == type);
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,6 +1,7 @@
|
||||
using System;
|
||||
using System.Linq;
|
||||
using NLog;
|
||||
using NzbDrone.Common;
|
||||
using NzbDrone.Common.Cache;
|
||||
using NzbDrone.Core.Lifecycle;
|
||||
using NzbDrone.Core.Messaging.Commands;
|
||||
@@ -12,45 +13,52 @@ namespace NzbDrone.Core.DataAugmentation.Scene
|
||||
{
|
||||
public interface ISceneMappingService
|
||||
{
|
||||
string GetSceneName(int tvdbId);
|
||||
Nullable<int> GetTvDbId(string cleanName);
|
||||
List<String> GetSceneNames(int tvdbId, IEnumerable<Int32> seasonNumbers);
|
||||
Nullable<int> GetTvDbId(string title);
|
||||
List<SceneMapping> FindByTvdbid(int tvdbId);
|
||||
Nullable<Int32> GetSeasonNumber(string title);
|
||||
}
|
||||
|
||||
public class SceneMappingService : ISceneMappingService,
|
||||
IHandleAsync<ApplicationStartedEvent>,
|
||||
IExecute<UpdateSceneMappingCommand>
|
||||
IHandleAsync<ApplicationStartedEvent>,
|
||||
IExecute<UpdateSceneMappingCommand>
|
||||
{
|
||||
private readonly ISceneMappingRepository _repository;
|
||||
private readonly ISceneMappingProxy _sceneMappingProxy;
|
||||
private readonly IEnumerable<ISceneMappingProvider> _sceneMappingProviders;
|
||||
private readonly Logger _logger;
|
||||
private readonly ICached<SceneMapping> _getSceneNameCache;
|
||||
private readonly ICached<SceneMapping> _gettvdbIdCache;
|
||||
private readonly ICached<List<SceneMapping>> _findbytvdbIdCache;
|
||||
|
||||
public SceneMappingService(ISceneMappingRepository repository, ISceneMappingProxy sceneMappingProxy, ICacheManager cacheManager, Logger logger)
|
||||
public SceneMappingService(ISceneMappingRepository repository,
|
||||
ICacheManager cacheManager,
|
||||
IEnumerable<ISceneMappingProvider> sceneMappingProviders,
|
||||
Logger logger)
|
||||
{
|
||||
_repository = repository;
|
||||
_sceneMappingProxy = sceneMappingProxy;
|
||||
_sceneMappingProviders = sceneMappingProviders;
|
||||
|
||||
_getSceneNameCache = cacheManager.GetCache<SceneMapping>(GetType(), "scene_name");
|
||||
_gettvdbIdCache = cacheManager.GetCache<SceneMapping>(GetType(), "tvdb_id");
|
||||
_findbytvdbIdCache = cacheManager.GetCache<List<SceneMapping>>(GetType(), "find_tvdb_id");
|
||||
_logger = logger;
|
||||
}
|
||||
|
||||
public string GetSceneName(int tvdbId)
|
||||
public List<String> GetSceneNames(int tvdbId, IEnumerable<Int32> seasonNumbers)
|
||||
{
|
||||
var mapping = _getSceneNameCache.Find(tvdbId.ToString());
|
||||
var names = _findbytvdbIdCache.Find(tvdbId.ToString());
|
||||
|
||||
if (mapping == null) return null;
|
||||
if (names == null)
|
||||
{
|
||||
return new List<String>();
|
||||
}
|
||||
|
||||
return mapping.SearchTerm;
|
||||
return FilterNonEnglish(names.Where(s => seasonNumbers.Contains(s.SeasonNumber) ||
|
||||
s.SeasonNumber == -1)
|
||||
.Select(m => m.SearchTerm).Distinct().ToList());
|
||||
}
|
||||
|
||||
public Nullable<Int32> GetTvDbId(string cleanName)
|
||||
public Nullable<Int32> GetTvDbId(string title)
|
||||
{
|
||||
var mapping = _gettvdbIdCache.Find(cleanName.CleanSeriesTitle());
|
||||
var mapping = _gettvdbIdCache.Find(title.CleanSeriesTitle());
|
||||
|
||||
if (mapping == null)
|
||||
return null;
|
||||
@@ -60,60 +68,87 @@ namespace NzbDrone.Core.DataAugmentation.Scene
|
||||
|
||||
public List<SceneMapping> FindByTvdbid(int tvdbId)
|
||||
{
|
||||
return _findbytvdbIdCache.Find(tvdbId.ToString());
|
||||
var mappings = _findbytvdbIdCache.Find(tvdbId.ToString());
|
||||
|
||||
if (mappings == null)
|
||||
{
|
||||
return new List<SceneMapping>();
|
||||
}
|
||||
|
||||
return mappings;
|
||||
}
|
||||
|
||||
public Nullable<Int32> GetSeasonNumber(string title)
|
||||
{
|
||||
//TODO: we should be able to override xem aliases with ones from services
|
||||
//Example Fairy Tail - Alias is assigned to season 2 (anidb), but we're still using tvdb for everything
|
||||
|
||||
var mapping = _gettvdbIdCache.Find(title.CleanSeriesTitle());
|
||||
|
||||
if (mapping == null)
|
||||
return null;
|
||||
|
||||
return mapping.SeasonNumber;
|
||||
}
|
||||
|
||||
private void UpdateMappings()
|
||||
{
|
||||
_logger.Info("Updating Scene mapping");
|
||||
_logger.Info("Updating Scene mappings");
|
||||
|
||||
try
|
||||
foreach (var sceneMappingProvider in _sceneMappingProviders)
|
||||
{
|
||||
var mappings = _sceneMappingProxy.Fetch();
|
||||
|
||||
if (mappings.Any())
|
||||
try
|
||||
{
|
||||
_repository.Purge();
|
||||
var mappings = sceneMappingProvider.GetSceneMappings();
|
||||
|
||||
foreach (var sceneMapping in mappings)
|
||||
if (mappings.Any())
|
||||
{
|
||||
sceneMapping.ParseTerm = sceneMapping.Title.CleanSeriesTitle();
|
||||
_repository.Clear(sceneMappingProvider.GetType().Name);
|
||||
|
||||
foreach (var sceneMapping in mappings)
|
||||
{
|
||||
sceneMapping.ParseTerm = sceneMapping.Title.CleanSeriesTitle();
|
||||
sceneMapping.Type = sceneMappingProvider.GetType().Name;
|
||||
}
|
||||
|
||||
_repository.InsertMany(mappings.DistinctBy(s => s.ParseTerm).ToList());
|
||||
}
|
||||
else
|
||||
{
|
||||
_logger.Warn("Received empty list of mapping. will not update.");
|
||||
}
|
||||
|
||||
_repository.InsertMany(mappings);
|
||||
}
|
||||
else
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.Warn("Received empty list of mapping. will not update.");
|
||||
_logger.ErrorException("Failed to Update Scene Mappings:", ex);
|
||||
}
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
_logger.ErrorException("Failed to Update Scene Mappings:", ex);
|
||||
}
|
||||
|
||||
|
||||
RefreshCache();
|
||||
}
|
||||
|
||||
private void RefreshCache()
|
||||
{
|
||||
var mappings = _repository.All();
|
||||
var mappings = _repository.All().ToList();
|
||||
|
||||
_gettvdbIdCache.Clear();
|
||||
_getSceneNameCache.Clear();
|
||||
_findbytvdbIdCache.Clear();
|
||||
|
||||
foreach (var sceneMapping in mappings)
|
||||
{
|
||||
_getSceneNameCache.Set(sceneMapping.TvdbId.ToString(), sceneMapping);
|
||||
_gettvdbIdCache.Set(sceneMapping.ParseTerm.CleanSeriesTitle(), sceneMapping);
|
||||
}
|
||||
|
||||
foreach (var sceneMapping in mappings.GroupBy(x => x.TvdbId))
|
||||
{
|
||||
_findbytvdbIdCache.Set(sceneMapping.Key.ToString(), sceneMapping.ToList());
|
||||
}
|
||||
}
|
||||
|
||||
private List<String> FilterNonEnglish(List<String> titles)
|
||||
{
|
||||
return titles.Where(title => title.All(c => c <= 255)).ToList();
|
||||
}
|
||||
|
||||
public void HandleAsync(ApplicationStartedEvent message)
|
||||
{
|
||||
|
||||
@@ -0,0 +1,20 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
|
||||
namespace NzbDrone.Core.DataAugmentation.Scene
|
||||
{
|
||||
public class ServicesProvider : ISceneMappingProvider
|
||||
{
|
||||
private readonly ISceneMappingProxy _sceneMappingProxy;
|
||||
|
||||
public ServicesProvider(ISceneMappingProxy sceneMappingProxy)
|
||||
{
|
||||
_sceneMappingProxy = sceneMappingProxy;
|
||||
}
|
||||
|
||||
public List<SceneMapping> GetSceneMappings()
|
||||
{
|
||||
return _sceneMappingProxy.Fetch();
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,7 +1,9 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using Newtonsoft.Json.Linq;
|
||||
using NLog;
|
||||
using NzbDrone.Core.DataAugmentation.Scene;
|
||||
using NzbDrone.Core.DataAugmentation.Xem.Model;
|
||||
using NzbDrone.Core.Rest;
|
||||
using RestSharp;
|
||||
@@ -12,6 +14,7 @@ namespace NzbDrone.Core.DataAugmentation.Xem
|
||||
{
|
||||
List<int> GetXemSeriesIds();
|
||||
List<XemSceneTvdbMapping> GetSceneTvdbMappings(int id);
|
||||
List<SceneMapping> GetSceneTvdbNames();
|
||||
}
|
||||
|
||||
public class XemProxy : IXemProxy
|
||||
@@ -65,6 +68,47 @@ namespace NzbDrone.Core.DataAugmentation.Xem
|
||||
return response.Data.Where(c => c.Scene != null).ToList();
|
||||
}
|
||||
|
||||
public List<SceneMapping> GetSceneTvdbNames()
|
||||
{
|
||||
_logger.Debug("Fetching alternate names");
|
||||
var restClient = new RestClient(XEM_BASE_URL);
|
||||
|
||||
var request = BuildRequest("allNames");
|
||||
request.AddParameter("origin", "tvdb");
|
||||
//request.AddParameter("language", "us");
|
||||
request.AddParameter("seasonNumbers", true);
|
||||
|
||||
var response = restClient.ExecuteAndValidate<XemResult<Dictionary<Int32, List<JObject>>>>(request);
|
||||
CheckForFailureResult(response);
|
||||
|
||||
var result = new List<SceneMapping>();
|
||||
|
||||
foreach (var series in response.Data)
|
||||
{
|
||||
foreach (var name in series.Value)
|
||||
{
|
||||
foreach (var n in name)
|
||||
{
|
||||
int seasonNumber;
|
||||
if (!Int32.TryParse(n.Value.ToString(), out seasonNumber))
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
result.Add(new SceneMapping
|
||||
{
|
||||
Title = n.Key,
|
||||
SearchTerm = n.Key,
|
||||
SeasonNumber = seasonNumber,
|
||||
TvdbId = series.Key
|
||||
});
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
return result;
|
||||
}
|
||||
|
||||
private static void CheckForFailureResult<T>(XemResult<T> response)
|
||||
{
|
||||
if (response.Result.Equals("failure", StringComparison.InvariantCultureIgnoreCase) &&
|
||||
@@ -73,7 +117,5 @@ namespace NzbDrone.Core.DataAugmentation.Xem
|
||||
throw new Exception("Error response received from Xem: " + response.Message);
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,14 +1,16 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using NLog;
|
||||
using NzbDrone.Common.Cache;
|
||||
using NzbDrone.Core.DataAugmentation.Scene;
|
||||
using NzbDrone.Core.Messaging.Events;
|
||||
using NzbDrone.Core.Tv;
|
||||
using NzbDrone.Core.Tv.Events;
|
||||
|
||||
namespace NzbDrone.Core.DataAugmentation.Xem
|
||||
{
|
||||
public class XemService : IHandle<SeriesUpdatedEvent>, IHandle<SeriesRefreshStartingEvent>
|
||||
public class XemService : ISceneMappingProvider, IHandle<SeriesUpdatedEvent>, IHandle<SeriesRefreshStartingEvent>
|
||||
{
|
||||
private readonly IEpisodeService _episodeService;
|
||||
private readonly IXemProxy _xemProxy;
|
||||
@@ -47,7 +49,7 @@ namespace NzbDrone.Core.DataAugmentation.Xem
|
||||
|
||||
foreach (var episode in episodes)
|
||||
{
|
||||
episode.AbsoluteEpisodeNumber = 0;
|
||||
episode.SceneAbsoluteEpisodeNumber = 0;
|
||||
episode.SceneSeasonNumber = 0;
|
||||
episode.SceneEpisodeNumber = 0;
|
||||
}
|
||||
@@ -64,7 +66,7 @@ namespace NzbDrone.Core.DataAugmentation.Xem
|
||||
continue;
|
||||
}
|
||||
|
||||
episode.AbsoluteEpisodeNumber = mapping.Scene.Absolute;
|
||||
episode.SceneAbsoluteEpisodeNumber = mapping.Scene.Absolute;
|
||||
episode.SceneSeasonNumber = mapping.Scene.Season;
|
||||
episode.SceneEpisodeNumber = mapping.Scene.Episode;
|
||||
}
|
||||
@@ -96,6 +98,24 @@ namespace NzbDrone.Core.DataAugmentation.Xem
|
||||
}
|
||||
}
|
||||
|
||||
public List<SceneMapping> GetSceneMappings()
|
||||
{
|
||||
var mappings = _xemProxy.GetSceneTvdbNames();
|
||||
|
||||
return mappings.Where(m =>
|
||||
{
|
||||
int id;
|
||||
|
||||
if (Int32.TryParse(m.Title, out id))
|
||||
{
|
||||
_logger.Debug("Skipping all numeric name: {0} for {1}", m.Title, m.TvdbId);
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}).ToList();
|
||||
}
|
||||
|
||||
public void Handle(SeriesUpdatedEvent message)
|
||||
{
|
||||
if (_cache.Count == 0)
|
||||
|
||||
Reference in New Issue
Block a user