use std::net::IpAddr;
use toml_edit::
{
Array,
DocumentMut,
Item,
Value,
};
use crate::
{
consts,
network::codes::BanEntry,
};
fn set_ban(doc: &mut DocumentMut, section: &str, key: &str)
{
if doc.get(section).and_then(Item::as_array).is_none()
{
doc.insert(section, Item::Value(Value::Array(Array::new())));
}
let bans = doc.get_mut(section).and_then(Item::as_array_mut).expect("Ban list is not an array");
if !bans.iter().any(|ban| ban.as_str() == Some(key)) { bans.push(key); }
}
fn unset_ban(doc: &mut DocumentMut, section: &str, id: usize) -> bool {
let Some(bans) = doc.get_mut(section).and_then(Item::as_array_mut) else { return false };
if id >= bans.len() { return false; }
bans.remove(id);
true
}
fn ban_list(section: &str) -> Vec<BanEntry> {
super::get_data(&super::config_path(consts::SERVER_BANS_CONFIG)).get(section)
.and_then(Item::as_array)
.map(|bans| bans.iter().enumerate()
.filter_map(|(id, ban)| Some(BanEntry { id, subject: ban.as_str()?.to_string() }))
.collect())
.unwrap_or_default()
}
fn listed(section: &str, key: &str) -> bool {
super::get_data(&super::config_path(consts::SERVER_BANS_CONFIG)).get(section)
.and_then(Item::as_array)
.is_some_and(|bans| bans.iter().any(|ban| ban.as_str() == Some(key)))
}
pub fn banned(username: &str) -> bool {
listed("user", username)
}
pub fn banned_ip(ip: &IpAddr) -> bool {
listed("ip", &ip.to_string())
}
pub fn ban(username: &str) {
super::with_cached_mut(&super::config_path(consts::SERVER_BANS_CONFIG), |doc| set_ban(doc, "user", username));
}
pub fn ban_ip(ip: &IpAddr) {
super::with_cached_mut(&super::config_path(consts::SERVER_BANS_CONFIG), |doc| set_ban(doc, "ip", &ip.to_string()));
}
pub fn users() -> Vec<BanEntry> {
ban_list("user")
}
pub fn ips() -> Vec<BanEntry> {
ban_list("ip")
}
pub fn pardon(id: usize) -> bool {
let mut pardoned = false;
super::with_cached_mut(&super::config_path(consts::SERVER_BANS_CONFIG), |doc| pardoned = unset_ban(doc, "user", id));
pardoned
}
pub fn pardon_ip(id: usize) -> bool {
let mut pardoned = false;
super::with_cached_mut(&super::config_path(consts::SERVER_BANS_CONFIG), |doc| pardoned = unset_ban(doc, "ip", id));
pardoned
}