disint_model/interaction/
response.rs

1use derive_builder::Builder;
2use serde::Serialize;
3
4use super::embed::Embed;
5
6#[derive(Debug)]
7#[non_exhaustive]
8pub enum InteractionResponse {
9    Pong,
10    ChannelMessageWithSource(ApplicationCommandCallbackData),
11    DeferredChannelMessageWithSource,
12}
13
14impl Serialize for InteractionResponse {
15    fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
16    where
17        S: serde::Serializer,
18    {
19        InteractionResponseInner::new(self).serialize(s)
20    }
21}
22
23#[derive(Debug, Serialize)]
24pub struct ApplicationCommandCallbackData {
25    tts: Option<bool>,
26    content: Option<String>,
27    embeds: Option<Vec<Embed>>,
28    allowed_mentions: Option<AllowedMentions>,
29}
30
31#[derive(Debug, Default, Builder)]
32#[builder(default)]
33pub struct AllowedMentions {
34    roles: AllowedMentionsKind,
35    users: AllowedMentionsKind,
36    deny_mention_everyone: bool,
37}
38
39impl Serialize for AllowedMentions {
40    fn serialize<S>(&self, s: S) -> Result<S::Ok, S::Error>
41    where
42        S: serde::Serializer,
43    {
44        #[derive(Default, Serialize)]
45        struct AllowedMentionsInner<'a> {
46            parse: Vec<&'static str>,
47            roles: Option<&'a [String]>,
48            users: Option<&'a [String]>,
49        }
50
51        let mut inner = AllowedMentionsInner::default();
52        if !self.deny_mention_everyone {
53            inner.parse.push("everyone");
54        }
55        match &self.roles {
56            AllowedMentionsKind::All => inner.parse.push("roles"),
57            AllowedMentionsKind::List(l) => inner.roles = Some(&*l),
58            _ => {}
59        }
60        match &self.users {
61            AllowedMentionsKind::All => inner.parse.push("users"),
62            AllowedMentionsKind::List(l) => inner.users = Some(&*l),
63            _ => {}
64        }
65
66        inner.serialize(s)
67    }
68}
69
70#[derive(Clone, Debug)]
71pub enum AllowedMentionsKind {
72    All,
73    List(Vec<String>),
74    None,
75}
76
77impl AllowedMentionsKind {
78    pub fn new() -> Self {
79        Self::default()
80    }
81}
82
83impl std::iter::FromIterator<String> for AllowedMentionsKind {
84    fn from_iter<T: IntoIterator<Item = String>>(iter: T) -> Self {
85        Self::List(<Vec<_> as std::iter::FromIterator<_>>::from_iter(iter))
86    }
87}
88
89impl Default for AllowedMentionsKind {
90    fn default() -> Self {
91        Self::All
92    }
93}
94
95#[derive(Serialize)]
96struct InteractionResponseInner<'a> {
97    #[serde(rename = "type")]
98    ty: i32,
99    data: Option<&'a ApplicationCommandCallbackData>,
100}
101
102impl<'a> InteractionResponseInner<'a> {
103    fn new(val: &'a InteractionResponse) -> Self {
104        use InteractionResponse::*;
105
106        let (ty, data) = match val {
107            Pong => (1, None),
108            ChannelMessageWithSource(data) => (4, Some(data)),
109            DeferredChannelMessageWithSource => (5, None),
110        };
111
112        Self { ty, data }
113    }
114}
115
116#[derive(Debug)]
117pub struct InteractionResponseBuilder<State>(State);
118
119#[derive(Debug)]
120pub struct Pong;
121
122#[derive(Debug)]
123pub struct Deferred;
124
125#[derive(Debug, Default)]
126pub struct ChannelMessageNoContent {
127    tts: Option<bool>,
128    embeds: Option<Vec<Embed>>,
129    allowed_mentions: Option<AllowedMentions>,
130}
131
132#[derive(Debug)]
133pub struct ChannelMessage {
134    content: Option<String>,
135    tts: Option<bool>,
136    embeds: Option<Vec<Embed>>,
137    allowed_mentions: Option<AllowedMentions>,
138}
139
140impl InteractionResponseBuilder<Pong> {
141    pub fn pong() -> Self {
142        Self(Pong)
143    }
144
145    pub fn finish(self) -> InteractionResponse {
146        InteractionResponse::Pong
147    }
148}
149
150impl InteractionResponseBuilder<Deferred> {
151    pub fn deferred() -> Self {
152        Self(Deferred)
153    }
154
155    pub fn finish(self) -> InteractionResponse {
156        InteractionResponse::DeferredChannelMessageWithSource
157    }
158}
159
160impl InteractionResponseBuilder<ChannelMessageNoContent> {
161    pub fn channel_message() -> Self {
162        Self(ChannelMessageNoContent::default())
163    }
164
165    pub fn content(self, content: impl Into<String>) -> InteractionResponseBuilder<ChannelMessage> {
166        let ChannelMessageNoContent {
167            tts,
168            embeds,
169            allowed_mentions,
170        } = self.0;
171
172        InteractionResponseBuilder(ChannelMessage {
173            content: Some(content.into()),
174            tts,
175            embeds,
176            allowed_mentions,
177        })
178    }
179
180    pub fn tts(mut self, tts: bool) -> Self {
181        self.0.tts = Some(tts);
182        self
183    }
184
185    pub fn embed(self, embed: Embed) -> InteractionResponseBuilder<ChannelMessage> {
186        let ChannelMessageNoContent {
187            tts,
188            mut embeds,
189            allowed_mentions,
190        } = self.0;
191
192        embeds
193            .get_or_insert_with(Vec::new)
194            .push(embed);
195
196        InteractionResponseBuilder(ChannelMessage {
197            content: None,
198            tts,
199            embeds,
200            allowed_mentions,
201        })
202    }
203
204    pub fn allowed_mentions(mut self, allowed_mentions: AllowedMentions) -> Self {
205        self.0.allowed_mentions = Some(allowed_mentions);
206        self
207    }
208}
209
210impl InteractionResponseBuilder<ChannelMessage> {
211    pub fn finish(self) -> InteractionResponse {
212        let ChannelMessage {
213            content,
214            tts,
215            embeds,
216            allowed_mentions,
217        } = self.0;
218
219        let data = ApplicationCommandCallbackData {
220            tts,
221            content,
222            embeds,
223            allowed_mentions,
224        };
225
226        InteractionResponse::ChannelMessageWithSource(data)
227    }
228
229    pub fn content(mut self, content: impl Into<String>) -> Self {
230        self.0.content = Some(content.into());
231        self
232    }
233
234    pub fn tts(mut self, tts: bool) -> Self {
235        self.0.tts = Some(tts);
236        self
237    }
238
239    pub fn embed(mut self, embed: Embed) -> Self {
240        self.0
241            .embeds
242            .get_or_insert_with(Vec::new)
243            .push(embed);
244        self
245    }
246
247    pub fn allowed_mentions(mut self, allowed_mentions: AllowedMentions) -> Self {
248        self.0.allowed_mentions = Some(allowed_mentions);
249        self
250    }
251}