diff --git a/server/RdtClient.Data/Enums/DownloadClient.cs b/server/RdtClient.Data/Enums/DownloadClient.cs index dd31e51..3450b52 100644 --- a/server/RdtClient.Data/Enums/DownloadClient.cs +++ b/server/RdtClient.Data/Enums/DownloadClient.cs @@ -18,4 +18,7 @@ public enum DownloadClient [Description("Synology DownloadStation")] DownloadStation, + + [Description("Strm Downloader")] + Strm } \ No newline at end of file diff --git a/server/RdtClient.Service.Test/Services/Downloaders/StrmDownloaderTest.cs b/server/RdtClient.Service.Test/Services/Downloaders/StrmDownloaderTest.cs new file mode 100644 index 0000000..e323ce7 --- /dev/null +++ b/server/RdtClient.Service.Test/Services/Downloaders/StrmDownloaderTest.cs @@ -0,0 +1,43 @@ +using System.IO.Abstractions; +using System.IO.Abstractions.TestingHelpers; +using Moq; +using RdtClient.Service.Services.Downloaders; + +namespace RdtClient.Service.Test.Services.Downloaders; + +public class StrmDownloaderTest +{ + [Fact] + public async Task Download_WhenFileCreatedSuccesfully_RaisesDownloadCompleteEvent() + { + var mockFileSystem = new MockFileSystem(); + var strmDownloader = new StrmDownloader("http://example.com/video.mp4", "video.mp4", mockFileSystem); + + await Assert.RaisesAsync(a => strmDownloader.DownloadComplete += a, + a => strmDownloader.DownloadComplete -= a, + strmDownloader.Download); + + Assert.True(mockFileSystem.FileExists("video.mp4.strm")); + Assert.Equal(await mockFileSystem.File.ReadAllTextAsync("video.mp4.strm"), "http://example.com/video.mp4"); + } + + [Fact] + public async Task Download_WhenErrorCreatingFile_RaisesDownloadCompleteEventWithError() + { + // Arrange + var mockFileSystem = new Mock(); + mockFileSystem.Setup(fs => fs.File.WriteAllTextAsync(It.IsAny(), It.IsAny(), It.IsAny())) + .ThrowsAsync(new IOException("File write error")); + + var strmDownloader = new StrmDownloader("http://example.com/video.mp4", "video.mp4", mockFileSystem.Object); + + // Act & Assert + var raisedEvent = await Assert.RaisesAsync( + a => strmDownloader.DownloadComplete += a, + a => strmDownloader.DownloadComplete -= a, + strmDownloader.Download); + + Assert.NotNull(raisedEvent); + Assert.False(String.IsNullOrWhiteSpace(raisedEvent.Arguments.Error)); + } +} diff --git a/server/RdtClient.Service/Services/DownloadClient.cs b/server/RdtClient.Service/Services/DownloadClient.cs index 989c9c7..33d2ac4 100644 --- a/server/RdtClient.Service/Services/DownloadClient.cs +++ b/server/RdtClient.Service/Services/DownloadClient.cs @@ -1,4 +1,5 @@ -using RdtClient.Data.Enums; +using System.IO.Abstractions; +using RdtClient.Data.Enums; using RdtClient.Data.Models.Data; using RdtClient.Service.Helpers; using RdtClient.Service.Services.Downloaders; @@ -6,7 +7,7 @@ using RdtClient.Service.Services.TorrentClients; namespace RdtClient.Service.Services; -public class DownloadClient(Download download, Torrent torrent, String destinationPath, String? category) +public class DownloadClient(Download download, Torrent torrent, String destinationPath, String? category, IFileSystem fileSystem) { private static Int64 _totalBytesDownloadedThisSession; private static readonly Lock TotalBytesDownloadedLock = new(); @@ -70,6 +71,7 @@ public class DownloadClient(Download download, Torrent torrent, String destinati Data.Enums.DownloadClient.Aria2c => new Aria2cDownloader(download.RemoteId, download.Link, filePath, downloadPath, category), Data.Enums.DownloadClient.Symlink => new SymlinkDownloader(download.Link, filePath, downloadPath, torrent.ClientKind), Data.Enums.DownloadClient.DownloadStation => await DownloadStationDownloader.Init(download.RemoteId, download.Link, filePath, downloadPath, category), + Data.Enums.DownloadClient.Strm => new StrmDownloader(download.Link, filePath, fileSystem), _ => throw new($"Unknown download client {Type}") }; diff --git a/server/RdtClient.Service/Services/Downloaders/StrmDownloader.cs b/server/RdtClient.Service/Services/Downloaders/StrmDownloader.cs new file mode 100644 index 0000000..574a699 --- /dev/null +++ b/server/RdtClient.Service/Services/Downloaders/StrmDownloader.cs @@ -0,0 +1,44 @@ +using System.IO.Abstractions; + +namespace RdtClient.Service.Services.Downloaders; + +public class StrmDownloader(String downloadLink, String filePath, IFileSystem fileSystem) : IDownloader +{ + public event EventHandler? DownloadComplete; + public event EventHandler? DownloadProgress; + + public async Task Download() + { + try + { + await fileSystem.File.WriteAllTextAsync(filePath + ".strm", downloadLink); + + DownloadComplete?.Invoke(this, new()); + } + catch (Exception ex) + { + DownloadComplete?.Invoke(this, + new() + { + Error = ex.Message + }); + } + + return Guid.NewGuid().ToString(); + } + + public Task Cancel() + { + return Task.CompletedTask; + } + + public Task Pause() + { + return Task.CompletedTask; + } + + public Task Resume() + { + return Task.CompletedTask; + } +} diff --git a/server/RdtClient.Service/Services/TorrentRunner.cs b/server/RdtClient.Service/Services/TorrentRunner.cs index e7ba302..30c1e85 100644 --- a/server/RdtClient.Service/Services/TorrentRunner.cs +++ b/server/RdtClient.Service/Services/TorrentRunner.cs @@ -7,11 +7,12 @@ using RdtClient.Service.Helpers; using RdtClient.Service.Services.Downloaders; using System.Collections.Concurrent; using System.Diagnostics; +using System.IO.Abstractions; using System.Text.Json; namespace RdtClient.Service.Services; -public class TorrentRunner(ILogger logger, Torrents torrents, Downloads downloads) +public class TorrentRunner(ILogger logger, Torrents torrents, Downloads downloads, IFileSystem fileSystem) { public static readonly ConcurrentDictionary ActiveDownloadClients = new(); public static readonly ConcurrentDictionary ActiveUnpackClients = new(); @@ -428,7 +429,7 @@ public class TorrentRunner(ILogger logger, Torrents torrents, Dow Log($"Setting download path to {downloadPath}", download, torrent); // Start the download process - var downloadClient = new DownloadClient(download, torrent, downloadPath, torrent.Category); + var downloadClient = new DownloadClient(download, torrent, downloadPath, torrent.Category, fileSystem); if (ActiveDownloadClients.TryAdd(download.DownloadId, downloadClient)) { diff --git a/server/RdtClient.Web/Controllers/SettingsController.cs b/server/RdtClient.Web/Controllers/SettingsController.cs index f98942a..9a7e153 100644 --- a/server/RdtClient.Web/Controllers/SettingsController.cs +++ b/server/RdtClient.Web/Controllers/SettingsController.cs @@ -1,4 +1,5 @@ using System.Diagnostics; +using System.IO.Abstractions; using System.Reflection; using Aria2NET; using Microsoft.AspNetCore.Authorization; @@ -14,7 +15,7 @@ namespace RdtClient.Web.Controllers; [Authorize(Policy = "AuthSetting")] [Route("Api/Settings")] -public class SettingsController(Settings settings, Torrents torrents) : Controller +public class SettingsController(Settings settings, Torrents torrents, IFileSystem fileSystem) : Controller { [HttpGet] [Route("")] @@ -108,7 +109,7 @@ public class SettingsController(Settings settings, Torrents torrents) : Controll } }; - var downloadClient = new DownloadClient(download, download.Torrent, downloadPath, null); + var downloadClient = new DownloadClient(download, download.Torrent, downloadPath, null, fileSystem); await downloadClient.Start();