Compare commits

..

3 Commits

Author SHA1 Message Date
bcf68c8332 Added some rofi stuff for easier & quicker interaction
Looking actually pretty okay!
2025-08-19 23:01:32 +01:00
3f4af21a93 Search with uppercase should work
I made the search string also lowercase
2025-08-19 22:12:18 +01:00
98af8885a6 Added searching by lower or card name
Also added help strings
2025-08-19 22:02:18 +01:00
4 changed files with 109 additions and 23 deletions

View File

@@ -0,0 +1,9 @@
#!/bin/bash
CARDS=$(/home/arthurr/code/mini_projects/scryfall_deser/target/debug/scryfall_deser $@)
SELECTION=$(rofi -dmenu <<< "$CARDS")
CARD_OUTPUT=$(/home/arthurr/code/mini_projects/scryfall_deser/target/debug/scryfall_deser --exact $SELECTION)
rofi -e "$CARD_OUTPUT"

View File

@@ -1,4 +1,5 @@
use rusqlite; use rusqlite;
use std::fmt;
use std::fs; use std::fs;
use std::path::PathBuf; use std::path::PathBuf;
use std::str::SplitWhitespace; use std::str::SplitWhitespace;
@@ -77,6 +78,22 @@ pub fn update_db_with_file(file: PathBuf) -> bool {
true true
} }
// unsure if this should be in this file...
impl fmt::Display for DbCard {
fn fmt(&self, f: &mut fmt::Formatter) -> fmt::Result {
match &self.mana_cost {
Some(mc) => writeln!(f, "{}\t{}", self.name, mc)?,
None => writeln!(f, "{}", self.name)?,
}
match &self.oracle_text {
Some(ot) => writeln!(f, "{}", ot)?,
None => (),
}
Ok(())
}
}
#[derive(Debug)] #[derive(Debug)]
pub struct DbCard { pub struct DbCard {
pub name: String, pub name: String,
@@ -88,18 +105,28 @@ pub struct DbCard {
pub scryfall_uri: String, pub scryfall_uri: String,
} }
pub fn get_card_by_name(name: &str) -> DbCard { pub enum GetNameType {
Name,
LowercaseName,
}
pub fn get_card_by_name(name: &str, name_type: GetNameType) -> Option<DbCard> {
let sqlite_file = get_local_data_sqlite_file(); let sqlite_file = get_local_data_sqlite_file();
let conn = rusqlite::Connection::open(sqlite_file).unwrap(); let conn = rusqlite::Connection::open(sqlite_file).unwrap();
let mut stmt = conn let sql = match name_type {
.prepare( GetNameType::Name => {
"SELECT name, type_line, oracle_text, power_toughness, loyalty, mana_cost, scryfall_uri "SELECT name, type_line, oracle_text, power_toughness, loyalty, mana_cost, scryfall_uri
FROM cards WHERE name = (?1)", FROM cards WHERE name = (?1)"
) }
.unwrap(); GetNameType::LowercaseName => {
"SELECT name, type_line, oracle_text, power_toughness, loyalty, mana_cost, scryfall_uri
FROM cards WHERE lowercase_name = (?1)"
}
};
let mut stmt = conn.prepare(sql).unwrap();
let mut rows = stmt.query([name]).unwrap(); let mut rows = stmt.query([name]).unwrap();
let card = match rows.next().unwrap() { match rows.next().unwrap() {
Some(row) => DbCard { Some(row) => Some(DbCard {
name: row.get(0).unwrap(), name: row.get(0).unwrap(),
type_line: row.get(1).unwrap(), type_line: row.get(1).unwrap(),
oracle_text: row.get(2).unwrap(), oracle_text: row.get(2).unwrap(),
@@ -107,12 +134,9 @@ pub fn get_card_by_name(name: &str) -> DbCard {
loyalty: row.get(4).unwrap(), loyalty: row.get(4).unwrap(),
mana_cost: row.get(5).unwrap(), mana_cost: row.get(5).unwrap(),
scryfall_uri: row.get(6).unwrap(), scryfall_uri: row.get(6).unwrap(),
}, }),
None => { None => None,
panic!("{} isn't a card that exists", name);
} }
};
card
} }
const CREATE_CARDS_TABLE_SQL: &str = " const CREATE_CARDS_TABLE_SQL: &str = "

View File

@@ -5,7 +5,10 @@ mod deser;
pub use crate::deser::ScryfallCard; pub use crate::deser::ScryfallCard;
mod db; mod db;
pub use db::{get_all_lowercase_card_names, get_card_by_name, init_db, update_db_with_file}; pub use db::{
get_all_card_names, get_all_lowercase_card_names, get_card_by_name, init_db,
update_db_with_file, GetNameType,
};
mod utils; mod utils;
pub use utils::get_local_cache_folder; pub use utils::get_local_cache_folder;

View File

@@ -4,14 +4,29 @@ use scryfall_deser::get_card_by_name;
use scryfall_deser::get_local_cache_folder; use scryfall_deser::get_local_cache_folder;
use scryfall_deser::init_db; use scryfall_deser::init_db;
use scryfall_deser::update_db_with_file; use scryfall_deser::update_db_with_file;
use scryfall_deser::GetNameType;
use textdistance::str::damerau_levenshtein; use textdistance::str::damerau_levenshtein;
#[derive(Parser, Debug)] #[derive(Parser, Debug)]
#[command(version, about, long_about = None)] #[command(version, about, long_about = None)]
struct Args { struct Args {
/// Download the latest bulk from Scryfall and update local db
#[arg(short, long)] #[arg(short, long)]
update: bool, update: bool,
remainder: Vec<String>, /// Search for the exact string
#[arg(short, long)]
exact: bool,
/// Text to search for card with
search_text: Vec<String>,
}
fn exact_search(search_strings: Vec<String>) {
let search_string = search_strings.join(" ");
let card = get_card_by_name(&search_string, GetNameType::Name);
if card.is_none() {
panic!("No card found with exact name of {}", search_string);
}
println!("{}", card.unwrap());
} }
fn main() { fn main() {
@@ -24,24 +39,59 @@ fn main() {
update_db_with_file(path); update_db_with_file(path);
return; return;
} }
let card_name = args.remainder; if args.search_text.is_empty() {
if card_name.is_empty() {
panic!("You need to put some card text to search"); panic!("You need to put some card text to search");
} }
let search_string = card_name.join(" ");
//dbg!(&search_string); if args.exact {
exact_search(args.search_text);
return;
}
let mut search_string = String::new();
for card in args.search_text {
search_string.push_str(&card.to_lowercase());
search_string.push_str(" ");
}
search_string.pop();
// This section should be replaced with a SQL command
let cards = get_all_lowercase_card_names(); let cards = get_all_lowercase_card_names();
//dbg!(&cards);
let mut matching_cards = Vec::new(); let mut matching_cards = Vec::new();
for card in cards { for card in cards {
if card.contains(&search_string) { if card.contains(&search_string) {
matching_cards.push(card.clone()); matching_cards.push(card.clone());
} }
} }
dbg!(&matching_cards);
if matching_cards.is_empty() { if matching_cards.is_empty() {
// Do some distance checking stuff // Do some distance checking stuff
} } else if matching_cards.len() == 1 {
//dbg!(matching_cards); let card = get_card_by_name(&matching_cards[0], GetNameType::LowercaseName);
let card = get_card_by_name("Black Lotus");
dbg!(card); dbg!(card);
} else {
for card in matching_cards {
println!(
"{}",
get_card_by_name(&card, GetNameType::LowercaseName)
.unwrap()
.name
);
}
// This will be the harder part I think
}
/* For testing - all seemed to work alright
let card = get_card_by_name("Black Lotus", GetNameType::Name);
dbg!(card);
let cards = get_all_card_names();
for card in cards {
let card = get_card_by_name(&card);
dbg!(&card);
if card.is_none() {
panic!("None card for {:?}", card);
}
}
*/
} }