mirror of
https://github.com/mmvanheusden/SteamDepotDownloaderGUI.git
synced 2026-02-04 05:31:19 +01:00
chore: add vectum base
This commit is contained in:
11
src-tauri/.gitignore
vendored
11
src-tauri/.gitignore
vendored
@@ -2,3 +2,14 @@
|
||||
# will have compiled files and executables
|
||||
/target/
|
||||
|
||||
# Generated by Tauri
|
||||
# will have schema files for capabilities auto-completion
|
||||
/gen/schemas
|
||||
|
||||
|
||||
# DepotDownloader
|
||||
depot/
|
||||
downloads/
|
||||
.DepotDownloader/
|
||||
Games/
|
||||
Depots/
|
||||
2923
src-tauri/Cargo.lock
generated
2923
src-tauri/Cargo.lock
generated
File diff suppressed because it is too large
Load Diff
@@ -1,21 +1,23 @@
|
||||
[package]
|
||||
name = "steamdepotdownloadergui"
|
||||
version = "3.0.0"
|
||||
description = "A Tauri App"
|
||||
name = "vectum"
|
||||
version = "3.0.0-alpha.1"
|
||||
description = "Download older versions of Steam games with DepotDownloader"
|
||||
authors = ["mmvanheusden"]
|
||||
edition = "2021"
|
||||
|
||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||
|
||||
[build-dependencies]
|
||||
tauri-build = { version = "2.0.0-beta", features = [] }
|
||||
tauri-build = { version = "2.0.0-rc.11", features = [] }
|
||||
|
||||
[dependencies]
|
||||
tauri = { version = "2.0.0-beta", features = [] }
|
||||
tauri-plugin-shell = "2.0.0-beta"
|
||||
serde_json = "1.0"
|
||||
|
||||
[features]
|
||||
# this feature is used for production builds or when `devPath` points to the filesystem
|
||||
# DO NOT REMOVE!!
|
||||
custom-protocol = ["tauri/custom-protocol"]
|
||||
tauri = { version = "2.0.0-rc.14", features = [] }
|
||||
tauri-plugin-shell = "2.0.0-rc.3"
|
||||
tauri-plugin-dialog = "2.0.0-rc.7"
|
||||
serde = { version = "1", features = ["derive"] }
|
||||
serde_json = "1"
|
||||
derive-getters = "0.5.0"
|
||||
sha256 = "1.5.0"
|
||||
reqwest = { version = "0.12.7" }
|
||||
zip = "2.2.0"
|
||||
async-process = "2.3.0"
|
||||
|
||||
12
src-tauri/capabilities/default.json
Normal file
12
src-tauri/capabilities/default.json
Normal file
@@ -0,0 +1,12 @@
|
||||
{
|
||||
"$schema": "../gen/schemas/desktop-schema.json",
|
||||
"identifier": "default",
|
||||
"description": "Capability for the main window",
|
||||
"windows": ["main"],
|
||||
"permissions": [
|
||||
"core:default",
|
||||
"shell:allow-open",
|
||||
"dialog:default",
|
||||
"shell:default"
|
||||
]
|
||||
}
|
||||
@@ -1,18 +0,0 @@
|
||||
{
|
||||
"$schema": "./schemas/desktop-schema.json",
|
||||
"identifier": "default",
|
||||
"description": "Capability for the main window",
|
||||
"windows": [
|
||||
"main"
|
||||
],
|
||||
"permissions": [
|
||||
"path:default",
|
||||
"event:default",
|
||||
"window:default",
|
||||
"app:default",
|
||||
"resources:default",
|
||||
"menu:default",
|
||||
"tray:default",
|
||||
"shell:allow-open"
|
||||
]
|
||||
}
|
||||
@@ -1 +0,0 @@
|
||||
{"default":{"identifier":"default","description":"Capability for the main window","context":"local","windows":["main"],"permissions":["path:default","event:default","window:default","app:default","resources:default","menu:default","tray:default","shell:allow-open"],"platforms":["linux","macOS","windows","android","iOS"]}}
|
||||
@@ -1 +0,0 @@
|
||||
{schema_str}
|
||||
@@ -1 +0,0 @@
|
||||
{schema_str}
|
||||
File diff suppressed because one or more lines are too long
77
src-tauri/src/depotdownloader.rs
Normal file
77
src-tauri/src/depotdownloader.rs
Normal file
@@ -0,0 +1,77 @@
|
||||
use std::fs::File;
|
||||
use std::io::ErrorKind::AlreadyExists;
|
||||
use std::{fs, io};
|
||||
use std::{io::Write, path::Path};
|
||||
|
||||
use reqwest;
|
||||
use sha256;
|
||||
|
||||
pub fn calc_checksum(path: &Path) -> io::Result<String> {
|
||||
let bytes = fs::read(path)?;
|
||||
let hash = sha256::digest(&bytes);
|
||||
Ok(hash)
|
||||
}
|
||||
|
||||
/// Downloads a file. The file will be saved to the [`filename`] provided.
|
||||
pub async fn download_file(url: &str, filename: &Path) -> io::Result<()> {
|
||||
if filename.exists() {
|
||||
println!("DEBUG: Not downloading. File already exists.");
|
||||
return Err(io::Error::from(AlreadyExists));
|
||||
}
|
||||
|
||||
let mut file = File::create(filename)?;
|
||||
let response = reqwest::get(url)
|
||||
.await
|
||||
.expect("Failed to contact internet.");
|
||||
|
||||
let content = response
|
||||
.bytes()
|
||||
.await
|
||||
.expect("Failed to get response content.");
|
||||
|
||||
file.write_all(&content)?;
|
||||
Ok(())
|
||||
}
|
||||
|
||||
/// Unzips DepotDownloader zips
|
||||
pub fn unzip(zip_file: &Path) -> io::Result<()> {
|
||||
let file = File::open(zip_file)?;
|
||||
let mut archive = zip::ZipArchive::new(file)?;
|
||||
|
||||
for i in 0..archive.len() {
|
||||
let mut file = archive.by_index(i)?;
|
||||
|
||||
let outpath = match file.enclosed_name() {
|
||||
Some(path) => path,
|
||||
None => continue
|
||||
};
|
||||
|
||||
println!("Extracted {} from archive.", outpath.display());
|
||||
|
||||
if let Some(p) = outpath.parent() {
|
||||
if !p.exists() {
|
||||
fs::create_dir_all(p)?;
|
||||
}
|
||||
}
|
||||
let mut outfile = File::create(&outpath)?;
|
||||
io::copy(&mut file, &mut outfile)?;
|
||||
|
||||
|
||||
// Copy over permissions from enclosed file to extracted file on UNIX systems.
|
||||
#[cfg(unix)]
|
||||
{
|
||||
use std::os::unix::fs::PermissionsExt;
|
||||
|
||||
// If the mode `file.unix_mode()` is something (not None), copy it over to the extracted file.
|
||||
if let Some(mode) = file.unix_mode() {
|
||||
fs::set_permissions(&outpath, fs::Permissions::from_mode(mode))?;
|
||||
}
|
||||
|
||||
// Set DepotDownloader executable.
|
||||
if outpath.display().to_string() == "DepotDownloader" {
|
||||
fs::set_permissions(&outpath, fs::Permissions::from_mode(0o755))?; // WTF is an octal?
|
||||
}
|
||||
}
|
||||
}
|
||||
Ok(())
|
||||
}
|
||||
@@ -1,16 +1,125 @@
|
||||
// Prevents additional console window on Windows in release, DO NOT REMOVE!!
|
||||
#![cfg_attr(not(debug_assertions), windows_subsystem = "windows")]
|
||||
|
||||
// Learn more about Tauri commands at https://tauri.app/v1/guides/features/command
|
||||
use std::io;
|
||||
use std::path::{Path};
|
||||
use std::sync::OnceLock;
|
||||
use std::time::Duration;
|
||||
|
||||
use tauri::{AppHandle, Emitter};
|
||||
|
||||
use crate::terminal::Terminal;
|
||||
|
||||
mod steam;
|
||||
mod depotdownloader;
|
||||
mod terminal;
|
||||
|
||||
static DEPOTDOWNLOADER_VERSION: &str = "2.7.1";
|
||||
//TODO: arm
|
||||
static DEPOTDOWNLOADER_LINUX_URL: &str = "https://github.com/SteamRE/DepotDownloader/releases/download/DepotDownloader_2.7.1/DepotDownloader-linux-x64.zip";
|
||||
static DEPOTDOWNLOADER_WIN_URL: &str = "https://github.com/SteamRE/DepotDownloader/releases/download/DepotDownloader_2.7.1/DepotDownloader-windows-x64.zip";
|
||||
|
||||
|
||||
// We create this variable now, and quickly populate it in preload_vectum(). Then we later access the data in start_download()
|
||||
static TERMINAL: OnceLock<Vec<Terminal>> = OnceLock::new();
|
||||
|
||||
/// This function is called every time the app is reloaded/started. It quickly populates the [`TERMINAL`] variable with a working terminal.
|
||||
#[tauri::command]
|
||||
fn greet(name: &str) -> String {
|
||||
format!("Hello, {}! You've been greeted from Rust!", name)
|
||||
async fn preload_vectum(app: AppHandle) {
|
||||
// Only fill this variable once.
|
||||
if TERMINAL.get().is_none() { TERMINAL.set(terminal::get_installed_terminals(true).await).expect("Failed to set available terminals") }
|
||||
|
||||
// Send the default terminal name to the frontend.
|
||||
app.emit("default-terminal", Terminal::pretty_name(&TERMINAL.get().unwrap()[0])).unwrap();
|
||||
}
|
||||
|
||||
#[tauri::command]
|
||||
async fn start_download(steam_download: steam::SteamDownload) {
|
||||
let default_terminal = TERMINAL.get().unwrap();
|
||||
let working_dir = std::env::current_dir().unwrap();
|
||||
|
||||
let terminal_to_use = if steam_download.options().terminal().is_none() { default_terminal.first().unwrap() } else { &Terminal::from_index(&steam_download.options().terminal().unwrap()).unwrap() };
|
||||
|
||||
println!("\n\n---------------------HELLO FROM RUST!---------------------");
|
||||
println!("We received these values from frontend:");
|
||||
println!("\t- Username: {}", steam_download.username().as_ref().unwrap_or(&String::from("Not provided")));
|
||||
println!("\t- Password: {}", steam_download.password().as_ref().unwrap_or(&String::from("Not provided")));
|
||||
println!("\t- App ID: {}", steam_download.app_id());
|
||||
println!("\t- Depot ID: {}", steam_download.depot_id());
|
||||
println!("\t- Manifest ID: {}", steam_download.manifest_id());
|
||||
println!("\t- Output Path: {}", steam_download.output_path());
|
||||
println!("------------------------DEBUG INFORMATION-----------------");
|
||||
println!("\t- Default terminal: {}", Terminal::pretty_name(&default_terminal[0]));
|
||||
println!("\t- Terminal command: {:?}", terminal_to_use.create_command(&steam_download));
|
||||
println!("\t- Working directory: {}", working_dir.display());
|
||||
println!("----------------------------------------------------------");
|
||||
|
||||
terminal_to_use.create_command(&steam_download).spawn().ok();
|
||||
}
|
||||
|
||||
|
||||
/// Downloads the DepotDownloader zip file from the internet based on the OS.
|
||||
#[tauri::command]
|
||||
async fn download_depotdownloader() {
|
||||
let url = if std::env::consts::OS == "windows" {
|
||||
DEPOTDOWNLOADER_WIN_URL
|
||||
} else {
|
||||
DEPOTDOWNLOADER_LINUX_URL
|
||||
};
|
||||
|
||||
// Where we store the DepotDownloader zip.
|
||||
let zip_filename = format!("DepotDownloader-v{}-{}.zip", DEPOTDOWNLOADER_VERSION, std::env::consts::OS);
|
||||
let depotdownloader_zip = Path::new(&zip_filename);
|
||||
|
||||
println!("Downloading DepotDownloader for {} to .{}{}", std::env::consts::OS, std::path::MAIN_SEPARATOR, depotdownloader_zip.display());
|
||||
|
||||
match depotdownloader::download_file(url, depotdownloader_zip).await {
|
||||
Err(e) => {
|
||||
if e.kind() == io::ErrorKind::AlreadyExists {
|
||||
println!("DepotDownloader already exists. Skipping download.");
|
||||
return;
|
||||
}
|
||||
|
||||
println!("Failed to download DepotDownloader: {}", e);
|
||||
return;
|
||||
},
|
||||
_ => {}
|
||||
}
|
||||
|
||||
println!("Succesfully downloaded DepotDownloader from {}", url);
|
||||
|
||||
depotdownloader::unzip(depotdownloader_zip).unwrap();
|
||||
println!("Succesfully extracted DepotDownloader zip.");
|
||||
}
|
||||
|
||||
/// Checks internet connectivity using Google
|
||||
#[tauri::command]
|
||||
async fn internet_connection() -> bool {
|
||||
let client = reqwest::Client::builder().timeout(Duration::from_secs(5)).build().unwrap();
|
||||
|
||||
client.get("https://connectivitycheck.android.com/generate_204").send().await.is_ok()
|
||||
}
|
||||
|
||||
|
||||
#[tauri::command]
|
||||
async fn get_all_terminals(app: AppHandle) {
|
||||
let terminals = terminal::get_installed_terminals(false).await;
|
||||
|
||||
terminals.iter().for_each(|terminal| {
|
||||
println!("Terminal #{} ({}) is installed!", terminal.index().unwrap(), terminal.pretty_name());
|
||||
|
||||
// Sends: (terminal index aligned with dropdown; total terminals)
|
||||
app.emit("working-terminal", (terminal.index(), Terminal::total())).unwrap();
|
||||
});
|
||||
}
|
||||
|
||||
fn main() {
|
||||
tauri::Builder::default()
|
||||
.plugin(tauri_plugin_shell::init())
|
||||
.invoke_handler(tauri::generate_handler![greet])
|
||||
.run(tauri::generate_context!())
|
||||
.expect("error while running tauri application");
|
||||
println!();
|
||||
tauri::Builder::default().plugin(tauri_plugin_dialog::init()).plugin(tauri_plugin_shell::init()).invoke_handler(tauri::generate_handler![
|
||||
start_download,
|
||||
download_depotdownloader,
|
||||
internet_connection,
|
||||
preload_vectum,
|
||||
get_all_terminals
|
||||
]).run(tauri::generate_context!()).expect("error while running tauri application");
|
||||
}
|
||||
|
||||
41
src-tauri/src/steam.rs
Normal file
41
src-tauri/src/steam.rs
Normal file
@@ -0,0 +1,41 @@
|
||||
use std::path::PathBuf;
|
||||
use derive_getters::Getters;
|
||||
use serde::Deserialize;
|
||||
|
||||
|
||||
/// Represents the data required to download a Steam depot.
|
||||
#[derive(Deserialize, Debug, Getters)]
|
||||
pub struct SteamDownload {
|
||||
username: Option<String>,
|
||||
password: Option<String>,
|
||||
app_id: String,
|
||||
depot_id: String,
|
||||
manifest_id: String,
|
||||
options: VectumOptions
|
||||
}
|
||||
|
||||
#[derive(Debug, Deserialize, Getters)]
|
||||
pub struct VectumOptions {
|
||||
terminal: Option<u8>,
|
||||
output_directory: Option<PathBuf>,
|
||||
directory_name: Option<String>
|
||||
}
|
||||
|
||||
|
||||
impl SteamDownload {
|
||||
/// If a username or password are not provided, the download is considered anonymous
|
||||
pub fn is_anonymous(&self) -> bool {
|
||||
self.username.is_none() || self.password.is_none()
|
||||
}
|
||||
|
||||
/// The directory where the download should happen
|
||||
pub fn output_path(&self) -> String {
|
||||
let sep = std::path::MAIN_SEPARATOR.to_string();
|
||||
match (&self.options.output_directory, &self.options.directory_name) {
|
||||
(Some(output_dir), Some(dir_name)) => format!("{}{}{}", output_dir.display(), sep, dir_name),
|
||||
(Some(output_dir), None) => format!("{}{}{}", output_dir.display(), sep, &self.manifest_id),
|
||||
(None, Some(dir_name)) => format!(".{}{}", sep, dir_name),
|
||||
(None, None) => format!(".{}{}", sep, &self.manifest_id)
|
||||
}
|
||||
}
|
||||
}
|
||||
394
src-tauri/src/terminal.rs
Normal file
394
src-tauri/src/terminal.rs
Normal file
@@ -0,0 +1,394 @@
|
||||
use crate::steam::SteamDownload;
|
||||
use async_process::Command;
|
||||
use serde::Serialize;
|
||||
|
||||
/// Represents a terminal that can be used to run commands.
|
||||
/// **Should be in sync with the terminal dropdown in the frontend.**
|
||||
#[derive(Debug, Serialize, PartialEq)]
|
||||
pub enum Terminal {
|
||||
GNOMETerminal,
|
||||
Alacritty,
|
||||
Konsole,
|
||||
GNOMEConsole,
|
||||
Xfce4Terminal,
|
||||
DeepinTerminal,
|
||||
Terminator,
|
||||
Terminology,
|
||||
Kitty,
|
||||
LXTerminal,
|
||||
Tilix,
|
||||
CoolRetroTerm,
|
||||
XTerm,
|
||||
CMD,
|
||||
}
|
||||
|
||||
|
||||
impl Terminal {
|
||||
/// Iterates through each terminal
|
||||
pub fn iter() -> impl Iterator<Item=Terminal> {
|
||||
use self::Terminal::*;
|
||||
|
||||
vec![
|
||||
GNOMETerminal, Alacritty, Konsole, GNOMEConsole, Xfce4Terminal, DeepinTerminal, Terminator, Terminology, Kitty, LXTerminal, Tilix, CoolRetroTerm, XTerm, CMD,
|
||||
].into_iter()
|
||||
}
|
||||
|
||||
/// Get terminal from index in order of the [`Terminal`] enum
|
||||
pub fn from_index(index: &u8) -> Option<Terminal> {
|
||||
Terminal::iter().nth(*index as usize)
|
||||
}
|
||||
|
||||
/// Get the index of a terminal in the order of the [`Terminal`] enum
|
||||
/// Returns `None` if the terminal is not found.
|
||||
pub fn index(&self) -> Option<u8> {
|
||||
Terminal::iter().position(|x| x == *self).map(|x| x as u8)
|
||||
}
|
||||
|
||||
|
||||
/// Get total number of terminals **possible** depending on the OS
|
||||
pub fn total() -> u8 {
|
||||
if cfg!(windows) {
|
||||
return 1;
|
||||
}
|
||||
|
||||
Terminal::iter().count() as u8 - 1 // -1 because cmd is not available on linux
|
||||
}
|
||||
|
||||
/// Get the pretty name of a terminal
|
||||
pub fn pretty_name(&self) -> &str {
|
||||
match self {
|
||||
Terminal::GNOMETerminal => "GNOME Terminal",
|
||||
Terminal::GNOMEConsole => "GNOME Console",
|
||||
Terminal::Konsole => "Konsole",
|
||||
Terminal::Xfce4Terminal => "Xfce Terminal",
|
||||
Terminal::Terminator => "Terminator",
|
||||
Terminal::Terminology => "Terminology",
|
||||
Terminal::XTerm => "XTerm",
|
||||
Terminal::Kitty => "Kitty",
|
||||
Terminal::LXTerminal => "LXTerminal",
|
||||
Terminal::Tilix => "Tilix",
|
||||
Terminal::DeepinTerminal => "Deepin Terminal",
|
||||
Terminal::CoolRetroTerm => "cool-retro-term",
|
||||
Terminal::Alacritty => "Alacritty",
|
||||
Terminal::CMD => "CMD",
|
||||
}
|
||||
}
|
||||
|
||||
|
||||
//region Probing a terminal
|
||||
/// Checks if a [`Terminal`] is installed.
|
||||
/// **See:** [`get_installed_terminals`]
|
||||
pub async fn installed(&self) -> bool {
|
||||
match self {
|
||||
Terminal::CMD => {
|
||||
let mut cmd = Command::new("cmd");
|
||||
cmd.arg("/?").output().await.is_ok()
|
||||
}
|
||||
Terminal::GNOMETerminal => {
|
||||
let mut cmd = Command::new("gnome-terminal");
|
||||
cmd.arg("--version").output().await.is_ok()
|
||||
}
|
||||
Terminal::GNOMEConsole => {
|
||||
let mut cmd = Command::new("kgx");
|
||||
cmd.arg("--version").output().await.is_ok()
|
||||
}
|
||||
Terminal::Konsole => {
|
||||
let mut cmd = Command::new("konsole");
|
||||
cmd.arg("--version").output().await.is_ok()
|
||||
}
|
||||
Terminal::Xfce4Terminal => {
|
||||
let mut cmd = Command::new("xfce4-terminal");
|
||||
cmd.arg("--version").output().await.is_ok()
|
||||
}
|
||||
Terminal::Terminator => {
|
||||
let mut cmd = Command::new("terminator");
|
||||
cmd.arg("--version").output().await.is_ok()
|
||||
}
|
||||
Terminal::Terminology => {
|
||||
let mut cmd = Command::new("terminology");
|
||||
cmd.arg("--version").output().await.is_ok()
|
||||
}
|
||||
Terminal::XTerm => {
|
||||
let mut cmd = Command::new("xterm");
|
||||
cmd.arg("-v").output().await.is_ok()
|
||||
}
|
||||
Terminal::Kitty => {
|
||||
let mut cmd = Command::new("kitty");
|
||||
cmd.arg("--version").output().await.is_ok()
|
||||
}
|
||||
Terminal::LXTerminal => {
|
||||
let mut cmd = Command::new("lxterminal");
|
||||
cmd.arg("--version").output().await.is_ok()
|
||||
}
|
||||
Terminal::Tilix => {
|
||||
let mut cmd = Command::new("tilix");
|
||||
cmd.arg("--version").output().await.is_ok()
|
||||
}
|
||||
Terminal::DeepinTerminal => {
|
||||
let mut cmd = Command::new("deepin-terminal");
|
||||
cmd.arg("--version").output().await.is_ok()
|
||||
}
|
||||
Terminal::CoolRetroTerm => {
|
||||
let mut cmd = Command::new("cool-retro-term");
|
||||
cmd.arg("--version").output().await.is_ok()
|
||||
}
|
||||
Terminal::Alacritty => {
|
||||
let mut cmd = Command::new("alacritty");
|
||||
cmd.arg("--version").output().await.is_ok()
|
||||
}
|
||||
}
|
||||
}
|
||||
//endregion
|
||||
|
||||
|
||||
//region Running a command in the terminal
|
||||
/**
|
||||
Returns a [`Command`] that, when executed should open the terminal and run the command.
|
||||
|
||||
|
||||
## Commands
|
||||
`{command}` = `{command};echo Command finished with code $?;sleep infinity`
|
||||
|
||||
| Terminal | Command to open terminal |
|
||||
|----------------|---------------------------------------------------------------------------|
|
||||
| CMD | `start cmd.exe /k {command}` |
|
||||
| GNOMETerminal | `gnome-terminal -- /usr/bin/env sh -c {command}` |
|
||||
| GNOMEConsole | `kgx -e /usr/bin/env sh -c {command}` |
|
||||
| Konsole | `konsole -e /usr/bin/env sh -c {command}` |
|
||||
| Xfce4Terminal | `xfce4-terminal -x /usr/bin/env sh -c {command}` |
|
||||
| Terminator | `terminator -T "Downloading depot..." -e {command}` |
|
||||
| Terminology | `terminology -e /usr/bin/env sh -c {command}` |
|
||||
| XTerm | `xterm -hold -T "Downloading depot..." -e /usr/bin/env sh -c {command}` |
|
||||
| Kitty | `kitty /usr/bin/env sh -c {command}` |
|
||||
| LXTerminal | `lxterminal -e /usr/bin/env sh -c {command}` |
|
||||
| Tilix | `tilix -e /usr/bin/env sh -c {command}` |
|
||||
| DeepinTerminal | `deepin-terminal -e /usr/bin/env sh -c {command}` |
|
||||
| CoolRetroTerm | `cool-retro-term -e /usr/bin/env sh -c {command}` |
|
||||
| Alacritty | `alacritty -e /usr/bin/env sh -c {command}` |
|
||||
|
||||
*/
|
||||
pub fn create_command(&self, steam_download: &SteamDownload) -> Command {
|
||||
let command = create_depotdownloader_command(steam_download);
|
||||
|
||||
match self {
|
||||
Terminal::CMD => {
|
||||
let mut cmd = Command::new("cmd.exe");
|
||||
cmd.args(&["/c", "start", "PowerShell.exe", "-NoExit", "-Command"]).args(command);
|
||||
cmd
|
||||
}
|
||||
Terminal::GNOMETerminal => {
|
||||
let mut cmd = Command::new("gnome-terminal");
|
||||
cmd.args([
|
||||
"--",
|
||||
"/usr/bin/env",
|
||||
"sh",
|
||||
"-c",
|
||||
]).args(command);
|
||||
cmd
|
||||
}
|
||||
Terminal::GNOMEConsole => {
|
||||
let mut cmd = Command::new("kgx");
|
||||
cmd.args([
|
||||
"-e",
|
||||
"/usr/bin/env",
|
||||
"sh",
|
||||
"-c"
|
||||
]).args(command);
|
||||
cmd
|
||||
}
|
||||
Terminal::Konsole => {
|
||||
let mut cmd = Command::new("konsole");
|
||||
cmd.args([
|
||||
"-e",
|
||||
"/usr/bin/env",
|
||||
"sh",
|
||||
"-c",
|
||||
]).args(command);
|
||||
cmd
|
||||
}
|
||||
Terminal::Xfce4Terminal => {
|
||||
let mut cmd = Command::new("xfce4-terminal");
|
||||
cmd.args([
|
||||
"-x",
|
||||
"/usr/bin/env",
|
||||
"sh",
|
||||
"-c",
|
||||
]).args(command);
|
||||
cmd
|
||||
}
|
||||
Terminal::Terminator => {
|
||||
let mut cmd = Command::new("terminator");
|
||||
cmd.args([
|
||||
"-T",
|
||||
"Downloading depot...",
|
||||
"-e",
|
||||
]).args(command);
|
||||
cmd
|
||||
}
|
||||
Terminal::Terminology => {
|
||||
let mut cmd = Command::new("terminology");
|
||||
cmd.args([
|
||||
"-e",
|
||||
"/usr/bin/env",
|
||||
"sh",
|
||||
"-c",
|
||||
]).args(command);
|
||||
cmd
|
||||
}
|
||||
Terminal::XTerm => {
|
||||
let mut cmd = Command::new("xterm");
|
||||
cmd.args([
|
||||
"-hold",
|
||||
"-T",
|
||||
"Downloading depot...",
|
||||
"-e",
|
||||
"/usr/bin/env",
|
||||
"sh",
|
||||
"-c",
|
||||
]).args(command);
|
||||
cmd
|
||||
}
|
||||
Terminal::Kitty => {
|
||||
let mut cmd = Command::new("kitty");
|
||||
cmd.args([
|
||||
"/usr/bin/env",
|
||||
"sh",
|
||||
"-c",
|
||||
]).args(command);
|
||||
cmd
|
||||
}
|
||||
Terminal::LXTerminal => {
|
||||
let mut cmd = Command::new("lxterminal");
|
||||
cmd.args([
|
||||
"-e",
|
||||
"/usr/bin/env",
|
||||
"sh",
|
||||
"-c",
|
||||
]).args(command);
|
||||
cmd
|
||||
}
|
||||
Terminal::Tilix => {
|
||||
let mut cmd = Command::new("tilix");
|
||||
cmd.args([
|
||||
"-e",
|
||||
"/usr/bin/env",
|
||||
"sh",
|
||||
"-c",
|
||||
]).args(command);
|
||||
cmd
|
||||
}
|
||||
Terminal::DeepinTerminal => {
|
||||
let mut cmd = Command::new("deepin-terminal");
|
||||
cmd.args([
|
||||
"-e",
|
||||
"/usr/bin/env",
|
||||
"sh",
|
||||
"-c",
|
||||
]).args(command);
|
||||
cmd
|
||||
}
|
||||
Terminal::CoolRetroTerm => {
|
||||
let mut cmd = Command::new("cool-retro-term");
|
||||
cmd.args([
|
||||
"-e",
|
||||
"/usr/bin/env",
|
||||
"sh",
|
||||
"-c",
|
||||
]).args(command);
|
||||
cmd
|
||||
}
|
||||
Terminal::Alacritty => {
|
||||
let mut cmd = Command::new("alacritty");
|
||||
cmd.args([
|
||||
"-e",
|
||||
"/usr/bin/env",
|
||||
"sh",
|
||||
"-c",
|
||||
]).args(command);
|
||||
cmd
|
||||
}
|
||||
}
|
||||
}
|
||||
//endregion
|
||||
}
|
||||
|
||||
/**
|
||||
Checks if terminals are installed by checking if they respond to commands.
|
||||
|
||||
## How it works
|
||||
Probes a list of popular terminals and checks if they return an error when calling their `--version` or similar command line flag.
|
||||
|
||||
## Options
|
||||
* `return_immediately`: [`bool`]: Return as soon as one terminal is found.
|
||||
|
||||
## Returns
|
||||
A vector containing a list of terminals that should work.
|
||||
|
||||
## Commands
|
||||
| Terminal | Command to check if installed |
|
||||
|----------------|-------------------------------|
|
||||
| CMD | `cmd /?` |
|
||||
| GNOMETerminal | `gnome-terminal --version` |
|
||||
| GNOMEConsole | `kgx --version` |
|
||||
| Konsole | `konsole --version` |
|
||||
| Xfce4Terminal | `xfce4-terminal --version` |
|
||||
| Terminator | `terminator --version` |
|
||||
| Terminology | `terminology --version` |
|
||||
| XTerm | `xterm -v` |
|
||||
| Kitty | `kitty --version` |
|
||||
| LXTerminal | `lxterminal --version` |
|
||||
| Tilix | `tilix --version` |
|
||||
| DeepinTerminal | `deepin-terminal --version` |
|
||||
| CoolRetroTerm | `cool-retro-term --version` |
|
||||
| Alacritty | `alacritty --version` |
|
||||
|
||||
*/
|
||||
pub async fn get_installed_terminals(return_immediately: bool) -> Vec<Terminal> {
|
||||
#[cfg(windows)]
|
||||
// For Windows, only CMD is available.
|
||||
return vec!(Terminal::CMD);
|
||||
|
||||
let mut available_terminals: Vec<Terminal> = Vec::new();
|
||||
|
||||
for terminal in Terminal::iter() {
|
||||
// Probe terminal. If it doesn't raise an error, it is probably installed.
|
||||
if terminal.installed().await {
|
||||
if return_immediately {
|
||||
return vec![terminal];
|
||||
}
|
||||
available_terminals.push(terminal);
|
||||
}
|
||||
}
|
||||
|
||||
if available_terminals.is_empty() {
|
||||
eprintln!("No terminals were detected. Try installing one.");
|
||||
}
|
||||
|
||||
available_terminals
|
||||
}
|
||||
|
||||
/// Creates the DepotDownloader command necessary to download the requested manifest.
|
||||
fn create_depotdownloader_command(steam_download: &SteamDownload) -> Vec<String> {
|
||||
let output_dir = if cfg!(windows) {
|
||||
// In PowerShell, spaces can be escaped with a backtick.
|
||||
steam_download.output_path().replace(" ", "` ")
|
||||
} else {
|
||||
// In bash, spaces can be escaped with a backslash.
|
||||
steam_download.output_path().replace(" ", "\\ ")
|
||||
};
|
||||
|
||||
|
||||
if cfg!(not(windows)) {
|
||||
if steam_download.is_anonymous() {
|
||||
vec![format!(r#"./DepotDownloader -app {} -depot {} -manifest {} -dir {};echo Done!;sleep infinity"#, steam_download.app_id(), steam_download.depot_id(), steam_download.manifest_id(), output_dir)]
|
||||
} else {
|
||||
vec![format!(r#"./DepotDownloader -username {} -password {} -app {} -depot {} -manifest {} -dir {};echo Done!;sleep infinity"#, steam_download.username().clone().unwrap(), steam_download.password().clone().unwrap(), steam_download.app_id(), steam_download.depot_id(), steam_download.manifest_id(), output_dir)]
|
||||
}
|
||||
} else {
|
||||
if steam_download.is_anonymous() {
|
||||
vec![format!(r#".\DepotDownloader.exe -app {} -depot {} -manifest {} -dir {}"#, steam_download.app_id(), steam_download.depot_id(), steam_download.manifest_id(), output_dir)]
|
||||
} else {
|
||||
vec![format!(r#".\DepotDownloader.exe -username {} -password {} -app {} -depot {} -manifest {} -dir {}"#, steam_download.username().clone().unwrap(), steam_download.password().clone().unwrap(), steam_download.app_id(), steam_download.depot_id(), steam_download.manifest_id(), output_dir)]
|
||||
}
|
||||
}
|
||||
}
|
||||
@@ -1,17 +1,21 @@
|
||||
{
|
||||
"productName": "SteamDepotDownloaderGUI",
|
||||
"version": "3.0.0",
|
||||
"identifier": "net.00pium.depotdownloader",
|
||||
"version": "3.0.0-alpha.1",
|
||||
"identifier": "net.oopium.depotdownloader",
|
||||
"build": {
|
||||
"frontendDist": "../src"
|
||||
"beforeDevCommand": "pnpm dev",
|
||||
"devUrl": "http://localhost:1420",
|
||||
"beforeBuildCommand": "pnpm build",
|
||||
"frontendDist": "../dist"
|
||||
},
|
||||
"app": {
|
||||
"withGlobalTauri": true,
|
||||
"windows": [
|
||||
{
|
||||
"title": "steamdepotdownloadergui",
|
||||
"width": 800,
|
||||
"height": 600
|
||||
"title": "SteamDepotDownloaderGUI",
|
||||
"width": 445,
|
||||
"height": 650,
|
||||
"resizable": false
|
||||
}
|
||||
],
|
||||
"security": {
|
||||
|
||||
Reference in New Issue
Block a user