171 lines
4.5 KiB
Rust
171 lines
4.5 KiB
Rust
use chrono::{Duration, Utc};
|
|
use geoffrey_models::models::item::ItemListing;
|
|
use geoffrey_models::models::locations::{Location, LocationData, LocationType};
|
|
use geoffrey_models::models::player::Player;
|
|
use geoffrey_models::models::settings::GeoffreySettings;
|
|
use geoffrey_models::models::Portal;
|
|
use serenity::client::Cache;
|
|
use serenity::utils::{content_safe, ContentSafeOptions, MessageBuilder};
|
|
|
|
pub struct GeoffreyFormatter {
|
|
msg: String,
|
|
settings: GeoffreySettings,
|
|
}
|
|
|
|
impl GeoffreyFormatter {
|
|
pub fn new(settings: GeoffreySettings) -> Self {
|
|
Self {
|
|
msg: String::new(),
|
|
settings,
|
|
}
|
|
}
|
|
|
|
pub fn build(&mut self) -> String {
|
|
self.msg.clone()
|
|
}
|
|
|
|
pub fn push(&mut self, string: &str) -> &mut Self {
|
|
self.msg.push_str(string);
|
|
|
|
self
|
|
}
|
|
|
|
pub fn push_new_line(&mut self) -> &mut Self {
|
|
self.push("\n")
|
|
}
|
|
|
|
pub fn push_owners(&mut self, owners: &[Player]) -> &mut Self {
|
|
let mut plural = "";
|
|
let mut ellipses = "";
|
|
|
|
if owners.len() > 1 {
|
|
plural = "s"
|
|
}
|
|
|
|
let range = if owners.len() > self.settings.max_owners_to_display as usize {
|
|
ellipses = "...";
|
|
self.settings.max_owners_to_display as usize
|
|
} else {
|
|
owners.len()
|
|
};
|
|
|
|
self.msg = MessageBuilder::new()
|
|
.push(self.msg.clone())
|
|
.push("Owner")
|
|
.push(plural)
|
|
.push(": ")
|
|
.push(
|
|
owners[0..range]
|
|
.iter()
|
|
.map(|owner| owner.name.clone())
|
|
.collect::<Vec<String>>()
|
|
.join(", "),
|
|
)
|
|
.push(ellipses)
|
|
.build();
|
|
|
|
self
|
|
}
|
|
|
|
pub fn push_portal(&mut self, portal: &Portal) -> &mut Self {
|
|
self.push(&format!(
|
|
"Portal: {} {} (x={}, z={})",
|
|
portal.direction(),
|
|
portal.tunnel_addr(),
|
|
portal.x,
|
|
portal.z
|
|
))
|
|
}
|
|
|
|
pub fn push_loc(&mut self, loc: &Location) -> &mut Self {
|
|
self.push(
|
|
&MessageBuilder::new()
|
|
.push_bold_safe(&loc.name)
|
|
.push(", ")
|
|
.push(&loc.position)
|
|
.push(", ")
|
|
.build(),
|
|
);
|
|
|
|
match &loc.portal {
|
|
None => {}
|
|
Some(p) => {
|
|
self.push_portal(p).push(", ");
|
|
}
|
|
};
|
|
|
|
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 {
|
|
let stocked_diff = Utc::now() - listing.restocked_time;
|
|
|
|
let time_str = if stocked_diff < Duration::days(1) {
|
|
"today".to_string()
|
|
} else if stocked_diff < Duration::days(2) {
|
|
"1 day ago".to_string()
|
|
} else {
|
|
format!("{} days ago", stocked_diff.num_days())
|
|
};
|
|
|
|
let msg = MessageBuilder::new()
|
|
.push_bold_safe(&listing.item.name)
|
|
.push(", ")
|
|
.push(&listing.count_per_price)
|
|
.push(" for ")
|
|
.push(listing.price)
|
|
.push("D. Restocked ")
|
|
.push(time_str)
|
|
.build();
|
|
|
|
let msg = if listing.is_out_of_stock(self.settings.min_out_of_stock_votes) {
|
|
MessageBuilder::new().push_strike_safe(msg).to_string()
|
|
} else {
|
|
msg
|
|
};
|
|
|
|
self.push(&msg)
|
|
}
|
|
|
|
pub fn push_loc_full(&mut self, loc: &Location) -> &mut Self {
|
|
self.push_loc(loc);
|
|
|
|
match &loc.loc_data {
|
|
LocationData::Shop(shop) => {
|
|
if !shop.item_listings.is_empty() {
|
|
self.push_new_line()
|
|
.push(&MessageBuilder::new().push_bold("Inventory:").to_string())
|
|
.push_new_line();
|
|
|
|
for listing in &shop.item_listings {
|
|
self.push_item_listing(listing).push_new_line();
|
|
}
|
|
|
|
self
|
|
} else {
|
|
self
|
|
}
|
|
}
|
|
_ => self,
|
|
}
|
|
}
|
|
}
|
|
|
|
pub async fn clean_message(cache: impl AsRef<Cache>, msg: &str) -> String {
|
|
content_safe(
|
|
cache,
|
|
msg,
|
|
&ContentSafeOptions::new()
|
|
.clean_channel(true)
|
|
.clean_user(true)
|
|
.clean_everyone(true)
|
|
.clean_here(true)
|
|
.clean_role(true),
|
|
)
|
|
.await
|
|
}
|