151 lines
5.0 KiB
C#
151 lines
5.0 KiB
C#
using System;
|
|
using System.IO;
|
|
using System.IO.Compression;
|
|
using System.Net.Http;
|
|
using System.Net.Http.Headers;
|
|
using System.Threading;
|
|
using System.Threading.Tasks;
|
|
using Newtonsoft.Json.Linq;
|
|
using Pf2e.Scrapper.Helpers;
|
|
|
|
namespace Pf2e.Scrapper.Importers.Repositories;
|
|
|
|
public abstract class AbstractGitHubRepository(AbstractImporter importer)
|
|
: AbstractImporterRepository(importer)
|
|
{
|
|
public abstract string Repository { get; }
|
|
public abstract string AssetName { get; }
|
|
|
|
public override void Update(ProcessProgress progress)
|
|
{
|
|
ReleaseInformation releaseInformation = GetReleaseInformation();
|
|
string? currentVersion = GetCurrentVersion();
|
|
|
|
if (currentVersion == releaseInformation.TagName)
|
|
{
|
|
progress.Local.Complete();
|
|
progress.Information(
|
|
$"Данные {Repository} актуальны, текущая версия {currentVersion}."
|
|
);
|
|
return;
|
|
}
|
|
|
|
progress.Information(
|
|
$"Данные {Repository} устарели, обновляем {RepositoryDirPath} до версии {releaseInformation.TagName}..."
|
|
);
|
|
|
|
string assetFile = DownloadAsset(progress, releaseInformation);
|
|
|
|
ExtractAsset(assetFile, RepositoryDirPath, progress);
|
|
|
|
File.WriteAllText(
|
|
Path.Combine(RepositoryDirPath, "version.txt"),
|
|
releaseInformation.TagName
|
|
);
|
|
}
|
|
|
|
private ReleaseInformation GetReleaseInformation()
|
|
{
|
|
string releasesUrl = $"https://api.github.com/repos/{Repository}/releases/latest";
|
|
using HttpClient client = new();
|
|
client.DefaultRequestHeaders.UserAgent.Add(
|
|
new ProductInfoHeaderValue("Pf2eDataScrapper", "1.0")
|
|
);
|
|
string json = client.GetStringAsync(releasesUrl).Result;
|
|
JObject jObject = JObject.Parse(json);
|
|
|
|
return new()
|
|
{
|
|
TagName = jObject.SelectToken("tag_name")!.ToObject<string>()!,
|
|
DownloadUrl = jObject
|
|
.SelectToken("assets[?(@.name == '" + AssetName + "')].browser_download_url")!
|
|
.ToObject<string>()!,
|
|
Size = jObject
|
|
.SelectToken("assets[?(@.name == '" + AssetName + "')].size")!
|
|
.ToObject<int>()!,
|
|
};
|
|
}
|
|
|
|
private string? GetCurrentVersion()
|
|
{
|
|
string versionFilePath = Path.Combine(RepositoryDirPath, "version.txt");
|
|
if (File.Exists(versionFilePath))
|
|
{
|
|
return File.ReadAllText(versionFilePath).Trim();
|
|
}
|
|
return null;
|
|
}
|
|
|
|
private string DownloadAsset(ProcessProgress progress, ReleaseInformation releaseInformation)
|
|
{
|
|
string fileName = System.IO.Path.GetTempPath() + Guid.NewGuid().ToString() + ".zip";
|
|
using var fileStream = new FileStream(fileName, FileMode.Create, FileAccess.Write);
|
|
|
|
progress.Local.Reset(releaseInformation.Size);
|
|
progress.Local.Start(
|
|
$"[1/2] Загрузка {releaseInformation.TagName} ({releaseInformation.Size / 1024 / 1024} МБ)..."
|
|
);
|
|
|
|
Task.Run(async () =>
|
|
{
|
|
using HttpClient client = new();
|
|
using var response = await client.GetAsync(
|
|
releaseInformation.DownloadUrl,
|
|
HttpCompletionOption.ResponseHeadersRead
|
|
);
|
|
|
|
using var download = await response.Content.ReadAsStreamAsync();
|
|
|
|
var buffer = new byte[81920];
|
|
int bytesRead;
|
|
var t = CancellationToken.None;
|
|
|
|
while ((bytesRead = await download.ReadAsync(buffer, t).ConfigureAwait(false)) != 0)
|
|
{
|
|
await fileStream
|
|
.WriteAsync(buffer.AsMemory(0, bytesRead), t)
|
|
.ConfigureAwait(false);
|
|
progress.Local.Current += bytesRead;
|
|
}
|
|
})
|
|
.Wait();
|
|
|
|
progress.Local.Complete();
|
|
return fileName;
|
|
}
|
|
|
|
private void ExtractAsset(string assetFile, string targetDir, ProcessProgress progress)
|
|
{
|
|
using var zip = ZipFile.OpenRead(assetFile);
|
|
|
|
progress.Local.Reset(zip.Entries.Count);
|
|
progress.Local.Start("[2/2] Распаковка архива...");
|
|
|
|
foreach (var entry in zip.Entries)
|
|
{
|
|
if (string.IsNullOrEmpty(entry.Name))
|
|
continue; // Skip directories
|
|
|
|
string destinationPath = Path.Combine(targetDir, entry.FullName);
|
|
|
|
string directoryPath = Path.GetDirectoryName(destinationPath)!;
|
|
if (!Directory.Exists(directoryPath))
|
|
{
|
|
Directory.CreateDirectory(directoryPath);
|
|
}
|
|
|
|
entry.ExtractToFile(destinationPath, true);
|
|
progress.Local.Current++;
|
|
}
|
|
|
|
progress.Local.Complete();
|
|
}
|
|
|
|
private class ReleaseInformation
|
|
{
|
|
public string TagName { get; init; } = null!;
|
|
public string DownloadUrl { get; init; } = null!;
|
|
public int Size { get; init; } = 0;
|
|
}
|
|
}
|