diff --git a/Cargo.lock b/Cargo.lock index df9a23e..c0b8c45 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -17,6 +17,56 @@ version = "2.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "320119579fcad9c21884f5c4861d16174d0e06250625266f50fe6898340abefa" +[[package]] +name = "anstream" +version = "0.6.19" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "301af1932e46185686725e0fad2f8f2aa7da69dd70bf6ecc44d6b703844a3933" +dependencies = [ + "anstyle", + "anstyle-parse", + "anstyle-query", + "anstyle-wincon", + "colorchoice", + "is_terminal_polyfill", + "utf8parse", +] + +[[package]] +name = "anstyle" +version = "1.0.11" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "862ed96ca487e809f1c8e5a8447f6ee2cf102f846893800b20cebdf541fc6bbd" + +[[package]] +name = "anstyle-parse" +version = "0.2.7" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4e7644824f0aa2c7b9384579234ef10eb7efb6a0deb83f9630a49594dd9c15c2" +dependencies = [ + "utf8parse", +] + +[[package]] +name = "anstyle-query" +version = "1.1.3" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "6c8bdeb6047d8983be085bab0ba1472e6dc604e7041dbf6fcd5e71523014fae9" +dependencies = [ + "windows-sys 0.59.0", +] + +[[package]] +name = "anstyle-wincon" +version = "3.0.9" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "403f75924867bb1033c59fbf0797484329750cfbe3c4325cd33127941fabc882" +dependencies = [ + "anstyle", + "once_cell_polyfill", + "windows-sys 0.59.0", +] + [[package]] name = "atomic-waker" version = "1.1.2" @@ -83,6 +133,52 @@ version = "1.0.1" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "9555578bc9e57714c812a1f84e4fc5b4d21fcb063490c624de019f7464c91268" +[[package]] +name = "clap" +version = "4.5.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "40b6887a1d8685cebccf115538db5c0efe625ccac9696ad45c409d96566e910f" +dependencies = [ + "clap_builder", + "clap_derive", +] + +[[package]] +name = "clap_builder" +version = "4.5.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "e0c66c08ce9f0c698cbce5c0279d0bb6ac936d8674174fe48f736533b964f59e" +dependencies = [ + "anstream", + "anstyle", + "clap_lex", + "strsim", +] + +[[package]] +name = "clap_derive" +version = "4.5.40" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "d2c7947ae4cc3d851207c1adb5b5e260ff0cca11446b1d6d1423788e442257ce" +dependencies = [ + "heck", + "proc-macro2", + "quote", + "syn", +] + +[[package]] +name = "clap_lex" +version = "0.7.5" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b94f61472cee1439c0b966b47e3aca9ae07e45d070759512cd390ea2bebc6675" + +[[package]] +name = "colorchoice" +version = "1.0.4" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "b05b61dc5112cbb17e4b6cd61790d9845d13888356391624cbe7e41efeac1e75" + [[package]] name = "core-foundation" version = "0.9.4" @@ -294,6 +390,12 @@ version = "0.15.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "5971ac85611da7067dbfcabef3c70ebb5606018acd9e2a3903a0da507521e0d5" +[[package]] +name = "heck" +version = "0.5.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "2304e00983f87ffb38b55b444b5e3b60a884b5d30c0fca7d82fe33449bbe55ea" + [[package]] name = "http" version = "1.3.1" @@ -545,6 +647,12 @@ dependencies = [ "serde", ] +[[package]] +name = "is_terminal_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7943c866cc5cd64cbc25b2e01621d07fa8eb2a1a23160ee81ce38704e97b8ecf" + [[package]] name = "itoa" version = "1.0.15" @@ -659,6 +767,12 @@ version = "1.21.3" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "42f5e15c9953c5e4ccceeb2e7382a716482c34515315f7b03532b8b4e8393d2d" +[[package]] +name = "once_cell_polyfill" +version = "1.70.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "a4895175b425cb1f87721b59f0f286c2092bd4af812243672510e1ac53e2e0ad" + [[package]] name = "openssl" version = "0.10.73" @@ -850,6 +964,7 @@ dependencies = [ name = "rust_elaborator" version = "0.1.0" dependencies = [ + "clap", "csv", "fuzzy-matcher", "reqwest", @@ -1059,6 +1174,12 @@ version = "1.2.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a8f112729512f8e442d81f95a8a7ddf2b7c6b8a1a6f509a95864142b30cab2d3" +[[package]] +name = "strsim" +version = "0.11.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "7da8b5736845d9f2fcb837ea5d9e2628564b3b043a70948a3f0b778838c5fb4f" + [[package]] name = "subtle" version = "2.6.1" @@ -1330,6 +1451,12 @@ version = "1.0.4" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b6c140620e7ffbb22c2dee59cafe6084a59b5ffc27a8859a5f0d494b5d52b6be" +[[package]] +name = "utf8parse" +version = "0.2.2" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "06abde3611657adf66d383f00b093d7faecc7fa57071cce2578660c9f1010821" + [[package]] name = "vcpkg" version = "0.2.15" diff --git a/Cargo.toml b/Cargo.toml index 0c7c599..cb8181a 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -4,6 +4,7 @@ version = "0.1.0" edition = "2024" [dependencies] +clap = { version = "4.5.40", features = ["derive"] } csv = "1.3.1" fuzzy-matcher = { version = "0.3.7", features = ["compact"] } reqwest = { version = "0.12.20", features = ["json"] } diff --git a/README.md b/README.md index 35b228e..202f619 100644 --- a/README.md +++ b/README.md @@ -45,3 +45,9 @@ Uno, where `title` can be anything. Capitalization does not matter. Additional columns will not be present in `out.csv`. + +If you have an existing `out.csv`, you can add new rows and avoid recalling the rows that are already filled in with the flag `--mode expand`. + +`cat out.csv | nix run . -- --mode expand` + +This will only check rows that have a) a blank second column or b) NOT_FOUND in the second column. diff --git a/flake.lock b/flake.lock index a1462dc..f4e0d94 100644 --- a/flake.lock +++ b/flake.lock @@ -2,7 +2,9 @@ "nodes": { "naersk": { "inputs": { - "nixpkgs": "nixpkgs" + "nixpkgs": [ + "nixpkgs" + ] }, "locked": { "lastModified": 1745925850, @@ -20,27 +22,11 @@ }, "nixpkgs": { "locked": { - "lastModified": 1750215678, - "narHash": "sha256-Rc/ytpamXRf6z8UA2SGa4aaWxUXRbX2MAWIu2C8M+ok=", + "lastModified": 1750776420, + "narHash": "sha256-/CG+w0o0oJ5itVklOoLbdn2dGB0wbZVOoDm4np6w09A=", "owner": "NixOS", "repo": "nixpkgs", - "rev": "5395fb3ab3f97b9b7abca147249fa2e8ed27b192", - "type": "github" - }, - "original": { - "owner": "NixOS", - "ref": "nixpkgs-unstable", - "repo": "nixpkgs", - "type": "github" - } - }, - "nixpkgs_2": { - "locked": { - "lastModified": 1750134718, - "narHash": "sha256-v263g4GbxXv87hMXMCpjkIxd/viIF7p3JpJrwgKdNiI=", - "owner": "NixOS", - "repo": "nixpkgs", - "rev": "9e83b64f727c88a7711a2c463a7b16eedb69a84c", + "rev": "30a61f056ac492e3b7cdcb69c1e6abdcf00e39cf", "type": "github" }, "original": { @@ -52,7 +38,7 @@ "root": { "inputs": { "naersk": "naersk", - "nixpkgs": "nixpkgs_2" + "nixpkgs": "nixpkgs" } } }, diff --git a/flake.nix b/flake.nix index d870fa3..18ee5f3 100644 --- a/flake.nix +++ b/flake.nix @@ -1,7 +1,10 @@ { inputs = { nixpkgs.url = "nixpkgs/nixos-unstable"; - naersk.url = github:nix-community/naersk; + naersk = { + url = "github:nix-community/naersk"; + inputs.nixpkgs.follows = "nixpkgs"; + }; }; outputs = { nixpkgs, @@ -11,7 +14,11 @@ system = "x86_64-linux"; pkgs = nixpkgs.legacyPackages.${system}; in { - packages.${system}.default = pkgs.callPackage ./package.nix {naersk = pkgs.callPackage naersk {};}; + packages.${system} = { + default = pkgs.callPackage ./package.nix { + naersk = pkgs.callPackage naersk {}; + }; + }; # nixosModules.${system}.default = ./module.nix; }; } diff --git a/package.nix b/package.nix index e19bc78..b6c6453 100644 --- a/package.nix +++ b/package.nix @@ -1,7 +1,6 @@ { openssl, pkg-config, - stdenv, naersk, ... }: @@ -10,11 +9,6 @@ naersk.buildPackage { src = ./.; buildInputs = [openssl]; nativeBuildInputs = [pkg-config]; - # configurePhase = ''''; - # buildPhase = ''''; - # installPhase = '' - # install -Dm775 ./target/release/rust_elaborator $out/bin/rust_elaborator - # ''; meta = { mainProgram = "rust_elaborator"; homepage = "https://mtgmonkey.net"; diff --git a/src/lib.rs b/src/lib.rs index 8523265..855b30c 100644 --- a/src/lib.rs +++ b/src/lib.rs @@ -1,7 +1,13 @@ -use reqwest::Error; -use reqwest::header::USER_AGENT; +use clap::Parser; use serde::{Deserialize, Serialize}; +#[derive(Parser, Debug)] +#[command(version, about, long_about = None)] +pub struct Args { + #[arg(short, long, default_value_t = ("elaborate".to_string()))] + pub mode: String, +} + #[derive(Debug, Deserialize, Serialize)] pub struct Id_search_results { pub boardgame: Boardgame, diff --git a/src/main.rs b/src/main.rs index 57109ba..027a218 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,3 +1,4 @@ +use clap::Parser; use reqwest::header::USER_AGENT; use rust_elaborator::*; use std::io; @@ -6,7 +7,12 @@ use std::io::prelude::*; #[tokio::main] async fn main() -> Result<(), reqwest::Error> { println!("Welcome to rust_elaborator!"); - write_csv().await; + let args = Args::parse(); + match args.mode.as_str() { + "elaborate" => make_out_from_in().await, + "expand" => make_out_from_out().await, + _ => panic!(), + }; Ok(()) } @@ -130,31 +136,7 @@ fn find_best_boardgame( ) } -fn find_best_match(name: String, mut names: Vec<&String>) -> (String, i32) { - use fuzzy_matcher::FuzzyMatcher; - let matcher = fuzzy_matcher::skim::SkimMatcherV2::default(); - names.sort_unstable_by(|a, b| { - matcher - .fuzzy_match(a, &name) - .cmp(&matcher.fuzzy_match(b, &name)) - }); - ( - names[0].to_string(), - matcher.fuzzy_match(&names[0], &name).unwrap(), - ) -} - -fn read_csv() -> Result<(), Box> { - let mut reader = csv::Reader::from_reader(io::stdin()); - for result in reader.records() { - let record = result.unwrap(); - let game = &record[0]; - println!("Game: {}", game); - } - Ok(()) -} - -async fn write_csv() -> Result<(), Box> { +async fn make_out_from_in() -> Result<(), Box> { use std::fs::File; use std::io::prelude::*; let mut out = File::create("out.csv").unwrap(); @@ -179,32 +161,32 @@ async fn write_csv() -> Result<(), Box> { let boardgame = get_boardgame_from_name(&client, game.to_string()).await; match boardgame { Some(boardgame) => { - let minplayers = if (boardgame.minplayers != 0) { + let minplayers = if boardgame.minplayers != 0 { boardgame.minplayers.to_string() } else { "".to_string() }; - let maxplayers = if (boardgame.maxplayers != 0) { + let maxplayers = if boardgame.maxplayers != 0 { boardgame.maxplayers.to_string() } else { "".to_string() }; - let playingtime = if (boardgame.playingtime != 0) { + let playingtime = if boardgame.playingtime != 0 { boardgame.playingtime.to_string() } else { "".to_string() }; - let minplaytime = if (boardgame.minplaytime != 0) { + let minplaytime = if boardgame.minplaytime != 0 { boardgame.minplaytime.to_string() } else { "".to_string() }; - let maxplaytime = if (boardgame.maxplaytime != 0) { + let maxplaytime = if boardgame.maxplaytime != 0 { boardgame.maxplaytime.to_string() } else { "".to_string() }; - let age = if (boardgame.age != 0) { + let age = if boardgame.age != 0 { boardgame.age.to_string() } else { "".to_string() @@ -233,3 +215,89 @@ async fn write_csv() -> Result<(), Box> { } Ok(()) } + +async fn make_out_from_out() -> Result<(), Box> { + use std::fs::File; + let mut out = File::create("out.csv").unwrap(); + let mut writer = csv::Writer::from_writer(out); + let mut reader = csv::Reader::from_reader(io::stdin()); + writer + .write_record(&[ + "title", + "foundtitle", + "minplayers", + "maxplayers", + "playingtime", + "minplaytime", + "maxplaytime", + "age", + ]) + .unwrap(); + let client = reqwest::Client::new(); + for result in reader.records() { + let record = result.unwrap(); + let title = &record[0]; + let foundtitle = &record[1]; + if foundtitle == "" || foundtitle == "NOT_FOUND" { + let boardgame = get_boardgame_from_name(&client, title.to_string()).await; + match boardgame { + Some(boardgame) => { + let minplayers = if boardgame.minplayers != 0 { + boardgame.minplayers.to_string() + } else { + "".to_string() + }; + let maxplayers = if boardgame.maxplayers != 0 { + boardgame.maxplayers.to_string() + } else { + "".to_string() + }; + let playingtime = if boardgame.playingtime != 0 { + boardgame.playingtime.to_string() + } else { + "".to_string() + }; + let minplaytime = if boardgame.minplaytime != 0 { + boardgame.minplaytime.to_string() + } else { + "".to_string() + }; + let maxplaytime = if boardgame.maxplaytime != 0 { + boardgame.maxplaytime.to_string() + } else { + "".to_string() + }; + let age = if boardgame.age != 0 { + boardgame.age.to_string() + } else { + "".to_string() + }; + writer + .write_record(&[ + title, + get_name_from_name(&client, title.to_string()) + .await + .unwrap() + .as_str(), + minplayers.as_str(), + maxplayers.as_str(), + playingtime.as_str(), + minplaytime.as_str(), + maxplaytime.as_str(), + age.as_str(), + ]) + .unwrap() + } + None => writer + .write_record(&[title, "NOT_FOUND", "", "", "", "", "", ""]) + .unwrap(), + }; + } else { + writer.write_record(&[ + &record[0], &record[1], &record[2], &record[3], &record[4], &record[5], &record[6], + &record[7], + ]); + }; + } + Ok(()) +}