Skip to main content

twilight_http/request/application/interaction/
create_response.rs

1#[cfg(not(target_os = "wasi"))]
2use crate::response::{Response, ResponseFuture, marker::EmptyBody};
3use crate::{
4    client::Client,
5    error::Error,
6    request::{
7        Request, TryIntoRequest, application::interaction::CreateResponseWithResponse,
8        attachment::AttachmentManager,
9    },
10    routing::Route,
11};
12use std::future::IntoFuture;
13use twilight_model::{
14    http::interaction::InteractionResponse,
15    id::{Id, marker::InteractionMarker},
16};
17
18/// Respond to an interaction, by its ID and token.
19///
20/// This endpoint is not bound to the application's global rate limit.
21#[must_use = "requests must be configured and executed"]
22pub struct CreateResponse<'a> {
23    interaction_id: Id<InteractionMarker>,
24    interaction_token: &'a str,
25    response: &'a InteractionResponse,
26    http: &'a Client,
27}
28
29impl<'a> CreateResponse<'a> {
30    pub(crate) const fn new(
31        http: &'a Client,
32        interaction_id: Id<InteractionMarker>,
33        interaction_token: &'a str,
34        response: &'a InteractionResponse,
35    ) -> Self {
36        Self {
37            interaction_id,
38            interaction_token,
39            response,
40            http,
41        }
42    }
43
44    pub const fn with_response(self) -> CreateResponseWithResponse<'a> {
45        CreateResponseWithResponse::new(
46            self.http,
47            self.interaction_id,
48            self.interaction_token,
49            self.response,
50        )
51    }
52}
53
54#[cfg(not(target_os = "wasi"))]
55impl IntoFuture for CreateResponse<'_> {
56    type Output = Result<Response<EmptyBody>, Error>;
57
58    type IntoFuture = ResponseFuture<EmptyBody>;
59
60    fn into_future(self) -> Self::IntoFuture {
61        let http = self.http;
62
63        match self.try_into_request() {
64            Ok(request) => http.request(request),
65            Err(source) => ResponseFuture::error(source),
66        }
67    }
68}
69
70impl TryIntoRequest for CreateResponse<'_> {
71    fn try_into_request(self) -> Result<Request, Error> {
72        let mut request = Request::builder(&Route::InteractionCallback {
73            interaction_id: self.interaction_id.get(),
74            interaction_token: self.interaction_token,
75            with_response: false,
76        });
77
78        // Interaction executions don't need the authorization token, only the
79        // interaction token.
80        request = request.use_authorization_token(false);
81
82        // Determine whether we need to use a multipart/form-data body or a JSON
83        // body.
84        if let Some(attachments) = self
85            .response
86            .data
87            .as_ref()
88            .and_then(|data| data.attachments.as_ref())
89        {
90            let fields = crate::json::to_vec(&self.response).map_err(Error::json)?;
91
92            let form = AttachmentManager::new()
93                .set_files(attachments.iter().collect())
94                .build_form(&fields);
95
96            request = request.form(form);
97        } else {
98            request = request.json(&self.response);
99        }
100
101        request.build()
102    }
103}
104
105#[cfg(test)]
106mod tests {
107    use crate::{client::Client, request::TryIntoRequest};
108    use std::error::Error;
109    use twilight_model::{
110        http::interaction::{InteractionResponse, InteractionResponseType},
111        id::Id,
112    };
113
114    #[test]
115    fn interaction_callback() -> Result<(), Box<dyn Error>> {
116        let application_id = Id::new(1);
117        let interaction_id = Id::new(2);
118        let token = "foo".to_owned().into_boxed_str();
119
120        let client = Client::new(String::new());
121
122        let response = InteractionResponse {
123            kind: InteractionResponseType::DeferredUpdateMessage,
124            data: None,
125        };
126
127        let req = client
128            .interaction(application_id)
129            .create_response(interaction_id, &token, &response)
130            .try_into_request()?;
131
132        assert!(!req.use_authorization_token());
133
134        Ok(())
135    }
136}