use std::{any::Any, fmt::Display};
use crate::types::{Container, Embed, InteractionResponse, MessageFlags};
use super::HandlerError;
pub trait IntoResponse: Sized {
fn into_response(self) -> InteractionResponse;
fn try_into_response(self) -> Result<InteractionResponse, HandlerError> {
Ok(self.into_response())
}
}
impl IntoResponse for InteractionResponse {
fn into_response(self) -> InteractionResponse {
self
}
}
impl IntoResponse for String {
fn into_response(self) -> InteractionResponse {
InteractionResponse::respond_with_message(self)
}
}
impl IntoResponse for &str {
fn into_response(self) -> InteractionResponse {
InteractionResponse::respond_with_message(self.to_string())
}
}
impl IntoResponse for Embed {
fn into_response(self) -> InteractionResponse {
InteractionResponse::respond_with_embed(self)
}
}
impl IntoResponse for Container {
fn into_response(self) -> InteractionResponse {
InteractionResponse::respond_with_components(vec![self.into()])
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Ephemeral<T>(pub T);
impl<T: IntoResponse> IntoResponse for Ephemeral<T> {
fn into_response(self) -> InteractionResponse {
self.try_into_response()
.unwrap_or_else(|error| error.response())
}
fn try_into_response(self) -> Result<InteractionResponse, HandlerError> {
let mut response = self.0.try_into_response()?;
match &mut response {
InteractionResponse::ChannelMessageWithSource(data)
| InteractionResponse::UpdateMessage(data) => {
*data.flags.get_or_insert(MessageFlags::empty()) |= MessageFlags::Ephemeral;
}
InteractionResponse::DeferredChannelMessageWithSource(flags) => {
*flags.get_or_insert(MessageFlags::empty()) |= MessageFlags::Ephemeral;
}
_ => {}
}
Ok(response)
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Update<T>(pub T);
impl<T: IntoResponse> IntoResponse for Update<T> {
fn into_response(self) -> InteractionResponse {
self.try_into_response()
.unwrap_or_else(|error| error.response())
}
fn try_into_response(self) -> Result<InteractionResponse, HandlerError> {
Ok(match self.0.try_into_response()? {
InteractionResponse::ChannelMessageWithSource(data) => {
InteractionResponse::UpdateMessage(data)
}
InteractionResponse::DeferredChannelMessageWithSource(_) => {
InteractionResponse::DeferredUpdateMessage
}
other => other,
})
}
}
#[derive(Debug, Clone, Copy, PartialEq, Eq)]
pub struct Unthemed<T>(pub T);
impl<T: IntoResponse> IntoResponse for Unthemed<T> {
fn into_response(self) -> InteractionResponse {
self.try_into_response()
.unwrap_or_else(|error| error.response())
}
fn try_into_response(self) -> Result<InteractionResponse, HandlerError> {
let mut response = self.0.try_into_response()?;
if let Some(data) = response.message_data_mut() {
data.unthemed = true;
}
Ok(response)
}
}
pub trait CommandOutput {
fn into_result(self) -> Result<InteractionResponse, HandlerError>;
}
impl<T: IntoResponse> CommandOutput for T {
fn into_result(self) -> Result<InteractionResponse, HandlerError> {
self.try_into_response()
}
}
impl<T: IntoResponse, E: Display + 'static> CommandOutput for Result<T, E> {
fn into_result(self) -> Result<InteractionResponse, HandlerError> {
self.map_err(into_handler_error)?.try_into_response()
}
}
pub(crate) fn into_handler_error<E: Display + 'static>(error: E) -> HandlerError {
let mut error = Some(error);
match (&mut error as &mut dyn Any).downcast_mut::<Option<HandlerError>>() {
Some(handler_error) => handler_error.take().expect("taken once"),
None => HandlerError::new(error.expect("taken once")),
}
}