Skip to main content

twilight_http/request/channel/message/
get_channel_messages.rs

1use super::GetChannelMessagesConfigured;
2#[cfg(not(target_os = "wasi"))]
3use crate::response::{Response, ResponseFuture, marker::ListBody};
4use crate::{
5    client::Client,
6    error::Error,
7    request::{Request, TryIntoRequest},
8    routing::Route,
9};
10use std::future::IntoFuture;
11use twilight_model::{
12    channel::Message,
13    id::{
14        Id,
15        marker::{ChannelMarker, MessageMarker},
16    },
17};
18use twilight_validate::request::{
19    ValidationError, get_channel_messages_limit as validate_get_channel_messages_limit,
20};
21
22struct GetChannelMessagesFields {
23    limit: Option<u16>,
24}
25
26/// Get channel messages, by [`Id<ChannelMarker>`].
27///
28/// Only one of [`after`], [`around`], and [`before`] can be specified at a time.
29/// Once these are specified, the type returned is [`GetChannelMessagesConfigured`].
30///
31/// If [`limit`] is unspecified, the default set by Discord is 50.
32///
33/// # Examples
34///
35/// ```no_run
36/// use twilight_http::Client;
37/// use twilight_model::id::Id;
38///
39/// # #[tokio::main]
40/// # async fn main() -> Result<(), Box<dyn std::error::Error>> {
41/// let client = Client::new("my token".to_owned());
42/// let channel_id = Id::new(123);
43/// let message_id = Id::new(234);
44///
45/// let messages = client
46///     .channel_messages(channel_id)
47///     .before(message_id)
48///     .limit(6u16)
49///     .await?;
50///
51/// # Ok(()) }
52/// ```
53///
54/// [`after`]: Self::after
55/// [`around`]: Self::around
56/// [`before`]: Self::before
57/// [`GetChannelMessagesConfigured`]: super::GetChannelMessagesConfigured
58/// [`limit`]: Self::limit
59#[must_use = "requests must be configured and executed"]
60pub struct GetChannelMessages<'a> {
61    channel_id: Id<ChannelMarker>,
62    fields: Result<GetChannelMessagesFields, ValidationError>,
63    http: &'a Client,
64}
65
66impl<'a> GetChannelMessages<'a> {
67    pub(crate) const fn new(http: &'a Client, channel_id: Id<ChannelMarker>) -> Self {
68        Self {
69            channel_id,
70            fields: Ok(GetChannelMessagesFields { limit: None }),
71            http,
72        }
73    }
74
75    pub fn after(self, message_id: Id<MessageMarker>) -> GetChannelMessagesConfigured<'a> {
76        GetChannelMessagesConfigured::new(
77            self.http,
78            self.channel_id,
79            Some(message_id),
80            None,
81            None,
82            self.fields.map(|fields| fields.limit),
83        )
84    }
85
86    pub fn around(self, message_id: Id<MessageMarker>) -> GetChannelMessagesConfigured<'a> {
87        GetChannelMessagesConfigured::new(
88            self.http,
89            self.channel_id,
90            None,
91            Some(message_id),
92            None,
93            self.fields.map(|fields| fields.limit),
94        )
95    }
96
97    pub fn before(self, message_id: Id<MessageMarker>) -> GetChannelMessagesConfigured<'a> {
98        GetChannelMessagesConfigured::new(
99            self.http,
100            self.channel_id,
101            None,
102            None,
103            Some(message_id),
104            self.fields.map(|fields| fields.limit),
105        )
106    }
107
108    /// Set the maximum number of messages to retrieve.
109    ///
110    /// The minimum is 1 and the maximum is 100.
111    ///
112    /// # Errors
113    ///
114    /// Returns an error of type [`GetChannelMessages`] error type if the amount
115    /// is less than 1 or greater than 100.
116    ///
117    /// [`GetChannelMessages`]: twilight_validate::request::ValidationErrorType::GetChannelMessages
118    pub fn limit(mut self, limit: u16) -> Self {
119        self.fields = self.fields.and_then(|mut fields| {
120            validate_get_channel_messages_limit(limit)?;
121            fields.limit = Some(limit);
122
123            Ok(fields)
124        });
125
126        self
127    }
128}
129
130#[cfg(not(target_os = "wasi"))]
131impl IntoFuture for GetChannelMessages<'_> {
132    type Output = Result<Response<ListBody<Message>>, Error>;
133
134    type IntoFuture = ResponseFuture<ListBody<Message>>;
135
136    fn into_future(self) -> Self::IntoFuture {
137        let http = self.http;
138
139        match self.try_into_request() {
140            Ok(request) => http.request(request),
141            Err(source) => ResponseFuture::error(source),
142        }
143    }
144}
145
146impl TryIntoRequest for GetChannelMessages<'_> {
147    fn try_into_request(self) -> Result<Request, Error> {
148        let fields = self.fields.map_err(Error::validation)?;
149
150        Ok(Request::from_route(&Route::GetMessages {
151            after: None,
152            around: None,
153            before: None,
154            channel_id: self.channel_id.get(),
155            limit: fields.limit,
156        }))
157    }
158}