mirror of
https://github.com/djibux/BoilR.git
synced 2026-09-01 05:53:41 +02:00
Add support for legendary games
This commit is contained in:
Generated
+6
-2
@@ -837,7 +837,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "steam_shortcuts_util"
|
name = "steam_shortcuts_util"
|
||||||
version = "1.0.0"
|
version = "1.1.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "d8c2fce148525a785a93daaf7b41855fa1a2ba05052bab74f647b56256b2d3a8"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"ascii",
|
"ascii",
|
||||||
"crc32fast",
|
"crc32fast",
|
||||||
@@ -847,7 +849,9 @@ dependencies = [
|
|||||||
|
|
||||||
[[package]]
|
[[package]]
|
||||||
name = "steamgriddb_api"
|
name = "steamgriddb_api"
|
||||||
version = "0.1.3"
|
version = "0.2.0"
|
||||||
|
source = "registry+https://github.com/rust-lang/crates.io-index"
|
||||||
|
checksum = "49989dd0a9cb16bc02ea1939b513e310fcdbc31d52981d8c70bcb86a23b12d5f"
|
||||||
dependencies = [
|
dependencies = [
|
||||||
"reqwest",
|
"reqwest",
|
||||||
"serde",
|
"serde",
|
||||||
|
|||||||
+2
-2
@@ -6,8 +6,8 @@ edition = "2018"
|
|||||||
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html
|
||||||
|
|
||||||
[dependencies]
|
[dependencies]
|
||||||
steam_shortcuts_util={version="*", path="C:/src/Rust/steam_shortcuts_util"}
|
steam_shortcuts_util="1.1.0"
|
||||||
steamgriddb_api={version="*", path="C:/src/Rust/steamgriddb_api"}
|
steamgriddb_api="0.2,0"
|
||||||
serde={version="*", features=["derive"]}
|
serde={version="*", features=["derive"]}
|
||||||
serde_json="*"
|
serde_json="*"
|
||||||
tokio = { version = "1.11.0", features = ["full"] }
|
tokio = { version = "1.11.0", features = ["full"] }
|
||||||
|
|||||||
@@ -9,7 +9,6 @@ pub fn get_egs_manifests() -> Result<Vec<ManifestItem>, Box<dyn Error>> {
|
|||||||
let manifest_dir_path = get_manifest_dir_path()?;
|
let manifest_dir_path = get_manifest_dir_path()?;
|
||||||
let manifest_dir_result = std::fs::read_dir(&manifest_dir_path);
|
let manifest_dir_result = std::fs::read_dir(&manifest_dir_path);
|
||||||
if let Err(err) = manifest_dir_result {
|
if let Err(err) = manifest_dir_result {
|
||||||
//TODO make a new error type here instead
|
|
||||||
println!("Could not find manifest directory: {}", manifest_dir_path);
|
println!("Could not find manifest directory: {}", manifest_dir_path);
|
||||||
return Result::Err(Box::new(err));
|
return Result::Err(Box::new(err));
|
||||||
}
|
}
|
||||||
|
|||||||
@@ -1,5 +1,5 @@
|
|||||||
|
|
||||||
use serde::{Deserialize, Serialize};
|
use serde::{Deserialize, Serialize};
|
||||||
|
use steam_shortcuts_util::{Shortcut, shortcut::ShortcutOwned};
|
||||||
|
|
||||||
#[derive(Serialize, Deserialize, Debug, Clone)]
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
pub struct ManifestItem {
|
pub struct ManifestItem {
|
||||||
@@ -18,3 +18,31 @@ pub struct ManifestItem {
|
|||||||
#[serde(alias = "AppName")]
|
#[serde(alias = "AppName")]
|
||||||
pub app_name: String,
|
pub app_name: String,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
impl From<&ManifestItem> for ShortcutOwned {
|
||||||
|
fn from(manifest: &ManifestItem) -> Self {
|
||||||
|
let exe = format!(
|
||||||
|
"\"{}\\{}\"",
|
||||||
|
manifest.install_location, manifest.launch_executable
|
||||||
|
);
|
||||||
|
let mut start_dir = manifest.install_location.clone();
|
||||||
|
if !manifest.install_location.starts_with("\"") {
|
||||||
|
start_dir = format!("\"{}\"", manifest.install_location);
|
||||||
|
}
|
||||||
|
let shortcut = Shortcut::new(
|
||||||
|
0,
|
||||||
|
manifest.display_name.as_str(),
|
||||||
|
exe.as_str(),
|
||||||
|
start_dir.as_str(),
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
);
|
||||||
|
let mut owned_shortcut = shortcut.to_owned();
|
||||||
|
owned_shortcut.tags.push("EGS".to_owned());
|
||||||
|
owned_shortcut.tags.push("Ready TO Play".to_owned());
|
||||||
|
owned_shortcut.tags.push("Installed".to_owned());
|
||||||
|
|
||||||
|
owned_shortcut
|
||||||
|
}
|
||||||
|
}
|
||||||
|
|||||||
@@ -0,0 +1,14 @@
|
|||||||
|
use super::legendary_game::LegendaryGame;
|
||||||
|
use serde_json::from_str;
|
||||||
|
use std::process::Command;
|
||||||
|
use std::{error::Error};
|
||||||
|
|
||||||
|
pub fn get_legendary_games() -> Result<Vec<LegendaryGame>, Box<dyn Error>> {
|
||||||
|
let legendary_command = Command::new("legendary")
|
||||||
|
.arg("list-installed")
|
||||||
|
.arg("--json")
|
||||||
|
.output()?;
|
||||||
|
let json = String::from_utf8_lossy(&legendary_command.stdout);
|
||||||
|
let legendary_ouput = from_str(&json)?;
|
||||||
|
Ok(legendary_ouput)
|
||||||
|
}
|
||||||
@@ -0,0 +1,38 @@
|
|||||||
|
use serde::{Deserialize, Serialize};
|
||||||
|
use steam_shortcuts_util::{shortcut::ShortcutOwned, Shortcut};
|
||||||
|
|
||||||
|
#[derive(Serialize, Deserialize, Debug, Clone)]
|
||||||
|
pub struct LegendaryGame {
|
||||||
|
pub app_name: String,
|
||||||
|
pub can_run_offline: bool,
|
||||||
|
pub title: String,
|
||||||
|
pub is_dlc: bool,
|
||||||
|
pub install_path: String,
|
||||||
|
pub executable: String,
|
||||||
|
}
|
||||||
|
|
||||||
|
impl From<&LegendaryGame> for ShortcutOwned {
|
||||||
|
fn from(game: &LegendaryGame) -> Self {
|
||||||
|
let exe = format!("\"{}\\{}\"", game.install_path, game.executable);
|
||||||
|
let launch = format!("legendary launch {}", game.app_name);
|
||||||
|
let mut start_dir = game.install_path.clone();
|
||||||
|
if !game.install_path.starts_with("\"") {
|
||||||
|
start_dir = format!("\"{}\"", game.install_path);
|
||||||
|
}
|
||||||
|
let shortcut = Shortcut::new(
|
||||||
|
0,
|
||||||
|
game.title.as_str(),
|
||||||
|
launch.as_str(),
|
||||||
|
start_dir.as_str(),
|
||||||
|
exe.as_str(),
|
||||||
|
"",
|
||||||
|
"",
|
||||||
|
);
|
||||||
|
let mut owned_shortcut = shortcut.to_owned();
|
||||||
|
owned_shortcut.tags.push("Legendary".to_owned());
|
||||||
|
owned_shortcut.tags.push("Ready TO Play".to_owned());
|
||||||
|
owned_shortcut.tags.push("Installed".to_owned());
|
||||||
|
|
||||||
|
owned_shortcut
|
||||||
|
}
|
||||||
|
}
|
||||||
@@ -0,0 +1,5 @@
|
|||||||
|
mod legendary_game;
|
||||||
|
mod get_legendary_games;
|
||||||
|
|
||||||
|
pub use get_legendary_games::*;
|
||||||
|
pub use legendary_game::*;
|
||||||
+63
-38
@@ -8,6 +8,8 @@ use std::{
|
|||||||
};
|
};
|
||||||
mod cached_search;
|
mod cached_search;
|
||||||
mod egs;
|
mod egs;
|
||||||
|
mod legendary;
|
||||||
|
use crate::legendary::get_legendary_games;
|
||||||
use egs::{get_egs_manifests, ManifestItem};
|
use egs::{get_egs_manifests, ManifestItem};
|
||||||
use std::error::Error;
|
use std::error::Error;
|
||||||
use steam_shortcuts_util::{
|
use steam_shortcuts_util::{
|
||||||
@@ -22,14 +24,10 @@ pub struct ShortcutInfo {
|
|||||||
pub shortcuts: Vec<ShortcutOwned>,
|
pub shortcuts: Vec<ShortcutOwned>,
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
fn get_shortcuts_for_user(user: &SteamUsersInfo) -> ShortcutInfo {
|
fn get_shortcuts_for_user(user: &SteamUsersInfo) -> ShortcutInfo {
|
||||||
let mut shortcuts = vec![];
|
let mut shortcuts = vec![];
|
||||||
let mut new_path = user.shortcut_path.clone();
|
let mut new_path = user.shortcut_path.clone();
|
||||||
if let Some(shortcut_path) = &user.shortcut_path {
|
if let Some(shortcut_path) = &user.shortcut_path {
|
||||||
// std::fs::remove_file(path)
|
|
||||||
//TODO remove unwrap
|
|
||||||
let content = std::fs::read(shortcut_path).unwrap();
|
let content = std::fs::read(shortcut_path).unwrap();
|
||||||
shortcuts = parse_shortcuts(content.as_slice())
|
shortcuts = parse_shortcuts(content.as_slice())
|
||||||
.unwrap()
|
.unwrap()
|
||||||
@@ -60,27 +58,74 @@ fn get_shortcuts_for_user(user: &SteamUsersInfo) -> ShortcutInfo {
|
|||||||
|
|
||||||
#[tokio::main]
|
#[tokio::main]
|
||||||
async fn main() -> Result<(), Box<dyn Error>> {
|
async fn main() -> Result<(), Box<dyn Error>> {
|
||||||
|
if !Path::new("auth_key.txt").exists() {
|
||||||
|
println!("File auth_key.txt not found, the file has been created, please get a key from https://www.steamgriddb.com/ and copy it into auth_key.txt");
|
||||||
|
File::create(Path::new("auth_key.txt"))?;
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
let auth_key = std::fs::read_to_string("auth_key.txt")?;
|
let auth_key = std::fs::read_to_string("auth_key.txt")?;
|
||||||
|
|
||||||
|
if auth_key.trim().is_empty() {
|
||||||
|
println!("File auth_key.txt is empty please get an API key from https://www.steamgriddb.com/ and paste it into auth_key.txt");
|
||||||
|
return Ok(());
|
||||||
|
}
|
||||||
|
|
||||||
let client = steamgriddb_api::Client::new(auth_key);
|
let client = steamgriddb_api::Client::new(auth_key);
|
||||||
let mut search = CachedSearch::new(&client);
|
let mut search = CachedSearch::new(&client);
|
||||||
|
|
||||||
let egs_manifests = get_egs_manifests()?;
|
#[cfg(target_os = "windows")]
|
||||||
let egs_shortcuts: Vec<ShortcutOwned> =
|
let egs_shortcuts = {
|
||||||
egs_manifests.iter().map(manifest_to_shortcut).collect();
|
let egs_manifests = match get_egs_manifests() {
|
||||||
|
Ok(manifests) => manifests,
|
||||||
|
Err(e) => {
|
||||||
|
println!("Error getting manifests: {}", e);
|
||||||
|
vec![]
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let egs_shortcuts: Vec<ShortcutOwned> = egs_manifests.iter().map(|f| f.into()).collect();
|
||||||
println!("Found {} installed EGS Games", egs_manifests.len());
|
println!("Found {} installed EGS Games", egs_manifests.len());
|
||||||
|
egs_shortcuts
|
||||||
|
};
|
||||||
|
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
let legendary_shortcuts = {
|
||||||
|
let legendary_games = match get_legendary_games() {
|
||||||
|
Ok(games) => games,
|
||||||
|
Err(e) => {
|
||||||
|
println!("Error getting legendary games: {}", e);
|
||||||
|
vec![]
|
||||||
|
}
|
||||||
|
};
|
||||||
|
let legendary_shortcuts: Vec<ShortcutOwned> =
|
||||||
|
legendary_games.iter().map(|f| f.into()).collect();
|
||||||
|
println!(
|
||||||
|
"Found {} installed Legendary Games",
|
||||||
|
legendary_shortcuts.len()
|
||||||
|
);
|
||||||
|
legendary_shortcuts
|
||||||
|
};
|
||||||
|
|
||||||
let userinfo_shortcuts = get_shortcuts_paths()?;
|
let userinfo_shortcuts = get_shortcuts_paths()?;
|
||||||
println!("Found {} user(s)", userinfo_shortcuts.len());
|
println!("Found {} user(s)", userinfo_shortcuts.len());
|
||||||
|
|
||||||
for user in userinfo_shortcuts.iter() {
|
for user in userinfo_shortcuts.iter() {
|
||||||
let shortcut_info = get_shortcuts_for_user(user);
|
let shortcut_info = get_shortcuts_for_user(user);
|
||||||
|
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
let new_user_shortcuts: Vec<&ShortcutOwned> = shortcut_info
|
let new_user_shortcuts: Vec<&ShortcutOwned> = shortcut_info
|
||||||
.shortcuts
|
.shortcuts
|
||||||
.iter()
|
.iter()
|
||||||
.filter(|user_shortcut| !user_shortcut.tags.contains(&"EGS".to_owned()))
|
.filter(|user_shortcut| !user_shortcut.tags.contains(&"EGS".to_owned()))
|
||||||
.chain(egs_shortcuts.iter())
|
.chain(egs_shortcuts.iter())
|
||||||
.collect();
|
.collect();
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
let new_user_shortcuts: Vec<&ShortcutOwned> = shortcut_info
|
||||||
|
.shortcuts
|
||||||
|
.iter()
|
||||||
|
.filter(|user_shortcut| !user_shortcut.tags.contains(&"Legendary".to_owned()))
|
||||||
|
.chain(legendary_shortcuts.iter())
|
||||||
|
.collect();
|
||||||
|
|
||||||
let shortcuts = new_user_shortcuts.iter().map(|f| f.borrow()).collect();
|
let shortcuts = new_user_shortcuts.iter().map(|f| f.borrow()).collect();
|
||||||
|
|
||||||
@@ -110,8 +155,6 @@ async fn main() -> Result<(), Box<dyn Error>> {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
|
|
||||||
let types = vec![ImageType::Logo, ImageType::Hero, ImageType::Grid];
|
let types = vec![ImageType::Logo, ImageType::Hero, ImageType::Grid];
|
||||||
for image_type in types {
|
for image_type in types {
|
||||||
let mut images_needed = shortcuts
|
let mut images_needed = shortcuts
|
||||||
@@ -180,7 +223,6 @@ impl ImageType {
|
|||||||
}
|
}
|
||||||
}
|
}
|
||||||
|
|
||||||
|
|
||||||
fn get_users_images(user: &SteamUsersInfo) -> Result<Vec<String>, Box<dyn Error>> {
|
fn get_users_images(user: &SteamUsersInfo) -> Result<Vec<String>, Box<dyn Error>> {
|
||||||
let grid_folder = Path::new(user.steam_user_data_folder.as_str()).join("config/grid");
|
let grid_folder = Path::new(user.steam_user_data_folder.as_str()).join("config/grid");
|
||||||
std::fs::create_dir_all(&grid_folder)?;
|
std::fs::create_dir_all(&grid_folder)?;
|
||||||
@@ -192,32 +234,6 @@ fn get_users_images(user: &SteamUsersInfo) -> Result<Vec<String>, Box<dyn Error>
|
|||||||
Ok(file_names)
|
Ok(file_names)
|
||||||
}
|
}
|
||||||
|
|
||||||
fn manifest_to_shortcut(manifest: &ManifestItem) -> ShortcutOwned {
|
|
||||||
let exe = format!(
|
|
||||||
"\"{}\\{}\"",
|
|
||||||
manifest.install_location, manifest.launch_executable
|
|
||||||
);
|
|
||||||
let mut start_dir = manifest.install_location.clone();
|
|
||||||
if !manifest.install_location.starts_with("\"") {
|
|
||||||
start_dir = format!("\"{}\"", manifest.install_location);
|
|
||||||
}
|
|
||||||
let shortcut = Shortcut::new(
|
|
||||||
0,
|
|
||||||
manifest.display_name.as_str(),
|
|
||||||
exe.as_str(),
|
|
||||||
start_dir.as_str(),
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
"",
|
|
||||||
);
|
|
||||||
let mut owned_shortcut = shortcut.to_owned();
|
|
||||||
owned_shortcut.tags.push("EGS".to_owned());
|
|
||||||
owned_shortcut.tags.push("Ready TO Play".to_owned());
|
|
||||||
owned_shortcut.tags.push("Installed".to_owned());
|
|
||||||
|
|
||||||
owned_shortcut
|
|
||||||
}
|
|
||||||
|
|
||||||
#[derive(Debug)]
|
#[derive(Debug)]
|
||||||
struct SteamFolderNotFound {
|
struct SteamFolderNotFound {
|
||||||
location_tried: String,
|
location_tried: String,
|
||||||
@@ -267,12 +283,21 @@ struct SteamUsersInfo {
|
|||||||
|
|
||||||
/// Get the paths to the steam users shortcuts (one for each user)
|
/// Get the paths to the steam users shortcuts (one for each user)
|
||||||
fn get_shortcuts_paths() -> Result<Vec<SteamUsersInfo>, Box<dyn Error>> {
|
fn get_shortcuts_paths() -> Result<Vec<SteamUsersInfo>, Box<dyn Error>> {
|
||||||
|
#[cfg(target_os = "windows")]
|
||||||
|
let path_string = {
|
||||||
let key = "PROGRAMFILES(X86)";
|
let key = "PROGRAMFILES(X86)";
|
||||||
let program_files = env::var(key)?;
|
let program_files = env::var(key)?;
|
||||||
let path_string = format!(
|
format!(
|
||||||
"{program_files}//Steam//userdata//",
|
"{program_files}//Steam//userdata//",
|
||||||
program_files = program_files
|
program_files = program_files
|
||||||
);
|
)
|
||||||
|
};
|
||||||
|
#[cfg(target_os = "linux")]
|
||||||
|
let path_string = {
|
||||||
|
let home = std::env::var("HOME")?;
|
||||||
|
format!("{}/.steam/steam/userdata/", home)
|
||||||
|
};
|
||||||
|
|
||||||
let user_data_path = Path::new(path_string.as_str());
|
let user_data_path = Path::new(path_string.as_str());
|
||||||
if !user_data_path.exists() {
|
if !user_data_path.exists() {
|
||||||
return Result::Err(Box::new(SteamFolderNotFound {
|
return Result::Err(Box::new(SteamFolderNotFound {
|
||||||
|
|||||||
Reference in New Issue
Block a user