use std::future::{Future, IntoFuture};
use std::pin::Pin;
use super::cache::Cache;
use crate::error::HttpError;
use crate::http::client::HttpClient;
use crate::http::endpoints::messages::{Attachment, CreateMessage, EmbedBuilder};
use crate::model::id::{ChannelId, MessageId};
use crate::model::message::Message;
#[derive(Debug, Clone)]
pub struct Context {
pub http: HttpClient,
pub cache: Cache,
}
impl Context {
pub(crate) fn new(http: HttpClient, cache: Cache) -> Self {
Self { http, cache }
}
pub async fn send_message(
&self,
channel_id: ChannelId,
content: impl Into<String>,
) -> Result<Message, HttpError> {
self.http
.create_message(channel_id, &CreateMessage::text(content))
.await
}
pub fn send(&self, channel_id: ChannelId) -> MessageBuilder {
MessageBuilder {
http: self.http.clone(),
channel_id,
inner: CreateMessage::new(),
files: Vec::new(),
}
}
}
pub struct MessageBuilder {
http: HttpClient,
channel_id: ChannelId,
inner: CreateMessage,
files: Vec<(String, Vec<u8>)>,
}
impl MessageBuilder {
pub fn content(mut self, content: impl Into<String>) -> Self {
self.inner = self.inner.content(content);
self
}
pub fn tts(mut self, tts: bool) -> Self {
self.inner = self.inner.tts(tts);
self
}
pub fn embed(mut self, build: impl FnOnce(EmbedBuilder) -> EmbedBuilder) -> Self {
self.inner = self.inner.embed(build);
self
}
pub fn reply(mut self, message_id: MessageId) -> Self {
self.inner = self.inner.reply(message_id);
self
}
pub fn nonce(mut self, nonce: impl Into<String>) -> Self {
self.inner = self.inner.nonce(nonce);
self
}
pub fn file(mut self, name: impl Into<String>, bytes: Vec<u8>) -> Self {
let name = name.into();
let id = self.files.len() as u32;
let attachments = self.inner.attachments.get_or_insert_with(Vec::new);
attachments.push(Attachment {
id,
filename: name.clone(),
description: None,
});
self.files.push((name, bytes));
self
}
}
impl IntoFuture for MessageBuilder {
type Output = Result<Message, HttpError>;
type IntoFuture = Pin<Box<dyn Future<Output = Self::Output> + Send>>;
fn into_future(self) -> Self::IntoFuture {
let http = self.http;
let channel_id = self.channel_id;
let params = self.inner;
let files = self.files;
Box::pin(async move {
if files.is_empty() {
http.create_message(channel_id, ¶ms).await
} else {
http.create_message_with_files(channel_id, ¶ms, files)
.await
}
})
}
}