create .strm downloader

This commit is contained in:
Cucumberrbob 2025-06-15 14:24:54 +01:00
parent cb29187f72
commit f66d1fe197
No known key found for this signature in database
GPG key ID: 2B935C47401C3614
6 changed files with 100 additions and 6 deletions

View file

@ -18,4 +18,7 @@ public enum DownloadClient
[Description("Synology DownloadStation")] [Description("Synology DownloadStation")]
DownloadStation, DownloadStation,
[Description("Strm Downloader")]
Strm
} }

View file

@ -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<DownloadCompleteEventArgs>(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<IFileSystem>();
mockFileSystem.Setup(fs => fs.File.WriteAllTextAsync(It.IsAny<String>(), It.IsAny<String>(), It.IsAny<CancellationToken>()))
.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<DownloadCompleteEventArgs>(
a => strmDownloader.DownloadComplete += a,
a => strmDownloader.DownloadComplete -= a,
strmDownloader.Download);
Assert.NotNull(raisedEvent);
Assert.False(String.IsNullOrWhiteSpace(raisedEvent.Arguments.Error));
}
}

View file

@ -1,4 +1,5 @@
using RdtClient.Data.Enums; using System.IO.Abstractions;
using RdtClient.Data.Enums;
using RdtClient.Data.Models.Data; using RdtClient.Data.Models.Data;
using RdtClient.Service.Helpers; using RdtClient.Service.Helpers;
using RdtClient.Service.Services.Downloaders; using RdtClient.Service.Services.Downloaders;
@ -6,7 +7,7 @@ using RdtClient.Service.Services.TorrentClients;
namespace RdtClient.Service.Services; 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 Int64 _totalBytesDownloadedThisSession;
private static readonly Lock TotalBytesDownloadedLock = new(); 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.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.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.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}") _ => throw new($"Unknown download client {Type}")
}; };

View file

@ -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<DownloadCompleteEventArgs>? DownloadComplete;
public event EventHandler<DownloadProgressEventArgs>? DownloadProgress;
public async Task<String> 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;
}
}

View file

@ -7,11 +7,12 @@ using RdtClient.Service.Helpers;
using RdtClient.Service.Services.Downloaders; using RdtClient.Service.Services.Downloaders;
using System.Collections.Concurrent; using System.Collections.Concurrent;
using System.Diagnostics; using System.Diagnostics;
using System.IO.Abstractions;
using System.Text.Json; using System.Text.Json;
namespace RdtClient.Service.Services; namespace RdtClient.Service.Services;
public class TorrentRunner(ILogger<TorrentRunner> logger, Torrents torrents, Downloads downloads) public class TorrentRunner(ILogger<TorrentRunner> logger, Torrents torrents, Downloads downloads, IFileSystem fileSystem)
{ {
public static readonly ConcurrentDictionary<Guid, DownloadClient> ActiveDownloadClients = new(); public static readonly ConcurrentDictionary<Guid, DownloadClient> ActiveDownloadClients = new();
public static readonly ConcurrentDictionary<Guid, UnpackClient> ActiveUnpackClients = new(); public static readonly ConcurrentDictionary<Guid, UnpackClient> ActiveUnpackClients = new();
@ -428,7 +429,7 @@ public class TorrentRunner(ILogger<TorrentRunner> logger, Torrents torrents, Dow
Log($"Setting download path to {downloadPath}", download, torrent); Log($"Setting download path to {downloadPath}", download, torrent);
// Start the download process // 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)) if (ActiveDownloadClients.TryAdd(download.DownloadId, downloadClient))
{ {

View file

@ -1,4 +1,5 @@
using System.Diagnostics; using System.Diagnostics;
using System.IO.Abstractions;
using System.Reflection; using System.Reflection;
using Aria2NET; using Aria2NET;
using Microsoft.AspNetCore.Authorization; using Microsoft.AspNetCore.Authorization;
@ -14,7 +15,7 @@ namespace RdtClient.Web.Controllers;
[Authorize(Policy = "AuthSetting")] [Authorize(Policy = "AuthSetting")]
[Route("Api/Settings")] [Route("Api/Settings")]
public class SettingsController(Settings settings, Torrents torrents) : Controller public class SettingsController(Settings settings, Torrents torrents, IFileSystem fileSystem) : Controller
{ {
[HttpGet] [HttpGet]
[Route("")] [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(); await downloadClient.Start();