2018-08-05 14:28:05 +00:00
|
|
|
|
using System;
|
|
|
|
|
using System.Collections.Generic;
|
|
|
|
|
using System.Linq;
|
|
|
|
|
using NLog;
|
|
|
|
|
using NzbDrone.Common.Cache;
|
|
|
|
|
using NzbDrone.Common.Composition;
|
2018-09-10 19:25:10 +00:00
|
|
|
|
using NzbDrone.Core.Blacklisting;
|
|
|
|
|
using NzbDrone.Core.Datastore;
|
|
|
|
|
using NzbDrone.Core.History;
|
2019-12-18 02:17:47 +00:00
|
|
|
|
using NzbDrone.Core.Lifecycle;
|
2018-09-10 19:25:10 +00:00
|
|
|
|
using NzbDrone.Core.MediaFiles;
|
2019-12-18 02:17:47 +00:00
|
|
|
|
using NzbDrone.Core.Messaging.Events;
|
2018-08-05 14:28:05 +00:00
|
|
|
|
using NzbDrone.Core.Profiles;
|
|
|
|
|
|
|
|
|
|
namespace NzbDrone.Core.CustomFormats
|
|
|
|
|
{
|
|
|
|
|
public interface ICustomFormatService
|
|
|
|
|
{
|
|
|
|
|
void Update(CustomFormat customFormat);
|
|
|
|
|
CustomFormat Insert(CustomFormat customFormat);
|
|
|
|
|
List<CustomFormat> All();
|
|
|
|
|
CustomFormat GetById(int id);
|
2018-09-10 19:25:10 +00:00
|
|
|
|
void Delete(int id);
|
2018-08-05 14:28:05 +00:00
|
|
|
|
}
|
|
|
|
|
|
2019-12-18 02:17:47 +00:00
|
|
|
|
|
|
|
|
|
public class CustomFormatService : ICustomFormatService, IHandle<ApplicationStartedEvent>
|
2018-08-05 14:28:05 +00:00
|
|
|
|
{
|
|
|
|
|
private readonly ICustomFormatRepository _formatRepository;
|
|
|
|
|
private IProfileService _profileService;
|
2018-09-10 19:25:10 +00:00
|
|
|
|
private readonly IHistoryService _historyService;
|
2018-08-05 14:28:05 +00:00
|
|
|
|
|
|
|
|
|
public IProfileService ProfileService
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
if (_profileService == null)
|
|
|
|
|
{
|
|
|
|
|
_profileService = _container.Resolve<IProfileService>();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
return _profileService;
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private readonly IContainer _container;
|
|
|
|
|
private readonly ICached<Dictionary<int, CustomFormat>> _cache;
|
|
|
|
|
private readonly Logger _logger;
|
|
|
|
|
|
|
|
|
|
public static Dictionary<int, CustomFormat> AllCustomFormats;
|
|
|
|
|
|
|
|
|
|
public CustomFormatService(ICustomFormatRepository formatRepository, ICacheManager cacheManager,
|
2019-10-14 21:07:40 +00:00
|
|
|
|
IContainer container, IHistoryService historyService,
|
2018-08-05 14:28:05 +00:00
|
|
|
|
Logger logger)
|
|
|
|
|
{
|
|
|
|
|
_formatRepository = formatRepository;
|
|
|
|
|
_container = container;
|
|
|
|
|
_cache = cacheManager.GetCache<Dictionary<int, CustomFormat>>(typeof(CustomFormat), "formats");
|
2018-09-10 19:25:10 +00:00
|
|
|
|
_historyService = historyService;
|
2018-08-05 14:28:05 +00:00
|
|
|
|
_logger = logger;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public void Update(CustomFormat customFormat)
|
|
|
|
|
{
|
|
|
|
|
_formatRepository.Update(customFormat);
|
|
|
|
|
_cache.Clear();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public CustomFormat Insert(CustomFormat customFormat)
|
|
|
|
|
{
|
|
|
|
|
var ret = _formatRepository.Insert(customFormat);
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
ProfileService.AddCustomFormat(ret);
|
|
|
|
|
}
|
|
|
|
|
catch (Exception e)
|
|
|
|
|
{
|
2018-09-10 19:25:10 +00:00
|
|
|
|
_logger.Error(e, "Failure while trying to add the new custom format to all profiles. Deleting again!");
|
2018-08-05 14:28:05 +00:00
|
|
|
|
_formatRepository.Delete(ret);
|
|
|
|
|
throw;
|
|
|
|
|
}
|
|
|
|
|
_cache.Clear();
|
|
|
|
|
return ret;
|
|
|
|
|
}
|
|
|
|
|
|
2018-09-10 19:25:10 +00:00
|
|
|
|
public void Delete(int id)
|
|
|
|
|
{
|
|
|
|
|
_cache.Clear();
|
|
|
|
|
try
|
|
|
|
|
{
|
|
|
|
|
//First history:
|
|
|
|
|
var historyRepo = _container.Resolve<IHistoryRepository>();
|
|
|
|
|
DeleteInRepo(historyRepo, h => h.Quality.CustomFormats, (h, f) =>
|
|
|
|
|
{
|
|
|
|
|
h.Quality.CustomFormats = f;
|
|
|
|
|
return h;
|
|
|
|
|
}, id);
|
|
|
|
|
|
|
|
|
|
//Then Blacklist:
|
|
|
|
|
var blacklistRepo = _container.Resolve<IBlacklistRepository>();
|
|
|
|
|
DeleteInRepo(blacklistRepo, h => h.Quality.CustomFormats, (h, f) =>
|
|
|
|
|
{
|
|
|
|
|
h.Quality.CustomFormats = f;
|
|
|
|
|
return h;
|
|
|
|
|
}, id);
|
|
|
|
|
|
|
|
|
|
//Then MovieFiles:
|
|
|
|
|
var moviefileRepo = _container.Resolve<IMediaFileRepository>();
|
|
|
|
|
DeleteInRepo(moviefileRepo, h => h.Quality.CustomFormats, (h, f) =>
|
|
|
|
|
{
|
|
|
|
|
h.Quality.CustomFormats = f;
|
|
|
|
|
return h;
|
|
|
|
|
}, id);
|
|
|
|
|
|
|
|
|
|
//Then Profiles
|
|
|
|
|
ProfileService.DeleteCustomFormat(id);
|
|
|
|
|
}
|
|
|
|
|
catch (Exception e)
|
|
|
|
|
{
|
|
|
|
|
_logger.Error(e, "Failed to delete format with id {} from other repositories! Format will not be deleted!", id);
|
|
|
|
|
throw;
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
//Finally delete the format for real!
|
|
|
|
|
_formatRepository.Delete(id);
|
|
|
|
|
|
|
|
|
|
_cache.Clear();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
private void DeleteInRepo<TModel>(IBasicRepository<TModel> repository, Func<TModel, List<CustomFormat>> queryFunc,
|
|
|
|
|
Func<TModel, List<CustomFormat>, TModel> updateFunc, int customFormatId) where TModel : ModelBase, new()
|
|
|
|
|
{
|
2019-10-23 00:42:46 +00:00
|
|
|
|
var allItems = repository.All();
|
|
|
|
|
|
|
|
|
|
var toUpdate = allItems.Where(r => queryFunc(r).Exists(c => c.Id == customFormatId)).Select(r =>
|
2018-09-10 19:25:10 +00:00
|
|
|
|
{
|
2019-10-23 00:42:46 +00:00
|
|
|
|
return updateFunc(r, queryFunc(r).Where(c => c.Id != customFormatId).ToList());
|
|
|
|
|
});
|
|
|
|
|
|
|
|
|
|
repository.UpdateMany(toUpdate.ToList());
|
2018-09-10 19:25:10 +00:00
|
|
|
|
}
|
|
|
|
|
|
2018-08-05 14:28:05 +00:00
|
|
|
|
private Dictionary<int, CustomFormat> AllDictionary()
|
|
|
|
|
{
|
|
|
|
|
return _cache.Get("all", () =>
|
|
|
|
|
{
|
2019-12-18 02:17:47 +00:00
|
|
|
|
var all = _formatRepository.All().ToDictionary(m => m.Id);
|
2018-08-05 14:28:05 +00:00
|
|
|
|
AllCustomFormats = all;
|
|
|
|
|
return all;
|
|
|
|
|
});
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public List<CustomFormat> All()
|
|
|
|
|
{
|
|
|
|
|
return AllDictionary().Values.ToList();
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public CustomFormat GetById(int id)
|
|
|
|
|
{
|
|
|
|
|
return AllDictionary()[id];
|
|
|
|
|
}
|
|
|
|
|
|
|
|
|
|
public static Dictionary<string, List<CustomFormat>> Templates
|
|
|
|
|
{
|
|
|
|
|
get
|
|
|
|
|
{
|
|
|
|
|
return new Dictionary<string, List<CustomFormat>>
|
|
|
|
|
{
|
|
|
|
|
{
|
|
|
|
|
"Easy", new List<CustomFormat>
|
|
|
|
|
{
|
2019-05-02 10:55:48 +00:00
|
|
|
|
new CustomFormat("x264", @"C_RX_(x|h)\.?264"),
|
|
|
|
|
new CustomFormat("x265", @"C_RX_(((x|h)\.?265)|(HEVC))"),
|
2018-09-12 14:44:38 +00:00
|
|
|
|
new CustomFormat("Simple Hardcoded Subs", "C_RX_subs?"),
|
2018-08-05 14:28:05 +00:00
|
|
|
|
new CustomFormat("Multi Language", "L_English", "L_French")
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"Intermediate", new List<CustomFormat>
|
|
|
|
|
{
|
2018-09-12 14:44:38 +00:00
|
|
|
|
new CustomFormat("Hardcoded Subs", @"C_RX_\b(?<hcsub>(\w+SUBS?)\b)|(?<hc>(HC|SUBBED))\b"),
|
|
|
|
|
new CustomFormat("Surround", @"C_RX_\b((7|5).1)\b"),
|
|
|
|
|
new CustomFormat("Preferred Words", @"C_RX_\b(SPARKS|Framestor)\b"),
|
2018-08-05 14:28:05 +00:00
|
|
|
|
new CustomFormat("Scene", @"I_G_Scene"),
|
|
|
|
|
new CustomFormat("Internal Releases", @"I_HDB_Internal", @"I_AHD_Internal")
|
|
|
|
|
}
|
|
|
|
|
},
|
|
|
|
|
{
|
|
|
|
|
"Advanced", new List<CustomFormat>
|
|
|
|
|
{
|
|
|
|
|
new CustomFormat("Custom")
|
|
|
|
|
}
|
|
|
|
|
}
|
|
|
|
|
};
|
|
|
|
|
}
|
|
|
|
|
}
|
2019-12-18 02:17:47 +00:00
|
|
|
|
|
|
|
|
|
public void Handle(ApplicationStartedEvent message)
|
|
|
|
|
{
|
|
|
|
|
// Fillup cache for DataMapper.
|
|
|
|
|
All();
|
|
|
|
|
}
|
2018-08-05 14:28:05 +00:00
|
|
|
|
}
|
|
|
|
|
}
|