diff --git a/Cargo.lock b/Cargo.lock index f7a582e..6ad69ab 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -34,9 +34,9 @@ checksum = "23b62fc65de8e4e7f52534fb52b0f3ed04746ae267519eef2a83941e8085068b" [[package]] name = "async-trait" -version = "0.1.51" +version = "0.1.52" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "44318e776df68115a881de9a8fd1b9e53368d7a4a5ce4cc48517da3393233a5e" +checksum = "061a7acccaa286c011ddc30970520b98fa40e00c9d644633fb26b5fc63a265e3" dependencies = [ "proc-macro2", "quote", @@ -158,8 +158,8 @@ dependencies = [ "libc", "num-integer", "num-traits 0.2.14", - "serde 1.0.130", - "time 0.1.44", + "serde 1.0.132", + "time", "winapi", ] @@ -198,7 +198,7 @@ dependencies = [ "lazy_static", "nom", "rust-ini", - "serde 1.0.130", + "serde 1.0.132", "serde-hjson", "serde_json", "toml", @@ -273,9 +273,9 @@ dependencies = [ [[package]] name = "encoding_rs" -version = "0.8.29" +version = "0.8.30" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "a74ea89a0a1b98f6332de42c95baff457ada66d1cb4030f9ff151b2041a1c746" +checksum = "7896dc8abb250ffdda33912550faa54c88ec8b998dec0b2c55ab224921ce11df" dependencies = [ "cfg-if", ] @@ -335,9 +335,9 @@ dependencies = [ [[package]] name = "futures" -version = "0.3.18" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "8cd0210d8c325c245ff06fd95a3b13689a1a276ac8cfa8e8720cb840bfb84b9e" +checksum = "28560757fe2bb34e79f907794bb6b22ae8b0e5c669b638a1132f2592b19035b4" dependencies = [ "futures-channel", "futures-core", @@ -349,9 +349,9 @@ dependencies = [ [[package]] name = "futures-channel" -version = "0.3.18" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fc8cd39e3dbf865f7340dce6a2d401d24fd37c6fe6c4f0ee0de8bfca2252d27" +checksum = "ba3dda0b6588335f360afc675d0564c17a77a2bda81ca178a4b6081bd86c7f0b" dependencies = [ "futures-core", "futures-sink", @@ -359,33 +359,33 @@ dependencies = [ [[package]] name = "futures-core" -version = "0.3.18" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "629316e42fe7c2a0b9a65b47d159ceaa5453ab14e8f0a3c5eedbb8cd55b4a445" +checksum = "d0c8ff0461b82559810cdccfde3215c3f373807f5e5232b71479bff7bb2583d7" [[package]] name = "futures-io" -version = "0.3.18" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "e481354db6b5c353246ccf6a728b0c5511d752c08da7260546fc0933869daa11" +checksum = "b1f9d34af5a1aac6fb380f735fe510746c38067c5bf16c7fd250280503c971b2" [[package]] name = "futures-sink" -version = "0.3.18" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "996c6442437b62d21a32cd9906f9c41e7dc1e19a9579843fad948696769305af" +checksum = "e3055baccb68d74ff6480350f8d6eb8fcfa3aa11bdc1a1ae3afdd0514617d508" [[package]] name = "futures-task" -version = "0.3.18" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "dabf1872aaab32c886832f2276d2f5399887e2bd613698a02359e4ea83f8de12" +checksum = "6ee7c6485c30167ce4dfb83ac568a849fe53274c831081476ee13e0dce1aad72" [[package]] name = "futures-util" -version = "0.3.18" +version = "0.3.19" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41d22213122356472061ac0f1ab2cee28d2bac8491410fd68c2af53d1cedb83e" +checksum = "d9b5cf40b47a271f77a8b1bec03ca09044d99d2372c0de244e66430761127164" dependencies = [ "futures-channel", "futures-core", @@ -428,7 +428,7 @@ dependencies = [ "log", "rand 0.8.4", "regex", - "serde 1.0.130", + "serde 1.0.132", "serde_json", "simple_logger", "structopt", @@ -445,7 +445,7 @@ dependencies = [ "geoffrey_models", "log", "reqwest", - "serde 1.0.130", + "serde 1.0.132", "serde_json", "serde_plain", "serenity", @@ -463,9 +463,9 @@ dependencies = [ "json", "lazy_static", "log", - "serde 1.0.130", + "regex", + "serde 1.0.132", "serde_json", - "simple_logger", "sled", ] @@ -475,7 +475,7 @@ version = "0.1.0" dependencies = [ "chrono", "log", - "serde 1.0.130", + "serde 1.0.132", "serde_json", ] @@ -503,9 +503,9 @@ dependencies = [ [[package]] name = "h2" -version = "0.3.7" +version = "0.3.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7fd819562fcebdac5afc5c113c3ec36f902840b70fd4fc458799c8ce4607ae55" +checksum = "8f072413d126e57991455e0a922b31e4c8ba7c2ffbebf6b78b4f8521397d65cd" dependencies = [ "bytes 1.1.0", "fnv", @@ -577,7 +577,7 @@ checksum = "1323096b05d41827dadeaee54c9981958c0f94e670bc94ed80037d1a7b8b186b" dependencies = [ "bytes 1.1.0", "fnv", - "itoa", + "itoa 0.4.8", ] [[package]] @@ -605,9 +605,9 @@ checksum = "c4a1e36c821dbe04574f602848a19f742f4fb3c98d40449f11bcad18d6b17421" [[package]] name = "hyper" -version = "0.14.15" +version = "0.14.16" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "436ec0091e4f20e655156a30a0df3770fe2900aa301e548e08446ec794b6953c" +checksum = "b7ec3e62bdc98a2f0393a5048e4c30ef659440ea6e0e572965103e72bd836f55" dependencies = [ "bytes 1.1.0", "futures-channel", @@ -618,7 +618,7 @@ dependencies = [ "http-body", "httparse", "httpdate", - "itoa", + "itoa 0.4.8", "pin-project-lite", "socket2", "tokio", @@ -637,7 +637,7 @@ dependencies = [ "hyper", "rustls 0.20.2", "tokio", - "tokio-rustls 0.23.1", + "tokio-rustls 0.23.2", ] [[package]] @@ -704,6 +704,12 @@ version = "0.4.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "b71991ff56294aa922b450139ee08b3bfc70982c6b2c7562771375cf73542dd4" +[[package]] +name = "itoa" +version = "1.0.1" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "1aab8fc367588b89dcee83ab0fd66b72b50b72fa1904d7095045ace2b0c81c35" + [[package]] name = "js-sys" version = "0.3.55" @@ -740,9 +746,9 @@ dependencies = [ [[package]] name = "libc" -version = "0.2.109" +version = "0.2.112" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f98a04dce437184842841303488f70d0188c5f51437d2a834dc097eafa909a01" +checksum = "1b03d17f364a3a042d5e5d46b053bbbf82c92c9430c592dd4c064dc6ee997125" [[package]] name = "linked-hash-map" @@ -933,9 +939,9 @@ dependencies = [ [[package]] name = "once_cell" -version = "1.8.0" +version = "1.9.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "692fcb63b64b1758029e0a96ee63e049ce8c5948587f2f7208df04625e5f6b56" +checksum = "da32515d9f6e6e489d7bc9d84c71b060db7247dc035bbe44eac88cf87486d8d5" [[package]] name = "opaque-debug" @@ -965,9 +971,9 @@ checksum = "28988d872ab76095a6e6ac88d99b54fd267702734fd7ffe610ca27f533ddb95a" [[package]] name = "openssl-sys" -version = "0.9.71" +version = "0.9.72" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "7df13d165e607909b363a4757a6f133f8a818a74e9d3a98d09c6128e15fa4c73" +checksum = "7e46109c383602735fa0a2e48dd2b7c892b048e1bf69e5c3b1d804b7d9c203cb" dependencies = [ "autocfg", "cc", @@ -1041,9 +1047,9 @@ checksum = "8b870d8c151b6f2fb93e84a13146138f05d02ed11c7e7c54f8826aaaf7c9f184" [[package]] name = "pkg-config" -version = "0.3.22" +version = "0.3.24" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "12295df4f294471248581bc09bef3c38a5e46f1e36d6a37353621a0c6c357e1f" +checksum = "58893f751c9b0412871a09abd62ecd2a00298c6c83befa223ef98c52aef40cbe" [[package]] name = "ppv-lite86" @@ -1077,9 +1083,9 @@ dependencies = [ [[package]] name = "proc-macro2" -version = "1.0.33" +version = "1.0.34" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "fb37d2df5df740e582f28f8560cf425f52bb267d872fe58358eadb554909f07a" +checksum = "2f84e92c0f7c9d58328b85a78557813e4bd845130db68d7184635344399423b1" dependencies = [ "unicode-xid", ] @@ -1242,12 +1248,12 @@ dependencies = [ "pin-project-lite", "rustls 0.20.2", "rustls-pemfile", - "serde 1.0.130", + "serde 1.0.132", "serde_json", "serde_urlencoded", "tokio", "tokio-native-tls", - "tokio-rustls 0.23.1", + "tokio-rustls 0.23.2", "tokio-util", "url", "wasm-bindgen", @@ -1314,9 +1320,9 @@ dependencies = [ [[package]] name = "ryu" -version = "1.0.6" +version = "1.0.9" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "3c9613b5a66ab9ba26415184cfc41156594925a9cf3a2057e57f31ff145f6568" +checksum = "73b4b750c782965c211b42f022f59af1fbceabdd026623714f104152f1ec149f" [[package]] name = "safemem" @@ -1397,9 +1403,9 @@ checksum = "9dad3f759919b92c3068c696c15c3d17238234498bbdcc80f2c469606f948ac8" [[package]] name = "serde" -version = "1.0.130" +version = "1.0.132" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "f12d06de37cf59146fbdecab66aa99f9fe4f78722e3607577a5375d66bd0c913" +checksum = "8b9875c23cf305cd1fd7eb77234cbb705f21ea6a72c637a5c6db5fe4b8e7f008" dependencies = [ "serde_derive", ] @@ -1418,9 +1424,9 @@ dependencies = [ [[package]] name = "serde_derive" -version = "1.0.130" +version = "1.0.132" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d7bc1a1ab1961464eae040d96713baa5a724a8152c1222492465b54322ec508b" +checksum = "ecc0db5cb2556c0e558887d9bbdcf6ac4471e83ff66cf696e5419024d1606276" dependencies = [ "proc-macro2", "quote", @@ -1429,13 +1435,13 @@ dependencies = [ [[package]] name = "serde_json" -version = "1.0.72" +version = "1.0.73" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "d0ffa0837f2dfa6fb90868c2b5468cad482e175f7dad97e7421951e663f2b527" +checksum = "bcbd0344bc6533bc7ec56df11d42fb70f1b912351c0825ccb7211b59d8af7cf5" dependencies = [ - "itoa", + "itoa 1.0.1", "ryu", - "serde 1.0.130", + "serde 1.0.132", ] [[package]] @@ -1444,7 +1450,7 @@ version = "1.0.0" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "95455e7e29fada2052e72170af226fbe368a4ca33dee847875325d9fdb133858" dependencies = [ - "serde 1.0.130", + "serde 1.0.132", ] [[package]] @@ -1454,15 +1460,15 @@ source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "edfa57a7f8d9c1d260a549e7224100f6c43d43f9103e06dd8b4095a9b2b43ce9" dependencies = [ "form_urlencoded", - "itoa", + "itoa 0.4.8", "ryu", - "serde 1.0.130", + "serde 1.0.132", ] [[package]] name = "serenity" version = "0.10.9" -source = "git+https://github.com/serenity-rs/serenity.git#fe946df80ed725784ed5b6d5ee233fe82b896861" +source = "git+https://github.com/serenity-rs/serenity.git#04fc541b0e34d0e16c99039ce94cfe3cb79881b8" dependencies = [ "async-trait", "async-tungstenite", @@ -1474,7 +1480,7 @@ dependencies = [ "futures", "percent-encoding", "reqwest", - "serde 1.0.130", + "serde 1.0.132", "serde_json", "tokio", "tracing", @@ -1506,14 +1512,13 @@ dependencies = [ [[package]] name = "simple_logger" -version = "1.15.0" +version = "1.16.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "205596cf77a15774e5601c5ef759f4211ac381c0855a1f1d5e24a46f60f93e9a" +checksum = "45b60258a35dc3cb8a16890b8fd6723349bfa458d7960e25e633f1b1c19d7b5e" dependencies = [ "atty", "colored", "log", - "time 0.3.5", "winapi", ] @@ -1662,23 +1667,6 @@ dependencies = [ "winapi", ] -[[package]] -name = "time" -version = "0.3.5" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "41effe7cfa8af36f439fac33861b66b049edc6f9a32331e2312660529c1c24ad" -dependencies = [ - "itoa", - "libc", - "time-macros", -] - -[[package]] -name = "time-macros" -version = "0.2.3" -source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "25eb0ca3468fc0acc11828786797f6ef9aa1555e4a211a60d64cc8e4d1be47d6" - [[package]] name = "tinyvec" version = "1.5.1" @@ -1696,11 +1684,10 @@ checksum = "cda74da7e1a664f795bb1f8a87ec406fb89a02522cf6e50620d016add6dbbf5c" [[package]] name = "tokio" -version = "1.14.0" +version = "1.15.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "70e992e41e0d2fb9f755b37446f20900f64446ef54874f40a60c78f021ac6144" +checksum = "fbbf1c778ec206785635ce8ad57fe52b3009ae9e0c9f574a728f3049d3e55838" dependencies = [ - "autocfg", "bytes 1.1.0", "libc", "memchr", @@ -1716,9 +1703,9 @@ dependencies = [ [[package]] name = "tokio-macros" -version = "1.6.0" +version = "1.7.0" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "c9efc1aba077437943f7515666aa2b882dfabfbfdf89c819ea75a8d6e9eaba5e" +checksum = "b557f72f448c511a979e2564e55d74e6c4432fc96ff4f6241bc6bded342643b7" dependencies = [ "proc-macro2", "quote", @@ -1748,9 +1735,9 @@ dependencies = [ [[package]] name = "tokio-rustls" -version = "0.23.1" +version = "0.23.2" source = "registry+https://github.com/rust-lang/crates.io-index" -checksum = "4baa378e417d780beff82bf54ceb0d195193ea6a00c14e22359e7f39456b5689" +checksum = "a27d5f2b839802bd8267fa19b0530f5a08b9c08cd417976be2a65d130fe1c11b" dependencies = [ "rustls 0.20.2", "tokio", @@ -1801,7 +1788,7 @@ version = "0.5.8" source = "registry+https://github.com/rust-lang/crates.io-index" checksum = "a31142970826733df8241ef35dc040ef98c679ab14d7c3e54d827099b3acecaa" dependencies = [ - "serde 1.0.130", + "serde 1.0.132", ] [[package]] @@ -2021,7 +2008,7 @@ dependencies = [ "percent-encoding", "pin-project", "scoped-tls", - "serde 1.0.130", + "serde 1.0.132", "serde_json", "serde_urlencoded", "tokio", diff --git a/geoffrey_api/Cargo.toml b/geoffrey_api/Cargo.toml index 8e7a2a9..489fd03 100644 --- a/geoffrey_api/Cargo.toml +++ b/geoffrey_api/Cargo.toml @@ -16,7 +16,12 @@ geoffrey_db = { path = "../geoffrey_db" } config = "0.11.0" structopt = "0.3.21" log = "0.4.14" -simple_logger = "1.13.0" rand = "0.8.4" regex = "1.5.4" chrono = { version = "0.4.19", features = ["serde"] } + +# Doing this for now, as there seems to be an issue with using timestamps +[dependencies.simple_logger] +version = "1.16.0" +default-features = false +features = ["colors"] diff --git a/geoffrey_api/src/commands/add_item.rs b/geoffrey_api/src/commands/add_item.rs index cdfdac7..ff9b96b 100644 --- a/geoffrey_api/src/commands/add_item.rs +++ b/geoffrey_api/src/commands/add_item.rs @@ -1,9 +1,9 @@ use crate::commands::{Command, RequestType}; use crate::context::Context; use crate::Result; -use geoffrey_db::helper::load_location; +use geoffrey_db::helper::{find_location_by_name_type, load_location}; use geoffrey_models::models::item::ItemListing; -use geoffrey_models::models::locations::{Location, LocationDataDb, LocationDb, LocationType}; +use geoffrey_models::models::locations::{Location, LocationDataDb, LocationType}; use geoffrey_models::models::parameters::add_item_params::AddItemParams; use geoffrey_models::models::player::Player; use geoffrey_models::models::response::api_error::GeoffreyAPIError; @@ -39,37 +39,21 @@ impl Command for AddItem { fn run_command(ctx: Arc, req: &Self::Req, user: Option) -> Result { let user = user.unwrap(); - let shops: Vec = ctx - .db - .filter(|_, loc: &LocationDb| { - let loc_type: LocationType = loc.loc_data.clone().into(); + let mut shop = + find_location_by_name_type(&ctx.db, &req.shop, user.id.unwrap(), LocationType::Shop)?; - loc_type == LocationType::Shop - && loc.owners().contains(&user.id.unwrap()) - && loc.name.to_lowercase().contains(&req.shop.to_lowercase()) - })? - .collect(); + if let LocationDataDb::Shop(shop_data) = &mut shop.loc_data { + shop_data.item_listings.insert(ItemListing::new( + &req.item_name, + req.price, + req.quantity, + )); - if shops.is_empty() { - Err(GeoffreyAPIError::EntryNotFound) - } else if shops.len() > 1 { - Err(GeoffreyAPIError::MultipleLocationsMatch) + let shop = ctx.db.insert(shop)?; + + load_location(&ctx.db, &shop).map_err(|err| err.into()) } else { - let mut shop = shops[0].clone(); - - if let LocationDataDb::Shop(shop_data) = &mut shop.loc_data { - shop_data.item_listings.insert(ItemListing::new( - &req.item_name, - req.price, - req.quantity, - )); - - let shop = ctx.db.insert(shop)?; - - load_location(&ctx.db, &shop).map_err(|err| err.into()) - } else { - Err(GeoffreyAPIError::EntryNotFound) - } + Err(GeoffreyAPIError::EntryNotFound) } } } diff --git a/geoffrey_api/src/commands/delete.rs b/geoffrey_api/src/commands/delete.rs index 9edcb9e..07964d5 100644 --- a/geoffrey_api/src/commands/delete.rs +++ b/geoffrey_api/src/commands/delete.rs @@ -1,7 +1,7 @@ use crate::commands::{Command, RequestType}; use crate::context::Context; use crate::Result; -use geoffrey_db::helper::load_location; +use geoffrey_db::helper::{find_location_by_name, load_location}; use geoffrey_models::models::locations::{Location, LocationDb}; use geoffrey_models::models::parameters::delete_params::DeleteParams; use geoffrey_models::models::player::Player; @@ -29,16 +29,8 @@ impl Command for Delete { fn run_command(ctx: Arc, req: &Self::Req, user: Option) -> Result { let user = user.unwrap(); - let filter = regex::Regex::new(format!(r"(?i)^{}$", req.location).as_str()).unwrap(); - - let location: LocationDb = ctx - .db - .filter(|_, loc: &LocationDb| { - filter.is_match(&loc.name) && loc.owners().contains(&user.id.unwrap()) - })? - .next() - .ok_or(GeoffreyAPIError::EntryNotFound)?; + let location = find_location_by_name(&ctx.db, &req.location, user.id.unwrap())?; let location = load_location(&ctx.db, &location).map_err(GeoffreyAPIError::from)?; ctx.db.remove::(location.id)?; diff --git a/geoffrey_api/src/commands/edit.rs b/geoffrey_api/src/commands/edit.rs new file mode 100644 index 0000000..855ee52 --- /dev/null +++ b/geoffrey_api/src/commands/edit.rs @@ -0,0 +1,46 @@ +use crate::commands::{Command, RequestType}; +use crate::context::Context; +use crate::Result; +use geoffrey_db::helper::{find_location_by_name, load_location}; +use geoffrey_models::models::locations::Location; +use geoffrey_models::models::parameters::edit_params::EditParams; +use geoffrey_models::models::player::Player; +use geoffrey_models::models::CommandLevel; +use std::sync::Arc; + +pub struct Edit {} + +impl Command for Edit { + type Req = EditParams; + type Resp = Location; + + fn command_name() -> String { + "edit".to_string() + } + + fn request_type() -> RequestType { + RequestType::POST + } + + fn command_level() -> CommandLevel { + CommandLevel::REGISTERED + } + + fn run_command(ctx: Arc, req: &Self::Req, user: Option) -> Result { + let user = user.unwrap(); + + let mut location = find_location_by_name(&ctx.db, &req.loc_name, user.id.unwrap())?; + + if let Some(new_pos) = &req.new_pos { + location.position = *new_pos; + } + + if let Some(new_name) = &req.new_name { + location.name = new_name.clone(); + } + + let location = ctx.db.insert(location)?; + + load_location(&ctx.db, &location).map_err(|err| err.into()) + } +} diff --git a/geoffrey_api/src/commands/mod.rs b/geoffrey_api/src/commands/mod.rs index acf8fa3..b11cbcd 100644 --- a/geoffrey_api/src/commands/mod.rs +++ b/geoffrey_api/src/commands/mod.rs @@ -1,6 +1,7 @@ use crate::commands::add_item::AddItem; use crate::commands::add_location::AddLocation; use crate::commands::delete::Delete; +use crate::commands::edit::Edit; use crate::commands::find::FindCommand; use crate::commands::link::LinkCommand; use crate::commands::register::Register; @@ -26,6 +27,7 @@ pub mod add_item; pub mod add_location; pub mod add_token; pub mod delete; +pub mod edit; pub mod find; pub mod link; pub mod register; @@ -134,6 +136,7 @@ pub fn command_filter( .or(create_command_filter::(ctx.clone())) .or(create_command_filter::(ctx.clone())) .or(create_command_filter::(ctx.clone())) + .or(create_command_filter::(ctx.clone())) .or(create_command_filter::(ctx)), ) } diff --git a/geoffrey_api/src/commands/set_portal.rs b/geoffrey_api/src/commands/set_portal.rs index e53297e..bd9cf1c 100644 --- a/geoffrey_api/src/commands/set_portal.rs +++ b/geoffrey_api/src/commands/set_portal.rs @@ -1,11 +1,10 @@ use crate::commands::{Command, RequestType}; use crate::context::Context; use crate::Result; -use geoffrey_db::helper::load_location; -use geoffrey_models::models::locations::{Location, LocationDb}; +use geoffrey_db::helper::{find_location_by_name, load_location}; +use geoffrey_models::models::locations::Location; use geoffrey_models::models::parameters::set_portal_params::SetPortalParams; use geoffrey_models::models::player::Player; -use geoffrey_models::models::response::api_error::GeoffreyAPIError; use geoffrey_models::models::CommandLevel; use std::sync::Arc; @@ -29,15 +28,8 @@ impl Command for SetPortal { fn run_command(ctx: Arc, req: &Self::Req, user: Option) -> Result { let user = user.unwrap(); - let filter = regex::Regex::new(format!(r"(?i)^{}$", req.loc_name).as_str()).unwrap(); - let mut location: LocationDb = ctx - .db - .filter(|_, loc: &LocationDb| { - loc.owners().contains(&user.id.unwrap()) && filter.is_match(loc.name.as_str()) - })? - .next() - .ok_or(GeoffreyAPIError::EntryNotFound)?; + let mut location = find_location_by_name(&ctx.db, &req.loc_name, user.id.unwrap())?; location.portal = Some(req.portal.clone()); diff --git a/geoffrey_bot/Cargo.toml b/geoffrey_bot/Cargo.toml index 8eb5dd6..db202b6 100644 --- a/geoffrey_bot/Cargo.toml +++ b/geoffrey_bot/Cargo.toml @@ -17,4 +17,9 @@ async-trait = "0.1.51" config = "0.11.0" structopt = "0.3.21" log = "0.4.14" -simple_logger = "1.13.0" + +# Doing this for now, as there seems to be an issue with using timestamps +[dependencies.simple_logger] +version = "1.16.0" +default-features = false +features = ["colors"] \ No newline at end of file diff --git a/geoffrey_bot/src/bot/arg_parse.rs b/geoffrey_bot/src/bot/arg_parse.rs index ae90fd8..84d8efd 100644 --- a/geoffrey_bot/src/bot/arg_parse.rs +++ b/geoffrey_bot/src/bot/arg_parse.rs @@ -2,8 +2,10 @@ use crate::bot::commands::CommandError; use geoffrey_models::models::locations::LocationType; use geoffrey_models::models::parameters::selling_params::{ItemSort, Order}; use geoffrey_models::models::Dimension; +use serenity::builder::CreateApplicationCommandOption; use serenity::model::prelude::application_command::{ ApplicationCommandInteractionDataOption, ApplicationCommandInteractionDataOptionValue, + ApplicationCommandOptionType, }; use std::str::FromStr; @@ -70,3 +72,52 @@ pub fn option_to_order( Order::from_str(&loc_type).map_err(|_| CommandError::ArgumentParse(field.to_string())) } + +pub fn add_x_position_argument( + option: &mut CreateApplicationCommandOption, +) -> &mut CreateApplicationCommandOption { + option + .name("x") + .description("X coordinate") + .kind(ApplicationCommandOptionType::Integer) + .max_int_value(i32::MAX) + .min_int_value(i32::MIN) + .required(true) +} + +pub fn add_y_position_argument( + option: &mut CreateApplicationCommandOption, +) -> &mut CreateApplicationCommandOption { + option + .name("y") + .description("Y Coordinate") + .kind(ApplicationCommandOptionType::Integer) + .max_int_value(i32::MAX) + .min_int_value(i32::MIN) + .required(true) +} + +pub fn add_z_position_argument( + option: &mut CreateApplicationCommandOption, +) -> &mut CreateApplicationCommandOption { + option + .name("z") + .description("Z Coordinate") + .kind(ApplicationCommandOptionType::Integer) + .max_int_value(i32::MAX) + .min_int_value(i32::MIN) + .required(true) +} + +pub fn add_dimension_argument( + option: &mut CreateApplicationCommandOption, +) -> &mut CreateApplicationCommandOption { + option + .name("dimension") + .description("Dimension of the shop, default is Overworld") + .kind(ApplicationCommandOptionType::String) + .add_string_choice(Dimension::Overworld, Dimension::Overworld) + .add_string_choice(Dimension::Nether, Dimension::Nether) + .add_string_choice(Dimension::TheEnd, Dimension::TheEnd) + .required(false) +} diff --git a/geoffrey_bot/src/bot/commands/add_item.rs b/geoffrey_bot/src/bot/commands/add_item.rs index 7232e9a..fdad761 100644 --- a/geoffrey_bot/src/bot/commands/add_item.rs +++ b/geoffrey_bot/src/bot/commands/add_item.rs @@ -9,6 +9,7 @@ use geoffrey_models::models::parameters::add_item_params::AddItemParams; use crate::bot::arg_parse::{option_to_i64, option_to_string}; use crate::bot::commands::{BotCommand, CommandError}; +use crate::bot::formatters::display_loc; use crate::bot::lang::{PLAYER_ALREADY_SELLS_ITEM, PLAYER_DOES_NOT_HAVE_MATCHING_SHOP}; use geoffrey_models::models::response::api_error::GeoffreyAPIError; use serenity::builder::CreateApplicationCommand; @@ -90,6 +91,10 @@ impl BotCommand for AddItemCommand { } fn build_response(resp: Self::ApiResp) -> String { - format!("{} has been updated", resp.name) + format!( + "**{}** has been updated:\n{}", + resp.name, + display_loc(&resp) + ) } } diff --git a/geoffrey_bot/src/bot/commands/add_location.rs b/geoffrey_bot/src/bot/commands/add_location.rs index 47da7ea..5efb8e4 100644 --- a/geoffrey_bot/src/bot/commands/add_location.rs +++ b/geoffrey_bot/src/bot/commands/add_location.rs @@ -7,8 +7,12 @@ use serenity::model::interactions::application_command::{ ApplicationCommandInteraction, ApplicationCommandOptionType, }; -use crate::bot::arg_parse::{option_to_dim, option_to_i64, option_to_loc_type, option_to_string}; +use crate::bot::arg_parse::{ + add_dimension_argument, add_x_position_argument, add_y_position_argument, + add_z_position_argument, option_to_dim, option_to_i64, option_to_loc_type, option_to_string, +}; use crate::bot::commands::{BotCommand, CommandError}; +use crate::bot::formatters::display_loc; use serenity::builder::CreateApplicationCommand; pub struct AddLocationCommand; @@ -50,43 +54,10 @@ impl BotCommand for AddLocationCommand { .kind(ApplicationCommandOptionType::String) .required(true) }) - .create_option(|option| { - option - .name("x") - .description("X coordinate of the location") - .kind(ApplicationCommandOptionType::Integer) - .max_int_value(i32::MAX) - .min_int_value(i32::MIN) - .required(true) - }) - .create_option(|option| { - option - .name("y") - .description("Y coordinate of the location") - .kind(ApplicationCommandOptionType::Integer) - .max_int_value(i32::MAX) - .min_int_value(i32::MIN) - .required(true) - }) - .create_option(|option| { - option - .name("z") - .description("Z coordinate of the location") - .kind(ApplicationCommandOptionType::Integer) - .max_int_value(i32::MAX) - .min_int_value(i32::MIN) - .required(true) - }) - .create_option(|option| { - option - .name("dimension") - .description("Dimension of the shop, default is Overworld") - .kind(ApplicationCommandOptionType::String) - .add_string_choice(Dimension::Overworld, Dimension::Overworld) - .add_string_choice(Dimension::Nether, Dimension::Nether) - .add_string_choice(Dimension::TheEnd, Dimension::TheEnd) - .required(false) - }) + .create_option(add_x_position_argument) + .create_option(add_y_position_argument) + .create_option(add_z_position_argument) + .create_option(add_dimension_argument) } async fn process_arguments( @@ -106,6 +77,10 @@ impl BotCommand for AddLocationCommand { } fn build_response(resp: Self::ApiResp) -> String { - format!("{} has been added to Geoffrey.", resp.name) + format!( + "**{}** has been added to Geoffrey:\n{}", + resp.name, + display_loc(&resp) + ) } } diff --git a/geoffrey_bot/src/bot/commands/delete.rs b/geoffrey_bot/src/bot/commands/delete.rs index 5a8e251..b58a846 100644 --- a/geoffrey_bot/src/bot/commands/delete.rs +++ b/geoffrey_bot/src/bot/commands/delete.rs @@ -60,7 +60,7 @@ impl BotCommand for DeleteCommand { fn build_response(resp: Self::ApiResp) -> String { format!( - "{} has been been removed from Geoffrey, good riddance!", + "**{}** has been been removed from Geoffrey, good riddance!", resp.name ) } diff --git a/geoffrey_bot/src/bot/commands/edit_name.rs b/geoffrey_bot/src/bot/commands/edit_name.rs new file mode 100644 index 0000000..1243353 --- /dev/null +++ b/geoffrey_bot/src/bot/commands/edit_name.rs @@ -0,0 +1,70 @@ +use async_trait::async_trait; +use geoffrey_models::models::locations::Location; +use reqwest::Method; +use serenity::model::interactions::application_command::{ + ApplicationCommandInteraction, ApplicationCommandOptionType, +}; + +use crate::bot::arg_parse::option_to_string; +use crate::bot::commands::{BotCommand, CommandError}; +use crate::bot::formatters::display_loc; +use geoffrey_models::models::parameters::edit_params::EditParams; +use serenity::builder::CreateApplicationCommand; + +//TODO: Combine edit commands into one class once I figure out why subcommand are not working +pub struct EditNameCommand; + +#[async_trait] +impl BotCommand for EditNameCommand { + type ApiParams = EditParams; + type ApiResp = Location; + + fn command_name() -> String { + "edit_name".to_string() + } + + fn endpoint_name() -> String { + "edit".to_string() + } + + fn request_type() -> Method { + Method::POST + } + + fn create_app_command(command: &mut CreateApplicationCommand) -> &mut CreateApplicationCommand { + command + .name(Self::command_name()) + .description("Edit a location's name") + .create_option(|option| { + option + .name("loc_name") + .description("Location to edit") + .kind(ApplicationCommandOptionType::String) + .required(true) + }) + .create_option(|option| { + option + .name("new_name") + .description("New location name") + .kind(ApplicationCommandOptionType::String) + .required(true) + }) + } + + async fn process_arguments( + command_interaction: ApplicationCommandInteraction, + ) -> Result { + let options = command_interaction.data.options; + let name = option_to_string(options.get(0), "loc_name")?; + let new_name = option_to_string(options.get(1), "new_name")?; + Ok(Self::ApiParams::new(name, None, Some(new_name))) + } + + fn build_response(resp: Self::ApiResp) -> String { + format!( + "**{}** has been updated:\n{}", + resp.name, + display_loc(&resp) + ) + } +} diff --git a/geoffrey_bot/src/bot/commands/edit_pos.rs b/geoffrey_bot/src/bot/commands/edit_pos.rs new file mode 100644 index 0000000..0c3263b --- /dev/null +++ b/geoffrey_bot/src/bot/commands/edit_pos.rs @@ -0,0 +1,77 @@ +use async_trait::async_trait; +use geoffrey_models::models::locations::Location; +use geoffrey_models::models::{Dimension, Position}; +use reqwest::Method; +use serenity::model::interactions::application_command::{ + ApplicationCommandInteraction, ApplicationCommandOptionType, +}; + +use crate::bot::arg_parse::{ + add_dimension_argument, add_x_position_argument, add_y_position_argument, + add_z_position_argument, option_to_dim, option_to_i64, option_to_string, +}; +use crate::bot::commands::{BotCommand, CommandError}; +use crate::bot::formatters::display_loc; +use geoffrey_models::models::parameters::edit_params::EditParams; +use serenity::builder::CreateApplicationCommand; + +//TODO: Combine edit commands into one class once I figure out why subcommand are not working +pub struct EditPosCommand; + +#[async_trait] +impl BotCommand for EditPosCommand { + type ApiParams = EditParams; + type ApiResp = Location; + + fn command_name() -> String { + "edit_pos".to_string() + } + + fn endpoint_name() -> String { + "edit".to_string() + } + + fn request_type() -> Method { + Method::POST + } + + fn create_app_command(command: &mut CreateApplicationCommand) -> &mut CreateApplicationCommand { + command + .name(Self::command_name()) + .description("Edit a location's position") + .create_option(|option| { + option + .name("loc_name") + .description("Location to edit") + .kind(ApplicationCommandOptionType::String) + .required(true) + }) + .create_option(add_x_position_argument) + .create_option(add_y_position_argument) + .create_option(add_z_position_argument) + .create_option(add_dimension_argument) + } + + async fn process_arguments( + command_interaction: ApplicationCommandInteraction, + ) -> Result { + let options = command_interaction.data.options; + let name = option_to_string(options.get(0), "loc_name")?; + + let x = option_to_i64(options.get(1), "x")?; + let y = option_to_i64(options.get(2), "y")?; + let z = option_to_i64(options.get(3), "z")?; + let dim = option_to_dim(options.get(4), "dimension").unwrap_or(Dimension::Overworld); + let position = Position::new(x as i32, y as i32, z as i32, dim); + + Ok(Self::ApiParams::new(name, Some(position), None)) + } + + fn build_response(resp: Self::ApiResp) -> String { + format!( + "**{}** has been updated:\n{}", + resp.name, + display_loc(&resp) + ) + } +} diff --git a/geoffrey_bot/src/bot/commands/find.rs b/geoffrey_bot/src/bot/commands/find.rs index 682d938..c475556 100644 --- a/geoffrey_bot/src/bot/commands/find.rs +++ b/geoffrey_bot/src/bot/commands/find.rs @@ -57,7 +57,7 @@ impl BotCommand for FindCommand { let mut resp_str = String::new(); writeln!(resp_str, "The following locations match:").unwrap(); for loc in resp { - writeln!(resp_str, "{}", display_loc(loc)).unwrap(); + writeln!(resp_str, "{}", display_loc(&loc)).unwrap(); } resp_str } diff --git a/geoffrey_bot/src/bot/commands/mod.rs b/geoffrey_bot/src/bot/commands/mod.rs index 3cdd32e..f8831b1 100644 --- a/geoffrey_bot/src/bot/commands/mod.rs +++ b/geoffrey_bot/src/bot/commands/mod.rs @@ -20,6 +20,8 @@ use std::pin::Pin; pub mod add_item; pub mod add_location; pub mod delete; +pub mod edit_name; +pub mod edit_pos; pub mod find; pub mod register; pub mod selling; @@ -81,12 +83,16 @@ pub trait BotCommand: Send + 'static { fn command_name() -> String; + fn endpoint_name() -> String { + Self::command_name() + } + fn request_type() -> reqwest::Method; fn command_url(base_string: &str) -> String { let slash = if !base_string.ends_with('/') { "/" } else { "" }; - format!("{}{}command/{}/", base_string, slash, Self::command_name()) + format!("{}{}command/{}/", base_string, slash, Self::endpoint_name()) } async fn run_api_query( diff --git a/geoffrey_bot/src/bot/commands/set_portal.rs b/geoffrey_bot/src/bot/commands/set_portal.rs index 6606d88..e551c13 100644 --- a/geoffrey_bot/src/bot/commands/set_portal.rs +++ b/geoffrey_bot/src/bot/commands/set_portal.rs @@ -8,6 +8,7 @@ use serenity::model::interactions::application_command::{ use crate::bot::arg_parse::{option_to_i64, option_to_string}; use crate::bot::commands::{BotCommand, CommandError}; +use crate::bot::formatters::display_loc; use crate::bot::lang::PLAYER_DOES_NOT_HAVE_MATCHING_LOC; use geoffrey_models::models::parameters::set_portal_params::SetPortalParams; use geoffrey_models::models::response::api_error::GeoffreyAPIError; @@ -82,6 +83,10 @@ impl BotCommand for SetPortalCommand { } fn build_response(resp: Self::ApiResp) -> String { - format!("{} has been been updated.", resp.name) + format!( + "**{}** has been updated:\n{}", + resp.name, + display_loc(&resp) + ) } } diff --git a/geoffrey_bot/src/bot/formatters.rs b/geoffrey_bot/src/bot/formatters.rs index 74d50ec..10da14a 100644 --- a/geoffrey_bot/src/bot/formatters.rs +++ b/geoffrey_bot/src/bot/formatters.rs @@ -2,7 +2,7 @@ use geoffrey_models::models::locations::Location; use geoffrey_models::models::player::Player; use geoffrey_models::models::Portal; -pub fn display_owners(owners: Vec, limit: usize) -> String { +pub fn display_owners(owners: &[Player], limit: usize) -> String { let mut plural = ""; let mut ellipses = ""; @@ -29,7 +29,7 @@ pub fn display_owners(owners: Vec, limit: usize) -> String { ) } -pub fn display_portal(portal: Portal) -> String { +pub fn display_portal(portal: &Portal) -> String { format!( "Portal: {} {} (x={}, z={})", portal.direction(), @@ -39,8 +39,8 @@ pub fn display_portal(portal: Portal) -> String { ) } -pub fn display_loc(loc: Location) -> String { - let portal_str = match loc.portal { +pub fn display_loc(loc: &Location) -> String { + let portal_str = match &loc.portal { None => "".to_string(), Some(p) => format!("{}, ", display_portal(p)), }; @@ -50,6 +50,6 @@ pub fn display_loc(loc: Location) -> String { loc.name, loc.position, portal_str, - display_owners(loc.owners, 3), + display_owners(&loc.owners, 3), ) } diff --git a/geoffrey_bot/src/bot/mod.rs b/geoffrey_bot/src/bot/mod.rs index f68c106..803c0f9 100644 --- a/geoffrey_bot/src/bot/mod.rs +++ b/geoffrey_bot/src/bot/mod.rs @@ -2,6 +2,8 @@ use serenity::model::interactions::application_command::ApplicationCommand; use serenity::prelude::*; use crate::bot::commands::delete::DeleteCommand; +use crate::bot::commands::edit_name::EditNameCommand; +use crate::bot::commands::edit_pos::EditPosCommand; use crate::bot::commands::register::RegisterCommand; use crate::bot::commands::GeoffreyCommandFn; use crate::context::GeoffreyContext; @@ -23,15 +25,21 @@ mod lang; #[derive(Default)] pub struct CommandRunner { commands: HashMap, + pub app_commands: Vec, } impl CommandRunner { - async fn register_app_command(ctx: &Context) -> Result<(), CommandError> { - ApplicationCommand::create_global_application_command(&ctx.http, |command| { + async fn register_app_command( + &mut self, + ctx: &Context, + ) -> Result<(), CommandError> { + let command = ApplicationCommand::create_global_application_command(&ctx.http, |command| { T::create_app_command(command) }) .await?; + self.app_commands.push(command); + Ok(()) } @@ -45,7 +53,7 @@ impl CommandRunner { ctx: &Context, ) -> Result<&mut Self, CommandError> { self.add_command_to_lookup::(); - Self::register_app_command::(ctx).await?; + self.register_app_command::(ctx).await?; Ok(self) } @@ -83,6 +91,10 @@ pub async fn build_commands( .add_command::(ctx) .await? .add_command::(ctx) + .await? + .add_command::(ctx) + .await? + .add_command::(ctx) .await?; Ok(()) diff --git a/geoffrey_bot/src/main.rs b/geoffrey_bot/src/main.rs index b38f683..d2093f0 100644 --- a/geoffrey_bot/src/main.rs +++ b/geoffrey_bot/src/main.rs @@ -56,11 +56,17 @@ impl EventHandler for Handler { .expect("Unable to open command runner!"); match build_commands(&ctx, command_runner).await { - Ok(_) => {} + Ok(_) => { + log::debug!("Registered the following commands:"); + for command in &command_runner.app_commands { + log::debug!("{:?}", command) + } + } Err(e) => { log::warn!("Error registering commands: {:?}", e) } } + log::info!("Init completed."); } async fn interaction_create(&self, ctx: Context, interaction: Interaction) { diff --git a/geoffrey_db/Cargo.toml b/geoffrey_db/Cargo.toml index 39537df..4c09e27 100644 --- a/geoffrey_db/Cargo.toml +++ b/geoffrey_db/Cargo.toml @@ -13,8 +13,8 @@ serde_json = "1.0" geoffrey_models = { path = "../geoffrey_models" } byteorder = "1.4.2" log = "0.4.14" -simple_logger = "1.13.0" json = "0.12.4" +regex = "1.5.4" [dev-dependencies] lazy_static = "1.4.0" diff --git a/geoffrey_db/src/helper.rs b/geoffrey_db/src/helper.rs index 00781b3..195da0d 100644 --- a/geoffrey_db/src/helper.rs +++ b/geoffrey_db/src/helper.rs @@ -1,8 +1,10 @@ use crate::database::Database; -use crate::error::Result; +use crate::error::{GeoffreyDBError, Result}; use geoffrey_models::models::locations::market::Market; use geoffrey_models::models::locations::town::Town; -use geoffrey_models::models::locations::{Location, LocationData, LocationDataDb, LocationDb}; +use geoffrey_models::models::locations::{ + Location, LocationData, LocationDataDb, LocationDb, LocationType, +}; use geoffrey_models::models::player::Player; pub fn load_location_data(db: &Database, data: &LocationDataDb) -> Result { @@ -48,3 +50,39 @@ pub fn load_location(db: &Database, location: &LocationDb) -> Result { loc_data, )) } + +pub fn find_location_by_name( + db: &Database, + location_name: &str, + owner_id: u64, +) -> Result { + let filter = regex::Regex::new(format!(r"(?i)^{}$", location_name).as_str()).unwrap(); + + let location: LocationDb = db + .filter(|_, loc: &LocationDb| { + loc.owners().contains(&owner_id) && filter.is_match(loc.name.as_str()) + })? + .next() + .ok_or(GeoffreyDBError::NotFound)?; + + Ok(location) +} + +pub fn find_location_by_name_type( + db: &Database, + location_name: &str, + owner_id: u64, + loc_type: LocationType, +) -> Result { + let filter = regex::Regex::new(format!(r"(?i)^{}$", location_name).as_str()).unwrap(); + + let location: LocationDb = db + .filter(|_, loc: &LocationDb| { + let lt: LocationType = loc.loc_data.clone().into(); + loc.owners().contains(&owner_id) && filter.is_match(loc.name.as_str()) && lt == loc_type + })? + .next() + .ok_or(GeoffreyDBError::NotFound)?; + + Ok(location) +} diff --git a/geoffrey_models/Cargo.toml b/geoffrey_models/Cargo.toml index 9edb437..dd3546f 100644 --- a/geoffrey_models/Cargo.toml +++ b/geoffrey_models/Cargo.toml @@ -10,4 +10,4 @@ edition = "2018" serde = { version = "1.0", features = ["derive"] } serde_json = "1.0" chrono = { version = "0.4.19", features = ["serde"] } -log = "0.4.14" +log = "0.4.14" \ No newline at end of file diff --git a/geoffrey_models/src/models/parameters/edit_params.rs b/geoffrey_models/src/models/parameters/edit_params.rs new file mode 100644 index 0000000..c7a7ee4 --- /dev/null +++ b/geoffrey_models/src/models/parameters/edit_params.rs @@ -0,0 +1,22 @@ +use crate::models::parameters::GeoffreyParam; +use crate::models::Position; +use serde::{Deserialize, Serialize}; + +#[derive(Debug, Serialize, Deserialize, Clone)] +pub struct EditParams { + pub loc_name: String, + pub new_pos: Option, + pub new_name: Option, +} + +impl EditParams { + pub fn new(loc_name: String, new_pos: Option, new_name: Option) -> Self { + Self { + loc_name, + new_pos, + new_name, + } + } +} + +impl GeoffreyParam for EditParams {} diff --git a/geoffrey_models/src/models/parameters/mod.rs b/geoffrey_models/src/models/parameters/mod.rs index e9e5639..739d1fc 100644 --- a/geoffrey_models/src/models/parameters/mod.rs +++ b/geoffrey_models/src/models/parameters/mod.rs @@ -2,6 +2,7 @@ pub mod add_item_params; pub mod add_location_params; pub mod add_token_params; pub mod delete_params; +pub mod edit_params; pub mod find_params; pub mod link_params; pub mod register_params;