Compare commits
67 Commits
PatchHelpe
...
main
Author | SHA1 | Date | |
---|---|---|---|
3051fa69a8 | |||
d4776b578a | |||
84dd270f25 | |||
a2e8c67dbd | |||
d9d8f49808 | |||
67203037a1 | |||
ec8ddeb513 | |||
9f0369bbd6 | |||
66580eed52 | |||
3890f633e3 | |||
5acb29df2a | |||
f478552a33 | |||
8d62adb25e | |||
1b0acdc262 | |||
2060c5b3b4 | |||
e226667746 | |||
3e442296f6 | |||
549d41df4a | |||
a70f94dfd0 | |||
b232425df1 | |||
478aaa4daf | |||
21d96d113a | |||
4a10964f7f | |||
ae424eaa5f | |||
c8d1427472 | |||
7473bfd5fe | |||
980d8720ee | |||
38e46d6d1f | |||
eb37ba65ba | |||
6ba231287b | |||
a2800a6760 | |||
875072fc15 | |||
95b6e5147d | |||
d64595e2f9 | |||
abb18028f9 | |||
2d21636fe7 | |||
47f84f5cd7 | |||
d51dd9b469 | |||
86365114c8 | |||
648c2d730c | |||
5cf41dae3c | |||
fbc917bfbf | |||
2ebc596321 | |||
acbebe3821 | |||
138bc5e140 | |||
52ef069f7b | |||
b28850f8b5 | |||
4141385ea7 | |||
a879f686ff | |||
8af477e98b | |||
99f661a101 | |||
df6ca3b448 | |||
fec4063cf9 | |||
6f9ecf3e10 | |||
749c68c033 | |||
3e03c99f0a | |||
993e8dd2c3 | |||
1c5a668e78 | |||
21bc6e2e4a | |||
b243a150f5 | |||
d36d925d33 | |||
057d272306 | |||
0a53dbf2c7 | |||
7f532dc9b3 | |||
751f1e75f2 | |||
5445ebc2f6 | |||
14802059a0 |
28
EftPatchHelper/EftPatchHelper/EftInfo/EftClient.cs
Normal file
28
EftPatchHelper/EftPatchHelper/EftInfo/EftClient.cs
Normal file
@ -0,0 +1,28 @@
|
||||
using EftPatchHelper.Helpers;
|
||||
using EftPatchHelper.Model;
|
||||
using Spectre.Console;
|
||||
|
||||
namespace EftPatchHelper.EftInfo
|
||||
{
|
||||
public class EftClient
|
||||
{
|
||||
public string DisplayName => $"{Location}: {Version}";
|
||||
public string Version { get; set; }
|
||||
public string FolderPath { get; set; }
|
||||
public string PrepPath { get; set; }
|
||||
public EftClientLocation Location { get; set; }
|
||||
|
||||
public bool Backup(Settings settings, bool IgnoreIfexists = false)
|
||||
{
|
||||
string backupPath = Path.Join(settings.BackupFolderPath, Version);
|
||||
|
||||
if (Directory.Exists(backupPath) && Location != EftClientLocation.Live) return true;
|
||||
|
||||
AnsiConsole.MarkupLine($"[blue]Backing up {Version} ...[/]");
|
||||
|
||||
FolderCopy backup = new FolderCopy(FolderPath, backupPath);
|
||||
|
||||
return backup.Start(IgnoreIfexists);
|
||||
}
|
||||
}
|
||||
}
|
@ -0,0 +1,8 @@
|
||||
namespace EftPatchHelper.EftInfo
|
||||
{
|
||||
public enum EftClientLocation
|
||||
{
|
||||
Live = 0,
|
||||
Backup
|
||||
}
|
||||
}
|
@ -2,13 +2,42 @@
|
||||
|
||||
<PropertyGroup>
|
||||
<OutputType>Exe</OutputType>
|
||||
<TargetFramework>net6.0</TargetFramework>
|
||||
<TargetFramework>net8.0</TargetFramework>
|
||||
<ImplicitUsings>enable</ImplicitUsings>
|
||||
<Nullable>enable</Nullable>
|
||||
<AssemblyVersion>1.6.1</AssemblyVersion>
|
||||
<FileVersion>1.6.1</FileVersion>
|
||||
</PropertyGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<PackageReference Include="Spectre.Console" Version="0.43.0" />
|
||||
<PackageReference Include="AWSSDK.S3" Version="3.7.307.24" />
|
||||
<PackageReference Include="FubarCoder.RestSharp.Portable.Core" Version="4.0.8" />
|
||||
<PackageReference Include="FubarCoder.RestSharp.Portable.HttpClient" Version="4.0.8" />
|
||||
<PackageReference Include="GoFileSharp" Version="1.0.2" />
|
||||
<PackageReference Include="MegaApiClient" Version="1.10.2" />
|
||||
<PackageReference Include="Microsoft.Extensions.DependencyInjection" Version="6.0.0" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting" Version="6.0.1" />
|
||||
<PackageReference Include="Microsoft.Extensions.Hosting.Abstractions" Version="6.0.0" />
|
||||
<PackageReference Include="Newtonsoft.Json" Version="13.0.1" />
|
||||
<PackageReference Include="Spectre.Console" Version="0.44.0" />
|
||||
<PackageReference Include="Squid-Box.SevenZipSharp" Version="1.6.1.23" />
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<Reference Include="WinSCPnet">
|
||||
<HintPath>Resources\WinSCPnet.dll</HintPath>
|
||||
</Reference>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Update="settings.json">
|
||||
<CopyToOutputDirectory>Always</CopyToOutputDirectory>
|
||||
</None>
|
||||
</ItemGroup>
|
||||
|
||||
<ItemGroup>
|
||||
<None Remove="Resources\7z.dll" />
|
||||
<EmbeddedResource Include="Resources\7z.dll" />
|
||||
</ItemGroup>
|
||||
|
||||
</Project>
|
||||
|
16
EftPatchHelper/EftPatchHelper/Extensions/BoolExtensions.cs
Normal file
16
EftPatchHelper/EftPatchHelper/Extensions/BoolExtensions.cs
Normal file
@ -0,0 +1,16 @@
|
||||
using Spectre.Console;
|
||||
|
||||
namespace EftPatchHelper.Extensions
|
||||
{
|
||||
public static class BoolExtensions
|
||||
{
|
||||
public static void ValidateOrExit(this bool toValidate)
|
||||
{
|
||||
if (!toValidate)
|
||||
{
|
||||
AnsiConsole.Prompt(new TextPrompt<string>("Press [blue]enter[/] to close ...").AllowEmpty());
|
||||
Environment.Exit(0);
|
||||
}
|
||||
}
|
||||
}
|
||||
}
|
18
EftPatchHelper/EftPatchHelper/Extensions/ObjectExtensions.cs
Normal file
18
EftPatchHelper/EftPatchHelper/Extensions/ObjectExtensions.cs
Normal file
@ -0,0 +1,18 @@
|
||||
using Spectre.Console;
|
||||
|
||||
namespace EftPatchHelper.Extensions
|
||||
{
|
||||
public static class ObjectExtensions
|
||||
{
|
||||
public static T ValidateOrExit<T>(this object? toValidate)
|
||||
{
|
||||
if (toValidate == null || toValidate is not T)
|
||||
{
|
||||
AnsiConsole.Prompt(new TextPrompt<string>("Press [blue]enter[/] to close ...").AllowEmpty());
|
||||
Environment.Exit(0);
|
||||
}
|
||||
|
||||
return (T)toValidate;
|
||||
}
|
||||
}
|
||||
}
|
99
EftPatchHelper/EftPatchHelper/Helpers/EftClientSelector.cs
Normal file
99
EftPatchHelper/EftPatchHelper/Helpers/EftClientSelector.cs
Normal file
@ -0,0 +1,99 @@
|
||||
using EftPatchHelper.EftInfo;
|
||||
using EftPatchHelper.Model;
|
||||
using Spectre.Console;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace EftPatchHelper.Helpers
|
||||
{
|
||||
public class EftClientSelector
|
||||
{
|
||||
private List<EftClient> _clientList = new List<EftClient>();
|
||||
private Settings _settings;
|
||||
|
||||
public EftClientSelector(Settings settings)
|
||||
{
|
||||
_settings = settings;
|
||||
}
|
||||
|
||||
public string? GetLiveVersion()
|
||||
{
|
||||
// Get eft live version
|
||||
string eftVersion = FileVersionInfo.GetVersionInfo(Path.Join(_settings.LiveEftPath, "EscapeFromTarkov.exe")).ProductVersion?.Replace('-', '.');
|
||||
|
||||
//remove leading 0 from version number
|
||||
if (eftVersion != null && eftVersion.StartsWith("0."))
|
||||
{
|
||||
eftVersion = eftVersion.Remove(0, 2);
|
||||
}
|
||||
|
||||
string[] fixedVersion = eftVersion.Split('.')[0..4];
|
||||
|
||||
return string.Join('.', fixedVersion);
|
||||
}
|
||||
|
||||
public EftClient GetClient(string Version)
|
||||
{
|
||||
return _clientList.Where(x => x.Version == Version).FirstOrDefault();
|
||||
}
|
||||
|
||||
public void LoadClientList()
|
||||
{
|
||||
_clientList.Clear();
|
||||
|
||||
string? eftVersion = GetLiveVersion();
|
||||
|
||||
if (eftVersion != null)
|
||||
{
|
||||
|
||||
// add eft live version to version options
|
||||
_clientList.Add(new EftClient()
|
||||
{
|
||||
FolderPath = _settings.LiveEftPath,
|
||||
Version = eftVersion,
|
||||
PrepPath = Path.Join(_settings.PrepFolderPath, eftVersion),
|
||||
Location = EftClientLocation.Live
|
||||
});
|
||||
}
|
||||
|
||||
// add backup folders to version options
|
||||
foreach (string backup in Directory.GetDirectories(_settings.BackupFolderPath))
|
||||
{
|
||||
DirectoryInfo backupDir = new DirectoryInfo(backup);
|
||||
|
||||
if (!backupDir.Exists)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
_clientList.Add(new EftClient()
|
||||
{
|
||||
FolderPath = backupDir.FullName,
|
||||
Version = backupDir.Name,
|
||||
PrepPath = Path.Join(_settings.PrepFolderPath, backupDir.Name),
|
||||
Location = EftClientLocation.Backup
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
public EftClient GetClientSelection(string Prompt, string currentReleaseVersion = "")
|
||||
{
|
||||
SelectionPrompt<EftClient> clientPrompt = new SelectionPrompt<EftClient>()
|
||||
{
|
||||
Title = Prompt,
|
||||
MoreChoicesText = "Move cursor to see more versions",
|
||||
PageSize = 10,
|
||||
Converter = (x) =>
|
||||
{
|
||||
if (!string.IsNullOrWhiteSpace(currentReleaseVersion) && x.Version.EndsWith(currentReleaseVersion))
|
||||
return $"{x.DisplayName} - Latest Release";
|
||||
|
||||
return x.DisplayName;
|
||||
}
|
||||
};
|
||||
|
||||
clientPrompt.AddChoices(_clientList);
|
||||
|
||||
return clientPrompt.Show(AnsiConsole.Console);
|
||||
}
|
||||
}
|
||||
}
|
44
EftPatchHelper/EftPatchHelper/Helpers/FileHelper.cs
Normal file
44
EftPatchHelper/EftPatchHelper/Helpers/FileHelper.cs
Normal file
@ -0,0 +1,44 @@
|
||||
using System.Reflection;
|
||||
using Spectre.Console;
|
||||
|
||||
namespace EftPatchHelper.Helpers;
|
||||
|
||||
public class FileHelper
|
||||
{
|
||||
public bool StreamAssemblyResourceOut(string resourceName, string outputFilePath)
|
||||
{
|
||||
try
|
||||
{
|
||||
var assembly = Assembly.GetExecutingAssembly();
|
||||
|
||||
FileInfo outputFile = new FileInfo(outputFilePath);
|
||||
|
||||
if (outputFile.Exists)
|
||||
{
|
||||
outputFile.Delete();
|
||||
}
|
||||
|
||||
if (!outputFile.Directory.Exists)
|
||||
{
|
||||
Directory.CreateDirectory(outputFile.Directory.FullName);
|
||||
}
|
||||
|
||||
var resName = assembly.GetManifestResourceNames().First(x => x.EndsWith(resourceName));
|
||||
|
||||
using (FileStream fs = File.Create(outputFilePath))
|
||||
using (Stream s = assembly.GetManifestResourceStream(resName))
|
||||
{
|
||||
s.CopyTo(fs);
|
||||
}
|
||||
|
||||
outputFile.Refresh();
|
||||
return outputFile.Exists;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
AnsiConsole.WriteException(ex);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
}
|
@ -21,7 +21,7 @@ namespace EftPatchHelper.Helpers
|
||||
public static void Clean(string FolderPath)
|
||||
{
|
||||
AnsiConsole.Status()
|
||||
.Spinner(Spinner.Known.Default)
|
||||
.Spinner(Spinner.Known.Dots2)
|
||||
.Start($"Cleaning Folder ...", ctx =>
|
||||
{
|
||||
AnsiConsole.MarkupLine($"[blue]INFO:[/] [gray]Getting folders to remove for {FolderPath} ...[/]");
|
||||
@ -47,7 +47,7 @@ namespace EftPatchHelper.Helpers
|
||||
|
||||
fsInfo.Refresh();
|
||||
|
||||
if(!fsInfo.Exists)
|
||||
if (!fsInfo.Exists)
|
||||
{
|
||||
AnsiConsole.MarkupLine($"[blue]INFO:[/] [gray]Deleting {fsInfo.Name} ...[/] [green]OK[/]");
|
||||
continue;
|
||||
|
@ -18,7 +18,7 @@ namespace EftPatchHelper.Helpers
|
||||
this.DestinationFolder = DestinationFolder;
|
||||
}
|
||||
|
||||
public bool Start()
|
||||
public bool Start(bool IgnoreIfExists = false, bool merge = false)
|
||||
{
|
||||
DirectoryInfo sourceDir = new DirectoryInfo(SourceFolder);
|
||||
DirectoryInfo destDir = new DirectoryInfo(DestinationFolder);
|
||||
@ -28,9 +28,14 @@ namespace EftPatchHelper.Helpers
|
||||
destDir.Create();
|
||||
destDir.Refresh();
|
||||
}
|
||||
else
|
||||
else if (IgnoreIfExists)
|
||||
{
|
||||
if(!AnsiConsole.Confirm($"{destDir.FullName} exists. Do you want to overwright it?", false))
|
||||
AnsiConsole.MarkupLine("[yellow]Exists[/]");
|
||||
return true;
|
||||
}
|
||||
else if(!merge)
|
||||
{
|
||||
if (!AnsiConsole.Confirm($"{destDir.FullName} exists. Do you want to overwright it?", false))
|
||||
{
|
||||
AnsiConsole.MarkupLine("[yellow]Using existing folder[/]");
|
||||
return true;
|
||||
@ -50,7 +55,7 @@ namespace EftPatchHelper.Helpers
|
||||
new ProgressBarColumn(),
|
||||
new PercentageColumn(),
|
||||
new ElapsedTimeColumn(),
|
||||
new SpinnerColumn()
|
||||
new SpinnerColumn(Spinner.Known.Dots2)
|
||||
})
|
||||
.Start(ctx =>
|
||||
{
|
||||
|
122
EftPatchHelper/EftPatchHelper/Helpers/R2Helper.cs
Normal file
122
EftPatchHelper/EftPatchHelper/Helpers/R2Helper.cs
Normal file
@ -0,0 +1,122 @@
|
||||
using System.Net;
|
||||
using Amazon.Runtime;
|
||||
using Amazon.S3;
|
||||
using Amazon.S3.Model;
|
||||
using EftPatchHelper.Model;
|
||||
using Spectre.Console;
|
||||
|
||||
namespace EftPatchHelper.Helpers;
|
||||
|
||||
public class R2Helper
|
||||
{
|
||||
private readonly AmazonS3Client? _client;
|
||||
public string ConnectedDomain { get; private set; }
|
||||
public string BucketName { get; private set; }
|
||||
|
||||
public R2Helper(Settings settings, Options options)
|
||||
{
|
||||
ConnectedDomain = settings.R2ConnectedDomainUrl;
|
||||
BucketName = settings.R2BucketName;
|
||||
|
||||
if (settings.UsingR2())
|
||||
{
|
||||
var creds = new BasicAWSCredentials(settings.R2AccessKeyId, settings.R2SecretKeyId);
|
||||
_client = new AmazonS3Client(creds, new AmazonS3Config
|
||||
{
|
||||
ServiceURL = settings.R2ServiceUrl,
|
||||
});
|
||||
}
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Deletes all content in the bucket
|
||||
/// </summary>
|
||||
/// <returns>True if all contents of the bucket were deleted, otherwise false</returns>
|
||||
public async Task<bool> ClearBucketAsync()
|
||||
{
|
||||
if (_client == null)
|
||||
{
|
||||
AnsiConsole.MarkupLine("[red]Client is unavailable[/]");
|
||||
return false;
|
||||
}
|
||||
|
||||
AnsiConsole.MarkupLine($"[blue]Getting bucket contents: {BucketName}[/]");
|
||||
var listBucketResponse = await _client.ListObjectsAsync(BucketName);
|
||||
|
||||
if (listBucketResponse.HttpStatusCode != HttpStatusCode.OK)
|
||||
{
|
||||
AnsiConsole.MarkupLine("[red]failed to get bucket contents[/]");
|
||||
return false;
|
||||
}
|
||||
|
||||
if (listBucketResponse.S3Objects.Count == 0)
|
||||
{
|
||||
AnsiConsole.MarkupLine("[green]bucket is empty[/]");
|
||||
return true;
|
||||
}
|
||||
|
||||
AnsiConsole.MarkupLine("[blue]Removing old content[/]");
|
||||
foreach (var s3Object in listBucketResponse.S3Objects)
|
||||
{
|
||||
var deleteResponse = await _client.DeleteObjectAsync(BucketName, s3Object.Key);
|
||||
|
||||
if ((int)deleteResponse.HttpStatusCode < 200 || (int)deleteResponse.HttpStatusCode > 299)
|
||||
{
|
||||
AnsiConsole.MarkupLine($"[red]failed to delete {BucketName}::{s3Object.Key}[/]");
|
||||
return false;
|
||||
}
|
||||
|
||||
AnsiConsole.MarkupLine($"[green]{BucketName}::{s3Object.Key} removed[/]");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
/// <summary>
|
||||
/// Upload a file into the bucket
|
||||
/// </summary>
|
||||
/// <param name="file">The file to upload</param>
|
||||
/// <param name="progress">A progress object to track upload progress</param>
|
||||
/// <returns>True if the file was uploaded successfully, otherwise false</returns>
|
||||
public async Task<bool> UploadToBucketAsync(FileInfo file, IProgress<double>? progress = null)
|
||||
{
|
||||
if (_client == null)
|
||||
{
|
||||
AnsiConsole.MarkupLine("[red]Client is unavailable[/]");
|
||||
return false;
|
||||
}
|
||||
|
||||
file.Refresh();
|
||||
|
||||
if (!file.Exists)
|
||||
{
|
||||
AnsiConsole.MarkupLine($"[red]File '{file.Name}' does not exist[/]");
|
||||
return false;
|
||||
}
|
||||
|
||||
var request = new PutObjectRequest
|
||||
{
|
||||
BucketName = BucketName,
|
||||
FilePath = file.FullName,
|
||||
DisablePayloadSigning = true,
|
||||
};
|
||||
|
||||
if (progress != null)
|
||||
{
|
||||
request.StreamTransferProgress = (sender, progressArgs) =>
|
||||
{
|
||||
progress.Report(progressArgs.PercentDone);
|
||||
};
|
||||
}
|
||||
|
||||
var uploadResponse = await _client.PutObjectAsync(request);
|
||||
|
||||
if (uploadResponse.HttpStatusCode != HttpStatusCode.OK)
|
||||
{
|
||||
AnsiConsole.MarkupLine("[red]failed to upload file[/]");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
46
EftPatchHelper/EftPatchHelper/Helpers/ZipHelper.cs
Normal file
46
EftPatchHelper/EftPatchHelper/Helpers/ZipHelper.cs
Normal file
@ -0,0 +1,46 @@
|
||||
using SevenZip;
|
||||
using Spectre.Console;
|
||||
|
||||
namespace EftPatchHelper.Helpers;
|
||||
|
||||
public class ZipHelper
|
||||
{
|
||||
public string DllPath = Path.Join(Environment.CurrentDirectory, "7z.dll");
|
||||
public bool Compress(DirectoryInfo folder, FileInfo outputArchive,
|
||||
IProgress<double> progress)
|
||||
{
|
||||
try
|
||||
{
|
||||
using var outputStream = outputArchive.OpenWrite();
|
||||
|
||||
SevenZipBase.SetLibraryPath(DllPath);
|
||||
|
||||
var compressor = new SevenZipCompressor()
|
||||
{
|
||||
CompressionLevel = CompressionLevel.Normal,
|
||||
CompressionMethod = CompressionMethod.Lzma2,
|
||||
ArchiveFormat = OutArchiveFormat.SevenZip,
|
||||
PreserveDirectoryRoot = true
|
||||
};
|
||||
|
||||
compressor.Compressing += (_, args) => { progress.Report(args.PercentDone); };
|
||||
|
||||
compressor.CompressDirectory(folder.FullName, outputStream);
|
||||
|
||||
outputArchive.Refresh();
|
||||
|
||||
if (!outputArchive.Exists)
|
||||
{
|
||||
AnsiConsole.MarkupLine("output archive not found");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
AnsiConsole.WriteException(ex);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
}
|
6
EftPatchHelper/EftPatchHelper/Interfaces/ICleanupTask.cs
Normal file
6
EftPatchHelper/EftPatchHelper/Interfaces/ICleanupTask.cs
Normal file
@ -0,0 +1,6 @@
|
||||
namespace EftPatchHelper.Interfaces
|
||||
{
|
||||
public interface ICleanupTask : ITaskable
|
||||
{
|
||||
}
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
namespace EftPatchHelper.Interfaces
|
||||
{
|
||||
public interface IClientSelectionTask : ITaskable
|
||||
{
|
||||
}
|
||||
}
|
@ -0,0 +1,5 @@
|
||||
namespace EftPatchHelper.Interfaces;
|
||||
|
||||
public interface ICompressPatcherTasks : ITaskable
|
||||
{
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
namespace EftPatchHelper.Interfaces
|
||||
{
|
||||
public interface IFileProcessingTasks : ITaskable
|
||||
{
|
||||
}
|
||||
}
|
19
EftPatchHelper/EftPatchHelper/Interfaces/IFileUpload.cs
Normal file
19
EftPatchHelper/EftPatchHelper/Interfaces/IFileUpload.cs
Normal file
@ -0,0 +1,19 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace EftPatchHelper.Interfaces
|
||||
{
|
||||
public interface IFileUpload
|
||||
{
|
||||
public string DisplayName { get; set; }
|
||||
public string ServiceName { get; set; }
|
||||
public string HubEntryText { get; set; }
|
||||
public FileInfo UploadFileInfo { get; }
|
||||
public bool AddHubEntry { get; }
|
||||
public string GetLink();
|
||||
public Task<bool> UploadAsync(IProgress<double>? progress = null);
|
||||
}
|
||||
}
|
12
EftPatchHelper/EftPatchHelper/Interfaces/IMirrorUploader.cs
Normal file
12
EftPatchHelper/EftPatchHelper/Interfaces/IMirrorUploader.cs
Normal file
@ -0,0 +1,12 @@
|
||||
using System;
|
||||
using System.Collections.Generic;
|
||||
using System.Linq;
|
||||
using System.Text;
|
||||
using System.Threading.Tasks;
|
||||
|
||||
namespace EftPatchHelper.Interfaces
|
||||
{
|
||||
public interface IMirrorUploader : ITaskable
|
||||
{
|
||||
}
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
namespace EftPatchHelper.Interfaces
|
||||
{
|
||||
public interface IPatchGenTasks : ITaskable
|
||||
{
|
||||
}
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
namespace EftPatchHelper.Interfaces
|
||||
{
|
||||
public interface IPatchTestingTasks : ITaskable
|
||||
{
|
||||
}
|
||||
}
|
@ -0,0 +1,6 @@
|
||||
namespace EftPatchHelper.Interfaces
|
||||
{
|
||||
public interface ISettingsTask : ITaskable
|
||||
{
|
||||
}
|
||||
}
|
11
EftPatchHelper/EftPatchHelper/Interfaces/ITaskable.cs
Normal file
11
EftPatchHelper/EftPatchHelper/Interfaces/ITaskable.cs
Normal file
@ -0,0 +1,11 @@
|
||||
namespace EftPatchHelper.Interfaces
|
||||
{
|
||||
public interface ITaskable
|
||||
{
|
||||
/// <summary>
|
||||
/// Runs a predefined task
|
||||
/// </summary>
|
||||
/// <returns>Returns true if the task succeeded, otherwise false</returns>
|
||||
public void Run();
|
||||
}
|
||||
}
|
6
EftPatchHelper/EftPatchHelper/Interfaces/IUploadTasks.cs
Normal file
6
EftPatchHelper/EftPatchHelper/Interfaces/IUploadTasks.cs
Normal file
@ -0,0 +1,6 @@
|
||||
namespace EftPatchHelper.Interfaces
|
||||
{
|
||||
public interface IUploadTasks : ITaskable
|
||||
{
|
||||
}
|
||||
}
|
12
EftPatchHelper/EftPatchHelper/Model/DownloadMirror.cs
Normal file
12
EftPatchHelper/EftPatchHelper/Model/DownloadMirror.cs
Normal file
@ -0,0 +1,12 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace EftPatchHelper.Model
|
||||
{
|
||||
public class DownloadMirror
|
||||
{
|
||||
[JsonIgnore]
|
||||
public bool AddHubEntry { get; set; }
|
||||
public string Link { get; set; }
|
||||
public string Hash { get; set; }
|
||||
}
|
||||
}
|
68
EftPatchHelper/EftPatchHelper/Model/GoFileUpload.cs
Normal file
68
EftPatchHelper/EftPatchHelper/Model/GoFileUpload.cs
Normal file
@ -0,0 +1,68 @@
|
||||
using EftPatchHelper.Interfaces;
|
||||
using GoFileSharp;
|
||||
using GoFileSharp.Model;
|
||||
using GoFileSharp.Model.GoFileData;
|
||||
using GoFileSharp.Model.GoFileData.Wrappers;
|
||||
|
||||
|
||||
namespace EftPatchHelper.Model
|
||||
{
|
||||
public class GoFileUpload : IFileUpload
|
||||
{
|
||||
private GoFile _goFile;
|
||||
public FileInfo UploadFileInfo { get; private set; }
|
||||
private DirectLink? _directLink = null;
|
||||
private GoFileFile _uploadedFile;
|
||||
private string _folderId;
|
||||
|
||||
public string DisplayName { get; set; }
|
||||
public string ServiceName { get; set; }
|
||||
public string HubEntryText { get; set; }
|
||||
public bool AddHubEntry { get; }
|
||||
|
||||
public GoFileUpload(FileInfo file, string apiToken, string folderId)
|
||||
{
|
||||
_goFile = new GoFile(new GoFileOptions
|
||||
{
|
||||
ApiToken = apiToken
|
||||
});
|
||||
|
||||
_folderId = folderId;
|
||||
UploadFileInfo = file;
|
||||
ServiceName = "GoFile";
|
||||
DisplayName = $"{ServiceName} Upload";
|
||||
HubEntryText = $"Download from {ServiceName}";
|
||||
AddHubEntry = true;
|
||||
}
|
||||
|
||||
public string GetLink()
|
||||
{
|
||||
return _directLink?.Link ?? "";
|
||||
}
|
||||
|
||||
public async Task<bool> UploadAsync(IProgress<double>? progress = null)
|
||||
{
|
||||
var folder = await _goFile.GetFolderAsync(_folderId);
|
||||
|
||||
if (folder == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var uploadedFile = await folder.UploadIntoAsync(UploadFileInfo, progress);
|
||||
|
||||
if(uploadedFile == null) return false;
|
||||
|
||||
_directLink = await uploadedFile.AddDirectLink();
|
||||
|
||||
if(_directLink == null)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
_uploadedFile = uploadedFile;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
103
EftPatchHelper/EftPatchHelper/Model/MegaUpload.cs
Normal file
103
EftPatchHelper/EftPatchHelper/Model/MegaUpload.cs
Normal file
@ -0,0 +1,103 @@
|
||||
using EftPatchHelper.Interfaces;
|
||||
using CG.Web.MegaApiClient;
|
||||
using Spectre.Console;
|
||||
|
||||
namespace EftPatchHelper.Model
|
||||
{
|
||||
public class MegaUpload : IFileUpload, IDisposable
|
||||
{
|
||||
public FileInfo UploadFileInfo { get; private set; }
|
||||
private MegaApiClient _client;
|
||||
private string _email;
|
||||
private string _password;
|
||||
private string _mfaKey;
|
||||
private INode _uploadFolder;
|
||||
private INode _uploadedFile;
|
||||
|
||||
public string DisplayName { get; set; }
|
||||
public string ServiceName { get; set; }
|
||||
public string HubEntryText { get; set; }
|
||||
public bool AddHubEntry { get; }
|
||||
|
||||
|
||||
public MegaUpload(FileInfo file, string email, string password, string mfaKey = null)
|
||||
{
|
||||
_client = new MegaApiClient();
|
||||
UploadFileInfo = file;
|
||||
_email = email;
|
||||
_password = password;
|
||||
ServiceName = "Mega";
|
||||
DisplayName = $"{ServiceName} Upload";
|
||||
HubEntryText = $"Download from {ServiceName}";
|
||||
AddHubEntry = true;
|
||||
}
|
||||
|
||||
private async Task<bool> CheckLoginStatus()
|
||||
{
|
||||
if (!_client.IsLoggedIn)
|
||||
{
|
||||
AnsiConsole.Markup("[blue]Logging into mega ... [/]");
|
||||
|
||||
await _client.LoginAsync(_email, _password, _mfaKey);
|
||||
|
||||
if (!_client.IsLoggedIn)
|
||||
{
|
||||
AnsiConsole.MarkupLine("[red]failed[/]");
|
||||
return false;
|
||||
}
|
||||
AnsiConsole.MarkupLine("[green]ok[/]");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public async Task<bool> SetUploadFolder(string folderName)
|
||||
{
|
||||
if (!await CheckLoginStatus())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
AnsiConsole.Markup("[blue]Getting node ... [/]");
|
||||
var nodes = await _client.GetNodesAsync();
|
||||
|
||||
var trashNode = nodes.SingleOrDefault(x => x.Type == NodeType.Trash);
|
||||
|
||||
_uploadFolder = nodes.SingleOrDefault(x => x.Name == folderName && x.ParentId != trashNode.Id);
|
||||
|
||||
bool nodeSet = _uploadFolder != null;
|
||||
|
||||
AnsiConsole.MarkupLine(nodeSet != false ? "[green]node set[/]" : "[red]failed to set node[/]");
|
||||
|
||||
return nodeSet;
|
||||
}
|
||||
|
||||
public string GetLink()
|
||||
{
|
||||
return _client.GetDownloadLink(_uploadedFile).ToString();
|
||||
}
|
||||
|
||||
public async Task<bool> UploadAsync(IProgress<double>? progress = null)
|
||||
{
|
||||
UploadFileInfo.Refresh();
|
||||
|
||||
if (!UploadFileInfo.Exists) return false;
|
||||
|
||||
if(!await CheckLoginStatus())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
using var fileStream = UploadFileInfo.OpenRead();
|
||||
|
||||
_uploadedFile = await _client.UploadAsync(fileStream, UploadFileInfo.Name, _uploadFolder, progress);
|
||||
|
||||
return _uploadedFile != null;
|
||||
}
|
||||
|
||||
public void Dispose()
|
||||
{
|
||||
_client.Logout();
|
||||
}
|
||||
}
|
||||
}
|
52
EftPatchHelper/EftPatchHelper/Model/Options.cs
Normal file
52
EftPatchHelper/EftPatchHelper/Model/Options.cs
Normal file
@ -0,0 +1,52 @@
|
||||
using EftPatchHelper.EftInfo;
|
||||
|
||||
namespace EftPatchHelper.Model
|
||||
{
|
||||
public class Options
|
||||
{
|
||||
/// <summary>
|
||||
/// Whether or not the user opted to ignore existing directories.
|
||||
/// </summary>
|
||||
public bool IgnoreExistingDirectories = false;
|
||||
|
||||
/// <summary>
|
||||
/// The target client used to generate patches
|
||||
/// </summary>
|
||||
public EftClient TargetClient = null;
|
||||
|
||||
/// <summary>
|
||||
/// The source client used to generate patches
|
||||
/// </summary>
|
||||
public EftClient SourceClient = null;
|
||||
|
||||
/// <summary>
|
||||
/// The path to the patch folder containing the patches that were generated
|
||||
/// </summary>
|
||||
public string OutputPatchPath = null;
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not to upload the patcher to gofile.io
|
||||
/// </summary>
|
||||
public bool UploadToGoFile = false;
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not to upload the patcher to mega.io
|
||||
/// </summary>
|
||||
public bool UploadToMega = false;
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not to upload the patcher and mirror list to r2
|
||||
/// </summary>
|
||||
public bool UplaodToR2 = false;
|
||||
|
||||
/// <summary>
|
||||
/// Whether or not to upload to all sftp site listing
|
||||
/// </summary>
|
||||
public bool UploadToSftpSites = false;
|
||||
|
||||
/// <summary>
|
||||
/// List of mirrors to upload to Gitea
|
||||
/// </summary>
|
||||
public Dictionary<string, DownloadMirror> MirrorList = new Dictionary<string, DownloadMirror>();
|
||||
}
|
||||
}
|
8
EftPatchHelper/EftPatchHelper/Model/PatchInfo.cs
Normal file
8
EftPatchHelper/EftPatchHelper/Model/PatchInfo.cs
Normal file
@ -0,0 +1,8 @@
|
||||
namespace EftPatchHelper.Model;
|
||||
|
||||
public class PatchInfo
|
||||
{
|
||||
public int SourceClientVersion { get; set; }
|
||||
public int TargetClientVersion { get; set; }
|
||||
public List<DownloadMirror> Mirrors { get; set; }
|
||||
}
|
12
EftPatchHelper/EftPatchHelper/Model/PatcherExitCode.cs
Normal file
12
EftPatchHelper/EftPatchHelper/Model/PatcherExitCode.cs
Normal file
@ -0,0 +1,12 @@
|
||||
namespace EftPatchHelper.Model
|
||||
{
|
||||
public enum PatcherExitCode
|
||||
{
|
||||
ProgramClosed = 0,
|
||||
Success = 10,
|
||||
EftExeNotFound = 11,
|
||||
NoPatchFolder = 12,
|
||||
MissingFile = 13,
|
||||
MissingDir = 14
|
||||
}
|
||||
}
|
35
EftPatchHelper/EftPatchHelper/Model/R2Upload.cs
Normal file
35
EftPatchHelper/EftPatchHelper/Model/R2Upload.cs
Normal file
@ -0,0 +1,35 @@
|
||||
using EftPatchHelper.Helpers;
|
||||
using EftPatchHelper.Interfaces;
|
||||
|
||||
namespace EftPatchHelper.Model;
|
||||
|
||||
public class R2Upload : IFileUpload
|
||||
{
|
||||
public string DisplayName { get; set; }
|
||||
public string ServiceName { get; set; }
|
||||
public string HubEntryText { get; set; }
|
||||
public FileInfo UploadFileInfo { get; }
|
||||
public bool AddHubEntry { get; }
|
||||
|
||||
private readonly R2Helper _r2;
|
||||
|
||||
public R2Upload(FileInfo file, R2Helper r2)
|
||||
{
|
||||
_r2 = r2;
|
||||
UploadFileInfo = file;
|
||||
ServiceName = $"R2::{_r2.BucketName} Upload";
|
||||
DisplayName = $"{ServiceName} Upload";
|
||||
HubEntryText = $"Download from {ServiceName}";
|
||||
AddHubEntry = false;
|
||||
}
|
||||
|
||||
public string GetLink()
|
||||
{
|
||||
return $"{_r2.ConnectedDomain}/{UploadFileInfo.Name}";
|
||||
}
|
||||
|
||||
public async Task<bool> UploadAsync(IProgress<double>? progress = null)
|
||||
{
|
||||
return await _r2.UploadToBucketAsync(UploadFileInfo, progress);
|
||||
}
|
||||
}
|
8
EftPatchHelper/EftPatchHelper/Model/ReleaseInfo.cs
Normal file
8
EftPatchHelper/EftPatchHelper/Model/ReleaseInfo.cs
Normal file
@ -0,0 +1,8 @@
|
||||
namespace EftPatchHelper.Model;
|
||||
|
||||
public class ReleaseInfo
|
||||
{
|
||||
public string AkiVersion { get; set; }
|
||||
public string ClientVersion { get; set; }
|
||||
public List<ReleaseInfoMirror> Mirrors { get; set; }
|
||||
}
|
7
EftPatchHelper/EftPatchHelper/Model/ReleaseInfoMirror.cs
Normal file
7
EftPatchHelper/EftPatchHelper/Model/ReleaseInfoMirror.cs
Normal file
@ -0,0 +1,7 @@
|
||||
namespace EftPatchHelper.Model;
|
||||
|
||||
public class ReleaseInfoMirror
|
||||
{
|
||||
public string DownloadUrl { get; set; }
|
||||
public string Hash { get; set; }
|
||||
}
|
136
EftPatchHelper/EftPatchHelper/Model/Settings.cs
Normal file
136
EftPatchHelper/EftPatchHelper/Model/Settings.cs
Normal file
@ -0,0 +1,136 @@
|
||||
using Spectre.Console;
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace EftPatchHelper.Model
|
||||
{
|
||||
public class Settings
|
||||
{
|
||||
[JsonIgnore]
|
||||
public static string settingsFile = Path.Join(Directory.GetCurrentDirectory(), "settings.json");
|
||||
|
||||
[JsonPropertyName("targetEftVersion")]
|
||||
public string TargetEftVersion { get; set; } = "";
|
||||
|
||||
[JsonPropertyName("prepFolderPath")]
|
||||
public string PrepFolderPath { get; set; } = "";
|
||||
|
||||
[JsonPropertyName("backupFolderPath")]
|
||||
public string BackupFolderPath { get; set; } = "";
|
||||
|
||||
[JsonPropertyName("liveEftPath")]
|
||||
public string LiveEftPath { get; set; } = "";
|
||||
|
||||
[JsonPropertyName("autoZip")]
|
||||
public bool AutoZip { get; set; } = true;
|
||||
|
||||
[JsonPropertyName("autoClose")]
|
||||
public bool AutoClose { get; set; } = true;
|
||||
|
||||
[JsonPropertyName("patcherExePath")]
|
||||
public string PatcherEXEPath { get; set; } = "";
|
||||
|
||||
[JsonPropertyName("latestReleaseUrl")]
|
||||
public string LatestReleaseUrl { get; set; } = "";
|
||||
|
||||
[JsonPropertyName("megaEmail")]
|
||||
public string MegaEmail { get; set; } = "";
|
||||
|
||||
[JsonPropertyName("megaPassword")]
|
||||
public string MegaPassword { get; set; } = "";
|
||||
|
||||
[JsonPropertyName("megaUploadFolder")]
|
||||
public string MegaUploadFolder { get; set; } = "";
|
||||
|
||||
[JsonPropertyName("goFileApiKey")]
|
||||
public string GoFileApiKey { get; set; } = "";
|
||||
|
||||
[JsonPropertyName("goFileFolderId")]
|
||||
public string GoFileFolderId { get; set; } = "";
|
||||
|
||||
[JsonPropertyName("r2ConnectedDomainUrl")]
|
||||
public string R2ConnectedDomainUrl { get; set; } = "";
|
||||
|
||||
[JsonPropertyName("r2ServiceUrl")]
|
||||
public string R2ServiceUrl { get; set; } = "";
|
||||
|
||||
[JsonPropertyName("r2BucketName")]
|
||||
public string R2BucketName { get; set; } = "";
|
||||
|
||||
[JsonPropertyName("r2AccessKeyId")]
|
||||
public string R2AccessKeyId { get; set; } = "";
|
||||
|
||||
[JsonPropertyName("r2SecretKeyId")]
|
||||
public string R2SecretKeyId { get; set; } = "";
|
||||
|
||||
[JsonPropertyName("sftpUploads")]
|
||||
public List<SftpUploadInfo> SftpUploads { get; set; } = new();
|
||||
|
||||
public bool Save()
|
||||
{
|
||||
try
|
||||
{
|
||||
string json = JsonSerializer.Serialize(this, typeof(Settings), new JsonSerializerOptions() { WriteIndented = true });
|
||||
|
||||
if (string.IsNullOrWhiteSpace(json))
|
||||
{
|
||||
AnsiConsole.WriteLine("[red]!! Nothing was serialized !![/]");
|
||||
return false;
|
||||
}
|
||||
|
||||
File.WriteAllText(settingsFile, json);
|
||||
|
||||
return true;
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
AnsiConsole.WriteException(ex);
|
||||
return false;
|
||||
}
|
||||
}
|
||||
|
||||
public bool UsingMega()
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(MegaEmail)) return false;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(MegaPassword)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool UsingGoFile()
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(GoFileApiKey)) return false;
|
||||
|
||||
if(string.IsNullOrWhiteSpace(GoFileFolderId)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool UsingR2()
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(R2ConnectedDomainUrl)) return false;
|
||||
if (string.IsNullOrWhiteSpace(R2ServiceUrl)) return false;
|
||||
if (string.IsNullOrWhiteSpace(R2BucketName)) return false;
|
||||
if (string.IsNullOrWhiteSpace(R2AccessKeyId)) return false;
|
||||
if (string.IsNullOrWhiteSpace(R2SecretKeyId)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
public bool Validate()
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(TargetEftVersion)) return false;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(PrepFolderPath)) return false;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(BackupFolderPath)) return false;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(LiveEftPath)) return false;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(PatcherEXEPath)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
79
EftPatchHelper/EftPatchHelper/Model/SftpUpload.cs
Normal file
79
EftPatchHelper/EftPatchHelper/Model/SftpUpload.cs
Normal file
@ -0,0 +1,79 @@
|
||||
using EftPatchHelper.Interfaces;
|
||||
using WinSCP;
|
||||
|
||||
namespace EftPatchHelper.Model;
|
||||
|
||||
public class SftpUpload : IFileUpload
|
||||
{
|
||||
private readonly SftpUploadInfo _sftpInfo;
|
||||
private readonly SessionOptions _sessionOptions;
|
||||
public string DisplayName { get; set; }
|
||||
public string ServiceName { get; set; }
|
||||
public string HubEntryText { get; set; }
|
||||
public bool AddHubEntry { get; }
|
||||
|
||||
public FileInfo UploadFileInfo { get; }
|
||||
|
||||
public SftpUpload(FileInfo file, SftpUploadInfo sftpInfo)
|
||||
{
|
||||
UploadFileInfo = file;
|
||||
_sftpInfo = sftpInfo;
|
||||
|
||||
_sessionOptions = new SessionOptions
|
||||
{
|
||||
Protocol = Protocol.Sftp,
|
||||
UserName = _sftpInfo.Username,
|
||||
Password = _sftpInfo.Password,
|
||||
HostName = _sftpInfo.Hostname,
|
||||
PortNumber = _sftpInfo.Port,
|
||||
SshHostKeyFingerprint = _sftpInfo.HostKey
|
||||
};
|
||||
|
||||
ServiceName = _sftpInfo.Hostname;
|
||||
DisplayName = $"{ServiceName} Upload";
|
||||
HubEntryText = $"Download from {ServiceName}";
|
||||
AddHubEntry = sftpInfo.AllowHubEntry;
|
||||
}
|
||||
|
||||
public string GetLink()
|
||||
{
|
||||
var link = _sftpInfo.HttpPath;
|
||||
|
||||
if (!link.EndsWith('/'))
|
||||
{
|
||||
link += "/";
|
||||
}
|
||||
|
||||
return $"{link}{UploadFileInfo.Name}";
|
||||
}
|
||||
|
||||
public Task<bool> UploadAsync(IProgress<double>? progress = null)
|
||||
{
|
||||
TransferOptions transferOptions = new TransferOptions
|
||||
{
|
||||
TransferMode = TransferMode.Binary,
|
||||
};
|
||||
|
||||
using Session session = new Session();
|
||||
|
||||
if (progress != null)
|
||||
{
|
||||
session.FileTransferProgress += (_, args) => progress.Report(Math.Floor(args.FileProgress * 100));
|
||||
}
|
||||
|
||||
try
|
||||
{
|
||||
session.Open(_sessionOptions);
|
||||
|
||||
session.PutFiles(UploadFileInfo.FullName, $"{_sftpInfo.UploadPath}/{UploadFileInfo.Name}", false, transferOptions).Check();
|
||||
|
||||
return Task.FromResult(true);
|
||||
}
|
||||
catch
|
||||
{
|
||||
// ignored
|
||||
}
|
||||
|
||||
return Task.FromResult(false);
|
||||
}
|
||||
}
|
56
EftPatchHelper/EftPatchHelper/Model/SftpUploadInfo.cs
Normal file
56
EftPatchHelper/EftPatchHelper/Model/SftpUploadInfo.cs
Normal file
@ -0,0 +1,56 @@
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace EftPatchHelper.Model;
|
||||
|
||||
public class SftpUploadInfo
|
||||
{
|
||||
[JsonPropertyName("username")]
|
||||
public string Username { get; set; } = "";
|
||||
|
||||
[JsonPropertyName("password")]
|
||||
public string Password { get; set; } = "";
|
||||
|
||||
[JsonPropertyName("hostKey")]
|
||||
public string HostKey { get; set; } = "";
|
||||
|
||||
[JsonPropertyName("hostname")]
|
||||
public string Hostname { get; set; } = "";
|
||||
|
||||
[JsonPropertyName("port")]
|
||||
public int Port { get; set; } = 0;
|
||||
|
||||
[JsonPropertyName("uploadPath")]
|
||||
public string UploadPath { get; set; } = "";
|
||||
|
||||
[JsonPropertyName("httpPath")]
|
||||
public string HttpPath { get; set; } = "";
|
||||
|
||||
[JsonPropertyName("allowHubEntry")]
|
||||
public bool AllowHubEntry { get; set; } = false;
|
||||
|
||||
public bool IsValid()
|
||||
{
|
||||
if (string.IsNullOrWhiteSpace(Username))
|
||||
return false;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(Password))
|
||||
return false;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(Hostname))
|
||||
return false;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(HostKey))
|
||||
return false;
|
||||
|
||||
if (Port == 0)
|
||||
return false;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(UploadPath))
|
||||
return false;
|
||||
|
||||
if (string.IsNullOrWhiteSpace(HttpPath))
|
||||
return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
@ -1,144 +1,125 @@
|
||||
// See https://aka.ms/new-console-template for more information
|
||||
using EftPatchHelper;
|
||||
|
||||
using System.Reflection;
|
||||
using EftPatchHelper.Helpers;
|
||||
using EftPatchHelper.Interfaces;
|
||||
using EftPatchHelper.Model;
|
||||
using EftPatchHelper.Tasks;
|
||||
using Microsoft.Extensions.Configuration;
|
||||
using Microsoft.Extensions.DependencyInjection;
|
||||
using Microsoft.Extensions.Hosting;
|
||||
using Spectre.Console;
|
||||
using System.Diagnostics;
|
||||
|
||||
Settings? settings = Settings.Load();
|
||||
|
||||
// check settings file exists
|
||||
if(settings == null)
|
||||
namespace EftPatchHelper
|
||||
{
|
||||
settings = new Settings();
|
||||
settings.Save();
|
||||
public class Program
|
||||
{
|
||||
ITaskable _settingsTasks;
|
||||
ITaskable _clientSelectionTasks;
|
||||
ITaskable _cleanupTasks;
|
||||
ITaskable _fileProcessingTasks;
|
||||
ITaskable _patchGenTasks;
|
||||
ITaskable _patchTestingTasks;
|
||||
ITaskable _compressPatcherTasks;
|
||||
ITaskable _uploadTasks;
|
||||
ITaskable _uploadMirrorList;
|
||||
|
||||
public static void Main(string[] args)
|
||||
{
|
||||
Console.OutputEncoding = System.Text.Encoding.UTF8;
|
||||
|
||||
AnsiConsole.Write(new FigletText("EFT Patch Helper").Centered().Color(Color.Blue));
|
||||
var version = Assembly.GetExecutingAssembly().GetName().Version;
|
||||
AnsiConsole.Write(new Rule($"[purple]v{version}[/]").Centered().RuleStyle("blue"));
|
||||
|
||||
try
|
||||
{
|
||||
var host = ConfigureHost(args);
|
||||
host.Services.GetRequiredService<Program>().Run();
|
||||
}
|
||||
catch (Exception ex)
|
||||
{
|
||||
AnsiConsole.MarkupLine($"[red]{ex.Message.EscapeMarkup()}[/]");
|
||||
}
|
||||
|
||||
AnsiConsole.MarkupLine($"Settings file was create here: \n[blue]{Settings.settingsFile}[/]\n\nPlease update it and try again.");
|
||||
AnsiConsole.MarkupLine("Press [blue]Enter[/] to close ...");
|
||||
Console.ReadLine();
|
||||
return;
|
||||
}
|
||||
|
||||
// validate settings
|
||||
if(!settings.Validate())
|
||||
{
|
||||
AnsiConsole.MarkupLine($"[red]Settings file seems to be missing some information, please fix it[/]\n\nPath to file:\n[blue]{Settings.settingsFile}[/]\n\n");
|
||||
AnsiConsole.MarkupLine("Press [blue]Enter[/] to close ...");
|
||||
Console.ReadLine();
|
||||
return;
|
||||
}
|
||||
|
||||
/// Fancy
|
||||
AnsiConsole.Write(new FigletText("EFT Patch Helper").Centered().Color(Color.Blue));
|
||||
|
||||
// show some settings information
|
||||
AnsiConsole.WriteLine();
|
||||
AnsiConsole.MarkupLine($"Current target version is [purple]{settings.TargetEftVersion}[/]");
|
||||
AnsiConsole.MarkupLine($"Prep folder path is [purple]{settings.PrepFolderPath}[/]");
|
||||
AnsiConsole.MarkupLine($"Backup folder path is [purple]{settings.BackupFolderPath}[/]");
|
||||
AnsiConsole.WriteLine();
|
||||
|
||||
// Source Selection Prompt
|
||||
SelectionPrompt<string> sourcePrompt = new SelectionPrompt<string>()
|
||||
{
|
||||
Title = "Select Source Version",
|
||||
MoreChoicesText = "Move cursor to see more versions",
|
||||
PageSize = 10
|
||||
};
|
||||
|
||||
// Get eft live version
|
||||
var eftVersion = FileVersionInfo.GetVersionInfo(Path.Join(settings.LiveEftPath, "EscapeFromTarkov.exe")).ProductVersion?.Replace('-', '.');
|
||||
|
||||
if(eftVersion != null)
|
||||
{
|
||||
//remove leading 0 from version number
|
||||
if (eftVersion.StartsWith("0."))
|
||||
{
|
||||
eftVersion = eftVersion.Remove(0, 2);
|
||||
}
|
||||
|
||||
// add eft liver version to selection prompt choices
|
||||
sourcePrompt.AddChoice($"Live: {eftVersion}");
|
||||
}
|
||||
|
||||
// add backup folders to source prompt choices
|
||||
foreach(string backup in Directory.GetDirectories(settings.BackupFolderPath))
|
||||
{
|
||||
DirectoryInfo backupDir = new DirectoryInfo(backup);
|
||||
|
||||
if(!backupDir.Exists)
|
||||
public Program(
|
||||
ISettingsTask settingsTasks,
|
||||
IClientSelectionTask clientSelectionTasks,
|
||||
ICleanupTask cleanupTasks,
|
||||
IFileProcessingTasks fileProcessingTasks,
|
||||
IPatchGenTasks patchGenTasks,
|
||||
IPatchTestingTasks patchTestingTasks,
|
||||
ICompressPatcherTasks compressPatcherTasks,
|
||||
IUploadTasks uploadTasks,
|
||||
IMirrorUploader uploadMirrorList
|
||||
)
|
||||
{
|
||||
continue;
|
||||
_settingsTasks = settingsTasks;
|
||||
_clientSelectionTasks = clientSelectionTasks;
|
||||
_cleanupTasks = cleanupTasks;
|
||||
_fileProcessingTasks = fileProcessingTasks;
|
||||
_patchGenTasks = patchGenTasks;
|
||||
_patchTestingTasks = patchTestingTasks;
|
||||
_compressPatcherTasks = compressPatcherTasks;
|
||||
_uploadMirrorList = uploadMirrorList;
|
||||
_uploadTasks = uploadTasks;
|
||||
}
|
||||
|
||||
sourcePrompt.AddChoice($"Backup: {backupDir.Name}");
|
||||
}
|
||||
|
||||
|
||||
string result = sourcePrompt.Show(AnsiConsole.Console);
|
||||
|
||||
string sourceVersion = result.Split(": ")[1];
|
||||
|
||||
string sourceBackupPath = Path.Join(settings.BackupFolderPath, sourceVersion);
|
||||
|
||||
//backup live folder if it was selected
|
||||
if(result.StartsWith("Live:"))
|
||||
{
|
||||
// only backup the live folder if it doesn't exist already
|
||||
if(!Directory.Exists(sourceBackupPath))
|
||||
public void Run()
|
||||
{
|
||||
AnsiConsole.MarkupLine("[blue]Backing up live ...[/]");
|
||||
FolderCopy backupLiveCopy = new FolderCopy(settings.LiveEftPath, sourceBackupPath);
|
||||
|
||||
backupLiveCopy.Start();
|
||||
_settingsTasks.Run();
|
||||
_clientSelectionTasks.Run();
|
||||
_cleanupTasks.Run();
|
||||
_fileProcessingTasks.Run();
|
||||
_patchGenTasks.Run();
|
||||
_patchTestingTasks.Run();
|
||||
_compressPatcherTasks.Run();
|
||||
_uploadTasks.Run();
|
||||
_uploadMirrorList.Run();
|
||||
}
|
||||
}
|
||||
|
||||
string targetBackupPath = Path.Join(settings.BackupFolderPath, settings.TargetEftVersion);
|
||||
|
||||
string targetPrepPath = Path.Join(settings.PrepFolderPath, settings.TargetEftVersion);
|
||||
|
||||
string sourcePrepPath = Path.Join(settings.PrepFolderPath, sourceVersion);
|
||||
|
||||
|
||||
//copy source to prep directory
|
||||
AnsiConsole.MarkupLine("[gray]Copying[/] [blue]source[/][gray] to prep area ...[/]");
|
||||
|
||||
FolderCopy sourceCopy = new FolderCopy(sourceBackupPath, sourcePrepPath);
|
||||
|
||||
sourceCopy.Start();
|
||||
|
||||
//copy target to prep directory
|
||||
AnsiConsole.MarkupLine("[gray]Copying[/] [blue]target[/][gray] to prep area ...[/]");
|
||||
|
||||
FolderCopy targetCopy = new FolderCopy(targetBackupPath, targetPrepPath);
|
||||
|
||||
targetCopy.Start();
|
||||
|
||||
// clean prep source and target folders of uneeded data
|
||||
FolderCleaner.Clean(sourcePrepPath);
|
||||
|
||||
FolderCleaner.Clean(targetPrepPath);
|
||||
|
||||
// start patcher
|
||||
if(File.Exists(settings.PatcherEXEPath))
|
||||
{
|
||||
string patcherOutputName = $"Patcher_{sourceVersion}_to_{settings.TargetEftVersion}";
|
||||
|
||||
AnsiConsole.Markup("Starting patcher ... ");
|
||||
|
||||
Process.Start(new ProcessStartInfo()
|
||||
private static IHost ConfigureHost(string[] args)
|
||||
{
|
||||
FileName = settings.PatcherEXEPath,
|
||||
WorkingDirectory = new FileInfo(settings.PatcherEXEPath).Directory?.FullName ?? Directory.GetCurrentDirectory(),
|
||||
ArgumentList = {$"OutputFolderName::{patcherOutputName}", $"SourceFolderPath::{sourcePrepPath}", $"TargetFolderPath::{targetPrepPath}", $"AutoZip::{settings.AutoZip}"}
|
||||
return Host.CreateDefaultBuilder(args).ConfigureServices((_, services) =>
|
||||
{
|
||||
HttpClient client = new HttpClient() { Timeout = TimeSpan.FromHours(1) };
|
||||
|
||||
services.AddSingleton<Options>();
|
||||
services.AddSingleton(client);
|
||||
services.AddSingleton<Settings>(serviceProvider =>
|
||||
{
|
||||
var configuration = serviceProvider.GetRequiredService<IConfiguration>();
|
||||
var settings = configuration.Get<Settings>();
|
||||
if (settings == null) throw new Exception("Failed to retrieve settings");
|
||||
return settings;
|
||||
});
|
||||
|
||||
services.AddSingleton<FileHelper>();
|
||||
services.AddSingleton<ZipHelper>();
|
||||
services.AddSingleton<R2Helper>();
|
||||
|
||||
services.AddScoped<EftClientSelector>();
|
||||
|
||||
services.AddTransient<ISettingsTask, StartupSettingsTask>();
|
||||
services.AddTransient<ICleanupTask, CleanupTask>();
|
||||
services.AddTransient<IClientSelectionTask, ClientSelectionTask>();
|
||||
services.AddTransient<IFileProcessingTasks, FileProcessingTasks>();
|
||||
services.AddTransient<IPatchGenTasks, PatchGenTasks>();
|
||||
services.AddTransient<IPatchTestingTasks, PatchTestingTasks>();
|
||||
services.AddTransient<ICompressPatcherTasks, CompressPatcherTasks>();
|
||||
services.AddTransient<IUploadTasks, UploadTasks>();
|
||||
services.AddTransient<IMirrorUploader, UploadMirrorListTasks>();
|
||||
services.AddTransient<Program>();
|
||||
})
|
||||
.ConfigureAppConfiguration((_, config) =>
|
||||
{
|
||||
config.AddJsonFile(Settings.settingsFile, optional: true, reloadOnChange: true);
|
||||
})
|
||||
.Build();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
||||
AnsiConsole.MarkupLine("[green]done[/]");
|
||||
|
||||
AnsiConsole.WriteLine();
|
||||
|
||||
// done
|
||||
AnsiConsole.MarkupLine("Press [blue]Enter[/] to close ...");
|
||||
|
||||
Console.ReadLine();
|
BIN
EftPatchHelper/EftPatchHelper/Resources/7z.dll
Normal file
BIN
EftPatchHelper/EftPatchHelper/Resources/7z.dll
Normal file
Binary file not shown.
BIN
EftPatchHelper/EftPatchHelper/Resources/Gitea.dll
Normal file
BIN
EftPatchHelper/EftPatchHelper/Resources/Gitea.dll
Normal file
Binary file not shown.
BIN
EftPatchHelper/EftPatchHelper/Resources/WinSCPnet.dll
Normal file
BIN
EftPatchHelper/EftPatchHelper/Resources/WinSCPnet.dll
Normal file
Binary file not shown.
@ -1,62 +0,0 @@
|
||||
using System.Text.Json;
|
||||
using System.Text.Json.Serialization;
|
||||
|
||||
namespace EftPatchHelper
|
||||
{
|
||||
public class Settings
|
||||
{
|
||||
[JsonIgnore]
|
||||
public static string settingsFile = Path.Join(Directory.GetCurrentDirectory(), "settings.json");
|
||||
|
||||
[JsonPropertyName("target_eft_version")]
|
||||
public string TargetEftVersion { get; set; } = "";
|
||||
|
||||
[JsonPropertyName("prep_folder_path")]
|
||||
public string PrepFolderPath { get; set; } = "";
|
||||
|
||||
[JsonPropertyName("backup_folder_path")]
|
||||
public string BackupFolderPath { get; set; } = "";
|
||||
|
||||
[JsonPropertyName("live_eft_path")]
|
||||
public string LiveEftPath { get; set; } = "";
|
||||
|
||||
[JsonPropertyName("auto_zip")]
|
||||
public bool AutoZip { get; set; } = true;
|
||||
|
||||
[JsonPropertyName("patcher_exe_path")]
|
||||
public string PatcherEXEPath { get; set; } = "";
|
||||
|
||||
public void Save()
|
||||
{
|
||||
string json = JsonSerializer.Serialize(this, typeof(Settings), new JsonSerializerOptions() { WriteIndented = true });
|
||||
|
||||
if (string.IsNullOrWhiteSpace(json)) return;
|
||||
|
||||
File.WriteAllText(settingsFile, json);
|
||||
}
|
||||
|
||||
public static Settings? Load()
|
||||
{
|
||||
if (!File.Exists(settingsFile)) return null;
|
||||
|
||||
string json = File.ReadAllText(settingsFile);
|
||||
|
||||
return JsonSerializer.Deserialize<Settings>(json);
|
||||
}
|
||||
|
||||
public bool Validate()
|
||||
{
|
||||
if(string.IsNullOrWhiteSpace(TargetEftVersion)) return false;
|
||||
|
||||
if(string.IsNullOrWhiteSpace(PrepFolderPath)) return false;
|
||||
|
||||
if(string.IsNullOrWhiteSpace(BackupFolderPath)) return false;
|
||||
|
||||
if(string.IsNullOrWhiteSpace(LiveEftPath)) return false;
|
||||
|
||||
if(string.IsNullOrWhiteSpace(PatcherEXEPath)) return false;
|
||||
|
||||
return true;
|
||||
}
|
||||
}
|
||||
}
|
103
EftPatchHelper/EftPatchHelper/Tasks/CleanupTask.cs
Normal file
103
EftPatchHelper/EftPatchHelper/Tasks/CleanupTask.cs
Normal file
@ -0,0 +1,103 @@
|
||||
using EftPatchHelper.Interfaces;
|
||||
using EftPatchHelper.Model;
|
||||
using Spectre.Console;
|
||||
|
||||
namespace EftPatchHelper.Tasks
|
||||
{
|
||||
public class CleanupTask : ICleanupTask
|
||||
{
|
||||
private Settings _settings;
|
||||
private Options _options;
|
||||
|
||||
List<FileSystemInfo> _fileToRemove = new List<FileSystemInfo>();
|
||||
|
||||
public CleanupTask(Settings settings, Options options)
|
||||
{
|
||||
_settings = settings;
|
||||
_options = options;
|
||||
}
|
||||
|
||||
private void GetPathsToRemove()
|
||||
{
|
||||
var prepFolders = Directory.GetDirectories(_settings.PrepFolderPath, "*");
|
||||
|
||||
foreach (var prepFolder in prepFolders)
|
||||
{
|
||||
if (prepFolder == _options.TargetClient.PrepPath && !File.Exists(Path.Join(prepFolder, "Patcher.exe")))
|
||||
continue;
|
||||
|
||||
_fileToRemove.Add(new DirectoryInfo(prepFolder));
|
||||
}
|
||||
|
||||
var mirrorsPath = Path.Join(Environment.CurrentDirectory, "mirrors.json");
|
||||
var hubentries = Directory.GetFiles(Environment.CurrentDirectory, "hubEntry_*.txt");
|
||||
|
||||
if (File.Exists(mirrorsPath))
|
||||
_fileToRemove.Add(new FileInfo(mirrorsPath));
|
||||
|
||||
_fileToRemove.AddRange(hubentries.Select(x => new FileInfo(x)));
|
||||
|
||||
var patcherDir = new FileInfo(_settings.PatcherEXEPath).Directory;
|
||||
|
||||
_fileToRemove.AddRange(patcherDir.GetFiles().Where(x => x.FullName != _settings.PatcherEXEPath));
|
||||
_fileToRemove.AddRange(patcherDir.GetDirectories("*", SearchOption.TopDirectoryOnly));
|
||||
}
|
||||
|
||||
private void RemoveData(Table table)
|
||||
{
|
||||
AnsiConsole.Live(table).Start(ctx =>
|
||||
{
|
||||
for (int i = 0; i < _fileToRemove.Count; i++)
|
||||
{
|
||||
table.UpdateCell(i, 0, "[white]Removing ...[/]");
|
||||
|
||||
ctx.Refresh();
|
||||
|
||||
var item = _fileToRemove[i];
|
||||
|
||||
if (item is DirectoryInfo dir)
|
||||
dir.Delete(true);
|
||||
|
||||
if (item is FileInfo file)
|
||||
file.Delete();
|
||||
|
||||
|
||||
table.UpdateCell(i, 0, item.Exists ? "[red]Exists[/]" : "[green]Removed[/]");
|
||||
ctx.Refresh();
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void Run()
|
||||
{
|
||||
GetPathsToRemove();
|
||||
|
||||
if (_fileToRemove.Count == 0)
|
||||
return;
|
||||
|
||||
Table removableFilesTable = new Table()
|
||||
.Alignment(Justify.Center)
|
||||
.AddColumn("Status")
|
||||
.AddColumn("File Name")
|
||||
.AddColumn("Full Path")
|
||||
.BorderStyle(Style.Parse("blue"));
|
||||
|
||||
foreach (var file in _fileToRemove)
|
||||
{
|
||||
removableFilesTable.AddRow("[grey]Exists[/]", file.Name, file.FullName);
|
||||
}
|
||||
|
||||
var cursorPos = Console.GetCursorPosition();
|
||||
|
||||
AnsiConsole.Write(removableFilesTable);
|
||||
|
||||
|
||||
var removeFiles = new ConfirmationPrompt("Run cleanup to remove files shown above?").Show(AnsiConsole.Console);
|
||||
|
||||
Console.SetCursorPosition(cursorPos.Left, cursorPos.Top);
|
||||
|
||||
if (removeFiles)
|
||||
RemoveData(removableFilesTable);
|
||||
}
|
||||
}
|
||||
}
|
88
EftPatchHelper/EftPatchHelper/Tasks/ClientSelectionTask.cs
Normal file
88
EftPatchHelper/EftPatchHelper/Tasks/ClientSelectionTask.cs
Normal file
@ -0,0 +1,88 @@
|
||||
using System.Net.Http.Json;
|
||||
using EftPatchHelper.Extensions;
|
||||
using EftPatchHelper.Helpers;
|
||||
using EftPatchHelper.Interfaces;
|
||||
using EftPatchHelper.Model;
|
||||
using Spectre.Console;
|
||||
|
||||
namespace EftPatchHelper.Tasks
|
||||
{
|
||||
public class ClientSelectionTask : IClientSelectionTask
|
||||
{
|
||||
private Settings _settings;
|
||||
private Options _options;
|
||||
private EftClientSelector _clientSelector;
|
||||
private HttpClient _http;
|
||||
|
||||
public ClientSelectionTask(Settings settings, Options options, EftClientSelector clientSelector, HttpClient client)
|
||||
{
|
||||
_settings = settings;
|
||||
_options = options;
|
||||
_http = client;
|
||||
_clientSelector = clientSelector;
|
||||
}
|
||||
|
||||
private bool ChangeSettingsTargetVersion(string currentReleaseVersion)
|
||||
{
|
||||
_options.TargetClient = _clientSelector.GetClientSelection("Select [yellow]Target[/] Version", currentReleaseVersion);
|
||||
|
||||
AnsiConsole.WriteLine();
|
||||
ConfirmationPrompt changeVersion = new ConfirmationPrompt($"Update settings target version to use [purple]{_options.TargetClient.Version}[/]?");
|
||||
|
||||
if (changeVersion.Show(AnsiConsole.Console))
|
||||
{
|
||||
_settings.TargetEftVersion = _options.TargetClient.Version;
|
||||
|
||||
return _settings.Save();
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private bool ConfirmExistingTargetVersion(string currentReleaseVersion)
|
||||
{
|
||||
_clientSelector.LoadClientList();
|
||||
|
||||
_options.TargetClient = _clientSelector.GetClient(_settings.TargetEftVersion);
|
||||
|
||||
ConfirmationPrompt confirmTarget = new ConfirmationPrompt($"Use version [purple]{_settings.TargetEftVersion}[/] {(_options.TargetClient.Version.EndsWith(currentReleaseVersion) ? " ([green]latest release[/])" : "")} as target?");
|
||||
|
||||
// If client is null or requested change, return false to ensure change settings target is called.
|
||||
return _options.TargetClient == null || !confirmTarget.Show(AnsiConsole.Console);
|
||||
}
|
||||
|
||||
private bool SelectSourceVersion()
|
||||
{
|
||||
_options.SourceClient = _clientSelector.GetClientSelection("Select [blue]Source[/] Version");
|
||||
|
||||
return _options.SourceClient != null;
|
||||
}
|
||||
|
||||
private string GetCurrentReleaseVersion()
|
||||
{
|
||||
return AnsiConsole.Status().Start("Starting...", async ctx =>
|
||||
{
|
||||
ctx.Spinner = Spinner.Known.Dots8;
|
||||
ctx.Status = "Getting latest release ...";
|
||||
|
||||
var blah = await _http.GetAsync(_settings.LatestReleaseUrl);
|
||||
var release = await blah.Content.ReadFromJsonAsync<ReleaseInfo>();
|
||||
|
||||
return release?.ClientVersion ?? "failed to get version :(";
|
||||
}).GetAwaiter().GetResult();
|
||||
}
|
||||
|
||||
public void Run()
|
||||
{
|
||||
var currentReleaseVersion = GetCurrentReleaseVersion();
|
||||
|
||||
if (ConfirmExistingTargetVersion(currentReleaseVersion))
|
||||
{
|
||||
ChangeSettingsTargetVersion(currentReleaseVersion).ValidateOrExit();
|
||||
}
|
||||
|
||||
SelectSourceVersion().ValidateOrExit();
|
||||
}
|
||||
}
|
||||
}
|
||||
|
63
EftPatchHelper/EftPatchHelper/Tasks/CompressPatcherTasks.cs
Normal file
63
EftPatchHelper/EftPatchHelper/Tasks/CompressPatcherTasks.cs
Normal file
@ -0,0 +1,63 @@
|
||||
using EftPatchHelper.Extensions;
|
||||
using EftPatchHelper.Helpers;
|
||||
using EftPatchHelper.Interfaces;
|
||||
using EftPatchHelper.Model;
|
||||
using Spectre.Console;
|
||||
|
||||
namespace EftPatchHelper.Tasks;
|
||||
|
||||
public class CompressPatcherTasks : ICompressPatcherTasks
|
||||
{
|
||||
private Options _options;
|
||||
private FileHelper _fileHelper;
|
||||
private ZipHelper _zipHelper;
|
||||
|
||||
public CompressPatcherTasks(Options options, FileHelper fileHelper, ZipHelper zipHelper)
|
||||
{
|
||||
_options = options;
|
||||
_fileHelper = fileHelper;
|
||||
_zipHelper = zipHelper;
|
||||
}
|
||||
|
||||
public bool CompressPatcher()
|
||||
{
|
||||
return AnsiConsole.Progress()
|
||||
.Columns(new ProgressColumn[]
|
||||
{
|
||||
new TaskDescriptionColumn(),
|
||||
new ProgressBarColumn(),
|
||||
new PercentageColumn(),
|
||||
new ElapsedTimeColumn(),
|
||||
new SpinnerColumn(Spinner.Known.Dots2)
|
||||
})
|
||||
.Start(ctx =>
|
||||
{
|
||||
|
||||
var compressionTask = ctx.AddTask("Compressing Patcher");
|
||||
compressionTask.MaxValue = 100;
|
||||
|
||||
if (!_fileHelper.StreamAssemblyResourceOut("7z.dll", _zipHelper.DllPath))
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var patchFolder = new DirectoryInfo(_options.OutputPatchPath);
|
||||
|
||||
var patchArchiveFile = new FileInfo(_options.OutputPatchPath + ".7z");
|
||||
|
||||
if (!patchFolder.Exists)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var progress = new Progress<double>(p => { compressionTask.Increment(p - compressionTask.Percentage);});
|
||||
|
||||
return _zipHelper.Compress(patchFolder, patchArchiveFile, progress);
|
||||
});
|
||||
}
|
||||
|
||||
public void Run()
|
||||
{
|
||||
CompressPatcher().ValidateOrExit();
|
||||
}
|
||||
}
|
57
EftPatchHelper/EftPatchHelper/Tasks/FileProcessingTasks.cs
Normal file
57
EftPatchHelper/EftPatchHelper/Tasks/FileProcessingTasks.cs
Normal file
@ -0,0 +1,57 @@
|
||||
using EftPatchHelper.EftInfo;
|
||||
using EftPatchHelper.Extensions;
|
||||
using EftPatchHelper.Helpers;
|
||||
using EftPatchHelper.Interfaces;
|
||||
using EftPatchHelper.Model;
|
||||
using Spectre.Console;
|
||||
|
||||
namespace EftPatchHelper.Tasks
|
||||
{
|
||||
public class FileProcessingTasks : IFileProcessingTasks
|
||||
{
|
||||
Settings _settings;
|
||||
Options _options;
|
||||
|
||||
public FileProcessingTasks(Settings settings, Options options)
|
||||
{
|
||||
_settings = settings;
|
||||
_options = options;
|
||||
}
|
||||
|
||||
private bool BackupClients()
|
||||
{
|
||||
bool targetOK = _options.TargetClient.Backup(_settings, _options.IgnoreExistingDirectories);
|
||||
bool sourceOK = _options.SourceClient.Backup(_settings, _options.IgnoreExistingDirectories);
|
||||
|
||||
return targetOK && sourceOK;
|
||||
}
|
||||
|
||||
private bool CopyData(EftClient client, string message)
|
||||
{
|
||||
AnsiConsole.WriteLine();
|
||||
AnsiConsole.MarkupLine(message);
|
||||
|
||||
var folderCopy = new FolderCopy(client.FolderPath, client.PrepPath);
|
||||
|
||||
return folderCopy.Start(_options.IgnoreExistingDirectories);
|
||||
}
|
||||
|
||||
private void CleanPrepFolders()
|
||||
{
|
||||
FolderCleaner.Clean(_options.TargetClient.PrepPath);
|
||||
FolderCleaner.Clean(_options.SourceClient.PrepPath);
|
||||
}
|
||||
|
||||
public void Run()
|
||||
{
|
||||
AnsiConsole.Write(new Rule("Starting Tasks, this will take some time :)"));
|
||||
|
||||
BackupClients().ValidateOrExit();
|
||||
|
||||
CopyData(_options.SourceClient, "[gray]Copying[/] [blue]source[/][gray] to prep area ...[/]").ValidateOrExit();
|
||||
CopyData(_options.TargetClient, "[gray]Copying[/] [blue]target[/][gray] to prep area ...[/]").ValidateOrExit();
|
||||
|
||||
CleanPrepFolders();
|
||||
}
|
||||
}
|
||||
}
|
92
EftPatchHelper/EftPatchHelper/Tasks/PatchGenTasks.cs
Normal file
92
EftPatchHelper/EftPatchHelper/Tasks/PatchGenTasks.cs
Normal file
@ -0,0 +1,92 @@
|
||||
using EftPatchHelper.Extensions;
|
||||
using EftPatchHelper.Interfaces;
|
||||
using EftPatchHelper.Model;
|
||||
using Spectre.Console;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace EftPatchHelper.Tasks
|
||||
{
|
||||
internal class PatchGenTasks : IPatchGenTasks
|
||||
{
|
||||
private Settings _settings;
|
||||
private Options _options;
|
||||
|
||||
public PatchGenTasks(Settings settings, Options options)
|
||||
{
|
||||
_settings = settings;
|
||||
_options = options;
|
||||
}
|
||||
|
||||
private bool RunPatchGenerator()
|
||||
{
|
||||
if (!File.Exists(_settings.PatcherEXEPath))
|
||||
{
|
||||
AnsiConsole.WriteLine("Could not find patch generator exe");
|
||||
return false;
|
||||
}
|
||||
|
||||
string patcherOutputName = $"Patcher_{_options.SourceClient.Version}_to_{_options.TargetClient.Version}";
|
||||
|
||||
var patcherPath = new FileInfo(_settings.PatcherEXEPath)?.Directory?.FullName;
|
||||
|
||||
if(patcherPath == null)
|
||||
{
|
||||
AnsiConsole.WriteLine("Could not find patch generator folder");
|
||||
return false;
|
||||
}
|
||||
|
||||
_options.OutputPatchPath = Path.Join(patcherPath, patcherOutputName);
|
||||
|
||||
return AnsiConsole.Status().Spinner(Spinner.Known.Shark).Start("Staring Patch Generator ...", (StatusContext context) =>
|
||||
{
|
||||
var genProc = Process.Start(new ProcessStartInfo()
|
||||
{
|
||||
FileName = _settings.PatcherEXEPath,
|
||||
WorkingDirectory = new FileInfo(_settings.PatcherEXEPath).Directory?.FullName ?? Directory.GetCurrentDirectory(),
|
||||
ArgumentList =
|
||||
{
|
||||
$"OutputFolderName::{patcherOutputName}",
|
||||
$"SourceFolderPath::{_options.SourceClient.PrepPath}",
|
||||
$"TargetFolderPath::{_options.TargetClient.PrepPath}",
|
||||
$"AutoZip::false",
|
||||
$"AutoClose::{_settings.AutoClose}"
|
||||
}
|
||||
});
|
||||
|
||||
|
||||
context.Status = "Generating patches ...";
|
||||
|
||||
genProc?.WaitForExit();
|
||||
|
||||
switch ((PatcherExitCode)genProc.ExitCode)
|
||||
{
|
||||
case PatcherExitCode.ProgramClosed:
|
||||
{
|
||||
AnsiConsole.MarkupLine("[red]Program was closed[/]");
|
||||
return false;
|
||||
}
|
||||
case PatcherExitCode.Success:
|
||||
{
|
||||
AnsiConsole.MarkupLine("[green]Patches Generated[/]");
|
||||
return true;
|
||||
}
|
||||
case PatcherExitCode.MissingDir:
|
||||
{
|
||||
AnsiConsole.MarkupLine("[red]Missing Dir[/]");
|
||||
return false;
|
||||
}
|
||||
default:
|
||||
{
|
||||
AnsiConsole.MarkupLine("[red]Something went wrong[/]");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void Run()
|
||||
{
|
||||
RunPatchGenerator().ValidateOrExit();
|
||||
}
|
||||
}
|
||||
}
|
84
EftPatchHelper/EftPatchHelper/Tasks/PatchTestingTasks.cs
Normal file
84
EftPatchHelper/EftPatchHelper/Tasks/PatchTestingTasks.cs
Normal file
@ -0,0 +1,84 @@
|
||||
using EftPatchHelper.Extensions;
|
||||
using EftPatchHelper.Helpers;
|
||||
using EftPatchHelper.Interfaces;
|
||||
using EftPatchHelper.Model;
|
||||
using Spectre.Console;
|
||||
using System.Diagnostics;
|
||||
|
||||
namespace EftPatchHelper.Tasks
|
||||
{
|
||||
public class PatchTestingTasks : IPatchTestingTasks
|
||||
{
|
||||
private Settings _settings;
|
||||
private Options _options;
|
||||
|
||||
public PatchTestingTasks(Settings settings, Options options)
|
||||
{
|
||||
_settings = settings;
|
||||
_options = options;
|
||||
}
|
||||
|
||||
private bool CopySourceToPrep()
|
||||
{
|
||||
AnsiConsole.WriteLine();
|
||||
AnsiConsole.MarkupLine($"Re-copying [blue]source[/] to prep area for testing ...");
|
||||
|
||||
var sourceCopy = new FolderCopy(_options.SourceClient.FolderPath, _options.SourceClient.PrepPath);
|
||||
|
||||
return sourceCopy.Start(false, true);
|
||||
}
|
||||
|
||||
private bool RunPatcher()
|
||||
{
|
||||
var patcherCopy = new FolderCopy(_options.OutputPatchPath, _options.SourceClient.PrepPath);
|
||||
|
||||
patcherCopy.Start(false, true);
|
||||
|
||||
return AnsiConsole.Status().Spinner(Spinner.Known.Shark).Start("Starting Patcher ...", (StatusContext context) =>
|
||||
{
|
||||
var patchProcess = Process.Start(new ProcessStartInfo()
|
||||
{
|
||||
FileName = Path.Join(_options.SourceClient.PrepPath, "patcher.exe"),
|
||||
ArgumentList = { "autoclose" },
|
||||
WorkingDirectory = _options.SourceClient.PrepPath
|
||||
});
|
||||
|
||||
context.Status = "Running Patcher Test ...";
|
||||
|
||||
patchProcess.WaitForExit();
|
||||
|
||||
|
||||
switch ((PatcherExitCode)patchProcess.ExitCode)
|
||||
{
|
||||
case PatcherExitCode.Success:
|
||||
{
|
||||
AnsiConsole.MarkupLine("[green]Patch Test Succeeded[/]");
|
||||
return true;
|
||||
}
|
||||
case PatcherExitCode.NoPatchFolder:
|
||||
{
|
||||
AnsiConsole.MarkupLine("[red]No patch folder found[/]");
|
||||
return false;
|
||||
}
|
||||
case PatcherExitCode.MissingFile:
|
||||
{
|
||||
AnsiConsole.MarkupLine("[red]Missing file[/]");
|
||||
return false;
|
||||
}
|
||||
default:
|
||||
{
|
||||
AnsiConsole.MarkupLine("[red]Something went wrong[/]");
|
||||
return false;
|
||||
}
|
||||
}
|
||||
});
|
||||
}
|
||||
|
||||
public void Run()
|
||||
{
|
||||
CopySourceToPrep().ValidateOrExit();
|
||||
|
||||
RunPatcher().ValidateOrExit();
|
||||
}
|
||||
}
|
||||
}
|
96
EftPatchHelper/EftPatchHelper/Tasks/StartupSettingsTask.cs
Normal file
96
EftPatchHelper/EftPatchHelper/Tasks/StartupSettingsTask.cs
Normal file
@ -0,0 +1,96 @@
|
||||
using EftPatchHelper.Extensions;
|
||||
using EftPatchHelper.Interfaces;
|
||||
using EftPatchHelper.Model;
|
||||
using Spectre.Console;
|
||||
|
||||
namespace EftPatchHelper.Tasks
|
||||
{
|
||||
public class StartupSettingsTask : ISettingsTask
|
||||
{
|
||||
private Settings? _settings { get; set; }
|
||||
private Options _options { get; set; }
|
||||
public StartupSettingsTask(Settings? settings, Options options)
|
||||
{
|
||||
_settings = settings;
|
||||
_options = options;
|
||||
}
|
||||
|
||||
public void PrintSummary()
|
||||
{
|
||||
AnsiConsole.WriteLine();
|
||||
|
||||
// show some settings information
|
||||
Table settingsTable = new Table()
|
||||
.Alignment(Justify.Center)
|
||||
.HorizontalBorder()
|
||||
.HideHeaders()
|
||||
.BorderStyle(Style.Parse("blue"))
|
||||
.AddColumn("Data")
|
||||
.AddColumn("Value")
|
||||
.AddRow("Current target version", $"[purple]{_settings?.TargetEftVersion}[/]")
|
||||
.AddRow("Prep folder path", $"[purple]{_settings?.PrepFolderPath}[/]")
|
||||
.AddRow("Backup folder path", $"[purple]{_settings?.BackupFolderPath}[/]");
|
||||
|
||||
AnsiConsole.Write(settingsTable);
|
||||
|
||||
AnsiConsole.WriteLine();
|
||||
}
|
||||
|
||||
private bool ValidateSettings()
|
||||
{
|
||||
// check settings file exists
|
||||
if (_settings == null)
|
||||
{
|
||||
_settings = new Settings();
|
||||
_settings.Save();
|
||||
|
||||
AnsiConsole.MarkupLine($"Settings file was create here: \n[blue]{Settings.settingsFile}[/]\n\nPlease update it and try again.");
|
||||
return false;
|
||||
}
|
||||
|
||||
// validate settings
|
||||
if (!_settings.Validate())
|
||||
{
|
||||
AnsiConsole.MarkupLine($"[red]Settings file seems to be missing some information, please fix it[/]\n\nPath to file:\n[blue]{Settings.settingsFile}[/]\n\n");
|
||||
return false;
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void ConfirmOptions()
|
||||
{
|
||||
_options.IgnoreExistingDirectories = new ConfirmationPrompt("Skip existing directories? (you will be prompted if no)").Show(AnsiConsole.Console);
|
||||
|
||||
if (_settings.UsingMega())
|
||||
{
|
||||
_options.UploadToMega = new ConfirmationPrompt("Upload to Mega?").Show(AnsiConsole.Console);
|
||||
}
|
||||
|
||||
if (_settings.UsingGoFile())
|
||||
{
|
||||
_options.UploadToGoFile = new ConfirmationPrompt("Upload to GoFile?").Show(AnsiConsole.Console);
|
||||
}
|
||||
|
||||
if (_settings.UsingR2())
|
||||
{
|
||||
_options.UplaodToR2 = new ConfirmationPrompt($"Upload to R2 ({_settings.R2BucketName})?").Show(AnsiConsole.Console);
|
||||
}
|
||||
|
||||
if (_settings.SftpUploads.Count > 0)
|
||||
{
|
||||
_options.UploadToSftpSites =
|
||||
new ConfirmationPrompt($"Upload to SFTP sites? ( {_settings.SftpUploads.Count} sites )").Show(AnsiConsole.Console);
|
||||
}
|
||||
}
|
||||
|
||||
public void Run()
|
||||
{
|
||||
ValidateSettings().ValidateOrExit();
|
||||
|
||||
ConfirmOptions();
|
||||
|
||||
PrintSummary();
|
||||
}
|
||||
}
|
||||
}
|
78
EftPatchHelper/EftPatchHelper/Tasks/UploadMirrorListTasks.cs
Normal file
78
EftPatchHelper/EftPatchHelper/Tasks/UploadMirrorListTasks.cs
Normal file
@ -0,0 +1,78 @@
|
||||
using EftPatchHelper.Interfaces;
|
||||
using EftPatchHelper.Model;
|
||||
using Spectre.Console;
|
||||
using System.Text.Json;
|
||||
using EftPatchHelper.Helpers;
|
||||
|
||||
namespace EftPatchHelper.Tasks
|
||||
{
|
||||
public class UploadMirrorListTasks : IMirrorUploader
|
||||
{
|
||||
private Settings _settings;
|
||||
private Options _options;
|
||||
private R2Helper _r2;
|
||||
|
||||
public UploadMirrorListTasks(Settings settigns, Options options, R2Helper r2)
|
||||
{
|
||||
_settings = settigns;
|
||||
_options = options;
|
||||
_r2 = r2;
|
||||
}
|
||||
|
||||
private async Task<bool> UploadMirrorList(FileInfo file)
|
||||
{
|
||||
return await AnsiConsole.Progress().Columns(new ProgressColumn[]
|
||||
{
|
||||
new TaskDescriptionColumn() { Alignment = Justify.Left },
|
||||
new ProgressBarColumn(),
|
||||
new PercentageColumn(),
|
||||
new RemainingTimeColumn(),
|
||||
new SpinnerColumn(Spinner.Known.Dots2),
|
||||
})
|
||||
.StartAsync(async ctx =>
|
||||
{
|
||||
var uploadTask = ctx.AddTask("mirrors.json upload");
|
||||
|
||||
var progress = new Progress<double>((p) => { uploadTask.Value = p; });
|
||||
|
||||
return await _r2.UploadToBucketAsync(file, progress);
|
||||
});
|
||||
}
|
||||
|
||||
public bool CreateMirrorList(FileInfo mirrorListFileInfo)
|
||||
{
|
||||
var sourcePatchVersion = _options.SourceClient.Version.Split('.').Last();
|
||||
var targetPatchVersion = _options.TargetClient.Version.Split('.').Last();
|
||||
var mirrorInfo = new PatchInfo
|
||||
{
|
||||
SourceClientVersion = int.Parse(sourcePatchVersion),
|
||||
TargetClientVersion = int.Parse(targetPatchVersion),
|
||||
Mirrors = _options.MirrorList.Values.ToList()
|
||||
};
|
||||
|
||||
string json = JsonSerializer.Serialize(mirrorInfo, new JsonSerializerOptions() { WriteIndented = true });
|
||||
|
||||
File.WriteAllText(mirrorListFileInfo.FullName, json);
|
||||
|
||||
mirrorListFileInfo.Refresh();
|
||||
|
||||
return mirrorListFileInfo.Exists;
|
||||
}
|
||||
|
||||
public void Run()
|
||||
{
|
||||
if (!_settings.UsingR2() || !_options.UplaodToR2)
|
||||
{
|
||||
return;
|
||||
}
|
||||
|
||||
AnsiConsole.WriteLine();
|
||||
|
||||
var fileInfo = new FileInfo(Path.Join(Environment.CurrentDirectory, "mirrors.json"));
|
||||
|
||||
CreateMirrorList(fileInfo);
|
||||
|
||||
UploadMirrorList(fileInfo).GetAwaiter().GetResult();
|
||||
}
|
||||
}
|
||||
}
|
210
EftPatchHelper/EftPatchHelper/Tasks/UploadTasks.cs
Normal file
210
EftPatchHelper/EftPatchHelper/Tasks/UploadTasks.cs
Normal file
@ -0,0 +1,210 @@
|
||||
using EftPatchHelper.Extensions;
|
||||
using EftPatchHelper.Interfaces;
|
||||
using EftPatchHelper.Model;
|
||||
using Spectre.Console;
|
||||
using System.Security.Cryptography;
|
||||
using EftPatchHelper.Helpers;
|
||||
|
||||
namespace EftPatchHelper.Tasks
|
||||
{
|
||||
public class UploadTasks : IUploadTasks
|
||||
{
|
||||
private readonly Options _options;
|
||||
private readonly Settings _settings;
|
||||
private readonly R2Helper _r2;
|
||||
private readonly List<IFileUpload> _fileUploads = new();
|
||||
private readonly Dictionary<IFileUpload, ProgressTask> _uploadTasks = new();
|
||||
|
||||
public UploadTasks(Options options, Settings settings, R2Helper r2)
|
||||
{
|
||||
_options = options;
|
||||
_settings = settings;
|
||||
_r2 = r2;
|
||||
}
|
||||
|
||||
private static string GetFileHash(FileInfo file)
|
||||
{
|
||||
using (MD5 md5Service = MD5.Create())
|
||||
using (var sourceStream = file.OpenRead())
|
||||
{
|
||||
byte[] sourceHash = md5Service.ComputeHash(sourceStream);
|
||||
|
||||
return Convert.ToBase64String(sourceHash);
|
||||
}
|
||||
}
|
||||
|
||||
private async Task<bool> BuildUploadList()
|
||||
{
|
||||
var patcherFile = new FileInfo(_options.OutputPatchPath + ".7z");
|
||||
|
||||
if (!patcherFile.Exists)
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
AnsiConsole.WriteLine("Building mirrors list ...");
|
||||
|
||||
if(_settings.UsingGoFile() && _options.UploadToGoFile)
|
||||
{
|
||||
var gofile = new GoFileUpload(patcherFile, _settings.GoFileApiKey, _settings.GoFileFolderId);
|
||||
_fileUploads.Add(gofile);
|
||||
AnsiConsole.WriteLine("Added GoFile");
|
||||
}
|
||||
|
||||
if (_settings.UsingR2() && _options.UplaodToR2)
|
||||
{
|
||||
if (!await _r2.ClearBucketAsync())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
var r2 = new R2Upload(patcherFile, _r2);
|
||||
_fileUploads.Add(r2);
|
||||
AnsiConsole.WriteLine($"Added R2::{_r2.BucketName}");
|
||||
}
|
||||
|
||||
if (_settings.SftpUploads.Count > 0 && _options.UploadToSftpSites)
|
||||
{
|
||||
foreach (var sftpInfo in _settings.SftpUploads)
|
||||
{
|
||||
if (!sftpInfo.IsValid())
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
AnsiConsole.WriteLine($"Added SFTP: {sftpInfo.Hostname}");
|
||||
_fileUploads.Add(new SftpUpload(patcherFile, sftpInfo));
|
||||
}
|
||||
}
|
||||
|
||||
if (_settings.UsingMega() && _options.UploadToMega)
|
||||
{
|
||||
var mega = new MegaUpload(patcherFile, _settings.MegaEmail, _settings.MegaPassword);
|
||||
await mega.SetUploadFolder(_settings.MegaUploadFolder);
|
||||
_fileUploads.Add(mega);
|
||||
AnsiConsole.WriteLine("Added MEGA");
|
||||
}
|
||||
|
||||
return true;
|
||||
}
|
||||
|
||||
private void CreateHubEntrySource()
|
||||
{
|
||||
string output = $"<p>Downgrade EFT Client files from version {_options.SourceClient.Version} to {_options.TargetClient.Version}</p>\n<p><br></p>";
|
||||
|
||||
foreach (var pair in _options.MirrorList)
|
||||
{
|
||||
if (!pair.Value.AddHubEntry)
|
||||
{
|
||||
continue;
|
||||
}
|
||||
|
||||
var displayText = pair.Key;
|
||||
var link = pair.Value.Link;
|
||||
|
||||
if(link.Contains("gofile.io/download/direct/"))
|
||||
{
|
||||
// gofile direct link is only for the mirror list, the hub entry should use the normal link
|
||||
link = link.Replace("gofile.io/download/direct/", "gofile.io/download/");
|
||||
}
|
||||
|
||||
output += $"\n<p><a href=\"{link}\">{displayText}</a></p>";
|
||||
}
|
||||
|
||||
AnsiConsole.WriteLine(output);
|
||||
|
||||
var unixTimestamp = (int)DateTime.UtcNow.Subtract(DateTime.UnixEpoch).TotalSeconds;
|
||||
|
||||
string outputPath = $"{Environment.CurrentDirectory}\\hubEntry_{unixTimestamp}.txt";
|
||||
File.WriteAllText(outputPath, output);
|
||||
|
||||
if(File.Exists(outputPath))
|
||||
{
|
||||
AnsiConsole.MarkupLine($"[green]Hub Entry Source saved: {outputPath.EscapeMarkup()}[/]");
|
||||
}
|
||||
else
|
||||
{
|
||||
AnsiConsole.MarkupLine($"[red]Hub Entry Source saved failed[/]");
|
||||
}
|
||||
}
|
||||
|
||||
static string BytesToString(long byteCount)
|
||||
{
|
||||
string[] suf = { "B", "KB", "MB", "GB", "TB", "PB", "EB" };
|
||||
|
||||
if (byteCount == 0)
|
||||
{
|
||||
return "0" + suf[0];
|
||||
}
|
||||
|
||||
long bytes = Math.Abs(byteCount);
|
||||
int place = Convert.ToInt32(Math.Floor(Math.Log(bytes, 1024)));
|
||||
double num = Math.Round(bytes / Math.Pow(1024, place), 1);
|
||||
return (Math.Sign(byteCount) * num).ToString() + suf[place];
|
||||
}
|
||||
|
||||
private async Task<bool> UploadAllFiles()
|
||||
{
|
||||
if(!await BuildUploadList())
|
||||
{
|
||||
return false;
|
||||
}
|
||||
|
||||
AnsiConsole.MarkupLine($"[blue]Starting {_fileUploads[0].UploadFileInfo.Name} uploads ...[/]");
|
||||
|
||||
var succeeded = await AnsiConsole.Progress().Columns(
|
||||
new TaskDescriptionColumn() { Alignment = Justify.Left},
|
||||
new ProgressBarColumn(),
|
||||
new PercentageColumn(),
|
||||
new RemainingTimeColumn(),
|
||||
new SpinnerColumn(Spinner.Known.Dots2)
|
||||
).StartAsync<bool>(async context =>
|
||||
{
|
||||
foreach(var file in _fileUploads)
|
||||
{
|
||||
var task = context.AddTask($"[purple][[Pending]][/] {file.DisplayName} - [blue]{BytesToString(file.UploadFileInfo.Length)}[/]");
|
||||
task.IsIndeterminate = true;
|
||||
_uploadTasks.Add(file, task);
|
||||
}
|
||||
|
||||
foreach(var pair in _uploadTasks)
|
||||
{
|
||||
// set the value of the progress task object
|
||||
var progress = new System.Progress<double>((d) => pair.Value.Value = d);
|
||||
|
||||
pair.Value.IsIndeterminate = false;
|
||||
pair.Value.Description = $"{pair.Key.DisplayName} - [blue]{BytesToString(pair.Key.UploadFileInfo.Length)}[/]";
|
||||
|
||||
if(!await pair.Key.UploadAsync(progress))
|
||||
{
|
||||
AnsiConsole.MarkupLine($"[red]{pair.Key.DisplayName.EscapeMarkup()} failed[/]");
|
||||
}
|
||||
else
|
||||
{
|
||||
DownloadMirror mirror = new DownloadMirror
|
||||
{
|
||||
AddHubEntry = pair.Key.AddHubEntry,
|
||||
Link = pair.Key.GetLink(),
|
||||
Hash = GetFileHash(pair.Key.UploadFileInfo)
|
||||
};
|
||||
|
||||
_options.MirrorList.Add(pair.Key.HubEntryText, mirror);
|
||||
}
|
||||
}
|
||||
|
||||
return _options.MirrorList.Count > 0;
|
||||
});
|
||||
|
||||
return succeeded;
|
||||
}
|
||||
|
||||
public void Run()
|
||||
{
|
||||
if (!_options.UploadToGoFile && !_options.UploadToMega && !_options.UploadToSftpSites && !_options.UplaodToR2) return;
|
||||
|
||||
UploadAllFiles().GetAwaiter().GetResult().ValidateOrExit();
|
||||
|
||||
CreateHubEntrySource();
|
||||
}
|
||||
}
|
||||
}
|
32
EftPatchHelper/EftPatchHelper/settings.json
Normal file
32
EftPatchHelper/EftPatchHelper/settings.json
Normal file
@ -0,0 +1,32 @@
|
||||
{
|
||||
"targetEftVersion": "",
|
||||
"prepFolderPath": "",
|
||||
"backupFolderPath": "",
|
||||
"liveEftPath": "",
|
||||
"patcherExePath": "",
|
||||
"autoZip": true,
|
||||
"autoClose": false,
|
||||
"latestReleaseUrl": "",
|
||||
"megaEmail": "",
|
||||
"megaPassword": "",
|
||||
"megaUploadFolder": "",
|
||||
"goFileApiKey": "",
|
||||
"goFileFolderId": "",
|
||||
"r2ConnectedDomainUrl": "",
|
||||
"r2ServiceUrl": "",
|
||||
"r2BucketName": "",
|
||||
"r2AccessKeyId": "",
|
||||
"r2SecretKeyId": "",
|
||||
"sftpUploads": [
|
||||
{
|
||||
"username": "example-remove-before-using",
|
||||
"password": "password123",
|
||||
"hostKey": "ssh-ed12345 SLKDJFK3928D2LDKFJ2",
|
||||
"hostname": "sftp.slugma-ligma.com",
|
||||
"port": 12345,
|
||||
"uploadPath": "/public/patchers",
|
||||
"httpPath": "https://mirror.slugma-ligma.com/patchers",
|
||||
"allowHubEntry": true
|
||||
}
|
||||
]
|
||||
}
|
10
README.md
10
README.md
@ -1,5 +1,13 @@
|
||||
# EftPatchHelper
|
||||
|
||||
A way for me to be very lazy when making patches.
|
||||
A helper tool for automating patch generation
|
||||
|
||||
...
|
||||
|
||||
Basically, a way for me to be very lazy when making patches.
|
||||
|
||||
Figured I'd share :)
|
||||
|
||||
## Requirements
|
||||
- .net 8
|
||||
- PatchGenerator.exe (https://dev.sp-tarkov.com/waffle.lord/Patcher/releases)
|
Loading…
x
Reference in New Issue
Block a user