Harden bot: line cap, send throttle, panic isolation, verbose flag, weather cache, tests

This commit is contained in:
Jean Chevronnet 2026-07-29 18:46:10 +00:00
parent 1c320ad0c3
commit 9325150315
7 changed files with 165 additions and 10 deletions

View file

@ -1,16 +1,18 @@
use std::collections::BTreeMap;
use std::collections::{BTreeMap, HashMap};
use std::fs;
use std::io::{self, Read, Write};
use std::iter::Peekable;
use std::net::{TcpStream, ToSocketAddrs};
use std::path::{Path, PathBuf};
use std::str::Chars;
use std::time::Duration;
use std::time::{Duration, Instant};
use native_tls::TlsConnector;
use crate::bot::module::{Action, Command, CommandSpec, Module};
const CACHE_TTL: Duration = Duration::from_secs(600);
const COMMANDS: &[CommandSpec] = &[
CommandSpec { name: "add", usage: "add <location>", about: "save your weather location" },
CommandSpec { name: "w", usage: "w [location]", about: "weather for your saved location" },
@ -19,6 +21,7 @@ const COMMANDS: &[CommandSpec] = &[
pub struct Weather {
store: Store,
path: PathBuf,
cache: HashMap<String, (Instant, String)>,
}
impl Weather {
@ -32,7 +35,7 @@ impl Weather {
}
pub fn with_path(path: PathBuf) -> Weather {
Weather { store: Store::load(&path), path }
Weather { store: Store::load(&path), path, cache: HashMap::new() }
}
pub fn location_of(&self, nick: &str) -> Option<&str> {
@ -74,8 +77,17 @@ impl Module for Weather {
cmd.sender, cmd.prefix
))];
};
let key = loc.to_lowercase();
if let Some((at, text)) = self.cache.get(&key) {
if at.elapsed() < CACHE_TTL {
return vec![Action::reply(text.clone())];
}
}
match fetch_weather(&loc) {
Ok(text) => vec![Action::reply(text)],
Ok(text) => {
self.cache.insert(key, (Instant::now(), text.clone()));
vec![Action::reply(text)]
}
Err(e) => vec![Action::reply(format!("weather unavailable: {e}"))],
}
}