Enable author controls and uploading

This commit is contained in:
Timothy Baldridge
2022-07-13 07:41:39 -06:00
parent 28e7e1f01a
commit 6671fcb533
3 changed files with 67 additions and 4 deletions

View File

@ -46,7 +46,7 @@ namespace Wabbajack.View_Models.Settings
Task.Run(async () => Task.Run(async () =>
{ {
var isAuthor = string.IsNullOrWhiteSpace((await _token.Get())?.AuthorKey); var isAuthor = !string.IsNullOrWhiteSpace((await _token.Get())?.AuthorKey);
IsVisible = isAuthor ? Visibility.Visible : Visibility.Collapsed; IsVisible = isAuthor ? Visibility.Visible : Visibility.Collapsed;
}); });
@ -65,7 +65,7 @@ namespace Wabbajack.View_Models.Settings
_isUploading.OnNext(true); _isUploading.OnNext(true);
try try
{ {
var (progress, task) = _wjClient.UploadAuthorFile(Picker.TargetPath); var (progress, task) = await _wjClient.UploadAuthorFile(Picker.TargetPath);
var disposable = progress.Subscribe(m => var disposable = progress.Subscribe(m =>
{ {

View File

@ -34,6 +34,8 @@ namespace Wabbajack
.DisposeWith(disposable); .DisposeWith(disposable);
this.OneWayBindStrict(this.ViewModel, x => x.Performance, x => x.PerformanceView.ViewModel) this.OneWayBindStrict(this.ViewModel, x => x.Performance, x => x.PerformanceView.ViewModel)
.DisposeWith(disposable); .DisposeWith(disposable);
this.OneWayBindStrict(this.ViewModel, x => x.AuthorFile, x => x.AuthorFilesView.ViewModel)
.DisposeWith(disposable);
this.MiscGalleryView.ViewModel = this.ViewModel; this.MiscGalleryView.ViewModel = this.ViewModel;
}); });
} }

View File

@ -5,6 +5,7 @@ using System.IO.Compression;
using System.Linq; using System.Linq;
using System.Net.Http; using System.Net.Http;
using System.Net.Http.Json; using System.Net.Http.Json;
using System.Reactive.Subjects;
using System.Text; using System.Text;
using System.Threading; using System.Threading;
using System.Threading.Tasks; using System.Threading.Tasks;
@ -28,6 +29,7 @@ using Wabbajack.Paths.IO;
using Wabbajack.RateLimiter; using Wabbajack.RateLimiter;
using YamlDotNet.Serialization; using YamlDotNet.Serialization;
using YamlDotNet.Serialization.NamingConventions; using YamlDotNet.Serialization.NamingConventions;
using YamlDotNet.Serialization.TypeInspectors;
namespace Wabbajack.Networking.WabbajackClientApi; namespace Wabbajack.Networking.WabbajackClientApi;
@ -350,9 +352,68 @@ public class Client
} }
public (IObservable<(Percent PercentDone, string Message)> Progress, Task<Uri> Task) UploadAuthorFile(AbsolutePath pickerTargetPath) public async Task<(IObservable<(Percent PercentDone, string Message)> Progress, Task<Uri> Task)> UploadAuthorFile(
AbsolutePath path)
{ {
throw new NotImplementedException(); var apiKey = (await _token.Get())!.AuthorKey;
var report = new Subject<(Percent PercentDone, string Message)>();
var tsk = Task.Run<Uri>(async () =>
{
report.OnNext((Percent.Zero, "Generating File Definition"));
var definition = await GenerateFileDefinition(path);
report.OnNext((Percent.Zero, "Creating file upload"));
await CircuitBreaker.WithAutoRetryAllAsync(_logger, async () =>
{
var msg = await MakeMessage(HttpMethod.Put, new Uri($"{_configuration.BuildServerUrl}authored_files/create"));
msg.Content = new StringContent(_dtos.Serialize(definition));
using var result = await _client.SendAsync(msg);
HttpException.ThrowOnFailure(result);
definition.ServerAssignedUniqueId = await result.Content.ReadAsStringAsync();
});
report.OnNext((Percent.Zero, "Starting part uploads"));
await definition.Parts.PDoAll(_limiter, async part =>
{
report.OnNext((Percent.FactoryPutInRange(part.Index, definition.Parts.Length),
$"Uploading Part ({part.Index}/{definition.Parts.Length})"));
var buffer = new byte[part.Size];
await using (var fs = path.Open(FileMode.Open, FileAccess.Read, FileShare.Read))
{
fs.Position = part.Offset;
await fs.ReadAsync(buffer);
}
await CircuitBreaker.WithAutoRetryAllAsync(_logger, async () =>
{
var msg = await MakeMessage(HttpMethod.Put,
new Uri(
$"{_configuration.BuildServerUrl}authored_files/{definition.ServerAssignedUniqueId}/part/{part.Index}"));
msg.Content = new ByteArrayContent(buffer);
using var putResult = await _client.SendAsync(msg);
HttpException.ThrowOnFailure(putResult);
var hash = Hash.FromBase64(await putResult.Content.ReadAsStringAsync());
if (hash != part.Hash)
throw new InvalidDataException("Hashes don't match");
return hash;
});
});
report.OnNext((Percent.Zero, "Finalizing upload"));
return await CircuitBreaker.WithAutoRetryAllAsync(_logger, async () =>
{
var msg = await MakeMessage(HttpMethod.Put,
new Uri($"{_configuration.BuildServerUrl}authored_files/{definition.ServerAssignedUniqueId}/finish"));
msg.Content = new StringContent(_dtos.Serialize(definition));
using var result = await _client.SendAsync(msg);
HttpException.ThrowOnFailure(result);
report.OnNext((Percent.One, "Finished"));
return new Uri($"https://authored-files.wabbajack.org/{definition.MungedName}");
});
});
return (report, tsk);
} }
public async Task<ForcedRemoval[]> GetForcedRemovals(CancellationToken token) public async Task<ForcedRemoval[]> GetForcedRemovals(CancellationToken token)
{ {