public Download DownloadFile(string url, bool processAfterDownload = true, string toPlaylistID = null, bool suppressToast = false)
        {
            //prevent the same URL from going in the queue twice.
            var exists = false;

            lock (_downloads)
            {
                exists = _downloads.Any(x => x.DownloadUrl == new Uri(url));
            }

            if (exists)
            {
                var deadDl = new Download(url);
                deadDl.StatusChanged += StatusChangeHandler;
                deadDl.SuppressToast  = suppressToast;
                deadDl.SetStatus(DownloadStatus.Failed, "File is already being downloaded.");
                return(deadDl);
            }

            Download dl = new Download(url, processAfterDownload);

            dl.TargetPlaylistID = toPlaylistID;
            dl.SuppressToast    = suppressToast;
            lock (_downloads)
                _downloads.Add(dl);

            dl.StatusChanged += StatusChangeHandler;
            dl.SetStatus(DownloadStatus.NotStarted);
            return(dl);
        }
Exemple #2
0
        public void ImportFile(string filename, string mimeType, byte[] fileData)
        {
            var ext = Path.GetExtension(filename).ToLower().ToLower().TrimStart('.');

            if (ext == "bplist" || ext == "json")
            {
                try
                {
                    //oh boy a playlist!
                    BPList bplist;
                    using (MemoryStream ms = new MemoryStream(fileData))
                        using (StreamReader sr = new StreamReader(ms))
                            using (JsonTextReader tr = new JsonTextReader(sr))
                                bplist = new JsonSerializer().Deserialize <BPList>(tr);

                    if (bplist.PlaylistTitle == null || bplist.Songs == null)
                    {
                        Log.LogErr($"Playlist title is null and it's songlist is null from file {filename}.");
                        _showToast("Playlist Failed", $"{filename} did not seem to have a playlist in it.", ToastType.Error);
                        return;
                    }

                    Log.LogMsg($"Creating playlist '{bplist.PlaylistTitle}'");
                    var bspl = new BeatSaberPlaylist()
                    {
                        PlaylistID      = GetPlaylistID(filename, bplist),
                        CoverImageBytes = bplist.Image,
                        PlaylistName    = bplist.PlaylistTitle
                    };
                    var plOp = new AddOrUpdatePlaylistOp(bspl);
                    _getEngine().OpManager.QueueOp(plOp);

                    plOp.FinishedEvent.WaitOne();
                    if (plOp.Status == OpStatus.Failed)
                    {
                        Log.LogErr("Exception in ImportFile handling a bplist playlist!", plOp.Exception);
                        _showToast("Playlist Failed", $"Unable to create playlist '{bplist.PlaylistTitle}'!", ToastType.Error);
                        return;
                    }
                    else if (plOp.Status == OpStatus.Complete)
                    {
                        //SUCCESS!  except what a fail on this poorly structured if/else block
                    }
                    else
                    {
                        throw new Exception("Playlist op finished with a completely unexpected status.");
                    }

                    WebClient        client          = new WebClient();
                    var              downloads       = new List <Download>();
                    var              ops             = new ConcurrentBag <AssetOp>();
                    Debouncey <bool> configDebouncer = new Debouncey <bool>(5000, false);
                    configDebouncer.Debounced += (s, e) =>
                    {
                        _getConfig().Config = _getEngine().GetCurrentConfig();
                    };
                    foreach (var song in bplist.Songs)
                    {
                        string url = Constants.BEATSAVER_ROOT;
                        if (!string.IsNullOrWhiteSpace(song.Key))
                        {
                            url += string.Format(Constants.BEATSAVER_KEY_API, song.Key);
                        }
                        else if (!string.IsNullOrWhiteSpace(song.Hash))
                        {
                            url += string.Format(Constants.BEATSAVER_HASH_API, song.Hash);
                        }
                        else
                        {
                            Log.LogErr($"Song '{song.SongName ?? "(null)"}' in playlist '{bplist.PlaylistTitle}' has no hash or key.");
                            var dl = new Download("http://localhost", false);
                            dl.SetStatus(DownloadStatus.Failed, $"Song '{song.SongName ?? "(null)"}' in playlist '{bplist.PlaylistTitle}' has no hash or key.");
                            downloads.Add(dl);
                            continue;
                        }
                        try
                        {
                            var    bsaver      = client.DownloadString(url);
                            JToken jt          = JToken.Parse(bsaver);
                            var    downloadUrl = jt.Value <string>("downloadURL");
                            if (string.IsNullOrWhiteSpace(downloadUrl))
                            {
                                Log.LogErr($"Song '{song.SongName ?? "(null)"}' in playlist '{bplist.PlaylistTitle}' did not have a downloadURL in the response from beat saver.");
                                var dl = new Download("http://localhost", false);
                                dl.SetStatus(DownloadStatus.Failed, $"Song '{song.SongName ?? "(null)"}' in playlist '{bplist.PlaylistTitle}' did not have a downloadURL in the response from beat saver.");
                                downloads.Add(dl);
                                continue;
                            }
                            try
                            {
                                var dl = _getDownloadManager().DownloadFile(Constants.BEATSAVER_ROOT.CombineFwdSlash(downloadUrl), false);
                                dl.StatusChanged += (s, e) =>
                                {
                                    if (e.Status == DownloadStatus.Failed)
                                    {
                                        Log.LogErr($"Song '{song.SongName}' in playlist '{bplist.PlaylistTitle}' failed to download.");
                                    }
                                    else if (e.Status == DownloadStatus.Processed)
                                    {
                                        try
                                        {
                                            MemoryStream ms = new MemoryStream(dl.DownloadedData);
                                            try
                                            {
                                                var provider = new ZipFileProvider(ms, dl.DownloadedFilename, FileCacheMode.None, true, FileUtils.GetTempDirectory());
                                                try
                                                {
                                                    var op = ImportSongFile(provider, () =>
                                                    {
                                                        provider.Dispose();
                                                        ms.Dispose();
                                                    }, bspl, true);
                                                    op.OpFinished += (so, eo) =>
                                                    {
                                                        if (eo.Status == OpStatus.Complete)
                                                        {
                                                            configDebouncer.EventRaised(this, true);
                                                        }
                                                    };
                                                    ops.Add(op);
                                                }
                                                catch
                                                {
                                                    provider.Dispose();
                                                    throw;
                                                }
                                            }
                                            catch
                                            {
                                                ms.Dispose();
                                                throw;
                                            }
                                        }
                                        catch (Exception ex)
                                        {
                                            Log.LogErr($"Song '{song.SongName}' in playlist '{bplist.PlaylistTitle}' threw an exception on adding to playlist", ex);
                                        }
                                    }
                                };
                                downloads.Add(dl);
                            }
                            catch (Exception ex)
                            {
                                Log.LogErr($"Exception making secondary call to get download readirect URL for '{downloadUrl}' on beat saver!", ex);
                                var dl = new Download("http://localhost", false);
                                dl.SetStatus(DownloadStatus.Failed, $"Failed to get download information for '{downloadUrl}' from beat saver!");
                                downloads.Add(dl);
                                continue;
                            }
                        }
                        catch (Exception ex)
                        {
                            Log.LogErr($"Exception on song '{song.SongName ?? "(null)"}' in playlist '{bplist.PlaylistTitle}' getting info from beatsaver!", ex);
                            var dl = new Download("http://localhost", false);
                            dl.SetStatus(DownloadStatus.Failed, $"Failed to get information on '{song.SongName ?? "(null)"}' in playlist '{bplist.PlaylistTitle}' from beatsaver!");
                            downloads.Add(dl);
                        }
                    }

                    if (downloads.Count < 1)
                    {
                        Log.LogErr($"Every single song in playlist '{bplist.PlaylistTitle}' failed to start downloading!");
                        _showToast("Playlist Failed", $"Every song in the playlist '{bplist.PlaylistTitle}' failed to start downloading.", ToastType.Error);
                        return;
                    }
                    downloads.WaitForFinish();
                    ops.WaitForFinish();

                    var badDl      = downloads.Count(x => x.Status == DownloadStatus.Failed);
                    var goodCount  = ops.Count(x => x.Status == OpStatus.Complete);
                    var existCount = ops.Count(x => x.Status == OpStatus.Failed && x.Exception as AddSongException != null && ((AddSongException)x.Exception).FailType == AddSongFailType.SongExists);
                    var badSong    = ops.Count(x => x.Status == OpStatus.Failed) - existCount;
                    _getConfig().Config = _getEngine().GetCurrentConfig();
                    _showToast("Playlist Import Complete", $"Playlist '{bplist.PlaylistTitle}' has completed.  {goodCount} of {bplist.Songs.Count} songs succeeded.", ToastType.Success, 8);
                    // successfully downloaded, {existCount} already existed in other playlists, {badDl} failed to download, {badSong} failed to import."

                    //save playlist file for later use on QAE commit
                    var          plFileSave = _qaeConfig.PlaylistsPath.CombineFwdSlash(Path.GetFileNameWithoutExtension(filename) + ".json");
                    QueuedFileOp qfo        = new QueuedFileOp()
                    {
                        Type       = QueuedFileOperationType.WriteFile,
                        TargetPath = plFileSave,
                        SourceData = fileData
                    };
                    _getEngine().OpManager.QueueOp(qfo);
                }
                catch (Exception ex)
                {
                    Log.LogErr("Exception in ImportFile handling a bplist playlist!", ex);
                    _showToast("Playlist Failed", $"Failed to read playlist from {filename}!", ToastType.Error);
                }
            }
            else
            {
                Log.LogErr($"Unsupported file type uploaded as {filename}");
                _showToast("Unsupported File", $"The file {filename} is not a supported type.", ToastType.Error);
            }
        }