sparkle_convenience/
message.rs1#![allow(deprecated)]
2
3use std::fmt::{Debug, Display};
4
5use anyhow;
6use async_trait::async_trait;
7use twilight_http::{request::channel::message::CreateMessage, Response};
8use twilight_model::{
9 channel::Message,
10 id::{
11 marker::{ChannelMarker, UserMarker},
12 Id,
13 },
14};
15use twilight_validate::message::MessageValidationError;
16
17use crate::{
18 error,
19 error::{extract::HttpErrorExt, Error, ErrorExt, NoCustomError, UserError},
20 reply::Reply,
21 Bot,
22};
23
24impl Bot {
25 pub async fn handle_error<Custom: Display + Debug + Send + Sync + 'static>(
40 &self,
41 channel_id: Id<ChannelMarker>,
42 reply: Reply,
43 error: anyhow::Error,
44 ) -> Option<Response<Message>> {
45 if error.ignore() {
46 return None;
47 }
48
49 if let Some(internal_err) = error.internal::<Custom>() {
50 self.log(internal_err).await;
51 }
52
53 let create_res = match self.http.create_message(channel_id).with_reply(&reply) {
54 Ok(create) => create.await.map_err(anyhow::Error::new),
55 Err(validation_err) => Err(validation_err.into()),
56 };
57
58 match create_res.map_err(error::ErrorExt::internal::<Custom>) {
59 Ok(response) => Some(response),
60 Err(create_err) => {
61 if let Some(create_internal_err) = create_err {
62 self.log(create_internal_err).await;
63 }
64 None
65 }
66 }
67 }
68
69 pub async fn handle_error_no_custom(
73 &self,
74 channel_id: Id<ChannelMarker>,
75 reply: Reply,
76 error: anyhow::Error,
77 ) -> Option<Response<Message>> {
78 self.handle_error::<NoCustomError>(channel_id, reply, error)
79 .await
80 }
81}
82
83#[deprecated(note = "Use `Reply::create_private_message` instead")]
85#[async_trait]
86#[allow(clippy::module_name_repetitions)]
87pub trait HttpExt {
88 async fn dm_user(&self, user_id: Id<UserMarker>) -> Result<CreateMessage<'_>, Error>;
90}
91
92#[async_trait]
93impl HttpExt for twilight_http::Client {
94 async fn dm_user(&self, user_id: Id<UserMarker>) -> Result<CreateMessage<'_>, Error> {
95 let channel_id = self
96 .create_private_channel(user_id)
97 .await?
98 .model()
99 .await?
100 .id;
101
102 Ok(self.create_message(channel_id))
103 }
104}
105
106#[deprecated(note = "Use `Reply::create_message` instead")]
108#[async_trait]
109pub trait CreateMessageExt<'a>: Sized {
110 fn with_reply(self, reply: &'a Reply) -> Result<Self, MessageValidationError>;
119
120 async fn execute_ignore_permissions(self) -> Result<Response<Message>, Error>;
133}
134
135#[async_trait]
136impl<'a> CreateMessageExt<'a> for CreateMessage<'a> {
137 fn with_reply(self, reply: &'a Reply) -> Result<Self, MessageValidationError> {
138 let mut message = self
139 .embeds(&reply.embeds)?
140 .components(&reply.components)?
141 .attachments(&reply.attachments)?
142 .flags(reply.flags)
143 .tts(reply.tts);
144
145 if !reply.content.is_empty() {
146 message = message.content(&reply.content)?;
147 }
148
149 if let Some(allowed_mentions) = &reply.allowed_mentions {
150 message = message.allowed_mentions(allowed_mentions.as_ref());
151 }
152
153 Ok(message)
154 }
155
156 async fn execute_ignore_permissions(self) -> Result<Response<Message>, Error> {
157 self.await.map_err(|http_err| {
158 if http_err.missing_permissions() {
159 UserError::Ignore.into()
160 } else {
161 http_err.into()
162 }
163 })
164 }
165}