Skip to main content

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}