From ac2a3cdd9fc5e458b50de47632f3295041de79da Mon Sep 17 00:00:00 2001 From: Joscha Date: Thu, 26 Jan 2023 18:42:46 +0100 Subject: [PATCH] Add testbot_commands example --- examples/testbot_commands.rs | 145 +++++++++++++++++++++++++++++++++++ 1 file changed, 145 insertions(+) create mode 100644 examples/testbot_commands.rs diff --git a/examples/testbot_commands.rs b/examples/testbot_commands.rs new file mode 100644 index 0000000..34ed170 --- /dev/null +++ b/examples/testbot_commands.rs @@ -0,0 +1,145 @@ +// TODO Add description +// TODO Clean up and unify test bots + +use std::sync::Arc; + +use async_trait::async_trait; +use clap::Parser; +use euphoxide::api::Message; +use euphoxide::bot::botrulez::{FullHelp, HasDescriptions, HasStartTime, Ping, ShortHelp, Uptime}; +use euphoxide::bot::command::{Clap, ClapCommand, Context, General, Global, Hidden, Specific}; +use euphoxide::bot::commands::Commands; +use euphoxide::bot::instance::{Event, ServerConfig}; +use euphoxide::bot::instances::Instances; +use euphoxide::conn; +use log::error; +use time::OffsetDateTime; +use tokio::sync::mpsc; + +const HELP: &str = "I'm an example bot for https://github.com/Garmelon/euphoxide"; + +/// Kill this bot. +#[derive(Parser)] +struct KillArgs; + +struct Kill; + +#[async_trait] +impl ClapCommand for Kill { + type Args = KillArgs; + + async fn execute( + &self, + _args: Self::Args, + msg: &Message, + ctx: &Context, + bot: &mut Bot, + ) -> Result<(), conn::Error> { + bot.stop = true; + ctx.reply(msg.id, "/me dies").await?; + Ok(()) + } +} + +/// Do some testing. +#[derive(Parser)] +struct TestArgs { + /// How much testing to do. + #[arg(default_value_t = 1)] + amount: u64, +} + +struct Test; + +#[async_trait] +impl ClapCommand for Test { + type Args = TestArgs; + + async fn execute( + &self, + args: Self::Args, + msg: &Message, + ctx: &Context, + _bot: &mut Bot, + ) -> Result<(), conn::Error> { + let content = if args.amount == 1 { + format!("/me did {} test", args.amount) + } else { + format!("/me did {} tests", args.amount) + }; + ctx.reply(msg.id, content).await?; + Ok(()) + } +} + +struct Bot { + commands: Arc>, + start_time: OffsetDateTime, + stop: bool, +} + +impl HasDescriptions for Bot { + fn descriptions(&self, ctx: &Context) -> Vec { + self.commands.descriptions(ctx) + } +} + +impl HasStartTime for Bot { + fn start_time(&self) -> OffsetDateTime { + self.start_time + } +} + +#[tokio::main] +async fn main() { + let (tx, mut rx) = mpsc::unbounded_channel(); + let mut instances = Instances::new(ServerConfig::default()); + + let mut cmds = Commands::new(); + cmds.add(Hidden(General::new("ping", Clap(Ping::default())))); + cmds.add(Specific::new("ping", Clap(Ping::default()))); + cmds.add(Hidden(General::new("help", Clap(ShortHelp::new(HELP))))); + cmds.add(Specific::new("help", Clap(FullHelp::new(HELP, "")))); + cmds.add(Specific::new("uptime", Clap(Uptime))); + cmds.add(Specific::new("kill", Clap(Kill))); + cmds.add(Global::new("test", Clap(Test))); + let cmds = Arc::new(cmds); + + let mut bot = Bot { + commands: cmds.clone(), + start_time: OffsetDateTime::now_utc(), + stop: false, + }; + + for room in ["test", "test2", "testing"] { + let tx_clone = tx.clone(); + let instance = instances + .server_config() + .clone() + .room(room) + .username(Some("TestBot")) + .build(move |e| { + let _ = tx_clone.send(e); + }); + instances.add(instance); + } + + while let Some(event) = rx.recv().await { + instances.purge(); + if instances.is_empty() { + break; + } + + if let Event::Packet(config, packet, snapshot) = event { + let result = cmds + .handle_packet(&config, &packet, &snapshot, &mut bot) + .await; + if let Err(err) = result { + error!("{err}"); + } + if bot.stop { + break; + } + } + } +}