diff --git a/Cargo.lock b/Cargo.lock index e92fa29..e676861 100644 --- a/Cargo.lock +++ b/Cargo.lock @@ -498,6 +498,26 @@ dependencies = [ "cfg-if 0.1.10", ] +[[package]] +name = "enum-iterator" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "4eeac5c5edb79e4e39fe8439ef35207780a11f69c52cbe424ce3dfad4cb78de6" +dependencies = [ + "enum-iterator-derive", +] + +[[package]] +name = "enum-iterator-derive" +version = "0.7.0" +source = "registry+https://github.com/rust-lang/crates.io-index" +checksum = "c134c37760b27a871ba422106eedbb8247da973a09e82558bf26d619c882b159" +dependencies = [ + "proc-macro2 1.0.36", + "quote 1.0.18", + "syn 1.0.92", +] + [[package]] name = "event-listener" version = "2.5.2" @@ -1059,6 +1079,7 @@ name = "matrix-bot" version = "0.1.0" dependencies = [ "clap 3.1.16", + "enum-iterator", "matrix-sdk", "serde", "tokio", diff --git a/Cargo.toml b/Cargo.toml index 198f087..8b4cf2d 100644 --- a/Cargo.toml +++ b/Cargo.toml @@ -16,6 +16,7 @@ toml = "0.5" clap = { version = "3", features = ["derive"] } serde = { version = "1", features = ["derive"] } uwuify = "0.2" +enum-iterator = "0.7" [profile.release] strip = true diff --git a/src/main.rs b/src/main.rs index 5c30491..d7eefae 100644 --- a/src/main.rs +++ b/src/main.rs @@ -1,9 +1,12 @@ #![warn(clippy::nursery, clippy::pedantic)] +use std::fmt::Display; use std::path::PathBuf; +use std::str::FromStr; use std::time::Duration; use clap::Parser; +use enum_iterator::IntoEnumIterator; use matrix_sdk::room::{Joined, Room}; use matrix_sdk::ruma::events::room::member::MemberEventContent; use matrix_sdk::ruma::events::room::message::{ @@ -163,9 +166,11 @@ async fn parse_message(event: SyncMessageEvent, room: Joine if let Some(message) = message.strip_prefix('!') { let (command, args) = message.split_once(' ').unwrap_or((message, "")); - match command { - "source" => source(room).await?, - "uwu" => uwuify(room, args).await?, + match BotCommand::from_str(command).ok() { + Some(BotCommand::Source) => source(room).await?, + Some(BotCommand::Uwu) => uwuify(room, args).await?, + Some(BotCommand::Ping) => ping(room).await?, + Some(BotCommand::Help) => help(room).await?, _ => unsupported_command(event, room, command).await?, } } @@ -173,6 +178,50 @@ async fn parse_message(event: SyncMessageEvent, room: Joine Ok(()) } +#[derive(enum_iterator::IntoEnumIterator)] +enum BotCommand { + Help, + Source, + Uwu, + Ping, +} + +impl BotCommand { + const fn help_text(&self) -> &'static str { + match self { + Self::Source => "Links to the source code for this bot.", + Self::Uwu => "Uwuifies your message.", + Self::Ping => "Pong!", + Self::Help => "Prints this help.", + } + } +} + +impl FromStr for BotCommand { + type Err = (); + + fn from_str(s: &str) -> std::result::Result { + match s.to_lowercase().as_str() { + "source" => Ok(Self::Source), + "uwu" => Ok(Self::Uwu), + "ping" => Ok(Self::Ping), + "help" => Ok(Self::Help), + _ => Err(()), + } + } +} + +impl Display for BotCommand { + fn fmt(&self, f: &mut std::fmt::Formatter<'_>) -> std::fmt::Result { + match self { + BotCommand::Source => write!(f, "source"), + BotCommand::Uwu => write!(f, "uwu"), + BotCommand::Ping => write!(f, "ping"), + BotCommand::Help => write!(f, "help"), + } + } +} + async fn source(room: Joined) -> Result<()> { let content = MessageEventContent::text_plain("https://git.eddie.sh/edward/matrix-bot"); room.send(content, None).await?; @@ -185,6 +234,25 @@ async fn uwuify(room: Joined, message: &str) -> Result<()> { Ok(()) } +async fn ping(room: Joined) -> Result<()> { + let content = MessageEventContent::text_plain("Pong!"); + room.send(content, None).await?; + Ok(()) +} + +async fn help(room: Joined) -> Result<()> { + let mut msg = "List of commands:\n\n".to_owned(); + for command in BotCommand::into_enum_iter() { + msg.push_str(&command.to_string()); + msg.push_str(" - "); + msg.push_str(command.help_text()); + msg.push_str("\n"); + } + let content = MessageEventContent::notice_plain(msg); + room.send(content, None).await?; + Ok(()) +} + async fn unsupported_command( original_event: SyncMessageEvent, room: Joined,