New: Lidarr to Readarr

This commit is contained in:
Qstick
2020-02-29 15:51:29 -05:00
parent 7359c2a9fa
commit 3b7eb01918
565 changed files with 1669 additions and 4272 deletions
@@ -0,0 +1,131 @@
using System.Collections.Generic;
using System.IO;
using System.Linq;
using NzbDrone.Common.Crypto;
using NzbDrone.Common.Disk;
using NzbDrone.Common.EnvironmentInfo;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.Backup;
using Readarr.Http;
using Readarr.Http.REST;
namespace Readarr.Api.V1.System.Backup
{
public class BackupModule : ReadarrRestModule<BackupResource>
{
private readonly IBackupService _backupService;
private readonly IAppFolderInfo _appFolderInfo;
private readonly IDiskProvider _diskProvider;
private static readonly List<string> ValidExtensions = new List<string> { ".zip", ".db", ".xml" };
public BackupModule(IBackupService backupService,
IAppFolderInfo appFolderInfo,
IDiskProvider diskProvider)
: base("system/backup")
{
_backupService = backupService;
_appFolderInfo = appFolderInfo;
_diskProvider = diskProvider;
GetResourceAll = GetBackupFiles;
DeleteResource = DeleteBackup;
Post(@"/restore/(?<id>[\d]{1,10})", x => Restore((int)x.Id));
Post("/restore/upload", x => UploadAndRestore());
}
public List<BackupResource> GetBackupFiles()
{
var backups = _backupService.GetBackups();
return backups.Select(b => new BackupResource
{
Id = GetBackupId(b),
Name = b.Name,
Path = $"/backup/{b.Type.ToString().ToLower()}/{b.Name}",
Type = b.Type,
Time = b.Time
})
.OrderByDescending(b => b.Time)
.ToList();
}
private void DeleteBackup(int id)
{
var backup = GetBackup(id);
var path = GetBackupPath(backup);
if (!_diskProvider.FileExists(path))
{
throw new NotFoundException();
}
_diskProvider.DeleteFile(path);
}
public object Restore(int id)
{
var backup = GetBackup(id);
if (backup == null)
{
throw new NotFoundException();
}
var path = GetBackupPath(backup);
_backupService.Restore(path);
return new
{
RestartRequired = true
};
}
public object UploadAndRestore()
{
var files = Context.Request.Files.ToList();
if (files.Empty())
{
throw new BadRequestException("file must be provided");
}
var file = files.First();
var extension = Path.GetExtension(file.Name);
if (!ValidExtensions.Contains(extension))
{
throw new UnsupportedMediaTypeException($"Invalid extension, must be one of: {ValidExtensions.Join(", ")}");
}
var path = Path.Combine(_appFolderInfo.TempFolder, $"readarr_backup_restore{extension}");
_diskProvider.SaveStream(file.Value, path);
_backupService.Restore(path);
// Cleanup restored file
_diskProvider.DeleteFile(path);
return new
{
RestartRequired = true
};
}
private string GetBackupPath(NzbDrone.Core.Backup.Backup backup)
{
return Path.Combine(_backupService.GetBackupFolder(backup.Type), backup.Name);
}
private int GetBackupId(NzbDrone.Core.Backup.Backup backup)
{
return HashConverter.GetHashInt31($"backup-{backup.Type}-{backup.Name}");
}
private NzbDrone.Core.Backup.Backup GetBackup(int id)
{
return _backupService.GetBackups().SingleOrDefault(b => GetBackupId(b) == id);
}
}
}
@@ -0,0 +1,14 @@
using System;
using NzbDrone.Core.Backup;
using Readarr.Http.REST;
namespace Readarr.Api.V1.System.Backup
{
public class BackupResource : RestResource
{
public string Name { get; set; }
public string Path { get; set; }
public BackupType Type { get; set; }
public DateTime Time { get; set; }
}
}
+95
View File
@@ -0,0 +1,95 @@
using System.Threading.Tasks;
using Nancy.Routing;
using NzbDrone.Common.EnvironmentInfo;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.Configuration;
using NzbDrone.Core.Datastore;
using NzbDrone.Core.Lifecycle;
namespace Readarr.Api.V1.System
{
public class SystemModule : ReadarrV1Module
{
private readonly IAppFolderInfo _appFolderInfo;
private readonly IRuntimeInfo _runtimeInfo;
private readonly IPlatformInfo _platformInfo;
private readonly IOsInfo _osInfo;
private readonly IRouteCacheProvider _routeCacheProvider;
private readonly IConfigFileProvider _configFileProvider;
private readonly IMainDatabase _database;
private readonly ILifecycleService _lifecycleService;
public SystemModule(IAppFolderInfo appFolderInfo,
IRuntimeInfo runtimeInfo,
IPlatformInfo platformInfo,
IOsInfo osInfo,
IRouteCacheProvider routeCacheProvider,
IConfigFileProvider configFileProvider,
IMainDatabase database,
ILifecycleService lifecycleService)
: base("system")
{
_appFolderInfo = appFolderInfo;
_runtimeInfo = runtimeInfo;
_platformInfo = platformInfo;
_osInfo = osInfo;
_routeCacheProvider = routeCacheProvider;
_configFileProvider = configFileProvider;
_database = database;
_lifecycleService = lifecycleService;
Get("/status", x => GetStatus());
Get("/routes", x => GetRoutes());
Post("/shutdown", x => Shutdown());
Post("/restart", x => Restart());
}
private object GetStatus()
{
return new
{
Version = BuildInfo.Version.ToString(),
BuildTime = BuildInfo.BuildDateTime,
IsDebug = BuildInfo.IsDebug,
IsProduction = RuntimeInfo.IsProduction,
IsAdmin = _runtimeInfo.IsAdmin,
IsUserInteractive = RuntimeInfo.IsUserInteractive,
StartupPath = _appFolderInfo.StartUpFolder,
AppData = _appFolderInfo.GetAppDataPath(),
OsName = _osInfo.Name,
OsVersion = _osInfo.Version,
IsNetCore = PlatformInfo.IsNetCore,
IsMono = PlatformInfo.IsMono,
IsLinux = OsInfo.IsLinux,
IsOsx = OsInfo.IsOsx,
IsWindows = OsInfo.IsWindows,
IsDocker = _osInfo.IsDocker,
Mode = _runtimeInfo.Mode,
Branch = _configFileProvider.Branch,
Authentication = _configFileProvider.AuthenticationMethod,
SqliteVersion = _database.Version,
MigrationVersion = _database.Migration,
UrlBase = _configFileProvider.UrlBase,
RuntimeVersion = _platformInfo.Version,
RuntimeName = PlatformInfo.Platform,
StartTime = _runtimeInfo.StartTime
};
}
private object GetRoutes()
{
return _routeCacheProvider.GetCache().Values;
}
private object Shutdown()
{
Task.Factory.StartNew(() => _lifecycleService.Shutdown());
return new { ShuttingDown = true };
}
private object Restart()
{
Task.Factory.StartNew(() => _lifecycleService.Restart());
return new { Restarting = true };
}
}
}
@@ -0,0 +1,66 @@
using System.Collections.Generic;
using System.Linq;
using NzbDrone.Common.Extensions;
using NzbDrone.Core.Datastore.Events;
using NzbDrone.Core.Jobs;
using NzbDrone.Core.Messaging.Events;
using NzbDrone.SignalR;
using Readarr.Http;
namespace Readarr.Api.V1.System.Tasks
{
public class TaskModule : ReadarrRestModuleWithSignalR<TaskResource, ScheduledTask>, IHandle<CommandExecutedEvent>
{
private readonly ITaskManager _taskManager;
public TaskModule(ITaskManager taskManager, IBroadcastSignalRMessage broadcastSignalRMessage)
: base(broadcastSignalRMessage, "system/task")
{
_taskManager = taskManager;
GetResourceAll = GetAll;
GetResourceById = GetTask;
}
private List<TaskResource> GetAll()
{
return _taskManager.GetAll()
.Select(ConvertToResource)
.OrderBy(t => t.Name)
.ToList();
}
private TaskResource GetTask(int id)
{
var task = _taskManager.GetAll()
.SingleOrDefault(t => t.Id == id);
if (task == null)
{
return null;
}
return ConvertToResource(task);
}
private static TaskResource ConvertToResource(ScheduledTask scheduledTask)
{
var taskName = scheduledTask.TypeName.Split('.').Last().Replace("Command", "");
return new TaskResource
{
Id = scheduledTask.Id,
Name = taskName.SplitCamelCase(),
TaskName = taskName,
Interval = scheduledTask.Interval,
LastExecution = scheduledTask.LastExecution,
LastStartTime = scheduledTask.LastStartTime,
NextExecution = scheduledTask.LastExecution.AddMinutes(scheduledTask.Interval)
};
}
public void Handle(CommandExecutedEvent message)
{
BroadcastResourceChange(ModelAction.Sync);
}
}
}
@@ -0,0 +1,17 @@
using System;
using Readarr.Http.REST;
namespace Readarr.Api.V1.System.Tasks
{
public class TaskResource : RestResource
{
public string Name { get; set; }
public string TaskName { get; set; }
public int Interval { get; set; }
public DateTime LastExecution { get; set; }
public DateTime LastStartTime { get; set; }
public DateTime NextExecution { get; set; }
public TimeSpan LastDuration => LastExecution - LastStartTime;
}
}