diff --git a/euphoxide-bot/examples/examplebot.rs b/euphoxide-bot/examples/examplebot.rs index cf19a02..fec0fd9 100644 --- a/euphoxide-bot/examples/examplebot.rs +++ b/euphoxide-bot/examples/examplebot.rs @@ -3,10 +3,8 @@ use std::time::Duration; use async_trait::async_trait; use euphoxide::api::Message; use euphoxide_bot::{ - bang::{General, Specific}, - basic::Described, botrulez::{FullHelp, Ping, ShortHelp}, - Command, Commands, Context, Info, Propagate, + Command, CommandExt, Commands, Context, Info, Propagate, }; use euphoxide_client::MultiClient; use log::error; @@ -44,18 +42,21 @@ impl Command for Pyramid { async fn main() { let (event_tx, mut event_rx) = mpsc::channel(10); - let commands = Commands::new() - .then(Described::hidden(General::new("ping", Ping::default()))) - .then(Described::hidden(Specific::new("ping", Ping::default()))) - .then(Described::hidden(General::new( - "help", - ShortHelp::new("/me demonstrates how to use euphoxide"), - ))) - .then(Described::hidden(Specific::new( - "help", - FullHelp::new().with_after("Created using euphoxide."), - ))) - .then(General::new("pyramid", Pyramid)) + let commands = Commands::::new() + .then(Ping::default().general("ping").hidden()) + .then(Ping::default().specific("ping").hidden()) + .then( + ShortHelp::new("/me demonstrates how to use euphoxide") + .general("help") + .hidden(), + ) + .then( + FullHelp::new() + .with_after("Created using euphoxide.") + .specific("help") + .hidden(), + ) + .then(Pyramid.general("pyramid")) .build(); let clients = MultiClient::new(event_tx); diff --git a/euphoxide-bot/src/command.rs b/euphoxide-bot/src/command.rs index 626649f..d7150fe 100644 --- a/euphoxide-bot/src/command.rs +++ b/euphoxide-bot/src/command.rs @@ -7,6 +7,8 @@ pub mod clap; use std::{future::Future, sync::Arc}; use async_trait::async_trait; +use bang::{General, Global, Specific}; +use basic::{Described, Prefixed}; use euphoxide::{ api::{self, Data, Message, MessageId, SendEvent, SendReply}, client::{ @@ -118,6 +120,39 @@ pub trait Command { async fn execute(&self, arg: &str, msg: &Message, ctx: &Context) -> Result; } +pub trait CommandExt: Sized { + fn described(self) -> Described { + Described::new(self) + } + + fn hidden(self) -> Described { + Described::hidden(self) + } + + fn prefixed(self, prefix: impl ToString) -> Prefixed { + Prefixed::new(prefix, self) + } + + fn global(self, name: impl ToString) -> Global { + Global::new(name, self) + } + + fn general(self, name: impl ToString) -> General { + General::new(name, self) + } + + fn specific(self, name: impl ToString) -> Specific { + Specific::new(name, self) + } +} + +// Sadly this doesn't work: `impl> CommandExt for C {}` +// It leaves E unconstrained. Instead, we just implement CommandExt for all +// types. This is fine since it'll crash and burn once we try to use the created +// commands as actual commands. It also follows the spirit of adding trait +// constraints only where they are necessary. +impl CommandExt for C {} + pub struct Commands { commands: Vec + Sync + Send>>, }