ircbot/handler.rs
1use std::future::Future;
2use std::pin::Pin;
3use std::sync::Arc;
4
5use crate::context::Context;
6
7/// A boxed, heap-allocated future that is `Send + 'static`.
8pub type BoxFuture<T> = Pin<Box<dyn Future<Output = T> + Send + 'static>>;
9
10/// The type-erased handler function stored in [`HandlerEntry`].
11pub type HandlerFn<T> = Box<dyn Fn(Arc<T>, Context) -> BoxFuture<crate::Result> + Send + Sync>;
12
13/// What causes a handler to fire.
14#[derive(Debug, Clone, PartialEq, Eq)]
15pub enum Trigger {
16 /// Fires when the user sends `!<name>` (optionally in a specific channel).
17 ///
18 /// When `role` is `Some`, the command only fires for senders whose
19 /// `nick!user@host` matches one of the hostmask patterns configured for that
20 /// role (see [`State::with_role`](crate::State::with_role)); unauthorized
21 /// senders are silently ignored.
22 Command {
23 name: String,
24 target: Option<String>,
25 role: Option<String>,
26 },
27 /// Fires when an incoming PRIVMSG matches a glob pattern (`*` as wildcard).
28 Message {
29 pattern: String,
30 target: Option<String>,
31 },
32 /// Fires on a specific IRC event (e.g. "JOIN"), with optional target/regex filter.
33 Event {
34 event: String,
35 target: Option<String>,
36 regex: Option<String>,
37 },
38 /// Fires when a PRIVMSG addresses the bot by name at the start of the
39 /// message (e.g. `"botname: hello"` or `"botname, ping"`).
40 /// The text following the address prefix is provided as a capture.
41 Mention { target: Option<String> },
42 /// Fires on a schedule described by a cron expression. The expression uses
43 /// the 6-field Quartz format: `sec min hour day-of-month month day-of-week`
44 /// with an optional 7th `year` field. Times are evaluated in `tz`, which
45 /// must be a valid IANA timezone name (e.g. `"America/New_York"`); defaults
46 /// to `"UTC"` when not specified.
47 ///
48 /// When `target` is `None` the handler's [`Context::target`] is a
49 /// [`Target::User`](crate::Target::User) with an empty name (so its
50 /// `as_str()` is empty) and [`Context::is_channel`] returns `false`.
51 /// Handlers that need to send a message should either specify a `target` or
52 /// store the destination in their bot state.
53 ///
54 /// Example — top of every hour on weekday afternoons (Eastern time):
55 /// `"0 0 8-16 * * MON-FRI"` with `tz = "America/New_York"`
56 Cron {
57 schedule: String,
58 tz: String,
59 target: Option<String>,
60 },
61}
62
63/// Associates a [`Trigger`] with a handler function for a bot of type `T`.
64pub struct HandlerEntry<T> {
65 pub trigger: Trigger,
66 pub handler: HandlerFn<T>,
67}