wabbajack/Wabbajack.Services.OSIntegrated/Services/ModListDownloadMaintainer.cs
Luca a87f8dac7f
New Features from External Contributors [Merged to Internal Test Branch so Tests can run!] (#2325)
* added enderalse GOGID

* Fix readme opening twice when loading last modlist

* Edit Wabbajack CLI button text

* Cancel running downloads when shutting down application

* Add resume support for IHttpDownloader

* Add resume support for manual downloads

* Update CHANGELOG.md

* Improve game selection to only show games with results combined with the amount of lists

* Undo accidental removal of loading settings

* Add more tooltips and improve existing ones

* Update CHANGELOG.md

* Main test external pull readme fix (#2335)

* Fix SelectedGameType crashing Wabbajack when no settings are present yet, fix readme being clickable when not specified resulting in crash

* Add readme fix to CHANGELOG, fix typo

* Add readme button fix to changelog

---------

Co-authored-by: UrbanCMC <UrbanCMC@web.de>
Co-authored-by: Angad <angadmisra28@gmail.com>
Co-authored-by: trawzified <55751269+tr4wzified@users.noreply.github.com>
Co-authored-by: Timothy Baldridge <tbaldridge@gmail.com>
2023-05-07 14:32:18 -06:00

97 lines
3.4 KiB
C#

using System;
using System.Reactive.Subjects;
using System.Text.Json;
using System.Threading;
using System.Threading.Tasks;
using Microsoft.Extensions.Logging;
using Wabbajack.Common;
using Wabbajack.Downloaders;
using Wabbajack.DTOs;
using Wabbajack.DTOs.JsonConverters;
using Wabbajack.Paths;
using Wabbajack.Paths.IO;
using Wabbajack.RateLimiter;
using Wabbajack.VFS;
namespace Wabbajack.Services.OSIntegrated.Services;
public class ModListDownloadMaintainer
{
private readonly ILogger<ModListDownloadMaintainer> _logger;
private readonly Configuration _configuration;
private readonly DownloadDispatcher _dispatcher;
private readonly FileHashCache _hashCache;
private readonly IResource<DownloadDispatcher> _rateLimiter;
private int _downloadingCount;
private readonly DTOSerializer _dtos;
public ModListDownloadMaintainer(ILogger<ModListDownloadMaintainer> logger, Configuration configuration,
DownloadDispatcher dispatcher, FileHashCache hashCache, DTOSerializer dtos, IResource<DownloadDispatcher> rateLimiter)
{
_logger = logger;
_configuration = configuration;
_dispatcher = dispatcher;
_hashCache = hashCache;
_rateLimiter = rateLimiter;
_downloadingCount = 0;
_dtos = dtos;
}
public AbsolutePath ModListPath(ModlistMetadata metadata)
{
return _configuration.ModListsDownloadLocation.Combine(metadata.NamespacedName.Replace("/", "_@@_")).WithExtension(Ext.Wabbajack);
}
public async Task<bool> HaveModList(ModlistMetadata metadata, CancellationToken? token = null)
{
token ??= CancellationToken.None;
var path = ModListPath(metadata);
if (!path.FileExists()) return false;
if (await _hashCache.TryGetHashCache(path) == metadata.DownloadMetadata!.Hash) return true;
if (_downloadingCount > 0) return false;
return await _hashCache.FileHashCachedAsync(path, token.Value) == metadata.DownloadMetadata!.Hash;
}
public (IObservable<Percent> Progress, Task Task) DownloadModlist(ModlistMetadata metadata, CancellationToken token)
{
var path = ModListPath(metadata);
var progress = new Subject<Percent>();
progress.OnNext(Percent.Zero);
var tsk = Task.Run(async () =>
{
try
{
Interlocked.Increment(ref _downloadingCount);
using var job = await _rateLimiter.Begin($"Downloading {metadata.Title}", metadata.DownloadMetadata!.Size,
token);
job.OnUpdate += (_, pr) => { progress.OnNext(pr.Progress); };
var hash = await _dispatcher.Download(new Archive()
{
State = _dispatcher.Parse(new Uri(metadata.Links.Download))!,
Size = metadata.DownloadMetadata.Size,
Hash = metadata.DownloadMetadata.Hash
}, path, job, token);
if (token.IsCancellationRequested)
{
return;
}
await _hashCache.FileHashWriteCache(path, hash);
await path.WithExtension(Ext.MetaData).WriteAllTextAsync(JsonSerializer.Serialize(metadata), token);
}
finally
{
progress.OnCompleted();
Interlocked.Decrement(ref _downloadingCount);
}
}, token);
return (progress, tsk);
}
}