Misc cleanup
ci/woodpecker/push/woodpecker Pipeline was successful Details

+ info now trys to find the "best match"
+ report_out_of_stock no longer matches all items with the same sub string
+ Added type to loc strings in the bot
+ clippy + fmt
main
Joey Hines 2022-01-08 16:05:56 -07:00
parent 5fcb021fe0
commit c3c3814d77
No known key found for this signature in database
GPG Key ID: 80F567B5C968F91B
11 changed files with 59 additions and 19 deletions

9
Cargo.lock generated
View File

@ -172,7 +172,7 @@ dependencies = [
"ansi_term", "ansi_term",
"atty", "atty",
"bitflags", "bitflags",
"strsim", "strsim 0.8.0",
"textwrap", "textwrap",
"unicode-width", "unicode-width",
"vec_map", "vec_map",
@ -431,6 +431,7 @@ dependencies = [
"serde 1.0.133", "serde 1.0.133",
"serde_json", "serde_json",
"simple_logger", "simple_logger",
"strsim 0.10.0",
"structopt", "structopt",
"tokio", "tokio",
"warp", "warp",
@ -1579,6 +1580,12 @@ version = "0.8.0"
source = "registry+https://github.com/rust-lang/crates.io-index" source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a" checksum = "8ea5119cdb4c55b55d432abb513a0429384878c15dde60cc77b1c99de1a95a6a"
[[package]]
name = "strsim"
version = "0.10.0"
source = "registry+https://github.com/rust-lang/crates.io-index"
checksum = "73473c0e59e6d5812c5dfe2a064a6444949f089e20eec9a2e5506596494e4623"
[[package]] [[package]]
name = "structopt" name = "structopt"
version = "0.3.25" version = "0.3.25"

View File

@ -19,6 +19,7 @@ log = "0.4.14"
rand = "0.8.4" rand = "0.8.4"
regex = "1.5.4" regex = "1.5.4"
chrono = { version = "0.4.19", features = ["serde"] } chrono = { version = "0.4.19", features = ["serde"] }
strsim = "0.10.0"
# Doing this for now, as there seems to be an issue with using timestamps # Doing this for now, as there seems to be an issue with using timestamps
[dependencies.simple_logger] [dependencies.simple_logger]

View File

@ -9,6 +9,7 @@ use geoffrey_models::models::player::Player;
use geoffrey_models::models::response::api_error::GeoffreyAPIError; use geoffrey_models::models::response::api_error::GeoffreyAPIError;
use geoffrey_models::models::CommandLevel; use geoffrey_models::models::CommandLevel;
use std::sync::Arc; use std::sync::Arc;
use strsim::normalized_damerau_levenshtein;
pub struct InfoCommand {} pub struct InfoCommand {}
@ -29,14 +30,24 @@ impl Command for InfoCommand {
} }
fn run_command(ctx: Arc<Context>, req: &Self::Req, _: Option<Player>) -> Result<Self::Resp> { fn run_command(ctx: Arc<Context>, req: &Self::Req, _: Option<Player>) -> Result<Self::Resp> {
let query = QueryBuilder::<LocationDb>::default().with_name_regex(&req.location_name)?; let query = QueryBuilder::<LocationDb>::default()
.with_name_regex_case_insensitive(&req.location_name)?;
let location = ctx let mut locations = ctx.db.run_query(query)?;
.db
.run_query(query)?
.pop()
.ok_or(GeoffreyAPIError::EntryNotFound)?;
Ok(load_location(&ctx.db, &location)?) if locations.is_empty() {
Err(GeoffreyAPIError::EntryNotFound)
} else {
locations.sort_by(|a, b| {
let a =
(normalized_damerau_levenshtein(&a.name, &req.location_name) * 1000.0) as u32;
let b =
(normalized_damerau_levenshtein(&b.name, &req.location_name) * 1000.0) as u32;
a.cmp(&b)
});
Ok(load_location(&ctx.db, &locations.pop().unwrap())?)
}
} }
} }

View File

@ -44,7 +44,9 @@ impl Command for ReportOutOfStock {
.ok_or(GeoffreyAPIError::EntryNotFound)?; .ok_or(GeoffreyAPIError::EntryNotFound)?;
if let LocationDataDb::Shop(shop_data) = &mut shop.loc_data { if let LocationDataDb::Shop(shop_data) = &mut shop.loc_data {
let filter = regex::Regex::new(&req.item_name) let filter = regex::RegexBuilder::new(&format!("^{}$", &req.item_name))
.case_insensitive(true)
.build()
.map_err(|e| GeoffreyAPIError::InvalidRegex(e.to_string()))?; .map_err(|e| GeoffreyAPIError::InvalidRegex(e.to_string()))?;
let updated_items: HashSet<ItemListing> = shop_data let updated_items: HashSet<ItemListing> = shop_data

View File

@ -45,7 +45,9 @@ impl Command for Restock {
.ok_or(GeoffreyAPIError::EntryNotFound)?; .ok_or(GeoffreyAPIError::EntryNotFound)?;
if let LocationDataDb::Shop(shop_data) = &mut shop.loc_data { if let LocationDataDb::Shop(shop_data) = &mut shop.loc_data {
let filter = regex::Regex::new(&req.item_name) let filter = regex::RegexBuilder::new(&req.item_name)
.case_insensitive(true)
.build()
.map_err(|e| GeoffreyAPIError::InvalidRegex(e.to_string()))?; .map_err(|e| GeoffreyAPIError::InvalidRegex(e.to_string()))?;
let updated_items: HashSet<ItemListing> = shop_data let updated_items: HashSet<ItemListing> = shop_data

View File

@ -64,10 +64,11 @@ impl BotCommand for FindCommand {
formatter formatter
.push("The following locations match '") .push("The following locations match '")
.push(&params.query) .push(&params.query)
.push("'"); .push("':")
.push_new_line();
for loc in &resp { for loc in &resp {
formatter.push_loc(loc).push_new_line().push_new_line(); formatter.push_loc(loc).push_new_line();
} }
formatter.build() formatter.build()

View File

@ -100,7 +100,6 @@ impl BotCommand for SetPortalCommand {
portal.x, portal.x,
portal.z portal.z
)) ))
.push_bold_safe(resp.name)
.push_line("") .push_line("")
.build() .build()
} }

View File

@ -1,6 +1,6 @@
use chrono::{Duration, Utc}; use chrono::{Duration, Utc};
use geoffrey_models::models::item::ItemListing; use geoffrey_models::models::item::ItemListing;
use geoffrey_models::models::locations::{Location, LocationData}; use geoffrey_models::models::locations::{Location, LocationData, LocationType};
use geoffrey_models::models::player::Player; use geoffrey_models::models::player::Player;
use geoffrey_models::models::settings::GeoffreySettings; use geoffrey_models::models::settings::GeoffreySettings;
use geoffrey_models::models::Portal; use geoffrey_models::models::Portal;
@ -94,7 +94,11 @@ impl GeoffreyFormatter {
} }
}; };
self.push_owners(&loc.owners) let loc_type: LocationType = LocationType::from(&loc.loc_data);
self.push_owners(&loc.owners).push(", ");
self.push("Type: ").push(&loc_type.to_string())
} }
pub fn push_item_listing(&mut self, listing: &ItemListing) -> &mut Self { pub fn push_item_listing(&mut self, listing: &ItemListing) -> &mut Self {

View File

@ -78,7 +78,7 @@ pub fn find_location_by_name_type(
let location: LocationDb = db let location: LocationDb = db
.filter(|_, loc: &LocationDb| { .filter(|_, loc: &LocationDb| {
let lt: LocationType = loc.loc_data.clone().into(); let lt: LocationType = LocationType::from(&loc.loc_data);
loc.owners().contains(&owner_id) && filter.is_match(loc.name.as_str()) && lt == loc_type loc.owners().contains(&owner_id) && filter.is_match(loc.name.as_str()) && lt == loc_type
})? })?
.next() .next()

View File

@ -32,7 +32,7 @@ impl QueryBuilder<LocationDb> {
pub fn with_type(self, loc_type: LocationType) -> Self { pub fn with_type(self, loc_type: LocationType) -> Self {
self.add_query_clause(Box::new(move |_: u64, loc: &LocationDb| { self.add_query_clause(Box::new(move |_: u64, loc: &LocationDb| {
let next_loc_type: LocationType = loc.loc_data.clone().into(); let next_loc_type: LocationType = LocationType::from(&loc.loc_data);
loc_type == next_loc_type loc_type == next_loc_type
})) }))

View File

@ -26,8 +26,8 @@ pub enum LocationType {
Market, Market,
} }
impl From<LocationDataDb> for LocationType { impl From<&LocationDataDb> for LocationType {
fn from(l: LocationDataDb) -> Self { fn from(l: &LocationDataDb) -> Self {
match l { match l {
LocationDataDb::Base => LocationType::Base, LocationDataDb::Base => LocationType::Base,
LocationDataDb::Shop(_) => LocationType::Shop, LocationDataDb::Shop(_) => LocationType::Shop,
@ -39,6 +39,19 @@ impl From<LocationDataDb> for LocationType {
} }
} }
impl From<&LocationData> for LocationType {
fn from(l: &LocationData) -> Self {
match l {
LocationData::Base => LocationType::Base,
LocationData::Shop(_) => LocationType::Shop,
LocationData::Attraction => LocationType::Attraction,
LocationData::Town(_) => LocationType::Town,
LocationData::Farm(_) => LocationType::Farm,
LocationData::Market(_) => LocationType::Market,
}
}
}
impl Display for LocationType { impl Display for LocationType {
fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result { fn fmt(&self, f: &mut Formatter<'_>) -> std::fmt::Result {
let name = match self { let name = match self {