#[bot]Expand description
Derive-like attribute that turns an impl block into a runnable IRC bot.
§Custom state
Pass state = SomeType to give the bot a public state field your handlers
can read:
#[derive(Default)]
struct Counter { hits: std::sync::atomic::AtomicUsize }
#[bot(state = Counter)]
impl MyBot {
#[command("ping")]
async fn ping(&self, ctx: ircbot::Context) -> ircbot::Result {
let n = self.state.hits.fetch_add(1, std::sync::atomic::Ordering::Relaxed) + 1;
ctx.reply(format!("pong #{n}"))
}
}The state type must implement Default (it is initialised with
Default::default() by both MyBot::default() and MyBot::new) and must be
Send + Sync + 'static (the bot is shared across tasks as an Arc; that
bound is checked at main_loop). Because handlers receive &self, mutating
state requires interior mutability — an AtomicUsize, a Mutex<…>, etc. To
start from a non-default value, assign the public field after constructing:
let mut bot = MyBot::new(…).await?; bot.state = …;.
Note: a SIGHUP hot-reload re-execs the binary, so in-memory state is
reconstructed via Default and is not carried across the reload.
This is sugar over the lower-level API: a bot is any
Arc<T: Send + Sync + 'static> passed to ircbot::internal::run_bot with a
hand-built Vec<ircbot::HandlerEntry<T>>, which you can use directly when you
want full control over the bot type.
§Panics
Panics at compile time if the annotated impl block does not use a simple
(non-generic, non-path) type name, e.g. impl MyBot { … }.