using System; using System.IO; using System.IO.Compression; using System.Linq; using System.Threading.Tasks; using Wabbajack.Common; using Wabbajack.Common.Serialization.Json; using Wabbajack.Lib.AuthorApi; using Wabbajack.Lib.Downloaders.UrlDownloaders; using Wabbajack.Lib.Exceptions; using Wabbajack.Lib.Validation; namespace Wabbajack.Lib.Downloaders { public class WabbajackCDNDownloader : IDownloader { public async Task GetDownloaderState(dynamic archiveINI, bool quickMode = false) { var url = (Uri)DownloaderUtils.GetDirectURL(archiveINI); return url == null ? null : StateFromUrl(url); } public async Task Prepare() { } public static AbstractDownloadState? StateFromUrl(Uri url) { if (url.Host == "wabbajacktest.b-cdn.net" || url.Host == "wabbajack.b-cdn.net") { return new State(url); } return null; } [JsonName("WabbajackCDNDownloader+State")] public class State : AbstractDownloadState { public Uri Url { get; set; } public State(Uri url) { Url = url; } public override object[] PrimaryKey => new object[] {Url}; public override bool IsWhitelisted(ServerWhitelist whitelist) { return true; } public override async Task Download(Archive a, AbsolutePath destination) { var definition = await GetDefinition(); await using var fs = destination.Create(); var client = new Common.Http.Client(); await definition.Parts.DoProgress($"Downloading {a.Name}", async part => { fs.Position = part.Offset; using var response = await client.GetAsync($"{Url}/parts/{part.Index}"); if (!response.IsSuccessStatusCode) throw new HttpException((int)response.StatusCode, response.ReasonPhrase); await response.Content.CopyToAsync(fs); }); return true; } public override async Task Verify(Archive archive) { var definition = await GetDefinition(); return true; } private async Task GetDefinition() { var client = new Common.Http.Client(); using var data = await client.GetAsync(Url + "/definition.json.gz"); await using var gz = new GZipStream(await data.Content.ReadAsStreamAsync(), CompressionMode.Decompress); return gz.FromJson(); } public override IDownloader GetDownloader() { return DownloadDispatcher.GetInstance(); } public override string? GetManifestURL(Archive a) { return Url.ToString(); } public override string[] GetMetaIni() { return new[] {"[General]", $"directURL={Url}"}; } } } }