Skip to content

Commit

Permalink
remove unwraps, rename app-id to name-of and add id-of, spinners
Browse files Browse the repository at this point in the history
  • Loading branch information
xor-bits committed Mar 31, 2024
1 parent c8eac54 commit 3a16003
Show file tree
Hide file tree
Showing 8 changed files with 1,077 additions and 636 deletions.
1,084 changes: 680 additions & 404 deletions Cargo.lock

Large diffs are not rendered by default.

21 changes: 13 additions & 8 deletions Cargo.toml
Original file line number Diff line number Diff line change
@@ -1,29 +1,34 @@
[package]
name = "vapour"
authors = ["Eemeli Lehtonen"]
version = "0.1.0"
version = "0.2.0"
edition = "2021"

# See more keys and their definitions at https://doc.rust-lang.org/cargo/reference/manifest.html

[dependencies]
anyhow = "1.0"
directories = "5.0"
clap = { version = "4.2", features = ["derive", "color"] }
clap_complete = "4.2"
serde = { version = "1.0", features = ["derive"] }
serde_json = "1.0"
reqwest = { version = "0.11", features = ["blocking", "json"] }
tracing = "0.1"
reqwest = { version = "0.12", features = ["blocking", "json", "stream"] }
tracing-subscriber = "0.3"
owo-colors = "3.5"
once_cell = "1.17"
bincode = "1.3"
owo-colors = "4.0"
regex = "1.8"
is-terminal = "0.4"
sled = "0.34"
indicatif = "0.17"
tokio = { version = "1.37", features = ["rt", "macros"] }

[dev-dependencies]
insta = "1.29"

[build-dependencies]
# clap = { version = "4.2", features = ["derive", "color"] }
# clap_complete = "4.2"

[profile.dev]
opt-level = 1

[profile.dev.package."*"]
opt-level = 3
30 changes: 15 additions & 15 deletions flake.lock

Some generated files are not rendered by default. Learn more about how customized files appear on GitHub.

14 changes: 9 additions & 5 deletions flake.nix
Original file line number Diff line number Diff line change
@@ -1,10 +1,10 @@
{
description = "vapour - general purpose cli tool for Steam related tasks";
description = "vapour - general purpose cli tool for Steam related tasks";

inputs = {
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
nixpkgs.url = "github:NixOS/nixpkgs/nixos-unstable";
rust-overlay.url = "github:oxalica/rust-overlay";
flake-utils.url = "github:numtide/flake-utils";
flake-utils.url = "github:numtide/flake-utils";
};

outputs = { nixpkgs, rust-overlay, flake-utils, ... }:
Expand All @@ -20,14 +20,18 @@
};
in
{
devShells.default = pkgs.mkShell {
# `nix develop`
devShells.default = pkgs.mkShell rec {
buildInputs = with pkgs; [
pkg-config
openssl
rust-bin.nightly.latest.default
];

LD_LIBRARY_PATH = "${pkgs.lib.makeLibraryPath buildInputs}";
};

# `nix build`
packages.default = rustPlatform.buildRustPackage {
name = "vapour";

Expand All @@ -44,7 +48,7 @@
openssl
];

RUST_BACKTRACE=1;
RUST_BACKTRACE = 1;
};
}
);
Expand Down
30 changes: 23 additions & 7 deletions src/cli.rs
Original file line number Diff line number Diff line change
Expand Up @@ -6,38 +6,54 @@ use clap_complete::Shell;
#[derive(Debug, Clone, Parser)]
#[command(author, version, about, long_about = None)]
pub enum CliArgs {
/// Update appid database
Update,

/// Translate appid to app name
AppId(CliAppId),
NameOf(CliNameOf),

/// Get appids of games
IdOf(CliIdOf),

/// Get Proton prefix locations for games
/// Get Proton prefix locations of installed games
CompatData(CliCompatData),

/// Generate shell completions
Completions(CliCompletions),
}

#[derive(Debug, Clone, Copy, Args)]
pub struct CliAppId {
pub struct CliNameOf {
/// steam_appid
pub app_id: u32,
}

#[derive(Debug, Clone, Args)]
pub struct CliCompatData {
pub struct CliIdOf {
/// Make the regex case sensitive, by default it isn't
#[clap(short, long)]
pub case_sensitive: bool,

/// Sort the output by game name
/// Only include installed games
#[clap(short, long)]
pub installed: bool,

/// Regex pattern for game names
pub regex: String,
}

#[derive(Debug, Clone, Args)]
pub struct CliCompatData {
/// Make the regex case sensitive, by default it isn't
#[clap(short, long)]
pub sort: bool,
pub case_sensitive: bool,

/// basically appends "pfx/drive_c" to results
#[clap(short, long)]
pub drive_c: bool,

/// Regex pattern for game names
pub regex: Option<String>,
pub regex: String,
}

#[derive(Debug, Clone, Args)]
Expand Down
114 changes: 114 additions & 0 deletions src/db.rs
Original file line number Diff line number Diff line change
@@ -0,0 +1,114 @@
use std::{fs, time::Duration};

use anyhow::{anyhow, Result};
use directories::ProjectDirs;
use serde::Deserialize;
use sled::Tree;

//

pub async fn update_appids(appids: &Tree) -> Result<()> {
let raw = download_database()
.await
.map_err(|err| anyhow!("Failed to download the appid database: {err}"))?;

let spinner = indicatif::ProgressBar::new_spinner().with_message("Updating database");
spinner.enable_steady_tick(Duration::from_millis(100));

appids.clear()?;
for app in raw.applist.apps {
appids.insert(app.appid.to_le_bytes(), app.name.as_bytes())?;
}

spinner.finish_with_message("Finished updating database");

Ok(())
}

pub async fn open_db() -> Result<Tree> {
let spinner = indicatif::ProgressBar::new_spinner().with_message("Opening database");
spinner.enable_steady_tick(Duration::from_millis(100));

let dirs = ProjectDirs::from("app", "xor-bits", "vapour")
.ok_or_else(|| anyhow!("No valid home directory found"))?;

fs::create_dir_all(dirs.cache_dir())
.map_err(|err| anyhow!("Invalid cache directory: {err}"))?;

let db = sled::open(dirs.cache_dir().join("vapour.db"))
.map_err(|err| anyhow!("Invalid database: {err}"))?;

let appids = db.open_tree("appids")?;

spinner.finish_with_message("Finished opening database");

// initial download of the appid database
if db.insert("updated", "")?.is_none() {
update_appids(&appids).await?;
}

Ok(appids)
}

//

#[derive(Deserialize)]
struct RawData {
applist: RawApplist,
}

#[derive(Deserialize)]
struct RawApplist {
apps: Vec<RawApp>,
}

#[derive(Deserialize)]
struct RawApp {
appid: u32,
name: String,
}

//

async fn download_database() -> Result<RawData> {
const URL: &str = "https://api.steampowered.com/ISteamApps/GetAppList/v2/";

let resp = reqwest::get(URL).await?;

let spinner = indicatif::ProgressBar::new_spinner()
.with_message(format!("Downloading appid list from {URL}"));
spinner.enable_steady_tick(Duration::from_millis(100));

let json = resp.json().await;

spinner.finish_with_message(format!("Finished downloading appid list from {URL}"));
Ok(json?)

// TODO: progress bar
// let Some(total) = resp.content_length() else {
// // no size -> no loading bar

// };

// let bar = indicatif::ProgressBar::new(total);
// bar.set_message(format!("Downloading appid list from {URL}"));

// let mut stream = resp.bytes_stream();
// let mut result = vec![];
// let mut downloaded = 0;

// while let Some(chunk) = stream.next().await {
// let chunk = chunk?;
// result.extend_from_slice(chunk.as_ref());
// downloaded = total.min(downloaded + chunk.len() as u64);
// bar.set_position(downloaded);

// tokio::time::sleep(tokio::time::Duration::from_millis(1000)).await;
// }

// bar.finish_with_message("Downloaded appid list");

// let result: RawData = serde_json::de::from_slice(&result)?;

// Ok(result)
}
Loading

0 comments on commit 3a16003

Please sign in to comment.