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); }
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); } }