1use std::collections::HashMap;
2use std::env;
3use std::fmt::Debug;
4
5use mattermost_api::client::{AuthenticationData, Mattermost};
6use tracing::trace;
7
8mod command;
9mod error;
10mod handler;
11pub mod response;
12
13use command::IntoCommand;
14use handler::Handler;
15
16pub use self::error::{Error, Result};
17
18pub struct MattermostBot {
19 handler: Handler,
20 client: Mattermost,
21}
22
23impl MattermostBot {
24 pub fn new() -> Result<Self> {
34 let mm_url =
35 env::var("MATTERMOST_URL").map_err(|_| Error::EnvVarMissing("MATTERMOST_URL"))?;
36 let mm_token =
37 env::var("MATTERMOST_TOKEN").map_err(|_| Error::EnvVarMissing("MATTERMOST_TOKEN"))?;
38 let auth_data = AuthenticationData::from_access_token(mm_token);
39 let client = Mattermost::new(&mm_url, auth_data).map_err(Error::MattermostApi)?;
40 let listener = client.clone();
41 Ok(MattermostBot {
42 handler: Handler {
43 admins: Vec::new(),
44 admin_commands: HashMap::new(),
45 commands: HashMap::new(),
46 client,
47 },
48 client: listener,
49 })
50 }
51
52 #[must_use]
53 pub fn add_command<H, Args>(mut self, name: &str, handler: H) -> Self
54 where
55 H: IntoCommand<Args>,
56 {
57 self.handler
58 .commands
59 .insert(name.into(), handler.into_command());
60 trace!("adding command: {name}");
61 self
62 }
63
64 #[must_use]
65 pub fn add_admin_command<H, Args>(mut self, name: &str, handler: H) -> Self
66 where
67 H: IntoCommand<Args>,
68 {
69 self.handler
70 .admin_commands
71 .insert(name.into(), handler.into_command());
72 trace!("adding admin command: {name}");
73 self
74 }
75
76 #[must_use]
77 pub fn add_admin(mut self, name: String) -> Self {
78 trace!("adding admin: {name}");
79 self.handler.admins.push(name);
80 self
81 }
82
83 #[must_use]
84 pub fn add_admins(mut self, names: Vec<String>) -> Self {
85 trace!("adding admins: {names:?}");
86 self.handler.admins.extend(names);
87 self
88 }
89
90 pub async fn listen(self) -> Result<()> {
100 let handler = self.handler;
101 let mut listener = self.client;
102 listener
103 .connect_to_websocket(handler)
104 .await
105 .map_err(Error::MattermostApi)
106 }
107}
108
109impl Default for MattermostBot {
110 fn default() -> Self {
117 match Self::new() {
118 Ok(bot) => bot,
119 Err(e) => panic!("Failed to create bot: {e:?}"),
120 }
121 }
122}
123
124impl Debug for MattermostBot {
125 fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result {
126 f.debug_struct("MattermostBot")
127 .field("commands", &self.handler.commands.keys())
128 .finish_non_exhaustive()
129 }
130}