Add support for extras, conditionally displaying commands in the help command, and start working on moderation commands
This commit is contained in:
@@ -8,20 +8,20 @@ use twilight_model::channel::message::{
|
||||
|
||||
use crate::framework::interactions::{InteractionError, context::InteractionContext};
|
||||
|
||||
type ComponentWithID<T> = (Option<String>, Arc<dyn Component<T>>);
|
||||
type ComponentWithID<T, E> = (Option<String>, Arc<dyn Component<T, E>>);
|
||||
|
||||
pub struct ActionRow<T> {
|
||||
components: Vec<ComponentWithID<T>>,
|
||||
pub struct ActionRow<T, E> {
|
||||
components: Vec<ComponentWithID<T, E>>,
|
||||
}
|
||||
|
||||
impl<T> ActionRow<T> {
|
||||
pub fn new(components: &[ComponentWithID<T>]) -> Self {
|
||||
impl<T, E> ActionRow<T, E> {
|
||||
pub fn new(components: &[ComponentWithID<T, E>]) -> Self {
|
||||
Self {
|
||||
components: components.to_vec(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add(&mut self, id: Option<String>, component: Arc<dyn Component<T>>) {
|
||||
pub fn add(&mut self, id: Option<String>, component: Arc<dyn Component<T, E>>) {
|
||||
self.components.push((id, component));
|
||||
}
|
||||
|
||||
@@ -41,19 +41,21 @@ impl<T> ActionRow<T> {
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
pub trait Component<T>: Send + Sync + Debug {
|
||||
pub trait Component<T, E>: Send + Sync + Debug {
|
||||
fn custom_id(&self) -> Option<String> {
|
||||
Some(String::from("component"))
|
||||
}
|
||||
fn build(&self, id: Option<String>) -> TwilightComponent;
|
||||
|
||||
async fn execute(&self, ctx: InteractionContext<T>) -> Result<(), InteractionError>;
|
||||
async fn execute(&self, ctx: InteractionContext<T, E>) -> Result<(), InteractionError>;
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<T, S: Send + Sync + 'static> Component<S> for T
|
||||
impl<T, S, E> Component<S, E> for T
|
||||
where
|
||||
T: Button<S>,
|
||||
T: Button<S, E>,
|
||||
S: Send + Sync + 'static,
|
||||
E: Send + Sync + 'static,
|
||||
{
|
||||
fn custom_id(&self) -> Option<String> {
|
||||
Button::id(self)
|
||||
@@ -75,13 +77,17 @@ where
|
||||
})
|
||||
}
|
||||
|
||||
async fn execute(&self, ctx: InteractionContext<S>) -> Result<(), InteractionError> {
|
||||
async fn execute(&self, ctx: InteractionContext<S, E>) -> Result<(), InteractionError> {
|
||||
self.on_press(ctx).await
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
pub trait Button<S: Send + Sync + 'static>: Send + Sync + Debug {
|
||||
pub trait Button<S, E>: Send + Sync + Debug
|
||||
where
|
||||
S: Send + Sync + 'static,
|
||||
E: Send + Sync + 'static,
|
||||
{
|
||||
fn id(&self) -> Option<String> {
|
||||
if self.url().is_none() {
|
||||
Some(String::from("Button"))
|
||||
@@ -99,7 +105,7 @@ pub trait Button<S: Send + Sync + 'static>: Send + Sync + Debug {
|
||||
None
|
||||
}
|
||||
|
||||
async fn on_press(&self, ctx: InteractionContext<S>) -> Result<(), InteractionError> {
|
||||
async fn on_press(&self, ctx: InteractionContext<S, E>) -> Result<(), InteractionError> {
|
||||
ctx.defer().await
|
||||
}
|
||||
}
|
||||
|
||||
@@ -10,15 +10,26 @@ use crate::framework::{
|
||||
commands::messages::OriginalMessageUpdater, interactions::InteractionError, runtime::Runtime,
|
||||
};
|
||||
|
||||
pub struct InteractionContext<T> {
|
||||
pub struct InteractionContext<T, E> {
|
||||
pub event: InteractionCreate,
|
||||
pub rt: Arc<Runtime<T>>,
|
||||
pub rt: Arc<Runtime<T, E>>,
|
||||
pub prefix: String,
|
||||
pub extras: E,
|
||||
}
|
||||
|
||||
impl<T> InteractionContext<T> {
|
||||
pub fn new(event: InteractionCreate, rt: Arc<Runtime<T>>, prefix: String) -> Self {
|
||||
Self { event, rt, prefix }
|
||||
impl<T, E> InteractionContext<T, E> {
|
||||
pub fn new(
|
||||
event: InteractionCreate,
|
||||
rt: Arc<Runtime<T, E>>,
|
||||
prefix: String,
|
||||
extras: E,
|
||||
) -> Self {
|
||||
Self {
|
||||
event,
|
||||
rt,
|
||||
prefix,
|
||||
extras,
|
||||
}
|
||||
}
|
||||
|
||||
pub async fn defer(&self) -> Result<(), InteractionError> {
|
||||
@@ -39,7 +50,7 @@ impl<T> InteractionContext<T> {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn original_message(&self) -> Option<OriginalMessage<T>> {
|
||||
pub fn original_message(&self) -> Option<OriginalMessage<T, E>> {
|
||||
self.event.message.as_ref().map(|_| OriginalMessage {
|
||||
interaction_id: self.event.id,
|
||||
interaction_token: self.event.token.clone(),
|
||||
@@ -48,17 +59,18 @@ impl<T> InteractionContext<T> {
|
||||
}
|
||||
}
|
||||
|
||||
pub struct OriginalMessage<T> {
|
||||
pub struct OriginalMessage<T, E> {
|
||||
interaction_id: Id<InteractionMarker>,
|
||||
interaction_token: String,
|
||||
rt: Arc<Runtime<T>>,
|
||||
rt: Arc<Runtime<T, E>>,
|
||||
}
|
||||
|
||||
impl<T> OriginalMessage<T>
|
||||
impl<T, E> OriginalMessage<T, E>
|
||||
where
|
||||
T: Send + Sync + 'static,
|
||||
E: Send + Sync + 'static,
|
||||
{
|
||||
pub fn edit(&self) -> OriginalMessageUpdater<T> {
|
||||
pub fn edit(&self) -> OriginalMessageUpdater<T, E> {
|
||||
OriginalMessageUpdater::new(
|
||||
self.interaction_id,
|
||||
self.interaction_token.clone(),
|
||||
|
||||
@@ -23,4 +23,7 @@ pub enum InteractionError {
|
||||
|
||||
#[error("No prefixes were returned for the event")]
|
||||
PrefixesVectorEmpty,
|
||||
|
||||
#[error("The extras getter failed to retrieve extras")]
|
||||
ExtrasGetterFailed,
|
||||
}
|
||||
|
||||
@@ -7,6 +7,7 @@ use twilight_model::{
|
||||
};
|
||||
|
||||
use crate::framework::{
|
||||
commands::extras::ExtrasGetter,
|
||||
interactions::{InteractionError, context::InteractionContext},
|
||||
runtime::Runtime,
|
||||
};
|
||||
@@ -14,13 +15,14 @@ use crate::framework::{
|
||||
use super::components::Component;
|
||||
|
||||
#[derive(Default)]
|
||||
pub struct ComponentRegistry<T> {
|
||||
inner: HashMap<String, Arc<dyn Component<T>>>,
|
||||
pub struct ComponentRegistry<T, E> {
|
||||
inner: HashMap<String, Arc<dyn Component<T, E>>>,
|
||||
}
|
||||
|
||||
impl<T> ComponentRegistry<T>
|
||||
impl<T, E> ComponentRegistry<T, E>
|
||||
where
|
||||
T: Send + Sync + 'static,
|
||||
E: Send + Sync + 'static,
|
||||
{
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
@@ -28,7 +30,7 @@ where
|
||||
}
|
||||
}
|
||||
|
||||
pub fn register(&self, id: impl ToString, component: Arc<dyn Component<T>>) {
|
||||
pub fn register(&self, id: impl ToString, component: Arc<dyn Component<T, E>>) {
|
||||
self.inner.upsert(id.to_string(), component);
|
||||
}
|
||||
|
||||
@@ -39,7 +41,8 @@ where
|
||||
pub async fn execute(
|
||||
&self,
|
||||
event: &InteractionCreate,
|
||||
rt: Arc<Runtime<T>>,
|
||||
rt: Arc<Runtime<T, E>>,
|
||||
extras: Arc<dyn ExtrasGetter<T, Extras = E>>,
|
||||
) -> Result<(), InteractionError> {
|
||||
if let Some(data) = &event.data {
|
||||
match data {
|
||||
@@ -55,11 +58,23 @@ where
|
||||
.first()
|
||||
.ok_or(InteractionError::PrefixesVectorEmpty)?;
|
||||
|
||||
let extras = extras
|
||||
.get_extra(
|
||||
&event.author().expect("Component interaction had no author"),
|
||||
&rt,
|
||||
)
|
||||
.await
|
||||
.inspect_err(|e| {
|
||||
log::error!("Failed to get extras for component interaction: {e:?}")
|
||||
})
|
||||
.map_err(|_| InteractionError::ExtrasGetterFailed)?;
|
||||
|
||||
component
|
||||
.execute(InteractionContext::new(
|
||||
event.clone(),
|
||||
rt.clone(),
|
||||
prefix.to_string(),
|
||||
extras,
|
||||
))
|
||||
.await
|
||||
} else {
|
||||
|
||||
@@ -4,6 +4,7 @@ use async_trait::async_trait;
|
||||
use twilight_model::gateway::payload::incoming::InteractionCreate;
|
||||
|
||||
use crate::framework::{
|
||||
commands::extras::ExtrasGetter,
|
||||
events::traits::{EventResult, OnInteractionHandler},
|
||||
runtime::Runtime,
|
||||
};
|
||||
@@ -12,11 +13,17 @@ use crate::framework::{
|
||||
pub struct InteractionRunner;
|
||||
|
||||
#[async_trait]
|
||||
impl<T> OnInteractionHandler<T> for InteractionRunner
|
||||
impl<T, E> OnInteractionHandler<T, E> for InteractionRunner
|
||||
where
|
||||
T: Send + Sync + 'static,
|
||||
E: Send + Sync + 'static,
|
||||
{
|
||||
async fn on_interaction(&self, event: &InteractionCreate, rt: Arc<Runtime<T>>) -> EventResult {
|
||||
Ok(rt.registry.execute(event, rt.clone()).await?)
|
||||
async fn on_interaction(
|
||||
&self,
|
||||
event: &InteractionCreate,
|
||||
rt: Arc<Runtime<T, E>>,
|
||||
extras: Arc<dyn ExtrasGetter<T, Extras = E>>,
|
||||
) -> EventResult {
|
||||
Ok(rt.registry.execute(event, rt.clone(), extras).await?)
|
||||
}
|
||||
}
|
||||
|
||||
Reference in New Issue
Block a user