Finish refactoring
This commit is contained in:
@@ -1,4 +1,4 @@
|
||||
use std::sync::Arc;
|
||||
use std::{fmt::Debug, sync::Arc};
|
||||
|
||||
use async_trait::async_trait;
|
||||
use twilight_model::channel::message::{
|
||||
@@ -8,18 +8,20 @@ use twilight_model::channel::message::{
|
||||
|
||||
use crate::framework::interactions::{InteractionError, context::InteractionContext};
|
||||
|
||||
pub struct ActionRow {
|
||||
components: Vec<(Option<String>, Arc<dyn Component>)>,
|
||||
type ComponentWithID<T> = (Option<String>, Arc<dyn Component<T>>);
|
||||
|
||||
pub struct ActionRow<T> {
|
||||
components: Vec<ComponentWithID<T>>,
|
||||
}
|
||||
|
||||
impl ActionRow {
|
||||
pub fn new(components: &[(Option<String>, Arc<dyn Component>)]) -> Self {
|
||||
impl<T> ActionRow<T> {
|
||||
pub fn new(components: &[ComponentWithID<T>]) -> Self {
|
||||
Self {
|
||||
components: components.to_vec(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn add(&mut self, id: Option<String>, component: Arc<dyn Component>) {
|
||||
pub fn add(&mut self, id: Option<String>, component: Arc<dyn Component<T>>) {
|
||||
self.components.push((id, component));
|
||||
}
|
||||
|
||||
@@ -27,6 +29,10 @@ impl ActionRow {
|
||||
self.components.len()
|
||||
}
|
||||
|
||||
pub fn is_empty(&self) -> bool {
|
||||
self.components.is_empty()
|
||||
}
|
||||
|
||||
pub fn build(self) -> TwilightComponent {
|
||||
TwilightComponent::ActionRow(TwilightActionRow {
|
||||
components: self
|
||||
@@ -39,19 +45,19 @@ impl ActionRow {
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
pub trait Component: Send + Sync {
|
||||
pub trait Component<T>: 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) -> Result<(), InteractionError>;
|
||||
async fn execute(&self, ctx: InteractionContext<T>) -> Result<(), InteractionError>;
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
impl<T> Component for T
|
||||
impl<T, S: Send + Sync + 'static> Component<S> for T
|
||||
where
|
||||
T: Button,
|
||||
T: Button<S>,
|
||||
{
|
||||
fn custom_id(&self) -> Option<String> {
|
||||
Button::id(self)
|
||||
@@ -73,13 +79,13 @@ where
|
||||
})
|
||||
}
|
||||
|
||||
async fn execute(&self, ctx: InteractionContext) -> Result<(), InteractionError> {
|
||||
async fn execute(&self, ctx: InteractionContext<S>) -> Result<(), InteractionError> {
|
||||
self.on_press(ctx).await
|
||||
}
|
||||
}
|
||||
|
||||
#[async_trait]
|
||||
pub trait Button: Send + Sync {
|
||||
pub trait Button<S: Send + Sync + 'static>: Send + Sync + Debug {
|
||||
fn id(&self) -> Option<String> {
|
||||
if self.url().is_none() {
|
||||
Some(String::from("Button"))
|
||||
@@ -97,7 +103,7 @@ pub trait Button: Send + Sync {
|
||||
None
|
||||
}
|
||||
|
||||
async fn on_press(&self, ctx: InteractionContext) -> Result<(), InteractionError> {
|
||||
async fn on_press(&self, ctx: InteractionContext<S>) -> Result<(), InteractionError> {
|
||||
ctx.defer().await
|
||||
}
|
||||
}
|
||||
|
||||
@@ -1,36 +1,30 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use twilight_http::Client;
|
||||
use twilight_model::{
|
||||
gateway::payload::incoming::InteractionCreate,
|
||||
http::interaction::{InteractionResponse, InteractionResponseType},
|
||||
id::{Id, marker::InteractionMarker},
|
||||
oauth::Application,
|
||||
};
|
||||
|
||||
use crate::framework::{
|
||||
commands::messages::OriginalMessageUpdater, handlers::Handlers, interactions::{registry::Registry, InteractionError}
|
||||
commands::messages::OriginalMessageUpdater, interactions::InteractionError, runtime::Runtime,
|
||||
};
|
||||
|
||||
pub struct InteractionContext {
|
||||
pub struct InteractionContext<T> {
|
||||
pub event: InteractionCreate,
|
||||
pub handlers: Arc<Handlers>,
|
||||
pub rt: Arc<Runtime<T>>,
|
||||
pub prefix: String,
|
||||
}
|
||||
|
||||
impl InteractionContext {
|
||||
pub fn new(
|
||||
event: InteractionCreate,
|
||||
handlers: Arc<Handlers>,
|
||||
) -> Self {
|
||||
Self {
|
||||
event,
|
||||
handlers
|
||||
}
|
||||
impl<T> InteractionContext<T> {
|
||||
pub fn new(event: InteractionCreate, rt: Arc<Runtime<T>>, prefix: String) -> Self {
|
||||
Self { event, rt, prefix }
|
||||
}
|
||||
|
||||
pub async fn defer(&self) -> Result<(), InteractionError> {
|
||||
self.handlers.http
|
||||
.interaction(self.handlers.app.id)
|
||||
self.rt
|
||||
.http
|
||||
.interaction(self.rt.app.id)
|
||||
.create_response(
|
||||
self.event.id,
|
||||
&self.event.token,
|
||||
@@ -46,8 +40,9 @@ impl InteractionContext {
|
||||
}
|
||||
|
||||
pub async fn think(&self) -> Result<(), InteractionError> {
|
||||
self.handlers.http
|
||||
.interaction(self.handlers.app.id)
|
||||
self.rt
|
||||
.http
|
||||
.interaction(self.rt.app.id)
|
||||
.create_response(
|
||||
self.event.id,
|
||||
&self.event.token,
|
||||
@@ -62,27 +57,30 @@ impl InteractionContext {
|
||||
Ok(())
|
||||
}
|
||||
|
||||
pub fn original_message(&self) -> Option<OriginalMessage> {
|
||||
pub fn original_message(&self) -> Option<OriginalMessage<T>> {
|
||||
self.event.message.as_ref().map(|_| OriginalMessage {
|
||||
interaction_id: self.event.id,
|
||||
interaction_token: self.event.token.clone(),
|
||||
handlers: self.handlers.clone()
|
||||
rt: self.rt.clone(),
|
||||
})
|
||||
}
|
||||
}
|
||||
|
||||
pub struct OriginalMessage {
|
||||
pub struct OriginalMessage<T> {
|
||||
interaction_id: Id<InteractionMarker>,
|
||||
interaction_token: String,
|
||||
handlers: Arc<Handlers>
|
||||
rt: Arc<Runtime<T>>,
|
||||
}
|
||||
|
||||
impl OriginalMessage {
|
||||
pub fn edit(&self) -> OriginalMessageUpdater {
|
||||
impl<T> OriginalMessage<T>
|
||||
where
|
||||
T: Send + Sync + 'static,
|
||||
{
|
||||
pub fn edit(&self) -> OriginalMessageUpdater<T> {
|
||||
OriginalMessageUpdater::new(
|
||||
self.interaction_id,
|
||||
self.interaction_token.clone(),
|
||||
self.handlers.clone(),
|
||||
self.rt.clone(),
|
||||
)
|
||||
}
|
||||
}
|
||||
|
||||
@@ -3,6 +3,7 @@ use thiserror::Error;
|
||||
pub mod components;
|
||||
pub mod context;
|
||||
pub mod registry;
|
||||
pub mod runner;
|
||||
|
||||
#[derive(Debug, Error)]
|
||||
pub enum InteractionError {
|
||||
@@ -19,4 +20,7 @@ pub enum InteractionError {
|
||||
|
||||
#[error("The original message was attempted to be edited, but it failed")]
|
||||
OriginalMessageEditingFailed,
|
||||
|
||||
#[error("No prefixes were returned for the event")]
|
||||
PrefixesVectorEmpty,
|
||||
}
|
||||
|
||||
@@ -1,28 +1,34 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use scc::HashMap;
|
||||
use twilight_http::Client;
|
||||
|
||||
use twilight_model::{
|
||||
application::interaction::InteractionData, gateway::payload::incoming::InteractionCreate,
|
||||
oauth::Application,
|
||||
};
|
||||
|
||||
use crate::framework::{handlers::Handlers, interactions::{context::InteractionContext, InteractionError}};
|
||||
use crate::framework::{
|
||||
interactions::{InteractionError, context::InteractionContext},
|
||||
runtime::Runtime,
|
||||
};
|
||||
|
||||
use super::components::Component;
|
||||
|
||||
pub struct Registry {
|
||||
inner: HashMap<String, Arc<dyn Component>>,
|
||||
#[derive(Default)]
|
||||
pub struct ComponentRegistry<T> {
|
||||
inner: HashMap<String, Arc<dyn Component<T>>>,
|
||||
}
|
||||
|
||||
impl Registry {
|
||||
impl<T> ComponentRegistry<T>
|
||||
where
|
||||
T: Send + Sync + 'static,
|
||||
{
|
||||
pub fn new() -> Self {
|
||||
Self {
|
||||
inner: Default::default(),
|
||||
}
|
||||
}
|
||||
|
||||
pub fn register(&self, id: impl ToString, component: Arc<dyn Component>) {
|
||||
pub fn register(&self, id: impl ToString, component: Arc<dyn Component<T>>) {
|
||||
self.inner.upsert(id.to_string(), component);
|
||||
}
|
||||
|
||||
@@ -32,15 +38,29 @@ impl Registry {
|
||||
|
||||
pub async fn execute(
|
||||
&self,
|
||||
event: InteractionCreate,
|
||||
handlers: Arc<Handlers>,
|
||||
event: &InteractionCreate,
|
||||
rt: Arc<Runtime<T>>,
|
||||
) -> Result<(), InteractionError> {
|
||||
if let Some(data) = &event.data {
|
||||
match data {
|
||||
InteractionData::MessageComponent(data) => {
|
||||
if let Some(component) = self.inner.get_async(&data.custom_id).await {
|
||||
let prefixes = rt
|
||||
.get_prefixes(
|
||||
event.guild_id.map(|id| id.get()),
|
||||
event.author_id().map(|id| id.get()),
|
||||
)
|
||||
.await;
|
||||
let prefix = prefixes
|
||||
.first()
|
||||
.ok_or(InteractionError::PrefixesVectorEmpty)?;
|
||||
|
||||
component
|
||||
.execute(InteractionContext::new(event, handlers))
|
||||
.execute(InteractionContext::new(
|
||||
event.clone(),
|
||||
rt.clone(),
|
||||
prefix.to_string(),
|
||||
))
|
||||
.await
|
||||
} else {
|
||||
Err(InteractionError::InteractionNotFound)
|
||||
|
||||
@@ -0,0 +1,26 @@
|
||||
use std::sync::Arc;
|
||||
|
||||
use async_trait::async_trait;
|
||||
use twilight_model::gateway::payload::incoming::InteractionCreate;
|
||||
|
||||
use crate::{
|
||||
framework::{
|
||||
events::traits::{EventResult, OnInteractionHandler},
|
||||
runtime::Runtime,
|
||||
},
|
||||
state::State,
|
||||
};
|
||||
|
||||
#[derive(Debug)]
|
||||
pub struct InteractionRunner;
|
||||
|
||||
#[async_trait]
|
||||
impl OnInteractionHandler<State> for InteractionRunner {
|
||||
async fn on_interaction(
|
||||
&self,
|
||||
event: &InteractionCreate,
|
||||
rt: Arc<Runtime<State>>,
|
||||
) -> EventResult {
|
||||
Ok(rt.registry.execute(event, rt.clone()).await?)
|
||||
}
|
||||
}
|
||||
Reference in New Issue
Block a user