Пример #1
0
        public void DeleteMod(ModDefinition def)
        {
            if (_modConfig.InstalledModIDs.Contains(def.ID))
            {
                var ops = GetUninstallModOps(def);
                ops.ForEach(x => _getEngine().OpManager.QueueOp(x));
                ops.WaitForFinish();
                if (ops.Any(x => x.Status == OpStatus.Failed))
                {
                    string err = "";
                    foreach (var failed in ops.Where(x => x.Status == OpStatus.Failed))
                    {
                        err += failed.GetType().Name + " failed! " + failed.Exception ?? " \n";
                    }
                    throw new Exception("Uninstall of mod failed, cannot delete it! " + err);
                }
            }
            var defPath = _config.ModsSourcePath.CombineFwdSlash(def.ID);

            if (!_config.RootFileProvider.DirectoryExists(defPath))
            {
                Log.LogErr($"Tried to delete mod ID {def.ID} but it doesn't seem to exist at {defPath}.  Going to count it as already uninstalled.");
                return;
            }

            var qfo = new QueuedFileOp()
            {
                Tag = def.id, Type = QueuedFileOperationType.DeleteFolder, TargetPath = defPath
            };

            _getEngine().QueuedFileOperations.Add(qfo);
            _deletedModIDs.Add(def.ID);
            ResetCache();
        }
Пример #2
0
 public List <AssetOp> GetInstallOps(ModContext context)
 {
     if (!context.Config.RootFileProvider.FileExists(context.ModPath.CombineFwdSlash(InstallLibraryFile)))
     {
         throw new Exception($"HookMod installation failed because the library file {InstallLibraryFile} could not be found.");
     }
     if (context.Config.ModLibsFileProvider.FileExists(InstallLibraryFile))
     {
         Log.LogMsg($"HookMod library file {InstallLibraryFile} already exists, it will be overwritten.");
     }
     try
     {
         var bytes = context.Config.RootFileProvider.Read(context.ModPath.CombineFwdSlash(InstallLibraryFile));
         var op    = new QueuedFileOp()
         {
             Type = QueuedFileOperationType.WriteFile, TargetPath = InstallLibraryFile, SourceData = bytes, ProviderType = QueuedFileOperationProviderType.ModLibs
         };
         return(new List <AssetOp>()
         {
             op
         });
     }
     catch (Exception ex)
     {
         Log.LogErr($"HookMod install failed to queue install mod to {InstallLibraryFile}.", ex);
         throw;
     }
 }
Пример #3
0
        public override List <AssetOp> GetInstallOps(ModContext context)
        {
            Log.LogMsg($"Installing FileCopy component");
            if (string.IsNullOrEmpty(SourceFileName))
            {
                throw new InvalidOperationException("FileCopy is being installed, but has no filename!");
            }
            if (string.IsNullOrEmpty(TargetRootedPathAndFileName))
            {
                throw new InvalidOperationException("FileCopy is being installed, but has no root filesystem target path!");
            }

            if (!context.Config.RootFileProvider.FileExists(context.ModPath.CombineFwdSlash(SourceFileName)))
            {
                throw new Exception($"FileCopy installation failed because the file {SourceFileName} could not be found.");
            }
            if (System.IO.File.Exists(TargetRootedPathAndFileName))
            {
                Log.LogMsg($"FileCopy target file {TargetRootedPathAndFileName} already exists, it will be overwritten.");
            }
            try
            {
                var bytes = context.Config.RootFileProvider.Read(context.ModPath.CombineFwdSlash(SourceFileName));
                var op    = new QueuedFileOp()
                {
                    Type = QueuedFileOperationType.WriteFile, TargetPath = TargetRootedPathAndFileName, SourceData = bytes, ProviderType = QueuedFileOperationProviderType.FileSystemRoot
                };
                return(new List <AssetOp>()
                {
                    op
                });
            }
            catch (Exception ex)
            {
                Log.LogErr($"FileCopy install failed to queue install mod to {TargetRootedPathAndFileName}.", ex);
                throw;
            }
        }
Пример #4
0
 public List <AssetOp> GetUninstallOps(ModContext context)
 {
     if (!context.Config.ModLibsFileProvider.FileExists(RemoveLibraryFile))
     {
         Log.LogErr($"Tried uninstalling HookMod library {RemoveLibraryFile} but it did not exist.");
         return(new List <AssetOp>());
     }
     try
     {
         var op = new QueuedFileOp()
         {
             ProviderType = QueuedFileOperationProviderType.ModLibs, TargetPath = RemoveLibraryFile, Type = QueuedFileOperationType.DeleteFile
         };
         return(new List <AssetOp>()
         {
             op
         });
     }
     catch (Exception ex)
     {
         Log.LogErr($"Uninstall HookMod failed to queue delete file {RemoveLibraryFile}!", ex);
         throw;
     }
 }
Пример #5
0
        public override List <AssetOp> GetUninstallOps(ModContext context)
        {
            if (string.IsNullOrWhiteSpace(TargetRootedPathAndFileName))
            {
                return(new List <AssetOp>());
            }

            try
            {
                var op = new QueuedFileOp()
                {
                    ProviderType = QueuedFileOperationProviderType.FileSystemRoot, TargetPath = TargetRootedPathAndFileName, Type = QueuedFileOperationType.DeleteFile
                };
                return(new List <AssetOp>()
                {
                    op
                });
            }
            catch (Exception ex)
            {
                Log.LogErr($"Uninstall HookMod failed to queue delete file {TargetRootedPathAndFileName}!", ex);
                throw;
            }
        }
Пример #6
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);
            }
        }