Example #1
0
            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);
            }
Example #2
0
            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);
            }
Example #3
0
 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));
     }
 }
Example #4
0
 public static void OnDownloadStart(object sender, DownloadEventArgs ev) => DownloadStart?.Invoke(sender, ev);
Example #5
0
 private void OnDownloadStart(DownloadStartEventArgs e)
 {
     try { DownloadStart?.Invoke(this, e); } catch { }
 }
Example #6
0
        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);
            }
        }
Example #7
0
            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);
            }
Example #8
0
 public void ReceiveSignal(DownloadStart message) =>
 _logger.Info($"[{nameof(StreamReceiver)}] Init download");