diff --git a/.gitignore b/.gitignore index da134307..ad436745 100644 --- a/.gitignore +++ b/.gitignore @@ -27,3 +27,6 @@ npm-debug.log.* *.css.d.ts *.sass.d.ts *.scss.d.ts + +# externals +externals/bs-admin-start/target/* diff --git a/assets/scripts/start_beat_saber_admin.exe b/assets/scripts/start_beat_saber_admin.exe new file mode 100644 index 00000000..672a78e8 Binary files /dev/null and b/assets/scripts/start_beat_saber_admin.exe differ diff --git a/externals/bs-admin-start/.cargo/config.toml b/externals/bs-admin-start/.cargo/config.toml new file mode 100644 index 00000000..ac2b23f8 --- /dev/null +++ b/externals/bs-admin-start/.cargo/config.toml @@ -0,0 +1,2 @@ +[target.x86_64-pc-windows-msvc] +rustflags = ["-C", "target-feature=+crt-static"] diff --git a/externals/bs-admin-start/Cargo.lock b/externals/bs-admin-start/Cargo.lock new file mode 100644 index 00000000..f15d8279 --- /dev/null +++ b/externals/bs-admin-start/Cargo.lock @@ -0,0 +1,83 @@ +# This file is automatically @generated by Cargo. +# It is not intended for manual editing. +version = 3 + +[[package]] +name = "proc-macro2" +version = "1.0.76" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "95fc56cda0b5c3325f5fbbd7ff9fda9e02bb00bb3dac51252d2f1bfa1cb8cc8c" +dependencies = [ + "unicode-ident", +] + +[[package]] +name = "quote" +version = "1.0.35" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "291ec9ab5efd934aaf503a6466c5d5251535d108ee747472c3977cc5acc868ef" +dependencies = [ + "proc-macro2", +] + +[[package]] +name = "serde" +version = "1.0.195" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "63261df402c67811e9ac6def069e4786148c4563f4b50fd4bf30aa370d626b02" +dependencies = [ + "serde_derive", +] + +[[package]] +name = "serde_derive" +version = "1.0.195" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "46fe8f8603d81ba86327b23a2e9cdf49e1255fb94a4c5f297f6ee0547178ea2c" +dependencies = [ + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "start_beat_saber_admin" +version = "0.1.0" +dependencies = [ + "winres", +] + +[[package]] +name = "syn" +version = "2.0.48" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "0f3531638e407dfc0814761abb7c00a5b54992b849452a0646b7f65c9f770f3f" +dependencies = [ + "proc-macro2", + "quote", + "unicode-ident", +] + +[[package]] +name = "toml" +version = "0.5.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "f4f7f0dd8d50a853a531c426359045b1998f04219d88799810762cd4ad314234" +dependencies = [ + "serde", +] + +[[package]] +name = "unicode-ident" +version = "1.0.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "3354b9ac3fae1ff6755cb6db53683adb661634f67557942dea4facebec0fee4b" + +[[package]] +name = "winres" +version = "0.1.12" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b68db261ef59e9e52806f688020631e987592bd83619edccda9c47d42cde4f6c" +dependencies = [ + "toml", +] diff --git a/externals/bs-admin-start/Cargo.toml b/externals/bs-admin-start/Cargo.toml new file mode 100644 index 00000000..118f1b32 --- /dev/null +++ b/externals/bs-admin-start/Cargo.toml @@ -0,0 +1,18 @@ +[package] +name = "start_beat_saber_admin" +version = "0.1.0" +edition = "2021" +build = "build.rs" + +[build-dependencies] +winres = "0.1.12" + +[profile.release] +codegen-units = 1 +lto = true +opt-level = "z" + +[package.metadata.winres] +FileDescription = "Start Beat Saber as Admin" +LegalCopyright = "Copyright © 2024 Zagrios" +CompanyName = "Zagrios" diff --git a/externals/bs-admin-start/build.rs b/externals/bs-admin-start/build.rs new file mode 100644 index 00000000..374f1355 --- /dev/null +++ b/externals/bs-admin-start/build.rs @@ -0,0 +1,20 @@ +extern crate winres; + +fn main() { + if cfg!(target_os = "windows") { + let mut res = winres::WindowsResource::new(); + res.set_manifest(r#" + + + + + + + + + + "#); + res.set_icon("./icon.ico"); + res.compile().unwrap(); + } +} diff --git a/externals/bs-admin-start/icon.ico b/externals/bs-admin-start/icon.ico new file mode 100644 index 00000000..660923e2 Binary files /dev/null and b/externals/bs-admin-start/icon.ico differ diff --git a/externals/bs-admin-start/src/main.rs b/externals/bs-admin-start/src/main.rs new file mode 100644 index 00000000..18b1dbb5 --- /dev/null +++ b/externals/bs-admin-start/src/main.rs @@ -0,0 +1,17 @@ + +use std::{process::Command, path::Path}; + +fn main() { + let args: Vec = std::env::args().collect(); + + let mut command = Command::new(args.get(1).unwrap()); + command.current_dir(Path::new(args.get(1).unwrap()).parent().unwrap()); + + for arg in args.iter().skip(1) { + command.arg(arg); + } + + command.env("SteamAppId", "620980"); + + let _ = command.spawn(); +} diff --git a/package-lock.json b/package-lock.json index 8fda678d..0305a3a8 100644 --- a/package-lock.json +++ b/package-lock.json @@ -24,6 +24,7 @@ "framer-motion": "^10.16.16", "fs-extra": "^11.2.0", "history": "^5.3.0", + "is-elevated": "^3.0.0", "jszip": "^3.10.1", "md5-file": "^5.0.0", "node-abi": "^3.47.0", @@ -7047,7 +7048,6 @@ "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, "dependencies": { "once": "^1.4.0" } @@ -10291,6 +10291,125 @@ "node": ">= 10" } }, + "node_modules/is-admin": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-admin/-/is-admin-3.0.0.tgz", + "integrity": "sha512-wOa3CXFJAu8BZ2BDtG9xYOOrsq6oiSvc2jFPy4X/HINx5bmJUcW8e+apItVbU2E7GIfBVaFVO7Zit4oAWtTJcw==", + "dependencies": { + "execa": "^1.0.0" + }, + "engines": { + "node": ">=8" + } + }, + "node_modules/is-admin/node_modules/cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "dependencies": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + }, + "engines": { + "node": ">=4.8" + } + }, + "node_modules/is-admin/node_modules/execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "dependencies": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/is-admin/node_modules/get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "dependencies": { + "pump": "^3.0.0" + }, + "engines": { + "node": ">=6" + } + }, + "node_modules/is-admin/node_modules/is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-admin/node_modules/npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==", + "dependencies": { + "path-key": "^2.0.0" + }, + "engines": { + "node": ">=4" + } + }, + "node_modules/is-admin/node_modules/path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==", + "engines": { + "node": ">=4" + } + }, + "node_modules/is-admin/node_modules/semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==", + "bin": { + "semver": "bin/semver" + } + }, + "node_modules/is-admin/node_modules/shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", + "dependencies": { + "shebang-regex": "^1.0.0" + }, + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-admin/node_modules/shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==", + "engines": { + "node": ">=0.10.0" + } + }, + "node_modules/is-admin/node_modules/which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "dependencies": { + "isexe": "^2.0.0" + }, + "bin": { + "which": "bin/which" + } + }, "node_modules/is-arguments": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", @@ -10431,6 +10550,18 @@ "url": "https://github.com/sponsors/sindresorhus" } }, + "node_modules/is-elevated": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-elevated/-/is-elevated-3.0.0.tgz", + "integrity": "sha512-wjcp6RkouU9jpg55zERl+BglvV5j4jx5c/EMvQ+d12j/+nIEenNWPu+qc0tCg3JkLodbKZMg1qhJzEwG4qjclg==", + "dependencies": { + "is-admin": "^3.0.0", + "is-root": "^2.1.0" + }, + "engines": { + "node": ">=8" + } + }, "node_modules/is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -10595,6 +10726,14 @@ "url": "https://github.com/sponsors/ljharb" } }, + "node_modules/is-root": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-root/-/is-root-2.1.0.tgz", + "integrity": "sha512-AGOriNp96vNBd3HtU+RzFEc75FfR5ymiYv8E553I71SCeXBiMsVDUtdio1OEFvrPyLIQ9tVR5RxXIFe5PUFjMg==", + "engines": { + "node": ">=6" + } + }, "node_modules/is-set": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", @@ -10760,8 +10899,7 @@ "node_modules/isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" }, "node_modules/isobject": { "version": "3.0.1", @@ -13572,6 +13710,11 @@ "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "dev": true }, + "node_modules/nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==" + }, "node_modules/no-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", @@ -14080,6 +14223,14 @@ "node": ">=8" } }, + "node_modules/p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==", + "engines": { + "node": ">=4" + } + }, "node_modules/p-limit": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", @@ -15389,7 +15540,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, "dependencies": { "end-of-stream": "^1.1.0", "once": "^1.3.1" @@ -16629,8 +16779,7 @@ "node_modules/signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" }, "node_modules/simple-swizzle": { "version": "0.2.2", @@ -17091,6 +17240,14 @@ "node": ">=4" } }, + "node_modules/strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==", + "engines": { + "node": ">=0.10.0" + } + }, "node_modules/strip-final-newline": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", @@ -24610,7 +24767,6 @@ "version": "1.4.4", "resolved": "https://registry.npmjs.org/end-of-stream/-/end-of-stream-1.4.4.tgz", "integrity": "sha512-+uw1inIHVPQoaVuHzRyXd21icM+cnt4CzD5rW+NC1wjOUSTOs+Te7FOv7AhN7vS9x/oIyhLP5PR1H+phQAHu5Q==", - "dev": true, "requires": { "once": "^1.4.0" } @@ -26978,6 +27134,94 @@ "integrity": "sha512-1qTgH9NG+IIJ4yfKs2e6Pp1bZg8wbDbKHT21HrLIeYBTRLgMYKnMTPAuI3Lcs61nfx5h1xlXnbJtH1kX5/d/ng==", "dev": true }, + "is-admin": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-admin/-/is-admin-3.0.0.tgz", + "integrity": "sha512-wOa3CXFJAu8BZ2BDtG9xYOOrsq6oiSvc2jFPy4X/HINx5bmJUcW8e+apItVbU2E7GIfBVaFVO7Zit4oAWtTJcw==", + "requires": { + "execa": "^1.0.0" + }, + "dependencies": { + "cross-spawn": { + "version": "6.0.5", + "resolved": "https://registry.npmjs.org/cross-spawn/-/cross-spawn-6.0.5.tgz", + "integrity": "sha512-eTVLrBSt7fjbDygz805pMnstIs2VTBNkRm0qxZd+M7A5XDdxVRWO5MxGBXZhjY4cqLYLdtrGqRf8mBPmzwSpWQ==", + "requires": { + "nice-try": "^1.0.4", + "path-key": "^2.0.1", + "semver": "^5.5.0", + "shebang-command": "^1.2.0", + "which": "^1.2.9" + } + }, + "execa": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/execa/-/execa-1.0.0.tgz", + "integrity": "sha512-adbxcyWV46qiHyvSp50TKt05tB4tK3HcmF7/nxfAdhnox83seTDbwnaqKO4sXRy7roHAIFqJP/Rw/AuEbX61LA==", + "requires": { + "cross-spawn": "^6.0.0", + "get-stream": "^4.0.0", + "is-stream": "^1.1.0", + "npm-run-path": "^2.0.0", + "p-finally": "^1.0.0", + "signal-exit": "^3.0.0", + "strip-eof": "^1.0.0" + } + }, + "get-stream": { + "version": "4.1.0", + "resolved": "https://registry.npmjs.org/get-stream/-/get-stream-4.1.0.tgz", + "integrity": "sha512-GMat4EJ5161kIy2HevLlr4luNjBgvmj413KaQA7jt4V8B4RDsfpHk7WQ9GVqfYyyx8OS/L66Kox+rJRNklLK7w==", + "requires": { + "pump": "^3.0.0" + } + }, + "is-stream": { + "version": "1.1.0", + "resolved": "https://registry.npmjs.org/is-stream/-/is-stream-1.1.0.tgz", + "integrity": "sha512-uQPm8kcs47jx38atAcWTVxyltQYoPT68y9aWYdV6yWXSyW8mzSat0TL6CiWdZeCdF3KrAvpVtnHbTv4RN+rqdQ==" + }, + "npm-run-path": { + "version": "2.0.2", + "resolved": "https://registry.npmjs.org/npm-run-path/-/npm-run-path-2.0.2.tgz", + "integrity": "sha512-lJxZYlT4DW/bRUtFh1MQIWqmLwQfAxnqWG4HhEdjMlkrJYnJn0Jrr2u3mgxqaWsdiBc76TYkTG/mhrnYTuzfHw==", + "requires": { + "path-key": "^2.0.0" + } + }, + "path-key": { + "version": "2.0.1", + "resolved": "https://registry.npmjs.org/path-key/-/path-key-2.0.1.tgz", + "integrity": "sha512-fEHGKCSmUSDPv4uoj8AlD+joPlq3peND+HRYyxFz4KPw4z926S/b8rIuFs2FYJg3BwsxJf6A9/3eIdLaYC+9Dw==" + }, + "semver": { + "version": "5.7.2", + "resolved": "https://registry.npmjs.org/semver/-/semver-5.7.2.tgz", + "integrity": "sha512-cBznnQ9KjJqU67B52RMC65CMarK2600WFnbkcaiwWq3xy/5haFJlshgnpjovMVJ+Hff49d8GEn0b87C5pDQ10g==" + }, + "shebang-command": { + "version": "1.2.0", + "resolved": "https://registry.npmjs.org/shebang-command/-/shebang-command-1.2.0.tgz", + "integrity": "sha512-EV3L1+UQWGor21OmnvojK36mhg+TyIKDh3iFBKBohr5xeXIhNBcx8oWdgkTEEQ+BEFFYdLRuqMfd5L84N1V5Vg==", + "requires": { + "shebang-regex": "^1.0.0" + } + }, + "shebang-regex": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/shebang-regex/-/shebang-regex-1.0.0.tgz", + "integrity": "sha512-wpoSFAxys6b2a2wHZ1XpDSgD7N9iVjg29Ph9uV/uaP9Ex/KXlkTZTeddxDPSYQpgvzKLGJke2UU0AzoGCjNIvQ==" + }, + "which": { + "version": "1.3.1", + "resolved": "https://registry.npmjs.org/which/-/which-1.3.1.tgz", + "integrity": "sha512-HxJdYWq1MTIQbJ3nw0cqssHoTNU267KlrDuGZ1WYlxDStUtKUhOaJmh112/TZmHxxUfuJqPXSOm7tDyas0OSIQ==", + "requires": { + "isexe": "^2.0.0" + } + } + } + }, "is-arguments": { "version": "1.1.1", "resolved": "https://registry.npmjs.org/is-arguments/-/is-arguments-1.1.1.tgz", @@ -27073,6 +27317,15 @@ "integrity": "sha512-F+i2BKsFrH66iaUFc0woD8sLy8getkwTwtOBjvs56Cx4CgJDeKQeqfz8wAYiSb8JOprWhHH5p77PbmYCvvUuXQ==", "dev": true }, + "is-elevated": { + "version": "3.0.0", + "resolved": "https://registry.npmjs.org/is-elevated/-/is-elevated-3.0.0.tgz", + "integrity": "sha512-wjcp6RkouU9jpg55zERl+BglvV5j4jx5c/EMvQ+d12j/+nIEenNWPu+qc0tCg3JkLodbKZMg1qhJzEwG4qjclg==", + "requires": { + "is-admin": "^3.0.0", + "is-root": "^2.1.0" + } + }, "is-extglob": { "version": "2.1.1", "resolved": "https://registry.npmjs.org/is-extglob/-/is-extglob-2.1.1.tgz", @@ -27183,6 +27436,11 @@ "has-tostringtag": "^1.0.0" } }, + "is-root": { + "version": "2.1.0", + "resolved": "https://registry.npmjs.org/is-root/-/is-root-2.1.0.tgz", + "integrity": "sha512-AGOriNp96vNBd3HtU+RzFEc75FfR5ymiYv8E553I71SCeXBiMsVDUtdio1OEFvrPyLIQ9tVR5RxXIFe5PUFjMg==" + }, "is-set": { "version": "2.0.2", "resolved": "https://registry.npmjs.org/is-set/-/is-set-2.0.2.tgz", @@ -27294,8 +27552,7 @@ "isexe": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/isexe/-/isexe-2.0.0.tgz", - "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==", - "dev": true + "integrity": "sha512-RHxMLp9lnKHGHRng9QFhRCMbYAcVpn69smSGcq3f36xjgVVWThj4qqLbTLlq7Ssj8B+fIQ1EuCEGI2lKsyQeIw==" }, "isobject": { "version": "3.0.1", @@ -29583,6 +29840,11 @@ "integrity": "sha512-Yd3UES5mWCSqR+qNT93S3UoYUkqAZ9lLg8a7g9rimsWmYGK8cVToA4/sF3RrshdyV3sAGMXVUmpMYOw+dLpOuw==", "dev": true }, + "nice-try": { + "version": "1.0.5", + "resolved": "https://registry.npmjs.org/nice-try/-/nice-try-1.0.5.tgz", + "integrity": "sha512-1nh45deeb5olNY7eX82BkPO7SSxR5SSYJiPTrTdFUVYwAl8CKMA5N9PjTYkHiRjisVcxcQ1HXdLhx2qxxJzLNQ==" + }, "no-case": { "version": "3.0.4", "resolved": "https://registry.npmjs.org/no-case/-/no-case-3.0.4.tgz", @@ -29954,6 +30216,11 @@ "integrity": "sha512-BZOr3nRQHOntUjTrH8+Lh54smKHoHyur8We1V8DSMVrl5A2malOOwuJRnKRDjSnkoeBh4at6BwEnb5I7Jl31wg==", "dev": true }, + "p-finally": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/p-finally/-/p-finally-1.0.0.tgz", + "integrity": "sha512-LICb2p9CB7FS+0eR1oqWnHhp0FljGLZCWBE9aix0Uye9W8LTQPwMTYVGWQWIw9RdQiDg4+epXQODwIYJtSJaow==" + }, "p-limit": { "version": "2.3.0", "resolved": "https://registry.npmjs.org/p-limit/-/p-limit-2.3.0.tgz", @@ -30844,7 +31111,6 @@ "version": "3.0.0", "resolved": "https://registry.npmjs.org/pump/-/pump-3.0.0.tgz", "integrity": "sha512-LwZy+p3SFs1Pytd/jYct4wpv49HiYCqd9Rlc5ZVdk0V+8Yzv6jR5Blk3TRmPL1ft69TxP0IMZGJ+WPFU2BFhww==", - "dev": true, "requires": { "end-of-stream": "^1.1.0", "once": "^1.3.1" @@ -31787,8 +32053,7 @@ "signal-exit": { "version": "3.0.7", "resolved": "https://registry.npmjs.org/signal-exit/-/signal-exit-3.0.7.tgz", - "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==", - "dev": true + "integrity": "sha512-wnD2ZE+l+SPC/uoS0vXeE9L1+0wuaMqKlfz9AMUo38JsyLSBWSFcHR1Rri62LZc12vLr1gb3jl7iwQhgwpAbGQ==" }, "simple-swizzle": { "version": "0.2.2", @@ -32152,6 +32417,11 @@ "integrity": "sha512-vavAMRXOgBVNF6nyEEmL3DBK19iRpDcoIwW+swQ+CbGiu7lju6t+JklA1MHweoWtadgt4ISVUsXLyDq34ddcwA==", "dev": true }, + "strip-eof": { + "version": "1.0.0", + "resolved": "https://registry.npmjs.org/strip-eof/-/strip-eof-1.0.0.tgz", + "integrity": "sha512-7FCwGGmx8mD5xQd3RPUvnSpUXHM3BWuzjtpD4TXsfcZ9EL4azvVVUscFYwD9nx8Kh+uCBC00XBtAykoMHwTh8Q==" + }, "strip-final-newline": { "version": "2.0.0", "resolved": "https://registry.npmjs.org/strip-final-newline/-/strip-final-newline-2.0.0.tgz", diff --git a/package.json b/package.json index 3e8e3c40..24abeafb 100644 --- a/package.json +++ b/package.json @@ -250,6 +250,7 @@ "framer-motion": "^10.16.16", "fs-extra": "^11.2.0", "history": "^5.3.0", + "is-elevated": "^3.0.0", "jszip": "^3.10.1", "md5-file": "^5.0.0", "node-abi": "^3.47.0", diff --git a/release/app/package-lock.json b/release/app/package-lock.json index 20438518..94f8f59f 100644 --- a/release/app/package-lock.json +++ b/release/app/package-lock.json @@ -11,6 +11,7 @@ "license": "MIT", "dependencies": { "ps-list": "^7.2.0", + "query-process": "^0.0.3", "regedit-rs": "^1.0.2", "sharp": "^0.32.6" } @@ -344,6 +345,160 @@ "once": "^1.3.1" } }, + "node_modules/query-process": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/query-process/-/query-process-0.0.3.tgz", + "integrity": "sha512-6WRue0P+c84abP0o8MkDvigoS/gkkJzsSBt10PsOoBkP7Yodo4DducFsn9XyS4S+LuVYPAE5Hr4+kVNR5Onykg==", + "engines": { + "node": ">= 10" + }, + "optionalDependencies": { + "query-process-android-arm-eabi": "0.0.3", + "query-process-android-arm64": "0.0.3", + "query-process-linux-arm-gnueabihf": "0.0.3", + "query-process-linux-arm64-gnu": "0.0.3", + "query-process-linux-arm64-musl": "0.0.3", + "query-process-linux-x64-gnu": "0.0.3", + "query-process-linux-x64-musl": "0.0.3", + "query-process-win32-arm64-msvc": "0.0.3", + "query-process-win32-x64-msvc": "0.0.3" + } + }, + "node_modules/query-process-android-arm-eabi": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/query-process-android-arm-eabi/-/query-process-android-arm-eabi-0.0.3.tgz", + "integrity": "sha512-NB+9T+/poBcygDiG+7d2lJSeioP5ZyLT0HwUBdnLgNWvNCpzbJxydup1SLpnt5G2NF6nlTgbUZlH4hvxY7t/bw==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/query-process-android-arm64": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/query-process-android-arm64/-/query-process-android-arm64-0.0.3.tgz", + "integrity": "sha512-TiAw2yO62vQzM0s02471LToHyUs/PRkLGGlA715z10BPIM5NckzIe245AI45CDyH6tE/3nVHUd0LX/dfjQtTcw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "android" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/query-process-linux-arm-gnueabihf": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/query-process-linux-arm-gnueabihf/-/query-process-linux-arm-gnueabihf-0.0.3.tgz", + "integrity": "sha512-w7NLHBKt7qselCDoh/PVWyeuEb2NiiDDf1A9UB4K3Ns/H24hK3NbfMMBm8mCFxUnFUqoVX8O+VMs7dD/FNlTxA==", + "cpu": [ + "arm" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/query-process-linux-arm64-gnu": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/query-process-linux-arm64-gnu/-/query-process-linux-arm64-gnu-0.0.3.tgz", + "integrity": "sha512-nrPHjnSqCBuuN7IZkZWOnBpiJjyKOjfpT0Xt2EjSGp+I7C0CHbnhCL/vG1hBzaWZn0mxJ5nf0c5N0Fja7krnpQ==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/query-process-linux-arm64-musl": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/query-process-linux-arm64-musl/-/query-process-linux-arm64-musl-0.0.3.tgz", + "integrity": "sha512-vk8xMYTnS1PRKhwJgqLKyBAGIFP2CYZW2BsaKuNgQKUrDv7NnBaG7yukZT8niHNO1ycSrFpR/xqeJ8R23hO07A==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/query-process-linux-x64-gnu": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/query-process-linux-x64-gnu/-/query-process-linux-x64-gnu-0.0.3.tgz", + "integrity": "sha512-j1tGcNnGyVCABJ1PHZD1gKuyuomNzsPow3NDuZzUGjPqvKu67RsmKJJJOhMyT1SvUkcqdLFdtS1KTD20I4GS5Q==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/query-process-linux-x64-musl": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/query-process-linux-x64-musl/-/query-process-linux-x64-musl-0.0.3.tgz", + "integrity": "sha512-AOGrrI/Qcb30iKFstiW60zNG/HQevCY0Q38eMHGd7LrBZ5sEN7NzZOjzKp43KeNHejuZBDMxf0gdGAqDznOAng==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "linux" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/query-process-win32-arm64-msvc": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/query-process-win32-arm64-msvc/-/query-process-win32-arm64-msvc-0.0.3.tgz", + "integrity": "sha512-LHvxbzMFwPPUXHe4bDCAqs1bYbp8j0bMW8XyJGPZnIYrnwHz6g8VE5WQEtXQxSznsbfVxAKJXUtn088EjDVazw==", + "cpu": [ + "arm64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, + "node_modules/query-process-win32-x64-msvc": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/query-process-win32-x64-msvc/-/query-process-win32-x64-msvc-0.0.3.tgz", + "integrity": "sha512-LfHAKmfqyKCgl9K+sTz0KyNwMwB79VcXZUy/Et9iQKLuZt7PDYpHWcFdhrfHw2qqIdKWTED8KmnmsOLhUn/2OA==", + "cpu": [ + "x64" + ], + "optional": true, + "os": [ + "win32" + ], + "engines": { + "node": ">= 10" + } + }, "node_modules/queue-tick": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/queue-tick/-/queue-tick-1.0.1.tgz", @@ -851,6 +1006,76 @@ "once": "^1.3.1" } }, + "query-process": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/query-process/-/query-process-0.0.3.tgz", + "integrity": "sha512-6WRue0P+c84abP0o8MkDvigoS/gkkJzsSBt10PsOoBkP7Yodo4DducFsn9XyS4S+LuVYPAE5Hr4+kVNR5Onykg==", + "requires": { + "query-process-android-arm-eabi": "0.0.3", + "query-process-android-arm64": "0.0.3", + "query-process-linux-arm-gnueabihf": "0.0.3", + "query-process-linux-arm64-gnu": "0.0.3", + "query-process-linux-arm64-musl": "0.0.3", + "query-process-linux-x64-gnu": "0.0.3", + "query-process-linux-x64-musl": "0.0.3", + "query-process-win32-arm64-msvc": "0.0.3", + "query-process-win32-x64-msvc": "0.0.3" + } + }, + "query-process-android-arm-eabi": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/query-process-android-arm-eabi/-/query-process-android-arm-eabi-0.0.3.tgz", + "integrity": "sha512-NB+9T+/poBcygDiG+7d2lJSeioP5ZyLT0HwUBdnLgNWvNCpzbJxydup1SLpnt5G2NF6nlTgbUZlH4hvxY7t/bw==", + "optional": true + }, + "query-process-android-arm64": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/query-process-android-arm64/-/query-process-android-arm64-0.0.3.tgz", + "integrity": "sha512-TiAw2yO62vQzM0s02471LToHyUs/PRkLGGlA715z10BPIM5NckzIe245AI45CDyH6tE/3nVHUd0LX/dfjQtTcw==", + "optional": true + }, + "query-process-linux-arm-gnueabihf": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/query-process-linux-arm-gnueabihf/-/query-process-linux-arm-gnueabihf-0.0.3.tgz", + "integrity": "sha512-w7NLHBKt7qselCDoh/PVWyeuEb2NiiDDf1A9UB4K3Ns/H24hK3NbfMMBm8mCFxUnFUqoVX8O+VMs7dD/FNlTxA==", + "optional": true + }, + "query-process-linux-arm64-gnu": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/query-process-linux-arm64-gnu/-/query-process-linux-arm64-gnu-0.0.3.tgz", + "integrity": "sha512-nrPHjnSqCBuuN7IZkZWOnBpiJjyKOjfpT0Xt2EjSGp+I7C0CHbnhCL/vG1hBzaWZn0mxJ5nf0c5N0Fja7krnpQ==", + "optional": true + }, + "query-process-linux-arm64-musl": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/query-process-linux-arm64-musl/-/query-process-linux-arm64-musl-0.0.3.tgz", + "integrity": "sha512-vk8xMYTnS1PRKhwJgqLKyBAGIFP2CYZW2BsaKuNgQKUrDv7NnBaG7yukZT8niHNO1ycSrFpR/xqeJ8R23hO07A==", + "optional": true + }, + "query-process-linux-x64-gnu": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/query-process-linux-x64-gnu/-/query-process-linux-x64-gnu-0.0.3.tgz", + "integrity": "sha512-j1tGcNnGyVCABJ1PHZD1gKuyuomNzsPow3NDuZzUGjPqvKu67RsmKJJJOhMyT1SvUkcqdLFdtS1KTD20I4GS5Q==", + "optional": true + }, + "query-process-linux-x64-musl": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/query-process-linux-x64-musl/-/query-process-linux-x64-musl-0.0.3.tgz", + "integrity": "sha512-AOGrrI/Qcb30iKFstiW60zNG/HQevCY0Q38eMHGd7LrBZ5sEN7NzZOjzKp43KeNHejuZBDMxf0gdGAqDznOAng==", + "optional": true + }, + "query-process-win32-arm64-msvc": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/query-process-win32-arm64-msvc/-/query-process-win32-arm64-msvc-0.0.3.tgz", + "integrity": "sha512-LHvxbzMFwPPUXHe4bDCAqs1bYbp8j0bMW8XyJGPZnIYrnwHz6g8VE5WQEtXQxSznsbfVxAKJXUtn088EjDVazw==", + "optional": true + }, + "query-process-win32-x64-msvc": { + "version": "0.0.3", + "resolved": "https://registry.npmjs.org/query-process-win32-x64-msvc/-/query-process-win32-x64-msvc-0.0.3.tgz", + "integrity": "sha512-LfHAKmfqyKCgl9K+sTz0KyNwMwB79VcXZUy/Et9iQKLuZt7PDYpHWcFdhrfHw2qqIdKWTED8KmnmsOLhUn/2OA==", + "optional": true + }, "queue-tick": { "version": "1.0.1", "resolved": "https://registry.npmjs.org/queue-tick/-/queue-tick-1.0.1.tgz", diff --git a/release/app/package.json b/release/app/package.json index 2f41eb68..ffb87505 100644 --- a/release/app/package.json +++ b/release/app/package.json @@ -15,6 +15,7 @@ }, "dependencies": { "ps-list": "^7.2.0", + "query-process": "^0.0.3", "regedit-rs": "^1.0.2", "sharp": "^0.32.6" }, diff --git a/src/main/helpers/os.helpers.ts b/src/main/helpers/os.helpers.ts index da6aed8d..e44a6c70 100644 --- a/src/main/helpers/os.helpers.ts +++ b/src/main/helpers/os.helpers.ts @@ -10,4 +10,16 @@ export async function taskRunning(task: string): Promise { log.error(error); return false; } -} \ No newline at end of file +} + +export async function getProcessPid(task: string): Promise { + try { + const processes = await psList(); + const process = processes.find(process => process.name?.includes(task) || process.cmd?.includes(task)); + return process?.pid; + } + catch(error){ + log.error(error); + return null; + } +} diff --git a/src/main/services/bs-launcher/steam-launcher.service.ts b/src/main/services/bs-launcher/steam-launcher.service.ts index 7ebc0cb0..29e6d861 100644 --- a/src/main/services/bs-launcher/steam-launcher.service.ts +++ b/src/main/services/bs-launcher/steam-launcher.service.ts @@ -8,6 +8,9 @@ import { BS_APP_ID, BS_EXECUTABLE, STEAMVR_APP_ID } from "../../constants"; import log from "electron-log"; import { AbstractLauncherService } from "./abstract-launcher.service"; import { CustomError } from "../../../shared/models/exceptions/custom-error.class"; +import isElevated from "is-elevated"; +import { UtilsService } from "../utils.service"; +import { exec } from "child_process"; export class SteamLauncherService extends AbstractLauncherService implements StoreLauncherInterface{ @@ -21,10 +24,12 @@ export class SteamLauncherService extends AbstractLauncherService implements Sto } private readonly steam: SteamService; + private readonly util: UtilsService; private constructor(){ super(); this.steam = SteamService.getInstance(); + this.util = UtilsService.getInstance(); } private getSteamVRPath(): Promise { @@ -41,6 +46,17 @@ export class SteamLauncherService extends AbstractLauncherService implements Sto }); } + private needStartBsAsAdmin(): Promise { + return isElevated().then(elevated => { + if(elevated){ return false; } + return this.steam.isElevated(); + }) + } + + private getStartBsAsAdminExePath(): string { + return path.join(this.util.getAssetsScriptsPath(), "start_beat_saber_admin.exe"); + } + public async restoreSteamVR(): Promise { const steamVrFolder = await this.getSteamVRPath(); const steamVrBackup = `${steamVrFolder}.bak`; @@ -53,7 +69,7 @@ export class SteamLauncherService extends AbstractLauncherService implements Sto log.error("Error while restoring SteamVR", err); }); } - + public launch(launchOptions: LaunchOption): Observable{ return new Observable(obs => {(async () => { @@ -90,7 +106,26 @@ export class SteamLauncherService extends AbstractLauncherService implements Sto obs.next({type: BSLaunchEvent.BS_LAUNCHING}); - await this.launchBs(exePath, launchArgs, { env: {...process.env, "SteamAppId": BS_APP_ID} }).then(exitCode => { + const needToStartAsAdmin = await this.needStartBsAsAdmin().catch(err => { + log.error("Error while checking if need to start BS as Admin", err); + return false; + }); + + const launchPromise = !needToStartAsAdmin ? ( + this.launchBs(exePath, launchArgs, { env: {...process.env, "SteamAppId": BS_APP_ID} }) + ) : ( + new Promise(resolve => { + const adminProcess = exec(`"${this.getStartBsAsAdminExePath()}" "${exePath}" ${launchArgs.join(" ")}`, { env: {...process.env, "SteamAppId": BS_APP_ID} }); + adminProcess.on("error", err => {log.error("Error while starting BS as Admin", err); resolve(-1)}); + + setTimeout(() => { + adminProcess.removeAllListeners("error"); + resolve(-1); + }, 35_000); + }) + ); + + await launchPromise.then(exitCode => { log.info("BS process exit code", exitCode); }).catch(err => { throw CustomError.fromError(err, BSLaunchError.BS_EXIT_ERROR); @@ -109,4 +144,4 @@ export class SteamLauncherService extends AbstractLauncherService implements Sto })}); } -} \ No newline at end of file +} diff --git a/src/main/services/steam.service.ts b/src/main/services/steam.service.ts index 9e8472a3..5583169d 100644 --- a/src/main/services/steam.service.ts +++ b/src/main/services/steam.service.ts @@ -5,11 +5,15 @@ import { readFile } from "fs/promises"; import { pathExist } from "../helpers/fs.helpers"; import log from "electron-log"; import { app, shell } from "electron"; -import { taskRunning } from "../helpers/os.helpers"; +import { getProcessPid, taskRunning } from "../helpers/os.helpers"; +import { isElevated } from "query-process"; export class SteamService { + private static readonly PROCESS_NAME = "steam"; + private static instance: SteamService; + private steamPath: string = ''; private constructor(){} @@ -29,12 +33,25 @@ export class SteamService { } public async steamRunning(): Promise{ - const steamProcessRunning = await taskRunning("steam"); + const steamProcessRunning = await taskRunning(SteamService.PROCESS_NAME); if(process.platform === "linux") { return steamProcessRunning; } const activeUser = await this.getActiveUser().catch(err => log.error(err)); return steamProcessRunning && !!activeUser; } + public async getSteamPid(): Promise{ + return getProcessPid(SteamService.PROCESS_NAME); + } + + public async isElevated(): Promise{ + if(process.platform === "linux"){ return true; } + const steamPid = await this.getSteamPid(); + + if(!steamPid){ return false; } + + return isElevated(steamPid); + } + public async getSteamPath(): Promise{ if(this.steamPath){ return this.steamPath; } @@ -68,7 +85,7 @@ export class SteamService { let libraryFolders: any = path.join(steamPath, "steamapps", "libraryfolders.vdf"); if (!(await pathExist(libraryFolders))) { return null; } - + libraryFolders = parse(await readFile(libraryFolders, { encoding: "utf-8" })); if (!libraryFolders.libraryfolders) { return null; } @@ -83,7 +100,7 @@ export class SteamService { } return null; - + } catch (e) { log.error(e); return null; @@ -91,7 +108,7 @@ export class SteamService { } public async openSteam(): Promise { - + await shell.openPath("steam://open/games"); return new Promise((resolve, reject) => {