public Task <DownloadData> QueueDownload(UriString url, NPath targetDirectory) { var destinationFile = targetDirectory.Combine(url.Filename); result = new DownloadData(url, destinationFile); Action <ITask <NPath>, NPath, bool, Exception> verifyDownload = (t, res, success, ex) => { isSuccessful &= success; if (!success) { exception = ex; } if (!isSuccessful) { DownloadFailed(result, exception); } else { DownloadComplete(result); } }; var fileDownload = DownloadFile(url, targetDirectory, result, verifyDownload); fileDownload.OnStart += _ => DownloadStart?.Invoke(result); queuedTasks.Add(fileDownload); return(aggregateDownloads.Task); }
public Task <DownloadData> QueueDownload(UriString url, UriString md5Url, NPath targetDirectory) { var destinationFile = targetDirectory.Combine(url.Filename); var destinationMd5 = targetDirectory.Combine(md5Url.Filename); result = new DownloadData(url, destinationFile); Action <ITask <NPath>, NPath, bool, Exception> verifyDownload = (t, res, success, ex) => { var count = Interlocked.Increment(ref finishedTaskCount); isSuccessful &= success; if (!success) { exception = ex; } if (count == queuedTasks.Count) { if (!isSuccessful) { DownloadFailed(result, exception); } else { if (!Utils.VerifyFileIntegrity(destinationFile, destinationMd5)) { destinationMd5.Delete(); destinationFile.Delete(); DownloadFailed(result, new DownloadException($"Verification of {url} failed")); } else { DownloadComplete(result); } } } }; var md5Exists = destinationMd5.FileExists(); var fileExists = destinationFile.FileExists(); if (!md5Exists) { var md5Download = DownloadFile(md5Url, targetDirectory, result, verifyDownload); md5Download.OnStart += _ => DownloadStart?.Invoke(result); queuedTasks.Add(md5Download); } if (!fileExists) { var fileDownload = DownloadFile(url, targetDirectory, result, verifyDownload); if (md5Exists) // only invoke DownloadStart if it hasn't been invoked before in the md5 download { fileDownload.OnStart += _ => DownloadStart?.Invoke(result); } queuedTasks.Add(fileDownload); } return(aggregateDownloads.Task); }
internal void StartDownload(IEnumerable <DependencyObject> download, DownloadStart downloadStart = null, DownloadProgress downloadProgress = null, DownloadFailed downloadFail = null, DownloadFinish downloadFinish = null, InstallFailed installFail = null, InstallFinish installFinish = null) { foreach (var item in download) { StartCoroutine(UpdateModCoroutine(item, downloadStart, downloadProgress, downloadFail, downloadFinish, installFail, installFinish)); } }
public static void OnDownloadStart(object sender, DownloadEventArgs ev) => DownloadStart?.Invoke(sender, ev);
private void OnDownloadStart(DownloadStartEventArgs e) { try { DownloadStart?.Invoke(this, e); } catch { } }
private static IEnumerator UpdateModCoroutine(DependencyObject item, DownloadStart downloadStart, DownloadProgress progress, DownloadFailed dlFail, DownloadFinish finish, InstallFailed installFail, InstallFinish installFinish) { // (3.2) Logger.updater.Debug($"Release: {BeatSaber.ReleaseType}"); var mod = new Ref <ApiEndpoint.Mod>(null); yield return(GetModInfo(item.Name, item.ResolvedVersion.ToString(), mod)); try { mod.Verify(); } catch (Exception e) { Logger.updater.Error($"Error occurred while trying to get information for {item}"); Logger.updater.Error(e); yield break; } var releaseName = BeatSaber.ReleaseType == BeatSaber.Release.Steam ? ApiEndpoint.Mod.DownloadsObject.TypeSteam : ApiEndpoint.Mod.DownloadsObject.TypeOculus; var platformFile = mod.Value.Downloads.First(f => f.Type == ApiEndpoint.Mod.DownloadsObject.TypeUniversal || f.Type == releaseName); string url = ApiEndpoint.BeatModBase + platformFile.Path; Logger.updater.Debug($"URL = {url}"); const int maxTries = 3; int tries = maxTries; while (tries > 0) { if (tries-- != maxTries) { Logger.updater.Debug("Re-trying download..."); } using (var stream = new MemoryStream()) using (var request = UnityWebRequest.Get(url)) using (var taskTokenSource = new CancellationTokenSource()) { var dlh = new StreamDownloadHandler(stream, (int i1, int i2, double d) => progress?.Invoke(item, i1, i2, d)); request.downloadHandler = dlh; downloadStart?.Invoke(item); Logger.updater.Debug("Sending request"); //Logger.updater.Debug(request?.downloadHandler?.ToString() ?? "DLH==NULL"); yield return(request.SendWebRequest()); Logger.updater.Debug("Download finished"); if (request.isNetworkError) { Logger.updater.Error("Network error while trying to update mod"); Logger.updater.Error(request.error); dlFail?.Invoke(item, request.error); taskTokenSource.Cancel(); continue; } if (request.isHttpError) { Logger.updater.Error("Server returned an error code while trying to update mod"); Logger.updater.Error(request.error); dlFail?.Invoke(item, request.error); taskTokenSource.Cancel(); continue; } finish?.Invoke(item); stream.Seek(0, SeekOrigin.Begin); // reset to beginning var downloadTask = Task.Run(() => { // use slightly more multi threaded approach than co-routines // ReSharper disable once AccessToDisposedClosure ExtractPluginAsync(stream, item, platformFile); }, taskTokenSource.Token); while (!(downloadTask.IsCompleted || downloadTask.IsCanceled || downloadTask.IsFaulted)) { yield return(null); // pause co-routine until task is done } if (downloadTask.IsFaulted) { if (downloadTask.Exception != null && downloadTask.Exception.InnerExceptions.Any(e => e is BeatmodsInterceptException)) { // any exception is an intercept exception Logger.updater.Error($"BeatMods did not return expected data for {item.Name}"); } Logger.updater.Error($"Error downloading mod {item.Name}"); Logger.updater.Error(downloadTask.Exception); installFail?.Invoke(item, downloadTask.Exception); continue; } break; } } if (tries == 0) { Logger.updater.Warn($"Plugin download failed {maxTries} times, not re-trying"); installFinish?.Invoke(item, true); } else { Logger.updater.Debug("Download complete"); installFinish?.Invoke(item, false); } }
public Task <DownloadData> QueueDownload(UriString url, UriString md5Url, NPath targetDirectory) { var destinationFile = targetDirectory.Combine(url.Filename); var destinationMd5 = targetDirectory.Combine(md5Url.Filename); var result = new DownloadData(url, destinationFile); Action <ITask <NPath>, NPath, bool, Exception> verifyDownload = (t, res, success, ex) => { var count = Interlocked.Increment(ref finishedTaskCount); isSuccessful &= success; if (!success) { exception = ex; } if (count == queuedTasks.Count) { if (!isSuccessful) { DownloadFailed(result, exception); } else { if (!Utils.VerifyFileIntegrity(destinationFile, destinationMd5)) { destinationMd5.Delete(); destinationFile.Delete(); DownloadFailed(result, new DownloadException($"Verification of {url} failed")); } else { DownloadComplete(result); } } } }; var md5Exists = destinationMd5.FileExists(); var fileExists = destinationFile.FileExists(); if (!md5Exists) { destinationMd5.DeleteIfExists(); var md5Download = new DownloadTask(cancellationToken, fs, md5Url, targetDirectory) .Catch(e => DownloadFailed(result, e)); md5Download.OnEnd += verifyDownload; queuedTasks.Add(md5Download); } if (!fileExists) { var fileDownload = new DownloadTask(cancellationToken, fs, url, targetDirectory) .Catch(e => DownloadFailed(result, e)); fileDownload.OnStart += _ => DownloadStart?.Invoke(result); fileDownload.OnEnd += verifyDownload; queuedTasks.Add(fileDownload); } if (fileExists && md5Exists) { var verification = new FuncTask <NPath>(cancellationToken, () => destinationFile); verification.OnEnd += verifyDownload; queuedTasks.Add(verification); } return(aggregateDownloads.Task); }
public void ReceiveSignal(DownloadStart message) => _logger.Info($"[{nameof(StreamReceiver)}] Init download");